Re: [PATCH] usb: xhci: Fix isochronous scheduling regression

From: Alan Stern

Date: Wed Aug 26 2026 - 11:25:15 EST


On Wed, Aug 26, 2026 at 11:34:15AM +0300, Mathias Nyman wrote:
> On 8/24/26 18:51, Alan Stern wrote:
> > On Mon, Aug 24, 2026 at 06:21:22PM +0300, Mathias Nyman wrote:
> > > On 8/22/26 05:38, Alan Stern wrote:
> > > > On Fri, Aug 21, 2026 at 06:03:50PM +0200, Michal Pecio wrote:
> > > > > On Fri, 21 Aug 2026 10:44:07 -0400, Alan Stern wrote:
> >
> > > > Possible alternative: Make the URB_ISO_ASAP flag take precedence over
> > > > the "queue is non-empty" condition.
> > >
> > > xhci driver does this. If URB_ISO_ASAP is set then xhci driver always sets
> > > the SIA "Start Isoch ASAP" flag for the transfer blocks.
> >
> > I wasn't very precise before. I meant URB_ISO_ASAP should take
> > precedence when there are no active URBs but there may still be some
> > URBs being given back. In other words, when the list_empty test
> > succeeds. If the list of queued URBs is not empty then new URBs should
> > always be assigned to the next available slot -- unless we decide to
> > support a new URB_USE_FRAME flag and the flag is set.
> >
>
> URB_ISO_ASAP always takes precedence in xHC case.
>
> xHC controller has a "SIA" flag that we set for each TD (URB frame)
> in the URB when USR_ISO_ASAP is set.
> If there are no active URBs mid stream, and ring underruns, then xHC will process
> the next TD with SIA flag at its earliest possible slot.
> So URBs with URB_ISO_ASAP flag will be out of sync and laggy, but not lose data
> in underrun cases.

Well, that's kind of the point.

The USB spec explicitly allows -- and expects! -- isochronous transfers
to lose data from time to time. That's why these transfers don't use
ACK/NAK handshakes and don't do retransmissions.

Given this attitude, it seems very likely that the USBIF would recommend
losing data rather than losing synchronization. I don't know what the
attitude is of the various drivers in the kernel, but it wouldn't be
surprising if they also take this point of view. (Consider trying to
keep an audio stream in sync with a video stream, for example.)

> A frame is only dropped in SIA case if xHC fails for internal reasons to
> process that transfer in time. This triggers a Missed Service Error, and xHC
> moves to process the next TD (frame).

But as you said, the hardware will try to transfer the packet even if it
chooses to use a time slot later than the one the class driver wanted.
This is the wrong approach; the packet should be dropped, and the later
time slot should contain the packet that the class driver intended.

Perhaps you will say this merely shows that these class drivers
shouldn't set URB_ISO_ASAP. Or to put it another way, URB_ISO_ASAP
indicates that the driver prefers losing synchronization over losing
data.

> Class driver can then detect lagging out of sync URB_ISO_ASAP transfers based on
> the unexpected large gaps between urb->start_frame numbers

The class driver should realize that URB_ISO_ASAP generally _will_ incur
lag and loss of synchronization occasionally. It should set that flag
only when it doesn't mind these things. In which case it probably
doesn't need to check the gaps between start_frame numbers.

The real problem we are trying to solve here is what should happen when
a class driver starts falling behind, submitting URBs too late. If it
gets _very_ far behind, there's really no choice but to restart the
stream, losing synchronization. But if the driver is only a little
behind (and has a chance of catching up again), there is a choice
between losing synchronization and losing data. URB_ISO_ASAP allows the
driver to tell us how it wants that choice to be made.

Furthermore, as long as the class driver is doing the best it can -- by
resubmitting from within its completion handler -- we should try to
support it by putting in the "only a little behind" category.

Alan Stern