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>
This commit is contained in:
Jack Pham 2015-12-09 15:52:43 -08:00 committed by David Keitel
parent 3d2c84e2f1
commit 3a490dd6eb

View file

@ -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);