Re: [RFT PATCH] xhci: Handle spurious events on Etron host isoc enpoints

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

Kuangyi Chiang <ki.chiang65@xxxxxxxxx> 於 2025年3月1日 週六 上午10:05寫道:
>
> Hi,
>
> Thanks for the patch.
>
> Mathias Nyman <mathias.nyman@xxxxxxxxxxxxxxx> 於 2025年3月1日 週六 上午12:17寫道:
> >
> > Unplugging a USB3.0 webcam from Etron hosts while streaming results
> > in errors like this:
> >
> > [ 2.646387] xhci_hcd 0000:03:00.0: ERROR Transfer event TRB DMA ptr not part of current TD ep_index 18 comp_code 13
> > [ 2.646446] xhci_hcd 0000:03:00.0: Looking for event-dma 000000002fdf8630 trb-start 000000002fdf8640 trb-end 000000002fdf8650
> > [ 2.646560] xhci_hcd 0000:03:00.0: ERROR Transfer event TRB DMA ptr not part of current TD ep_index 18 comp_code 13
> > [ 2.646568] xhci_hcd 0000:03:00.0: Looking for event-dma 000000002fdf8660 trb-start 000000002fdf8670 trb-end 000000002fdf8670
> >
> > Etron xHC generates two transfer events for the TRB if an error is
> > detected while processing the last TRB of an isoc TD.
> >
> > The first event can be any sort of error (like USB Transaction or
> > Babble Detected, etc), and the final event is Success.
> >
> > The xHCI driver will handle the TD after the first event and remove it
> > from its internal list, and then print an "Transfer event TRB DMA ptr
> > not part of current TD" error message after the final event.
> >
> > Commit 5372c65e1311 ("xhci: process isoc TD properly when there was a
> > transaction error mid TD.") is designed to address isoc transaction
> > errors, but unfortunately it doesn't account for this scenario.
> >
> > This issue is similar to the XHCI_SPURIOUS_SUCCESS case where a success
> > event follows a 'short transfer' event, but the TD the event points to
> > is already given back.
> >
> > Expand the spurious success 'short transfer' event handling to cover
> > the spurious success after error on Etron hosts.
> >
> > Kuangyi Chiang reported this issue and submitted a different solution
> > based on using error_mid_td. This commit message is mostly taken
> > from that patch.
> >
> > Reported-by: Kuangyi Chiang <ki.chiang65@xxxxxxxxx>
> > Signed-off-by: Mathias Nyman <mathias.nyman@xxxxxxxxxxxxxxx>
> > ---
> >  drivers/usb/host/xhci-ring.c | 36 +++++++++++++++++++++++++-----------
> >  drivers/usb/host/xhci.h      |  2 +-
> >  2 files changed, 26 insertions(+), 12 deletions(-)
> >
> > diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
> > index 965bffce301e..3d3e6cd69019 100644
> > --- a/drivers/usb/host/xhci-ring.c
> > +++ b/drivers/usb/host/xhci-ring.c
> > @@ -2644,6 +2644,22 @@ static int handle_transferless_tx_event(struct xhci_hcd *xhci, struct xhci_virt_
> >         return 0;
> >  }
> >
> > +static bool xhci_spurious_success_tx_event(struct xhci_hcd *xhci,
> > +                                          struct xhci_ring *ring)
> > +{
> > +       switch (ring->old_trb_comp_code) {
> > +       case COMP_SHORT_PACKET:
> > +               return xhci->quirks & XHCI_SPURIOUS_SUCCESS;
> > +       case COMP_USB_TRANSACTION_ERROR:
> > +       case COMP_BABBLE_DETECTED_ERROR:
> > +       case COMP_ISOCH_BUFFER_OVERRUN:
> > +               return xhci->quirks & XHCI_ETRON_HOST &&
> > +                       ring->type == TYPE_ISOC;
> > +       default:
> > +               return false;
> > +       }
> > +}
> > +
> >  /*
> >   * If this function returns an error condition, it means it got a Transfer
> >   * event with a corrupted Slot ID, Endpoint ID, or TRB DMA address.
> > @@ -2697,8 +2713,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
> >         case COMP_SUCCESS:
> >                 if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
> >                         trb_comp_code = COMP_SHORT_PACKET;
> > -                       xhci_dbg(xhci, "Successful completion on short TX for slot %u ep %u with last td short %d\n",
> > -                                slot_id, ep_index, ep_ring->last_td_was_short);
> > +                       xhci_dbg(xhci, "Successful completion on short TX for slot %u ep %u with last td comp code %d\n",
> > +                                slot_id, ep_index, ep_ring->old_trb_comp_code);
> >                 }
> >                 break;
> >         case COMP_SHORT_PACKET:
> > @@ -2846,7 +2862,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
> >                  */
> >                 if (trb_comp_code != COMP_STOPPED &&
> >                     trb_comp_code != COMP_STOPPED_LENGTH_INVALID &&
> > -                   !ep_ring->last_td_was_short) {
> > +                   !xhci_spurious_success_tx_event(xhci, ep_ring)) {
> >                         xhci_warn(xhci, "Event TRB for slot %u ep %u with no TDs queued\n",
> >                                   slot_id, ep_index);
> >                 }
> > @@ -2890,11 +2906,12 @@ static int handle_tx_event(struct xhci_hcd *xhci,
> >
> >                         /*
> >                          * Some hosts give a spurious success event after a short
> > -                        * transfer. Ignore it.
> > +                        * transfer or error on last TRB. Ignore it.
> >                          */
> > -                       if ((xhci->quirks & XHCI_SPURIOUS_SUCCESS) &&
> > -                           ep_ring->last_td_was_short) {
> > -                               ep_ring->last_td_was_short = false;
> > +                       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 = trb_comp_code;
> >                                 return 0;
> >                         }
> >
> > @@ -2922,10 +2939,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
> >          */
> >         } while (ep->skip);
> >
> > -       if (trb_comp_code == COMP_SHORT_PACKET)
> > -               ep_ring->last_td_was_short = true;
> > -       else
> > -               ep_ring->last_td_was_short = false;
> > +       ep_ring->old_trb_comp_code = trb_comp_code;
> >
> >         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);
> > diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
> > index 8c164340a2c3..c75c2c12ce53 100644
> > --- a/drivers/usb/host/xhci.h
> > +++ b/drivers/usb/host/xhci.h
> > @@ -1371,7 +1371,7 @@ struct xhci_ring {
> >         unsigned int            num_trbs_free; /* used only by xhci DbC */
> >         unsigned int            bounce_buf_len;
> >         enum xhci_ring_type     type;
> > -       bool                    last_td_was_short;
> > +       u32                     last_td_comp_code;
>
> Should be changed to old_trb_comp_code.
>
> >         struct radix_tree_root  *trb_address_map;
> >  };
> >
> > --
> > 2.43.0
> >
>
> I'll test this later.

It works. See the below dynamic debug messages:

[ 1138.281772] xhci_hcd 0000:04:00.0: Successful completion on short
TX for slot 1 ep 18 with last td comp code 13
[ 1138.281777] xhci_hcd 0000:04:00.0: Spurious event dma
0x000000010b5ba600, comp_code 13 after 13
[ 1138.282013] xhci_hcd 0000:04:00.0: Successful completion on short
TX for slot 1 ep 18 with last td comp code 13
[ 1138.282019] xhci_hcd 0000:04:00.0: Spurious event dma
0x000000010b5ba630, comp_code 13 after 13
[ 1138.282271] xhci_hcd 0000:04:00.0: Successful completion on short
TX for slot 1 ep 18 with last td comp code 13
[ 1138.282277] xhci_hcd 0000:04:00.0: Spurious event dma
0x000000010b5ba660, comp_code 13 after 13
[ 1138.282420] xhci_hcd 0000:04:00.0: Successful completion on short
TX for slot 1 ep 18 with last td comp code 13
[ 1138.282425] xhci_hcd 0000:04:00.0: Spurious event dma
0x000000010b5ba680, comp_code 13 after 13
[ 1138.282653] xhci_hcd 0000:04:00.0: Transfer error for slot 1 ep 18
on endpoint
[ 1138.282659] xhci_hcd 0000:04:00.0: Error mid isoc TD, wait for
final completion event
[ 1138.282779] xhci_hcd 0000:04:00.0: Successful completion on short
TX for slot 1 ep 18 with last td comp code 4
[ 1138.282785] xhci_hcd 0000:04:00.0: Transfer error for slot 1 ep 18
on endpoint
[ 1138.282911] xhci_hcd 0000:04:00.0: Successful completion on short
TX for slot 1 ep 18 with last td comp code 4
[ 1138.282916] xhci_hcd 0000:04:00.0: Spurious event dma
0x000000010b5ba6c0, comp_code 13 after 4
[ 1138.282920] xhci_hcd 0000:04:00.0: Transfer error for slot 1 ep 18
on endpoint
[ 1138.282923] xhci_hcd 0000:04:00.0: Error mid isoc TD, wait for
final completion event
[ 1138.283039] xhci_hcd 0000:04:00.0: Successful completion on short
TX for slot 1 ep 18 with last td comp code 4
[ 1138.283045] xhci_hcd 0000:04:00.0: Transfer error for slot 1 ep 18
on endpoint
[ 1138.283163] xhci_hcd 0000:04:00.0: Successful completion on short
TX for slot 1 ep 18 with last td comp code 4
[ 1138.283167] xhci_hcd 0000:04:00.0: Spurious event dma
0x000000010b5ba6f0, comp_code 13 after 4

>
> Thanks,
> Kuangyi Chiang

Thanks,
Kuangyi Chiang





[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux