Skip to content

Commit 0c74d23

Browse files
matnymangregkh
authored andcommitted
xhci: Avoid queuing redundant Stop Endpoint command for stalled endpoint
If EP_STALLED flag is set in xhci_urb_dequeue(), without EP_HALTED or SET_DEQ_PENDING flags, then the endpoint is in stopped state and the cancelled URB can be given back immediately withouth queueing a 'stop endpoint' command. Without this change the cancelled URB would eventually be given back in the 'context state error' completion path of the 'stop endpoint' command. This is not optimal. For this improvement to work the EP_STALLED flag must be cleared with xhci lock held. Suggested-by: Michal Pecio <michal.pecio@gmail.com> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Link: https://lore.kernel.org/r/20250311154551.4035726-2-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 525b139 commit 0c74d23

File tree

1 file changed

+5
-3
lines changed

1 file changed

+5
-3
lines changed

drivers/usb/host/xhci.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1773,8 +1773,8 @@ static int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
17731773
goto done;
17741774
}
17751775

1776-
/* In this case no commands are pending but the endpoint is stopped */
1777-
if (ep->ep_state & EP_CLEARING_TT) {
1776+
/* In these cases no commands are pending but the endpoint is stopped */
1777+
if (ep->ep_state & (EP_CLEARING_TT | EP_STALLED)) {
17781778
/* and cancelled TDs can be given back right away */
17791779
xhci_dbg(xhci, "Invalidating TDs instantly on slot %d ep %d in state 0x%x\n",
17801780
urb->dev->slot_id, ep_index, ep->ep_state);
@@ -3211,10 +3211,12 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd,
32113211
return;
32123212

32133213
ep = &vdev->eps[ep_index];
3214+
3215+
spin_lock_irqsave(&xhci->lock, flags);
3216+
32143217
ep->ep_state &= ~EP_STALLED;
32153218

32163219
/* Bail out if toggle is already being cleared by a endpoint reset */
3217-
spin_lock_irqsave(&xhci->lock, flags);
32183220
if (ep->ep_state & EP_HARD_CLEAR_TOGGLE) {
32193221
ep->ep_state &= ~EP_HARD_CLEAR_TOGGLE;
32203222
spin_unlock_irqrestore(&xhci->lock, flags);

0 commit comments

Comments
 (0)