All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/2] ALSA: virtio: fix staged capture ACK ordering and period scheduling
@ 2026-10-17  6:00 Joonho Lee
  2026-10-17  6:00 ` [RFC PATCH 1/2] ALSA: virtio: account staged capture reads before RX refill Joonho Lee
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Joonho Lee @ 2026-10-17  6:00 UTC (permalink / raw)
  To: Anton Yakovlev, Michael S. Tsirkin, Takashi Iwai
  Cc: Jaroslav Kysela, linux-sound, virtualization, linux-kernel

Hi,

These two follow-ups address separate failure paths in the staged
capture support from the VZ RFC v2. Patch 1 fixes ACK accounting under
concurrent RX completion. Patch 2 changes scheduling of staged capture
period work. Keeping them separate lets the accounting fix and
scheduling policy be reviewed and tested independently.

Patch 1 commits consumed bytes under the substream lock before waiting
for the RX queue lock. It then refills with queue -> substream lock
ordering. After consumption has been committed, refill failure latches
XRUN and ACK returns success. Returning an error would roll ALSA
appl_ptr back while the driver's consumption counters remained advanced.
Pre-commit errors still propagate. Ring-capacity checks continue to
reject unread overflow.

Patch 2 routes staged capture period work to system_highpri_wq at all
ten producers, including self-requeue and the ACK error paths. Playback
and non-staged streams retain normal scheduling. Work cancellation and
initialization, buffer sizes, sample accounting and module parameter
defaults remain unchanged. Enabling staged capture changes scheduling;
this patch does not provide real-time guarantees.

Base and prerequisites

The tested base is sound.git 5618f6837ef3314e2c581d4c05ec13b7ed975cb4.
It contains core capture-drain commits 1f21537b1186 and d9f52113f2634.
Those commits supply the core dependency for this series and supersede
the older core RFC v3 dependency named by the VZ RFC v2 cover letter.

Apply these public prerequisites in order, then patches 1 and 2:

1. Five virtio-snd lifetime/error-recovery v3 patches:
   https://lore.kernel.org/all/cover.1791881787.git.mynameisjune111@gmail.com/
2. The generic teardown-wait RFC v2 patch:
   https://lore.kernel.org/all/rfc-v2-generic-control-wait-0.2eddd58a796e497f@gmail.com/
3. The VZ capture RFC v2 patch:
   https://lore.kernel.org/all/rfc-v2-vz-capture-compat-1.b9ab4c1540dc4691@gmail.com/

The seven stable prerequisite patch IDs are listed below. These
follow-ups need the pending staged-capture implementation; its
introducing patch has no upstream commit ID for a Fixes tag yet. The two
changes do not include the separate control tracepoints or input-route
recovery work.

Validation

For patch 1, source-extracted host fixtures under ASan/UBSan reproduce
the baseline ACK race and post-commit pointer rollback. The candidate
preserves wrapped data and accounting, including failed refill. Two
ARM64 QEMU boots exercise the extracted logic with real spinlocks, KASAN
and lockdep. A full-driver baseline/candidate matrix passed 20 lifecycle
scenarios, covering packed tails, delayed PREPARE/START/STOP/RELEASE,
pending RX, reset cancellation and playback/capture recovery.

For patch 2, the unchanged candidate also passed ten full-driver QEMU
scenarios with KASAN and lockdep. The ARM64 build emitted the known 517
-Woverride-init warnings outside sound/, with no sound-source warnings.
The fixtures use test glue and a modified QEMU backend for fault
injection.

The physical comparison used the built-in MacBook Pro microphone through
VZ, a two-vCPU/2048 MiB guest, mono S16_LE at 48 kHz, a 1024-frame
period and a 4096-frame buffer. Six fresh boots compared ACK-only with
ACK plus patch 2, in A/B, B/A, A/B order. Each boot ran quiet capture
for six seconds, then a 70-second target with 16 nice-0 CPU workers,
then a six-second reopen. The reader also used nice 0 in both arms.

  Run  ACK-only received before EPIPE     ACK + patch 2
  1       563520 frames (11.74 seconds)   3360000 frames (70 seconds)
  2      1476752 frames (30.77 seconds)   3360000 frames (70 seconds)
  3      1455840 frames (30.33 seconds)   3360000 frames (70 seconds)

All three failures logged ring_capacity. All candidate captures had zero
read errors and nonzero signal; all six immediate reopens passed.
Routes, worker priorities, worker cleanup and guest shutdown were
checked. Trace loss was zero. The initrd contents differed only in
virtio_snd.ko and its expected-hash file; the kernel and capture
executable were equal.

The first baseline failure included a 108.112 ms period-work dispatch
delay and a 255.821 ms runnable wait for the reader. The other two
failures left pending work without matching execution, so their
matched-only latency maxima understate outstanding work. Candidate
maximum dispatch delays were 13.029, 12.355 and 20.366 ms across the
three runs.

In a separate pair with the reader at nice -10 in both arms, both
versions completed 70 seconds and reopened successfully. Host load was
lower during that control. It is an exploratory result, not an isolated
priority effect. Host load varied throughout the comparisons and tracing
adds overhead. The evidence supports this change for the tested
workload, with contention affecting both kernel work and userspace
scheduling. It does not establish an exclusive kernel-only cause or
lossless capture under arbitrary load.

One initial run failed before valid capture because of a harness
identity check. Another had a result-parser delimiter error; its
original trace was preserved and independently reparsed. Four preflight
attempts refused an unexpected input device before launching a VM. These
are excluded from clean-capture counts. The eight accepted boots contain
24 capture phases: three reproduced baseline failures and 21 completed
captures.

Remaining coverage and review questions

The physical result covers this built-in mono input and this guest
setup. Input switching, sleep/wake, other interfaces, other VMMs and
physical non-coherent DMA remain outside this comparison. Guest poweroff
was used for cleanup; graceful ACPI shutdown was not tested by this
matrix. The fresh regressions described above predate this packaging
step. The committed source matches the tested source byte for byte.

The new fixtures, harness and raw logs are currently local. An immutable
public reproducer snapshot still needs to be prepared before submission.

Is system_highpri_wq appropriate for the opt-in staged capture path, or
would a driver-owned queue be preferable? Is returning success after the
ACK accounting commit, with XRUN latched on refill failure, the right
way to preserve ALSA pointer consistency? I would also appreciate
guidance on whether these follow-ups should be folded into the pending
VZ revision.

Codex (GPT-6 Astra) assisted with test harnesses, trace review and this
text. The work was directed at isolating the ACK race, preserving
accounting on errors, and comparing unchanged baseline/candidate
artifacts under the same explicit guest workload. The patches carry
Assisted-by attribution.

Thanks,
Joonho

Joonho Lee (2):
  ALSA: virtio: account staged capture reads before RX refill
  ALSA: virtio: prioritize staged capture period work

 sound/virtio/virtio_pcm.c     |   4 +-
 sound/virtio/virtio_pcm.h     |  12 ++++
 sound/virtio/virtio_pcm_msg.c |   6 +-
 sound/virtio/virtio_pcm_ops.c | 132 ++++++++++++++++++++--------------
 4 files changed, 96 insertions(+), 58 deletions(-)


base-commit: 5618f6837ef3314e2c581d4c05ec13b7ed975cb4
prerequisite-patch-id: 39fb327a004c966ab90f66a34a64bbdbb3ffb475
prerequisite-patch-id: 7c6bc344656fd839ae0d697ba18d66ac0b47827a
prerequisite-patch-id: 9dd290ac3147fa7b49a475d7df8a6172778f2860
prerequisite-patch-id: f4c24a5e441343a690f4ac2437f181c815bc23d0
prerequisite-patch-id: ab4a5b770247a65272ab7af18a75a147daf81287
prerequisite-patch-id: cfe3e7000e695a2fda27993f4d9acf0a637cf24e
prerequisite-patch-id: 771e8815f2b874d98376f309dc60bc90244f378c
prerequisite-message-id: cover.1791881787.git.mynameisjune111@gmail.com
prerequisite-message-id: rfc-v2-generic-control-wait-0.2eddd58a796e497f@gmail.com
prerequisite-message-id: rfc-v2-vz-capture-compat-0.b9ab4c1540dc4691@gmail.com

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [RFC PATCH 1/2] ALSA: virtio: account staged capture reads before RX refill
  2026-10-17  6:00 [RFC PATCH 0/2] ALSA: virtio: fix staged capture ACK ordering and period scheduling Joonho Lee
@ 2026-10-17  6:00 ` Joonho Lee
  2026-10-17  6:03   ` sashiko-bot
  2026-10-17  6:00 ` [RFC PATCH 2/2] ALSA: virtio: prioritize staged capture period work Joonho Lee
  2026-10-17 12:51 ` [RFC PATCH 0/2] ALSA: virtio: fix staged capture ACK ordering and period scheduling Joonho Lee
  2 siblings, 1 reply; 6+ messages in thread
From: Joonho Lee @ 2026-10-17  6:00 UTC (permalink / raw)
  To: Anton Yakovlev, Michael S. Tsirkin, Takashi Iwai
  Cc: Jaroslav Kysela, linux-sound, virtualization, linux-kernel

The RX callback holds the queue lock across a batch of completions. A
reader that has copied samples can wait for that lock in ACK before its
consumed bytes are removed from capture_ready. A later completion in the
same batch can then reject data using stale ring occupancy.

Account the staged read under the substream lock before acquiring the RX
queue lock. Release that lock before taking the queue and substream locks
in their established order to refill requests.

Once accounting is committed, latch refill errors as XRUN and return
success from ACK. A negative return would make ALSA restore appl_ptr while
the driver retained the consumed-byte accounting. Keep pre-commit errors,
ring-capacity checks, and normal period-work scheduling unchanged.

Source-extracted host and kernel fixtures reproduce the stale-capacity
race and post-commit ALSA pointer rollback. The candidate preserves wrapped
data and pointer accounting. KASAN/lockdep QEMU lifecycle checks passed.
The fixtures substitute selected backend helpers and do not independently
establish physical-device acceptance.

This follows pending staged capture support, whose introducing patch has
no upstream commit ID for a Fixes tag yet.

Link: https://lore.kernel.org/all/rfc-v2-vz-capture-compat-1.b9ab4c1540dc4691@gmail.com/
Assisted-by: LLM
Signed-off-by: Joonho Lee <mynameisjune111@gmail.com>
---
 sound/virtio/virtio_pcm_ops.c | 128 ++++++++++++++++++++--------------
 1 file changed, 77 insertions(+), 51 deletions(-)

diff --git a/sound/virtio/virtio_pcm_ops.c b/sound/virtio/virtio_pcm_ops.c
index 003832d112551..85e7576903d56 100644
--- a/sound/virtio/virtio_pcm_ops.c
+++ b/sound/virtio/virtio_pcm_ops.c
@@ -1229,70 +1229,96 @@ static int virtsnd_pcm_pb_ack(struct snd_pcm_substream *substream)
 	return 0;
 }
 
-static int virtsnd_pcm_cp_ack(struct snd_pcm_substream *substream)
+static int virtsnd_pcm_capture_staged_ack(struct virtio_pcm_substream *vss,
+					  struct snd_pcm_runtime *runtime)
 {
-	struct virtio_pcm_substream *vss = snd_pcm_substream_chip(substream);
 	struct virtio_snd_queue *queue = virtsnd_pcm_queue(vss);
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct virtsnd_pcm_transfer transfer = {};
-	int rc;
+	int rc = 0;
+
+	/*
+	 * The RX callback holds the queue lock while draining completions.
+	 * Account ALSA's read under the substream lock alone so completions later
+	 * in that drain observe the newly released ring space.
+	 */
+	scoped_guard(spinlock_irqsave, &vss->lock) {
+		snd_pcm_uframes_t appl_ptr;
+		snd_pcm_sframes_t diff;
+		size_t bytes;
+		u64 next_acked_total;
+
+		if (!vss->runtime_active || !runtime || !runtime->control ||
+		    !runtime->dma_area)
+			return -EBADFD;
+		if (vss->xfer_xrun)
+			return -EPIPE;
+		if (!virtsnd_pcm_capture_counters_valid(vss)) {
+			vss->xfer_xrun = true;
+			schedule_work(&vss->elapsed_period);
+			return -EPIPE;
+		}
 
+		appl_ptr = runtime->control->appl_ptr;
+		diff = appl_ptr - vss->pcm_indirect.appl_ptr;
+		if (diff < -(snd_pcm_sframes_t)(runtime->boundary / 2))
+			diff += runtime->boundary;
+		if (diff < 0 ||
+		    (snd_pcm_uframes_t)diff > runtime->buffer_size) {
+			vss->xfer_xrun = true;
+			schedule_work(&vss->elapsed_period);
+			return -EPIPE;
+		}
+
+		/* ACK includes any subperiod tail already copied to the ring. */
+		bytes = frames_to_bytes(runtime, diff);
+		if (bytes > vss->capture_ready ||
+		    check_add_overflow(vss->capture_acked_total, (u64)bytes,
+				       &next_acked_total) ||
+		    next_acked_total > vss->capture_copied_total) {
+			vss->xfer_xrun = true;
+			schedule_work(&vss->elapsed_period);
+			return -EPIPE;
+		}
+
+		vss->capture_acked_total = next_acked_total;
+		vss->capture_ready -= bytes;
+		vss->pcm_indirect.appl_ptr = appl_ptr;
+	}
+
+	/* Preserve the queue -> substream lock order while refilling requests. */
 	scoped_guard(spinlock_irqsave, &queue->lock) {
 		guard(spinlock)(&vss->lock);
-		if (vss->capture_staging) {
-			snd_pcm_uframes_t appl_ptr;
-			snd_pcm_sframes_t diff;
-			size_t bytes;
-			u64 next_acked_total;
-
-			if (!vss->runtime_active || !runtime || !runtime->control ||
-			    !runtime->dma_area)
-				return -EBADFD;
-			if (vss->xfer_xrun)
-				return -EPIPE;
-			if (!virtsnd_pcm_capture_counters_valid(vss)) {
+		if (vss->runtime_active && vss->xfer_enabled &&
+		    !vss->xfer_xrun) {
+			rc = virtsnd_pcm_capture_send(vss);
+			if (rc) {
 				vss->xfer_xrun = true;
 				schedule_work(&vss->elapsed_period);
-				return -EPIPE;
 			}
-			appl_ptr = runtime->control->appl_ptr;
-			diff = appl_ptr - vss->pcm_indirect.appl_ptr;
+		}
+	}
 
-			if (diff < -(snd_pcm_sframes_t)(runtime->boundary / 2))
-				diff += runtime->boundary;
-			if (diff < 0 ||
-			    (snd_pcm_uframes_t)diff > runtime->buffer_size) {
-				vss->xfer_xrun = true;
-				schedule_work(&vss->elapsed_period);
-				return -EPIPE;
-			}
+	if (rc)
+		dev_warn_ratelimited(&vss->snd->vdev->dev,
+				     "SID %u: failed to refill capture queue after ACK: %d\n",
+				     vss->sid, rc);
 
-			/* ACK includes any subperiod tail already copied to the ring. */
-			bytes = frames_to_bytes(runtime, diff);
-			if (bytes > vss->capture_ready ||
-			    check_add_overflow(vss->capture_acked_total, (u64)bytes,
-					       &next_acked_total) ||
-			    next_acked_total > vss->capture_copied_total) {
-				vss->xfer_xrun = true;
-				schedule_work(&vss->elapsed_period);
-				return -EPIPE;
-			}
+	/* The ACK is committed; a refill failure is reported by the next XRUN. */
+	return 0;
+}
 
-			vss->capture_acked_total = next_acked_total;
-			vss->capture_ready -= bytes;
-			vss->pcm_indirect.appl_ptr = appl_ptr;
-			if (vss->xfer_enabled) {
-				rc = virtsnd_pcm_capture_send(vss);
-				if (rc) {
-					vss->xfer_xrun = true;
-					schedule_work(&vss->elapsed_period);
-				}
-				return rc;
-			}
+static int virtsnd_pcm_cp_ack(struct snd_pcm_substream *substream)
+{
+	struct virtio_pcm_substream *vss = snd_pcm_substream_chip(substream);
+	struct virtio_snd_queue *queue = virtsnd_pcm_queue(vss);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct virtsnd_pcm_transfer transfer = {};
+	int rc;
 
-			return 0;
-		}
+	if (vss->capture_staging)
+		return virtsnd_pcm_capture_staged_ack(vss, runtime);
 
+	scoped_guard(spinlock_irqsave, &queue->lock) {
+		guard(spinlock)(&vss->lock);
 		transfer.indirect = vss->pcm_indirect;
 		if (vss->stopped) {
 			rc = -EPIPE;

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [RFC PATCH 2/2] ALSA: virtio: prioritize staged capture period work
  2026-10-17  6:00 [RFC PATCH 0/2] ALSA: virtio: fix staged capture ACK ordering and period scheduling Joonho Lee
  2026-10-17  6:00 ` [RFC PATCH 1/2] ALSA: virtio: account staged capture reads before RX refill Joonho Lee
@ 2026-10-17  6:00 ` Joonho Lee
  2026-10-17  6:03   ` sashiko-bot
  2026-10-17 12:51 ` [RFC PATCH 0/2] ALSA: virtio: fix staged capture ACK ordering and period scheduling Joonho Lee
  2 siblings, 1 reply; 6+ messages in thread
From: Joonho Lee @ 2026-10-17  6:00 UTC (permalink / raw)
  To: Anton Yakovlev, Michael S. Tsirkin, Takashi Iwai
  Cc: Jaroslav Kysela, linux-sound, virtualization, linux-kernel

CPU contention can delay staged capture period notifications while RX
completions continue filling the unread ring. In a two-vCPU VZ guest with
16 nice-0 CPU workers, the ACK-fixed baseline stopped with ring_capacity
and EPIPE in three runs, after 11.74, 30.77 and 30.33 seconds of audio.

Route staged capture period work through system_highpri_wq with a common
helper at all ten producers, including ACK errors and self-requeue. Keep
playback and non-staged streams on the normal workqueue. Initialization,
cancellation, buffer geometry and capture accounting remain unchanged.

With the same kernel, input, geometry and userspace priority, the candidate
completed three 70-second captures and immediate reopens. Its maximum
matched queue-to-start delay was 20.366 ms, versus 108.112 ms in the first
baseline failure. The other baseline failures had pending work without
matching execution, so matched-only statistics do not bound that delay.

Reader scheduling delays were also present. Both arms passed a separate
nice -10 reader control, and host load varied between runs. These results
support the change for the tested workload without isolating a kernel-only
cause or guaranteeing lossless capture under arbitrary CPU load.
KASAN/lockdep QEMU regressions passed with the unchanged candidate source.

This follows the staged ACK fix and pending VZ capture support. The
introducing staged-capture patch has no upstream Fixes commit ID yet.

Link: https://lore.kernel.org/all/rfc-v2-vz-capture-compat-1.b9ab4c1540dc4691@gmail.com/
Assisted-by: LLM
Signed-off-by: Joonho Lee <mynameisjune111@gmail.com>
---
 sound/virtio/virtio_pcm.c     |  4 ++--
 sound/virtio/virtio_pcm.h     | 12 ++++++++++++
 sound/virtio/virtio_pcm_msg.c |  6 +++---
 sound/virtio/virtio_pcm_ops.c | 10 +++++-----
 4 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/sound/virtio/virtio_pcm.c b/sound/virtio/virtio_pcm.c
index a3478fc8848db..d8515b2144a14 100644
--- a/sound/virtio/virtio_pcm.c
+++ b/sound/virtio/virtio_pcm.c
@@ -397,7 +397,7 @@ static void virtsnd_pcm_period_elapsed(struct work_struct *work)
 	}
 
 	if (requeue)
-		schedule_work(&vss->elapsed_period);
+		virtsnd_pcm_schedule_period_elapsed(vss);
 }
 
 /**
@@ -606,7 +606,7 @@ void virtsnd_pcm_event(struct virtio_snd *snd, struct virtio_snd_event *event)
 			if (vss->xfer_enabled) {
 				vss->xfer_xrun = true;
 				if (vss->capture_staging)
-					schedule_work(&vss->elapsed_period);
+					virtsnd_pcm_schedule_period_elapsed(vss);
 			}
 		}
 		break;
diff --git a/sound/virtio/virtio_pcm.h b/sound/virtio/virtio_pcm.h
index e143a15592f05..5d1d88f2823b2 100644
--- a/sound/virtio/virtio_pcm.h
+++ b/sound/virtio/virtio_pcm.h
@@ -8,6 +8,7 @@
 
 #include <linux/atomic.h>
 #include <linux/virtio_config.h>
+#include <linux/workqueue.h>
 #include <sound/pcm.h>
 #include <sound/pcm-indirect.h>
 
@@ -114,6 +115,17 @@ struct virtio_pcm_substream {
 	wait_queue_head_t msg_empty;
 };
 
+/* Keep non-staged PCM notifications on schedule_work()'s normal queue. */
+static inline bool
+virtsnd_pcm_schedule_period_elapsed(struct virtio_pcm_substream *vss)
+{
+	if (vss->direction == SNDRV_PCM_STREAM_CAPTURE &&
+	    vss->capture_staging)
+		return queue_work(system_highpri_wq, &vss->elapsed_period);
+
+	return schedule_work(&vss->elapsed_period);
+}
+
 /*
  * ALSA may observe a subperiod tail before its period callback. Keep actual
  * unread occupancy separate from pointer observations and notification state.
diff --git a/sound/virtio/virtio_pcm_msg.c b/sound/virtio/virtio_pcm_msg.c
index 795e52e09564b..663f7695b5be8 100644
--- a/sound/virtio/virtio_pcm_msg.c
+++ b/sound/virtio/virtio_pcm_msg.c
@@ -627,7 +627,7 @@ static void virtsnd_pcm_capture_xrun_locked(struct virtio_pcm_substream *vss)
 {
 	if (!vss->xfer_xrun) {
 		vss->xfer_xrun = true;
-		schedule_work(&vss->elapsed_period);
+		virtsnd_pcm_schedule_period_elapsed(vss);
 	}
 }
 
@@ -720,7 +720,7 @@ static void virtsnd_pcm_capture_complete(struct virtio_pcm_msg *msg,
 			virtsnd_pcm_capture_xrun_locked(vss);
 		}
 		if (got_audio && !vss->xfer_xrun)
-			schedule_work(&vss->elapsed_period);
+			virtsnd_pcm_schedule_period_elapsed(vss);
 	} else if (!vss->msg_count) {
 		wake_up_all(&vss->msg_empty);
 	}
@@ -858,7 +858,7 @@ static void virtsnd_pcm_msg_complete(struct virtio_pcm_msg *msg,
 		runtime->delay =
 			bytes_to_frames(runtime,
 					le32_to_cpu(msg->status.latency_bytes));
-		schedule_work(&vss->elapsed_period);
+		virtsnd_pcm_schedule_period_elapsed(vss);
 	} else if (!vss->msg_count) {
 		wake_up_all(&vss->msg_empty);
 	}
diff --git a/sound/virtio/virtio_pcm_ops.c b/sound/virtio/virtio_pcm_ops.c
index 85e7576903d56..d50924b792f65 100644
--- a/sound/virtio/virtio_pcm_ops.c
+++ b/sound/virtio/virtio_pcm_ops.c
@@ -232,7 +232,7 @@ virtsnd_pcm_pause_restart_fail(struct virtio_pcm_substream *vss,
 				VIRTSND_PCM_PAUSE_RESTART_RESET_REQUIRED;
 	}
 	if (notify_xrun)
-		schedule_work(&vss->elapsed_period);
+		virtsnd_pcm_schedule_period_elapsed(vss);
 	vss->substream->runtime->stop_operating = true;
 }
 
@@ -1253,7 +1253,7 @@ static int virtsnd_pcm_capture_staged_ack(struct virtio_pcm_substream *vss,
 			return -EPIPE;
 		if (!virtsnd_pcm_capture_counters_valid(vss)) {
 			vss->xfer_xrun = true;
-			schedule_work(&vss->elapsed_period);
+			virtsnd_pcm_schedule_period_elapsed(vss);
 			return -EPIPE;
 		}
 
@@ -1264,7 +1264,7 @@ static int virtsnd_pcm_capture_staged_ack(struct virtio_pcm_substream *vss,
 		if (diff < 0 ||
 		    (snd_pcm_uframes_t)diff > runtime->buffer_size) {
 			vss->xfer_xrun = true;
-			schedule_work(&vss->elapsed_period);
+			virtsnd_pcm_schedule_period_elapsed(vss);
 			return -EPIPE;
 		}
 
@@ -1275,7 +1275,7 @@ static int virtsnd_pcm_capture_staged_ack(struct virtio_pcm_substream *vss,
 				       &next_acked_total) ||
 		    next_acked_total > vss->capture_copied_total) {
 			vss->xfer_xrun = true;
-			schedule_work(&vss->elapsed_period);
+			virtsnd_pcm_schedule_period_elapsed(vss);
 			return -EPIPE;
 		}
 
@@ -1292,7 +1292,7 @@ static int virtsnd_pcm_capture_staged_ack(struct virtio_pcm_substream *vss,
 			rc = virtsnd_pcm_capture_send(vss);
 			if (rc) {
 				vss->xfer_xrun = true;
-				schedule_work(&vss->elapsed_period);
+				virtsnd_pcm_schedule_period_elapsed(vss);
 			}
 		}
 	}

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [RFC PATCH 2/2] ALSA: virtio: prioritize staged capture period work
  2026-10-17  6:00 ` [RFC PATCH 2/2] ALSA: virtio: prioritize staged capture period work Joonho Lee
@ 2026-10-17  6:03   ` sashiko-bot
  0 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-10-17  6:03 UTC (permalink / raw)
  To: Joonho Lee; +Cc: virtualization, Michael S. Tsirkin, Eugenio Perez

> CPU contention can delay staged capture period notifications while RX
> completions continue filling the unread ring. In a two-vCPU VZ guest with
> 16 nice-0 CPU workers, the ACK-fixed baseline stopped with ring_capacity
> and EPIPE in three runs, after 11.74, 30.77 and 30.33 seconds of audio.
> 
> Route staged capture period work through system_highpri_wq with a common
> helper at all ten producers, including ACK errors and self-requeue. Keep
> playback and non-staged streams on the normal workqueue. Initialization,
> cancellation, buffer geometry and capture accounting remain unchanged.
> 
> With the same kernel, input, geometry and userspace priority, the candidate
> completed three 70-second captures and immediate reopens. Its maximum
> matched queue-to-start delay was 20.366 ms, versus 108.112 ms in the first
> baseline failure. The other baseline failures had pending work without
> matching execution, so matched-only statistics do not bound that delay.
> 
> Reader scheduling delays were also present. Both arms passed a separate
> nice -10 reader control, and host load varied between runs. These results
> support the change for the tested workload without isolating a kernel-only
> cause or guaranteeing lossless capture under arbitrary CPU load.
> KASAN/lockdep QEMU regressions passed with the unchanged candidate source.
> 
> This follows the staged ACK fix and pending VZ capture support. The
> introducing staged-capture patch has no upstream Fixes commit ID yet.
> 
> Link: https://lore.kernel.org/all/rfc-v2-vz-capture-compat-1.b9ab4c1540dc4691@gmail.com/
> Assisted-by: LLM
> Signed-off-by: Joonho Lee <mynameisjune111@gmail.com>

Sashiko has reviewed this patch and found no issues.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/rfc-virtio-snd-capture-followups-0.f2737c95c12e45b4@gmail.com?part=2


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [RFC PATCH 1/2] ALSA: virtio: account staged capture reads before RX refill
  2026-10-17  6:00 ` [RFC PATCH 1/2] ALSA: virtio: account staged capture reads before RX refill Joonho Lee
@ 2026-10-17  6:03   ` sashiko-bot
  0 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-10-17  6:03 UTC (permalink / raw)
  To: Joonho Lee; +Cc: virtualization, Michael S. Tsirkin, Eugenio Perez

> The RX callback holds the queue lock across a batch of completions. A
> reader that has copied samples can wait for that lock in ACK before its
> consumed bytes are removed from capture_ready. A later completion in the
> same batch can then reject data using stale ring occupancy.
> 
> Account the staged read under the substream lock before acquiring the RX
> queue lock. Release that lock before taking the queue and substream locks
> in their established order to refill requests.
> 
> Once accounting is committed, latch refill errors as XRUN and return
> success from ACK. A negative return would make ALSA restore appl_ptr while
> the driver retained the consumed-byte accounting. Keep pre-commit errors,
> ring-capacity checks, and normal period-work scheduling unchanged.
> 
> Source-extracted host and kernel fixtures reproduce the stale-capacity
> race and post-commit ALSA pointer rollback. The candidate preserves wrapped
> data and pointer accounting. KASAN/lockdep QEMU lifecycle checks passed.
> The fixtures substitute selected backend helpers and do not independently
> establish physical-device acceptance.
> 
> This follows pending staged capture support, whose introducing patch has
> no upstream commit ID for a Fixes tag yet.
> 
> Link: https://lore.kernel.org/all/rfc-v2-vz-capture-compat-1.b9ab4c1540dc4691@gmail.com/
> Assisted-by: LLM
> Signed-off-by: Joonho Lee <mynameisjune111@gmail.com>

Sashiko has reviewed this patch and found no issues.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/rfc-virtio-snd-capture-followups-0.f2737c95c12e45b4@gmail.com?part=1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [RFC PATCH 0/2] ALSA: virtio: fix staged capture ACK ordering and period scheduling
  2026-10-17  6:00 [RFC PATCH 0/2] ALSA: virtio: fix staged capture ACK ordering and period scheduling Joonho Lee
  2026-10-17  6:00 ` [RFC PATCH 1/2] ALSA: virtio: account staged capture reads before RX refill Joonho Lee
  2026-10-17  6:00 ` [RFC PATCH 2/2] ALSA: virtio: prioritize staged capture period work Joonho Lee
@ 2026-10-17 12:51 ` Joonho Lee
  2 siblings, 0 replies; 6+ messages in thread
From: Joonho Lee @ 2026-10-17 12:51 UTC (permalink / raw)
  To: Anton Yakovlev, Michael S. Tsirkin, Takashi Iwai
  Cc: Jaroslav Kysela, linux-sound, virtualization, linux-kernel

Hi,

I've prepared the reproducer and build instructions for this series:

https://github.com/whatisyourname0/virtio-snd-reproducer/tree/88913cb432c3771d179a274e3b622a22b03bb9f1/capture-followups

DEPENDENCIES.md lists the exact base and prerequisite patches. The
preparation script reconstructs the pre-ACK, ACK-only and ACK plus
scheduling trees from those patches. Each tree matches the source used
for the original tests. The two kernel patches in this series are
unchanged.

For patch 1, ack/ extracts the baseline and candidate routines and tests
ACK ordering and refill failure with two kernel threads. I rebuilt the
ACK-only kernel and fixture module with KASAN and lockdep. All four
cases passed, followed by module unload and a clean guest shutdown. The
fixture supplies test queue hooks; full virtqueue coverage is a separate
part of the test setup.

I also rebuilt QEMU and the kernel with both patches for the capture
regression checks. All 24 captures across four/eight channels and
one/two vCPUs matched the expected file length and SHA-256. A deliberate
reader stall produced XRUN, and a fresh capture after it matched the
oracle. An eight-channel, one-vCPU run completed 70 seconds under guest
CPU load and a subsequent ten-second capture without XRUN or a data
mismatch. The kernel logs were clean.

These QEMU tests use a deterministic synthetic source. They cover
capture correctness and recovery; the VZ comparison in the original
cover letter remains the evidence for patch 2's scheduling benefit. The
ACK fixture uses the ACK-only tree because patch 2 changes a shared
helper. Both build paths are documented separately.

FRESH-BUILD-VALIDATION.md records the source and artifact hashes,
results and remaining test limits. The package also includes the QEMU
fixture patch, the guest build recipe and the channel/frame oracle.

I'd appreciate guidance on which parts would be most useful to keep in
the kernel test suite and which should stay with the QEMU test backend.

Thanks,
Joonho

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-10-17 12:51 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-17  6:00 [RFC PATCH 0/2] ALSA: virtio: fix staged capture ACK ordering and period scheduling Joonho Lee
2026-10-17  6:00 ` [RFC PATCH 1/2] ALSA: virtio: account staged capture reads before RX refill Joonho Lee
2026-10-17  6:03   ` sashiko-bot
2026-10-17  6:00 ` [RFC PATCH 2/2] ALSA: virtio: prioritize staged capture period work Joonho Lee
2026-10-17  6:03   ` sashiko-bot
2026-10-17 12:51 ` [RFC PATCH 0/2] ALSA: virtio: fix staged capture ACK ordering and period scheduling Joonho Lee

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.