diff options
author | Oliver Neukum <oliver@neukum.org> | 2009-10-07 03:25:10 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-10-09 16:52:08 -0400 |
commit | 88fa6590b30ef8c4d41923449ada104f915d8df8 (patch) | |
tree | c234aed89fa1c94b8115e6a6cb5eb9433357a52c | |
parent | d55500941fe6db4d7424c744522ee2451ac1ceda (diff) |
USB: serial: fix race between unthrottle and completion handler in opticon
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>
-rw-r--r-- | drivers/usb/serial/opticon.c | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 1085a577c5c1..80f59b6350cb 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c | |||
@@ -314,21 +314,24 @@ static void opticon_unthrottle(struct tty_struct *tty) | |||
314 | struct usb_serial_port *port = tty->driver_data; | 314 | struct usb_serial_port *port = tty->driver_data; |
315 | struct opticon_private *priv = usb_get_serial_data(port->serial); | 315 | struct opticon_private *priv = usb_get_serial_data(port->serial); |
316 | unsigned long flags; | 316 | unsigned long flags; |
317 | int result; | 317 | int result, was_throttled; |
318 | 318 | ||
319 | dbg("%s - port %d", __func__, port->number); | 319 | dbg("%s - port %d", __func__, port->number); |
320 | 320 | ||
321 | spin_lock_irqsave(&priv->lock, flags); | 321 | spin_lock_irqsave(&priv->lock, flags); |
322 | priv->throttled = false; | 322 | priv->throttled = false; |
323 | was_throttled = priv->actually_throttled; | ||
323 | priv->actually_throttled = false; | 324 | priv->actually_throttled = false; |
324 | spin_unlock_irqrestore(&priv->lock, flags); | 325 | spin_unlock_irqrestore(&priv->lock, flags); |
325 | 326 | ||
326 | priv->bulk_read_urb->dev = port->serial->dev; | 327 | priv->bulk_read_urb->dev = port->serial->dev; |
327 | result = usb_submit_urb(priv->bulk_read_urb, GFP_ATOMIC); | 328 | if (was_throttled) { |
328 | if (result) | 329 | result = usb_submit_urb(priv->bulk_read_urb, GFP_ATOMIC); |
329 | dev_err(&port->dev, | 330 | if (result) |
330 | "%s - failed submitting read urb, error %d\n", | 331 | dev_err(&port->dev, |
332 | "%s - failed submitting read urb, error %d\n", | ||
331 | __func__, result); | 333 | __func__, result); |
334 | } | ||
332 | } | 335 | } |
333 | 336 | ||
334 | static int opticon_tiocmget(struct tty_struct *tty, struct file *file) | 337 | static int opticon_tiocmget(struct tty_struct *tty, struct file *file) |