diff options
Diffstat (limited to 'drivers/usb/wusbcore/security.c')
-rw-r--r-- | drivers/usb/wusbcore/security.c | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/drivers/usb/wusbcore/security.c b/drivers/usb/wusbcore/security.c index 95be995..cc74d66 100644 --- a/drivers/usb/wusbcore/security.c +++ b/drivers/usb/wusbcore/security.c @@ -33,6 +33,20 @@ static void wusbhc_gtk_rekey_work(struct work_struct *work); int wusbhc_sec_create(struct wusbhc *wusbhc) { + /* + * WQ is singlethread because we need to serialize rekey operations. + * Use a separate workqueue for security operations instead of the + * wusbd workqueue because security operations may need to communicate + * directly with downstream wireless devices using synchronous URBs. + * If a device is not responding, this could block other host + * controller operations. + */ + wusbhc->wq_security = create_singlethread_workqueue("wusbd_security"); + if (wusbhc->wq_security == NULL) { + pr_err("WUSB-core: Cannot create wusbd_security workqueue\n"); + return -ENOMEM; + } + wusbhc->gtk.descr.bLength = sizeof(wusbhc->gtk.descr) + sizeof(wusbhc->gtk.data); wusbhc->gtk.descr.bDescriptorType = USB_DT_KEY; @@ -48,6 +62,7 @@ int wusbhc_sec_create(struct wusbhc *wusbhc) /* Called when the HC is destroyed */ void wusbhc_sec_destroy(struct wusbhc *wusbhc) { + destroy_workqueue(wusbhc->wq_security); } @@ -596,5 +611,5 @@ void wusbhc_gtk_rekey(struct wusbhc *wusbhc) * and will cause a deadlock. Instead, queue a work item to do * it when the lock is not held */ - queue_work(wusbd, &wusbhc->gtk_rekey_work); + queue_work(wusbhc->wq_security, &wusbhc->gtk_rekey_work); } |