aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci.c
diff options
context:
space:
mode:
authorAndiry Xu <andiry.xu@amd.com>2012-04-14 02:54:30 +0800
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2012-05-03 13:10:17 -0700
commitf370b9968a220a3d79d870dd7dee674cc0ff3d10 (patch)
tree65353e2712388752b40769ca6e53bdb7147a0d20 /drivers/usb/host/xhci.c
parentusb: cp210x: Corrected USB request type definitions (diff)
downloadlinux-dev-f370b9968a220a3d79d870dd7dee674cc0ff3d10.tar.xz
linux-dev-f370b9968a220a3d79d870dd7dee674cc0ff3d10.zip
xHCI: keep track of ports being resumed and indicate in hub_status_data
This commit adds a bit-array to xhci bus_state for keeping track of which ports are undergoing a resume transition. If any of the bits are set when xhci_hub_status_data() is called, the routine will return a non-zero value even if no ports have any status changes pending. This will allow usbcore to handle races between root-hub suspend and port wakeup. This patch should be backported to kernels as old as 3.4, that contain the commit 879d38e6bc36d73b0ac40ec9b0d839fda9fa8b1a "USB: fix race between root-hub suspend and remote wakeup". Signed-off-by: Andiry Xu <andiry.xu@amd.com> Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Cc: Alan Stern <stern@rowland.harvard.edu> Cc: stable@vger.kernel.org
Diffstat (limited to 'drivers/usb/host/xhci.c')
-rw-r--r--drivers/usb/host/xhci.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 36641a7f2371..5910048b0a2e 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -152,7 +152,7 @@ int xhci_reset(struct xhci_hcd *xhci)
{
u32 command;
u32 state;
- int ret;
+ int ret, i;
state = xhci_readl(xhci, &xhci->op_regs->status);
if ((state & STS_HALT) == 0) {
@@ -175,7 +175,15 @@ int xhci_reset(struct xhci_hcd *xhci)
* xHCI cannot write to any doorbells or operational registers other
* than status until the "Controller Not Ready" flag is cleared.
*/
- return handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000);
+ ret = handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000);
+
+ for (i = 0; i < 2; ++i) {
+ xhci->bus_state[i].port_c_suspend = 0;
+ xhci->bus_state[i].suspended_ports = 0;
+ xhci->bus_state[i].resuming_ports = 0;
+ }
+
+ return ret;
}
#ifdef CONFIG_PCI