From: Arjan Mels <[email protected]>

Implemented pre_reset and post_reset methods of the driver to prevent the
driver from being unbound upon a device reset. Because of this also the
asynchronous reset introduced to prevent a race condition is no longer necessary
(and sometimes causes problems, because it comes later then expected).

Signed-off-by: Arjan Mels <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Takahiro Hirofuchi <[email protected]>
Cc: Max Vozeler <[email protected]>
Cc: usbip-devel <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
 drivers/staging/usbip/stub_dev.c |   21 +++++++++++++++++++++
 drivers/staging/usbip/stub_rx.c  |   20 +++++++++++---------
 2 files changed, 32 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c
index 6e99ec8..8cbea42 100644
--- a/drivers/staging/usbip/stub_dev.c
+++ b/drivers/staging/usbip/stub_dev.c
@@ -26,6 +26,8 @@
 static int stub_probe(struct usb_interface *interface,
                      const struct usb_device_id *id);
 static void stub_disconnect(struct usb_interface *interface);
+static int stub_pre_reset(struct usb_interface *interface);
+static int stub_post_reset(struct usb_interface *interface);
 
 /*
  * Define device IDs here if you want to explicitly limit exportable devices.
@@ -59,6 +61,8 @@ struct usb_driver stub_driver = {
        .probe          = stub_probe,
        .disconnect     = stub_disconnect,
        .id_table       = stub_table,
+       .pre_reset      = stub_pre_reset,
+       .post_reset     = stub_post_reset,
 };
 
 /*
@@ -541,3 +545,20 @@ static void stub_disconnect(struct usb_interface 
*interface)
                del_match_busid((char *)udev_busid);
        }
 }
+
+/* 
+ * Presence of pre_reset and post_reset prevents the driver from being unbound
+ * when the device is being reset
+ */
+ 
+int stub_pre_reset(struct usb_interface *interface)
+{
+       dev_dbg(&interface->dev, "pre_reset\n");
+       return 0;
+}
+
+int stub_post_reset(struct usb_interface *interface)
+{
+       dev_dbg(&interface->dev, "post_reset\n");
+       return 0;
+}
diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c
index a5c1fa1..bc57844 100644
--- a/drivers/staging/usbip/stub_rx.c
+++ b/drivers/staging/usbip/stub_rx.c
@@ -175,16 +175,18 @@ static int tweak_reset_device_cmd(struct urb *urb)
        dev_info(&urb->dev->dev, "usb_queue_reset_device\n");
 
        /*
-        * 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.
+        * With the implementation of pre_reset and post_reset the driver no 
+        * longer unbinds. This allows the use of synchronous reset.
         */
-       usb_queue_reset_device(sdev->interface);
+
+       if (usb_lock_device_for_reset(sdev->udev, sdev->interface)<0)
+       {
+               dev_err(&urb->dev->dev, "could not obtain lock to reset 
device\n");
+               return 0;
+       }
+       usb_reset_device(sdev->udev);
+       usb_unlock_device(sdev->udev);
+
        return 0;
 }
 
-- 
1.7.5.4

_______________________________________________
devel mailing list
[email protected]
http://driverdev.linuxdriverproject.org/mailman/listinfo/devel

Reply via email to