From: Greg Kroah-Hartman Date: Mon, 23 Jun 2014 19:37:09 +0000 (-0400) Subject: 3.10-stable patches X-Git-Tag: v3.4.95~25 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bad88a57831e88504b40e1a38f97e7ecc7790a4c;p=thirdparty%2Fkernel%2Fstable-queue.git 3.10-stable patches added patches: usb-cdc-acm-fix-broken-runtime-suspend.patch usb-cdc-acm-fix-i-o-after-failed-open.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 --- diff --git a/queue-3.10/series b/queue-3.10/series index c0417aa1404..6b271667b55 100644 --- a/queue-3.10/series +++ b/queue-3.10/series @@ -27,3 +27,10 @@ net-mlx4_core-preserve-pci_dev_data-after-__mlx4_remove_one.patch kvm-lapic-sync-highest-isr-to-hardware-apic-on-eoi.patch arm-at91-fix-at91_sysirq_mask_rtc-for-sam9x5-socs.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-i-o-after-failed-open.patch +usb-cdc-acm-fix-runtime-pm-imbalance-at-shutdown.patch diff --git a/queue-3.10/usb-cdc-acm-fix-broken-runtime-suspend.patch b/queue-3.10/usb-cdc-acm-fix-broken-runtime-suspend.patch new file mode 100644 index 00000000000..a1451398ab9 --- /dev/null +++ b/queue-3.10/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 +@@ -233,12 +233,9 @@ static int acm_write_start(struct acm *a + acm->susp_count); + 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 0; /* A white lie */ ++ return 0; + } + usb_mark_last_busy(acm->dev); + +@@ -591,6 +588,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__); +@@ -599,6 +598,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); +@@ -1190,6 +1199,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) { +@@ -1459,7 +1469,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); +@@ -1471,10 +1481,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 +@@ -117,7 +117,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.10/usb-cdc-acm-fix-i-o-after-failed-open.patch b/queue-3.10/usb-cdc-acm-fix-i-o-after-failed-open.patch new file mode 100644 index 00000000000..c540a2ddecd --- /dev/null +++ b/queue-3.10/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 +@@ -523,6 +523,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__); + +@@ -571,6 +572,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.10/usb-cdc-acm-fix-runtime-pm-for-control-messages.patch b/queue-3.10/usb-cdc-acm-fix-runtime-pm-for-control-messages.patch new file mode 100644 index 00000000000..7ed5e1605ef --- /dev/null +++ b/queue-3.10/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.10/usb-cdc-acm-fix-runtime-pm-imbalance-at-shutdown.patch b/queue-3.10/usb-cdc-acm-fix-runtime-pm-imbalance-at-shutdown.patch new file mode 100644 index 00000000000..90362624390 --- /dev/null +++ b/queue-3.10/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 +@@ -604,12 +604,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 (;;) { +@@ -627,7 +628,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.10/usb-cdc-acm-fix-shutdown-and-suspend-race.patch b/queue-3.10/usb-cdc-acm-fix-shutdown-and-suspend-race.patch new file mode 100644 index 00000000000..a5f6e3381f2 --- /dev/null +++ b/queue-3.10/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 +@@ -1470,8 +1470,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.10/usb-cdc-acm-fix-write-and-resume-race.patch b/queue-3.10/usb-cdc-acm-fix-write-and-resume-race.patch new file mode 100644 index 00000000000..eb48e67758d --- /dev/null +++ b/queue-3.10/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 +@@ -1461,27 +1461,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); + } + + /* +@@ -1489,12 +1482,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.10/usb-cdc-acm-fix-write-and-suspend-race.patch b/queue-3.10/usb-cdc-acm-fix-write-and-suspend-race.patch new file mode 100644 index 00000000000..062a5e7735a --- /dev/null +++ b/queue-3.10/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 +@@ -1434,18 +1434,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);