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

Reply via email to