Skip to content

Commit d6169d0

Browse files
matnymangregkh
authored andcommitted
xhci: fix deadlock at host remove by running watchdog correctly
If a URB is killed while the host is removed we can end up in a situation where the hub thread takes the roothub device lock, and waits for the URB to be given back by xhci-hcd, blocking the host remove code. xhci-hcd tries to stop the endpoint and give back the urb, but can't as the host is removed from PCI bus at the same time, preventing the normal way of giving back urb. Instead we need to rely on the stop command timeout function to give back the urb. This xhci_stop_endpoint_command_watchdog() timeout function used a XHCI_STATE_DYING flag to indicate if the timeout function is already running, but later this flag has been taking into use in other places to mark that xhci is dying. Remove checks for XHCI_STATE_DYING in xhci_urb_dequeue. We are still checking that reading from pci state does not return 0xffffffff or that host is not halted before trying to stop the endpoint. This whole area of stopping endpoints, giving back URBs, and the wathdog timeout need rework, this fix focuses on solving a specific deadlock issue that we can then send to stable before any major rework. Cc: <[email protected]> Signed-off-by: Mathias Nyman <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 7b6c1b4 commit d6169d0

File tree

2 files changed

+0
-24
lines changed

2 files changed

+0
-24
lines changed

drivers/usb/host/xhci-ring.c

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -913,17 +913,6 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)
913913
spin_lock_irqsave(&xhci->lock, flags);
914914

915915
ep->stop_cmds_pending--;
916-
if (xhci->xhc_state & XHCI_STATE_REMOVING) {
917-
spin_unlock_irqrestore(&xhci->lock, flags);
918-
return;
919-
}
920-
if (xhci->xhc_state & XHCI_STATE_DYING) {
921-
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
922-
"Stop EP timer ran, but another timer marked "
923-
"xHCI as DYING, exiting.");
924-
spin_unlock_irqrestore(&xhci->lock, flags);
925-
return;
926-
}
927916
if (!(ep->stop_cmds_pending == 0 && (ep->ep_state & EP_HALT_PENDING))) {
928917
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
929918
"Stop EP timer ran, but no command pending, "

drivers/usb/host/xhci.c

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1534,19 +1534,6 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
15341534
xhci_urb_free_priv(urb_priv);
15351535
return ret;
15361536
}
1537-
if ((xhci->xhc_state & XHCI_STATE_DYING) ||
1538-
(xhci->xhc_state & XHCI_STATE_HALTED)) {
1539-
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
1540-
"Ep 0x%x: URB %p to be canceled on "
1541-
"non-responsive xHCI host.",
1542-
urb->ep->desc.bEndpointAddress, urb);
1543-
/* Let the stop endpoint command watchdog timer (which set this
1544-
* state) finish cleaning up the endpoint TD lists. We must
1545-
* have caught it in the middle of dropping a lock and giving
1546-
* back an URB.
1547-
*/
1548-
goto done;
1549-
}
15501537

15511538
ep_index = xhci_get_endpoint_index(&urb->ep->desc);
15521539
ep = &xhci->devs[urb->dev->slot_id]->eps[ep_index];

0 commit comments

Comments
 (0)