Hi Thomas,

> Subject: Re: [RFC 1/8] dma-buf: Add support for map/unmap APIs for
> interconnects
> 
> Hi, Vivek,
> 
> On Tue, 2025-10-14 at 00:08 -0700, Vivek Kasireddy wrote:
> > For the map operation, the dma-buf core will create an xarray but
> > the exporter is expected to populate it with the interconnect
> > specific addresses. And, similarly for unmap, the exporter is
> > expected to cleanup the individual entries of the xarray.
> >
> > Cc: Jason Gunthorpe <[email protected]>
> > Cc: Christian Koenig <[email protected]>
> > Cc: Sumit Semwal <[email protected]>
> > Cc: Thomas Hellström <[email protected]>
> > Cc: Simona Vetter <[email protected]>
> > Signed-off-by: Vivek Kasireddy <[email protected]>
> > ---
> >  drivers/dma-buf/dma-buf.c            | 68
> > ++++++++++++++++++++++++++++
> >  include/linux/dma-buf-interconnect.h | 29 ++++++++++++
> >  include/linux/dma-buf.h              | 11 +++++
> >  3 files changed, 108 insertions(+)
> >  create mode 100644 include/linux/dma-buf-interconnect.h
> >
> > diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
> > index 2bcf9ceca997..162642bd53e8 100644
> > --- a/drivers/dma-buf/dma-buf.c
> > +++ b/drivers/dma-buf/dma-buf.c
> > @@ -1612,6 +1612,74 @@ void dma_buf_vunmap_unlocked(struct
> dma_buf
> > *dmabuf, struct iosys_map *map)
> >  }
> >  EXPORT_SYMBOL_NS_GPL(dma_buf_vunmap_unlocked, "DMA_BUF");
> >
> > +struct dma_buf_ranges *
> > +dma_buf_map_interconnect(struct dma_buf_attachment *attach)
> 
> Even if this is an RFC, please add kerneldoc so that the way the
> interface is intended to be used becomes completely clear. Both for
> functions and structs.
Ok, will add documentation in the next version.

> 
> 
> > +{
> > +   const struct dma_buf_interconnect_ops *ic_ops;
> > +   struct dma_buf *dmabuf = attach->dmabuf;
> > +   struct dma_buf_ranges *ranges;
> > +   int ret;
> > +
> > +   might_sleep();
> > +
> > +   if (WARN_ON(!attach || !attach->dmabuf))
> > +           return ERR_PTR(-EINVAL);
> > +
> > +   if (!dma_buf_attachment_is_dynamic(attach))
> > +           return ERR_PTR(-EINVAL);
> > +
> > +   if (!attach->allow_ic)
> > +           return ERR_PTR(-EOPNOTSUPP);
> > +
> > +   dma_resv_assert_held(attach->dmabuf->resv);
> > +
> > +   ic_ops = dmabuf->ops->interconnect_ops;
> > +   if (!ic_ops || !ic_ops->map_interconnect)
> > +           return ERR_PTR(-EINVAL);
> > +
> > +   ranges = kzalloc(sizeof(*ranges), GFP_KERNEL);
> > +   if (!ranges)
> > +           return ERR_PTR(-ENOMEM);
> > +
> > +   xa_init(&ranges->ranges);
> > +   ret = ic_ops->map_interconnect(attach, ranges);
> > +   if (ret)
> > +           goto err_free_ranges;
> > +
> > +   return ranges;
> > +
> > +err_free_ranges:
> > +   xa_destroy(&ranges->ranges);
> > +   kfree(ranges);
> > +   return ERR_PTR(ret);
> > +}
> > +EXPORT_SYMBOL_NS_GPL(dma_buf_map_interconnect, "DMA_BUF");
> > +
> > +void dma_buf_unmap_interconnect(struct dma_buf_attachment *attach,
> > +                           struct dma_buf_ranges *ranges)
> > +{
> > +   const struct dma_buf_interconnect_ops *ic_ops;
> > +   struct dma_buf *dmabuf = attach->dmabuf;
> > +
> > +   if (WARN_ON(!attach || !attach->dmabuf || !ranges))
> > +           return;
> > +
> > +   if (!attach->allow_ic)
> > +           return;
> > +
> > +   ic_ops = dmabuf->ops->interconnect_ops;
> > +   if (!ic_ops || !ic_ops->unmap_interconnect)
> > +           return;
> > +
> > +   dma_resv_assert_held(attach->dmabuf->resv);
> > +
> > +   ic_ops->unmap_interconnect(attach, ranges);
> > +
> > +   xa_destroy(&ranges->ranges);
> > +   kfree(ranges);
> > +}
> > +EXPORT_SYMBOL_NS_GPL(dma_buf_unmap_interconnect, "DMA_BUF");
> > +
> >  #ifdef CONFIG_DEBUG_FS
> >  static int dma_buf_debug_show(struct seq_file *s, void *unused)
> >  {
> > diff --git a/include/linux/dma-buf-interconnect.h
> > b/include/linux/dma-buf-interconnect.h
> > new file mode 100644
> > index 000000000000..17504dea9691
> > --- /dev/null
> > +++ b/include/linux/dma-buf-interconnect.h
> > @@ -0,0 +1,29 @@
> > +/* SPDX-License-Identifier: MIT */
> > +
> > +#ifndef __DMA_BUF_INTERCONNECT_H__
> > +#define __DMA_BUF_INTERCONNECT_H__
> > +
> > +#include <linux/xarray.h>
> > +
> > +struct dma_buf_attachment;
> > +
> > +struct dma_buf_ranges {
> > +   struct xarray ranges;
> > +   unsigned int nranges;
> 
> IIUC this would replace the sg-table right?
Yes, that is the intended goal. 

> I guess Jason or Christian
> would need to comment on whether this is generic enough or whether it
> needs to be interconnect-dependent.
AFAIU, the individual entries of the xarray could be of any type that is
interconnect-specific and shared between exporter and importer.
For example, for IOV interconnect, I have picked struct range as the
type (to represent individual entries of the xarray) to share addresses
between exporter and importer.

> 
> > +};
> > +
> > +enum dma_buf_interconnect_type {
> > +   DMA_BUF_INTERCONNECT_NONE = 0,
> > +};
> 
> This calls for registering all known interconnects with the dma-buf
> layer even if the interconnects are completely driver-private. I'd
> suggest using a pointer to identify interconnect and whatever entity
> defines the interconnect provides a unique pointer. For globally
> visible interconnects this could be done in dma-buf.c or a dma-buf-
> interconnect.c
Thank you for your suggestion. I'll explore the idea in more detail.

> 
> > +
> > +struct dma_buf_interconnect {
> > +   enum dma_buf_interconnect_type type;
> > +};
> > +
> > +struct dma_buf_interconnect_ops {
> > +   int (*map_interconnect)(struct dma_buf_attachment *attach,
> > +                           struct dma_buf_ranges *ranges);
> > +   void (*unmap_interconnect)(struct dma_buf_attachment
> > *attach,
> > +                              struct dma_buf_ranges *ranges);
> > +};
> > +#endif
> > diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
> > index d58e329ac0e7..db91c67c00d6 100644
> > --- a/include/linux/dma-buf.h
> > +++ b/include/linux/dma-buf.h
> > @@ -23,6 +23,8 @@
> >  #include <linux/dma-fence.h>
> >  #include <linux/wait.h>
> >
> > +#include <linux/dma-buf-interconnect.h>
> > +
> >  struct device;
> >  struct dma_buf;
> >  struct dma_buf_attachment;
> > @@ -276,6 +278,8 @@ struct dma_buf_ops {
> >
> >     int (*vmap)(struct dma_buf *dmabuf, struct iosys_map *map);
> >     void (*vunmap)(struct dma_buf *dmabuf, struct iosys_map
> > *map);
> > +
> > +   const struct dma_buf_interconnect_ops *interconnect_ops;
> >  };
> >
> >  /**
> > @@ -502,7 +506,9 @@ struct dma_buf_attachment {
> >     struct device *dev;
> >     struct list_head node;
> >     bool peer2peer;
> > +   bool allow_ic;
> >     const struct dma_buf_attach_ops *importer_ops;
> > +   struct dma_buf_interconnect interconnect;
> 
> Hmm. Could we have a pointer to the interconnect here? Let's say the
> interconnect implementation would want to subclass with additional
> information?
Sure. I was going to do that in the next version.

Thanks,
Vivek

> 
> 
> >     void *importer_priv;
> >     void *priv;
> >  };
> > @@ -589,6 +595,11 @@ struct sg_table
> *dma_buf_map_attachment(struct
> > dma_buf_attachment *,
> >                                     enum dma_data_direction);
> >  void dma_buf_unmap_attachment(struct dma_buf_attachment *, struct
> > sg_table *,
> >                             enum dma_data_direction);
> > +
> > +struct dma_buf_ranges *dma_buf_map_interconnect(struct
> > dma_buf_attachment *);
> > +void dma_buf_unmap_interconnect(struct dma_buf_attachment *,
> > +                           struct dma_buf_ranges *);
> > +
> >  void dma_buf_move_notify(struct dma_buf *dma_buf);
> >  int dma_buf_begin_cpu_access(struct dma_buf *dma_buf,
> >                          enum dma_data_direction dir);
> 
> Thanks,
> Thomas
> 

Reply via email to