summaryrefslogtreecommitdiff
path: root/drivers/usb/serial
diff options
context:
space:
mode:
authorOliver Neukum <oliver@neukum.org>2011-02-10 15:33:29 +0100
committerGreg Kroah-Hartman <gregkh@suse.de>2011-02-17 10:51:12 -0800
commit16871dcac74c63227aa92e0012f3004a648c2062 (patch)
tree9cfb094c3e86ed37fe1a99a2f8024dd3860f0e43 /drivers/usb/serial
parent433508ae30f13c0bf6905e576c42899a8535f0bb (diff)
downloadlinux-3.10-16871dcac74c63227aa92e0012f3004a648c2062.tar.gz
linux-3.10-16871dcac74c63227aa92e0012f3004a648c2062.tar.bz2
linux-3.10-16871dcac74c63227aa92e0012f3004a648c2062.zip
usb_wwan: error case of resume
If an error happens during resumption. The remaining data has to be cleanly discarded and the pm counters have to be adjusted. Signed-off-by: Oliver Neukum <oneukum@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r--drivers/usb/serial/usb_wwan.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index 84fe1b6ba11..fe5e48eb969 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -664,6 +664,18 @@ int usb_wwan_suspend(struct usb_serial *serial, pm_message_t message)
}
EXPORT_SYMBOL(usb_wwan_suspend);
+static void unbusy_queued_urb(struct urb *urb, struct usb_wwan_port_private *portdata)
+{
+ int i;
+
+ for (i = 0; i < N_OUT_URB; i++) {
+ if (urb == portdata->out_urbs[i]) {
+ clear_bit(i, &portdata->out_busy);
+ break;
+ }
+ }
+}
+
static void play_delayed(struct usb_serial_port *port)
{
struct usb_wwan_intf_private *data;
@@ -675,8 +687,17 @@ static void play_delayed(struct usb_serial_port *port)
data = port->serial->private;
while ((urb = usb_get_from_anchor(&portdata->delayed))) {
err = usb_submit_urb(urb, GFP_ATOMIC);
- if (!err)
+ if (!err) {
data->in_flight++;
+ } else {
+ /* we have to throw away the rest */
+ do {
+ unbusy_queued_urb(urb, portdata);
+ //extremely dirty
+ atomic_dec(&port->serial->interface->dev.power.usage_count);
+ } while ((urb = usb_get_from_anchor(&portdata->delayed)));
+ break;
+ }
}
}