diff options
author | Bjørn Mork <bjorn@mork.no> | 2012-02-10 03:44:08 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-02-10 14:28:18 -0500 |
commit | 88044202756925ad47c51c2f634a4f2c17afe068 (patch) | |
tree | 88b8fa746469f5f3161941fa4d35a0e0336b229c /drivers/usb/class | |
parent | 7483948fdd31a8642ef0288aab6f368b98d53c29 (diff) |
usb: cdc-wdm: make reset work with blocking IO
Add a flag to tell wdm_read/wdm_write that a reset is in progress,
and wake any blocking read/write before taking the mutexes. This
allows the device to reset without waiting for blocking IO to
finish.
Signed-off-by: Bjørn Mork <bjorn@mork.no>
Acked-by: Oliver Neukum <oneukum@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/class')
-rw-r--r-- | drivers/usb/class/cdc-wdm.c | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index f63601a2054c..b27bbb957e16 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c | |||
@@ -70,6 +70,7 @@ MODULE_DEVICE_TABLE (usb, wdm_ids); | |||
70 | #define WDM_POLL_RUNNING 6 | 70 | #define WDM_POLL_RUNNING 6 |
71 | #define WDM_RESPONDING 7 | 71 | #define WDM_RESPONDING 7 |
72 | #define WDM_SUSPENDING 8 | 72 | #define WDM_SUSPENDING 8 |
73 | #define WDM_RESETTING 9 | ||
73 | 74 | ||
74 | #define WDM_MAX 16 | 75 | #define WDM_MAX 16 |
75 | 76 | ||
@@ -340,6 +341,10 @@ static ssize_t wdm_write | |||
340 | else | 341 | else |
341 | if (test_bit(WDM_IN_USE, &desc->flags)) | 342 | if (test_bit(WDM_IN_USE, &desc->flags)) |
342 | r = -EAGAIN; | 343 | r = -EAGAIN; |
344 | |||
345 | if (test_bit(WDM_RESETTING, &desc->flags)) | ||
346 | r = -EIO; | ||
347 | |||
343 | if (r < 0) { | 348 | if (r < 0) { |
344 | kfree(buf); | 349 | kfree(buf); |
345 | goto out; | 350 | goto out; |
@@ -419,6 +424,10 @@ retry: | |||
419 | rv = -ENODEV; | 424 | rv = -ENODEV; |
420 | goto err; | 425 | goto err; |
421 | } | 426 | } |
427 | if (test_bit(WDM_RESETTING, &desc->flags)) { | ||
428 | rv = -EIO; | ||
429 | goto err; | ||
430 | } | ||
422 | usb_mark_last_busy(interface_to_usbdev(desc->intf)); | 431 | usb_mark_last_busy(interface_to_usbdev(desc->intf)); |
423 | if (rv < 0) { | 432 | if (rv < 0) { |
424 | rv = -ERESTARTSYS; | 433 | rv = -ERESTARTSYS; |
@@ -859,10 +868,6 @@ static int wdm_pre_reset(struct usb_interface *intf) | |||
859 | { | 868 | { |
860 | struct wdm_device *desc = usb_get_intfdata(intf); | 869 | struct wdm_device *desc = usb_get_intfdata(intf); |
861 | 870 | ||
862 | mutex_lock(&desc->rlock); | ||
863 | mutex_lock(&desc->wlock); | ||
864 | kill_urbs(desc); | ||
865 | |||
866 | /* | 871 | /* |
867 | * we notify everybody using poll of | 872 | * we notify everybody using poll of |
868 | * an exceptional situation | 873 | * an exceptional situation |
@@ -870,9 +875,16 @@ static int wdm_pre_reset(struct usb_interface *intf) | |||
870 | * message from the device is lost | 875 | * message from the device is lost |
871 | */ | 876 | */ |
872 | spin_lock_irq(&desc->iuspin); | 877 | spin_lock_irq(&desc->iuspin); |
878 | set_bit(WDM_RESETTING, &desc->flags); /* inform read/write */ | ||
879 | set_bit(WDM_READ, &desc->flags); /* unblock read */ | ||
880 | clear_bit(WDM_IN_USE, &desc->flags); /* unblock write */ | ||
873 | desc->rerr = -EINTR; | 881 | desc->rerr = -EINTR; |
874 | spin_unlock_irq(&desc->iuspin); | 882 | spin_unlock_irq(&desc->iuspin); |
875 | wake_up_all(&desc->wait); | 883 | wake_up_all(&desc->wait); |
884 | mutex_lock(&desc->rlock); | ||
885 | mutex_lock(&desc->wlock); | ||
886 | kill_urbs(desc); | ||
887 | cancel_work_sync(&desc->rxwork); | ||
876 | return 0; | 888 | return 0; |
877 | } | 889 | } |
878 | 890 | ||
@@ -881,6 +893,7 @@ static int wdm_post_reset(struct usb_interface *intf) | |||
881 | struct wdm_device *desc = usb_get_intfdata(intf); | 893 | struct wdm_device *desc = usb_get_intfdata(intf); |
882 | int rv; | 894 | int rv; |
883 | 895 | ||
896 | clear_bit(WDM_RESETTING, &desc->flags); | ||
884 | rv = recover_from_urb_loss(desc); | 897 | rv = recover_from_urb_loss(desc); |
885 | mutex_unlock(&desc->wlock); | 898 | mutex_unlock(&desc->wlock); |
886 | mutex_unlock(&desc->rlock); | 899 | mutex_unlock(&desc->rlock); |