Gitweb: http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=62127a585cc72509a0bfae502cc16f9935a4cda6 Commit: 62127a585cc72509a0bfae502cc16f9935a4cda6 Parent: b80349b17c6e1236a24616f71e59ed31279de25a Author: Oliver Neukum <[EMAIL PROTECTED]> AuthorDate: Fri Mar 23 14:30:16 2007 +0100 Committer: Greg Kroah-Hartman <[EMAIL PROTECTED]> CommitDate: Fri Apr 27 13:28:38 2007 -0700
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 <[EMAIL PROTECTED]> Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]> --- 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 8ff9d54..8fb8e2f 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, dbg("%s - write limit hit\n", __FUNCTION__); return 0; } + priv->tx_outstanding_urbs++; spin_unlock_irqrestore(&priv->tx_lock, flags); data_offset = priv->write_offset; @@ -1450,14 +1451,15 @@ static int ftdi_write (struct usb_serial_port *port, buffer = kmalloc (transfer_size, GFP_ATOMIC); if (!buffer) { err("%s ran out of kernel memory for urb ...", __FUNCTION__); - return -ENOMEM; + count = -ENOMEM; + goto error_no_buffer; } urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) { err("%s - no more free urbs", __FUNCTION__); - kfree (buffer); - return -ENOMEM; + count = -ENOMEM; + goto error_no_urb; } /* Copy data */ @@ -1499,10 +1501,9 @@ static int ftdi_write (struct usb_serial_port *port, if (status) { err("%s - failed submitting write urb, error %d", __FUNCTION__, status); count = status; - kfree (buffer); + goto error; } else { spin_lock_irqsave(&priv->tx_lock, flags); - ++priv->tx_outstanding_urbs; priv->tx_outstanding_bytes += count; priv->tx_bytes += count; spin_unlock_irqrestore(&priv->tx_lock, flags); @@ -1510,10 +1511,19 @@ static int ftdi_write (struct usb_serial_port *port, /* we are done with this urb, so let the host driver * really free it when it is finished with it */ - usb_free_urb (urb); + usb_free_urb(urb); dbg("%s write returning: %d", __FUNCTION__, count); return count; +error: + usb_free_urb(urb); +error_no_urb: + kfree (buffer); +error_no_buffer: + spin_lock_irqsave(&priv->tx_lock, flags); + priv->tx_outstanding_urbs--; + spin_unlock_irqrestore(&priv->tx_lock, flags); + return count; } /* ftdi_write */ - To unsubscribe from this list: send the line "unsubscribe git-commits-head" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html