diff options
Diffstat (limited to 'drivers/usb')
-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 | ||