From: Michal Pecio <michal.pecio@gmail.com>
To: Mathias Nyman <mathias.nyman@intel.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 2/5] usb: xhci: Find transfer TRB early in handle_tx_event()
Date: Wed, 19 Nov 2025 12:03:47 +0100 [thread overview]
Message-ID: <20251119120347.70a02fde.michal.pecio@gmail.com> (raw)
In-Reply-To: <20251119120208.6a025eb0.michal.pecio@gmail.com>
As soon as we find the transfer ring to which an event belongs, we can
proceed to locate the exact TRB referenced by the event. This enables
better event handling and diagnostics, even if no TD matches the event.
Also set 'ep_seg' and remove its secondary use as a temporary boolean.
Bail out if event TRB pointer is not NULL and not a transfer TRB on the
endpoint's ring. This indicates that either the HC executes TRBs from a
wrong ring (bad Set TR Dequeue command, Link TRB damaged or ignored by
the HC) or its internal state is corrupted and the event is bogus.
No such event is going to match any TD on td_list and trying to handle
it would generally do nothing. On an isochronous endpoint we might skip
all pending TDs and create more chaos. Just log this error and get out.
Suggested-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: Michal Pecio <michal.pecio@gmail.com>
---
drivers/usb/host/xhci-ring.c | 35 +++++++++++++++++++++++++++++++----
1 file changed, 31 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 3d5124912a09..531e2f207b17 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -82,6 +82,27 @@ dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg,
return seg->dma + (segment_offset * sizeof(*trb));
}
+/*
+ * Look up a TRB by its DMA address, return NULL if not found on the ring.
+ * Search from start_seg to let callers optimize starting point selection.
+ * Write actual segment containing returned TRB to seg_out, if provided.
+ */
+static union xhci_trb *xhci_dma_to_trb(struct xhci_segment *start_seg, dma_addr_t dma,
+ struct xhci_segment **seg_out)
+{
+ struct xhci_segment *seg;
+
+ xhci_for_each_ring_seg(start_seg, seg) {
+ if (in_range(dma, seg->dma, TRB_SEGMENT_SIZE)) {
+ if (seg_out)
+ *seg_out = seg;
+ return seg->trbs + (dma - seg->dma) / sizeof(seg->trbs[0]);
+ }
+ }
+
+ return NULL;
+}
+
static bool trb_is_noop(union xhci_trb *trb)
{
return TRB_TYPE_NOOP_LE32(trb->generic.field[3]);
@@ -2672,6 +2693,15 @@ static int handle_tx_event(struct xhci_hcd *xhci,
if (!ep_ring)
return handle_transferless_tx_event(xhci, ep, trb_comp_code);
+ /* get the corresponding transfer TRB pointer */
+ ep_trb = xhci_dma_to_trb(ep_ring->deq_seg, ep_trb_dma, &ep_seg);
+ if (!ep_trb && ep_trb_dma) {
+ xhci_warn(xhci, "Ignoring '%s' event out of ring on slot %d ep %d\n",
+ xhci_trb_comp_code_string(trb_comp_code), slot_id, ep_index);
+ /* XXX: other ring's TDs may be executing on this EP, should we kill it? */
+ return 0;
+ }
+
/* Look for common error cases */
switch (trb_comp_code) {
/* Skip codes that require special handling depending on
@@ -2846,9 +2876,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
td_list);
/* Is this a TRB in the currently executing TD? */
- ep_seg = trb_in_td(td, ep_trb_dma);
-
- if (!ep_seg) {
+ if (!trb_in_td(td, ep_trb_dma)) {
if (ep->skip && usb_endpoint_xfer_isoc(&td->urb->ep->desc)) {
/* this event is unlikely to match any TD, don't skip them all */
@@ -2931,7 +2959,6 @@ static int handle_tx_event(struct xhci_hcd *xhci,
if (ring_xrun_event)
return 0;
- ep_trb = &ep_seg->trbs[(ep_trb_dma - ep_seg->dma) / sizeof(*ep_trb)];
trace_xhci_handle_transfer(ep_ring, (struct xhci_generic_trb *) ep_trb, ep_trb_dma);
/*
--
2.48.1
next prev parent reply other threads:[~2025-11-19 11:03 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-19 11:02 [PATCH 0/5] xHCI: Decouple updating Dequeue from giveback Michal Pecio
2025-11-19 11:02 ` [PATCH 1/5] usb: xhci: Track transfer ring dequeue progress properly Michal Pecio
2025-11-19 11:03 ` Michal Pecio [this message]
2025-11-19 11:04 ` [PATCH 3/5] usb: xhci: Refactor and generalize trb_in_td() Michal Pecio
2025-11-19 11:05 ` [PATCH 4/5] usb: xhci: Reduce error mid TD latency with a new "done TD" mechanism Michal Pecio
2025-11-19 11:06 ` [PATCH 5/5] usb: xhci: Handle short transfers as "done TDs" Michal Pecio
2025-11-19 12:35 ` [PATCH 0/5] xHCI: Decouple updating Dequeue from giveback Mathias Nyman
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=20251119120347.70a02fde.michal.pecio@gmail.com \
--to=michal.pecio@gmail.com \
--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.