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