drivers/infiniband/core/uverbs_main.c

Source file repositories/reference/linux-study-clean/drivers/infiniband/core/uverbs_main.c

File Facts

System
Linux kernel
Corpus path
drivers/infiniband/core/uverbs_main.c
Extension
.c
Size
36088 bytes
Lines
1358
Domain
Driver Families
Bucket
drivers/infiniband
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

const struct file_operations uverbs_event_fops = {
	.owner	 = THIS_MODULE,
	.read	 = ib_uverbs_comp_event_read,
	.poll    = ib_uverbs_comp_event_poll,
	.release = uverbs_uobject_fd_release,
	.fasync  = ib_uverbs_comp_event_fasync,
};

const struct file_operations uverbs_async_event_fops = {
	.owner	 = THIS_MODULE,
	.read	 = ib_uverbs_async_event_read,
	.poll    = ib_uverbs_async_event_poll,
	.release = uverbs_uobject_fd_release,
	.fasync  = ib_uverbs_async_event_fasync,
};

void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context)
{
	struct ib_uverbs_event_queue   *ev_queue = cq_context;
	struct ib_ucq_object	       *uobj;
	struct ib_uverbs_event	       *entry;
	unsigned long			flags;

	if (!ev_queue)
		return;

	spin_lock_irqsave(&ev_queue->lock, flags);
	if (ev_queue->is_closed) {
		spin_unlock_irqrestore(&ev_queue->lock, flags);
		return;
	}

	entry = kmalloc_obj(*entry, GFP_ATOMIC);
	if (!entry) {
		spin_unlock_irqrestore(&ev_queue->lock, flags);
		return;
	}

	uobj = cq->uobject;

	entry->desc.comp.cq_handle = cq->uobject->uevent.uobject.user_handle;
	entry->counter		   = &uobj->comp_events_reported;

	list_add_tail(&entry->list, &ev_queue->event_list);
	list_add_tail(&entry->obj_list, &uobj->comp_list);
	spin_unlock_irqrestore(&ev_queue->lock, flags);

	wake_up_interruptible(&ev_queue->poll_wait);
	kill_fasync(&ev_queue->async_queue, SIGIO, POLL_IN);
}

void ib_uverbs_async_handler(struct ib_uverbs_async_event_file *async_file,
			     __u64 element, __u64 event,
			     struct list_head *obj_list, u32 *counter)
{
	struct ib_uverbs_event *entry;
	unsigned long flags;

	if (!async_file)
		return;

	spin_lock_irqsave(&async_file->ev_queue.lock, flags);
	if (async_file->ev_queue.is_closed) {
		spin_unlock_irqrestore(&async_file->ev_queue.lock, flags);
		return;
	}

	entry = kmalloc_obj(*entry, GFP_ATOMIC);
	if (!entry) {
		spin_unlock_irqrestore(&async_file->ev_queue.lock, flags);
		return;
	}

	entry->desc.async.element = element;
	entry->desc.async.event_type = event;
	entry->desc.async.reserved = 0;
	entry->counter = counter;

	list_add_tail(&entry->list, &async_file->ev_queue.event_list);
	if (obj_list)
		list_add_tail(&entry->obj_list, obj_list);
	spin_unlock_irqrestore(&async_file->ev_queue.lock, flags);

	wake_up_interruptible(&async_file->ev_queue.poll_wait);
	kill_fasync(&async_file->ev_queue.async_queue, SIGIO, POLL_IN);
}

static void uverbs_uobj_event(struct ib_uevent_object *eobj,
			      struct ib_event *event)
{

Annotation

Implementation Notes