From: Michal Pecio <michal.pecio@gmail.com>
To: Mathias Nyman <mathias.nyman@intel.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Bart Nagel <bart@tremby.net>,
linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 4/5] usb: xhci: Shorten the TD skipping loop
Date: Tue, 4 Aug 2026 12:04:36 +0200 [thread overview]
Message-ID: <20260804120436.0832eea2.michal.pecio@gmail.com> (raw)
In-Reply-To: <20260804120110.01bda0e2.michal.pecio@gmail.com>
Half of this loop is code which only executes once to deal with cases
where no TD matches the event and then it returns. This code needs not
to be in any kind of loop, so get it out.
Optimize conditionals remaining in the loop body.
Signed-off-by: Michal Pecio <michal.pecio@gmail.com>
---
drivers/usb/host/xhci-ring.c | 69 +++++++++++++++++-------------------
1 file changed, 33 insertions(+), 36 deletions(-)
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 8270c63ec3bf..1f0cb6a701c5 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2843,10 +2843,9 @@ static int handle_tx_event(struct xhci_hcd *xhci,
td = list_first_entry(&ep_ring->td_list, struct xhci_td,
td_list);
- /* Is this TRB not part of the currently executing TD? */
- if (!trb_in_td(td, ep_trb_dma)) {
+ if (ep->skip) {
- if (ep->skip) {
+ if (!trb_in_td(td, ep_trb_dma)) {
/* this event is unlikely to match any TD, don't skip them all */
if (trb_comp_code == COMP_STOPPED_LENGTH_INVALID)
return 0;
@@ -2884,38 +2883,6 @@ static int handle_tx_event(struct xhci_hcd *xhci,
goto check_endpoint_halted;
}
- /* TD was queued after xrun, maybe xrun was on a link, don't panic yet */
- if (ring_xrun_event)
- return 0;
-
- /*
- * Skip the Force Stopped Event. The 'ep_trb' of FSE is not in the current
- * TD pointed by 'ep_ring->dequeue' because that the hardware dequeue
- * pointer still at the previous TRB of the current TD. The previous TRB
- * maybe a Link TD or the last TRB of the previous TD. The command
- * completion handle will take care the rest.
- */
- if (trb_comp_code == COMP_STOPPED ||
- trb_comp_code == COMP_STOPPED_LENGTH_INVALID) {
- return 0;
- }
-
- /*
- * Some hosts give a spurious success event after a short
- * transfer or error on last TRB. Ignore it.
- */
- if (xhci_spurious_success_tx_event(xhci, ep_ring)) {
- xhci_dbg(xhci, "Spurious event dma %pad, comp_code %u after %u\n",
- &ep_trb_dma, trb_comp_code, ep_ring->old_trb_comp_code);
- ep_ring->old_trb_comp_code = 0;
- return 0;
- }
-
- /* HC is busted, give up! */
- goto debug_finding_td;
- }
-
- if (ep->skip) {
xhci_dbg(xhci,
"Found td. Clear skip flag for slot %u ep %u.\n",
slot_id, ep_index);
@@ -2932,10 +2899,40 @@ static int handle_tx_event(struct xhci_hcd *xhci,
ep_ring->old_trb_comp_code = trb_comp_code;
- /* Get out if a TD was queued at enqueue after the xrun occurred */
+ /*
+ * Underrun handling ends here. Any TD pointed by the event was enqueued after the event
+ * occurred, so wait for its completion now. And it's not a bug if no such TD exists.
+ */
if (ring_xrun_event)
return 0;
+ /* Handle events not referencing the current TD */
+ if (!trb_in_td(td, ep_trb_dma)) {
+ /*
+ * Skip the Force Stopped Event. The 'ep_trb' of FSE is not in the current
+ * TD pointed by 'ep_ring->dequeue' because that the hardware dequeue
+ * pointer still at the previous TRB of the current TD. The previous TRB
+ * maybe a Link TD or the last TRB of the previous TD. The command
+ * completion handle will take care the rest.
+ */
+ if (trb_comp_code == COMP_STOPPED || trb_comp_code == COMP_STOPPED_LENGTH_INVALID)
+ return 0;
+
+ /*
+ * Some hosts give a spurious success event after a short
+ * transfer or error on last TRB. Ignore it.
+ */
+ if (xhci_spurious_success_tx_event(xhci, ep_ring)) {
+ xhci_dbg(xhci, "Spurious event dma %pad, comp_code %u after %u\n",
+ &ep_trb_dma, trb_comp_code, ep_ring->old_trb_comp_code);
+ ep_ring->old_trb_comp_code = 0;
+ return 0;
+ }
+
+ /* HC is busted, give up! */
+ goto debug_finding_td;
+ }
+
trace_xhci_handle_transfer(ep_ring, (struct xhci_generic_trb *) ep_trb, ep_trb_dma);
/*
--
2.48.1
next prev parent reply other threads:[~2026-08-04 10:04 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-04 10:01 [PATCH 0/5] xhci: Sort out the TD skipping business Michal Pecio
2026-08-04 10:02 ` [PATCH 1/5] usb: xhci: Handle bogus TRB pointers in Missed Service Error events Michal Pecio
2026-08-05 17:13 ` Mathias Nyman
2026-08-04 10:03 ` [PATCH 2/5] usb: xhci: Guarantee URB giveback on Ring Underrun/Overrun Michal Pecio
2026-08-04 10:03 ` [PATCH 3/5] usb: xhci: Don't set the skip flag on non-isoc endpoints Michal Pecio
2026-08-04 10:04 ` Michal Pecio [this message]
2026-08-05 17:14 ` [PATCH 4/5] usb: xhci: Shorten the TD skipping loop Mathias Nyman
2026-08-04 10:05 ` [PATCH 5/5] usb: xhci: Rework and improve the TD matching and skipping logic Michal Pecio
2026-08-05 17:39 ` Mathias Nyman
2026-08-05 19:30 ` Michal Pecio
2026-08-06 11:00 ` Michal Pecio
2026-08-06 22:16 ` Mathias Nyman
2026-08-05 19:06 ` [PATCH 0/5] xhci: Sort out the TD skipping business Bart Nagel
2026-08-05 20:21 ` Michal Pecio
2026-08-06 18:28 ` Bart Nagel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260804120436.0832eea2.michal.pecio@gmail.com \
--to=michal.pecio@gmail.com \
--cc=bart@tremby.net \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=mathias.nyman@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.