aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias Nyman2021-01-29 15:00:43 +0200
committerGreg Kroah-Hartman2021-01-29 14:16:52 +0100
commit51ee4a84300200c51303ef15b84981b2edb6ec47 (patch)
treef195d5f4b2d4738e8118215b46823d1a01e28d1e
parent741eafb3457ca3c5159e01809a3fd7c754079d25 (diff)
xhci: Check for pending reset endpoint command before queueing a new one.
A halted endpoint can be detected both when transfer events complete, and in stop endpoint command completion. Both these handlers will start clearing up the halted endpoint and queue a reset endpoint command. It's possible to get both events for the same halted endpoint if right after a URB cancel queues a stop endpoint command the endpoint stalls. Use the EP_HALTED flag to prevent resetting the endpoint twice. Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Link: https://lore.kernel.org/r/20210129130044.206855-27-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/host/xhci-ring.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 1440041acae2..26f5557ed7c6 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -873,8 +873,6 @@ static void xhci_handle_halted_endpoint(struct xhci_hcd *xhci,
if (ep->vdev->flags & VDEV_PORT_ERROR)
return;
- ep->ep_state |= EP_HALTED;
-
/* add td to cancelled list and let reset ep handler take care of it */
if (reset_type == EP_HARD_RESET) {
ep->ep_state |= EP_HARD_CLEAR_TOGGLE;
@@ -884,10 +882,17 @@ static void xhci_handle_halted_endpoint(struct xhci_hcd *xhci,
}
}
+ if (ep->ep_state & EP_HALTED) {
+ xhci_dbg(xhci, "Reset ep command already pending\n");
+ return;
+ }
+
err = xhci_reset_halted_ep(xhci, slot_id, ep->ep_index, reset_type);
if (err)
return;
+ ep->ep_state |= EP_HALTED;
+
xhci_ring_cmd_db(xhci);
}
@@ -2575,7 +2580,6 @@ static int handle_tx_event(struct xhci_hcd *xhci,
case COMP_STALL_ERROR:
xhci_dbg(xhci, "Stalled endpoint for slot %u ep %u\n", slot_id,
ep_index);
- ep->ep_state |= EP_HALTED;
status = -EPIPE;
break;
case COMP_SPLIT_TRANSACTION_ERROR: