diff --git a/sound/virtio/virtio_pcm.h b/sound/virtio/virtio_pcm.h index 368dafa5df3f..8837dfc12828 100644 --- a/sound/virtio/virtio_pcm.h +++ b/sound/virtio/virtio_pcm.h @@ -118,6 +118,8 @@ int virtsnd_pcm_msg_alloc(struct virtio_pcm_substream *vss, void virtsnd_pcm_msg_free(struct virtio_pcm_substream *vss); +void virtsnd_pcm_msg_reset(struct virtio_pcm_substream *vss); + int virtsnd_pcm_msg_send(struct virtio_pcm_substream *vss, unsigned long offset, unsigned long bytes); diff --git a/sound/virtio/virtio_pcm_msg.c b/sound/virtio/virtio_pcm_msg.c index a5c4e7027717..72103f606716 100644 --- a/sound/virtio/virtio_pcm_msg.c +++ b/sound/virtio/virtio_pcm_msg.c @@ -182,6 +182,25 @@ void virtsnd_pcm_msg_free(struct virtio_pcm_substream *vss) vss->nmsgs = 0; } +/** + * virtsnd_pcm_msg_reset() - Reset the fill level of all I/O messages. + * @vss: VirtIO PCM substream. + * + * Messages that were only partially filled by the application when the + * substream was stopped are never sent to the device, so their length must be + * cleared before the substream is started again. + * + * Context: Any context. Takes and releases the VirtIO substream spinlock. + */ +void virtsnd_pcm_msg_reset(struct virtio_pcm_substream *vss) +{ + unsigned int i; + + guard(spinlock_irqsave)(&vss->lock); + for (i = 0; vss->msgs && i < vss->nmsgs; ++i) + vss->msgs[i]->length = 0; +} + /** * virtsnd_pcm_msg_send() - Send asynchronous I/O messages. * @vss: VirtIO PCM substream. diff --git a/sound/virtio/virtio_pcm_ops.c b/sound/virtio/virtio_pcm_ops.c index 1105e7ff3523..1091100a4c98 100644 --- a/sound/virtio/virtio_pcm_ops.c +++ b/sound/virtio/virtio_pcm_ops.c @@ -299,6 +299,7 @@ static int virtsnd_pcm_prepare(struct snd_pcm_substream *substream) vss->xfer_xrun = false; vss->suspended = false; vss->msg_count = 0; + virtsnd_pcm_msg_reset(vss); memset(&vss->pcm_indirect, 0, sizeof(vss->pcm_indirect)); vss->pcm_indirect.sw_buffer_size =