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

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

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

index 1085a577c5c1c9b209fee089c1c36ac156ac5bc1..80f59b6350cbdcee5a9864ef51990c51e2309ad4 100644 (file)
@@ -314,21 +314,24 @@ static void opticon_unthrottle(struct tty_struct *tty)
        struct usb_serial_port *port = tty->driver_data;
        struct opticon_private *priv = usb_get_serial_data(port->serial);
        unsigned long flags;
-       int result;
+       int result, 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->bulk_read_urb->dev = port->serial->dev;
-       result = usb_submit_urb(priv->bulk_read_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->bulk_read_urb, GFP_ATOMIC);
+               if (result)
+                       dev_err(&port->dev,
+                               "%s - failed submitting read urb, error %d\n",
                                                        __func__, result);
+       }
 }
 
 static int opticon_tiocmget(struct tty_struct *tty, struct file *file)