* [Bug 220748] usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set
2025-11-04 21:25 [Bug 220748] New: usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set bugzilla-daemon
@ 2025-11-05 8:40 ` bugzilla-daemon
2025-11-05 8:48 ` bugzilla-daemon
` (15 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: bugzilla-daemon @ 2025-11-05 8:40 UTC (permalink / raw)
To: linux-usb
https://bugzilla.kernel.org/show_bug.cgi?id=220748
Michał Pecio (michal.pecio@gmail.com) changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |michal.pecio@gmail.com
--- Comment #1 from Michał Pecio (michal.pecio@gmail.com) ---
Looks like you are right. I guess it means that synchronizing multiple
soundcards or playback/capture streams isn't working either? (If class drivers
implement that in the first place.)
I wonder if this could be the reason for some weird snd-usb-audio behavior
reported in the past (repeatedly unlinking and retrying URBs for unclear reason
when running full-duplex with very low latency). But it's just a wild guess.
Did you try the obvious?
+ if (!(urb->transfer_flags & URB_ISO_ASAP))
+ goto skip_start_over;
/* Calculate the start frame and put it in urb->start_frame. */
> instead for example in drivers/usb/host/xhci-ring.c, function
> xhci_queue_isoc_tx_prepare() the URB_ISO_ASAP flag is correctly used
Actually, this function looks OK but it isn't called correctly because this
shouldn't be limited to CFC *if* we are scheduling the first TD in a new "data
flow" (xHCI 4.11.2.5). But on modern HW it seems to be correct, and if you skip
the earlier urb->start_frame overwrite, chances are things may work for you.
> This causes issues with devices that require a specific frame interval (like
> professional audio interfaces, for example the Motu AVB line)
Does it mean there is hardware which breaks when polled at the rate specified
in its own endpoint descriptor? Would it still break if you insert zero-length
frames in the "forbidden" periods?
Using start_frame like that seems complicated and it's not feasible on Gen-1
controllers (no CFC). Per Documentation/driver-api/usb/URB drivers may specify
any service interval on per-URB basis, but this of course can't work with xHCI
and results in a warning. However, as suggested in check_interval() comments,
there could be a way of setting different polling interval at endpoint
creation. I see no reason for xHCI HW not to accept that, even Gen-1.
> https://linuxmusicians.com/viewtopic.php?p=179979#p179979
Hmm, using the sideband API to bypass kernel bugs seems even more extreme :)
--
You may reply to this email to add a comment.
You are receiving this mail because:
You are watching the assignee of the bug.
^ permalink raw reply [flat|nested] 18+ messages in thread* [Bug 220748] usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set
2025-11-04 21:25 [Bug 220748] New: usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set bugzilla-daemon
2025-11-05 8:40 ` [Bug 220748] " bugzilla-daemon
@ 2025-11-05 8:48 ` bugzilla-daemon
2025-11-05 8:53 ` bugzilla-daemon
` (14 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: bugzilla-daemon @ 2025-11-05 8:48 UTC (permalink / raw)
To: linux-usb
https://bugzilla.kernel.org/show_bug.cgi?id=220748
--- Comment #2 from Nicola Lunghi (nick83ola@gmail.com) ---
I haven't tried any changes as I'm not familiar with usb devices and wanted
some feedback first
> Did you try the obvious?
> + if (!(urb->transfer_flags & URB_ISO_ASAP))
> + goto skip_start_over;
> /* Calculate the start frame and put it in urb->start_frame. */
I can try this and see if it works yes. my problem is how to see/debug this?
--
You may reply to this email to add a comment.
You are receiving this mail because:
You are watching the assignee of the bug.
^ permalink raw reply [flat|nested] 18+ messages in thread* [Bug 220748] usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set
2025-11-04 21:25 [Bug 220748] New: usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set bugzilla-daemon
2025-11-05 8:40 ` [Bug 220748] " bugzilla-daemon
2025-11-05 8:48 ` bugzilla-daemon
@ 2025-11-05 8:53 ` bugzilla-daemon
2025-11-05 9:06 ` bugzilla-daemon
` (13 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: bugzilla-daemon @ 2025-11-05 8:53 UTC (permalink / raw)
To: linux-usb
https://bugzilla.kernel.org/show_bug.cgi?id=220748
--- Comment #3 from Nicola Lunghi (nick83ola@gmail.com) ---
sorry haven't finished responding. I can try to skip directly to
skip_start_over but the logic in ehci-sched seems more complicated than that
and not being familiar with usb protocol I don't know how for example debug
this. what could be a test setup to see the frames or record the frame that are
sent and the timing? with the ASAP scheduling if a driver try to send the
frames at a specific intervals the xhci driver 'breaks' all the syncronizations
in the way is this implemented.
the issue arised from a Motu AVB interface that expect a precise message rate
and without it it looses the channel synchronization as it expect a specific
rate for the messages.
--
You may reply to this email to add a comment.
You are receiving this mail because:
You are watching the assignee of the bug.
^ permalink raw reply [flat|nested] 18+ messages in thread* [Bug 220748] usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set
2025-11-04 21:25 [Bug 220748] New: usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set bugzilla-daemon
` (2 preceding siblings ...)
2025-11-05 8:53 ` bugzilla-daemon
@ 2025-11-05 9:06 ` bugzilla-daemon
2025-11-05 15:47 ` bugzilla-daemon
` (12 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: bugzilla-daemon @ 2025-11-05 9:06 UTC (permalink / raw)
To: linux-usb
https://bugzilla.kernel.org/show_bug.cgi?id=220748
--- Comment #4 from Michał Pecio (michal.pecio@gmail.com) ---
As for debugging, you can obviously print anything to dmesg with
printk()/pr_info()/xhci_info(). But this may generate quite a noise on isoc
endpoints if you print in every interval.
If you mount debugfs and go to
/sys/kernel/debug/usb/xhci/<controller-pci-address>/devices/<device-slot-id>/
you will find epXX directories and trbs file in each. The file contains a
human-readable dump of the transfer ring written by the driver for given
endpoint, so you can inspect if the TRBs make sense. This only works while the
endpoint is enabled, i.e. if you stop streaming and driver switches to an empty
altsetting zero, the endpoint will disappear from debugfs.
--
You may reply to this email to add a comment.
You are receiving this mail because:
You are watching the assignee of the bug.
^ permalink raw reply [flat|nested] 18+ messages in thread* [Bug 220748] usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set
2025-11-04 21:25 [Bug 220748] New: usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set bugzilla-daemon
` (3 preceding siblings ...)
2025-11-05 9:06 ` bugzilla-daemon
@ 2025-11-05 15:47 ` bugzilla-daemon
2025-11-05 18:28 ` bugzilla-daemon
` (11 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: bugzilla-daemon @ 2025-11-05 15:47 UTC (permalink / raw)
To: linux-usb
https://bugzilla.kernel.org/show_bug.cgi?id=220748
--- Comment #5 from Alan Stern (stern@rowland.harvard.edu) ---
For anyone who wants to know more about how isochronous scheduling is intended
to work in the Linux USB stack, see the description in the kerneldoc for
usb_submit_urb() in drivers/usb/core/urb.c.
In short, the start_frame field in struct urb is output-only. The host
controller driver doesn't pay any attention to it when an URB is submitted, but
the frame assigned to the URB's first isochronous packet gets stored in
start_frame before the URB completes. Furthermore, the URB_ISO_ASAP flag only
affects what happens to an URB that was submitted too late to keep the
endpoint's queue going (say, because interrupts were blocked for too long). If
the queue is just starting up, or the URB isn't already too late, URB_ISO_ASAP
is ignored.
Also, host controller drivers are not likely to pay attention to the interval
field. They will use the interval specified in the endpoint's descriptor.
--
You may reply to this email to add a comment.
You are receiving this mail because:
You are watching the assignee of the bug.
^ permalink raw reply [flat|nested] 18+ messages in thread* [Bug 220748] usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set
2025-11-04 21:25 [Bug 220748] New: usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set bugzilla-daemon
` (4 preceding siblings ...)
2025-11-05 15:47 ` bugzilla-daemon
@ 2025-11-05 18:28 ` bugzilla-daemon
2025-11-05 18:30 ` bugzilla-daemon
` (10 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: bugzilla-daemon @ 2025-11-05 18:28 UTC (permalink / raw)
To: linux-usb
https://bugzilla.kernel.org/show_bug.cgi?id=220748
--- Comment #6 from Nicola Lunghi (nick83ola@gmail.com) ---
(In reply to Alan Stern from comment #5)
> For anyone who wants to know more about how isochronous scheduling is
> intended to work in the Linux USB stack, see the description in the
> kerneldoc for usb_submit_urb() in drivers/usb/core/urb.c.
>
> In short, the start_frame field in struct urb is output-only. The host
> controller driver doesn't pay any attention to it when an URB is submitted,
> but the frame assigned to the URB's first isochronous packet gets stored in
> start_frame before the URB completes. Furthermore, the URB_ISO_ASAP flag
> only affects what happens to an URB that was submitted too late to keep the
> endpoint's queue going (say, because interrupts were blocked for too long).
> If the queue is just starting up, or the URB isn't already too late,
> URB_ISO_ASAP is ignored.
>
> Also, host controller drivers are not likely to pay attention to the
> interval field. They will use the interval specified in the endpoint's
> descriptor.
Sorry Alan I don't understand your considerations. are you saying that this is
not valid? the documentation you pointed out states that
With few exceptions, USB device drivers should never access URB fields
* provided by usbcore or the HCD until its complete() is called.
* The exceptions relate to periodic transfer scheduling. For both
* interrupt and isochronous urbs, as part of successful URB submission
* urb->interval is modified to reflect the actual transfer period used
* (normally some power of two units). And for isochronous urbs,
* urb->start_frame is modified to reflect when the URB's transfers were
* scheduled to start.
I also found this documentation from intel
https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf
pag 219 4.11.2.5 describes the start frame field.
I don't have time today I'll try to play with this during the we.
Can someone tell me if my considerations at the beginning are valid and the
behaviour that we have is missing the start_frame handling, or there's
something I don't see and the driver is actually doing the right thing?
Thanks,
Nicola
--
You may reply to this email to add a comment.
You are receiving this mail because:
You are watching the assignee of the bug.
^ permalink raw reply [flat|nested] 18+ messages in thread* [Bug 220748] usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set
2025-11-04 21:25 [Bug 220748] New: usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set bugzilla-daemon
` (5 preceding siblings ...)
2025-11-05 18:28 ` bugzilla-daemon
@ 2025-11-05 18:30 ` bugzilla-daemon
2025-11-05 20:16 ` bugzilla-daemon
` (9 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: bugzilla-daemon @ 2025-11-05 18:30 UTC (permalink / raw)
To: linux-usb
https://bugzilla.kernel.org/show_bug.cgi?id=220748
--- Comment #7 from Nicola Lunghi (nick83ola@gmail.com) ---
Sorry just rereading Michael comments they are useful! I'll take a look this we
thanks!
--
You may reply to this email to add a comment.
You are receiving this mail because:
You are watching the assignee of the bug.
^ permalink raw reply [flat|nested] 18+ messages in thread* [Bug 220748] usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set
2025-11-04 21:25 [Bug 220748] New: usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set bugzilla-daemon
` (6 preceding siblings ...)
2025-11-05 18:30 ` bugzilla-daemon
@ 2025-11-05 20:16 ` bugzilla-daemon
2025-11-05 21:18 ` bugzilla-daemon
` (8 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: bugzilla-daemon @ 2025-11-05 20:16 UTC (permalink / raw)
To: linux-usb
https://bugzilla.kernel.org/show_bug.cgi?id=220748
--- Comment #8 from Alan Stern (stern@rowland.harvard.edu) ---
Sorry, yes, urb->interval and urb->start_frame do get modified during
submission. Drivers are allowed to read those fields before the URB completes.
The documentation from Intel is irrelevant. It discusses the xHCI hardware,
but we're talking about the Linux software interface.
As for the considerations at the start of this bug report... xhci-hcd is
indeed supposed to ignore urb->start_frame during submission and overwrite it
with the actual starting (micro)frame number. And most of the time, xhci-hcd
is supposed to ignore URB_ISO_ASAP. But it's not supposed to ignore
URB_ISO_ASAP in cases where the URB was submitted too late. By "too late", I
mean that at the time the URB was submitted, the (micro)frame that it should
have been scheduled for -- one period after the last frame of the preceding URB
-- had already elapsed.
--
You may reply to this email to add a comment.
You are receiving this mail because:
You are watching the assignee of the bug.
^ permalink raw reply [flat|nested] 18+ messages in thread* [Bug 220748] usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set
2025-11-04 21:25 [Bug 220748] New: usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set bugzilla-daemon
` (7 preceding siblings ...)
2025-11-05 20:16 ` bugzilla-daemon
@ 2025-11-05 21:18 ` bugzilla-daemon
2025-11-06 3:52 ` bugzilla-daemon
` (7 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: bugzilla-daemon @ 2025-11-05 21:18 UTC (permalink / raw)
To: linux-usb
https://bugzilla.kernel.org/show_bug.cgi?id=220748
--- Comment #9 from Michał Pecio (michal.pecio@gmail.com) ---
Thanks Alan, that's good to know, because Documentation/ is horribly out of
date and the kerneldoc doesn't really say that this field is ignored as input.
(Also, it says that if the whole URB is already expired, it would fail to
submit, but this behavior was apparently later changed to completing with
-EXDEV).
After a bit of digging, I see that urb->start_frame and URB_ISO_ASAP used to
actually work the intuitive way on UHCI in early 2000s, but then EHCI began to
act as if ASAP is always set, xHCI got the same behavior, UHCI was converted to
EHCI behavior, and ASAP got a new and different meaning.
So today it is unrealistic to expect host controller drivers to respect
start_frame, class drivers aren't setting it to anything meaningful, and the
patch I suggested earlier would likely break some class drivers unless a new
flag separate from URB_ISO_ASAP is added to force using the requested
start_frame.
I still wonder if providing means of overriding the polling interval wouldn't
be easier overall (less changes to snd-usb-audio required to support this new
HW).
--
You may reply to this email to add a comment.
You are receiving this mail because:
You are watching the assignee of the bug.
^ permalink raw reply [flat|nested] 18+ messages in thread* [Bug 220748] usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set
2025-11-04 21:25 [Bug 220748] New: usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set bugzilla-daemon
` (8 preceding siblings ...)
2025-11-05 21:18 ` bugzilla-daemon
@ 2025-11-06 3:52 ` bugzilla-daemon
2025-11-06 8:27 ` bugzilla-daemon
` (6 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: bugzilla-daemon @ 2025-11-06 3:52 UTC (permalink / raw)
To: linux-usb
https://bugzilla.kernel.org/show_bug.cgi?id=220748
--- Comment #10 from Alan Stern (stern@rowland.harvard.edu) ---
Figuring out how to handle isochronous transfers has been very difficult; it's
not obvious what scheme would work best. Compounding that difficulty is the
fact that different host controller drivers store their (micro)frame numbers
differently, so drivers will never know exactly what to expect.
You say that uhci-hcd used to work "the intuitive way", but in fact experience
has shown that no way is truly intuitive. Or to put it another differently,
what's intuitive for one person is not intuitive for another.
And don't forget that host controller drivers have to handle isochronous
endpoint queues that can be in three or four different possible states: empty,
partially or completely full, and partially full but totally expired. It's not
at all easy to come up with a set of flags and values that can handle all the
possibilities in ways that drivers will find convenient to use.
The matter of specifying polling intervals different from what the endpoint
descriptor says is yet another can of worms. For example, host controllers
generally can't change polling intervals in mid-stream. And some might reserve
the necessary bandwidth at the time when the alternate setting is installed,
before any URBs have been submitted -- how would one go about changing it from
the default value then?
--
You may reply to this email to add a comment.
You are receiving this mail because:
You are watching the assignee of the bug.
^ permalink raw reply [flat|nested] 18+ messages in thread* [Bug 220748] usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set
2025-11-04 21:25 [Bug 220748] New: usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set bugzilla-daemon
` (9 preceding siblings ...)
2025-11-06 3:52 ` bugzilla-daemon
@ 2025-11-06 8:27 ` bugzilla-daemon
2025-11-06 8:35 ` bugzilla-daemon
` (5 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: bugzilla-daemon @ 2025-11-06 8:27 UTC (permalink / raw)
To: linux-usb
https://bugzilla.kernel.org/show_bug.cgi?id=220748
--- Comment #11 from Michał Pecio (michal.pecio@gmail.com) ---
if (!qh->bandwidth_reserved) {
qh->period = urb->interval;
[...]
} else if (qh->period != urb->interval) {
return -EINVAL; /* Can't change the period */
--
You may reply to this email to add a comment.
You are receiving this mail because:
You are watching the assignee of the bug.
^ permalink raw reply [flat|nested] 18+ messages in thread* [Bug 220748] usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set
2025-11-04 21:25 [Bug 220748] New: usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set bugzilla-daemon
` (10 preceding siblings ...)
2025-11-06 8:27 ` bugzilla-daemon
@ 2025-11-06 8:35 ` bugzilla-daemon
2025-11-06 15:03 ` bugzilla-daemon
` (4 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: bugzilla-daemon @ 2025-11-06 8:35 UTC (permalink / raw)
To: linux-usb
https://bugzilla.kernel.org/show_bug.cgi?id=220748
--- Comment #12 from Michał Pecio (michal.pecio@gmail.com) ---
Oops, sorry for accidental post. This was meant to say that the solution to not
changing polling interval mid-stream already exists in UHCI and isn't very
hard.
As for bandwidth reservation, the problem could be ignored ("you are requesting
something really weird, deal with it"). Or in case of xHCI I think it could
also be solved - changing BW allocation involves similar steps as changing the
interval, so they could be done both (as long as there are no pending URBs).
BTW, purely for testing purposes, I suppose one could hack the kernel to modify
device's descriptor and reduce polling interval. If this helps, then there
would be grounds for wondering about how to implement interval switching more
cleanly.
--
You may reply to this email to add a comment.
You are receiving this mail because:
You are watching the assignee of the bug.
^ permalink raw reply [flat|nested] 18+ messages in thread* [Bug 220748] usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set
2025-11-04 21:25 [Bug 220748] New: usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set bugzilla-daemon
` (11 preceding siblings ...)
2025-11-06 8:35 ` bugzilla-daemon
@ 2025-11-06 15:03 ` bugzilla-daemon
2025-11-08 10:33 ` bugzilla-daemon
` (3 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: bugzilla-daemon @ 2025-11-06 15:03 UTC (permalink / raw)
To: linux-usb
https://bugzilla.kernel.org/show_bug.cgi?id=220748
--- Comment #13 from Alan Stern (stern@rowland.harvard.edu) ---
The solution that's in uhci-hcd is specific to that driver. It won't
necessarily work with other drivers. Or rather, it might work but probably not
in the same way (since qh->bandwidth_reserved will be set and cleared at
different times in different host controller drivers). It wouldn't be
surprising if it doesn't work at all for some drivers (for example, if
bandwidth_reserved gets set when the altsetting is installed, before any URBs
can be submitted). The scheme simply is not usable as a general-purpose
approach.
Ignoring bandwidth reservation is the same as ignoring attempts to change the
polling interval, since reserved bandwidth = maxpacket size / polling interval
(roughly speaking). Besides, the USB spec does not allow USB-2 drivers to
ignore bandwidth reservation, and xHCI hardware enforces bandwidth reservation.
Now, if this turns out to be sufficiently important to enough people, we could
always add a new kernel API specifically meant for changing an endpoint's
interval. Maybe by adding a new ioctl to usbfs -- I don't know. This would
complicate the existing usbfs API for reporting endpoint descriptors: Should
the new interval be stored in the descriptor or should it be reported
separately somehow?
--
You may reply to this email to add a comment.
You are receiving this mail because:
You are watching the assignee of the bug.
^ permalink raw reply [flat|nested] 18+ messages in thread* [Bug 220748] usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set
2025-11-04 21:25 [Bug 220748] New: usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set bugzilla-daemon
` (12 preceding siblings ...)
2025-11-06 15:03 ` bugzilla-daemon
@ 2025-11-08 10:33 ` bugzilla-daemon
2025-11-08 16:09 ` bugzilla-daemon
` (2 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: bugzilla-daemon @ 2025-11-08 10:33 UTC (permalink / raw)
To: linux-usb
https://bugzilla.kernel.org/show_bug.cgi?id=220748
--- Comment #14 from Michał Pecio (michal.pecio@gmail.com) ---
I skimmed the linked forum thread and it seems the issue is not so much with
"needing a specific frame interval", but not tolerating any missing packets.
https://linuxmusicians.com/viewtopic.php?p=177688#p177688
So no-gaps scheduling is already the default *without* URB_ISO_ASAP and drivers
don't need to fill sequential frame IDs themselves if that's what they want.
Note that this stops working when the queue underruns - next URB is assumed to
be a new stream and will be scheduled into the future, not into the past.
If there are gaps despite the driver resubmitting on time, that may be a bug,
but a different one than originally assumed.
If drivers want to insert a gap to resynchronize after detected lost packets,
I'm afraid that's not supported in the current model. It would be technically
possible on CFC xHCI hosts and likely EHCI. A concern is how drivers would know
when frame ID overflows back to zero and how much into the future they can
schedule.
The urb->start_frame field is now output, so drivers can use it to confirm if
the URBs are scheduled sequentially as intended. At least with CFC, it appears
that these numbers should be consistent with reality, though I have never
tested it. Debugfs/tracing/printk may be used to check them against TRBs
written to the HW.
Non-CFC looks weird, maybe it could be improved somewhat but not sure. The old
xHCI 1.0 spec is limited in what it guarantees.
--
You may reply to this email to add a comment.
You are receiving this mail because:
You are watching the assignee of the bug.
^ permalink raw reply [flat|nested] 18+ messages in thread* [Bug 220748] usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set
2025-11-04 21:25 [Bug 220748] New: usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set bugzilla-daemon
` (13 preceding siblings ...)
2025-11-08 10:33 ` bugzilla-daemon
@ 2025-11-08 16:09 ` bugzilla-daemon
2025-11-10 10:23 ` bugzilla-daemon
2025-11-10 10:42 ` bugzilla-daemon
16 siblings, 0 replies; 18+ messages in thread
From: bugzilla-daemon @ 2025-11-08 16:09 UTC (permalink / raw)
To: linux-usb
https://bugzilla.kernel.org/show_bug.cgi?id=220748
--- Comment #15 from Alan Stern (stern@rowland.harvard.edu) ---
When the queue underruns is exactly when URB_ISO_ASAP is supposed to matter.
If the flag is set in the new URB then that URB should be scheduled for the
first slot in the future, leaving a logical gap in the queue. If the flag is
clear then the new URB is supposed to be scheduled for the slot that follows
the preceding URB, which means that some of its packets will never be sent
because their slots have already expired. This will still leave a physical gap
in the queue, of course -- no way to avoid that -- but it will maintain the
logical alignment of URBs and frames.
Thus by submitting all URBs with URB_ISO_ASAP clear, drivers can help ensure
that the queue remains synchronized to within the limits imposed by the host
controller driver. If xhci-hcd doesn't behave this way then it should be
changed.
As for inserting a gap to resynchronize after detected lost packets, it's
simple enough for drivers to submit isochronous URBs with some of the packet
lengths set to 0. Figuring out how many packets should have length 0 will be
tricky, but that can be adjusted after the URBs complete, by checking their
starting frame numbers.
I believe drivers can safely assume that the 8 low-order bits of the frame
number will be valid (11 bits for microframe numbers), and that they are
allowed to submit URBs up to 50 ms in the future. The kerneldoc says 10 - 200
ms, but it's being conservative. When a driver wants to keep latency to a
minimum, it won't go more than 1 or 2 ms into the future, anyway.
--
You may reply to this email to add a comment.
You are receiving this mail because:
You are watching the assignee of the bug.
^ permalink raw reply [flat|nested] 18+ messages in thread* [Bug 220748] usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set
2025-11-04 21:25 [Bug 220748] New: usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set bugzilla-daemon
` (14 preceding siblings ...)
2025-11-08 16:09 ` bugzilla-daemon
@ 2025-11-10 10:23 ` bugzilla-daemon
2025-11-10 10:42 ` bugzilla-daemon
16 siblings, 0 replies; 18+ messages in thread
From: bugzilla-daemon @ 2025-11-10 10:23 UTC (permalink / raw)
To: linux-usb
https://bugzilla.kernel.org/show_bug.cgi?id=220748
--- Comment #16 from Michał Pecio (michal.pecio@gmail.com) ---
(In reply to Alan Stern from comment #15)
> When the queue underruns is exactly when URB_ISO_ASAP is supposed to matter.
> If the flag is set in the new URB then that URB should be scheduled for the
> first slot in the future, leaving a logical gap in the queue. If the flag
> is clear then the new URB is supposed to be scheduled for the slot that
> follows the preceding URB
I meant cases when the queue empties completely and there is no preceding URB.
But I see that there is a subtle difference in EHCI - it still considers a new
submission to be continuation of the earlier stream if earlier URBs have been
given back but their completion callbacks are still running. We can do it too.
But the real bug is xhci_get_isoc_frame_id(). This should convert
urb->start_frame and packet index into frame_id to be passed to HW, but it also
reschedules URBs which it doesn't like (and does some nonsense if the queue
gets too long).
This happens silently under normal conditions and the warnings at the end of
this function are bogus, almost impossible to trigger. So that's why no one
noticed. The only indicator is urb->start_frame discontinuity, but it seems
that class drivers trust HCDs and aren't validating that.
I don't know if that's the cause of those Motu issues, but it's clearly
involved in the other problem with low-latency duplex operation on CFC
controllers which was reported last year and which I can repro on my HW.
The above applies to xHCI 1.1 controllers (typically USB 3.1 and newer). On
older ones urb->start_frame returned to drivers is kinda bogus and everything
goes ASAP. Which actually seems to work better in most cases than the buggy CFC
stuff, but gaps due to late submission remain undetected.
--
You may reply to this email to add a comment.
You are receiving this mail because:
You are watching the assignee of the bug.
^ permalink raw reply [flat|nested] 18+ messages in thread* [Bug 220748] usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set
2025-11-04 21:25 [Bug 220748] New: usb: xhci_queue_isoc_tx_prepare ignore start_frame and always assumes URB_ISO_ASAP is set bugzilla-daemon
` (15 preceding siblings ...)
2025-11-10 10:23 ` bugzilla-daemon
@ 2025-11-10 10:42 ` bugzilla-daemon
16 siblings, 0 replies; 18+ messages in thread
From: bugzilla-daemon @ 2025-11-10 10:42 UTC (permalink / raw)
To: linux-usb
https://bugzilla.kernel.org/show_bug.cgi?id=220748
--- Comment #17 from Michał Pecio (michal.pecio@gmail.com) ---
Created attachment 308930
--> https://bugzilla.kernel.org/attachment.cgi?id=308930&action=edit
schedule isoc packets sequentially on CFC
This is a test patch which knocks out the problematic code and adds some
debugging on CFC controllers - interrupts are enabled on *all* packets, even if
the URB isn't done yet, and for each packet we check if its completion is
handled in the expected microframe. This may show false positives (the packet
moved as intended, but IRQ is handled later) but it would also catch cases when
HW executes (or reports execution) of a packet later than expected.
For example, it warns about every single packet for full speed devices behind
high speed hubs on my ASMedia controllers. Don't do it ;)
It needs a fair bit of testing to see if this approach is feasible and I still
see remaining issues in some tests (which may be due to xhci-hcd or
snd-usb-audio) but it seems to work generally better than unpatched driver.
May or may not help with Motu devices, I don't know what exactly goes wrong
with them. And again, for now, only CFC is expected to be scheduled accurately.
--
You may reply to this email to add a comment.
You are receiving this mail because:
You are watching the assignee of the bug.
^ permalink raw reply [flat|nested] 18+ messages in thread