From 30aa22c75b0d9cc5238c31075745e9fee1eb1bec Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 23 Jun 2014 15:37:55 -0400 Subject: [PATCH] 3.15-stable patches added patches: usb-cdc-acm-fix-broken-runtime-suspend.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-open-and-suspend-race.patch usb-cdc-acm-fix-potential-urb-leak-and-pm-imbalance-in-write.patch usb-cdc-acm-fix-runtime-pm-for-control-messages.patch usb-cdc-acm-fix-runtime-pm-imbalance-at-shutdown.patch usb-cdc-acm-fix-shutdown-and-suspend-race.patch usb-cdc-acm-fix-write-and-resume-race.patch usb-cdc-acm-fix-write-and-suspend-race.patch --- queue-3.15/series | 10 ++ ...b-cdc-acm-fix-broken-runtime-suspend.patch | 125 ++++++++++++++++++ ...m-fix-failed-open-not-being-detected.patch | 67 ++++++++++ ...sb-cdc-acm-fix-i-o-after-failed-open.patch | 39 ++++++ ...sb-cdc-acm-fix-open-and-suspend-race.patch | 59 +++++++++ ...l-urb-leak-and-pm-imbalance-in-write.patch | 39 ++++++ ...-fix-runtime-pm-for-control-messages.patch | 49 +++++++ ...fix-runtime-pm-imbalance-at-shutdown.patch | 52 ++++++++ ...dc-acm-fix-shutdown-and-suspend-race.patch | 35 +++++ ...sb-cdc-acm-fix-write-and-resume-race.patch | 79 +++++++++++ ...b-cdc-acm-fix-write-and-suspend-race.patch | 54 ++++++++ 11 files changed, 608 insertions(+) create mode 100644 queue-3.15/usb-cdc-acm-fix-broken-runtime-suspend.patch create mode 100644 queue-3.15/usb-cdc-acm-fix-failed-open-not-being-detected.patch create mode 100644 queue-3.15/usb-cdc-acm-fix-i-o-after-failed-open.patch create mode 100644 queue-3.15/usb-cdc-acm-fix-open-and-suspend-race.patch create mode 100644 queue-3.15/usb-cdc-acm-fix-potential-urb-leak-and-pm-imbalance-in-write.patch create mode 100644 queue-3.15/usb-cdc-acm-fix-runtime-pm-for-control-messages.patch create mode 100644 queue-3.15/usb-cdc-acm-fix-runtime-pm-imbalance-at-shutdown.patch create mode 100644 queue-3.15/usb-cdc-acm-fix-shutdown-and-suspend-race.patch create mode 100644 queue-3.15/usb-cdc-acm-fix-write-and-resume-race.patch create mode 100644 queue-3.15/usb-cdc-acm-fix-write-and-suspend-race.patch diff --git a/queue-3.15/series b/queue-3.15/series index 960f30e8713..d7a46157633 100644 --- a/queue-3.15/series +++ b/queue-3.15/series @@ -23,3 +23,13 @@ arm-at91-fix-at91_sysirq_mask_rtc-for-sam9x5-socs.patch 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 diff --git a/queue-3.15/usb-cdc-acm-fix-broken-runtime-suspend.patch b/queue-3.15/usb-cdc-acm-fix-broken-runtime-suspend.patch new file mode 100644 index 00000000000..5ec29e10dab --- /dev/null +++ b/queue-3.15/usb-cdc-acm-fix-broken-runtime-suspend.patch @@ -0,0 +1,125 @@ +From 140cb81ac8c625942a1d695875932c615767a526 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 26 May 2014 19:23:38 +0200 +Subject: USB: cdc-acm: fix broken runtime suspend + +From: Johan Hovold + +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 +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + 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 diff --git a/queue-3.15/usb-cdc-acm-fix-failed-open-not-being-detected.patch b/queue-3.15/usb-cdc-acm-fix-failed-open-not-being-detected.patch new file mode 100644 index 00000000000..7c8628c89c5 --- /dev/null +++ b/queue-3.15/usb-cdc-acm-fix-failed-open-not-being-detected.patch @@ -0,0 +1,67 @@ +From 8727bf689a77a79816065e23a7a58a474ad544f9 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 26 May 2014 19:23:43 +0200 +Subject: USB: cdc-acm: fix failed open not being detected + +From: Johan Hovold + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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) diff --git a/queue-3.15/usb-cdc-acm-fix-i-o-after-failed-open.patch b/queue-3.15/usb-cdc-acm-fix-i-o-after-failed-open.patch new file mode 100644 index 00000000000..d89b46461c5 --- /dev/null +++ b/queue-3.15/usb-cdc-acm-fix-i-o-after-failed-open.patch @@ -0,0 +1,39 @@ +From e4c36076c2a6195ec62c35b03c3fde84d0087dc8 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 26 May 2014 19:23:44 +0200 +Subject: USB: cdc-acm: fix I/O after failed open + +From: Johan Hovold + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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: diff --git a/queue-3.15/usb-cdc-acm-fix-open-and-suspend-race.patch b/queue-3.15/usb-cdc-acm-fix-open-and-suspend-race.patch new file mode 100644 index 00000000000..7d05956274a --- /dev/null +++ b/queue-3.15/usb-cdc-acm-fix-open-and-suspend-race.patch @@ -0,0 +1,59 @@ +From 703df3297fb1950b0aa53e656108eb936d3f21d9 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 26 May 2014 19:23:42 +0200 +Subject: USB: cdc-acm: fix open and suspend race + +From: Johan Hovold + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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); diff --git a/queue-3.15/usb-cdc-acm-fix-potential-urb-leak-and-pm-imbalance-in-write.patch b/queue-3.15/usb-cdc-acm-fix-potential-urb-leak-and-pm-imbalance-in-write.patch new file mode 100644 index 00000000000..c3628063607 --- /dev/null +++ b/queue-3.15/usb-cdc-acm-fix-potential-urb-leak-and-pm-imbalance-in-write.patch @@ -0,0 +1,39 @@ +From 183a45087d126d126e8dd1d9b2602fc129dff9ad Mon Sep 17 00:00:00 2001 +From: Johan Hovold +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 + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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); diff --git a/queue-3.15/usb-cdc-acm-fix-runtime-pm-for-control-messages.patch b/queue-3.15/usb-cdc-acm-fix-runtime-pm-for-control-messages.patch new file mode 100644 index 00000000000..7ed5e1605ef --- /dev/null +++ b/queue-3.15/usb-cdc-acm-fix-runtime-pm-for-control-messages.patch @@ -0,0 +1,49 @@ +From bae3f4c53585e9a170da9436e0f06919874bda9a Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 26 May 2014 19:23:39 +0200 +Subject: USB: cdc-acm: fix runtime PM for control messages + +From: Johan Hovold + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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; + } + diff --git a/queue-3.15/usb-cdc-acm-fix-runtime-pm-imbalance-at-shutdown.patch b/queue-3.15/usb-cdc-acm-fix-runtime-pm-imbalance-at-shutdown.patch new file mode 100644 index 00000000000..fc45a16c4a6 --- /dev/null +++ b/queue-3.15/usb-cdc-acm-fix-runtime-pm-imbalance-at-shutdown.patch @@ -0,0 +1,52 @@ +From 5292afa657d0e790b7479ad8eef9450c1e040b3d Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 26 May 2014 19:23:45 +0200 +Subject: USB: cdc-acm: fix runtime PM imbalance at shutdown + +From: Johan Hovold + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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); + } diff --git a/queue-3.15/usb-cdc-acm-fix-shutdown-and-suspend-race.patch b/queue-3.15/usb-cdc-acm-fix-shutdown-and-suspend-race.patch new file mode 100644 index 00000000000..6bca412247b --- /dev/null +++ b/queue-3.15/usb-cdc-acm-fix-shutdown-and-suspend-race.patch @@ -0,0 +1,35 @@ +From ed797074031a37bb9bf4a70952fffc606b77274d Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 26 May 2014 19:23:40 +0200 +Subject: USB: cdc-acm: fix shutdown and suspend race + +From: Johan Hovold + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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; + } diff --git a/queue-3.15/usb-cdc-acm-fix-write-and-resume-race.patch b/queue-3.15/usb-cdc-acm-fix-write-and-resume-race.patch new file mode 100644 index 00000000000..a0231205dbd --- /dev/null +++ b/queue-3.15/usb-cdc-acm-fix-write-and-resume-race.patch @@ -0,0 +1,79 @@ +From e144ed28bed10684f9aaec6325ed974d53f76110 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 26 May 2014 19:23:37 +0200 +Subject: USB: cdc-acm: fix write and resume race + +From: Johan Hovold + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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; + } + diff --git a/queue-3.15/usb-cdc-acm-fix-write-and-suspend-race.patch b/queue-3.15/usb-cdc-acm-fix-write-and-suspend-race.patch new file mode 100644 index 00000000000..a4aa2811fb5 --- /dev/null +++ b/queue-3.15/usb-cdc-acm-fix-write-and-suspend-race.patch @@ -0,0 +1,54 @@ +From 5a345c20c17d87099224a4be12e69e5bd7023dca Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 26 May 2014 19:23:36 +0200 +Subject: USB: cdc-acm: fix write and suspend race + +From: Johan Hovold + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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); -- 2.47.3