mirror of
https://github.com/qemu/qemu.git
synced 2024-11-24 19:33:39 +08:00
libvhost-user: Introduce vu_queue_map_desc()
Introduce vu_queue_map_desc() which should be independent with vu_queue_pop(); Signed-off-by: Xie Yongji <xieyongji@baidu.com> Signed-off-by: Zhang Yu <zhangyu31@baidu.com> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-Id: <20190228085355.9614-4-xieyongji@baidu.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
792468cc6f
commit
f7671f3d49
@ -1848,49 +1848,20 @@ virtqueue_alloc_element(size_t sz,
|
||||
return elem;
|
||||
}
|
||||
|
||||
void *
|
||||
vu_queue_pop(VuDev *dev, VuVirtq *vq, size_t sz)
|
||||
static void *
|
||||
vu_queue_map_desc(VuDev *dev, VuVirtq *vq, unsigned int idx, size_t sz)
|
||||
{
|
||||
unsigned int i, head, max, desc_len;
|
||||
struct vring_desc *desc = vq->vring.desc;
|
||||
uint64_t desc_addr, read_len;
|
||||
unsigned int desc_len;
|
||||
unsigned int max = vq->vring.num;
|
||||
unsigned int i = idx;
|
||||
VuVirtqElement *elem;
|
||||
unsigned out_num, in_num;
|
||||
unsigned int out_num = 0, in_num = 0;
|
||||
struct iovec iov[VIRTQUEUE_MAX_SIZE];
|
||||
struct vring_desc desc_buf[VIRTQUEUE_MAX_SIZE];
|
||||
struct vring_desc *desc;
|
||||
int rc;
|
||||
|
||||
if (unlikely(dev->broken) ||
|
||||
unlikely(!vq->vring.avail)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (vu_queue_empty(dev, vq)) {
|
||||
return NULL;
|
||||
}
|
||||
/* Needed after virtio_queue_empty(), see comment in
|
||||
* virtqueue_num_heads(). */
|
||||
smp_rmb();
|
||||
|
||||
/* When we start there are none of either input nor output. */
|
||||
out_num = in_num = 0;
|
||||
|
||||
max = vq->vring.num;
|
||||
if (vq->inuse >= vq->vring.num) {
|
||||
vu_panic(dev, "Virtqueue size exceeded");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!virtqueue_get_head(dev, vq, vq->last_avail_idx++, &head)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (vu_has_feature(dev, VIRTIO_RING_F_EVENT_IDX)) {
|
||||
vring_set_avail_event(vq, vq->last_avail_idx);
|
||||
}
|
||||
|
||||
i = head;
|
||||
desc = vq->vring.desc;
|
||||
if (desc[i].flags & VRING_DESC_F_INDIRECT) {
|
||||
if (desc[i].len % sizeof(struct vring_desc)) {
|
||||
vu_panic(dev, "Invalid size for indirect buffer table");
|
||||
@ -1942,12 +1913,13 @@ vu_queue_pop(VuDev *dev, VuVirtq *vq, size_t sz)
|
||||
} while (rc == VIRTQUEUE_READ_DESC_MORE);
|
||||
|
||||
if (rc == VIRTQUEUE_READ_DESC_ERROR) {
|
||||
vu_panic(dev, "read descriptor error");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Now copy what we have collected and mapped */
|
||||
elem = virtqueue_alloc_element(sz, out_num, in_num);
|
||||
elem->index = head;
|
||||
elem->index = idx;
|
||||
for (i = 0; i < out_num; i++) {
|
||||
elem->out_sg[i] = iov[i];
|
||||
}
|
||||
@ -1955,6 +1927,48 @@ vu_queue_pop(VuDev *dev, VuVirtq *vq, size_t sz)
|
||||
elem->in_sg[i] = iov[out_num + i];
|
||||
}
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
void *
|
||||
vu_queue_pop(VuDev *dev, VuVirtq *vq, size_t sz)
|
||||
{
|
||||
unsigned int head;
|
||||
VuVirtqElement *elem;
|
||||
|
||||
if (unlikely(dev->broken) ||
|
||||
unlikely(!vq->vring.avail)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (vu_queue_empty(dev, vq)) {
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
* Needed after virtio_queue_empty(), see comment in
|
||||
* virtqueue_num_heads().
|
||||
*/
|
||||
smp_rmb();
|
||||
|
||||
if (vq->inuse >= vq->vring.num) {
|
||||
vu_panic(dev, "Virtqueue size exceeded");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!virtqueue_get_head(dev, vq, vq->last_avail_idx++, &head)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (vu_has_feature(dev, VIRTIO_RING_F_EVENT_IDX)) {
|
||||
vring_set_avail_event(vq, vq->last_avail_idx);
|
||||
}
|
||||
|
||||
elem = vu_queue_map_desc(dev, vq, head, sz);
|
||||
|
||||
if (!elem) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vq->inuse++;
|
||||
|
||||
return elem;
|
||||
|
Loading…
Reference in New Issue
Block a user