* [PATCH v3] ALSA: usb-audio: Fix boot-time audio stuttering for USB Audio device
@ 2026-07-28 11:13 Zhang Heng
2026-07-28 16:32 ` Takashi Iwai
0 siblings, 1 reply; 2+ messages in thread
From: Zhang Heng @ 2026-07-28 11:13 UTC (permalink / raw)
To: perex, tiwai, kees, chengordon326, jussi, hulianqin, i, g,
cryolitia, pav
Cc: linux-sound, linux-kernel, Zhang Heng
This USB Audio device (0x1e0b:0xd01e) exhibits audio stuttering
during boot when playing audio. Once the system is fully booted,
playback is normal.
The device reports its isochronous endpoints with the Asynchronous
sync type (bmAttributes = 0x03), which causes the driver to
calculate nurbs = min(max_urbs, ...) = 3, providing only ~16ms
of buffering. During boot, the higher system scheduling jitter
(e.g., from init scripts, device enumeration, and driver probing)
can exceed this buffer depth, causing audible stuttering.
This patch adds a device-specific quirk (QUIRK_FLAG_PLAYBACK_URB_FIXUP)
that applies two changes for this device:
1. Forces nurbs to MAX_URBS (12), providing sufficient buffering
2. Sets URB_ISO_ASAP flag for more consistent xHCI scheduling
Both changes are required together for stable boot-time playback:
- The larger buffer absorbs scheduling jitter during boot
- URB_ISO_ASAP ensures consistent URB submission timing, preventing
the xHCI scheduler from introducing variable delays
Test methodology:
- Without patch: reboot and play audio → stuttering audible in all
tests (reproduced consistently across multiple attempts)
- With nurbs=8 only: occasional minor stuttering observed after
multiple tests (insufficient buffer depth)
- With full patch (nurbs=12 + URB_ISO_ASAP): reboot and play audio
→ no stuttering observed (tested in 10+ reboot cycles without
reproducing the issue)
Signed-off-by: Zhang Heng <zhangheng@kylinos.cn>
---
sound/usb/endpoint.c | 7 ++++++-
sound/usb/quirks.c | 3 +++
sound/usb/usbaudio.h | 8 ++++++++
3 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 24cd7692bd01..54aeac7d087b 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -1232,7 +1232,10 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep)
/* try to use enough URBs to contain an entire ALSA buffer */
max_urbs = min((unsigned) MAX_URBS,
MAX_QUEUE * packs_per_ms / urb_packs);
- ep->nurbs = min(max_urbs, urbs_per_period * ep->cur_buffer_periods);
+ if (chip->quirk_flags & QUIRK_FLAG_PLAYBACK_URB_FIXUP)
+ ep->nurbs = MAX_URBS;
+ else
+ ep->nurbs = min(max_urbs, urbs_per_period * ep->cur_buffer_periods);
}
/* allocate and initialize data urbs */
@@ -1256,6 +1259,8 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep)
goto out_of_memory;
u->urb->pipe = ep->pipe;
u->urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
+ if (chip->quirk_flags & QUIRK_FLAG_PLAYBACK_URB_FIXUP)
+ u->urb->transfer_flags |= URB_ISO_ASAP;
u->urb->interval = 1 << ep->datainterval;
u->urb->context = u;
u->urb->complete = snd_complete_urb;
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 40aa40fccb46..2b4e665564d2 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -2422,6 +2422,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16),
DEVICE_FLG(0x1bcf, 0x2283, /* NexiGo N930AF FHD Webcam */
QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16),
+ DEVICE_FLG(0x1e0b, 0xd01e, /* Generic USB Audio Device */
+ QUIRK_FLAG_PLAYBACK_URB_FIXUP),
DEVICE_FLG(0x1ff7, 0x0f81, /* SC13A Webcam */
QUIRK_FLAG_GET_SAMPLE_RATE),
DEVICE_FLG(0x2040, 0x7200, /* Hauppauge HVR-950Q */
@@ -2631,6 +2633,7 @@ static const char *const snd_usb_audio_quirk_flag_names[] = {
QUIRK_STRING_ENTRY(MIXER_CAPTURE_LINEAR_VOL),
QUIRK_STRING_ENTRY(IFB_SILENCE_ON_EMPTY),
QUIRK_STRING_ENTRY(MIXER_GET_CUR_BROKEN),
+ QUIRK_STRING_ENTRY(PLAYBACK_URB_FIXUP),
NULL
};
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index e26f9092417e..dc1d0c8c9c80 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -254,6 +254,12 @@ extern bool snd_usb_skip_validation;
* check being non-fatal and only disabling GET_CUR instead of the whole mixer.
* The current volume will then be provided by the internal cache that stores
* the last set volume
+ * QUIRK_FLAG_PLAYBACK_URB_FIXUP
+ * Set URB_ISO_ASAP flag for isochronous URBs and force nurbs to MAX_URBS.
+ * This is needed for devices that exhibit boot-time audio stuttering due
+ * to insufficient buffer depth combined with xHCI scheduling variability.
+ * The larger buffer (MAX_URBS = 12, ~64ms) absorbs system scheduling
+ * jitter during boot, while URB_ISO_ASAP ensures consistent xHCI scheduling.
*/
enum {
@@ -288,6 +294,7 @@ enum {
QUIRK_TYPE_MIXER_CAPTURE_LINEAR_VOL = 28,
QUIRK_TYPE_IFB_SILENCE_ON_EMPTY = 29,
QUIRK_TYPE_MIXER_GET_CUR_BROKEN = 30,
+ QUIRK_TYPE_PLAYBACK_URB_FIXUP = 31,
/* Please also edit snd_usb_audio_quirk_flag_names */
};
@@ -324,5 +331,6 @@ enum {
#define QUIRK_FLAG_MIXER_CAPTURE_LINEAR_VOL QUIRK_FLAG(MIXER_CAPTURE_LINEAR_VOL)
#define QUIRK_FLAG_IFB_SILENCE_ON_EMPTY QUIRK_FLAG(IFB_SILENCE_ON_EMPTY)
#define QUIRK_FLAG_MIXER_GET_CUR_BROKEN QUIRK_FLAG(MIXER_GET_CUR_BROKEN)
+#define QUIRK_FLAG_PLAYBACK_URB_FIXUP QUIRK_FLAG(PLAYBACK_URB_FIXUP)
#endif /* __USBAUDIO_H */
--
2.25.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH v3] ALSA: usb-audio: Fix boot-time audio stuttering for USB Audio device
2026-07-28 11:13 [PATCH v3] ALSA: usb-audio: Fix boot-time audio stuttering for USB Audio device Zhang Heng
@ 2026-07-28 16:32 ` Takashi Iwai
0 siblings, 0 replies; 2+ messages in thread
From: Takashi Iwai @ 2026-07-28 16:32 UTC (permalink / raw)
To: Zhang Heng
Cc: perex, tiwai, kees, chengordon326, jussi, hulianqin, i, g,
cryolitia, pav, linux-sound, linux-kernel
On Tue, 28 Jul 2026 13:13:09 +0200,
Zhang Heng wrote:
>
> This USB Audio device (0x1e0b:0xd01e) exhibits audio stuttering
> during boot when playing audio. Once the system is fully booted,
> playback is normal.
>
> The device reports its isochronous endpoints with the Asynchronous
> sync type (bmAttributes = 0x03), which causes the driver to
> calculate nurbs = min(max_urbs, ...) = 3, providing only ~16ms
> of buffering. During boot, the higher system scheduling jitter
> (e.g., from init scripts, device enumeration, and driver probing)
> can exceed this buffer depth, causing audible stuttering.
>
> This patch adds a device-specific quirk (QUIRK_FLAG_PLAYBACK_URB_FIXUP)
> that applies two changes for this device:
> 1. Forces nurbs to MAX_URBS (12), providing sufficient buffering
> 2. Sets URB_ISO_ASAP flag for more consistent xHCI scheduling
>
> Both changes are required together for stable boot-time playback:
> - The larger buffer absorbs scheduling jitter during boot
> - URB_ISO_ASAP ensures consistent URB submission timing, preventing
> the xHCI scheduler from introducing variable delays
>
> Test methodology:
> - Without patch: reboot and play audio → stuttering audible in all
> tests (reproduced consistently across multiple attempts)
> - With nurbs=8 only: occasional minor stuttering observed after
> multiple tests (insufficient buffer depth)
> - With full patch (nurbs=12 + URB_ISO_ASAP): reboot and play audio
> → no stuttering observed (tested in 10+ reboot cycles without
> reproducing the issue)
>
> Signed-off-by: Zhang Heng <zhangheng@kylinos.cn>
Looks a bit like voodoo, but better than vanilla, as it seems.
Applied to for-next branch now.
thanks,
Takashi
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-07-28 16:33 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-28 11:13 [PATCH v3] ALSA: usb-audio: Fix boot-time audio stuttering for USB Audio device Zhang Heng
2026-07-28 16:32 ` Takashi Iwai
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox