drivers/misc/vmw_vmci/vmci_doorbell.c

Source file repositories/reference/linux-study-clean/drivers/misc/vmw_vmci/vmci_doorbell.c

File Facts

System
Linux kernel
Corpus path
drivers/misc/vmw_vmci/vmci_doorbell.c
Extension
.c
Size
15463 bytes
Lines
552
Domain
Driver Families
Bucket
drivers/misc
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct dbell_entry {
	struct vmci_resource resource;
	struct hlist_node node;
	struct work_struct work;
	vmci_callback notify_cb;
	void *client_data;
	u32 idx;
	u32 priv_flags;
	bool run_delayed;
	atomic_t active;	/* Only used by guest personality */
};

/* The VMCI index table keeps track of currently registered doorbells. */
struct dbell_index_table {
	spinlock_t lock;	/* Index table lock */
	struct hlist_head entries[VMCI_DOORBELL_INDEX_TABLE_SIZE];
};

static struct dbell_index_table vmci_doorbell_it = {
	.lock = __SPIN_LOCK_UNLOCKED(vmci_doorbell_it.lock),
};

/*
 * The max_notify_idx is one larger than the currently known bitmap index in
 * use, and is used to determine how much of the bitmap needs to be scanned.
 */
static u32 max_notify_idx;

/*
 * The notify_idx_count is used for determining whether there are free entries
 * within the bitmap (if notify_idx_count + 1 < max_notify_idx).
 */
static u32 notify_idx_count;

/*
 * The last_notify_idx_reserved is used to track the last index handed out - in
 * the case where multiple handles share a notification index, we hand out
 * indexes round robin based on last_notify_idx_reserved.
 */
static u32 last_notify_idx_reserved;

/* This is a one entry cache used to by the index allocation. */
static u32 last_notify_idx_released = PAGE_SIZE;


/*
 * Utility function that retrieves the privilege flags associated
 * with a given doorbell handle. For guest endpoints, the
 * privileges are determined by the context ID, but for host
 * endpoints privileges are associated with the complete
 * handle. Hypervisor endpoints are not yet supported.
 */
int vmci_dbell_get_priv_flags(struct vmci_handle handle, u32 *priv_flags)
{
	if (priv_flags == NULL || handle.context == VMCI_INVALID_ID)
		return VMCI_ERROR_INVALID_ARGS;

	if (handle.context == VMCI_HOST_CONTEXT_ID) {
		struct dbell_entry *entry;
		struct vmci_resource *resource;

		resource = vmci_resource_by_handle(handle,
						   VMCI_RESOURCE_TYPE_DOORBELL);
		if (!resource)
			return VMCI_ERROR_NOT_FOUND;

		entry = container_of(resource, struct dbell_entry, resource);
		*priv_flags = entry->priv_flags;
		vmci_resource_put(resource);
	} else if (handle.context == VMCI_HYPERVISOR_CONTEXT_ID) {
		/*
		 * Hypervisor endpoints for notifications are not
		 * supported (yet).
		 */
		return VMCI_ERROR_INVALID_ARGS;
	} else {
		*priv_flags = vmci_context_get_priv_flags(handle.context);
	}

	return VMCI_SUCCESS;
}

/*
 * Find doorbell entry by bitmap index.
 */
static struct dbell_entry *dbell_index_table_find(u32 idx)
{
	u32 bucket = VMCI_DOORBELL_HASH(idx);
	struct dbell_entry *dbell;

Annotation

Implementation Notes