mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-08 18:23:57 -06:00
virtio: virtqueue_ordered_fill - VIRTIO_F_IN_ORDER support
Add VIRTIO_F_IN_ORDER feature support for the virtqueue_fill operation. The goal of the virtqueue_ordered_fill operation when the VIRTIO_F_IN_ORDER feature has been negotiated is to search for this now-used element, set its length, and mark the element as filled in the VirtQueue's used_elems array. By marking the element as filled, it will indicate that this element has been processed and is ready to be flushed, so long as the element is in-order. Reviewed-by: Eugenio Pérez <eperezma@redhat.com> Signed-off-by: Jonah Palmer <jonah.palmer@oracle.com> Message-Id: <20240710125522.4168043-4-jonah.palmer@oracle.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
2256e8482b
commit
b44135daa3
1 changed files with 43 additions and 1 deletions
|
@ -872,6 +872,46 @@ static void virtqueue_packed_fill(VirtQueue *vq, const VirtQueueElement *elem,
|
||||||
vq->used_elems[idx].ndescs = elem->ndescs;
|
vq->used_elems[idx].ndescs = elem->ndescs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void virtqueue_ordered_fill(VirtQueue *vq, const VirtQueueElement *elem,
|
||||||
|
unsigned int len)
|
||||||
|
{
|
||||||
|
unsigned int i, steps, max_steps;
|
||||||
|
|
||||||
|
i = vq->used_idx % vq->vring.num;
|
||||||
|
steps = 0;
|
||||||
|
/*
|
||||||
|
* We shouldn't need to increase 'i' by more than the distance
|
||||||
|
* between used_idx and last_avail_idx.
|
||||||
|
*/
|
||||||
|
max_steps = (vq->last_avail_idx - vq->used_idx) % vq->vring.num;
|
||||||
|
|
||||||
|
/* Search for element in vq->used_elems */
|
||||||
|
while (steps <= max_steps) {
|
||||||
|
/* Found element, set length and mark as filled */
|
||||||
|
if (vq->used_elems[i].index == elem->index) {
|
||||||
|
vq->used_elems[i].len = len;
|
||||||
|
vq->used_elems[i].in_order_filled = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
i += vq->used_elems[i].ndescs;
|
||||||
|
steps += vq->used_elems[i].ndescs;
|
||||||
|
|
||||||
|
if (i >= vq->vring.num) {
|
||||||
|
i -= vq->vring.num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We should be able to find a matching VirtQueueElement in
|
||||||
|
* used_elems. If we don't, this is an error.
|
||||||
|
*/
|
||||||
|
if (steps >= max_steps) {
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR, "%s: %s cannot fill buffer id %u\n",
|
||||||
|
__func__, vq->vdev->name, elem->index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void virtqueue_packed_fill_desc(VirtQueue *vq,
|
static void virtqueue_packed_fill_desc(VirtQueue *vq,
|
||||||
const VirtQueueElement *elem,
|
const VirtQueueElement *elem,
|
||||||
unsigned int idx,
|
unsigned int idx,
|
||||||
|
@ -922,7 +962,9 @@ void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virtio_vdev_has_feature(vq->vdev, VIRTIO_F_RING_PACKED)) {
|
if (virtio_vdev_has_feature(vq->vdev, VIRTIO_F_IN_ORDER)) {
|
||||||
|
virtqueue_ordered_fill(vq, elem, len);
|
||||||
|
} else if (virtio_vdev_has_feature(vq->vdev, VIRTIO_F_RING_PACKED)) {
|
||||||
virtqueue_packed_fill(vq, elem, len, idx);
|
virtqueue_packed_fill(vq, elem, len, idx);
|
||||||
} else {
|
} else {
|
||||||
virtqueue_split_fill(vq, elem, len, idx);
|
virtqueue_split_fill(vq, elem, len, idx);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue