mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 10:04:04 +02:00
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:
parent
8d34983720
commit
fad902d670
|
|
@ -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);
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user