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

visor_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/visor.c

index b9341f0e452b32c05ed321e413e0f9c470bdf0c4..ad1f9232292d264506b16cb5b5bd8a625dc2e88d 100644 (file)
@@ -595,20 +595,23 @@ static void visor_unthrottle(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
        struct visor_private *priv = usb_get_serial_port_data(port);
-       int result;
+       int result, was_throttled;
 
        dbg("%s - port %d", __func__, port->number);
        spin_lock_irq(&priv->lock);
        priv->throttled = 0;
+       was_throttled = priv->actually_throttled;
        priv->actually_throttled = 0;
        spin_unlock_irq(&priv->lock);
 
-       port->read_urb->dev = port->serial->dev;
-       result = usb_submit_urb(port->read_urb, GFP_KERNEL);
-       if (result)
-               dev_err(&port->dev,
-                       "%s - failed submitting read urb, error %d\n",
+       if (was_throttled) {
+               port->read_urb->dev = port->serial->dev;
+               result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+               if (result)
+                       dev_err(&port->dev,
+                               "%s - failed submitting read urb, error %d\n",
                                                        __func__, result);
+       }
 }
 
 static int palm_os_3_probe(struct usb_serial *serial,