Thread (21 messages) flat view 21 messages, 2 authors, 8d ago

Re: [PATCH v5 17/18] dma-buf: Let importers ask how peer-to-peer traffic is routed

From: Christian König <christian.koenig@amd.com>
Date: 2026-09-11 07:52:07
Also in: dri-devel, kvm, linux-doc, linux-iommu, linux-media, linux-pci, lkml

On 9/10/26 13:32, Leon Romanovsky wrote:
From: Leon Romanovsky <leonro@nvidia.com>

Exporters keep the &struct p2pdma_provider in their own private data and
hand it to dma_buf_phys_vec_to_sgt() on every map. An importer cannot reach
it, so it has no way to learn how its own peer-to-peer traffic would be
routed before it programs its hardware.
Why should that be interesting to importers?

In general importers should just consome the data provided by a DMA-buf and don't participate in any way in the decision how that data is made available.
 
Publish the provider through &struct dma_buf_export_info instead,
That is a very bad idea and not even remotely acceptable.

This needs to be a callback instead if that should really fly.

Regards,
Christian.
quoted hunk ↗ jump to hunk
and add
dma_buf_p2pdma_map_type() for importers to query it by TLP class. It is
fixed at export time, so dma_buf_phys_vec_to_sgt() no longer needs it as an
argument and the two exporters no longer need a copy of it.

Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
 drivers/dma-buf/dma-buf-mapping.c                 | 41 +++++++++++++++++++----
 drivers/dma-buf/dma-buf.c                         |  1 +
 drivers/infiniband/core/uverbs.h                  |  1 -
 drivers/infiniband/core/uverbs_std_types_dmabuf.c |  7 ++--
 drivers/vfio/pci/vfio_pci_dmabuf.c                |  8 ++---
 include/linux/dma-buf-mapping.h                   |  4 ++-
 include/linux/dma-buf.h                           |  5 +++
 7 files changed, 49 insertions(+), 18 deletions(-)
diff --git a/drivers/dma-buf/dma-buf-mapping.c b/drivers/dma-buf/dma-buf-mapping.c
index 794acff2546a..8b431000e906 100644
--- a/drivers/dma-buf/dma-buf-mapping.c
+++ b/drivers/dma-buf/dma-buf-mapping.c
@@ -6,6 +6,32 @@
 #include <linux/dma-buf-mapping.h>
 #include <linux/dma-resv.h>
 
+/**
+ * dma_buf_p2pdma_map_type - How peer-to-peer traffic to a buffer is routed
+ * @attach:	attachment of the importer that will issue the traffic
+ * @tlp_flags:	&enum pci_p2pdma_tlp_flags describing the TLPs it will issue
+ *
+ * Reports how the PCIe fabric routes @tlp_flags traffic between the buffer
+ * behind @attach and the importer attached to it, so that an importer can
+ * choose the TLP attributes that earn it a direct route before it programs
+ * its hardware.
+ *
+ * Return: the mapping type for @tlp_flags traffic, or PCI_P2PDMA_MAP_NONE
+ * when the exporter named no &struct p2pdma_provider and nothing is known
+ * about the route.
+ */
+enum pci_p2pdma_map_type
+dma_buf_p2pdma_map_type(struct dma_buf_attachment *attach,
+			unsigned int tlp_flags)
+{
+	if (!attach->dmabuf->provider)
+		return PCI_P2PDMA_MAP_NONE;
+
+	return pci_p2pdma_map_type_tlp(attach->dmabuf->provider, attach->dev,
+				       tlp_flags);
+}
+EXPORT_SYMBOL_NS_GPL(dma_buf_p2pdma_map_type, "DMA_BUF");
+
 static struct scatterlist *fill_sg_entry(struct scatterlist *sgl, size_t length,
 					 dma_addr_t addr)
 {
@@ -71,7 +97,6 @@ struct dma_buf_dma {
  * from arrays of physical vectors. This funciton is intended for MMIO memory
  * only.
  * @attach:	[in]	attachment whose scatterlist is to be returned
- * @provider:	[in]	p2pdma provider
  * @phys_vec:	[in]	array of physical vectors
  * @nr_ranges:	[in]	number of entries in phys_vec array
  * @size:	[in]	total size of phys_vec
@@ -85,16 +110,17 @@ struct dma_buf_dma {
  *
  * A mapping must be unmapped by using dma_buf_free_sgt().
  *
- * NOTE: This function is intended for exporters. If direct traffic routing is
- * mandatory exporter should call routing pci_p2pdma_map_type() before calling
- * this function.
+ * NOTE: This function is intended for exporters, and works on MMIO memory
+ * only, so &dma_buf.provider must have been set at export time. If direct
+ * traffic routing is mandatory the exporter should call
+ * pci_p2pdma_map_type() before calling this function.
  */
 struct sg_table *dma_buf_phys_vec_to_sgt(struct dma_buf_attachment *attach,
-					 struct p2pdma_provider *provider,
 					 struct phys_vec *phys_vec,
 					 size_t nr_ranges, size_t size,
 					 enum dma_data_direction dir)
 {
+	struct p2pdma_provider *provider;
 	unsigned int nents, mapped_len = 0;
 	struct dma_buf_dma *dma;
 	struct scatterlist *sgl;
@@ -104,10 +130,11 @@ struct sg_table *dma_buf_phys_vec_to_sgt(struct dma_buf_attachment *attach,
 
 	dma_resv_assert_held(attach->dmabuf->resv);
 
-	if (WARN_ON(!attach || !attach->dmabuf || !provider))
-		/* This function is supposed to work on MMIO memory only */
+	if (WARN_ON(!attach || !attach->dmabuf || !attach->dmabuf->provider))
 		return ERR_PTR(-EINVAL);
 
+	provider = attach->dmabuf->provider;
+
 	dma = kzalloc_obj(*dma);
 	if (!dma)
 		return ERR_PTR(-ENOMEM);
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index d504c636dc29..c2b9944e9659 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -747,6 +747,7 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
 	dmabuf->size = exp_info->size;
 	dmabuf->exp_name = exp_info->exp_name;
 	dmabuf->owner = exp_info->owner;
+	dmabuf->provider = exp_info->provider;
 	spin_lock_init(&dmabuf->name_lock);
 	init_waitqueue_head(&dmabuf->poll);
 	dmabuf->cb_in.poll = dmabuf->cb_out.poll = &dmabuf->poll;
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index c64dd6b94e10..fbdac18b69ca 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -139,7 +139,6 @@ struct ib_uverbs_dmabuf_file {
 	struct list_head dmabufs_elm;
 	struct rdma_user_mmap_entry *mmap_entry;
 	struct phys_vec phys_vec;
-	struct p2pdma_provider *provider;
 	struct kref kref;
 	struct completion comp;
 	u8 revoked :1;
diff --git a/drivers/infiniband/core/uverbs_std_types_dmabuf.c b/drivers/infiniband/core/uverbs_std_types_dmabuf.c
index 2411ebee69e2..94d3719a34da 100644
--- a/drivers/infiniband/core/uverbs_std_types_dmabuf.c
+++ b/drivers/infiniband/core/uverbs_std_types_dmabuf.c
@@ -33,9 +33,8 @@ uverbs_dmabuf_map(struct dma_buf_attachment *attachment,
 	if (priv->revoked)
 		return ERR_PTR(-ENODEV);
 
-	ret = dma_buf_phys_vec_to_sgt(attachment, priv->provider,
-				      &priv->phys_vec, 1, priv->phys_vec.len,
-				      dir);
+	ret = dma_buf_phys_vec_to_sgt(attachment, &priv->phys_vec, 1,
+				      priv->phys_vec.len, dir);
 	if (IS_ERR(ret))
 		return ret;
 
@@ -108,7 +107,7 @@ static int UVERBS_HANDLER(UVERBS_METHOD_DMABUF_ALLOC)(
 		return -EINVAL;
 
 	ret = ib_dev->ops.mmap_get_pfns(mmap_entry, &uverbs_dmabuf->phys_vec,
-					&uverbs_dmabuf->provider);
+					&exp_info.provider);
 	if (ret)
 		goto err;
 
diff --git a/drivers/vfio/pci/vfio_pci_dmabuf.c b/drivers/vfio/pci/vfio_pci_dmabuf.c
index c16f460c01d6..10f47992e7f5 100644
--- a/drivers/vfio/pci/vfio_pci_dmabuf.c
+++ b/drivers/vfio/pci/vfio_pci_dmabuf.c
@@ -15,7 +15,6 @@ struct vfio_pci_dma_buf {
 	struct list_head dmabufs_elm;
 	size_t size;
 	struct phys_vec *phys_vec;
-	struct p2pdma_provider *provider;
 	u32 nr_ranges;
 	struct kref kref;
 	struct completion comp;
@@ -59,9 +58,8 @@ vfio_pci_dma_buf_map(struct dma_buf_attachment *attachment,
 	if (priv->revoked)
 		return ERR_PTR(-ENODEV);
 
-	ret = dma_buf_phys_vec_to_sgt(attachment, priv->provider,
-				      priv->phys_vec, priv->nr_ranges,
-				      priv->size, dir);
+	ret = dma_buf_phys_vec_to_sgt(attachment, priv->phys_vec,
+				      priv->nr_ranges, priv->size, dir);
 	if (IS_ERR(ret))
 		return ret;
 
@@ -274,7 +272,7 @@ int vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags,
 	priv->vdev = vdev;
 	priv->nr_ranges = get_dma_buf.nr_ranges;
 	priv->size = length;
-	ret = vdev->pci_ops->get_dmabuf_phys(vdev, &priv->provider,
+	ret = vdev->pci_ops->get_dmabuf_phys(vdev, &exp_info.provider,
 					     get_dma_buf.region_index,
 					     priv->phys_vec, dma_ranges,
 					     priv->nr_ranges);
diff --git a/include/linux/dma-buf-mapping.h b/include/linux/dma-buf-mapping.h
index 09bde3f748e4..d63ac4d52aa5 100644
--- a/include/linux/dma-buf-mapping.h
+++ b/include/linux/dma-buf-mapping.h
@@ -7,8 +7,10 @@
 #define __DMA_BUF_MAPPING_H__
 #include <linux/dma-buf.h>
 
+enum pci_p2pdma_map_type
+dma_buf_p2pdma_map_type(struct dma_buf_attachment *attach,
+			unsigned int tlp_flags);
 struct sg_table *dma_buf_phys_vec_to_sgt(struct dma_buf_attachment *attach,
-					 struct p2pdma_provider *provider,
 					 struct phys_vec *phys_vec,
 					 size_t nr_ranges, size_t size,
 					 enum dma_data_direction dir);
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index d1203da56fc5..81c136fcee6e 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -368,6 +368,9 @@ struct dma_buf {
 	/** @priv: exporter specific private data for this buffer object. */
 	void *priv;
 
+	/** @provider: The peer-to-peer provider backing this buffer. */
+	struct p2pdma_provider *provider;
+
 	/**
 	 * @resv:
 	 *
@@ -501,6 +504,7 @@ struct dma_buf_attachment {
  * @flags:	mode flags for the file
  * @resv:	reservation-object, NULL to allocate default one
  * @priv:	Attach private data of allocator to this buffer
+ * @provider:	Peer-to-peer provider backing the buffer
  *
  * This structure holds the information required to export the buffer. Used
  * with dma_buf_export() only.
@@ -512,6 +516,7 @@ struct dma_buf_export_info {
 	size_t size;
 	int flags;
 	struct dma_resv *resv;
+	struct p2pdma_provider *provider;
 	void *priv;
 };
 
  
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help