xhci: Add helper to find trb from its dma address

Add a xhci_dma_to_trb() helper, and use it to find the transfer TRB
early in handle_tx_event() based on the dma address found in the
event TRB.

With this helper we can avoid using 'ep_seg' transfer TRB segment
variable as both a a boolean to indicate if the transfer TRB is part
of the next queued TD, and to actually find the transfer TRB based
on ep_seg and ep_trb_dma.

This is a first step in reworking and cleaning up trb_in_td() and
handle_tx_event()

Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://patch.msgid.link/20251119142417.2820519-3-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Mathias Nyman 2025-11-19 16:23:56 +02:00 committed by Greg Kroah-Hartman
parent 8d34983720
commit fad902d670

View File

@ -82,6 +82,23 @@ dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg,
return seg->dma + (segment_offset * sizeof(*trb));
}
static union xhci_trb *xhci_dma_to_trb(struct xhci_segment *start_seg,
dma_addr_t dma,
struct xhci_segment **match_seg)
{
struct xhci_segment *seg;
xhci_for_each_ring_seg(start_seg, seg) {
if (in_range(dma, seg->dma, TRB_SEGMENT_SIZE)) {
if (match_seg)
*match_seg = seg;
return &seg->trbs[(dma - seg->dma) / sizeof(union xhci_trb)];
}
}
return NULL;
}
static bool trb_is_noop(union xhci_trb *trb)
{
return TRB_TYPE_NOOP_LE32(trb->generic.field[3]);
@ -2658,7 +2675,6 @@ static int handle_tx_event(struct xhci_hcd *xhci,
int ep_index;
struct xhci_td *td = NULL;
dma_addr_t ep_trb_dma;
struct xhci_segment *ep_seg;
union xhci_trb *ep_trb;
int status = -EINPROGRESS;
struct xhci_ep_ctx *ep_ctx;
@ -2689,6 +2705,9 @@ static int handle_tx_event(struct xhci_hcd *xhci,
if (!ep_ring)
return handle_transferless_tx_event(xhci, ep, trb_comp_code);
/* find the transfer trb this events points to */
ep_trb = xhci_dma_to_trb(ep_ring->deq_seg, ep_trb_dma, NULL);
/* Look for common error cases */
switch (trb_comp_code) {
/* Skip codes that require special handling depending on
@ -2862,10 +2881,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
td = list_first_entry(&ep_ring->td_list, struct xhci_td,
td_list);
/* Is this a TRB in the currently executing TD? */
ep_seg = trb_in_td(td, ep_trb_dma);
if (!ep_seg) {
/* Is this TRB not part of the currently executing TD? */
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 */
@ -2948,7 +2965,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);
/*