Skip to content

Commit

Permalink
USB: xhci: Wait for host to start running.
Browse files Browse the repository at this point in the history
When the run bit is set in the xHCI command register, it may take a few
microseconds for the host to start running.  We cannot ring any doorbells
until the host is actually running, so wait until the status register says
the host is running.

Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Reported-by: Shinya Saito <shinya.saito.sx@renesas.com>
Cc: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Sarah Sharp authored and Greg Kroah-Hartman committed Jun 4, 2010
1 parent 2d62f3e commit ed07453
Showing 1 changed file with 32 additions and 7 deletions.
39 changes: 32 additions & 7 deletions drivers/usb/host/xhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit ed07453

Please sign in to comment.