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
--- /dev/null
+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)
--- /dev/null
+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,
--- /dev/null
+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;
--- /dev/null
+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 */
--- /dev/null
+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);
+ }