From 9dc6b944f16c0904331903ba0ec36e558e1a3537 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Tue, 30 Dec 2025 14:46:47 +0800 Subject: [PATCH] virtio_ring: factor out split indirect detaching logic MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Factor out the split indirect descriptor detaching logic in order to allow it to be reused by the in order support. Acked-by: Eugenio Pérez Reviewed-by: Xuan Zhuo Signed-off-by: Jason Wang Signed-off-by: Michael S. Tsirkin Message-Id: <20251230064649.55597-18-jasowang@redhat.com> --- drivers/virtio/virtio_ring.c | 62 ++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 3389aad6f5a87..c0eaa907c67b3 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -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,34 +832,10 @@ 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, -- 2.47.3