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