From 78f2a0ff00f4ca588e65c1e61df4d66fc21a4035 Mon Sep 17 00:00:00 2001 From: Bowen Wang Date: Mon, 4 Nov 2024 10:26:52 +0800 Subject: [PATCH] virtqueue: add virtqueue_get_next_avail_buffer() API In virtio device side, we always need to get the next avaiable buffer based on current buffer index. So add this API for convinience use. For example, virtio blk driver origanize the buffer: +----------+ | Reqeust | (Flags: Read | Next) +----------+ | Buffer | (Flags: Read/Write | Next) +----------+ | Response | (Flags: Write) +----------+ For the virtio blk device size, we need get the Buffer and Response buffer based on the Request buffer index. Signed-off-by: Bowen Wang Signed-off-by: Yongrong Wang --- lib/include/openamp/virtqueue.h | 15 +++++++++++++++ lib/virtio/virtqueue.c | 22 ++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/lib/include/openamp/virtqueue.h b/lib/include/openamp/virtqueue.h index 819439871..cf2e01c1e 100644 --- a/lib/include/openamp/virtqueue.h +++ b/lib/include/openamp/virtqueue.h @@ -292,6 +292,21 @@ void *virtqueue_get_buffer(struct virtqueue *vq, uint32_t *len, uint16_t *idx); void *virtqueue_get_available_buffer(struct virtqueue *vq, uint16_t *avail_idx, uint32_t *len); +/** + * @internal + * + * @brief Returns next available buffer from VirtIO queue + * + * @param vq Pointer to VirtIO queue control block + * @param idx Index used in vring desc table + * @param next_idx Pointer to index of next buffer in vring desc table + * @param next_len Length of next buffer in vring desc table + * + * @return Pointer to next available buffer + */ +void *virtqueue_get_next_avail_buffer(struct virtqueue *vq, uint16_t idx, + uint16_t *next_idx, uint32_t *next_len); + /** * @internal * diff --git a/lib/virtio/virtqueue.c b/lib/virtio/virtqueue.c index 363fda8a4..be3ddc126 100644 --- a/lib/virtio/virtqueue.c +++ b/lib/virtio/virtqueue.c @@ -231,6 +231,28 @@ void *virtqueue_get_available_buffer(struct virtqueue *vq, uint16_t *avail_idx, return buffer; } +void *virtqueue_get_next_avail_buffer(struct virtqueue *vq, uint16_t idx, + uint16_t *next_idx, uint32_t *next_len) +{ + FAR void *buffer; + uint16_t next; + + VRING_INVALIDATE(vq->vq_ring.desc[idx], sizeof(struct vring_desc)); + if (!(vq->vq_ring.desc[idx].flags & VRING_DESC_F_NEXT)) + return NULL; + + next = vq->vq_ring.desc[idx].next; + if (next_idx) + *next_idx = next; + + VRING_INVALIDATE(vq->vq_ring.desc[next], sizeof(struct vring_desc)); + buffer = virtqueue_phys_to_virt(vq, vq->vq_ring.desc[next].addr); + if (next_len) + *next_len = vq->vq_ring.desc[next].len; + + return buffer; +} + int virtqueue_add_consumed_buffer(struct virtqueue *vq, uint16_t head_idx, uint32_t len) {