Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=5ec1862e7b612d804ca10a0475dccf98c857efec
Commit:     5ec1862e7b612d804ca10a0475dccf98c857efec
Parent:     2f007de2f4296e4dafae6ab0b3cc1bc49443137a
Author:     Oliver Neukum <[EMAIL PROTECTED]>
AuthorDate: Tue Mar 27 16:02:34 2007 +0200
Committer:  Greg Kroah-Hartman <[EMAIL PROTECTED]>
CommitDate: Fri Apr 27 13:28:38 2007 -0700

    USB: fix omninet write vs. close race
    
    omninet kills all URBs in close. However write() returns as soon as
    the URB has been submitted. Killing the last URB means a race that
    can lose that date written in the last call to write().
    As a fix this is moved to shutdown().
    
    Signed-off-by: Oliver Neukum <[EMAIL PROTECTED]>
    Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>
---
 drivers/usb/serial/omninet.c |   40 ++++++++++++++++++++++------------------
 1 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 357cc11..4adfab9 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -69,6 +69,7 @@ static void omninet_write_bulk_callback       (struct urb 
*urb);
 static int  omninet_write              (struct usb_serial_port *port, const 
unsigned char *buf, int count);
 static int  omninet_write_room         (struct usb_serial_port *port);
 static void omninet_shutdown           (struct usb_serial *serial);
+static int omninet_attach              (struct usb_serial *serial);
 
 static struct usb_device_id id_table [] = {
        { USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) },
@@ -99,6 +100,7 @@ static struct usb_serial_driver zyxel_omninet_device = {
        .num_bulk_in =          1,
        .num_bulk_out =         2,
        .num_ports =            1,
+       .attach =               omninet_attach,
        .open =                 omninet_open,
        .close =                omninet_close,
        .write =                omninet_write,
@@ -145,22 +147,30 @@ struct omninet_data
        __u8    od_outseq;      // Sequence number for bulk_out URBs
 };
 
+static int omninet_attach (struct usb_serial *serial)
+{
+       struct omninet_data *od;
+       struct usb_serial_port *port = serial->port[0];
+
+       od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL );
+       if( !od ) {
+               err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct 
omninet_data));
+               return -ENOMEM;
+       }
+       usb_set_serial_port_data(port, od);
+       return 0;
+}
+
 static int omninet_open (struct usb_serial_port *port, struct file *filp)
 {
        struct usb_serial       *serial = port->serial;
        struct usb_serial_port  *wport;
-       struct omninet_data     *od;
+       struct omninet_data     *od = usb_get_serial_port_data(port);
        int                     result = 0;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
        od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL );
-       if( !od ) {
-               err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct 
omninet_data));
-               return -ENOMEM;
-       }
-
-       usb_set_serial_port_data(port, od);
        wport = serial->port[1];
        wport->tty = port->tty;
 
@@ -172,9 +182,6 @@ static int omninet_open (struct usb_serial_port *port, 
struct file *filp)
        result = usb_submit_urb(port->read_urb, GFP_KERNEL);
        if (result) {
                err("%s - failed submitting read urb, error %d", __FUNCTION__, 
result);
-               /* open failed - all allocations must be freed */
-               kfree(od);
-               usb_set_serial_port_data(port, NULL);
        }
 
        return result;
@@ -182,16 +189,8 @@ static int omninet_open (struct usb_serial_port *port, 
struct file *filp)
 
 static void omninet_close (struct usb_serial_port *port, struct file * filp)
 {
-       struct usb_serial       *serial = port->serial;
-       struct usb_serial_port  *wport;
-
        dbg("%s - port %d", __FUNCTION__, port->number);
-
-       wport = serial->port[1];
-       usb_kill_urb(wport->write_urb);
        usb_kill_urb(port->read_urb);
-
-       kfree(usb_get_serial_port_data(port));
 }
 
 
@@ -330,7 +329,12 @@ static void omninet_write_bulk_callback (struct urb *urb)
 
 static void omninet_shutdown (struct usb_serial *serial)
 {
+       struct usb_serial_port *wport = serial->port[1];
+       struct usb_serial_port *port = serial->port[0];
        dbg ("%s", __FUNCTION__);
+
+       usb_kill_urb(wport->write_urb);
+       kfree(usb_get_serial_port_data(port));
 }
 
 
-
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