]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
virtio_ring: factor out split indirect detaching logic
authorJason Wang <jasowang@redhat.com>
Tue, 30 Dec 2025 06:46:47 +0000 (14:46 +0800)
committerMichael S. Tsirkin <mst@redhat.com>
Wed, 31 Dec 2025 10:39:18 +0000 (05:39 -0500)
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 <eperezma@redhat.com>
Reviewed-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20251230064649.55597-18-jasowang@redhat.com>

drivers/virtio/virtio_ring.c

index 3389aad6f5a87d4b16284fe6779bdae93e0f4e2f..c0eaa907c67b368b6c210dbab45f30f9604483b8 100644 (file)
@@ -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,