This is a note to let you know that I've just added the patch titled USB: usb_wwan: fix urb leak at shutdown to my usb git tree which can be found at git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git in the usb-next branch. The patch will show up in the next release of the linux-next tree (usually sometime within the next 24 hours during the week.) The patch will also be merged in the next major kernel release during the merge window. If you have any questions about this process, please let me know. >From 79eed03e77d481b55d85d1cfe5a1636a0d3897fd Mon Sep 17 00:00:00 2001 From: Johan Hovold <jhovold@xxxxxxxxx> Date: Mon, 26 May 2014 19:23:16 +0200 Subject: USB: usb_wwan: fix urb leak at shutdown The delayed-write queue was never emptied at shutdown (close), something which could lead to leaked urbs if the port is closed before being runtime resumed due to a write. When this happens the output buffer would not drain on close (closing_wait timeout), and after consecutive opens, writes could be corrupted with previously buffered data, transfered with reduced throughput or completely blocked. Note that unbusy_queued_urb() was simply moved out of CONFIG_PM. Fixes: 383cedc3bb43 ("USB: serial: full autosuspend support for the option driver") Cc: <stable@xxxxxxxxxxxxxxx> # v2.6.32 Signed-off-by: Johan Hovold <jhovold@xxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- drivers/usb/serial/usb_wwan.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 2b8f02696c00..2ab478b55759 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -414,12 +414,26 @@ int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port) } EXPORT_SYMBOL(usb_wwan_open); +static void unbusy_queued_urb(struct urb *urb, + struct usb_wwan_port_private *portdata) +{ + int i; + + for (i = 0; i < N_OUT_URB; i++) { + if (urb == portdata->out_urbs[i]) { + clear_bit(i, &portdata->out_busy); + break; + } + } +} + void usb_wwan_close(struct usb_serial_port *port) { int i; struct usb_serial *serial = port->serial; struct usb_wwan_port_private *portdata; struct usb_wwan_intf_private *intfdata = port->serial->private; + struct urb *urb; portdata = usb_get_serial_port_data(port); @@ -428,6 +442,14 @@ void usb_wwan_close(struct usb_serial_port *port) portdata->opened = 0; spin_unlock_irq(&intfdata->susp_lock); + for (;;) { + urb = usb_get_from_anchor(&portdata->delayed); + if (!urb) + break; + unbusy_queued_urb(urb, portdata); + usb_autopm_put_interface_async(serial->interface); + } + for (i = 0; i < N_IN_URB; i++) usb_kill_urb(portdata->in_urbs[i]); for (i = 0; i < N_OUT_URB; i++) @@ -596,18 +618,6 @@ int usb_wwan_suspend(struct usb_serial *serial, pm_message_t message) } EXPORT_SYMBOL(usb_wwan_suspend); -static void unbusy_queued_urb(struct urb *urb, struct usb_wwan_port_private *portdata) -{ - int i; - - for (i = 0; i < N_OUT_URB; i++) { - if (urb == portdata->out_urbs[i]) { - clear_bit(i, &portdata->out_busy); - break; - } - } -} - static void play_delayed(struct usb_serial_port *port) { struct usb_wwan_intf_private *data; -- 1.9.0 -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html