diff --git a/drivers/virtio/virtio-rng.c b/drivers/virtio/virtio-rng.c index b13f5174f9b..3593726464c 100644 --- a/drivers/virtio/virtio-rng.c +++ b/drivers/virtio/virtio-rng.c @@ -28,6 +28,7 @@ #include #include +#include #include #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;