]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/usb/host/xhci.c
USB: xhci: Wait for host to start running.
[net-next-2.6.git] / drivers / usb / host / xhci.c
index 79ccfe5f8ad010d8159fe1011bb4055aa1c9e51f..8a49c6716b69e26c81ac7d86909eaac171d1a67e 100644 (file)
@@ -105,6 +105,33 @@ int xhci_halt(struct xhci_hcd *xhci)
                        STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC);
 }
 
+/*
+ * Set the run bit and wait for the host to be running.
+ */
+int xhci_start(struct xhci_hcd *xhci)
+{
+       u32 temp;
+       int ret;
+
+       temp = xhci_readl(xhci, &xhci->op_regs->command);
+       temp |= (CMD_RUN);
+       xhci_dbg(xhci, "// Turn on HC, cmd = 0x%x.\n",
+                       temp);
+       xhci_writel(xhci, temp, &xhci->op_regs->command);
+
+       /*
+        * Wait for the HCHalted Status bit to be 0 to indicate the host is
+        * running.
+        */
+       ret = handshake(xhci, &xhci->op_regs->status,
+                       STS_HALT, 0, XHCI_MAX_HALT_USEC);
+       if (ret == -ETIMEDOUT)
+               xhci_err(xhci, "Host took too long to start, "
+                               "waited %u microseconds.\n",
+                               XHCI_MAX_HALT_USEC);
+       return ret;
+}
+
 /*
  * Reset a halted HC, and set the internal HC state to HC_STATE_HALT.
  *
@@ -460,13 +487,11 @@ int xhci_run(struct usb_hcd *hcd)
        if (NUM_TEST_NOOPS > 0)
                doorbell = xhci_setup_one_noop(xhci);
 
-       temp = xhci_readl(xhci, &xhci->op_regs->command);
-       temp |= (CMD_RUN);
-       xhci_dbg(xhci, "// Turn on HC, cmd = 0x%x.\n",
-                       temp);
-       xhci_writel(xhci, temp, &xhci->op_regs->command);
-       /* Flush PCI posted writes */
-       temp = xhci_readl(xhci, &xhci->op_regs->command);
+       if (xhci_start(xhci)) {
+               xhci_halt(xhci);
+               return -ENODEV;
+       }
+
        xhci_dbg(xhci, "// @%p = 0x%x\n", &xhci->op_regs->command, temp);
        if (doorbell)
                (*doorbell)(xhci);