Am Donnerstag, 24. September 2009 23:32:39 schrieb Johan Hovold: > > You can, if you wish to hide what's going on, poison the urb. The > > correct sequence is: > > > > 1. poison the urb > > 2. cancel_delayed_work_sync > > > > 3. unpoison the urb > > <snip> > > > Step 1 sets a flag. > > And this is what we generally want to be doing I assume, rather than > adding an explicit state flag? If we do this we might just as well do it generically. Alan, this uses flush_scheduled_work() prone to deadlocks. I think I used it safely in this patch. Could you check? Regards Oliver -- commit c9a1991c01c7a2650f124cab5c0549743c1e6da4 Author: Oliver Neukum <oliver@xxxxxxxxxx> Date: Mon Sep 28 13:11:10 2009 +0200 usb:usbserial: safe generic unlinking of all URBs use usb_poison_urb() and flush_scheduled_work() for a safe generic unlink of all URBs even if completion handlers submit other URBs or drivers submit URBs from work queues diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index aa6b2ae..2797956 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -311,6 +311,7 @@ static void serial_down(struct usb_serial_port *port) if (drv->close) drv->close(port); mutex_unlock(&port->mutex); + kill_traffic(); } static void serial_hangup(struct tty_struct *tty) @@ -590,21 +591,17 @@ static void usb_serial_port_work(struct work_struct *work) static void kill_traffic(struct usb_serial_port *port) { - usb_kill_urb(port->read_urb); - usb_kill_urb(port->write_urb); - /* - * This is tricky. - * Some drivers submit the read_urb in the - * handler for the write_urb or vice versa - * this order determines the order in which - * usb_kill_urb() must be used to reliably - * kill the URBs. As it is unknown here, - * both orders must be used in turn. - * The call below is not redundant. - */ - usb_kill_urb(port->read_urb); - usb_kill_urb(port->interrupt_in_urb); - usb_kill_urb(port->interrupt_out_urb); + usb_poison_urb(port->read_urb); + usb_poison_urb(port->write_urb); + usb_poison_urb(port->interrupt_in_urb); + usb_poison_urb(port->interrupt_out_urb); + + flush_scheduled_work(); + + usb_unpoison_urb(port->read_urb); + usb_unpoison_urb(port->write_urb); + usb_unpoison_urb(port->interrupt_in_urb); + usb_unpoison_urb(port->interrupt_out_urb); } static void port_release(struct device *dev) -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html