]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 15 Jan 2013 13:04:43 +0000 (05:04 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 15 Jan 2013 13:04:43 +0000 (05:04 -0800)
added patches:
usb-handle-warm-reset-failure-on-empty-port.patch
usb-hub-handle-claim-of-enabled-remote-wakeup-after-reset.patch
usb-ignore-port-state-until-reset-completes.patch
xhci-avoid-dead-ports-add-roothub-port-polling.patch
xhci-handle-hs-bulk-ctrl-endpoints-that-don-t-nak.patch

queue-3.4/series
queue-3.4/usb-handle-warm-reset-failure-on-empty-port.patch [new file with mode: 0644]
queue-3.4/usb-hub-handle-claim-of-enabled-remote-wakeup-after-reset.patch [new file with mode: 0644]
queue-3.4/usb-ignore-port-state-until-reset-completes.patch [new file with mode: 0644]
queue-3.4/xhci-avoid-dead-ports-add-roothub-port-polling.patch [new file with mode: 0644]
queue-3.4/xhci-handle-hs-bulk-ctrl-endpoints-that-don-t-nak.patch [new file with mode: 0644]

index e295ea8ce05c91545c4f0f71a856a2bc6c909849..a0d5f6fa3fa15a36019ad9df47e3ffc42c60de92 100644 (file)
@@ -101,3 +101,8 @@ usb-handle-auto-transition-from-hot-to-warm-reset.patch
 usb-ignore-xhci-reset-device-status.patch
 usb-allow-usb-3.0-ports-to-be-disabled.patch
 usb-increase-reset-timeout.patch
+usb-ignore-port-state-until-reset-completes.patch
+usb-handle-warm-reset-failure-on-empty-port.patch
+xhci-avoid-dead-ports-add-roothub-port-polling.patch
+usb-hub-handle-claim-of-enabled-remote-wakeup-after-reset.patch
+xhci-handle-hs-bulk-ctrl-endpoints-that-don-t-nak.patch
diff --git a/queue-3.4/usb-handle-warm-reset-failure-on-empty-port.patch b/queue-3.4/usb-handle-warm-reset-failure-on-empty-port.patch
new file mode 100644 (file)
index 0000000..1f09e82
--- /dev/null
@@ -0,0 +1,76 @@
+From 65bdac5effd15d6af619b3b7218627ef4d84ed6a Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Wed, 14 Nov 2012 17:58:04 -0800
+Subject: USB: Handle warm reset failure on empty port.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit 65bdac5effd15d6af619b3b7218627ef4d84ed6a upstream.
+
+An empty port can transition to either Inactive or Compliance Mode if a
+newly connected USB 3.0 device fails to link train.  In that case, we
+issue a warm reset.  Some devices, such as John's Roseweil eusb3
+enclosure, slip back into Compliance Mode after the warm reset.
+
+The current warm reset code does not check for device connect status on
+warm reset completion, and it incorrectly reports the warm reset
+succeeded.  This causes the USB core to attempt to send a Set Address
+control transfer to a port in Compliance Mode, which will always fail.
+
+Make hub_port_wait_reset check the current connect status and link state
+after the warm reset completes.  Return a failure status if the device
+is disconnected or the link state is Compliance Mode or SS.Inactive.
+
+Make hub_events disable the port if warm reset fails.  This will disable
+the port, and then bring it back into the RxDetect state.  Make the USB
+core ignore the connect change until the device reconnects.
+
+Note that this patch does NOT handle connected devices slipping into the
+Inactive state very well.  This is a concern, because devices can go
+into the Inactive state on U1/U2 exit failure.  However, the fix for
+that case is too large for stable, so it will be submitted in a separate
+patch.
+
+This patch should be backported to kernels as old as 3.2, contain the
+commit ID 75d7cf72ab9fa01dc70877aa5c68e8ef477229dc "usbcore: refine warm
+reset logic"
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Reported-by: John Covici <covici@ccs.covici.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/core/hub.c |   12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2266,6 +2266,11 @@ static int hub_port_wait_reset(struct us
+                               return 0;
+                       }
+               } else {
++                      if (!(portstatus & USB_PORT_STAT_CONNECTION) ||
++                                      hub_port_warm_reset_required(hub,
++                                              portstatus))
++                              return -ENOTCONN;
++
+                       return 0;
+               }
+@@ -3830,9 +3835,14 @@ static void hub_events(void)
+                        * SS.Inactive state.
+                        */
+                       if (hub_port_warm_reset_required(hub, portstatus)) {
++                              int status;
++
+                               dev_dbg(hub_dev, "warm reset port %d\n", i);
+-                              hub_port_reset(hub, i, NULL,
++                              status = hub_port_reset(hub, i, NULL,
+                                               HUB_BH_RESET_TIME, true);
++                              if (status < 0)
++                                      hub_port_disable(hub, i, 1);
++                              connect_change = 0;
+                       }
+                       if (connect_change)
diff --git a/queue-3.4/usb-hub-handle-claim-of-enabled-remote-wakeup-after-reset.patch b/queue-3.4/usb-hub-handle-claim-of-enabled-remote-wakeup-after-reset.patch
new file mode 100644 (file)
index 0000000..4894502
--- /dev/null
@@ -0,0 +1,50 @@
+From 07e72b95f5038cc82304b9a4a2eb7f9fc391ea68 Mon Sep 17 00:00:00 2001
+From: Oliver Neukum <oliver@neukum.org>
+Date: Thu, 29 Nov 2012 15:05:57 +0100
+Subject: USB: hub: handle claim of enabled remote wakeup after reset
+
+From: Oliver Neukum <oliver@neukum.org>
+
+commit 07e72b95f5038cc82304b9a4a2eb7f9fc391ea68 upstream.
+
+Some touchscreens have buggy firmware which claims
+remote wakeup to be enabled after a reset. They nevertheless
+crash if the feature is cleared by the host.
+Add a check for reset resume before checking for
+an enabled remote wakeup feature. On compliant
+devices the feature must be cleared after a reset anyway.
+
+Signed-off-by: Oliver Neukum <oneukum@suse.de>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/core/hub.c |   10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2609,7 +2609,7 @@ int usb_port_suspend(struct usb_device *
+ static int finish_port_resume(struct usb_device *udev)
+ {
+       int     status = 0;
+-      u16     devstatus;
++      u16     devstatus = 0;
+       /* caller owns the udev device lock */
+       dev_dbg(&udev->dev, "%s\n",
+@@ -2654,7 +2654,13 @@ static int finish_port_resume(struct usb
+       if (status) {
+               dev_dbg(&udev->dev, "gone after usb resume? status %d\n",
+                               status);
+-      } else if (udev->actconfig) {
++      /*
++       * There are a few quirky devices which violate the standard
++       * by claiming to have remote wakeup enabled after a reset,
++       * which crash if the feature is cleared, hence check for
++       * 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,
diff --git a/queue-3.4/usb-ignore-port-state-until-reset-completes.patch b/queue-3.4/usb-ignore-port-state-until-reset-completes.patch
new file mode 100644 (file)
index 0000000..ff7f15b
--- /dev/null
@@ -0,0 +1,84 @@
+From 4f43447e62b37ee19c82a13f72f35b1ca60a74d3 Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Thu, 15 Nov 2012 14:58:04 -0800
+Subject: USB: Ignore port state until reset completes.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit 4f43447e62b37ee19c82a13f72f35b1ca60a74d3 upstream.
+
+The port reset code bails out early if the current connect status is
+cleared (device disconnected).  If we're issuing a hot reset, it may
+also look at the link state before the reset is finished.
+
+Section 10.14.2.6 of the USB 3.0 spec says that when a port enters the
+Error state or Resetting state, the port connection bit retains the
+value from the previous state.  Therefore we can't trust it until the
+reset finishes.  Also, the xHCI spec section 4.19.1.2.5 says software
+shall ignore the link state while the port is resetting, as it can be in
+an unknown state.
+
+The port state during reset is also unknown for USB 2.0 hubs.  The hub
+sends a reset signal by driving the bus into an SE0 state.  This
+overwhelms the "connect" signal from the device, so the port can't tell
+whether anything is connected or not.
+
+Fix the port reset code to ignore the port link state and current
+connect bit until the reset finishes, and USB_PORT_STAT_RESET is
+cleared.
+
+Remove the check for USB_PORT_STAT_C_BH_RESET in the warm reset case,
+because it's redundant.  When the warm reset finishes, the port reset
+bit will be cleared at the same time USB_PORT_STAT_C_BH_RESET is set.
+Remove the now-redundant check for a cleared USB_PORT_STAT_RESET bit
+in the code to deal with the finished reset.
+
+This patch should be backported to all stable kernels.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/core/hub.c |   14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2203,6 +2203,10 @@ static int hub_port_wait_reset(struct us
+               if (ret < 0)
+                       return ret;
++              /* The port state is unknown until the reset completes. */
++              if ((portstatus & USB_PORT_STAT_RESET))
++                      goto delay;
++
+               /*
+                * Some buggy devices require a warm reset to be issued even
+                * when the port appears not to be connected.
+@@ -2248,11 +2252,7 @@ static int hub_port_wait_reset(struct us
+                       if ((portchange & USB_PORT_STAT_C_CONNECTION))
+                               return -ENOTCONN;
+-                      /* if we`ve finished resetting, then break out of
+-                       * the loop
+-                       */
+-                      if (!(portstatus & USB_PORT_STAT_RESET) &&
+-                          (portstatus & USB_PORT_STAT_ENABLE)) {
++                      if ((portstatus & USB_PORT_STAT_ENABLE)) {
+                               if (hub_is_wusb(hub))
+                                       udev->speed = USB_SPEED_WIRELESS;
+                               else if (hub_is_superspeed(hub->hdev))
+@@ -2266,10 +2266,10 @@ static int hub_port_wait_reset(struct us
+                               return 0;
+                       }
+               } else {
+-                      if (portchange & USB_PORT_STAT_C_BH_RESET)
+-                              return 0;
++                      return 0;
+               }
++delay:
+               /* switch to the long delay after two short delay failures */
+               if (delay_time >= 2 * HUB_SHORT_RESET_TIME)
+                       delay = HUB_LONG_RESET_TIME;
diff --git a/queue-3.4/xhci-avoid-dead-ports-add-roothub-port-polling.patch b/queue-3.4/xhci-avoid-dead-ports-add-roothub-port-polling.patch
new file mode 100644 (file)
index 0000000..41e3cf3
--- /dev/null
@@ -0,0 +1,119 @@
+From c52804a472649b2e5005342308739434cbd51119 Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Tue, 27 Nov 2012 12:30:23 -0800
+Subject: xhci: Avoid "dead ports", add roothub port polling.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit c52804a472649b2e5005342308739434cbd51119 upstream.
+
+The USB core hub thread (khubd) is designed with external USB hubs in
+mind.  It expects that if a port status change bit is set, the hub will
+continue to send a notification through the hub status data transfer.
+Basically, it expects hub notifications to be level-triggered.
+
+The xHCI host controller is designed to be edge-triggered on the logical
+'OR' of all the port status change bits.  When all port status change
+bits are clear, and a new change bit is set, the xHC will generate a
+Port Status Change Event.  If another change bit is set in the same port
+status register before the first bit is cleared, it will not send
+another event.
+
+This means that the hub code may lose port status changes because of
+race conditions between clearing change bits.  The user sees this as a
+"dead port" that doesn't react to device connects.
+
+The fix is to turn on port polling whenever a new change bit is set.
+Once the USB core issues a hub status request that shows that no change
+bits are set in any USB ports, turn off port polling.
+
+We can't allow the USB core to poll the roothub for port events during
+host suspend because if the PCI host is in D3cold, the port registers
+will be all f's.  Instead, stop the port polling timer, and
+unconditionally restart it when the host resumes.  If there are no port
+change bits set after the resume, the first call to hub_status_data will
+disable polling.
+
+This patch should be backported to stable kernels with the first xHCI
+support, 2.6.31 and newer, that include the commit
+0f2a79300a1471cf92ab43af165ea13555c8b0a5 "USB: xhci: Root hub support."
+There will be merge conflicts because the check for HC_STATE_SUSPENDED
+was moved into xhci_suspend in 3.8.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-hub.c  |    7 +++++++
+ drivers/usb/host/xhci-ring.c |    9 +++++++++
+ drivers/usb/host/xhci.c      |   10 ++++++++++
+ 3 files changed, 26 insertions(+)
+
+--- a/drivers/usb/host/xhci-hub.c
++++ b/drivers/usb/host/xhci-hub.c
+@@ -940,6 +940,7 @@ int xhci_hub_status_data(struct usb_hcd
+       int max_ports;
+       __le32 __iomem **port_array;
+       struct xhci_bus_state *bus_state;
++      bool reset_change = false;
+       max_ports = xhci_get_ports(hcd, &port_array);
+       bus_state = &xhci->bus_state[hcd_index(hcd)];
+@@ -971,6 +972,12 @@ int xhci_hub_status_data(struct usb_hcd
+                       buf[(i + 1) / 8] |= 1 << (i + 1) % 8;
+                       status = 1;
+               }
++              if ((temp & PORT_RC))
++                      reset_change = true;
++      }
++      if (!status && !reset_change) {
++              xhci_dbg(xhci, "%s: stopping port polling.\n", __func__);
++              clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+       }
+       spin_unlock_irqrestore(&xhci->lock, flags);
+       return status ? retval : 0;
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1725,6 +1725,15 @@ cleanup:
+       if (bogus_port_status)
+               return;
++      /*
++       * xHCI port-status-change events occur when the "or" of all the
++       * status-change bits in the portsc register changes from 0 to 1.
++       * New status changes won't cause an event if any other change
++       * bits are still set.  When an event occurs, switch over to
++       * polling to avoid losing status changes.
++       */
++      xhci_dbg(xhci, "%s: starting port polling.\n", __func__);
++      set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+       spin_unlock(&xhci->lock);
+       /* Pass this up to the core */
+       usb_hcd_poll_rh_status(hcd);
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -880,6 +880,11 @@ int xhci_suspend(struct xhci_hcd *xhci)
+       struct usb_hcd          *hcd = xhci_to_hcd(xhci);
+       u32                     command;
++      /* Don't poll the roothubs on bus suspend. */
++      xhci_dbg(xhci, "%s: stopping port polling.\n", __func__);
++      clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
++      del_timer_sync(&hcd->rh_timer);
++
+       spin_lock_irq(&xhci->lock);
+       clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+       clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
+@@ -1064,6 +1069,11 @@ int xhci_resume(struct xhci_hcd *xhci, b
+       if (xhci->quirks & XHCI_COMP_MODE_QUIRK)
+               compliance_mode_recovery_timer_init(xhci);
++      /* Re-enable port polling. */
++      xhci_dbg(xhci, "%s: starting port polling.\n", __func__);
++      set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
++      usb_hcd_poll_rh_status(hcd);
++
+       return retval;
+ }
+ #endif        /* CONFIG_PM */
diff --git a/queue-3.4/xhci-handle-hs-bulk-ctrl-endpoints-that-don-t-nak.patch b/queue-3.4/xhci-handle-hs-bulk-ctrl-endpoints-that-don-t-nak.patch
new file mode 100644 (file)
index 0000000..01e95de
--- /dev/null
@@ -0,0 +1,47 @@
+From 55c1945edaac94c5338a3647bc2e85ff75d9cf36 Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Mon, 17 Dec 2012 14:12:35 -0800
+Subject: xhci: Handle HS bulk/ctrl endpoints that don't NAK.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit 55c1945edaac94c5338a3647bc2e85ff75d9cf36 upstream.
+
+A high speed control or bulk endpoint may have bInterval set to zero,
+which means it does not NAK.  If bInterval is non-zero, it means the
+endpoint NAKs at a rate of 2^(bInterval - 1).
+
+The xHCI code to compute the NAK interval does not handle the special
+case of zero properly.  The current code unconditionally subtracts one
+from bInterval and uses it as an exponent.  This causes a very large
+bInterval to be used, and warning messages like these will be printed:
+
+usb 1-1: ep 0x1 - rounding interval to 32768 microframes, ep desc says 0 microframes
+
+This may cause the xHCI host hardware to reject the Configure Endpoint
+command, which means the HS device will be unusable under xHCI ports.
+
+This patch should be backported to kernels as old as 2.6.31, that contain
+commit dfa49c4ad120a784ef1ff0717168aa79f55a483a "USB: xhci - fix math in
+xhci_get_endpoint_interval()".
+
+Reported-by: Vincent Pelletier <plr.vincent@gmail.com>
+Suggested-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-mem.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -1250,6 +1250,8 @@ static unsigned int xhci_microframes_to_
+ static unsigned int xhci_parse_microframe_interval(struct usb_device *udev,
+               struct usb_host_endpoint *ep)
+ {
++      if (ep->desc.bInterval == 0)
++              return 0;
+       return xhci_microframes_to_exponent(udev, ep,
+                       ep->desc.bInterval, 0, 15);
+ }