summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorJack Pham <jackp@codeaurora.org>2015-12-09 15:52:43 -0800
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 21:22:04 -0700
commit3a490dd6ebf9e5ac5d8b457be2ce58794249416c (patch)
treeed89991a2ec4e2d5a4a059958745a6606be52e44 /drivers/usb
parent3d2c84e2f1c0694ac6e50f7a901caf365edf1681 (diff)
usb: xhci: clean up command queue when halting
Calling usb_remove_hcd() on both of the xHCI HCDs may race with hub_event() which executes on its own workqueue. When xhci_halt() is called and stops the command ring, the hub thread may have already issued a command such as xhci_configure_endpoint() and is currently waiting for the command to complete while holding the device lock. Meanwhile since the controller is already halted, no events are expected to complete and the command timer will continually timeout every 5 seconds and re-arm itself. Since the completion for the command is never issued, the threads are essentially deadlocked. Avoid this situation when halting the controller by forcing the command queue to be cleaned up. Change-Id: I88150e3435b5f06e37e9881dddaeff4807c24cc9 Signed-off-by: Jack Pham <jackp@codeaurora.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/xhci.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index b9577ebbb2b1..e57340a86eb3 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -117,6 +117,13 @@ int xhci_halt(struct xhci_hcd *xhci)
if (!ret) {
xhci->xhc_state |= XHCI_STATE_HALTED;
xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
+
+ if (timer_pending(&xhci->cmd_timer)) {
+ xhci_dbg_trace(xhci, trace_xhci_dbg_init,
+ "Cleanup command queue");
+ del_timer(&xhci->cmd_timer);
+ xhci_cleanup_command_queue(xhci);
+ }
} else
xhci_warn(xhci, "Host not halted after %u microseconds.\n",
XHCI_MAX_HALT_USEC);