Re: Regression: webcam freezing since Linux 6.15
Mathias Nyman <[email protected]> Thu, 30 Jul 2026 17:46:44 +0300
| Newsgroups | org.kernel.vger.linux-usb |
|---|---|
| Message-ID | <[email protected]> |
On 7/30/26 14:08, Michal Pecio wrote:
> On Wed, 29 Jul 2026 12:37:01 -0700, Bart Nagel wrote:
>> I didn't seem to have the "before" blobs your patch indicates in my
>> repo and it didn't want to apply where I was (at the first failing
>> commit) so I went to 6.18.28 and applied your patch there.
>
> Sorry, forgot to say that the patch was made for 6.15, but if it works
> on 6.18 then fine. The alien blob IDs are other (unrelated) patches.
>
>> [ 340.443735] xhci_hcd 0000:00:14.0: Miss service interval error for slot 7 ep 2 ep_trb_dma 10aea6260 td_dma 10aea6270, set skip flag
>> [ 340.443740] xhci_hcd 0000:00:14.0: Event 23 for old TD end DMA 10aea6260 after 7us
>> [ 340.443743] xhci_hcd 0000:00:14.0: BAILING OUT
>> [ 340.443858] xhci_hcd 0000:00:14.0: Miss service interval error for slot 7 ep 2 ep_trb_dma 0 td_dma 10aea6270, set skip flag
>> [ 340.443861] xhci_hcd 0000:00:14.0: Miss service interval error for slot 7 ep 2 ep_trb_dma 0 td_dma 10aea6270, set skip flag
>> [ 340.444110] xhci_hcd 0000:00:14.0: Found td. Clear skip flag for slot 7 ep 2.
>
> As expected, ep_trb_dma points one entry before the first pending TD.
> The driver would throw out all TDs searching for the one which doesn't
> exist anymore, but we prevented it and later recovered normally after
> getting some event (not logged) which pointed to a valid TD.
>
> So the fix works, maybe with exception of one edge case (see below).
> We could potentially use it, or revert the bisected patch (it was only
> an optimization, maybe nobody will notice), or add a quirk for this
> particular chipset to ignore ep_trb_dma in Missed Service Errors.
>
> Long term solution would be improving detection of events pointing to
> completed TDs and/or not skipping when we don't have a sensible TRB
> pointer. But we also need a "trivial" fix for stable kernels like 6.18.
>
How about something like this:
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 4f98d8269625..639f15dec947 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2614,6 +2614,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
unsigned int slot_id;
int ep_index;
struct xhci_td *td = NULL;
+ struct xhci_td *ev_td = NULL;
dma_addr_t ep_trb_dma;
union xhci_trb *ep_trb;
int status = -EINPROGRESS;
@@ -2648,6 +2649,14 @@ static int handle_tx_event(struct xhci_hcd *xhci,
/* find the transfer trb this events points to */
ep_trb = xhci_dma_to_trb(ep_ring->deq_seg, ep_trb_dma, NULL);
+ /* find the td this event points to */
+ list_for_each_entry(td, &ep_ring->td_list, td_list) {
+ if (trb_in_td(td, ep_trb_dma)) {
+ ev_td = td;
+ break;
+ }
+ }
+
/* Look for common error cases */
switch (trb_comp_code) {
/* Skip codes that require special handling depending on
@@ -2795,7 +2804,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
}
/* If the TRB pointer is NULL, missed TDs will be skipped on the next event */
- if (trb_comp_code == COMP_MISSED_SERVICE_ERROR && !ep_trb_dma)
+ if (trb_comp_code == COMP_MISSED_SERVICE_ERROR && !ev_td)
return 0;
if (list_empty(&ep_ring->td_list)) {
Should be trivial enough, handle MSE on link trb, and is in the right
direction for a longterm fix.
knowing ev_td will allow us to simplify the horrible do { } while (ep->skip)
loop later.
Thanks
Mathias