summaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/usb_wwan.c
diff options
context:
space:
mode:
authorJohan Hovold2014-05-26 19:23:19 +0200
committerGreg Kroah-Hartman2014-05-28 00:04:06 +0200
commit7436f41283ef2a45f8320ad482edd0aba1bd5843 (patch)
treec49e6192184345a7a3672478a63f8532f0ea54be /drivers/usb/serial/usb_wwan.c
parentUSB: usb_wwan: fix potential blocked I/O after resume (diff)
downloadkernel-qcow2-linux-7436f41283ef2a45f8320ad482edd0aba1bd5843.tar.gz
kernel-qcow2-linux-7436f41283ef2a45f8320ad482edd0aba1bd5843.tar.xz
kernel-qcow2-linux-7436f41283ef2a45f8320ad482edd0aba1bd5843.zip
USB: usb_wwan: fix discarded writes on resume errors
There's no reason not to try sending off any further delayed write urbs, should one urb-submission fail. Signed-off-by: Johan Hovold <jhovold@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/serial/usb_wwan.c')
-rw-r--r--drivers/usb/serial/usb_wwan.c27
1 files changed, 16 insertions, 11 deletions
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index d91a9883e869..ab8c17536534 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -621,28 +621,33 @@ EXPORT_SYMBOL(usb_wwan_suspend);
static int play_delayed(struct usb_serial_port *port)
{
+ struct usb_serial *serial = port->serial;
struct usb_wwan_intf_private *data;
struct usb_wwan_port_private *portdata;
struct urb *urb;
- int err = 0;
+ int err_count = 0;
+ int err;
portdata = usb_get_serial_port_data(port);
data = port->serial->private;
while ((urb = usb_get_from_anchor(&portdata->delayed))) {
err = usb_submit_urb(urb, GFP_ATOMIC);
- if (!err) {
- data->in_flight++;
- } else {
- /* we have to throw away the rest */
- do {
- unbusy_queued_urb(urb, portdata);
- usb_autopm_put_interface_no_suspend(port->serial->interface);
- } while ((urb = usb_get_from_anchor(&portdata->delayed)));
- break;
+ if (err) {
+ dev_err(&port->dev,
+ "%s: submit write urb failed: %d\n",
+ __func__, err);
+ err_count++;
+ unbusy_queued_urb(urb, portdata);
+ usb_autopm_put_interface_async(serial->interface);
+ continue;
}
+ data->in_flight++;
}
- return err;
+ if (err_count)
+ return -EIO;
+
+ return 0;
}
int usb_wwan_resume(struct usb_serial *serial)