diff options
author | Mathias Nyman | 2021-01-29 15:00:43 +0200 |
---|---|---|
committer | Greg Kroah-Hartman | 2021-01-29 14:16:52 +0100 |
commit | 51ee4a84300200c51303ef15b84981b2edb6ec47 (patch) | |
tree | f195d5f4b2d4738e8118215b46823d1a01e28d1e | |
parent | 741eafb3457ca3c5159e01809a3fd7c754079d25 (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.c | 10 |
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: |