diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 238ebe158b8317df4e0b0361a39b3ba4b41a0fa1..2c11411ca5f5f2f413dbc5f31582d44a0534bb27 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -98,11 +98,15 @@ void xhci_quiesce(struct xhci_hcd *xhci) */ int xhci_halt(struct xhci_hcd *xhci) { + int ret; xhci_dbg(xhci, "// Halt the HC\n"); xhci_quiesce(xhci); - return handshake(xhci, &xhci->op_regs->status, + ret = handshake(xhci, &xhci->op_regs->status, STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC); + if (!ret) + xhci->xhc_state |= XHCI_STATE_HALTED; + return ret; } /* @@ -129,6 +133,8 @@ int xhci_start(struct xhci_hcd *xhci) xhci_err(xhci, "Host took too long to start, " "waited %u microseconds.\n", XHCI_MAX_HALT_USEC); + if (!ret) + xhci->xhc_state &= ~XHCI_STATE_HALTED; return ret; } @@ -1212,7 +1218,7 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) if (ret || !urb->hcpriv) goto done; temp = xhci_readl(xhci, &xhci->op_regs->status); - if (temp == 0xffffffff) { + if (temp == 0xffffffff || (xhci->xhc_state & XHCI_STATE_HALTED)) { xhci_dbg(xhci, "HW died, freeing TD.\n"); urb_priv = urb->hcpriv; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index e9217bb288ad44affc859d1f9e1ad599a9d31c64..e69f1cdf4b5bb8b05b8f8942a443afc3dbfa1f01 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1260,6 +1260,7 @@ struct xhci_hcd { * There are no reports of xHCI host controllers that display this issue. */ #define XHCI_STATE_DYING (1 << 0) +#define XHCI_STATE_HALTED (1 << 1) /* Statistics */ int error_bitmask; unsigned int quirks;