Linux Sound subsystem development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Joonho Lee" <mynameisjune111@gmail.com>, linux-sound@vger.kernel.org
Cc: virtualization@lists.linux.dev,
	"Michael S. Tsirkin" <mst@redhat.com>,
	"Eugenio Perez" <eperezma@redhat.com>
Subject: Re: [PATCH v24 16/16] ALSA: virtio: preserve playback progress across pause
Date: Wed, 11 Nov 2026 00:49:55 +0000	[thread overview]
Message-ID: <sashiko-outbox-208038@kernel.org> (raw)
In-Reply-To: <20261111000543.28550-17-mynameisjune111@gmail.com>

Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [High] ALSA: virtio: spurious playback wrap and XRUN in
  virtsnd_pcm_period_elapsed()
- [Medium] ALSA: virtio: stale runtime->delay after prepare and playback
  reset
--

commit 6d3754161befb6c587ef38462dc537d40330faae
Author: Joonho Lee <mynameisjune111@gmail.com>

ALSA: virtio: preserve playback progress across pause

This commit preserves playback completion progress across pause, caches
device latency in the substream state, and limits queued playback data to
less than one buffer ring.

> diff --git a/sound/virtio/virtio_pcm_msg.c b/sound/virtio/virtio_pcm_msg.c
> index 5fdd22de61736..7721376f2ecde 100644
> --- a/sound/virtio/virtio_pcm_msg.c
> +++ b/sound/virtio/virtio_pcm_msg.c
> @@ -1002,12 +1002,10 @@ static void virtsnd_pcm_msg_complete(struct virtio_pcm_msg *msg,
>  	/* Keep latched errors until prepare establishes a fresh epoch. */
>  	vss->msg_count--;
>  
> -	if (vss->xfer_enabled) {
> -		struct snd_pcm_runtime *runtime = vss->substream->runtime;
> -
> -		runtime->delay = bytes_to_frames(runtime, latency_bytes);
> +	/* A queued request can outlive the ALSA runtime after hw_free. */
> +	vss->playback_latency_bytes = latency_bytes;
> +	if (vss->prepared && !vss->preparing)
>  		virtsnd_pcm_schedule_period_elapsed(vss);
> -	}
>  	if (!vss->msg_count)
>  		wake_up_all(&vss->msg_empty);
>  }

[Severity: High]
Can a stale or duplicate vss->elapsed_period work item run after all
playback progress has already been consumed or reset, causing a false
XRUN?

virtsnd_pcm_msg_complete() now schedules vss->elapsed_period while paused,
and virtsnd_pcm_trigger_inner() schedules it again on resume when
virtsnd_pcm_playback_progress_pending() is true.  However,
virtsnd_pcm_playback_reset() does not cancel pending work when rebasing
vss->hw_ptr and vss->pcm_indirect.hw_io, and virtsnd_pcm_period_elapsed()
calls snd_pcm_period_elapsed_under_stream_lock() unconditionally for
playback:

sound/virtio/virtio_pcm.c:virtsnd_pcm_period_elapsed() {
    ...
	if (vss->direction != SNDRV_PCM_STREAM_CAPTURE) {
		snd_pcm_period_elapsed_under_stream_lock(substream);
		return;
	}
}

For example, if a late TX completion arrives while paused and queues
vss->elapsed_period, and the application runs SNDRV_PCM_IOCTL_RESET
followed by SNDRV_PCM_TRIGGER_PAUSE_RELEASE before the worker executes:

CPU0 (vhost / irq)                CPU1 (ioctl / kworker)
virtsnd_pcm_msg_complete()
  msg_count-- (becomes 0)
  schedule_work(&elapsed_period)
                                  virtsnd_pcm_playback_reset()
                                    hw_ptr = 0;
                                    pcm_indirect.hw_io = 0;
                                  snd_pcm_do_pause(substream, 0)
                                    runtime->hw_ptr_jiffies =
                                      jiffies - HZ * 1000;
                                  virtsnd_pcm_period_elapsed()
                                    snd_pcm_period_elapsed_under_stream_lock()
                                      snd_pcm_update_hw_ptr0(..., 1)
                                        <-- false wrap + XRUN

Because virtsnd_pcm_period_elapsed() runs with in_interrupt = 1 when
vss->hw_ptr == vss->pcm_indirect.hw_io, new_hw_ptr equals
runtime->hw_ptr_interrupt while runtime->hw_ptr_jiffies is backdated
from pause, so snd_pcm_update_hw_ptr0() treats the unchanged pointer as a
full-buffer interrupt wrap, adds runtime->buffer_size to hw_base, and
stops the stream with an XRUN.  The same happens if the worker dequeues
elapsed_period and blocks on the stream lock while PAUSE_RELEASE holds it
and queues a second run.

Should virtsnd_pcm_period_elapsed() check
virtsnd_pcm_playback_progress_pending(vss) before calling
snd_pcm_period_elapsed_under_stream_lock()?

> diff --git a/sound/virtio/virtio_pcm_ops.c b/sound/virtio/virtio_pcm_ops.c
> index da4e98836721d..7fbbce1dcbb73 100644
> --- a/sound/virtio/virtio_pcm_ops.c
> +++ b/sound/virtio/virtio_pcm_ops.c
> @@ -770,6 +770,12 @@ static int virtsnd_pcm_prepare_locked(struct snd_pcm_substream *substream)
>  		memset(&vss->pcm_indirect, 0, sizeof(vss->pcm_indirect));
>  		vss->pcm_indirect.sw_buffer_size = vss->buffer_bytes;
>  		vss->pcm_indirect.hw_buffer_size = vss->buffer_bytes;
> +		if (vss->direction == SNDRV_PCM_STREAM_PLAYBACK) {
> +			/* Keep unobserved completions below one physical ring. */
> +			vss->pcm_indirect.hw_queue_size = vss->buffer_bytes -
> +				snd_pcm_lib_period_bytes(substream);
> +			vss->playback_latency_bytes = 0;
> +		}

[ ... ]

> @@ -1610,6 +1627,7 @@ virtsnd_pcm_pb_pointer(struct snd_pcm_substream *substream)
>  		}
>  		if (!paused_pointer)
>  			hw_ptr = vss->hw_ptr;
> +		runtime->delay = bytes_to_frames(runtime, vss->playback_latency_bytes);
>  	}
>  	if (paused_pointer) {
>  		if (defer_work)
> @@ -2226,6 +2244,7 @@ static int virtsnd_pcm_playback_reset(struct snd_pcm_substream *substream)
>  	vss->pcm_indirect.hw_data = position;
>  	vss->pcm_indirect.sw_io = position;
>  	vss->pcm_indirect.sw_data = position;
> +	vss->playback_latency_bytes = 0;
>  	vss->pcm_indirect.hw_ready = 0;
>  	vss->pcm_indirect.sw_ready = 0;
>  	vss->pcm_indirect.appl_ptr = runtime->status->hw_ptr;

[Severity: Medium]
Does clearing vss->playback_latency_bytes in virtsnd_pcm_prepare_locked()
and virtsnd_pcm_playback_reset() leave a stale runtime->delay behind?

runtime->delay is now updated only when virtsnd_pcm_pb_pointer() runs.
During prepare, or during SNDRV_PCM_IOCTL_RESET inPREPARED or PAUSED
state, snd_pcm_lib_reset() does not call virtsnd_pcm_pb_pointer().  When
SNDRV_PCM_IOCTL_RESET is called in RUNNING state,
virtsnd_pcm_playback_reset() calls snd_pcm_lib_reset() before zeroing
vss->playback_latency_bytes, so virtsnd_pcm_pb_pointer() reloads the old
vss->playback_latency_bytes into runtime->delay during the reset.  In both
cases runtime->delay keeps the previous playback latency until the next
pointer update, and SNDRV_PCM_IOCTL_DELAY or SNDRV_PCM_IOCTL_STATUS
reports stale delay.

Clearing vss->playback_latency_bytes and runtime->delay before
snd_pcm_lib_reset(), and zeroing runtime->delay in
virtsnd_pcm_prepare_locked(), would keep both in sync.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261111000543.28550-1-mynameisjune111@gmail.com?part=16

      reply	other threads:[~2026-11-11  0:49 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-11  0:05 [PATCH v24 00/16] ALSA: virtio: serialize PCM recovery and preserve capture and playback progress Joonho Lee
2026-11-11  0:05 ` [PATCH v24 01/16] ALSA: pcm: mark stop-threshold accesses for capture policy sampling Joonho Lee
2026-11-11  0:05 ` [PATCH v24 02/16] ALSA: pcm: report partial progress under the stream lock Joonho Lee
2026-11-11  0:25   ` sashiko-bot
2026-11-11  0:05 ` [PATCH v24 03/16] ALSA: pcm: add an optional reset operation " Joonho Lee
2026-11-11  0:05 ` [PATCH v24 04/16] ALSA: pcm: notify drivers after linked prepare completes Joonho Lee
2026-11-11  0:05 ` [PATCH v24 05/16] ALSA: pcm: serialize linked buffer actions Joonho Lee
2026-11-11  0:05 ` [PATCH v24 06/16] ALSA: virtio: propagate playback send failures through ACK Joonho Lee
2026-11-11  0:34   ` sashiko-bot
2026-11-11  0:05 ` [PATCH v24 07/16] ALSA: virtio: Recover PCM state after a failed start Joonho Lee
2026-11-11  0:05 ` [PATCH v24 08/16] ALSA: virtio: Retain queued messages through device reset Joonho Lee
2026-11-11  0:05 ` [PATCH v24 09/16] ALSA: virtio: bound PCM transfers and retain DMA buffers Joonho Lee
2026-11-11  0:05 ` [PATCH v24 10/16] ALSA: virtio: Keep control payloads alive through DMA completion Joonho Lee
2026-11-11  0:05 ` [PATCH v24 11/16] ALSA: virtio: wait through signals for PCM teardown Joonho Lee
2026-11-11  0:28   ` sashiko-bot
2026-11-11  0:05 ` [PATCH v24 12/16] ALSA: virtio: use request-owned capture and serialize recovery Joonho Lee
2026-11-11  0:38   ` sashiko-bot
2026-11-11  0:05 ` [PATCH v24 13/16] ALSA: virtio: prioritize capture period work Joonho Lee
2026-11-11  0:05 ` [PATCH v24 14/16] docs: describe virtio-sound capture options Joonho Lee
2026-11-11  0:24   ` sashiko-bot
2026-11-11  0:05 ` [PATCH v24 15/16] ALSA: virtio: reject invalid playback completions Joonho Lee
2026-11-11  0:05 ` [PATCH v24 16/16] ALSA: virtio: preserve playback progress across pause Joonho Lee
2026-11-11  0:49   ` sashiko-bot [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=sashiko-outbox-208038@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=eperezma@redhat.com \
    --cc=linux-sound@vger.kernel.org \
    --cc=mst@redhat.com \
    --cc=mynameisjune111@gmail.com \
    --cc=sashiko-reviews@lists.linux.dev \
    --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