virtio-rng.c: add spin lock to fix get/add virtqueue buffer at the same time err

the virtqueue should be protected by the spinlock, because the virtqueues are used
both in worker and interrupt.

Signed-off-by: wangyongrong <wangyongrong@xiaomi.com>
This commit is contained in:
wangyongrong 2024-06-07 16:43:52 +08:00 committed by Xiang Xiao
parent f6f151a8e1
commit 735dc6e2bf

View file

@ -28,6 +28,7 @@
#include <nuttx/fs/fs.h>
#include <nuttx/semaphore.h>
#include <nuttx/spinlock.h>
#include <nuttx/virtio/virtio.h>
#include "virtio-rng.h"
@ -50,6 +51,7 @@ struct virtio_rng_priv_s
{
FAR struct virtio_device *vdev;
char name[NAME_MAX];
spinlock_t lock;
};
/****************************************************************************
@ -106,16 +108,25 @@ static int g_virtio_rng_idx = 0;
static void virtio_rng_done(FAR struct virtqueue *vq)
{
FAR struct virtio_rng_priv_s *priv = vq->vq_dev->priv;
FAR struct virtio_rng_cookie_s *cookie;
irqstate_t flags;
uint32_t len;
/* Get the buffer, virtqueue_get_buffer() return the cookie added in
* virtio_rng_read().
*/
cookie = virtqueue_get_buffer(vq, &len, NULL);
if (cookie != NULL)
for (; ; )
{
flags = spin_lock_irqsave(&priv->lock);
cookie = virtqueue_get_buffer(vq, &len, NULL);
spin_unlock_irqrestore(&priv->lock, flags);
if (cookie == NULL)
{
break;
}
/* Assign the return length */
cookie->len = len;
@ -137,6 +148,7 @@ static ssize_t virtio_rng_read(FAR struct file *filep, FAR char *buffer,
FAR struct virtqueue *vq = priv->vdev->vrings_info[0].vq;
struct virtio_rng_cookie_s cookie;
struct virtqueue_buf vb;
irqstate_t flags;
int ret;
/* Init the cookie */
@ -155,15 +167,18 @@ static ssize_t virtio_rng_read(FAR struct file *filep, FAR char *buffer,
return -ENOMEM;
}
flags = spin_lock_irqsave(&priv->lock);
ret = virtqueue_add_buffer(vq, &vb, 0, 1, &cookie);
if (ret < 0)
{
spin_unlock_irqrestore(&priv->lock, flags);
return ret;
}
/* Notify the other side to process the added virtqueue buffer */
virtqueue_kick(vq);
spin_unlock_irqrestore(&priv->lock, flags);
/* Wait fot completion */
@ -191,6 +206,7 @@ static int virtio_rng_probe(FAR struct virtio_device *vdev)
return -ENOMEM;
}
spin_lock_init(&priv->lock);
priv->vdev = vdev;
vdev->priv = priv;