]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.7-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 5 Feb 2013 22:21:36 +0000 (14:21 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 5 Feb 2013 22:21:36 +0000 (14:21 -0800)
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
queue-3.7/usb-ehci-fix-bug-in-scheduling-periodic-split-transfers.patch [new file with mode: 0644]
queue-3.7/usb-ehci-fix-timer-bug-affecting-port-resume.patch [new file with mode: 0644]
queue-3.7/usb-ehci-remove-ass-pss-polling-timeout.patch [new file with mode: 0644]
queue-3.7/usb-ehci-unlink-one-async-qh-at-a-time.patch [new file with mode: 0644]
queue-3.7/usb-using-correct-way-to-clear-usb3.0-device-s-remote-wakeup-feature.patch [new file with mode: 0644]

index f551d185fc77fe9488c08eca2cdc1c013a6725c7..a9844bf832341a34b60c545eebc5041ec58c0b0f 100644 (file)
@@ -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 (file)
index 0000000..b749f48
--- /dev/null
@@ -0,0 +1,38 @@
+From 3e619d04159be54b3daa0b7036b0ce9e067f4b5d Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Wed, 30 Jan 2013 16:36:40 -0500
+Subject: USB: EHCI: fix bug in scheduling periodic split transfers
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+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 <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..c088dc8
--- /dev/null
@@ -0,0 +1,51 @@
+From ee74290b7853db9d5fd64db70e5c175241c59fba Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Fri, 25 Jan 2013 17:17:43 -0500
+Subject: USB: EHCI: fix timer bug affecting port resume
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+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 <stern@rowland.harvard.edu>
+Reported-and-tested-by: Norbert Preining <preining@logic.at>
+Tested-by: Ming Lei <ming.lei@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..e617a91
--- /dev/null
@@ -0,0 +1,80 @@
+From 55bcdce8a8228223ec4d17d8ded8134ed265d2c5 Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Fri, 25 Jan 2013 16:52:45 -0500
+Subject: USB: EHCI: remove ASS/PSS polling timeout
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+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 <stern@rowland.harvard.edu>
+Tested-by: Piergiorgio Sartor <piergiorgio.sartor@nexgo.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..88c0a3f
--- /dev/null
@@ -0,0 +1,122 @@
+From 6e0c3339a6f19d748f16091d0a05adeb1e1f822b Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Fri, 25 Jan 2013 16:54:22 -0500
+Subject: USB: EHCI: unlink one async QH at a time
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+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 <stern@rowland.harvard.edu>
+Reported-and-tested-by: Piergiorgio Sartor <piergiorgio.sartor@nexgo.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..a040d11
--- /dev/null
@@ -0,0 +1,140 @@
+From 54a3ac0c9e5b7213daa358ce74d154352657353a Mon Sep 17 00:00:00 2001
+From: Lan Tianyu <tianyu.lan@intel.com>
+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 <tianyu.lan@intel.com>
+
+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 <tianyu.lan@intel.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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. */