virtqueue_add_packed() only supports virtual addresses, dma is completed
in virtqueue_add_packed().

In some scenarios (such as the AF_XDP scenario), the memory is allocated
and DMA is completed in advance, so it is necessary for us to support
passing the DMA address to virtqueue_add_packed().

This patch stipulates that if sg->dma_address is not NULL, use this
address as the DMA address. And record this information in extra->flags,
which can be skipped when executing dma unmap.

extra->flags |= VRING_DESC_F_PREDMA;

This relies on the previous patch, in the indirect scenario, for each
desc allocated, an extra is allocated at the same time.

Signed-off-by: Xuan Zhuo <[email protected]>
---
 drivers/virtio/virtio_ring.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index add8430d9678..e165bc2e1344 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -1010,6 +1010,9 @@ static void vring_unmap_extra_packed(const struct 
vring_virtqueue *vq,
                                 (flags & VRING_DESC_F_WRITE) ?
                                 DMA_FROM_DEVICE : DMA_TO_DEVICE);
        } else {
+               if (flags & VRING_DESC_F_PREDMA)
+                       return;
+
                dma_unmap_page(vring_dma_dev(vq),
                               extra->addr, extra->len,
                               (flags & VRING_DESC_F_WRITE) ?
@@ -1092,6 +1095,8 @@ static int virtqueue_add_indirect_packed(struct 
vring_virtqueue *vq,
                        extra->addr  = addr;
                        extra->len   = sg->length;
                        extra->flags = flags;
+                       if (sg_is_predma(sg))
+                               extra->flags |= VRING_DESC_F_PREDMA;
 
                        i++;
                }
@@ -1249,9 +1254,14 @@ static inline int virtqueue_add_packed(struct virtqueue 
*_vq,
                        if (unlikely(vq->use_dma_api)) {
                                vq->packed.desc_extra[curr].addr = addr;
                                vq->packed.desc_extra[curr].len = sg->length;
-                               vq->packed.desc_extra[curr].flags =
-                                       le16_to_cpu(flags);
                        }
+
+                       vq->packed.desc_extra[curr].flags = le16_to_cpu(flags);
+
+                       if (sg_is_predma(sg))
+                               vq->packed.desc_extra[curr].flags |=
+                                       VRING_DESC_F_PREDMA;
+
                        prev = curr;
                        curr = vq->packed.desc_extra[curr].next;
 
-- 
2.31.0

_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

Reply via email to