virtio devices: update virtqueue operate buffer add lock API

1. Use the virtqueue_xxx_lock() api;
2. Add spinlock for some virtio and vhost drivers that do not
   use spinlock to protect the virtqueues;

Signed-off-by: Yongrong Wang <wangyongrong@xiaomi.com>
This commit is contained in:
Yongrong Wang 2024-07-15 16:56:55 +08:00 committed by Xiang Xiao
parent fd9efb600c
commit 26ac220810
8 changed files with 53 additions and 35 deletions

View File

@ -43,6 +43,7 @@ struct vhost_rng_priv_s
{
FAR struct vhost_device *hdev;
struct work_s work;
spinlock_t lock;
};
/****************************************************************************
@ -82,11 +83,13 @@ static void vhost_rng_work(FAR void *arg)
FAR struct vhost_rng_priv_s *priv = arg;
FAR struct virtqueue *vq;
FAR void *buf;
irqstate_t flags;
uint16_t idx;
uint32_t len;
ssize_t ret;
vq = priv->hdev->vrings_info[0].vq;
flags = spin_lock_irqsave(&priv->lock);
for (; ; )
{
buf = virtqueue_get_available_buffer(vq, &idx, &len);
@ -95,6 +98,7 @@ static void vhost_rng_work(FAR void *arg)
break;
}
spin_unlock_irqrestore(&priv->lock, flags);
ret = getrandom(buf, len, 0);
if (ret < 0)
{
@ -102,9 +106,12 @@ static void vhost_rng_work(FAR void *arg)
ret = 0;
}
flags = spin_lock_irqsave(&priv->lock);
virtqueue_add_consumed_buffer(vq, idx, (uint32_t)ret);
virtqueue_kick(vq);
}
spin_unlock_irqrestore(&priv->lock, flags);
}
/****************************************************************************
@ -139,6 +146,7 @@ static int vhost_rng_probe(FAR struct vhost_device *hdev)
return -ENOMEM;
}
spin_lock_init(&priv->lock);
priv->hdev = hdev;
hdev->priv = priv;

View File

@ -194,15 +194,12 @@ static void virtio_blk_wait_complete(FAR struct virtqueue *vq,
{
FAR struct virtio_blk_priv_s *priv = vq->vq_dev->priv;
FAR sem_t *sem;
irqstate_t flags;
if (up_interrupt_context())
{
for (; ; )
{
flags = spin_lock_irqsave(&priv->lock);
sem = virtqueue_get_buffer(vq, NULL, NULL);
spin_unlock_irqrestore(&priv->lock, flags);
sem = virtqueue_get_buffer_lock(vq, NULL, NULL, &priv->lock);
if (sem == respsem)
{
break;
@ -266,7 +263,7 @@ static ssize_t virtio_blk_rdwr(FAR struct virtio_blk_priv_s *priv,
if (up_interrupt_context())
{
virtqueue_disable_cb(vq);
virtqueue_disable_cb_lock(vq, &priv->lock);
}
flags = spin_lock_irqsave(&priv->lock);
@ -294,7 +291,7 @@ static ssize_t virtio_blk_rdwr(FAR struct virtio_blk_priv_s *priv,
err:
if (up_interrupt_context())
{
virtqueue_enable_cb(vq);
virtqueue_enable_cb_lock(vq, &priv->lock);
}
return ret >= 0 ? nsectors : ret;
@ -487,13 +484,10 @@ static void virtio_blk_done(FAR struct virtqueue *vq)
{
FAR struct virtio_blk_priv_s *priv = vq->vq_dev->priv;
FAR sem_t *respsem;
irqstate_t flags;
for (; ; )
{
flags = spin_lock_irqsave(&priv->lock);
respsem = virtqueue_get_buffer(vq, NULL, NULL);
spin_unlock_irqrestore(&priv->lock, flags);
respsem = virtqueue_get_buffer_lock(vq, NULL, NULL, &priv->lock);
if (respsem == NULL)
{
break;

View File

@ -63,6 +63,7 @@ struct virtio_gpu_priv_s
fb_coord_t yres; /* Vertical resolution in pixel rows */
fb_coord_t stride; /* Width of a row in bytes */
uint8_t display; /* Display number */
spinlock_t lock; /* Lock */
};
struct virtio_gpu_cookie_s
@ -141,6 +142,8 @@ static int virtio_gpu_send_cmd(FAR struct virtqueue *vq,
FAR struct virtqueue_buf *buf_list,
int readable, int writable, FAR void *buf)
{
FAR struct virtio_gpu_priv_s *priv = vq->vq_dev->priv;
irqstate_t flags;
int ret;
if (writable > 0)
@ -152,12 +155,18 @@ static int virtio_gpu_send_cmd(FAR struct virtqueue *vq,
nxsem_init(&sem, 0, 0);
cookie.blocking = true;
cookie.p = &sem;
flags = spin_lock_irqsave(&priv->lock);
ret = virtqueue_add_buffer(vq, buf_list, readable, writable, &cookie);
if (ret >= 0)
{
virtqueue_kick(vq);
spin_unlock_irqrestore(&priv->lock, flags);
nxsem_wait(&sem);
}
else
{
spin_unlock_irqrestore(&priv->lock, flags);
}
nxsem_destroy(&sem);
}
@ -175,14 +184,17 @@ static int virtio_gpu_send_cmd(FAR struct virtqueue *vq,
{
cookie->blocking = false;
cookie->p = buf;
flags = spin_lock_irqsave(&priv->lock);
ret = virtqueue_add_buffer(vq, buf_list, readable, writable,
cookie);
if (ret >= 0)
{
virtqueue_kick(vq);
spin_unlock_irqrestore(&priv->lock, flags);
}
else
{
spin_unlock_irqrestore(&priv->lock, flags);
kmm_free(cookie);
}
}
@ -202,9 +214,11 @@ static int virtio_gpu_send_cmd(FAR struct virtqueue *vq,
static void virtio_gpu_done(FAR struct virtqueue *vq)
{
FAR struct virtio_gpu_priv_s *priv = vq->vq_dev->priv;
FAR struct virtio_gpu_cookie_s *cookie;
while ((cookie = virtqueue_get_buffer(vq, NULL, NULL)) != NULL)
while ((cookie =
virtqueue_get_buffer_lock(vq, NULL, NULL, &priv->lock)) != NULL)
{
if (cookie->blocking)
{
@ -229,6 +243,7 @@ static int virtio_gpu_init(FAR struct virtio_gpu_priv_s *priv,
vq_callback callbacks[VIRTIO_GPU_NUM];
int ret;
spin_lock_init(&priv->lock);
priv->vdev = vdev;
vdev->priv = priv;

View File

@ -62,6 +62,7 @@ struct virtio_input_priv
struct virtio_input_event evt[VIRTIO_INPUT_EVT_NUM];
size_t evtnum; /* Input event number */
struct work_s work; /* Supports the interrupt handling "bottom half" */
spinlock_t lock; /* Lock */
virtio_send_event_handler eventhandler;
union
@ -253,7 +254,7 @@ static void virtio_input_worker(FAR void *arg)
uint32_t len;
while ((evt = (FAR struct virtio_input_event *)
virtqueue_get_buffer(vq, &len, NULL)) != NULL)
virtqueue_get_buffer_lock(vq, &len, NULL, &priv->lock)) != NULL)
{
vrtinfo("virtio_input_worker (type,code,value)-(%d,%d,%" PRIu32 ").\n",
evt->type, evt->code, evt->value);
@ -262,10 +263,10 @@ static void virtio_input_worker(FAR void *arg)
vb.buf = evt;
vb.len = len;
virtqueue_add_buffer(vq, &vb, 0, 1, vb.buf);
virtqueue_add_buffer_lock(vq, &vb, 0, 1, vb.buf, &priv->lock);
}
virtqueue_kick(vq);
virtqueue_kick_lock(vq, &priv->lock);
}
/****************************************************************************
@ -300,10 +301,10 @@ static void virtio_input_fill_event(FAR struct virtio_input_priv *priv)
{
vb.buf = &priv->evt[i];
vb.len = sizeof(struct virtio_input_event);
virtqueue_add_buffer(vq, &vb, 0, 1, vb.buf);
virtqueue_add_buffer_lock(vq, &vb, 0, 1, vb.buf, &priv->lock);
}
virtqueue_kick(vq);
virtqueue_kick_lock(vq, &priv->lock);
}
/****************************************************************************
@ -377,6 +378,7 @@ static int virtio_input_probe(FAR struct virtio_device *vdev)
return -ENOMEM;
}
spin_lock_init(&priv->lock);
priv->vdev = vdev;
vdev->priv = priv;

View File

@ -110,18 +110,15 @@ 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
/* Get the buffer, virtqueue_get_buffer_lock() return the cookie added in
* virtio_rng_read().
*/
for (; ; )
{
flags = spin_lock_irqsave(&priv->lock);
cookie = virtqueue_get_buffer(vq, &len, NULL);
spin_unlock_irqrestore(&priv->lock, flags);
cookie = virtqueue_get_buffer_lock(vq, &len, NULL, &priv->lock);
if (cookie == NULL)
{
break;

View File

@ -105,14 +105,11 @@ 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;
for (; ; )
{
flags = spin_lock_irqsave(&priv->lock);
cookie = virtqueue_get_buffer(vq, &len, NULL);
spin_unlock_irqrestore(&priv->lock, flags);
cookie = virtqueue_get_buffer_lock(vq, &len, NULL, &priv->lock);
if (cookie == NULL)
{
break;

View File

@ -419,14 +419,11 @@ static void virtio_serial_rxready(FAR struct virtqueue *vq)
{
FAR struct virtio_serial_priv_s *priv = vq->vq_dev->priv;
FAR struct uart_dmaxfer_s *xfer;
irqstate_t flags;
uint32_t len;
/* Received some data, call uart_recvchars_done() */
flags = spin_lock_irqsave(&priv->lock);
xfer = virtqueue_get_buffer(vq, &len, NULL);
spin_unlock_irqrestore(&priv->lock, flags);
xfer = virtqueue_get_buffer_lock(vq, &len, NULL, &priv->lock);
if (xfer == NULL)
{
return;
@ -448,14 +445,11 @@ static void virtio_serial_rxready(FAR struct virtqueue *vq)
static void virtio_serial_txdone(FAR struct virtqueue *vq)
{
FAR struct virtio_serial_priv_s *priv = vq->vq_dev->priv;
irqstate_t flags;
uintptr_t len;
/* Call uart_xmitchars_done to notify the upperhalf */
flags = spin_lock_irqsave(&priv->lock);
len = (uintptr_t)virtqueue_get_buffer(vq, NULL, NULL);
spin_unlock_irqrestore(&priv->lock, flags);
len = (uintptr_t)virtqueue_get_buffer_lock(vq, NULL, NULL, &priv->lock);
priv->udev.dmatx.nbytes = len;
uart_xmitchars_done(&priv->udev);

View File

@ -86,6 +86,7 @@ struct virtio_snd_s
FAR struct virtio_snd_dev_s *dev;
FAR struct virtio_snd_pcm_info *info;
struct virtio_snd_config config;
spinlock_t lock;
};
/****************************************************************************
@ -332,11 +333,13 @@ virtio_snd_get_support_formats(FAR const struct virtio_snd_pcm_info *info,
static void virtio_snd_pcm_notify_cb(FAR struct virtqueue *vq)
{
FAR struct virtio_snd_s *priv = vq->vq_dev->priv;
for (; ; )
{
FAR struct virtio_snd_buffer_s *buf;
FAR struct virtio_snd_dev_s *sdev;
buf = virtqueue_get_buffer(vq, NULL, NULL);
buf = virtqueue_get_buffer_lock(vq, NULL, NULL, &priv->lock);
if (buf == NULL)
{
break;
@ -360,9 +363,10 @@ static void virtio_snd_pcm_notify_cb(FAR struct virtqueue *vq)
static void virtio_snd_ctl_notify_cb(FAR struct virtqueue *vq)
{
FAR struct virtio_snd_s *priv = vq->vq_dev->priv;
FAR sem_t *ctl_sem;
ctl_sem = virtqueue_get_buffer(vq, NULL, NULL);
ctl_sem = virtqueue_get_buffer_lock(vq, NULL, NULL, &priv->lock);
nxsem_post(ctl_sem);
}
@ -388,6 +392,7 @@ static int virtio_snd_send_pcm(FAR struct virtio_snd_dev_s *sdev,
VIRTIO_SND_VQ_RX : VIRTIO_SND_VQ_TX;
FAR struct virtqueue *vq = priv->vdev->vrings_info[idx].vq;
struct virtqueue_buf vb[3];
irqstate_t flags;
vb[0].buf = &buf->xfer;
vb[0].len = sizeof(buf->xfer);
@ -396,6 +401,7 @@ static int virtio_snd_send_pcm(FAR struct virtio_snd_dev_s *sdev,
vb[2].buf = &buf->status;
vb[2].len = sizeof(buf->status);
flags = spin_lock_irqsave(&priv->lock);
if (idx == VIRTIO_SND_VQ_RX)
{
virtqueue_add_buffer(vq, vb, 1, 2, buf);
@ -406,6 +412,7 @@ static int virtio_snd_send_pcm(FAR struct virtio_snd_dev_s *sdev,
}
virtqueue_kick(vq);
spin_unlock_irqrestore(&priv->lock, flags);
sdev->cache_buffers++;
return OK;
@ -422,13 +429,16 @@ static int virtio_snd_send_ctl(FAR struct virtio_snd_s *priv,
{
FAR struct virtqueue *vq =
priv->vdev->vrings_info[VIRTIO_SND_VQ_CONTROL].vq;
irqstate_t flags;
sem_t ctl_sem;
int ret;
nxsem_init(&ctl_sem, 0, 0);
flags = spin_lock_irqsave(&priv->lock);
virtqueue_add_buffer(vq, vb, readable, writable, &ctl_sem);
virtqueue_kick(vq);
spin_unlock_irqrestore(&priv->lock, flags);
ret = nxsem_wait_uninterruptible(&ctl_sem);
nxsem_destroy(&ctl_sem);
@ -1199,6 +1209,7 @@ static int virtio_snd_probe(FAR struct virtio_device *vdev)
return -ENOMEM;
}
spin_lock_init(&priv->lock);
priv->vdev = vdev;
vdev->priv = priv;