diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/host/xhci.c | 10 | ||||
-rw-r--r-- | drivers/usb/host/xhci.h | 1 |
2 files changed, 9 insertions, 2 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 238ebe1..2c11411 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 e9217bb..e69f1cd 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; |