aboutgitcodebugslistschat
diff options
context:
space:
mode:
-rw-r--r--virtio.c29
-rw-r--r--virtio.h4
-rw-r--r--vu_common.c14
3 files changed, 32 insertions, 15 deletions
diff --git a/virtio.c b/virtio.c
index 447137e..a671163 100644
--- a/virtio.c
+++ b/virtio.c
@@ -428,12 +428,18 @@ static bool virtqueue_map_desc(const struct vu_dev *dev,
* @vq: Virtqueue
* @idx: First descriptor ring entry to map
* @elem: Virtqueue element to store descriptor ring iov
+ * @in_sg: Incoming iovec array for device-writable descriptors
+ * @max_in_sg: Maximum number of entries in @in_sg
+ * @out_sg: Outgoing iovec array for device-readable descriptors
+ * @max_out_sg: Maximum number of entries in @out_sg
*
* Return: -1 if there is an error, 0 otherwise
*/
static int vu_queue_map_desc(const struct vu_dev *dev,
struct vu_virtq *vq, unsigned int idx,
- struct vu_virtq_element *elem)
+ struct vu_virtq_element *elem,
+ struct iovec *in_sg, size_t max_in_sg,
+ struct iovec *out_sg, size_t max_out_sg)
{
const struct vring_desc *desc = vq->vring.desc;
struct vring_desc desc_buf[VIRTQUEUE_MAX_SIZE];
@@ -470,16 +476,16 @@ static int vu_queue_map_desc(const struct vu_dev *dev,
/* Collect all the descriptors */
do {
if (le16toh(desc[i].flags) & VRING_DESC_F_WRITE) {
- if (!virtqueue_map_desc(dev, &in_num, elem->in_sg,
- elem->in_num,
+ if (!virtqueue_map_desc(dev, &in_num, in_sg,
+ max_in_sg,
le64toh(desc[i].addr),
le32toh(desc[i].len)))
return -1;
} else {
if (in_num)
die("Incorrect order for descriptors");
- if (!virtqueue_map_desc(dev, &out_num, elem->out_sg,
- elem->out_num,
+ if (!virtqueue_map_desc(dev, &out_num, out_sg,
+ max_out_sg,
le64toh(desc[i].addr),
le32toh(desc[i].len))) {
return -1;
@@ -496,7 +502,9 @@ static int vu_queue_map_desc(const struct vu_dev *dev,
die("vhost-user: Failed to read descriptor list");
elem->index = idx;
+ elem->in_sg = in_sg;
elem->in_num = in_num;
+ elem->out_sg = out_sg;
elem->out_num = out_num;
return 0;
@@ -507,11 +515,17 @@ static int vu_queue_map_desc(const struct vu_dev *dev,
* @dev: Vhost-user device
* @vq: Virtqueue
* @elem: Virtqueue element to fill with the entry information
+ * @in_sg: Incoming iovec array for device-writable descriptors
+ * @max_in_sg: Maximum number of entries in @in_sg
+ * @out_sg: Outgoing iovec array for device-readable descriptors
+ * @max_out_sg: Maximum number of entries in @out_sg
*
* Return: -1 if there is an error, 0 otherwise
*/
int vu_queue_pop(const struct vu_dev *dev, struct vu_virtq *vq,
- struct vu_virtq_element *elem)
+ struct vu_virtq_element *elem,
+ struct iovec *in_sg, size_t max_in_sg,
+ struct iovec *out_sg, size_t max_out_sg)
{
unsigned int head;
int ret;
@@ -535,7 +549,8 @@ int vu_queue_pop(const struct vu_dev *dev, struct vu_virtq *vq,
if (vu_has_feature(dev, VIRTIO_RING_F_EVENT_IDX))
vring_set_avail_event(vq, vq->last_avail_idx);
- ret = vu_queue_map_desc(dev, vq, head, elem);
+ ret = vu_queue_map_desc(dev, vq, head, elem, in_sg, max_in_sg,
+ out_sg, max_out_sg);
if (ret < 0)
return ret;
diff --git a/virtio.h b/virtio.h
index d04bbe8..c7e447d 100644
--- a/virtio.h
+++ b/virtio.h
@@ -188,7 +188,9 @@ static inline bool vu_has_protocol_feature(const struct vu_dev *vdev,
void vu_queue_notify(const struct vu_dev *dev, struct vu_virtq *vq);
int vu_queue_pop(const struct vu_dev *dev, struct vu_virtq *vq,
- struct vu_virtq_element *elem);
+ struct vu_virtq_element *elem,
+ struct iovec *in_sg, size_t max_in_sg,
+ struct iovec *out_sg, size_t max_out_sg);
void vu_queue_detach_element(struct vu_virtq *vq);
void vu_queue_unpop(struct vu_virtq *vq);
bool vu_queue_rewind(struct vu_virtq *vq, unsigned int num);
diff --git a/vu_common.c b/vu_common.c
index 5f2ce18..4d809ac 100644
--- a/vu_common.c
+++ b/vu_common.c
@@ -91,7 +91,11 @@ int vu_collect(const struct vu_dev *vdev, struct vu_virtq *vq,
struct iovec *iov;
int ret;
- ret = vu_queue_pop(vdev, vq, &elem[elem_cnt]);
+ ret = vu_queue_pop(vdev, vq, &elem[elem_cnt],
+ elem[elem_cnt].in_sg,
+ elem[elem_cnt].in_num,
+ elem[elem_cnt].out_sg,
+ elem[elem_cnt].out_num);
if (ret < 0)
break;
@@ -178,12 +182,8 @@ static void vu_handle_tx(struct vu_dev *vdev, int index,
int ret;
struct iov_tail data;
- elem[count].out_num = VU_MAX_TX_BUFFER_NB;
- elem[count].out_sg = &out_sg[out_sg_count];
- elem[count].in_num = 0;
- elem[count].in_sg = NULL;
-
- ret = vu_queue_pop(vdev, vq, &elem[count]);
+ ret = vu_queue_pop(vdev, vq, &elem[count], NULL, 0,
+ &out_sg[out_sg_count], VU_MAX_TX_BUFFER_NB);
if (ret < 0)
break;
out_sg_count += elem[count].out_num;