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 <[email protected]> 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 <[email protected]> --- 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;
