diff options
author | Oliver Neukum <oneukum@suse.de> | 2007-03-23 09:30:16 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-04-27 16:28:38 -0400 |
commit | 62127a585cc72509a0bfae502cc16f9935a4cda6 (patch) | |
tree | 96515ced9943c82c36103cf2e48d859cb4c237e6 /drivers/usb/serial/ftdi_sio.c | |
parent | b80349b17c6e1236a24616f71e59ed31279de25a (diff) |
USB: fix race in ftdio_write
this has the same race as the visor driver. The counter must be incremented
under the lock it is checked under.
Signed-off-by: Oliver Neukum <oneukum@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial/ftdi_sio.c')
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 8ff9d54b21e6..8fb8e2f64545 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -1433,6 +1433,7 @@ static int ftdi_write (struct usb_serial_port *port, | |||
1433 | dbg("%s - write limit hit\n", __FUNCTION__); | 1433 | dbg("%s - write limit hit\n", __FUNCTION__); |
1434 | return 0; | 1434 | return 0; |
1435 | } | 1435 | } |
1436 | priv->tx_outstanding_urbs++; | ||
1436 | spin_unlock_irqrestore(&priv->tx_lock, flags); | 1437 | spin_unlock_irqrestore(&priv->tx_lock, flags); |
1437 | 1438 | ||
1438 | data_offset = priv->write_offset; | 1439 | data_offset = priv->write_offset; |
@@ -1450,14 +1451,15 @@ static int ftdi_write (struct usb_serial_port *port, | |||
1450 | buffer = kmalloc (transfer_size, GFP_ATOMIC); | 1451 | buffer = kmalloc (transfer_size, GFP_ATOMIC); |
1451 | if (!buffer) { | 1452 | if (!buffer) { |
1452 | err("%s ran out of kernel memory for urb ...", __FUNCTION__); | 1453 | err("%s ran out of kernel memory for urb ...", __FUNCTION__); |
1453 | return -ENOMEM; | 1454 | count = -ENOMEM; |
1455 | goto error_no_buffer; | ||
1454 | } | 1456 | } |
1455 | 1457 | ||
1456 | urb = usb_alloc_urb(0, GFP_ATOMIC); | 1458 | urb = usb_alloc_urb(0, GFP_ATOMIC); |
1457 | if (!urb) { | 1459 | if (!urb) { |
1458 | err("%s - no more free urbs", __FUNCTION__); | 1460 | err("%s - no more free urbs", __FUNCTION__); |
1459 | kfree (buffer); | 1461 | count = -ENOMEM; |
1460 | return -ENOMEM; | 1462 | goto error_no_urb; |
1461 | } | 1463 | } |
1462 | 1464 | ||
1463 | /* Copy data */ | 1465 | /* Copy data */ |
@@ -1499,10 +1501,9 @@ static int ftdi_write (struct usb_serial_port *port, | |||
1499 | if (status) { | 1501 | if (status) { |
1500 | err("%s - failed submitting write urb, error %d", __FUNCTION__, status); | 1502 | err("%s - failed submitting write urb, error %d", __FUNCTION__, status); |
1501 | count = status; | 1503 | count = status; |
1502 | kfree (buffer); | 1504 | goto error; |
1503 | } else { | 1505 | } else { |
1504 | spin_lock_irqsave(&priv->tx_lock, flags); | 1506 | spin_lock_irqsave(&priv->tx_lock, flags); |
1505 | ++priv->tx_outstanding_urbs; | ||
1506 | priv->tx_outstanding_bytes += count; | 1507 | priv->tx_outstanding_bytes += count; |
1507 | priv->tx_bytes += count; | 1508 | priv->tx_bytes += count; |
1508 | spin_unlock_irqrestore(&priv->tx_lock, flags); | 1509 | spin_unlock_irqrestore(&priv->tx_lock, flags); |
@@ -1510,10 +1511,19 @@ static int ftdi_write (struct usb_serial_port *port, | |||
1510 | 1511 | ||
1511 | /* we are done with this urb, so let the host driver | 1512 | /* we are done with this urb, so let the host driver |
1512 | * really free it when it is finished with it */ | 1513 | * really free it when it is finished with it */ |
1513 | usb_free_urb (urb); | 1514 | usb_free_urb(urb); |
1514 | 1515 | ||
1515 | dbg("%s write returning: %d", __FUNCTION__, count); | 1516 | dbg("%s write returning: %d", __FUNCTION__, count); |
1516 | return count; | 1517 | return count; |
1518 | error: | ||
1519 | usb_free_urb(urb); | ||
1520 | error_no_urb: | ||
1521 | kfree (buffer); | ||
1522 | error_no_buffer: | ||
1523 | spin_lock_irqsave(&priv->tx_lock, flags); | ||
1524 | priv->tx_outstanding_urbs--; | ||
1525 | spin_unlock_irqrestore(&priv->tx_lock, flags); | ||
1526 | return count; | ||
1517 | } /* ftdi_write */ | 1527 | } /* ftdi_write */ |
1518 | 1528 | ||
1519 | 1529 | ||