From 377f184019921ec0854dd5dbfd8b861d1b689274 Mon Sep 17 00:00:00 2001 From: wangyongrong Date: Thu, 13 Jun 2024 09:51:16 +0800 Subject: [PATCH] virtio-rpmb.c: add spin lock for virtqueue add/get buffer Virtqueeus are used in both user thread and interrupt, so add spinlock to proetect them. Signed-off-by: wangyongrong --- drivers/virtio/virtio-rpmb.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/virtio/virtio-rpmb.c b/drivers/virtio/virtio-rpmb.c index d944875d02..eb8e688d4a 100644 --- a/drivers/virtio/virtio-rpmb.c +++ b/drivers/virtio/virtio-rpmb.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -49,6 +50,7 @@ struct virtio_rpmb_priv_s /* The virtio device we're associated with */ FAR struct virtio_device *vdev; + spinlock_t lock; }; struct virtio_rpmb_cookie_s @@ -101,12 +103,21 @@ static const struct file_operations g_virtio_rpmb_ops = static void virtio_rpmb_done(FAR struct virtqueue *vq) { + FAR struct virtio_rpmb_priv_s *priv = vq->vq_dev->priv; FAR struct virtio_rpmb_cookie_s *cookie; + irqstate_t flags; uint32_t len; - 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; @@ -128,6 +139,7 @@ static int virtio_rpmb_transact(FAR struct virtio_rpmb_priv_s *priv, { FAR struct virtqueue *vq = priv->vdev->vrings_info[0].vq; struct virtio_rpmb_cookie_s cookie; + irqstate_t flags; int ret; /* Init the cookie */ @@ -139,15 +151,18 @@ static int virtio_rpmb_transact(FAR struct virtio_rpmb_priv_s *priv, * cookie. (virtqueue_get_buffer() will return cookie). */ + flags = spin_lock_irqsave(&priv->lock); ret = virtqueue_add_buffer(vq, vb, out, in, &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 */ @@ -189,6 +204,7 @@ static int virtio_rpmb_init(FAR struct virtio_rpmb_priv_s *priv, priv->vdev = vdev; vdev->priv = priv; + spin_lock_init(&priv->lock); /* Initialize the virtio device */