Commit 9dc6b944 authored by Jason Wang's avatar Jason Wang Committed by Michael S. Tsirkin
Browse files

virtio_ring: factor out split indirect detaching logic



Factor out the split indirect descriptor detaching logic in order to
allow it to be reused by the in order support.

Acked-by: default avatarEugenio Pérez <eperezma@redhat.com>
Reviewed-by: default avatarXuan Zhuo <xuanzhuo@linux.alibaba.com>
Signed-off-by: default avatarJason Wang <jasowang@redhat.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Message-Id: <20251230064649.55597-18-jasowang@redhat.com>
parent fa56d17b
Loading
Loading
Loading
Loading
+34 −28
Original line number Diff line number Diff line
@@ -775,11 +775,41 @@ static bool virtqueue_kick_prepare_split(struct vring_virtqueue *vq)
	return needs_kick;
}

static void detach_indirect_split(struct vring_virtqueue *vq,
				  unsigned int head)
{
	struct vring_desc_extra *extra = vq->split.desc_extra;
	struct vring_desc *indir_desc = vq->split.desc_state[head].indir_desc;
	unsigned int j;
	u32 len, num;

	/* Free the indirect table, if any, now that it's unmapped. */
	if (!indir_desc)
		return;
	len = vq->split.desc_extra[head].len;

	BUG_ON(!(vq->split.desc_extra[head].flags &
			VRING_DESC_F_INDIRECT));
	BUG_ON(len == 0 || len % sizeof(struct vring_desc));

	num = len / sizeof(struct vring_desc);

	extra = (struct vring_desc_extra *)&indir_desc[num];

	if (vq->use_map_api) {
		for (j = 0; j < num; j++)
			vring_unmap_one_split(vq, &extra[j]);
	}

	kfree(indir_desc);
	vq->split.desc_state[head].indir_desc = NULL;
}

static void detach_buf_split(struct vring_virtqueue *vq, unsigned int head,
			     void **ctx)
{
	struct vring_desc_extra *extra;
	unsigned int i, j;
	unsigned int i;
	__virtio16 nextflag = cpu_to_virtio16(vq->vq.vdev, VRING_DESC_F_NEXT);

	/* Clear data ptr. */
@@ -802,35 +832,11 @@ static void detach_buf_split(struct vring_virtqueue *vq, unsigned int head,
	/* Plus final descriptor */
	vq->vq.num_free++;

	if (vq->indirect) {
		struct vring_desc *indir_desc =
				vq->split.desc_state[head].indir_desc;
		u32 len, num;

		/* Free the indirect table, if any, now that it's unmapped. */
		if (!indir_desc)
			return;
		len = vq->split.desc_extra[head].len;

		BUG_ON(!(vq->split.desc_extra[head].flags &
				VRING_DESC_F_INDIRECT));
		BUG_ON(len == 0 || len % sizeof(struct vring_desc));

		num = len / sizeof(struct vring_desc);

		extra = (struct vring_desc_extra *)&indir_desc[num];

		if (vq->use_map_api) {
			for (j = 0; j < num; j++)
				vring_unmap_one_split(vq, &extra[j]);
		}

		kfree(indir_desc);
		vq->split.desc_state[head].indir_desc = NULL;
	} else if (ctx) {
	if (vq->indirect)
		detach_indirect_split(vq, head);
	else if (ctx)
		*ctx = vq->split.desc_state[head].indir_desc;
}
}

static bool virtqueue_poll_split(const struct vring_virtqueue *vq,
				 unsigned int last_used_idx)