aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/class
diff options
context:
space:
mode:
authorBjørn Mork <bjorn@mork.no>2012-02-10 03:44:08 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-02-10 14:28:18 -0500
commit88044202756925ad47c51c2f634a4f2c17afe068 (patch)
tree88b8fa746469f5f3161941fa4d35a0e0336b229c /drivers/usb/class
parent7483948fdd31a8642ef0288aab6f368b98d53c29 (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.c21
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);