提交 ed07453f 编写于 作者: S Sarah Sharp 提交者: Greg Kroah-Hartman

USB: xhci: Wait for host to start running.

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: NSarah Sharp <sarah.a.sharp@linux.intel.com>
Reported-by: NShinya Saito <shinya.saito.sx@renesas.com>
Cc: stable <stable@kernel.org>
Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
上级 2d62f3ee
...@@ -105,6 +105,33 @@ int xhci_halt(struct xhci_hcd *xhci) ...@@ -105,6 +105,33 @@ int xhci_halt(struct xhci_hcd *xhci)
STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC); 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. * 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) ...@@ -460,13 +487,11 @@ int xhci_run(struct usb_hcd *hcd)
if (NUM_TEST_NOOPS > 0) if (NUM_TEST_NOOPS > 0)
doorbell = xhci_setup_one_noop(xhci); doorbell = xhci_setup_one_noop(xhci);
temp = xhci_readl(xhci, &xhci->op_regs->command); if (xhci_start(xhci)) {
temp |= (CMD_RUN); xhci_halt(xhci);
xhci_dbg(xhci, "// Turn on HC, cmd = 0x%x.\n", return -ENODEV;
temp); }
xhci_writel(xhci, temp, &xhci->op_regs->command);
/* Flush PCI posted writes */
temp = xhci_readl(xhci, &xhci->op_regs->command);
xhci_dbg(xhci, "// @%p = 0x%x\n", &xhci->op_regs->command, temp); xhci_dbg(xhci, "// @%p = 0x%x\n", &xhci->op_regs->command, temp);
if (doorbell) if (doorbell)
(*doorbell)(xhci); (*doorbell)(xhci);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册