Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

usb: xhci: Expedite skipping missed isoch TDs on modern HCs

xHCI spec rev. 1.0 allowed the TRB pointer of Missed Service events
to be NULL. Having no idea which of the queued TDs were missed and
which are waiting, we can only set a flag to skip missed TDs later.

But HCs are also allowed to give us pointer to the last missed TRB,
and this became mandatory in spec rev. 1.1 and later.

Use this pointer, if available, to immediately skip all missed TDs.
This reduces latency and risk of skipping-related bugs, because we
can now leave the skip flag cleared for future events.

Handle Missed Service Error events as 'error mid TD', if applicable,
because rev. 1.0 spec excplicitly says so in notes to 4.10.3.2 and
later revs in 4.10.3.2 and 4.11.2.5.2. Notes to 4.9.1 seem to apply.

Tested on ASM1142 and ASM3142 v1.1 xHCs which provide TRB pointers.
Tested on AMD, Etron, Renesas v1.0 xHCs which provide TRB pointers.
Tested on NEC v0.96 and VIA v1.0 xHCs which send a NULL pointer.

Change inspired by a discussion about realtime USB audio.

Link: https://lore.kernel.org/linux-usb/76e1a191-020d-4a76-97f6-237f9bd0ede0@gmx.net/T/
Signed-off-by: Michal Pecio <michal.pecio@gmail.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20250306144954.3507700-7-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Michal Pecio and committed by
Greg Kroah-Hartman
d0b61959 906dec15

+10 -4
+10 -4
drivers/usb/host/xhci-ring.c
··· 2439 2439 if (ep_trb != td->end_trb) 2440 2440 td->error_mid_td = true; 2441 2441 break; 2442 + case COMP_MISSED_SERVICE_ERROR: 2443 + frame->status = -EXDEV; 2444 + sum_trbs_for_length = true; 2445 + if (ep_trb != td->end_trb) 2446 + td->error_mid_td = true; 2447 + break; 2442 2448 case COMP_INCOMPATIBLE_DEVICE_ERROR: 2443 2449 case COMP_STALL_ERROR: 2444 2450 frame->status = -EPROTO; ··· 2755 2749 */ 2756 2750 ep->skip = true; 2757 2751 xhci_dbg(xhci, 2758 - "Miss service interval error for slot %u ep %u, set skip flag\n", 2759 - slot_id, ep_index); 2752 + "Miss service interval error for slot %u ep %u, set skip flag%s\n", 2753 + slot_id, ep_index, ep_trb_dma ? ", skip now" : ""); 2760 2754 break; 2761 2755 case COMP_NO_PING_RESPONSE_ERROR: 2762 2756 ep->skip = true; ··· 2805 2799 xhci_dequeue_td(xhci, td, ep_ring, td->status); 2806 2800 } 2807 2801 2808 - /* Missed TDs will be skipped on the next event */ 2809 - if (trb_comp_code == COMP_MISSED_SERVICE_ERROR) 2802 + /* If the TRB pointer is NULL, missed TDs will be skipped on the next event */ 2803 + if (trb_comp_code == COMP_MISSED_SERVICE_ERROR && !ep_trb_dma) 2810 2804 return 0; 2811 2805 2812 2806 if (list_empty(&ep_ring->td_list)) {