From c1f144fed96f10b1c7f58b882842b0a9d51d41ea Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 5 Feb 2013 14:21:36 -0800 Subject: [PATCH] 3.7-stable patches added patches: usb-ehci-fix-bug-in-scheduling-periodic-split-transfers.patch usb-ehci-fix-timer-bug-affecting-port-resume.patch usb-ehci-remove-ass-pss-polling-timeout.patch usb-ehci-unlink-one-async-qh-at-a-time.patch usb-using-correct-way-to-clear-usb3.0-device-s-remote-wakeup-feature.patch --- queue-3.7/series | 5 + ...-scheduling-periodic-split-transfers.patch | 38 +++++ ...-fix-timer-bug-affecting-port-resume.patch | 51 +++++++ ...-ehci-remove-ass-pss-polling-timeout.patch | 80 ++++++++++ ...b-ehci-unlink-one-async-qh-at-a-time.patch | 122 +++++++++++++++ ...sb3.0-device-s-remote-wakeup-feature.patch | 140 ++++++++++++++++++ 6 files changed, 436 insertions(+) create mode 100644 queue-3.7/usb-ehci-fix-bug-in-scheduling-periodic-split-transfers.patch create mode 100644 queue-3.7/usb-ehci-fix-timer-bug-affecting-port-resume.patch create mode 100644 queue-3.7/usb-ehci-remove-ass-pss-polling-timeout.patch create mode 100644 queue-3.7/usb-ehci-unlink-one-async-qh-at-a-time.patch create mode 100644 queue-3.7/usb-using-correct-way-to-clear-usb3.0-device-s-remote-wakeup-feature.patch diff --git a/queue-3.7/series b/queue-3.7/series index f551d185fc7..a9844bf8323 100644 --- a/queue-3.7/series +++ b/queue-3.7/series @@ -20,3 +20,8 @@ usb-ftdi_sio-add-pid-vid-entries-for-elv-ws-300-pc-ii.patch usb-option-add-support-for-telit-le920.patch usb-option-add-changhong-ch690.patch usb-qcserial-add-telit-gobi-qdl-device.patch +usb-ehci-remove-ass-pss-polling-timeout.patch +usb-ehci-unlink-one-async-qh-at-a-time.patch +usb-ehci-fix-timer-bug-affecting-port-resume.patch +usb-ehci-fix-bug-in-scheduling-periodic-split-transfers.patch +usb-using-correct-way-to-clear-usb3.0-device-s-remote-wakeup-feature.patch diff --git a/queue-3.7/usb-ehci-fix-bug-in-scheduling-periodic-split-transfers.patch b/queue-3.7/usb-ehci-fix-bug-in-scheduling-periodic-split-transfers.patch new file mode 100644 index 00000000000..b749f480ad5 --- /dev/null +++ b/queue-3.7/usb-ehci-fix-bug-in-scheduling-periodic-split-transfers.patch @@ -0,0 +1,38 @@ +From 3e619d04159be54b3daa0b7036b0ce9e067f4b5d Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Wed, 30 Jan 2013 16:36:40 -0500 +Subject: USB: EHCI: fix bug in scheduling periodic split transfers + +From: Alan Stern + +commit 3e619d04159be54b3daa0b7036b0ce9e067f4b5d upstream. + +This patch (as1654) fixes a very old bug in ehci-hcd, connected with +scheduling of periodic split transfers. The calculations for +full/low-speed bus usage are all carried out after the correction for +bit-stuffing has been applied, but the values in the max_tt_usecs +array assume it hasn't been. The array should allow for allocation of +up to 90% of the bus capacity, which is 900 us, not 780 us. + +The symptom caused by this bug is that any isochronous transfer to a +full-speed device with a maxpacket size larger than about 980 bytes is +always rejected with a -ENOSPC error. + +Signed-off-by: Alan Stern +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/ehci-sched.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/host/ehci-sched.c ++++ b/drivers/usb/host/ehci-sched.c +@@ -236,7 +236,7 @@ static inline unsigned char tt_start_ufr + } + + static const unsigned char +-max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 }; ++max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 125, 25 }; + + /* carryover low/fullspeed bandwidth that crosses uframe boundries */ + static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8]) diff --git a/queue-3.7/usb-ehci-fix-timer-bug-affecting-port-resume.patch b/queue-3.7/usb-ehci-fix-timer-bug-affecting-port-resume.patch new file mode 100644 index 00000000000..c088dc87435 --- /dev/null +++ b/queue-3.7/usb-ehci-fix-timer-bug-affecting-port-resume.patch @@ -0,0 +1,51 @@ +From ee74290b7853db9d5fd64db70e5c175241c59fba Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Fri, 25 Jan 2013 17:17:43 -0500 +Subject: USB: EHCI: fix timer bug affecting port resume + +From: Alan Stern + +commit ee74290b7853db9d5fd64db70e5c175241c59fba upstream. + +This patch (as1652) fixes a long-standing bug in ehci-hcd. The driver +relies on status polls to know when to stop port-resume signalling. +It uses the root-hub status timer to schedule these status polls. But +when the driver for the root hub is resumed, the timer is rescheduled +to go off immediately -- before the port is ready. When this happens +the timer does not get re-enabled, which prevents the port resume from +finishing until some other event occurs. + +The symptom is that when a new device is plugged in, it doesn't get +recognized or enumerated until lsusb is run or something else happens. + +The solution is to re-enable the root-hub status timer after every +status poll while a port resume is in progress. + +This bug hasn't surfaced before now because we never used to try to +suspend the root hub in the middle of a port resume (except by +coincidence). + +Signed-off-by: Alan Stern +Reported-and-tested-by: Norbert Preining +Tested-by: Ming Lei +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/ehci-hub.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/usb/host/ehci-hub.c ++++ b/drivers/usb/host/ehci-hub.c +@@ -623,7 +623,11 @@ ehci_hub_status_data (struct usb_hcd *hc + status = STS_PCD; + } + } +- /* FIXME autosuspend idle root hubs */ ++ ++ /* If a resume is in progress, make sure it can finish */ ++ if (ehci->resuming_ports) ++ mod_timer(&hcd->rh_timer, jiffies + msecs_to_jiffies(25)); ++ + spin_unlock_irqrestore (&ehci->lock, flags); + return status ? retval : 0; + } diff --git a/queue-3.7/usb-ehci-remove-ass-pss-polling-timeout.patch b/queue-3.7/usb-ehci-remove-ass-pss-polling-timeout.patch new file mode 100644 index 00000000000..e617a9196d3 --- /dev/null +++ b/queue-3.7/usb-ehci-remove-ass-pss-polling-timeout.patch @@ -0,0 +1,80 @@ +From 55bcdce8a8228223ec4d17d8ded8134ed265d2c5 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Fri, 25 Jan 2013 16:52:45 -0500 +Subject: USB: EHCI: remove ASS/PSS polling timeout + +From: Alan Stern + +commit 55bcdce8a8228223ec4d17d8ded8134ed265d2c5 upstream. + +This patch (as1647) attempts to work around a problem that seems to +affect some nVidia EHCI controllers. They sometimes take a very long +time to turn off their async or periodic schedules. I don't know if +this is a result of other problems, but in any case it seems wise not +to depend on schedule enables or disables taking effect in any +specific length of time. + +The patch removes the existing 20-ms timeout for enabling and +disabling the schedules. The driver will now continue to poll the +schedule state at 1-ms intervals until the controller finally decides +to obey the most recent command issued by the driver. Just in case +this hides a problem, a debugging message will be logged if the +controller takes longer than 20 polls. + +I don't know if this will actually fix anything, but it can't hurt. + +Signed-off-by: Alan Stern +Tested-by: Piergiorgio Sartor +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/ehci-timer.c | 29 +++++++++++++++-------------- + 1 file changed, 15 insertions(+), 14 deletions(-) + +--- a/drivers/usb/host/ehci-timer.c ++++ b/drivers/usb/host/ehci-timer.c +@@ -113,14 +113,15 @@ static void ehci_poll_ASS(struct ehci_hc + + if (want != actual) { + +- /* Poll again later, but give up after about 20 ms */ +- if (ehci->ASS_poll_count++ < 20) { +- ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true); +- return; +- } +- ehci_dbg(ehci, "Waited too long for the async schedule status (%x/%x), giving up\n", +- want, actual); ++ /* Poll again later */ ++ ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true); ++ ++ehci->ASS_poll_count; ++ return; + } ++ ++ if (ehci->ASS_poll_count > 20) ++ ehci_dbg(ehci, "ASS poll count reached %d\n", ++ ehci->ASS_poll_count); + ehci->ASS_poll_count = 0; + + /* The status is up-to-date; restart or stop the schedule as needed */ +@@ -159,14 +160,14 @@ static void ehci_poll_PSS(struct ehci_hc + + if (want != actual) { + +- /* Poll again later, but give up after about 20 ms */ +- if (ehci->PSS_poll_count++ < 20) { +- ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true); +- return; +- } +- ehci_dbg(ehci, "Waited too long for the periodic schedule status (%x/%x), giving up\n", +- want, actual); ++ /* Poll again later */ ++ ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true); ++ return; + } ++ ++ if (ehci->PSS_poll_count > 20) ++ ehci_dbg(ehci, "PSS poll count reached %d\n", ++ ehci->PSS_poll_count); + ehci->PSS_poll_count = 0; + + /* The status is up-to-date; restart or stop the schedule as needed */ diff --git a/queue-3.7/usb-ehci-unlink-one-async-qh-at-a-time.patch b/queue-3.7/usb-ehci-unlink-one-async-qh-at-a-time.patch new file mode 100644 index 00000000000..88c0a3fa7bd --- /dev/null +++ b/queue-3.7/usb-ehci-unlink-one-async-qh-at-a-time.patch @@ -0,0 +1,122 @@ +From 6e0c3339a6f19d748f16091d0a05adeb1e1f822b Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Fri, 25 Jan 2013 16:54:22 -0500 +Subject: USB: EHCI: unlink one async QH at a time + +From: Alan Stern + +commit 6e0c3339a6f19d748f16091d0a05adeb1e1f822b upstream. + +This patch (as1648) fixes a regression affecting nVidia EHCI +controllers. Evidently they don't like to have more than one async QH +unlinked at a time. I can't imagine how they manage to mess it up, +but at least one of them does. + +The patch changes the async unlink logic in two ways: + + Each time an IAA cycle is started, only the first QH on the + async unlink list is handled (rather than all of them). + + Async QHs do not all get unlinked as soon as they have been + empty for long enough. Instead, only the last one (i.e., the + one that has been on the schedule the longest) is unlinked, + and then only if no other unlinks are in progress at the time. + +This means that when multiple QHs are empty, they won't be unlinked as +quickly as before. That's okay; it won't affect correct operation of +the driver or add an excessive load. Multiple unlinks tend to be +relatively rare in any case. + +Signed-off-by: Alan Stern +Reported-and-tested-by: Piergiorgio Sartor +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/ehci-q.c | 50 +++++++++++++++++++++++++++------------------- + 1 file changed, 30 insertions(+), 20 deletions(-) + +--- a/drivers/usb/host/ehci-q.c ++++ b/drivers/usb/host/ehci-q.c +@@ -1197,17 +1197,26 @@ static void start_iaa_cycle(struct ehci_ + if (ehci->async_iaa || ehci->async_unlinking) + return; + +- /* Do all the waiting QHs at once */ +- ehci->async_iaa = ehci->async_unlink; +- ehci->async_unlink = NULL; +- + /* If the controller isn't running, we don't have to wait for it */ + if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) { ++ ++ /* Do all the waiting QHs */ ++ ehci->async_iaa = ehci->async_unlink; ++ ehci->async_unlink = NULL; ++ + if (!nested) /* Avoid recursion */ + end_unlink_async(ehci); + + /* Otherwise start a new IAA cycle */ + } else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) { ++ struct ehci_qh *qh; ++ ++ /* Do only the first waiting QH (nVidia bug?) */ ++ qh = ehci->async_unlink; ++ ehci->async_iaa = qh; ++ ehci->async_unlink = qh->unlink_next; ++ qh->unlink_next = NULL; ++ + /* Make sure the unlinks are all visible to the hardware */ + wmb(); + +@@ -1255,34 +1264,35 @@ static void end_unlink_async(struct ehci + } + } + ++static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh); ++ + static void unlink_empty_async(struct ehci_hcd *ehci) + { +- struct ehci_qh *qh, *next; +- bool stopped = (ehci->rh_state < EHCI_RH_RUNNING); ++ struct ehci_qh *qh; ++ struct ehci_qh *qh_to_unlink = NULL; + bool check_unlinks_later = false; ++ int count = 0; + +- /* Unlink all the async QHs that have been empty for a timer cycle */ +- next = ehci->async->qh_next.qh; +- while (next) { +- qh = next; +- next = qh->qh_next.qh; +- ++ /* Find the last async QH which has been empty for a timer cycle */ ++ for (qh = ehci->async->qh_next.qh; qh; qh = qh->qh_next.qh) { + if (list_empty(&qh->qtd_list) && + qh->qh_state == QH_STATE_LINKED) { +- if (!stopped && qh->unlink_cycle == +- ehci->async_unlink_cycle) ++ ++count; ++ if (qh->unlink_cycle == ehci->async_unlink_cycle) + check_unlinks_later = true; + else +- single_unlink_async(ehci, qh); ++ qh_to_unlink = qh; + } + } + +- /* Start a new IAA cycle if any QHs are waiting for it */ +- if (ehci->async_unlink) +- start_iaa_cycle(ehci, false); ++ /* If nothing else is being unlinked, unlink the last empty QH */ ++ if (!ehci->async_iaa && !ehci->async_unlink && qh_to_unlink) { ++ start_unlink_async(ehci, qh_to_unlink); ++ --count; ++ } + +- /* QHs that haven't been empty for long enough will be handled later */ +- if (check_unlinks_later) { ++ /* Other QHs will be handled later */ ++ if (count > 0) { + ehci_enable_event(ehci, EHCI_HRTIMER_ASYNC_UNLINKS, true); + ++ehci->async_unlink_cycle; + } diff --git a/queue-3.7/usb-using-correct-way-to-clear-usb3.0-device-s-remote-wakeup-feature.patch b/queue-3.7/usb-using-correct-way-to-clear-usb3.0-device-s-remote-wakeup-feature.patch new file mode 100644 index 00000000000..a040d111a3b --- /dev/null +++ b/queue-3.7/usb-using-correct-way-to-clear-usb3.0-device-s-remote-wakeup-feature.patch @@ -0,0 +1,140 @@ +From 54a3ac0c9e5b7213daa358ce74d154352657353a Mon Sep 17 00:00:00 2001 +From: Lan Tianyu +Date: Thu, 24 Jan 2013 10:31:28 +0800 +Subject: usb: Using correct way to clear usb3.0 device's remote wakeup feature. + +From: Lan Tianyu + +commit 54a3ac0c9e5b7213daa358ce74d154352657353a upstream. + +Usb3.0 device defines function remote wakeup which is only for interface +recipient rather than device recipient. This is different with usb2.0 device's +remote wakeup feature which is defined for device recipient. According usb3.0 +spec 9.4.5, the function remote wakeup can be modified by the SetFeature() +requests using the FUNCTION_SUSPEND feature selector. This patch is to use +correct way to disable usb3.0 device's function remote wakeup after suspend +error and resuming. + +This should be backported to kernels as old as 3.4, that contain the +commit 623bef9e03a60adc623b09673297ca7a1cdfb367 "USB/xhci: Enable remote +wakeup for USB3 devices." + +Signed-off-by: Lan Tianyu +Signed-off-by: Sarah Sharp +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/hub.c | 70 +++++++++++++++++++++++++++++++------------ + include/uapi/linux/usb/ch9.h | 6 +++ + 2 files changed, 58 insertions(+), 18 deletions(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -2799,6 +2799,23 @@ void usb_enable_ltm(struct usb_device *u + EXPORT_SYMBOL_GPL(usb_enable_ltm); + + #ifdef CONFIG_USB_SUSPEND ++/* ++ * usb_disable_function_remotewakeup - disable usb3.0 ++ * device's function remote wakeup ++ * @udev: target device ++ * ++ * Assume there's only one function on the USB 3.0 ++ * device and disable remote wake for the first ++ * interface. FIXME if the interface association ++ * descriptor shows there's more than one function. ++ */ ++static int usb_disable_function_remotewakeup(struct usb_device *udev) ++{ ++ return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), ++ USB_REQ_CLEAR_FEATURE, USB_RECIP_INTERFACE, ++ USB_INTRF_FUNC_SUSPEND, 0, NULL, 0, ++ USB_CTRL_SET_TIMEOUT); ++} + + /* + * usb_port_suspend - suspend a usb device's upstream port +@@ -2916,12 +2933,19 @@ int usb_port_suspend(struct usb_device * + dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n", + port1, status); + /* paranoia: "should not happen" */ +- if (udev->do_remote_wakeup) +- (void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0), +- USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, +- USB_DEVICE_REMOTE_WAKEUP, 0, +- NULL, 0, +- USB_CTRL_SET_TIMEOUT); ++ if (udev->do_remote_wakeup) { ++ if (!hub_is_superspeed(hub->hdev)) { ++ (void) usb_control_msg(udev, ++ usb_sndctrlpipe(udev, 0), ++ USB_REQ_CLEAR_FEATURE, ++ USB_RECIP_DEVICE, ++ USB_DEVICE_REMOTE_WAKEUP, 0, ++ NULL, 0, ++ USB_CTRL_SET_TIMEOUT); ++ } else ++ (void) usb_disable_function_remotewakeup(udev); ++ ++ } + + /* Try to enable USB2 hardware LPM again */ + if (udev->usb2_hw_lpm_capable == 1) +@@ -3012,20 +3036,30 @@ static int finish_port_resume(struct usb + * udev->reset_resume + */ + } else if (udev->actconfig && !udev->reset_resume) { +- le16_to_cpus(&devstatus); +- if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) { +- status = usb_control_msg(udev, +- usb_sndctrlpipe(udev, 0), +- USB_REQ_CLEAR_FEATURE, ++ if (!hub_is_superspeed(udev->parent)) { ++ le16_to_cpus(&devstatus); ++ if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) ++ status = usb_control_msg(udev, ++ usb_sndctrlpipe(udev, 0), ++ USB_REQ_CLEAR_FEATURE, + USB_RECIP_DEVICE, +- USB_DEVICE_REMOTE_WAKEUP, 0, +- NULL, 0, +- USB_CTRL_SET_TIMEOUT); +- if (status) +- dev_dbg(&udev->dev, +- "disable remote wakeup, status %d\n", +- status); ++ USB_DEVICE_REMOTE_WAKEUP, 0, ++ NULL, 0, ++ USB_CTRL_SET_TIMEOUT); ++ } else { ++ status = usb_get_status(udev, USB_RECIP_INTERFACE, 0, ++ &devstatus); ++ le16_to_cpus(&devstatus); ++ if (!status && devstatus & (USB_INTRF_STAT_FUNC_RW_CAP ++ | USB_INTRF_STAT_FUNC_RW)) ++ status = ++ usb_disable_function_remotewakeup(udev); + } ++ ++ if (status) ++ dev_dbg(&udev->dev, ++ "disable remote wakeup, status %d\n", ++ status); + status = 0; + } + return status; +--- a/include/uapi/linux/usb/ch9.h ++++ b/include/uapi/linux/usb/ch9.h +@@ -152,6 +152,12 @@ + #define USB_INTRF_FUNC_SUSPEND_LP (1 << (8 + 0)) + #define USB_INTRF_FUNC_SUSPEND_RW (1 << (8 + 1)) + ++/* ++ * Interface status, Figure 9-5 USB 3.0 spec ++ */ ++#define USB_INTRF_STAT_FUNC_RW_CAP 1 ++#define USB_INTRF_STAT_FUNC_RW 2 ++ + #define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */ + + /* Bit array elements as returned by the USB_REQ_GET_STATUS request. */ -- 2.47.3