]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 27 Jun 2014 22:02:11 +0000 (15:02 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 27 Jun 2014 22:02:11 +0000 (15:02 -0700)
added patches:
usb-usb_wwan-fix-urb-leak-at-shutdown.patch
usb-usb_wwan-fix-write-and-suspend-race.patch

queue-3.4/series
queue-3.4/usb-usb_wwan-fix-race-between-write-and-resume.patch
queue-3.4/usb-usb_wwan-fix-urb-leak-at-shutdown.patch [new file with mode: 0644]
queue-3.4/usb-usb_wwan-fix-write-and-suspend-race.patch [new file with mode: 0644]

index 08d28efe087cebeec109f8bfa583b881dc321472..08b2f0ee6ef0ce0e83954a5badb89557e9df7da6 100644 (file)
@@ -17,3 +17,5 @@ ext4-fix-wrong-assert-in-ext4_mb_normalize_request.patch
 matroxfb-perform-a-dummy-read-of-m_status.patch
 usb-usb_wwan-fix-urb-leak-in-write-error-path.patch
 usb-usb_wwan-fix-race-between-write-and-resume.patch
+usb-usb_wwan-fix-write-and-suspend-race.patch
+usb-usb_wwan-fix-urb-leak-at-shutdown.patch
index 467ef7dfd3a2e28e71f0b264d8788d995c16af65..fe444e37c682c866b6090edf3fa02892ffe51ff7 100644 (file)
@@ -27,11 +27,13 @@ Reviewed-by: David Cohen <david.a.cohen@linux.intel.com>
 Signed-off-by: Johan Hovold <jhovold@gmail.com>
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 
-diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
-index 47ad7550c5a6..112693a4100b 100644
+---
+ drivers/usb/serial/usb_wwan.c |    8 ++------
+ 1 file changed, 2 insertions(+), 6 deletions(-)
+
 --- a/drivers/usb/serial/usb_wwan.c
 +++ b/drivers/usb/serial/usb_wwan.c
-@@ -660,17 +660,15 @@ int usb_wwan_resume(struct usb_serial *serial)
+@@ -731,17 +731,15 @@ int usb_wwan_resume(struct usb_serial *s
                }
        }
  
@@ -43,7 +45,7 @@ index 47ad7550c5a6..112693a4100b 100644
  
                /* skip closed ports */
 -              spin_lock_irq(&intfdata->susp_lock);
--              if (!portdata || !portdata->opened) {
+-              if (!portdata->opened) {
 -                      spin_unlock_irq(&intfdata->susp_lock);
 +              if (!portdata || !portdata->opened)
                        continue;
@@ -51,7 +53,7 @@ index 47ad7550c5a6..112693a4100b 100644
  
                for (j = 0; j < N_IN_URB; j++) {
                        urb = portdata->in_urbs[j];
-@@ -683,9 +681,7 @@ int usb_wwan_resume(struct usb_serial *serial)
+@@ -754,9 +752,7 @@ int usb_wwan_resume(struct usb_serial *s
                        }
                }
                play_delayed(port);
diff --git a/queue-3.4/usb-usb_wwan-fix-urb-leak-at-shutdown.patch b/queue-3.4/usb-usb_wwan-fix-urb-leak-at-shutdown.patch
new file mode 100644 (file)
index 0000000..3014a05
--- /dev/null
@@ -0,0 +1,93 @@
+From 79eed03e77d481b55d85d1cfe5a1636a0d3897fd Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Mon, 26 May 2014 19:23:16 +0200
+Subject: USB: usb_wwan: fix urb leak at shutdown
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 79eed03e77d481b55d85d1cfe5a1636a0d3897fd upstream.
+
+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")
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/usb_wwan.c |   34 ++++++++++++++++++++++------------
+ 1 file changed, 22 insertions(+), 12 deletions(-)
+
+--- a/drivers/usb/serial/usb_wwan.c
++++ b/drivers/usb/serial/usb_wwan.c
+@@ -434,12 +434,26 @@ int usb_wwan_open(struct tty_struct *tty
+ }
+ 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;
+       dbg("%s", __func__);
+       portdata = usb_get_serial_port_data(port);
+@@ -450,6 +464,14 @@ void usb_wwan_close(struct usb_serial_po
+               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++)
+@@ -667,18 +689,6 @@ int usb_wwan_suspend(struct usb_serial *
+ }
+ 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;
diff --git a/queue-3.4/usb-usb_wwan-fix-write-and-suspend-race.patch b/queue-3.4/usb-usb_wwan-fix-write-and-suspend-race.patch
new file mode 100644 (file)
index 0000000..9d2ae88
--- /dev/null
@@ -0,0 +1,57 @@
+From 170fad9e22df0063eba0701adb966786d7a4ec5a Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Mon, 26 May 2014 19:23:15 +0200
+Subject: USB: usb_wwan: fix write and suspend race
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 170fad9e22df0063eba0701adb966786d7a4ec5a upstream.
+
+Fix race between write() and suspend() which could lead to writes being
+dropped (or I/O while suspended) if the device is runtime suspended
+while a write request is being processed.
+
+Specifically, suspend() releases the susp_lock after determining the
+device is idle but before setting the suspended flag, thus leaving a
+window where a concurrent write() can submit an urb.
+
+Fixes: 383cedc3bb43 ("USB: serial: full autosuspend support for the
+option driver")
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/usb_wwan.c |   12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+--- a/drivers/usb/serial/usb_wwan.c
++++ b/drivers/usb/serial/usb_wwan.c
+@@ -647,22 +647,20 @@ EXPORT_SYMBOL(usb_wwan_release);
+ int usb_wwan_suspend(struct usb_serial *serial, pm_message_t message)
+ {
+       struct usb_wwan_intf_private *intfdata = serial->private;
+-      int b;
+       dbg("%s entered", __func__);
++      spin_lock_irq(&intfdata->susp_lock);
+       if (PMSG_IS_AUTO(message)) {
+-              spin_lock_irq(&intfdata->susp_lock);
+-              b = intfdata->in_flight;
+-              spin_unlock_irq(&intfdata->susp_lock);
+-
+-              if (b)
++              if (intfdata->in_flight) {
++                      spin_unlock_irq(&intfdata->susp_lock);
+                       return -EBUSY;
++              }
+       }
+-      spin_lock_irq(&intfdata->susp_lock);
+       intfdata->suspended = 1;
+       spin_unlock_irq(&intfdata->susp_lock);
++
+       stop_read_write_urbs(serial);
+       return 0;