1)hub初始化时
hub_wq = alloc_workqueue(“usb_hub_wq”, WQ_FREEZABLE, 0);
INIT_WORK(&hub->events, hub_event)
queue_work(hub_wq, &hub->events)
–alloc_workqueue(“usb_hub_wq”, WQ_FREEZABLE, 0)
此函数在usb_hub_init中分配队列,替代了以前的thrread_run的功能
```int usb_hub_init(void)
{
if (usb_register(&hub_driver) < 0) {
...
}
/* The workqueue needs to be freezable to avoid interfering with USB-PERSIST port handover.
Otherwise it might see that a full-speed device was gone before the EHCI controller had handed
its port over to the companion full-speed controller.
*/
hub_wq = alloc_workqueue("usb_hub_wq", WQ_FREEZABLE, 0);
...
usb_deregister(&hub_driver);
}
–queue_work(hub_wq, &hub->events)
函数在kick_hub_wq中调用,以便hub_wq函数的调用
static void kick_hub_wq(struct usb_hub *hub)
{
struct usb_interface *intf;
printk("%s function enter\n", __func__);
if (hub->disconnected || work_pending(&hub->events))
return;
/*
* Suppress autosuspend until the event is proceed.
*
* Be careful and make sure that the symmetric operation is
* always called. We are here only when there is no pending
* work for this hub. Therefore put the interface either when
* the new work is called or when it is canceled.
*/
intf = to_usb_interface(hub->intfdev);
usb_autopm_get_interface_no_resume(intf);
kref_get(&hub->kref);
if (queue_work(hub_wq, &hub->events))
return;
/* the work has already been scheduled */
usb_autopm_put_interface_async(intf);
kref_put(&hub->kref, hub_release);
}