From: Michal Pecio <michal.pecio@gmail.com>
To: Nicola Lunghi <nick83ola@gmail.com>
Cc: mathias.nyman@intel.com, niklas.neronin@linux.intel.com,
gregkh@linuxfoundation.org, linux-usb@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH 1/2] usb: xhci: fix isoc silent reschedule creating stream gap on CFC controllers
Date: Fri, 8 May 2026 18:56:17 +0200 [thread overview]
Message-ID: <20260508185617.6bf8a6eb.michal.pecio@gmail.com> (raw)
In-Reply-To: <20260504233143.10242-3-nick83ola@gmail.com>
On Tue, 5 May 2026 01:31:43 +0200, Nicola Lunghi wrote:
> xhci_get_isoc_frame_id() silently rescheduled the first TRB to
> start_frame_id+1 when the requested start frame was out of the valid
> scheduling window or landed exactly on its boundary. This creates an
> explicit one-frame hole in the isochronous stream.
>
> Most USB audio devices tolerate a brief gap with a small glitch and
> recover automatically. However, some devices assume that once
> isochronous packets start streaming they flow continuously until the
> stream is explicitly stopped. Any gap causes the device firmware to
> permanently lose channel synchronization — subsequent packets are
> routed to the wrong output channels until the device is reset.
That's not the only problem, we are basically violating documented
usb_submit_urb() behavior, as Alan points out in Bugzilla.
> This was observed with the MOTU 1248 (USB ID 0x07fd:0x0005), where
> after a gap the 24-channel output stream shifts by a fixed number of
> channels, mapping audio intended for ch1/ch2 onto ch7/ch8 or other
> channel pairs depending on timing.
>
> Return -EINVAL instead so the caller falls back to TRB_SIA (Schedule
> Immediately After)
That's not what this acronym really means.
> which lets the hardware place the TRB right after the previous one
> without introducing a frame-aligned gap.
IIRC, the meaning of "Start Isoch ASAP" is like Linux URB_ISO_ASAP:
"as soon as possible *and not earlier* than possible".
To guarantee no gaps, we should use SIA=0 and incremental Frame IDs
on chips with CFC (without CFC it's a lost cause).
The reason using SIA=1 helped you is because in reality:
- the start_frame_id calculated here is pessimistic
- I found that the IST reported by HCs is usually pessimistic too
Therefore, even if this function believes that it's too late to execute
some transfer (and currently tries to reschedule it for later), the HC
may actually still execute it immediately without gaps if SIA=1.
But the right thing to do is SIA=0 and correctly specified Frame ID.
Setting SIA=1 opens the possibility of rescheduling for later (in HW)
when it *really* is too late. And we don't want that, we want late
submissions to result in Missed Service Error and EXDEV completion.
Note that the comment in this function is bogus too. In reality:
Software *shall* not schedule past end_frame_id.
Software *should* not schedule before start_frame_id.
The former is a requirement, the latter a recommendation. And a valid
one, if we want the URB to execute. But here, we want it to fail :)
Also, I'm not sure if ignoring submissions far into the future and
turning them into SIA=1 is the right action. If a driver submits an
untinterrupted stream (without URB_ISO_ASAP) going 895ms into the
future, we should probably stop this madness and error out (TBD).
> Link: https://bugzilla.kernel.org/show_bug.cgi?id=220748
> Assisted-by: Claude:claude-sonnet-4-6 sparse checkpatch
> Signed-off-by: Nicola Lunghi <nick83ola@gmail.com>
> ---
> drivers/usb/host/xhci-ring.c | 20 +++++++++++++-------
> 1 file changed, 13 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/usb/host/xhci-ring.c
> b/drivers/usb/host/xhci-ring.c index e47e644b296e..03e47db82092 100644
> --- a/drivers/usb/host/xhci-ring.c
> +++ b/drivers/usb/host/xhci-ring.c
> @@ -4030,15 +4030,21 @@ static int xhci_get_isoc_frame_id(struct
> xhci_hcd *xhci, ret = -EINVAL;
> }
>
> + /*
> + * If the first TRB's start frame is out of the scheduling window or
> + * lands exactly on its boundary, fall back to SIA (Schedule Immediately
> + * After) rather than forcing start_frame_id+1. A forced +1 creates an
> + * explicit one-frame hole that audio devices with strict continuity
> + * requirements cannot recover from. The caller handles -EINVAL by
> + * leaving sia_frame_id as TRB_SIA.
> + */
> if (index == 0) {
> if (ret == -EINVAL || start_frame == start_frame_id)
> {
> - start_frame = start_frame_id + 1;
> - if (urb->dev->speed == USB_SPEED_LOW ||
> - urb->dev->speed == USB_SPEED_FULL)
> - urb->start_frame = start_frame;
> - else
> - urb->start_frame = start_frame << 3;
> - ret = 0;
> + xhci_dbg(xhci, "isoc: start frame %d %s window [%d, %d], using SIA\n",
> + start_frame,
> + ret == -EINVAL ? "behind" : "at boundary of",
> + start_frame_id, end_frame_id);
I'm not very fond of debug prints which can show every microframe.
Even better than a "debuggable" code is one which is right, well tested
and known to work without worries.
> + return -EINVAL;
> }
> }
>
> --
> 2.51.0
>
next prev parent reply other threads:[~2026-05-08 16:56 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-04 23:31 [PATCH 0/2] xhci: Fix isochronous scheduling gaps on CFC controllers Nicola Lunghi
2026-05-04 23:31 ` [PATCH 1/2] usb: xhci: fix isoc silent reschedule creating stream gap " Nicola Lunghi
2026-05-05 13:32 ` Mathias Nyman
2026-05-08 16:56 ` Michal Pecio [this message]
2026-05-04 23:31 ` [PATCH 2/2] usb: xhci: fix CFC sequential scheduling lost on ring drain race Nicola Lunghi
-- strict thread matches above, loose matches on Subject: below --
2026-05-06 19:55 [PATCH 1/2] usb: xhci: fix isoc silent reschedule creating stream gap on CFC controllers Dylan Robinson
2026-05-07 2:25 ` Alan Stern
2026-05-07 9:59 ` Dylan Robinson
2026-05-07 12:12 ` Mathias Nyman
2026-05-07 16:58 ` Dylan Robinson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260508185617.6bf8a6eb.michal.pecio@gmail.com \
--to=michal.pecio@gmail.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=mathias.nyman@intel.com \
--cc=nick83ola@gmail.com \
--cc=niklas.neronin@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox