Commit c181bc5b authored by Elric Fu's avatar Elric Fu Committed by Sarah Sharp

xHCI: add cmd_ring_state

Adding cmd_ring_state for command ring. It helps to verify
the current command ring state for controlling the command
ring operations.

This patch should be backported to kernels as old as 3.0.  The commit
7ed603ec "xhci: Add an assertion to
check for virt_dev=0 bug." papers over the NULL pointer dereference that
I now believe is related to a timed out Set Address command.  This (and
the four patches that follow it) contain the real fix that also allows
VIA USB 3.0 hubs to consistently re-enumerate during the plug/unplug
stress tests.
Signed-off-by: default avatarElric Fu <elricfu1@gmail.com>
Signed-off-by: default avatarSarah Sharp <sarah.a.sharp@linux.intel.com>
Tested-by: default avatarMiroslav Sabljic <miroslav.sabljic@avl.com>
Cc: stable@vger.kernel.org
parent c2d57aec
...@@ -280,6 +280,9 @@ static inline int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring, ...@@ -280,6 +280,9 @@ static inline int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring,
/* Ring the host controller doorbell after placing a command on the ring */ /* Ring the host controller doorbell after placing a command on the ring */
void xhci_ring_cmd_db(struct xhci_hcd *xhci) void xhci_ring_cmd_db(struct xhci_hcd *xhci)
{ {
if (!(xhci->cmd_ring_state & CMD_RING_STATE_RUNNING))
return;
xhci_dbg(xhci, "// Ding dong!\n"); xhci_dbg(xhci, "// Ding dong!\n");
xhci_writel(xhci, DB_VALUE_HOST, &xhci->dba->doorbell[0]); xhci_writel(xhci, DB_VALUE_HOST, &xhci->dba->doorbell[0]);
/* Flush PCI posted writes */ /* Flush PCI posted writes */
......
...@@ -104,9 +104,10 @@ int xhci_halt(struct xhci_hcd *xhci) ...@@ -104,9 +104,10 @@ int xhci_halt(struct xhci_hcd *xhci)
ret = handshake(xhci, &xhci->op_regs->status, ret = handshake(xhci, &xhci->op_regs->status,
STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC); STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC);
if (!ret) if (!ret) {
xhci->xhc_state |= XHCI_STATE_HALTED; xhci->xhc_state |= XHCI_STATE_HALTED;
else xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
} else
xhci_warn(xhci, "Host not halted after %u microseconds.\n", xhci_warn(xhci, "Host not halted after %u microseconds.\n",
XHCI_MAX_HALT_USEC); XHCI_MAX_HALT_USEC);
return ret; return ret;
...@@ -485,6 +486,7 @@ static int xhci_run_finished(struct xhci_hcd *xhci) ...@@ -485,6 +486,7 @@ static int xhci_run_finished(struct xhci_hcd *xhci)
return -ENODEV; return -ENODEV;
} }
xhci->shared_hcd->state = HC_STATE_RUNNING; xhci->shared_hcd->state = HC_STATE_RUNNING;
xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
if (xhci->quirks & XHCI_NEC_HOST) if (xhci->quirks & XHCI_NEC_HOST)
xhci_ring_cmd_db(xhci); xhci_ring_cmd_db(xhci);
......
...@@ -1421,6 +1421,10 @@ struct xhci_hcd { ...@@ -1421,6 +1421,10 @@ struct xhci_hcd {
/* data structures */ /* data structures */
struct xhci_device_context_array *dcbaa; struct xhci_device_context_array *dcbaa;
struct xhci_ring *cmd_ring; struct xhci_ring *cmd_ring;
unsigned int cmd_ring_state;
#define CMD_RING_STATE_RUNNING (1 << 0)
#define CMD_RING_STATE_ABORTED (1 << 1)
#define CMD_RING_STATE_STOPPED (1 << 2)
unsigned int cmd_ring_reserved_trbs; unsigned int cmd_ring_reserved_trbs;
struct xhci_ring *event_ring; struct xhci_ring *event_ring;
struct xhci_erst erst; struct xhci_erst erst;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment