This code path is modified to handle in order devices. Abstract here so we can generalize on the caller.
Signed-off-by: Eugenio Pérez <[email protected]> --- hw/virtio/vhost-shadow-virtqueue.c | 45 +++++++++++++++++++----------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c index 7adacd4f542a..e7e3c9155cd0 100644 --- a/hw/virtio/vhost-shadow-virtqueue.c +++ b/hw/virtio/vhost-shadow-virtqueue.c @@ -444,6 +444,25 @@ static void vhost_svq_disable_notification(VhostShadowVirtqueue *svq) } } +/* + * Gets the next buffer id and moves forward the used idx, so the next time + * SVQ calls this function will get the next one. + * + * @svq: Shadow VirtQueue + * @len: Consumed length by the device. + * + * Return the next descriptor consumed by the device. + */ +static uint16_t vhost_svq_get_last_used_split(VhostShadowVirtqueue *svq, + uint32_t *len) +{ + const vring_used_t *used = svq->vring.used; + uint16_t last_used = svq->last_used_idx++ & (svq->vring.num - 1); + + *len = le32_to_cpu(used->ring[last_used].len); + return le32_to_cpu(used->ring[last_used].id); +} + static uint16_t vhost_svq_last_desc_of_chain(const VhostShadowVirtqueue *svq, uint16_t num, uint16_t i) { @@ -458,8 +477,6 @@ G_GNUC_WARN_UNUSED_RESULT static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq, uint32_t *len) { - const vring_used_t *used = svq->vring.used; - vring_used_elem_t used_elem; uint16_t last_used, last_used_chain, num; if (!vhost_svq_more_used(svq)) { @@ -468,33 +485,29 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq, /* Only get used array entries after they have been exposed by dev */ smp_rmb(); - last_used = svq->last_used_idx & (svq->vring.num - 1); - used_elem.id = le32_to_cpu(used->ring[last_used].id); - used_elem.len = le32_to_cpu(used->ring[last_used].len); + last_used = vhost_svq_get_last_used_split(svq, len); - svq->last_used_idx++; - if (unlikely(used_elem.id >= svq->vring.num)) { + if (unlikely(last_used >= svq->vring.num)) { qemu_log_mask(LOG_GUEST_ERROR, "Device %s says index %u is used", - svq->vdev->name, used_elem.id); + svq->vdev->name, last_used); return NULL; } - if (unlikely(!svq->desc_state[used_elem.id].ndescs)) { + if (unlikely(!svq->desc_state[last_used].ndescs)) { qemu_log_mask(LOG_GUEST_ERROR, "Device %s says index %u is used, but it was not available", - svq->vdev->name, used_elem.id); + svq->vdev->name, last_used); return NULL; } - num = svq->desc_state[used_elem.id].ndescs; - svq->desc_state[used_elem.id].ndescs = 0; - last_used_chain = vhost_svq_last_desc_of_chain(svq, num, used_elem.id); + num = svq->desc_state[last_used].ndescs; + svq->desc_state[last_used].ndescs = 0; + last_used_chain = vhost_svq_last_desc_of_chain(svq, num, last_used); svq->desc_state[last_used_chain].next = svq->free_head; - svq->free_head = used_elem.id; + svq->free_head = last_used; svq->num_free += num; - *len = used_elem.len; - return g_steal_pointer(&svq->desc_state[used_elem.id].elem); + return g_steal_pointer(&svq->desc_state[last_used].elem); } /** -- 2.53.0
