]> Pileus Git - ~andy/linux/commitdiff
staging: usbip: bugfixes related to kthread conversion
authorArjan Mels <arjan.mels@gmx.net>
Tue, 5 Apr 2011 18:26:11 +0000 (20:26 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 6 Apr 2011 22:51:13 +0000 (15:51 -0700)
When doing a usb port reset do a queued reset instead to prevent a
deadlock: the reset will cause the driver to unbind, causing the
usb_driver_lock_for_reset to stall.

Signed-off-by: Arjan Mels <arjan.mels@gmx.net>
Cc: Takahiro Hirofuchi <hirofuchi@users.sourceforge.net>
Cc: Max Vozeler <max@vozeler.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/usbip/stub_rx.c

index 6445f12cb4fd40cefacf77252fcfbf22eb7b3ff2..51fbd09864751cc3de95b091dda6e822c0f9660a 100644 (file)
@@ -171,33 +171,23 @@ static int tweak_set_configuration_cmd(struct urb *urb)
 
 static int tweak_reset_device_cmd(struct urb *urb)
 {
-       struct usb_ctrlrequest *req;
-       __u16 value;
-       __u16 index;
-       int ret;
-
-       req = (struct usb_ctrlrequest *) urb->setup_packet;
-       value = le16_to_cpu(req->wValue);
-       index = le16_to_cpu(req->wIndex);
-
-       usbip_uinfo("reset_device (port %d) to %s\n", index,
-                                               dev_name(&urb->dev->dev));
+       struct stub_priv *priv = (struct stub_priv *) urb->context;
+       struct stub_device *sdev = priv->sdev;
 
-       /* all interfaces should be owned by usbip driver, so just reset it.  */
-       ret = usb_lock_device_for_reset(urb->dev, NULL);
-       if (ret < 0) {
-               dev_err(&urb->dev->dev, "lock for reset\n");
-               return ret;
-       }
-
-       /* try to reset the device */
-       ret = usb_reset_device(urb->dev);
-       if (ret < 0)
-               dev_err(&urb->dev->dev, "device reset\n");
+       usbip_uinfo("reset_device %s\n", dev_name(&urb->dev->dev));
 
-       usb_unlock_device(urb->dev);
-
-       return ret;
+       /*
+        * usb_lock_device_for_reset caused a deadlock: it causes the driver
+        * to unbind. In the shutdown the rx thread is signalled to shut down
+        * but this thread is pending in the usb_lock_device_for_reset.
+        *
+        * Instead queue the reset.
+        *
+        * Unfortunatly an existing usbip connection will be dropped due to
+        * driver unbinding.
+        */
+       usb_queue_reset_device(sdev->interface);
+       return 0;
 }
 
 /*