aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorElric Fu <elricfu1@gmail.com>2012-06-27 04:30:57 -0400
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2012-09-13 18:46:41 -0400
commitc181bc5b5d5c79b71203cd10cef97f802fb6f9c1 (patch)
treef6378b3d7c7cbef225674a56dcb94d0063b6ffd2
parentc2d57aec81f3d479642523fd4d3537006168c240 (diff)
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 7ed603ecf8b68ab81f4c83097d3063d43ec73bb8 "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: Elric Fu <elricfu1@gmail.com> Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Tested-by: Miroslav Sabljic <miroslav.sabljic@avl.com> Cc: stable@vger.kernel.org
-rw-r--r--drivers/usb/host/xhci-ring.c3
-rw-r--r--drivers/usb/host/xhci.c6
-rw-r--r--drivers/usb/host/xhci.h4
3 files changed, 11 insertions, 2 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 643c2f3f3e73..75c857ec55b9 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -280,6 +280,9 @@ static inline int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring,
280/* Ring the host controller doorbell after placing a command on the ring */ 280/* Ring the host controller doorbell after placing a command on the ring */
281void xhci_ring_cmd_db(struct xhci_hcd *xhci) 281void xhci_ring_cmd_db(struct xhci_hcd *xhci)
282{ 282{
283 if (!(xhci->cmd_ring_state & CMD_RING_STATE_RUNNING))
284 return;
285
283 xhci_dbg(xhci, "// Ding dong!\n"); 286 xhci_dbg(xhci, "// Ding dong!\n");
284 xhci_writel(xhci, DB_VALUE_HOST, &xhci->dba->doorbell[0]); 287 xhci_writel(xhci, DB_VALUE_HOST, &xhci->dba->doorbell[0]);
285 /* Flush PCI posted writes */ 288 /* Flush PCI posted writes */
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index c59d5b5b6c7d..f425356e71f2 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -104,9 +104,10 @@ int xhci_halt(struct xhci_hcd *xhci)
104 104
105 ret = handshake(xhci, &xhci->op_regs->status, 105 ret = handshake(xhci, &xhci->op_regs->status,
106 STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC); 106 STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC);
107 if (!ret) 107 if (!ret) {
108 xhci->xhc_state |= XHCI_STATE_HALTED; 108 xhci->xhc_state |= XHCI_STATE_HALTED;
109 else 109 xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
110 } else
110 xhci_warn(xhci, "Host not halted after %u microseconds.\n", 111 xhci_warn(xhci, "Host not halted after %u microseconds.\n",
111 XHCI_MAX_HALT_USEC); 112 XHCI_MAX_HALT_USEC);
112 return ret; 113 return ret;
@@ -485,6 +486,7 @@ static int xhci_run_finished(struct xhci_hcd *xhci)
485 return -ENODEV; 486 return -ENODEV;
486 } 487 }
487 xhci->shared_hcd->state = HC_STATE_RUNNING; 488 xhci->shared_hcd->state = HC_STATE_RUNNING;
489 xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
488 490
489 if (xhci->quirks & XHCI_NEC_HOST) 491 if (xhci->quirks & XHCI_NEC_HOST)
490 xhci_ring_cmd_db(xhci); 492 xhci_ring_cmd_db(xhci);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index c713256297ac..33f24e9fa766 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1421,6 +1421,10 @@ struct xhci_hcd {
1421 /* data structures */ 1421 /* data structures */
1422 struct xhci_device_context_array *dcbaa; 1422 struct xhci_device_context_array *dcbaa;
1423 struct xhci_ring *cmd_ring; 1423 struct xhci_ring *cmd_ring;
1424 unsigned int cmd_ring_state;
1425#define CMD_RING_STATE_RUNNING (1 << 0)
1426#define CMD_RING_STATE_ABORTED (1 << 1)
1427#define CMD_RING_STATE_STOPPED (1 << 2)
1424 unsigned int cmd_ring_reserved_trbs; 1428 unsigned int cmd_ring_reserved_trbs;
1425 struct xhci_ring *event_ring; 1429 struct xhci_ring *event_ring;
1426 struct xhci_erst erst; 1430 struct xhci_erst erst;