drivers/misc/vmw_vmci/vmci_event.c

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

File Facts

System
Linux kernel
Corpus path
drivers/misc/vmw_vmci/vmci_event.c
Extension
.c
Size
5311 bytes
Lines
221
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 vmci_subscription {
	u32 id;
	u32 event;
	vmci_event_cb callback;
	void *callback_data;
	struct list_head node;	/* on one of subscriber lists */
};

static struct list_head subscriber_array[VMCI_EVENT_MAX];
static DEFINE_MUTEX(subscriber_mutex);

int __init vmci_event_init(void)
{
	int i;

	for (i = 0; i < VMCI_EVENT_MAX; i++)
		INIT_LIST_HEAD(&subscriber_array[i]);

	return VMCI_SUCCESS;
}

void vmci_event_exit(void)
{
	int e;

	/* We free all memory at exit. */
	for (e = 0; e < VMCI_EVENT_MAX; e++) {
		struct vmci_subscription *cur, *p2;
		list_for_each_entry_safe(cur, p2, &subscriber_array[e], node) {

			/*
			 * We should never get here because all events
			 * should have been unregistered before we try
			 * to unload the driver module.
			 */
			pr_warn("Unexpected free events occurring\n");
			list_del(&cur->node);
			kfree(cur);
		}
	}
}

/*
 * Find entry. Assumes subscriber_mutex is held.
 */
static struct vmci_subscription *event_find(u32 sub_id)
{
	int e;

	for (e = 0; e < VMCI_EVENT_MAX; e++) {
		struct vmci_subscription *cur;
		list_for_each_entry(cur, &subscriber_array[e], node) {
			if (cur->id == sub_id)
				return cur;
		}
	}
	return NULL;
}

/*
 * Actually delivers the events to the subscribers.
 * The callback function for each subscriber is invoked.
 */
static void event_deliver(struct vmci_event_msg *event_msg)
{
	struct vmci_subscription *cur;
	struct list_head *subscriber_list;
	u32 sanitized_event, max_vmci_event;

	rcu_read_lock();
	max_vmci_event = ARRAY_SIZE(subscriber_array);
	sanitized_event = array_index_nospec(event_msg->event_data.event, max_vmci_event);
	subscriber_list = &subscriber_array[sanitized_event];
	list_for_each_entry_rcu(cur, subscriber_list, node) {
		cur->callback(cur->id, &event_msg->event_data,
			      cur->callback_data);
	}
	rcu_read_unlock();
}

/*
 * Dispatcher for the VMCI_EVENT_RECEIVE datagrams. Calls all
 * subscribers for given event.
 */
int vmci_event_dispatch(struct vmci_datagram *msg)
{
	struct vmci_event_msg *event_msg = (struct vmci_event_msg *)msg;

	if (msg->payload_size < sizeof(u32) ||
	    msg->payload_size > sizeof(struct vmci_event_data_max))

Annotation

Implementation Notes