Hi,

I've been looking at these issue in usb serial drivers. It seems to me
that kill_traffic() should be enhanced. If this is coupled with the
enhancements of the anchor stuff I posted recently this removes all races
in the drivers not using the standard URBs.
Additionally this modification will make implementations of suspen/resume
and eventually autosuspend easier for the subdrivers.

Thoughts?

        Regards
                Oliver

--- linux-2.6.24-sierra/include/linux/usb/serial.h.alt  2008-01-30 
12:43:25.000000000 +0100
+++ linux-2.6.24-sierra/include/linux/usb/serial.h      2008-01-30 
12:50:26.000000000 +0100
@@ -64,6 +64,7 @@ struct usb_serial_port {
        struct usb_serial *     serial;
        struct tty_struct *     tty;
        spinlock_t              lock;
+       struct usb_anchor       additional_urbs;
        struct mutex            mutex;
        unsigned char           number;
 
--- linux-2.6.24-sierra/drivers/usb/serial/usb-serial.c.alt     2008-01-30 
12:48:34.000000000 +0100
+++ linux-2.6.24-sierra/drivers/usb/serial/usb-serial.c 2008-01-30 
12:50:22.000000000 +0100
@@ -593,6 +593,13 @@ static void kill_traffic(struct usb_seri
        usb_kill_urb(port->read_urb);
        usb_kill_urb(port->interrupt_in_urb);
        usb_kill_urb(port->interrupt_out_urb);
+
+       /*
+        * This kills any additional URBs the subdrivers
+        * have anchored. This is needed for soft disconnect
+        */
+       usb_kill_anchored_urbs(&port->additional_urbs);
+
 }
 
 static void port_free(struct usb_serial_port *port)
@@ -879,6 +886,7 @@ int usb_serial_probe(struct usb_interfac
                port->serial = serial;
                spin_lock_init(&port->lock);
                mutex_init(&port->mutex);
+               init_usb_anchor(&port->additional_urbs);
                INIT_WORK(&port->work, usb_serial_port_work);
                serial->port[i] = port;
        }
--- linux-2.6.24-sierra/drivers/usb/serial/airprime.c.alt       2008-01-30 
13:06:38.000000000 +0100
+++ linux-2.6.24-sierra/drivers/usb/serial/airprime.c   2008-01-30 
13:22:38.000000000 +0100
@@ -98,10 +98,13 @@ static void airprime_read_bulk_callback(
                tty_flip_buffer_push (tty);
        }
 
+       usb_anchor_urb(urb, &port->additional_urbs);
        result = usb_submit_urb (urb, GFP_ATOMIC);
-       if (result)
+       if (result) {
                dev_err(&port->dev, "%s - failed resubmitting read urb, error 
%d\n",
                        __FUNCTION__, result);
+               usb_unanchor_urb(urb);
+       }
        return;
 }
 
@@ -174,8 +177,10 @@ static int airprime_open(struct usb_seri
                                                  
port->bulk_out_endpointAddress),
                                  buffer, buffer_size,
                                  airprime_read_bulk_callback, port);
+               usb_anchor_urb(urb, &port->additional_urbs);
                result = usb_submit_urb(urb, GFP_KERNEL);
                if (result) {
+                       usb_unanchor_urb(urb);
                        usb_free_urb(urb);
                        kfree(buffer);
                        dev_err(&port->dev,
@@ -198,9 +203,10 @@ static int airprime_open(struct usb_seri
        while (i-- != 0) {
                urb = priv->read_urbp[i];
                buffer = urb->transfer_buffer;
-               usb_kill_urb (urb);
-               usb_free_urb (urb);
-               kfree (buffer);
+               usb_kill_urb(urb);
+               usb_unanchor_urb(urb);
+               usb_free_urb(urb);
+               kfree(buffer);
        }
 
  out:
@@ -268,6 +274,7 @@ static int airprime_write(struct usb_ser
                                          port->bulk_out_endpointAddress),
                          buffer, count,
                          airprime_write_bulk_callback, port);
+       usb_anchor_urb(urb, &port->additional_urbs);
 
        /* send it down the pipe */
        status = usb_submit_urb(urb, GFP_ATOMIC);
@@ -276,6 +283,7 @@ static int airprime_write(struct usb_ser
                        "%s - usb_submit_urb(write bulk) failed with status = 
%d\n",
                        __FUNCTION__, status);
                count = status;
+               usb_unanchor_urb(urb);
                kfree (buffer);
        } else {
                spin_lock_irqsave(&priv->lock, flags);
-
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to