Linux Sound subsystem development
 help / color / mirror / Atom feed
* [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