[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CACGkMEt8djYRdSvwBK7QGoNV1iG-8nafOox0=pt6ix1m0NOZtA@mail.gmail.com>
Date: Thu, 23 Jan 2025 09:51:17 +0800
From: Jason Wang <jasowang@...hat.com>
To: Eugenio Pérez <eperezma@...hat.com>
Cc: linux-kernel@...r.kernel.org, mst@...hat.com,
Hanna Reitz <hreitz@...hat.com>, Stefano Garzarella <sgarzare@...hat.com>,
Xuan Zhuo <xuanzhuo@...ux.alibaba.com>, Vivek Goyal <vgoyal@...hat.com>,
Miklos Szeredi <miklos@...redi.hu>, German Maglione <gmaglione@...hat.com>,
Stefan Hajnoczi <stefanha@...hat.com>, virtualization@...ts.linux.dev
Subject: Re: [RFC 2/5] virtio_ring: introduce virtqueue_map/unmap_sgs()
On Thu, Jan 23, 2025 at 12:32 AM Eugenio Pérez <eperezma@...hat.com> wrote:
>
> From: Jason Wang <jasowang@...hat.com>
>
> Introduce new virtqueue DMA operations which allows the drivers that
> want to make use of the premapping API but operate at the sg level.
>
> Note that we still follow the assumtions if virtqueue_add() so
> dma_map_sg() is not used. This could be optimized in the future.
> Signed-off-by: Jason Wang <jasowang@...hat.com>
> Signed-off-by: Eugenio Pérez <eperezma@...hat.com>
> --
> Eugenio's changes: Remove blank
> TODO: Should we call directly dma_map instead of this? XDP do the direct
> call.
Note that we should have an indirection layer as the device is not
necessarily DMA capable.
And we probably need to rename the virtqueue_dma_map_XXX() to
virtqueue_map_XXX()
Thanks
> ---
> drivers/virtio/virtio_ring.c | 128 +++++++++++++++++++++++++++++++----
> include/linux/virtio.h | 10 +++
> 2 files changed, 125 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> index fdd2d2b07b5a..05729bc5cbb1 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -359,6 +359,26 @@ static struct device *vring_dma_dev(const struct vring_virtqueue *vq)
> return vq->dma_dev;
> }
>
> +static int __vring_map_one_sg(const struct vring_virtqueue *vq,
> + struct scatterlist *sg,
> + enum dma_data_direction direction,
> + dma_addr_t *addr)
> +{
> + /*
> + * We can't use dma_map_sg, because we don't use scatterlists in
> + * the way it expects (we don't guarantee that the scatterlist
> + * will exist for the lifetime of the mapping).
> + */
> + *addr = dma_map_page(vring_dma_dev(vq),
> + sg_page(sg), sg->offset, sg->length,
> + direction);
> +
> + if (dma_mapping_error(vring_dma_dev(vq), *addr))
> + return -ENOMEM;
> +
> + return 0;
> +}
> +
> /* Map one sg entry. */
> static int vring_map_one_sg(const struct vring_virtqueue *vq, struct scatterlist *sg,
> enum dma_data_direction direction, dma_addr_t *addr,
> @@ -383,19 +403,7 @@ static int vring_map_one_sg(const struct vring_virtqueue *vq, struct scatterlist
> return 0;
> }
>
> - /*
> - * We can't use dma_map_sg, because we don't use scatterlists in
> - * the way it expects (we don't guarantee that the scatterlist
> - * will exist for the lifetime of the mapping).
> - */
> - *addr = dma_map_page(vring_dma_dev(vq),
> - sg_page(sg), sg->offset, sg->length,
> - direction);
> -
> - if (dma_mapping_error(vring_dma_dev(vq), *addr))
> - return -ENOMEM;
> -
> - return 0;
> + return __vring_map_one_sg(vq, sg, direction, addr);
> }
>
> static dma_addr_t vring_map_single(const struct vring_virtqueue *vq,
> @@ -526,6 +534,100 @@ static inline unsigned int virtqueue_add_desc_split(struct virtqueue *vq,
> return next;
> }
>
> +void virtqueue_unmap_sgs(struct virtqueue *_vq,
> + struct scatterlist *sgs[],
> + unsigned int out_sgs,
> + unsigned int in_sgs)
> +{
> + struct vring_virtqueue *vq = to_vvq(_vq);
> + struct scatterlist *sg;
> + int n;
> +
> + for (n = 0; n < out_sgs; n++) {
> + for (sg = sgs[n]; sg; sg = sg_next(sg)) {
> + dma_unmap_page(vring_dma_dev(vq),
> + sg_dma_address(sg),
> + sg->length,
> + DMA_TO_DEVICE);
> + }
> + }
> +
> + for (; n < (out_sgs + in_sgs); n++) {
> + for (sg = sgs[n]; sg; sg = sg_next(sg)) {
> + dma_unmap_page(vring_dma_dev(vq),
> + sg_dma_address(sg),
> + sg->length,
> + DMA_FROM_DEVICE);
> + }
> + }
> +}
> +EXPORT_SYMBOL_GPL(virtqueue_unmap_sgs);
> +
> +int virtqueue_map_sgs(struct virtqueue *_vq,
> + struct scatterlist *sgs[],
> + unsigned int out_sgs,
> + unsigned int in_sgs)
> +{
> + struct vring_virtqueue *vq = to_vvq(_vq);
> + int i, n, mapped_sg = 0;
> + struct scatterlist *sg;
> +
> + for (n = 0; n < out_sgs; n++) {
> + for (sg = sgs[n]; sg; sg = sg_next(sg)) {
> + dma_addr_t addr;
> +
> + if (__vring_map_one_sg(vq, sg, DMA_TO_DEVICE, &addr))
> + goto unmap_release;
> +
> + sg_dma_address(sg) = addr;
> + mapped_sg++;
> + }
> + }
> +
> + for (; n < (out_sgs + in_sgs); n++) {
> + for (sg = sgs[n]; sg; sg = sg_next(sg)) {
> + dma_addr_t addr;
> +
> + if (__vring_map_one_sg(vq, sg, DMA_FROM_DEVICE, &addr))
> + goto unmap_release;
> +
> + sg_dma_address(sg) = addr;
> + mapped_sg++;
> + }
> + }
> +
> + return 0;
> +
> +unmap_release:
> + i = 0;
> +
> + for (n = 0; n < out_sgs; n++) {
> + for (sg = sgs[n]; sg; sg = sg_next(sg)) {
> + if (i++ == mapped_sg)
> + goto out;
> + dma_unmap_page(vring_dma_dev(vq),
> + sg_dma_address(sg),
> + sg->length,
> + DMA_TO_DEVICE);
> + }
> + }
> +
> + for (; n < (out_sgs + in_sgs); n++) {
> + for (sg = sgs[n]; sg; sg = sg_next(sg)) {
> +
> + if (i++ == mapped_sg)
> + goto out;
> + dma_unmap_page(vring_dma_dev(vq),
> + sg_dma_address(sg),
> + sg->length,
> + DMA_FROM_DEVICE);
> + }
> + }
> +out:
> + return -ENOMEM;
> +}
> +EXPORT_SYMBOL_GPL(virtqueue_map_sgs);
> +
> static inline int virtqueue_add_split(struct virtqueue *_vq,
> struct scatterlist *sgs[],
> unsigned int total_sg,
> diff --git a/include/linux/virtio.h b/include/linux/virtio.h
> index dd88682e27e3..28db998d691e 100644
> --- a/include/linux/virtio.h
> +++ b/include/linux/virtio.h
> @@ -67,6 +67,16 @@ int virtqueue_add_outbuf_premapped(struct virtqueue *vq,
> void *data,
> gfp_t gfp);
>
> +int virtqueue_map_sgs(struct virtqueue *_vq,
> + struct scatterlist *sgs[],
> + unsigned int out_sgs,
> + unsigned int in_sgs);
> +
> +void virtqueue_unmap_sgs(struct virtqueue *_vq,
> + struct scatterlist *sgs[],
> + unsigned int out_sgs,
> + unsigned int in_sgs);
> +
> int virtqueue_add_sgs(struct virtqueue *vq,
> struct scatterlist *sgs[],
> unsigned int out_sgs,
> --
> 2.48.1
>
Powered by blists - more mailing lists