summary refs log tree commit diff
path: root/drivers/usb/wusbcore
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/wusbcore')
-rw-r--r--drivers/usb/wusbcore/security.c17
-rw-r--r--drivers/usb/wusbcore/wusbhc.h3
2 files changed, 19 insertions, 1 deletions
diff --git a/drivers/usb/wusbcore/security.c b/drivers/usb/wusbcore/security.c
index 95be9953cd47..cc74d669c802 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);
 }
diff --git a/drivers/usb/wusbcore/wusbhc.h b/drivers/usb/wusbcore/wusbhc.h
index 2384add45371..41838db7f85c 100644
--- a/drivers/usb/wusbcore/wusbhc.h
+++ b/drivers/usb/wusbcore/wusbhc.h
@@ -295,6 +295,9 @@ struct wusbhc {
 	} __attribute__((packed)) gtk;
 	u8 gtk_index;
 	u32 gtk_tkid;
+
+	/* workqueue for WUSB security related tasks. */
+	struct workqueue_struct *wq_security;
 	struct work_struct gtk_rekey_work;
 
 	struct usb_encryption_descriptor *ccm1_etd;