Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+9 -2
+8 -2
drivers/usb/host/xhci.c
··· 98 98 */ 99 99 int xhci_halt(struct xhci_hcd *xhci) 100 100 { 101 + int ret; 101 102 xhci_dbg(xhci, "// Halt the HC\n"); 102 103 xhci_quiesce(xhci); 103 104 104 - return handshake(xhci, &xhci->op_regs->status, 105 + ret = handshake(xhci, &xhci->op_regs->status, 105 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 /* ··· 133 129 xhci_err(xhci, "Host took too long to start, " 134 130 "waited %u microseconds.\n", 135 131 XHCI_MAX_HALT_USEC); 132 + if (!ret) 133 + xhci->xhc_state &= ~XHCI_STATE_HALTED; 136 134 return ret; 137 135 } 138 136 ··· 1218 1212 if (ret || !urb->hcpriv) 1219 1213 goto done; 1220 1214 temp = xhci_readl(xhci, &xhci->op_regs->status); 1221 - if (temp == 0xffffffff) { 1215 + if (temp == 0xffffffff || (xhci->xhc_state & XHCI_STATE_HALTED)) { 1222 1216 xhci_dbg(xhci, "HW died, freeing TD.\n"); 1223 1217 urb_priv = urb->hcpriv; 1224 1218
+1
drivers/usb/host/xhci.h
··· 1260 1260 * There are no reports of xHCI host controllers that display this issue. 1261 1261 */ 1262 1262 #define XHCI_STATE_DYING (1 << 0) 1263 + #define XHCI_STATE_HALTED (1 << 1) 1263 1264 /* Statistics */ 1264 1265 int error_bitmask; 1265 1266 unsigned int quirks;