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
@ -872,6 +872,46 @@ static void virtqueue_packed_fill(VirtQueue *vq, const VirtQueueElement *elem,
|
||||
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,
|
||||
const VirtQueueElement *elem,
|
||||
unsigned int idx,
|
||||
@ -922,7 +962,9 @@ void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
|
||||
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);
|
||||
} else {
|
||||
virtqueue_split_fill(vq, elem, len, idx);
|
||||
|
Loading…
Reference in New Issue
Block a user