diff options
| author | Arjan Mels <arjan.mels@gmx.net> | 2011-05-20 17:25:46 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-06-07 15:28:41 -0400 |
| commit | d3ac0778801708caecb2b172328064255a350432 (patch) | |
| tree | 72899146455ec5605fa877d822d931918ba6e692 /drivers/staging | |
| parent | c11c4eebdd75fc0f443a3f794a2ddc85afed1932 (diff) | |
staging: usbip: bugfix prevent driver unbind
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 <arjan.mels@gmx.net>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Cc: Takahiro Hirofuchi <hirofuchi@users.sourceforge.net>
Cc: Max Vozeler <max@vozeler.com>
Cc: usbip-devel <usbip-devel@lists.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging')
| -rw-r--r-- | drivers/staging/usbip/stub_dev.c | 21 | ||||
| -rw-r--r-- | 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 6e99ec87fee..8cbea42b69b 100644 --- a/drivers/staging/usbip/stub_dev.c +++ b/drivers/staging/usbip/stub_dev.c | |||
| @@ -26,6 +26,8 @@ | |||
| 26 | static int stub_probe(struct usb_interface *interface, | 26 | static int stub_probe(struct usb_interface *interface, |
| 27 | const struct usb_device_id *id); | 27 | const struct usb_device_id *id); |
| 28 | static void stub_disconnect(struct usb_interface *interface); | 28 | static void stub_disconnect(struct usb_interface *interface); |
| 29 | static int stub_pre_reset(struct usb_interface *interface); | ||
| 30 | static int stub_post_reset(struct usb_interface *interface); | ||
| 29 | 31 | ||
| 30 | /* | 32 | /* |
| 31 | * Define device IDs here if you want to explicitly limit exportable devices. | 33 | * Define device IDs here if you want to explicitly limit exportable devices. |
| @@ -59,6 +61,8 @@ struct usb_driver stub_driver = { | |||
| 59 | .probe = stub_probe, | 61 | .probe = stub_probe, |
| 60 | .disconnect = stub_disconnect, | 62 | .disconnect = stub_disconnect, |
| 61 | .id_table = stub_table, | 63 | .id_table = stub_table, |
| 64 | .pre_reset = stub_pre_reset, | ||
| 65 | .post_reset = stub_post_reset, | ||
| 62 | }; | 66 | }; |
| 63 | 67 | ||
| 64 | /* | 68 | /* |
| @@ -541,3 +545,20 @@ static void stub_disconnect(struct usb_interface *interface) | |||
| 541 | del_match_busid((char *)udev_busid); | 545 | del_match_busid((char *)udev_busid); |
| 542 | } | 546 | } |
| 543 | } | 547 | } |
| 548 | |||
| 549 | /* | ||
| 550 | * Presence of pre_reset and post_reset prevents the driver from being unbound | ||
| 551 | * when the device is being reset | ||
| 552 | */ | ||
| 553 | |||
| 554 | int stub_pre_reset(struct usb_interface *interface) | ||
| 555 | { | ||
| 556 | dev_dbg(&interface->dev, "pre_reset\n"); | ||
| 557 | return 0; | ||
| 558 | } | ||
| 559 | |||
| 560 | int stub_post_reset(struct usb_interface *interface) | ||
| 561 | { | ||
| 562 | dev_dbg(&interface->dev, "post_reset\n"); | ||
| 563 | return 0; | ||
| 564 | } | ||
diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c index a5c1fa1f043..bc57844600b 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) | |||
| 175 | dev_info(&urb->dev->dev, "usb_queue_reset_device\n"); | 175 | dev_info(&urb->dev->dev, "usb_queue_reset_device\n"); |
| 176 | 176 | ||
| 177 | /* | 177 | /* |
| 178 | * usb_lock_device_for_reset caused a deadlock: it causes the driver | 178 | * With the implementation of pre_reset and post_reset the driver no |
| 179 | * to unbind. In the shutdown the rx thread is signalled to shut down | 179 | * longer unbinds. This allows the use of synchronous reset. |
| 180 | * but this thread is pending in the usb_lock_device_for_reset. | ||
| 181 | * | ||
| 182 | * Instead queue the reset. | ||
| 183 | * | ||
| 184 | * Unfortunatly an existing usbip connection will be dropped due to | ||
| 185 | * driver unbinding. | ||
| 186 | */ | 180 | */ |
| 187 | usb_queue_reset_device(sdev->interface); | 181 | |
| 182 | if (usb_lock_device_for_reset(sdev->udev, sdev->interface)<0) | ||
| 183 | { | ||
| 184 | dev_err(&urb->dev->dev, "could not obtain lock to reset device\n"); | ||
| 185 | return 0; | ||
| 186 | } | ||
| 187 | usb_reset_device(sdev->udev); | ||
| 188 | usb_unlock_device(sdev->udev); | ||
| 189 | |||
| 188 | return 0; | 190 | return 0; |
| 189 | } | 191 | } |
| 190 | 192 | ||
