kvm-lapic-sync-highest-isr-to-hardware-apic-on-eoi.patch
kvm-s390-drop-pending-interrupts-on-guest-exit.patch
mips-kvm-allocate-at-least-16kb-for-exception-handlers.patch
+usb-cdc-acm-fix-write-and-suspend-race.patch
+usb-cdc-acm-fix-write-and-resume-race.patch
+usb-cdc-acm-fix-broken-runtime-suspend.patch
+usb-cdc-acm-fix-runtime-pm-for-control-messages.patch
+usb-cdc-acm-fix-shutdown-and-suspend-race.patch
+usb-cdc-acm-fix-potential-urb-leak-and-pm-imbalance-in-write.patch
+usb-cdc-acm-fix-open-and-suspend-race.patch
+usb-cdc-acm-fix-failed-open-not-being-detected.patch
+usb-cdc-acm-fix-i-o-after-failed-open.patch
+usb-cdc-acm-fix-runtime-pm-imbalance-at-shutdown.patch
--- /dev/null
+From 140cb81ac8c625942a1d695875932c615767a526 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Mon, 26 May 2014 19:23:38 +0200
+Subject: USB: cdc-acm: fix broken runtime suspend
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 140cb81ac8c625942a1d695875932c615767a526 upstream.
+
+The current ACM runtime-suspend implementation is broken in several
+ways:
+
+Firstly, it buffers only the first write request being made while
+suspended -- any further writes are silently dropped.
+
+Secondly, writes being dropped also leak write urbs, which are never
+reclaimed (until the device is unbound).
+
+Thirdly, even the single buffered write is not cleared at shutdown
+(which may happen before the device is resumed), something which can
+lead to another urb leak as well as a PM usage-counter leak.
+
+Fix this by implementing a delayed-write queue using urb anchors and
+making sure to discard the queue properly at shutdown.
+
+Fixes: 11ea859d64b6 ("USB: additional power savings for cdc-acm devices
+that support remote wakeup")
+
+Reported-by: Xiao Jin <jin.xiao@intel.com>
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/class/cdc-acm.c | 32 ++++++++++++++++++++++----------
+ drivers/usb/class/cdc-acm.h | 2 +-
+ 2 files changed, 23 insertions(+), 11 deletions(-)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -573,6 +573,8 @@ static void acm_port_destruct(struct tty
+ static void acm_port_shutdown(struct tty_port *port)
+ {
+ struct acm *acm = container_of(port, struct acm, port);
++ struct urb *urb;
++ struct acm_wb *wb;
+ int i;
+
+ dev_dbg(&acm->control->dev, "%s\n", __func__);
+@@ -581,6 +583,16 @@ static void acm_port_shutdown(struct tty
+ if (!acm->disconnected) {
+ usb_autopm_get_interface(acm->control);
+ acm_set_control(acm, acm->ctrlout = 0);
++
++ for (;;) {
++ urb = usb_get_from_anchor(&acm->delayed);
++ if (!urb)
++ break;
++ wb = urb->context;
++ wb->use = 0;
++ usb_autopm_put_interface_async(acm->control);
++ }
++
+ usb_kill_urb(acm->ctrlurb);
+ for (i = 0; i < ACM_NW; i++)
+ usb_kill_urb(acm->wb[i].urb);
+@@ -648,12 +660,9 @@ static int acm_tty_write(struct tty_stru
+
+ usb_autopm_get_interface_async(acm->control);
+ if (acm->susp_count) {
+- if (!acm->delayed_wb)
+- acm->delayed_wb = wb;
+- else
+- usb_autopm_put_interface_async(acm->control);
++ usb_anchor_urb(wb->urb, &acm->delayed);
+ spin_unlock_irqrestore(&acm->write_lock, flags);
+- return count; /* A white lie */
++ return count;
+ }
+ usb_mark_last_busy(acm->dev);
+
+@@ -1269,6 +1278,7 @@ made_compressed_probe:
+ acm->bInterval = epread->bInterval;
+ tty_port_init(&acm->port);
+ acm->port.ops = &acm_port_ops;
++ init_usb_anchor(&acm->delayed);
+
+ buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
+ if (!buf) {
+@@ -1539,7 +1549,7 @@ static int acm_suspend(struct usb_interf
+ static int acm_resume(struct usb_interface *intf)
+ {
+ struct acm *acm = usb_get_intfdata(intf);
+- struct acm_wb *wb;
++ struct urb *urb;
+ int rv = 0;
+
+ spin_lock_irq(&acm->read_lock);
+@@ -1551,10 +1561,12 @@ static int acm_resume(struct usb_interfa
+ if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags)) {
+ rv = usb_submit_urb(acm->ctrlurb, GFP_ATOMIC);
+
+- if (acm->delayed_wb) {
+- wb = acm->delayed_wb;
+- acm->delayed_wb = NULL;
+- acm_start_wb(acm, wb);
++ for (;;) {
++ urb = usb_get_from_anchor(&acm->delayed);
++ if (!urb)
++ break;
++
++ acm_start_wb(acm, urb->context);
+ }
+
+ /*
+--- a/drivers/usb/class/cdc-acm.h
++++ b/drivers/usb/class/cdc-acm.h
+@@ -120,7 +120,7 @@ struct acm {
+ unsigned int throttled:1; /* actually throttled */
+ unsigned int throttle_req:1; /* throttle requested */
+ u8 bInterval;
+- struct acm_wb *delayed_wb; /* write queued for a device about to be woken */
++ struct usb_anchor delayed; /* writes queued for a device about to be woken */
+ };
+
+ #define CDC_DATA_INTERFACE_TYPE 0x0a
--- /dev/null
+From 8727bf689a77a79816065e23a7a58a474ad544f9 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Mon, 26 May 2014 19:23:43 +0200
+Subject: USB: cdc-acm: fix failed open not being detected
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 8727bf689a77a79816065e23a7a58a474ad544f9 upstream.
+
+Fix errors during open not being returned to userspace. Specifically,
+failed control-line manipulations or control or read urb submissions
+would not be detected.
+
+Fixes: 7fb57a019f94 ("USB: cdc-acm: Fix potential deadlock (lockdep
+warning)")
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/class/cdc-acm.c | 14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -525,17 +525,17 @@ static int acm_port_activate(struct tty_
+ acm->control->needs_remote_wakeup = 1;
+
+ acm->ctrlurb->dev = acm->dev;
+- if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) {
++ retval = usb_submit_urb(acm->ctrlurb, GFP_KERNEL);
++ if (retval) {
+ dev_err(&acm->control->dev,
+ "%s - usb_submit_urb(ctrl irq) failed\n", __func__);
+ goto error_submit_urb;
+ }
+
+ acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS;
+- if (acm_set_control(acm, acm->ctrlout) < 0 &&
+- (acm->ctrl_caps & USB_CDC_CAP_LINE)) {
++ retval = acm_set_control(acm, acm->ctrlout);
++ if (retval < 0 && (acm->ctrl_caps & USB_CDC_CAP_LINE))
+ goto error_set_control;
+- }
+
+ /*
+ * Unthrottle device in case the TTY was closed while throttled.
+@@ -545,7 +545,8 @@ static int acm_port_activate(struct tty_
+ acm->throttle_req = 0;
+ spin_unlock_irq(&acm->read_lock);
+
+- if (acm_submit_read_urbs(acm, GFP_KERNEL))
++ retval = acm_submit_read_urbs(acm, GFP_KERNEL);
++ if (retval)
+ goto error_submit_read_urbs;
+
+ usb_autopm_put_interface(acm->control);
+@@ -564,7 +565,8 @@ error_submit_urb:
+ error_get_interface:
+ disconnected:
+ mutex_unlock(&acm->mutex);
+- return retval;
++
++ return usb_translate_errors(retval);
+ }
+
+ static void acm_port_destruct(struct tty_port *port)
--- /dev/null
+From e4c36076c2a6195ec62c35b03c3fde84d0087dc8 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Mon, 26 May 2014 19:23:44 +0200
+Subject: USB: cdc-acm: fix I/O after failed open
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit e4c36076c2a6195ec62c35b03c3fde84d0087dc8 upstream.
+
+Make sure to kill any already submitted read urbs on read-urb submission
+failures in open in order to prevent doing I/O for a closed port.
+
+Fixes: 088c64f81284 ("USB: cdc-acm: re-write read processing")
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/class/cdc-acm.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -506,6 +506,7 @@ static int acm_port_activate(struct tty_
+ {
+ struct acm *acm = container_of(port, struct acm, port);
+ int retval = -ENODEV;
++ int i;
+
+ dev_dbg(&acm->control->dev, "%s\n", __func__);
+
+@@ -556,6 +557,8 @@ static int acm_port_activate(struct tty_
+ return 0;
+
+ error_submit_read_urbs:
++ for (i = 0; i < acm->rx_buflimit; i++)
++ usb_kill_urb(acm->read_urbs[i]);
+ acm->ctrlout = 0;
+ acm_set_control(acm, acm->ctrlout);
+ error_set_control:
--- /dev/null
+From 703df3297fb1950b0aa53e656108eb936d3f21d9 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Mon, 26 May 2014 19:23:42 +0200
+Subject: USB: cdc-acm: fix open and suspend race
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 703df3297fb1950b0aa53e656108eb936d3f21d9 upstream.
+
+We must not do the usb_autopm_put_interface() before submitting the read
+urbs or we might end up doing I/O to a suspended device.
+
+Fixes: 088c64f81284 ("USB: cdc-acm: re-write read processing")
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/class/cdc-acm.c | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -528,19 +528,15 @@ static int acm_port_activate(struct tty_
+ if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) {
+ dev_err(&acm->control->dev,
+ "%s - usb_submit_urb(ctrl irq) failed\n", __func__);
+- usb_autopm_put_interface(acm->control);
+ goto error_submit_urb;
+ }
+
+ acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS;
+ if (acm_set_control(acm, acm->ctrlout) < 0 &&
+ (acm->ctrl_caps & USB_CDC_CAP_LINE)) {
+- usb_autopm_put_interface(acm->control);
+ goto error_set_control;
+ }
+
+- usb_autopm_put_interface(acm->control);
+-
+ /*
+ * Unthrottle device in case the TTY was closed while throttled.
+ */
+@@ -552,6 +548,8 @@ static int acm_port_activate(struct tty_
+ if (acm_submit_read_urbs(acm, GFP_KERNEL))
+ goto error_submit_read_urbs;
+
++ usb_autopm_put_interface(acm->control);
++
+ mutex_unlock(&acm->mutex);
+
+ return 0;
+@@ -562,6 +560,7 @@ error_submit_read_urbs:
+ error_set_control:
+ usb_kill_urb(acm->ctrlurb);
+ error_submit_urb:
++ usb_autopm_put_interface(acm->control);
+ error_get_interface:
+ disconnected:
+ mutex_unlock(&acm->mutex);
--- /dev/null
+From 183a45087d126d126e8dd1d9b2602fc129dff9ad Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Mon, 26 May 2014 19:23:41 +0200
+Subject: USB: cdc-acm: fix potential urb leak and PM imbalance in write
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 183a45087d126d126e8dd1d9b2602fc129dff9ad upstream.
+
+Make sure to check return value of autopm get in write() in order to
+avoid urb leak and PM counter imbalance on errors.
+
+Fixes: 11ea859d64b6 ("USB: additional power savings for cdc-acm devices
+that support remote wakeup")
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/class/cdc-acm.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -668,7 +668,13 @@ static int acm_tty_write(struct tty_stru
+ memcpy(wb->buf, buf, count);
+ wb->len = count;
+
+- usb_autopm_get_interface_async(acm->control);
++ stat = usb_autopm_get_interface_async(acm->control);
++ if (stat) {
++ wb->use = 0;
++ spin_unlock_irqrestore(&acm->write_lock, flags);
++ return stat;
++ }
++
+ if (acm->susp_count) {
+ usb_anchor_urb(wb->urb, &acm->delayed);
+ spin_unlock_irqrestore(&acm->write_lock, flags);
--- /dev/null
+From bae3f4c53585e9a170da9436e0f06919874bda9a Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Mon, 26 May 2014 19:23:39 +0200
+Subject: USB: cdc-acm: fix runtime PM for control messages
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit bae3f4c53585e9a170da9436e0f06919874bda9a upstream.
+
+Fix runtime PM handling of control messages by adding the required PM
+counter operations.
+
+Fixes: 11ea859d64b6 ("USB: additional power savings for cdc-acm devices
+that support remote wakeup")
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/class/cdc-acm.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -122,13 +122,23 @@ static void acm_release_minor(struct acm
+ static int acm_ctrl_msg(struct acm *acm, int request, int value,
+ void *buf, int len)
+ {
+- int retval = usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0),
++ int retval;
++
++ retval = usb_autopm_get_interface(acm->control);
++ if (retval)
++ return retval;
++
++ retval = usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0),
+ request, USB_RT_ACM, value,
+ acm->control->altsetting[0].desc.bInterfaceNumber,
+ buf, len, 5000);
++
+ dev_dbg(&acm->control->dev,
+ "%s - rq 0x%02x, val %#x, len %#x, result %d\n",
+ __func__, request, value, len, retval);
++
++ usb_autopm_put_interface(acm->control);
++
+ return retval < 0 ? retval : 0;
+ }
+
--- /dev/null
+From 5292afa657d0e790b7479ad8eef9450c1e040b3d Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Mon, 26 May 2014 19:23:45 +0200
+Subject: USB: cdc-acm: fix runtime PM imbalance at shutdown
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 5292afa657d0e790b7479ad8eef9450c1e040b3d upstream.
+
+Make sure only to decrement the PM counters if they were actually
+incremented.
+
+Note that the USB PM counter, but not necessarily the driver core PM
+counter, is reset when the interface is unbound.
+
+Fixes: 11ea859d64b6 ("USB: additional power savings for cdc-acm devices
+that support remote wakeup")
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/class/cdc-acm.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -590,12 +590,13 @@ static void acm_port_shutdown(struct tty
+ struct urb *urb;
+ struct acm_wb *wb;
+ int i;
++ int pm_err;
+
+ dev_dbg(&acm->control->dev, "%s\n", __func__);
+
+ mutex_lock(&acm->mutex);
+ if (!acm->disconnected) {
+- usb_autopm_get_interface(acm->control);
++ pm_err = usb_autopm_get_interface(acm->control);
+ acm_set_control(acm, acm->ctrlout = 0);
+
+ for (;;) {
+@@ -613,7 +614,8 @@ static void acm_port_shutdown(struct tty
+ for (i = 0; i < acm->rx_buflimit; i++)
+ usb_kill_urb(acm->read_urbs[i]);
+ acm->control->needs_remote_wakeup = 0;
+- usb_autopm_put_interface(acm->control);
++ if (!pm_err)
++ usb_autopm_put_interface(acm->control);
+ }
+ mutex_unlock(&acm->mutex);
+ }
--- /dev/null
+From ed797074031a37bb9bf4a70952fffc606b77274d Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Mon, 26 May 2014 19:23:40 +0200
+Subject: USB: cdc-acm: fix shutdown and suspend race
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit ed797074031a37bb9bf4a70952fffc606b77274d upstream.
+
+We should stop I/O unconditionally at suspend rather than rely on the
+tty-port initialised flag (which is set prior to stopping I/O during
+shutdown) in order to prevent suspend returning with URBs still active.
+
+Fixes: 11ea859d64b6 ("USB: additional power savings for cdc-acm devices
+that support remote wakeup")
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/class/cdc-acm.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -1550,8 +1550,7 @@ static int acm_suspend(struct usb_interf
+ if (cnt)
+ return 0;
+
+- if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags))
+- stop_data_traffic(acm);
++ stop_data_traffic(acm);
+
+ return 0;
+ }
--- /dev/null
+From e144ed28bed10684f9aaec6325ed974d53f76110 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Mon, 26 May 2014 19:23:37 +0200
+Subject: USB: cdc-acm: fix write and resume race
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit e144ed28bed10684f9aaec6325ed974d53f76110 upstream.
+
+Fix race between write() and resume() due to improper locking that could
+lead to writes being reordered.
+
+Resume must be done atomically and susp_count be protected by the
+write_lock in order to prevent racing with write(). This could otherwise
+lead to writes being reordered if write() grabs the write_lock after
+susp_count is decremented, but before the delayed urb is submitted.
+
+Fixes: 11ea859d64b6 ("USB: additional power savings for cdc-acm devices
+that support remote wakeup")
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/class/cdc-acm.c | 23 +++++++++--------------
+ 1 file changed, 9 insertions(+), 14 deletions(-)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -1541,27 +1541,20 @@ static int acm_resume(struct usb_interfa
+ struct acm *acm = usb_get_intfdata(intf);
+ struct acm_wb *wb;
+ int rv = 0;
+- int cnt;
+
+ spin_lock_irq(&acm->read_lock);
+- acm->susp_count -= 1;
+- cnt = acm->susp_count;
+- spin_unlock_irq(&acm->read_lock);
++ spin_lock(&acm->write_lock);
+
+- if (cnt)
+- return 0;
++ if (--acm->susp_count)
++ goto out;
+
+ if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags)) {
+- rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO);
++ rv = usb_submit_urb(acm->ctrlurb, GFP_ATOMIC);
+
+- spin_lock_irq(&acm->write_lock);
+ if (acm->delayed_wb) {
+ wb = acm->delayed_wb;
+ acm->delayed_wb = NULL;
+- spin_unlock_irq(&acm->write_lock);
+ acm_start_wb(acm, wb);
+- } else {
+- spin_unlock_irq(&acm->write_lock);
+ }
+
+ /*
+@@ -1569,12 +1562,14 @@ static int acm_resume(struct usb_interfa
+ * do the write path at all cost
+ */
+ if (rv < 0)
+- goto err_out;
++ goto out;
+
+- rv = acm_submit_read_urbs(acm, GFP_NOIO);
++ rv = acm_submit_read_urbs(acm, GFP_ATOMIC);
+ }
++out:
++ spin_unlock(&acm->write_lock);
++ spin_unlock_irq(&acm->read_lock);
+
+-err_out:
+ return rv;
+ }
+
--- /dev/null
+From 5a345c20c17d87099224a4be12e69e5bd7023dca Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Mon, 26 May 2014 19:23:36 +0200
+Subject: USB: cdc-acm: fix write and suspend race
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 5a345c20c17d87099224a4be12e69e5bd7023dca 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 write_lock after determining the
+device is idle but before incrementing the susp_count, thus leaving a
+window where a concurrent write() can submit an urb.
+
+Fixes: 11ea859d64b6 ("USB: additional power savings for cdc-acm devices
+that support remote wakeup")
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/class/cdc-acm.c | 15 ++++++---------
+ 1 file changed, 6 insertions(+), 9 deletions(-)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -1514,18 +1514,15 @@ static int acm_suspend(struct usb_interf
+ struct acm *acm = usb_get_intfdata(intf);
+ int cnt;
+
++ spin_lock_irq(&acm->read_lock);
++ spin_lock(&acm->write_lock);
+ if (PMSG_IS_AUTO(message)) {
+- int b;
+-
+- spin_lock_irq(&acm->write_lock);
+- b = acm->transmitting;
+- spin_unlock_irq(&acm->write_lock);
+- if (b)
++ if (acm->transmitting) {
++ spin_unlock(&acm->write_lock);
++ spin_unlock_irq(&acm->read_lock);
+ return -EBUSY;
++ }
+ }
+-
+- spin_lock_irq(&acm->read_lock);
+- spin_lock(&acm->write_lock);
+ cnt = acm->susp_count++;
+ spin_unlock(&acm->write_lock);
+ spin_unlock_irq(&acm->read_lock);