You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2026/10/22 02:21:09 UTC
(nuttx) 04/10: drivers/virtio-snd: limit the buffer count to the virtqueue size
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 2f098fbb1f2efdac3828e56622570f5c7076c1c9
Author: jinxiuxu <ji...@xiaomi.com>
AuthorDate: Wed May 21 15:27:41 2025 +0800
drivers/virtio-snd: limit the buffer count to the virtqueue size
Each period buffer uses three descriptors, so
CONFIG_DRIVERS_VIRTIO_SND_BUFFER_COUNT buffers may not fit in the
virtqueue. Use min(BUFFER_COUNT, vq_nentries / 3) periods and scale
the period size so the total buffered time stays the same. Log an
error if more buffers than that are ever queued.
Signed-off-by: jinxiuxu <ji...@xiaomi.com>
---
drivers/virtio/virtio-snd.c | 23 +++++++++++++++++++----
1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/drivers/virtio/virtio-snd.c b/drivers/virtio/virtio-snd.c
index 165dba9abdf..da74fd29b70 100644
--- a/drivers/virtio/virtio-snd.c
+++ b/drivers/virtio/virtio-snd.c
@@ -74,6 +74,7 @@ struct virtio_snd_dev_s
struct audio_lowerhalf_s dev;
uint32_t cache_buffers;
uint32_t period_bytes;
+ uint32_t period_count;
uint32_t frame_size;
uint32_t index;
bool running;
@@ -427,6 +428,12 @@ static int virtio_snd_send_pcm(FAR struct virtio_snd_dev_s *sdev,
virtqueue_kick(vq);
sdev->cache_buffers++;
+ if (sdev->cache_buffers > sdev->period_count)
+ {
+ vrterr("cache_buffers:%"PRIu32" > period_count:%"PRIu32"\n",
+ sdev->cache_buffers, sdev->period_count);
+ }
+
spin_unlock_irqrestore(&priv->lock, flags);
return OK;
@@ -571,8 +578,7 @@ static int virtio_snd_set_params(FAR struct virtio_snd_dev_s *sdev,
}
req->period_bytes = sdev->period_bytes;
- req->buffer_bytes = req->period_bytes *
- CONFIG_DRIVERS_VIRTIO_SND_BUFFER_COUNT;
+ req->buffer_bytes = req->period_bytes * sdev->period_count;
resp = virtio_malloc_buf(priv->vdev, sizeof(*resp), 16);
if (resp == NULL)
@@ -750,6 +756,11 @@ static int virtio_snd_configure(FAR struct audio_lowerhalf_s *dev,
#endif
{
FAR struct virtio_snd_dev_s *sdev = (FAR struct virtio_snd_dev_s *)dev;
+ FAR struct virtio_snd_s *priv = sdev->priv;
+ FAR struct virtio_snd_pcm_info *info = &priv->info[sdev->index];
+ int idx = info->direction == VIRTIO_SND_D_INPUT ?
+ VIRTIO_SND_VQ_RX : VIRTIO_SND_VQ_TX;
+ FAR struct virtqueue *vq = priv->vdev->vrings_info[idx].vq;
int ret = -ENOTTY;
uint32_t rate;
uint8_t bps;
@@ -767,9 +778,13 @@ static int virtio_snd_configure(FAR struct audio_lowerhalf_s *dev,
bps = caps->ac_controls.b[2];
ch = caps->ac_channels;
sdev->frame_size = ch * bps / 8;
+ sdev->period_count = MIN(CONFIG_DRIVERS_VIRTIO_SND_BUFFER_COUNT,
+ vq->vq_nentries / 3);
sdev->period_bytes =
virtio_snd_get_period_bytes(rate, ch, bps,
- CONFIG_DRIVERS_VIRTIO_SOUND_PERIOD_TIME);
+ CONFIG_DRIVERS_VIRTIO_SOUND_PERIOD_TIME *
+ CONFIG_DRIVERS_VIRTIO_SND_BUFFER_COUNT /
+ sdev->period_count);
vrtinfo("period_bytes:%"PRIu32"\n", sdev->period_bytes);
ret = virtio_snd_set_params(sdev, ch, rate, bps);
if (ret < 0)
@@ -1019,7 +1034,7 @@ static int virtio_snd_ioctl(FAR struct audio_lowerhalf_s *dev,
{
case AUDIOIOC_GETBUFFERINFO:
bufinfo = (FAR struct ap_buffer_info_s *)arg;
- bufinfo->nbuffers = CONFIG_DRIVERS_VIRTIO_SND_BUFFER_COUNT;
+ bufinfo->nbuffers = sdev->period_count;
bufinfo->buffer_size = sdev->period_bytes;
break;