drivers/usb/usbip/usbip_event.c

Source file repositories/reference/linux-study-clean/drivers/usb/usbip/usbip_event.c

File Facts

System
Linux kernel
Corpus path
drivers/usb/usbip/usbip_event.c
Extension
.c
Size
3998 bytes
Lines
197
Domain
Driver Families
Bucket
drivers/usb
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 usbip_event {
	struct list_head node;
	struct usbip_device *ud;
};

static DEFINE_SPINLOCK(event_lock);
static LIST_HEAD(event_list);

static void set_event(struct usbip_device *ud, unsigned long event)
{
	unsigned long flags;

	spin_lock_irqsave(&ud->lock, flags);
	ud->event |= event;
	spin_unlock_irqrestore(&ud->lock, flags);
}

static void unset_event(struct usbip_device *ud, unsigned long event)
{
	unsigned long flags;

	spin_lock_irqsave(&ud->lock, flags);
	ud->event &= ~event;
	spin_unlock_irqrestore(&ud->lock, flags);
}

static struct usbip_device *get_event(void)
{
	struct usbip_event *ue = NULL;
	struct usbip_device *ud = NULL;
	unsigned long flags;

	spin_lock_irqsave(&event_lock, flags);
	if (!list_empty(&event_list)) {
		ue = list_first_entry(&event_list, struct usbip_event, node);
		list_del(&ue->node);
	}
	spin_unlock_irqrestore(&event_lock, flags);

	if (ue) {
		ud = ue->ud;
		kfree(ue);
	}
	return ud;
}

static struct task_struct *worker_context;

static void event_handler(struct work_struct *work)
{
	struct usbip_device *ud;

	if (worker_context == NULL) {
		worker_context = current;
	}

	while ((ud = get_event()) != NULL) {
		usbip_dbg_eh("pending event %lx\n", ud->event);

		mutex_lock(&ud->sysfs_lock);
		/*
		 * NOTE: shutdown must come first.
		 * Shutdown the device.
		 */
		if (ud->event & USBIP_EH_SHUTDOWN) {
			ud->eh_ops.shutdown(ud);
			unset_event(ud, USBIP_EH_SHUTDOWN);
		}

		/* Reset the device. */
		if (ud->event & USBIP_EH_RESET) {
			ud->eh_ops.reset(ud);
			unset_event(ud, USBIP_EH_RESET);
		}

		/* Mark the device as unusable. */
		if (ud->event & USBIP_EH_UNUSABLE) {
			ud->eh_ops.unusable(ud);
			unset_event(ud, USBIP_EH_UNUSABLE);
		}
		mutex_unlock(&ud->sysfs_lock);

		wake_up(&ud->eh_waitq);
	}
}

int usbip_start_eh(struct usbip_device *ud)
{
	init_waitqueue_head(&ud->eh_waitq);
	ud->event = 0;

Annotation

Implementation Notes