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 > >
