Hi Matt,

> Subject: Re: [RFC v2 4/8] vfio/pci/dmabuf: Add support for IOV interconnect
> 
> On Sun, Oct 26, 2025 at 09:44:16PM -0700, Vivek Kasireddy wrote:
> > Add support for IOV interconnect by provding ops for map/unmap and
> > match interconnect. Note that the xarray is populated with entries
> > of type struct range. The range type contains the start and end
> > addresses of the memory region.
> >
> > 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/vfio/pci/vfio_pci_dmabuf.c | 135
> ++++++++++++++++++++++++++++-
> >  1 file changed, 134 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/vfio/pci/vfio_pci_dmabuf.c
> b/drivers/vfio/pci/vfio_pci_dmabuf.c
> > index eaba010777f3..d2b7b5410e5a 100644
> > --- a/drivers/vfio/pci/vfio_pci_dmabuf.c
> > +++ b/drivers/vfio/pci/vfio_pci_dmabuf.c
> 
> In drm-tip vfio_pci_dmabuf.c does not exist as a file? Is this series
> based on another series / branch where vfio_pci_dmabuf.c hasn't made it
> into drm-tip yet?
That file is part of [1] which hasn't been merged yet. The last patch in [1]
adds the dmabuf feature to vfio-pci.

[1]: https://lore.kernel.org/dri-devel/[email protected]/

Thanks,
Vivek

> 
> Matt
> 
> > @@ -4,6 +4,7 @@
> >  #include <linux/dma-buf.h>
> >  #include <linux/pci-p2pdma.h>
> >  #include <linux/dma-resv.h>
> > +#include <linux/range.h>
> >
> >  #include "vfio_pci_priv.h"
> >
> > @@ -16,15 +17,132 @@ struct vfio_pci_dma_buf {
> >     size_t size;
> >     struct phys_vec *phys_vec;
> >     struct p2pdma_provider *provider;
> > +   struct dma_buf_interconnect_match *ic_match;
> >     u32 nr_ranges;
> >     u8 revoked : 1;
> >  };
> >
> > +static int
> > +vfio_pci_create_match(struct vfio_pci_dma_buf *priv,
> > +                     struct vfio_device_feature_dma_buf *dma_buf)
> > +{
> > +   struct dma_buf_interconnect_match *ic_match;
> > +
> > +   ic_match = kzalloc(sizeof(*ic_match), GFP_KERNEL);
> > +   if (!ic_match)
> > +           return -ENOMEM;
> > +
> > +   ic_match->dev = &priv->vdev->pdev->dev;
> > +   ic_match->bar = dma_buf->region_index;
> > +
> > +   priv->ic_match = ic_match;
> > +   return 0;
> > +}
> > +
> > +static int vfio_pci_map_iov_interconnect(struct vfio_pci_dma_buf *priv,
> > +                                    struct xarray *ranges)
> > +{
> > +   struct phys_vec *phys_vec = priv->phys_vec;
> > +   struct range *range;
> > +   unsigned long i;
> > +   void *entry;
> > +   int ret;
> > +
> > +   range = kmalloc_array(priv->nr_ranges, sizeof(*range), GFP_KERNEL);
> > +   if (!range)
> > +           return -ENOMEM;
> > +
> > +   for (i = 0; i < priv->nr_ranges; i++) {
> > +           entry = &range[i];
> > +           range[i].start = phys_vec[i].paddr;
> > +           range[i].end = phys_vec[i].paddr + phys_vec[i].len - 1;
> > +
> > +           entry = xa_store(ranges, i, entry, GFP_KERNEL);
> > +           if (xa_is_err(entry)) {
> > +                   ret = xa_err(entry);
> > +                   goto err_free_range;
> > +           }
> > +   }
> > +   return 0;
> > +
> > +err_free_range:
> > +   kfree(range);
> > +   return ret;
> > +}
> > +
> > +static int vfio_pci_map_interconnect(struct dma_buf_attachment
> *attachment,
> > +                                struct dma_buf_ranges *ranges)
> > +{
> > +   const struct dma_buf_interconnect *ic = attachment->ic_match->type;
> > +   struct vfio_pci_dma_buf *priv = attachment->dmabuf->priv;
> > +   int ret = -EINVAL;
> > +
> > +   ranges->nranges = priv->nr_ranges;
> > +
> > +   if (ic == iov_interconnect)
> > +           ret = vfio_pci_map_iov_interconnect(priv, &ranges->ranges);
> > +
> > +   return ret;
> > +}
> > +
> > +static void vfio_pci_unmap_interconnect(struct dma_buf_attachment
> *attachment,
> > +                                   struct dma_buf_ranges *ranges)
> > +{
> > +   void *entry;
> > +
> > +   entry = xa_load(&ranges->ranges, 0);
> > +   kfree(entry);
> > +}
> > +
> > +static bool
> > +vfio_pci_match_iov_interconnect(const struct
> dma_buf_interconnect_match *exp,
> > +                           const struct dma_buf_interconnect_match
> *imp)
> > +{
> > +   struct pci_dev *exp_pdev = to_pci_dev(exp->dev);
> > +   struct pci_dev *imp_pdev = to_pci_dev(imp->dev);
> > +
> > +   return imp_pdev == pci_physfn(exp_pdev) && imp->bar == exp->bar;
> > +}
> > +
> > +static bool
> > +vfio_pci_match_interconnect(const struct dma_buf_interconnect_match
> *exp,
> > +                       const struct dma_buf_interconnect_match *imp)
> > +{
> > +   const struct dma_buf_interconnect *ic = exp->type;
> > +
> > +   if (ic == iov_interconnect)
> > +           return vfio_pci_match_iov_interconnect(exp, imp);
> > +
> > +   return false;
> > +}
> > +
> > +static bool
> > +vfio_pci_match_interconnects(struct vfio_pci_dma_buf *priv,
> > +                        struct dma_buf_attachment *attachment)
> > +{
> > +   const struct dma_buf_attach_ops *aops = attachment->importer_ops;
> > +   const struct dma_buf_interconnect_match supports_ics[] = {
> > +           MATCH_INTERCONNECT(iov_interconnect,
> > +                              priv->ic_match->dev, priv->ic_match->bar),
> > +   };
> > +
> > +   if (attachment->allow_ic) {
> > +           if (aops->supports_interconnects(attachment, supports_ics,
> > +                                            ARRAY_SIZE(supports_ics)))
> > +                   return true;
> > +   }
> > +   return false;
> > +}
> > +
> >  static int vfio_pci_dma_buf_attach(struct dma_buf *dmabuf,
> >                                struct dma_buf_attachment *attachment)
> >  {
> >     struct vfio_pci_dma_buf *priv = dmabuf->priv;
> >
> > +   if (vfio_pci_match_interconnects(priv, attachment)) {
> > +           return 0;
> > +   }
> > +
> >     if (!attachment->peer2peer)
> >             return -EOPNOTSUPP;
> >
> > @@ -189,6 +307,7 @@ vfio_pci_dma_buf_map(struct dma_buf_attachment
> *attachment,
> >     return ERR_PTR(ret);
> >  }
> >
> > +
> >  static void vfio_pci_dma_buf_unmap(struct dma_buf_attachment
> *attachment,
> >                                struct sg_table *sgt,
> >                                enum dma_data_direction dir)
> > @@ -228,15 +347,23 @@ static void vfio_pci_dma_buf_release(struct
> dma_buf *dmabuf)
> >             vfio_device_put_registration(&priv->vdev->vdev);
> >     }
> >     kfree(priv->phys_vec);
> > +   kfree(priv->ic_match);
> >     kfree(priv);
> >  }
> >
> > +static const struct dma_buf_interconnect_ops vfio_pci_interconnect_ops =
> {
> > +   .match_interconnect = vfio_pci_match_interconnect,
> > +   .map_interconnect = vfio_pci_map_interconnect,
> > +   .unmap_interconnect = vfio_pci_unmap_interconnect,
> > +};
> > +
> >  static const struct dma_buf_ops vfio_pci_dmabuf_ops = {
> >     .attach = vfio_pci_dma_buf_attach,
> >     .detach = vfio_pci_dma_buf_detach,
> >     .map_dma_buf = vfio_pci_dma_buf_map,
> >     .release = vfio_pci_dma_buf_release,
> >     .unmap_dma_buf = vfio_pci_dma_buf_unmap,
> > +   .interconnect_ops = &vfio_pci_interconnect_ops,
> >  };
> >
> >  static void dma_ranges_to_p2p_phys(struct vfio_pci_dma_buf *priv,
> > @@ -365,6 +492,10 @@ int vfio_pci_core_feature_dma_buf(struct
> vfio_pci_core_device *vdev, u32 flags,
> >             goto err_free_phys;
> >     }
> >
> > +   ret = vfio_pci_create_match(priv, &get_dma_buf);
> > +   if (ret)
> > +           goto err_dev_put;
> > +
> >     exp_info.ops = &vfio_pci_dmabuf_ops;
> >     exp_info.size = priv->size;
> >     exp_info.flags = get_dma_buf.open_flags;
> > @@ -373,7 +504,7 @@ int vfio_pci_core_feature_dma_buf(struct
> vfio_pci_core_device *vdev, u32 flags,
> >     priv->dmabuf = dma_buf_export(&exp_info);
> >     if (IS_ERR(priv->dmabuf)) {
> >             ret = PTR_ERR(priv->dmabuf);
> > -           goto err_dev_put;
> > +           goto err_free_iov;
> >     }
> >
> >     /* dma_buf_put() now frees priv */
> > @@ -391,6 +522,8 @@ int vfio_pci_core_feature_dma_buf(struct
> vfio_pci_core_device *vdev, u32 flags,
> >      */
> >     return dma_buf_fd(priv->dmabuf, get_dma_buf.open_flags);
> >
> > +err_free_iov:
> > +   kfree(priv->ic_match);
> >  err_dev_put:
> >     vfio_device_put_registration(&vdev->vdev);
> >  err_free_phys:
> > --
> > 2.50.1
> >

Reply via email to