aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci.c
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2011-03-11 13:20:58 -0500
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2011-03-13 21:23:48 -0400
commitc6cc27c782e3a64cced0fcf1d6f492c8d8881c76 (patch)
treeb671f8101eb7513343f8bb02a7e00712798aa0ed /drivers/usb/host/xhci.c
parentb320937972d456db2a46fdcbc6bebc4dcdc9daa4 (diff)
xhci: Return canceled URBs immediately when host is halted.
When the xHCI host controller is halted, it won't respond to commands placed on the command ring. So if an URB is cancelled after the first roothub is deallocated, it will try to place a stop endpoint command on the command ring, which will fail. The command watchdog timer will fire after five seconds, and the host controller will be marked as dying, and all URBs will be completed. Add a flag to the xHCI's internal state variable for when the host controller is halted. Immediately return the canceled URB if the host controller is halted. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Diffstat (limited to 'drivers/usb/host/xhci.c')
-rw-r--r--drivers/usb/host/xhci.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 238ebe158b83..2c11411ca5f5 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -98,11 +98,15 @@ void xhci_quiesce(struct xhci_hcd *xhci)
98 */ 98 */
99int xhci_halt(struct xhci_hcd *xhci) 99int xhci_halt(struct xhci_hcd *xhci)
100{ 100{
101 int ret;
101 xhci_dbg(xhci, "// Halt the HC\n"); 102 xhci_dbg(xhci, "// Halt the HC\n");
102 xhci_quiesce(xhci); 103 xhci_quiesce(xhci);
103 104
104 return handshake(xhci, &xhci->op_regs->status, 105 ret = handshake(xhci, &xhci->op_regs->status,
105 STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC); 106 STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC);
107 if (!ret)
108 xhci->xhc_state |= XHCI_STATE_HALTED;
109 return ret;
106} 110}
107 111
108/* 112/*
@@ -129,6 +133,8 @@ int xhci_start(struct xhci_hcd *xhci)
129 xhci_err(xhci, "Host took too long to start, " 133 xhci_err(xhci, "Host took too long to start, "
130 "waited %u microseconds.\n", 134 "waited %u microseconds.\n",
131 XHCI_MAX_HALT_USEC); 135 XHCI_MAX_HALT_USEC);
136 if (!ret)
137 xhci->xhc_state &= ~XHCI_STATE_HALTED;
132 return ret; 138 return ret;
133} 139}
134 140
@@ -1212,7 +1218,7 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
1212 if (ret || !urb->hcpriv) 1218 if (ret || !urb->hcpriv)
1213 goto done; 1219 goto done;
1214 temp = xhci_readl(xhci, &xhci->op_regs->status); 1220 temp = xhci_readl(xhci, &xhci->op_regs->status);
1215 if (temp == 0xffffffff) { 1221 if (temp == 0xffffffff || (xhci->xhc_state & XHCI_STATE_HALTED)) {
1216 xhci_dbg(xhci, "HW died, freeing TD.\n"); 1222 xhci_dbg(xhci, "HW died, freeing TD.\n");
1217 urb_priv = urb->hcpriv; 1223 urb_priv = urb->hcpriv;
1218 1224