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:
parent
fd9efb600c
commit
26ac220810
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue