aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/host/xhci.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 40e0a0c221b8..79ccfe5f8ad0 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -116,6 +116,7 @@ int xhci_reset(struct xhci_hcd *xhci)
{
u32 command;
u32 state;
+ int ret;
state = xhci_readl(xhci, &xhci->op_regs->status);
if ((state & STS_HALT) == 0) {
@@ -130,7 +131,17 @@ int xhci_reset(struct xhci_hcd *xhci)
/* XXX: Why does EHCI set this here? Shouldn't other code do this? */
xhci_to_hcd(xhci)->state = HC_STATE_HALT;
- return handshake(xhci, &xhci->op_regs->command, CMD_RESET, 0, 250 * 1000);
+ ret = handshake(xhci, &xhci->op_regs->command,
+ CMD_RESET, 0, 250 * 1000);
+ if (ret)
+ return ret;
+
+ xhci_dbg(xhci, "Wait for controller to be ready for doorbell rings\n");
+ /*
+ * 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);
}