USB裝置插拔檢測
阿新 • • 發佈:2019-02-11
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); }