Commit 88044202 authored by Bjørn Mork's avatar Bjørn Mork Committed by Greg Kroah-Hartman

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: default avatarBjørn Mork <bjorn@mork.no>
Acked-by: default avatarOliver Neukum <oneukum@suse.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 7483948f
...@@ -70,6 +70,7 @@ MODULE_DEVICE_TABLE (usb, wdm_ids); ...@@ -70,6 +70,7 @@ MODULE_DEVICE_TABLE (usb, wdm_ids);
#define WDM_POLL_RUNNING 6 #define WDM_POLL_RUNNING 6
#define WDM_RESPONDING 7 #define WDM_RESPONDING 7
#define WDM_SUSPENDING 8 #define WDM_SUSPENDING 8
#define WDM_RESETTING 9
#define WDM_MAX 16 #define WDM_MAX 16
...@@ -340,6 +341,10 @@ static ssize_t wdm_write ...@@ -340,6 +341,10 @@ static ssize_t wdm_write
else else
if (test_bit(WDM_IN_USE, &desc->flags)) if (test_bit(WDM_IN_USE, &desc->flags))
r = -EAGAIN; r = -EAGAIN;
if (test_bit(WDM_RESETTING, &desc->flags))
r = -EIO;
if (r < 0) { if (r < 0) {
kfree(buf); kfree(buf);
goto out; goto out;
...@@ -419,6 +424,10 @@ static ssize_t wdm_read ...@@ -419,6 +424,10 @@ static ssize_t wdm_read
rv = -ENODEV; rv = -ENODEV;
goto err; goto err;
} }
if (test_bit(WDM_RESETTING, &desc->flags)) {
rv = -EIO;
goto err;
}
usb_mark_last_busy(interface_to_usbdev(desc->intf)); usb_mark_last_busy(interface_to_usbdev(desc->intf));
if (rv < 0) { if (rv < 0) {
rv = -ERESTARTSYS; rv = -ERESTARTSYS;
...@@ -859,10 +868,6 @@ static int wdm_pre_reset(struct usb_interface *intf) ...@@ -859,10 +868,6 @@ static int wdm_pre_reset(struct usb_interface *intf)
{ {
struct wdm_device *desc = usb_get_intfdata(intf); struct wdm_device *desc = usb_get_intfdata(intf);
mutex_lock(&desc->rlock);
mutex_lock(&desc->wlock);
kill_urbs(desc);
/* /*
* we notify everybody using poll of * we notify everybody using poll of
* an exceptional situation * an exceptional situation
...@@ -870,9 +875,16 @@ static int wdm_pre_reset(struct usb_interface *intf) ...@@ -870,9 +875,16 @@ static int wdm_pre_reset(struct usb_interface *intf)
* message from the device is lost * message from the device is lost
*/ */
spin_lock_irq(&desc->iuspin); spin_lock_irq(&desc->iuspin);
set_bit(WDM_RESETTING, &desc->flags); /* inform read/write */
set_bit(WDM_READ, &desc->flags); /* unblock read */
clear_bit(WDM_IN_USE, &desc->flags); /* unblock write */
desc->rerr = -EINTR; desc->rerr = -EINTR;
spin_unlock_irq(&desc->iuspin); spin_unlock_irq(&desc->iuspin);
wake_up_all(&desc->wait); wake_up_all(&desc->wait);
mutex_lock(&desc->rlock);
mutex_lock(&desc->wlock);
kill_urbs(desc);
cancel_work_sync(&desc->rxwork);
return 0; return 0;
} }
...@@ -881,6 +893,7 @@ static int wdm_post_reset(struct usb_interface *intf) ...@@ -881,6 +893,7 @@ static int wdm_post_reset(struct usb_interface *intf)
struct wdm_device *desc = usb_get_intfdata(intf); struct wdm_device *desc = usb_get_intfdata(intf);
int rv; int rv;
clear_bit(WDM_RESETTING, &desc->flags);
rv = recover_from_urb_loss(desc); rv = recover_from_urb_loss(desc);
mutex_unlock(&desc->wlock); mutex_unlock(&desc->wlock);
mutex_unlock(&desc->rlock); mutex_unlock(&desc->rlock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment