From: Joonho Lee <mynameisjune111@gmail.com>
To: linux-sound@vger.kernel.org
Cc: tiwai@suse.de, perex@perex.cz, anton.yakovlev@opensynergy.com,
mst@redhat.com, virtualization@lists.linux.dev,
linux-kernel@vger.kernel.org, corbet@lwn.net,
skhan@linuxfoundation.org, rdunlap@infradead.org,
linux-doc@vger.kernel.org, Joonho Lee <mynameisjune111@gmail.com>
Subject: [PATCH v9 14/14] ALSA: virtio: rebase ordinary capture accounting on RESET
Date: Thu, 29 Oct 2026 17:50:32 +0900 [thread overview]
Message-ID: <20261029085032.70689-15-mynameisjune111@gmail.com> (raw)
In-Reply-To: <20261029085032.70689-1-mynameisjune111@gmail.com>
Keep ordinary capture's indirect accounting in step with the core RESET
positions while retaining device ring offsets. Select the operation for
ordinary capture at open and preserve the staged capture operation.
A refill failure after the common pointer mutation must allow the core
to finish its matching rebase. Latch XRUN, stop further transfers, and
report it asynchronously, including when the stream is paused. Returning
an immediate refill error here used to skip core completion and leave
inconsistent positions.
RESET therefore returns zero for this late failure, with subsequent I/O
reporting the error. With the worker held, the first nonblocking read can
return -EAGAIN; later reads return -EPIPE, and paused resume is rejected.
Prepare or reopen is required for recovery. An earlier error returned
before pointer mutation still follows the normal negative-return path.
RUNNING and PAUSED, managed and free-running refill-failure tests passed,
including delayed workers, 48,000-frame recovery and reopen. Deterministic
MMAP capture tests cover position continuity around RESET.
Assisted-by: LLM
Signed-off-by: Joonho Lee <mynameisjune111@gmail.com>
---
diff --git a/sound/virtio/virtio_pcm_ops.c b/sound/virtio/virtio_pcm_ops.c
--- a/sound/virtio/virtio_pcm_ops.c
+++ b/sound/virtio/virtio_pcm_ops.c
@@ -10,6 +10,7 @@
#include "virtio_card.h"
static const struct snd_pcm_ops virtsnd_pcm_capture_staged_ops;
+static const struct snd_pcm_ops virtsnd_pcm_capture_indirect_ops;
bool virtsnd_capture_staging;
module_param_named(capture_staging, virtsnd_capture_staging, bool, 0444);
@@ -398,6 +399,9 @@
&virtsnd_pcm_capture_staged_ops :
&virtsnd_pcm_ops[substream->stream];
+ if (vss->direction == SNDRV_PCM_STREAM_CAPTURE && !vss->capture_staging)
+ substream->ops = &virtsnd_pcm_capture_indirect_ops;
+
snd_pcm_hw_constraint_integer(substream->runtime,
SNDRV_PCM_HW_PARAM_PERIODS);
@@ -1691,6 +1695,62 @@
return 0;
}
return virtsnd_pcm_sync_stop_locked(substream);
+}
+
+/*
+ * The PCM lock covers indirect accounting and core completion. Once lib_reset
+ * changes hw_ptr, complete the core rebase even if refilling fails. The latched
+ * XRUN rejects subsequent pointer/ACK operations; the worker publishes XRUN to
+ * paused streams too. RESET success therefore does not imply stream recovery.
+ */
+static int virtsnd_pcm_indirect_reset(struct snd_pcm_substream *substream)
+{
+ struct virtio_pcm_substream *vss = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct virtio_snd_queue *queue = virtsnd_pcm_queue(vss);
+ struct virtsnd_pcm_transfer transfer = {};
+ int rc;
+
+ rc = snd_pcm_lib_reset(substream);
+ if (rc)
+ return rc;
+ if (!snd_pcm_running(substream) &&
+ runtime->state != SNDRV_PCM_STATE_PAUSED)
+ return 0;
+
+ guard(spinlock_irqsave)(&queue->lock);
+ guard(spinlock)(&vss->lock);
+ if (vss->resetting || !vss->prepared || vss->stopped) {
+ vss->xfer_xrun = true;
+ virtsnd_pcm_schedule_period_elapsed(vss);
+ return 0;
+ }
+
+ /* Pausing does not move the device's fixed DMA buffer positions. */
+ if (runtime->state == SNDRV_PCM_STATE_PAUSED)
+ runtime->status->hw_ptr =
+ bytes_to_frames(runtime, vss->pcm_indirect.sw_io);
+
+ transfer.indirect = vss->pcm_indirect;
+ transfer.indirect.sw_ready = 0;
+ /* Consume no application delta while returning discarded RX space. */
+ transfer.indirect.appl_ptr = runtime->control->appl_ptr;
+ rc = snd_pcm_indirect_capture_transfer(substream, &transfer.indirect,
+ virtsnd_pcm_trans_copy);
+ if (!rc)
+ rc = transfer.error;
+ if (rc) {
+ virtsnd_pcm_transfer_failed(vss);
+ vss->xfer_xrun = true;
+ virtsnd_pcm_schedule_period_elapsed(vss);
+ return 0;
+ }
+
+ /* RESET discards all samples through the observed software pointer. */
+ transfer.indirect.sw_ready = 0;
+ transfer.indirect.appl_ptr = runtime->status->hw_ptr;
+ vss->pcm_indirect = transfer.indirect;
+ return 0;
}
/* The core holds the stream lock through the matching appl_ptr reset. */
@@ -1790,3 +1850,17 @@
.pointer = virtsnd_pcm_cp_pointer,
.ack = virtsnd_pcm_cp_ack,
};
+
+static const struct snd_pcm_ops virtsnd_pcm_capture_indirect_ops = {
+ .open = virtsnd_pcm_open,
+ .close = virtsnd_pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .reset = virtsnd_pcm_indirect_reset,
+ .hw_params = virtsnd_pcm_hw_params,
+ .hw_free = virtsnd_pcm_hw_free,
+ .prepare = virtsnd_pcm_prepare,
+ .trigger = virtsnd_pcm_trigger,
+ .sync_stop = virtsnd_pcm_sync_stop,
+ .pointer = virtsnd_pcm_cp_pointer,
+ .ack = virtsnd_pcm_cp_ack,
+};
prev parent reply other threads:[~2026-10-29 8:51 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-29 8:50 [PATCH v9 00/14] ALSA: virtio: staged capture recovery and PCM RESET synchronization Joonho Lee
2026-10-29 8:50 ` [PATCH v9 01/14] ALSA: virtio: Propagate PCM send failures through ACK Joonho Lee
2026-10-29 8:50 ` [PATCH v9 02/14] ALSA: virtio: Recover PCM state after a failed start Joonho Lee
2026-10-29 8:50 ` [PATCH v9 03/14] ALSA: virtio: Retain queued messages through device reset Joonho Lee
2026-10-29 8:50 ` [PATCH v9 04/14] ALSA: virtio: Keep PCM DMA buffers alive through device ownership Joonho Lee
2026-10-29 8:50 ` [PATCH v9 05/14] ALSA: virtio: Keep control payloads alive through DMA completion Joonho Lee
2026-10-29 8:50 ` [PATCH v9 06/14] ALSA: virtio: wait through signals for PCM teardown Joonho Lee
2026-10-29 8:50 ` [PATCH v9 07/14] ALSA: pcm: mark stop-threshold accesses for capture policy sampling Joonho Lee
2026-10-29 8:50 ` [PATCH v9 08/14] ALSA: pcm: report partial progress under the stream lock Joonho Lee
2026-10-29 8:50 ` [PATCH v9 09/14] ALSA: virtio: add staged capture accounting and lifecycle recovery Joonho Lee
2026-10-29 8:50 ` [PATCH v9 10/14] ALSA: virtio: prioritize staged capture period work Joonho Lee
2026-10-29 8:50 ` [PATCH v9 11/14] docs: describe virtio-sound capture options Joonho Lee
2026-10-29 8:50 ` [PATCH v9 12/14] ALSA: pcm: add an optional reset operation under the stream lock Joonho Lee
2026-10-29 8:50 ` [PATCH v9 13/14] ALSA: virtio: synchronize staged capture accounting during RESET Joonho Lee
2026-10-29 8:50 ` Joonho Lee [this message]
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=20261029085032.70689-15-mynameisjune111@gmail.com \
--to=mynameisjune111@gmail.com \
--cc=anton.yakovlev@opensynergy.com \
--cc=corbet@lwn.net \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sound@vger.kernel.org \
--cc=mst@redhat.com \
--cc=perex@perex.cz \
--cc=rdunlap@infradead.org \
--cc=skhan@linuxfoundation.org \
--cc=tiwai@suse.de \
--cc=virtualization@lists.linux.dev \
/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
all inboxes | Powered by JetHome®