Re: [PATCH] USB: serial: Fix read regression in 2.6.31

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux