USB: serial: fix race between unthrottle and completion handler in symbolserial
authorOliver Neukum <oliver@neukum.org>
Wed, 7 Oct 2009 07:30:49 +0000 (09:30 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 9 Oct 2009 20:52:08 +0000 (13:52 -0700)
usb:usbserial:symbolserial: fix race between unthrottle and completion handler

symbol_unthrottle() mustn't resubmit the URB unconditionally
as the URB may still be running.

the same bug as opticon.

Signed-off-by: Oliver Neukum <oliver@neukum.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/serial/symbolserial.c

index cb7e95f9fcbf584151a8f6a13bc3bd1ac0a08ad3..f25e5452684340896e4b67747fe47c5e8f057f9b 100644 (file)
@@ -179,20 +179,24 @@ static void symbol_unthrottle(struct tty_struct *tty)
        struct symbol_private *priv = usb_get_serial_data(port->serial);
        unsigned long flags;
        int result;
+       bool was_throttled;
 
        dbg("%s - port %d", __func__, port->number);
 
        spin_lock_irqsave(&priv->lock, flags);
        priv->throttled = false;
+       was_throttled = priv->actually_throttled;
        priv->actually_throttled = false;
        spin_unlock_irqrestore(&priv->lock, flags);
 
        priv->int_urb->dev = port->serial->dev;
-       result = usb_submit_urb(priv->int_urb, GFP_ATOMIC);
-       if (result)
-               dev_err(&port->dev,
-                       "%s - failed submitting read urb, error %d\n",
+       if (was_throttled) {
+               result = usb_submit_urb(priv->int_urb, GFP_ATOMIC);
+               if (result)
+                       dev_err(&port->dev,
+                               "%s - failed submitting read urb, error %d\n",
                                                        __func__, result);
+       }
 }
 
 static int symbol_startup(struct usb_serial *serial)