Linux RDMA and InfiniBand development
 help / color / mirror / Atom feed
From: Alistair Popple <apopple@nvidia.com>
To: dri-devel@lists.freedesktop.org, christian.koenig@amd.com,
	sumit.semwal@linaro.org, jgg@nvidia.com
Cc: "Alistair Popple" <apopple@nvidia.com>,
	"Thomas Hellström" <thomas.hellstrom@linux.intel.com>,
	"Simona Vetter" <simona.vetter@ffwll.ch>,
	"Matthew Brost" <matthew.brost@intel.com>,
	"Vivek Kasireddy" <vivek.kasireddy@intel.com>,
	"Dongwon Kim" <dongwon.kim@intel.com>,
	"Leon Romanovsky" <leonro@nvidia.com>,
	"Kevin Tian" <kevin.tian@intel.com>,
	"Xu Yilun" <yilun.xu@linux.intel.com>,
	"Karl Mehltretter" <kmehltretter@gmail.com>,
	"Baolu Lu" <baolu.lu@linux.intel.com>,
	"Felix Kuehling" <felix.kuehling@amd.com>,
	"Alex Deucher" <alexander.deucher@amd.com>,
	intel-xe@lists.freedesktop.org, amd-gfx@lists.freedesktop.org,
	linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org,
	linux-rdma@vger.kernel.org, iommu@lists.linux.dev,
	"Alexey Kardashevskiy" <aik@amd.com>,
	zhipingz@meta.com, treding@nvidia.com, jhubbard@nvidia.com
Subject: [PATCH 14/26] drm/amdgpu: Use the SGT mapping type
Date: Mon, 26 Oct 2026 16:36:05 +1100	[thread overview]
Message-ID: <20261026053623.202642-15-apopple@nvidia.com> (raw)
In-Reply-To: <20261026053623.202642-1-apopple@nvidia.com>

From: Jason Gunthorpe <jgg@nvidia.com>

Similar to xe, amdgpu wants to check pci_p2pdma_distance(), and
only needs that if peer2peer can be supported by the GPU. It can migrate to
system memory and support non-p2p DMA as well.

Further it supports a private non-PCI XGMI path. For now hack this on top
of a SGT type, but eventually this is likely better off as its own mapping
type.

Add two exporter SGT mapping types, one that matches P2P and one that
matches all of the non-p2p. The pin and map code will force migrate if
the non-p2p one is matched.

Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
[ the match set is recorded in attach->matches and the type
  selected from it at pin or map, so the pin walk, detach and the attach
  error path ask dma_buf_attach_accepts_sgt_p2p() whether an attachment
  could take P2P at all, and the XGMI override rewrites the recorded match
  set entry rather than only attach->map_type. The map path keeps using
  dma_buf_sgt_p2p_allowed() for the attachment being mapped, which has just
  been selected. The runtime PM reference follows the same question: held
  while P2P is in the match set, dropped in detach. - apopple ]
Signed-off-by: Alistair Popple <apopple@nvidia.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 137 +++++++++++++-------
 1 file changed, 92 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
index 9adf3eed8822..19ee9f85ff30 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -41,6 +41,7 @@
 #include <drm/amdgpu_drm.h>
 #include <drm/ttm/ttm_tt.h>
 #include <linux/dma-buf.h>
+#include <linux/dma-buf-mapping.h>
 #include <linux/dma-fence-array.h>
 #include <linux/pci-p2pdma.h>
 #include <linux/pm_runtime.h>
@@ -79,43 +80,11 @@ static struct amdgpu_device *dma_buf_attach_adev(struct dma_buf_attachment *atta
 static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf,
 				 struct dma_buf_attachment *attach)
 {
-	struct amdgpu_device *attach_adev = dma_buf_attach_adev(attach);
 	struct drm_gem_object *obj = dmabuf->priv;
 	struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
 	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
 	int r;
 
-	/*
-	 * Disable peer-to-peer access for DCC-enabled VRAM surfaces on GFX12+.
-	 * Such buffers cannot be safely accessed over P2P due to device-local
-	 * compression metadata. Fallback to system-memory path instead.
-	 * Device supports GFX12 (GC 12.x or newer)
-	 * BO was created with the AMDGPU_GEM_CREATE_GFX12_DCC flag
-	 *
-	 */
-	if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(12, 0, 0) &&
-	    bo->flags & AMDGPU_GEM_CREATE_GFX12_DCC)
-		attach->peer2peer = false;
-
-	if (!amdgpu_dmabuf_is_xgmi_accessible(attach_adev, bo) &&
-	    pci_p2pdma_distance(adev->pdev, attach->dev, false) < 0)
-		attach->peer2peer = false;
-
-	/*
-	 * Only allow P2P while the exporter is active, and keep it active
-	 * until detach.  With runtime PM disabled take a plain reference so
-	 * the put in detach stays balanced.
-	 */
-	if (attach->peer2peer) {
-		struct device *dev = adev_to_drm(adev)->dev;
-		int ret = pm_runtime_get_if_active(dev);
-
-		if (!ret)
-			attach->peer2peer = false;
-		else if (ret < 0)
-			pm_runtime_get_noresume(dev);
-	}
-
 	r = dma_resv_lock(bo->tbo.base.resv, NULL);
 	if (r)
 		goto err_pm_put;
@@ -127,7 +96,8 @@ static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf,
 	return 0;
 
 err_pm_put:
-	if (attach->peer2peer)
+	/* Drop the reference taken in amdgpu_dma_buf_match_mapping() */
+	if (dma_buf_attach_accepts_sgt_p2p(attach))
 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
 	return r;
 }
@@ -138,7 +108,7 @@ static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf,
  * @dmabuf: DMA-buf where we remove the attachment from
  * @attach: the attachment to remove
  *
- * Drop the runtime PM reference taken in amdgpu_dma_buf_attach().
+ * Drop the runtime PM reference taken in amdgpu_dma_buf_match_mapping().
  */
 static void amdgpu_dma_buf_detach(struct dma_buf *dmabuf,
 				  struct dma_buf_attachment *attach)
@@ -147,7 +117,7 @@ static void amdgpu_dma_buf_detach(struct dma_buf *dmabuf,
 	struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
 	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
 
-	if (attach->peer2peer)
+	if (dma_buf_attach_accepts_sgt_p2p(attach))
 		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
 }
 
@@ -175,7 +145,7 @@ static int amdgpu_dma_buf_pin(struct dma_buf_attachment *attach)
 	 * notiers are enabled.
 	 */
 	list_for_each_entry(attach, &dmabuf->attachments, node)
-		if (!attach->peer2peer)
+		if (!dma_buf_attach_accepts_sgt_p2p(attach))
 			domains &= ~AMDGPU_GEM_DOMAIN_VRAM;
 
 	if (domains & AMDGPU_GEM_DOMAIN_VRAM)
@@ -218,6 +188,7 @@ static void amdgpu_dma_buf_unpin(struct dma_buf_attachment *attach)
 static struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach,
 					   enum dma_data_direction dir)
 {
+	struct device *dma_dev = dma_buf_sgt_dma_device(attach);
 	struct dma_buf *dma_buf = attach->dmabuf;
 	struct drm_gem_object *obj = dma_buf->priv;
 	struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
@@ -231,7 +202,7 @@ static struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach,
 		unsigned int domains = AMDGPU_GEM_DOMAIN_GTT;
 
 		if (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM &&
-		    attach->peer2peer) {
+		    dma_buf_sgt_p2p_allowed(attach)) {
 			bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
 			domains |= AMDGPU_GEM_DOMAIN_VRAM;
 		}
@@ -249,7 +220,7 @@ static struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach,
 		if (IS_ERR(sgt))
 			return sgt;
 
-		if (dma_map_sgtable(attach->dev, sgt, dir,
+		if (dma_map_sgtable(dma_dev, sgt, dir,
 				    DMA_ATTR_SKIP_CPU_SYNC))
 			goto error_free;
 		break;
@@ -261,7 +232,7 @@ static struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach,
 			return ERR_PTR(-EINVAL);
 
 		r = amdgpu_vram_mgr_alloc_sgt(adev, bo->tbo.resource, 0,
-					      bo->tbo.base.size, attach->dev,
+					      bo->tbo.base.size, dma_dev,
 					      dir, &sgt);
 		if (r)
 			return ERR_PTR(r);
@@ -269,7 +240,7 @@ static struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach,
 
 	case AMDGPU_PL_MMIO_REMAP:
 		r = amdgpu_ttm_mmio_remap_alloc_sgt(adev, bo->tbo.resource,
-						    attach->dev, dir, &sgt);
+						    dma_dev, dir, &sgt);
 		if (r)
 			return ERR_PTR(r);
 		break;
@@ -299,21 +270,22 @@ static void amdgpu_dma_buf_unmap(struct dma_buf_attachment *attach,
 				 struct sg_table *sgt,
 				 enum dma_data_direction dir)
 {
+	struct device *dma_dev = dma_buf_sgt_dma_device(attach);
 	struct drm_gem_object *obj = attach->dmabuf->priv;
 	struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
 
 	if (bo->tbo.resource &&
 	    bo->tbo.resource->mem_type == AMDGPU_PL_MMIO_REMAP) {
-		amdgpu_ttm_mmio_remap_free_sgt(attach->dev, dir, sgt);
+		amdgpu_ttm_mmio_remap_free_sgt(dma_dev, dir, sgt);
 		return;
 	}
 
 	if (sg_page(sgt->sgl)) {
-		dma_unmap_sgtable(attach->dev, sgt, dir, 0);
+		dma_unmap_sgtable(dma_dev, sgt, dir, 0);
 		sg_free_table(sgt);
 		kfree(sgt);
 	} else {
-		amdgpu_vram_mgr_free_sgt(attach->dev, dir, sgt);
+		amdgpu_vram_mgr_free_sgt(dma_dev, dir, sgt);
 	}
 }
 
@@ -388,18 +360,93 @@ static void amdgpu_dma_buf_vunmap(struct dma_buf *dma_buf, struct iosys_map *map
 	amdgpu_bo_unpin(bo);
 }
 
+static const struct dma_buf_mapping_sgt_exp_ops amdgpu_dma_buf_sgt_ops = {
+	.map_dma_buf = amdgpu_dma_buf_map,
+	.unmap_dma_buf = amdgpu_dma_buf_unmap,
+};
+
+static int amdgpu_dma_buf_match_mapping(struct dma_buf_match_args *args)
+{
+	struct dma_buf_attachment *attach = args->attach;
+	struct drm_gem_object *obj = args->dmabuf->priv;
+	struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
+	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
+	struct device *dev = adev_to_drm(adev)->dev;
+	struct dma_buf_mapping_match sgt_match[2];
+	unsigned int num_match = 0;
+	bool peer2peer = true;
+	int ret;
+
+	/*
+	 * Disable peer-to-peer access for DCC-enabled VRAM surfaces on GFX12+.
+	 * Such buffers cannot be safely accessed over P2P due to device-local
+	 * compression metadata. Fallback to system-memory path instead.
+	 * Device supports GFX12 (GC 12.x or newer)
+	 * BO was created with the AMDGPU_GEM_CREATE_GFX12_DCC flag
+	 *
+	 */
+	if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(12, 0, 0) &&
+	    bo->flags & AMDGPU_GEM_CREATE_GFX12_DCC)
+		peer2peer = false;
+
+	/*
+	 * Only allow P2P while the exporter is active, and keep it active
+	 * until detach.  With runtime PM disabled take a plain reference so
+	 * the put in detach stays balanced.
+	 */
+	if (peer2peer) {
+		ret = pm_runtime_get_if_active(dev);
+		if (!ret)
+			peer2peer = false;
+		else if (ret < 0)
+			pm_runtime_get_noresume(dev);
+	}
+
+	if (peer2peer)
+		sgt_match[num_match++] = DMA_BUF_EMAPPING_SGT_P2P(
+			&amdgpu_dma_buf_sgt_ops, adev->pdev);
+	sgt_match[num_match++] = DMA_BUF_EMAPPING_SGT(&amdgpu_dma_buf_sgt_ops);
+
+	ret = dma_buf_match_mapping(args, sgt_match, num_match);
+	if (ret)
+		goto err_pm_put;
+
+	/*
+	 * If the transfer will use XGMI then force a P2P match: the importer
+	 * reaches VRAM over XGMI, so the BO may stay there even though PCIe
+	 * P2P did not match. Rewrite the recorded match set entry rather than
+	 * only attach->map_type, which is what dma_buf_mapping_select() will
+	 * copy from at pin or map time.
+	 */
+	if (peer2peer && !dma_buf_attach_accepts_sgt_p2p(attach) &&
+	    amdgpu_dmabuf_is_xgmi_accessible(dma_buf_attach_adev(attach), bo)) {
+		attach->matches[0].sgt_data.exporter_requires_p2p =
+			DMA_SGT_EXPORTER_REQUIRES_P2P_DISTANCE;
+		attach->map_type = attach->matches[0];
+	}
+
+	/* The PM reference is only needed while P2P is actually possible. */
+	if (peer2peer && !dma_buf_attach_accepts_sgt_p2p(attach))
+		pm_runtime_put_autosuspend(dev);
+	return 0;
+
+err_pm_put:
+	if (peer2peer)
+		pm_runtime_put_autosuspend(dev);
+	return ret;
+}
+
 const struct dma_buf_ops amdgpu_dmabuf_ops = {
 	.attach = amdgpu_dma_buf_attach,
 	.detach = amdgpu_dma_buf_detach,
 	.pin = amdgpu_dma_buf_pin,
 	.unpin = amdgpu_dma_buf_unpin,
-	.map_dma_buf = amdgpu_dma_buf_map,
-	.unmap_dma_buf = amdgpu_dma_buf_unmap,
 	.release = drm_gem_dmabuf_release,
 	.begin_cpu_access = amdgpu_dma_buf_begin_cpu_access,
 	.mmap = drm_gem_dmabuf_mmap,
 	.vmap = amdgpu_dma_buf_vmap,
 	.vunmap = amdgpu_dma_buf_vunmap,
+	.match_mapping = amdgpu_dma_buf_match_mapping,
 };
 
 /**
-- 
2.54.0


  parent reply	other threads:[~2026-10-26  5:38 UTC|newest]

Thread overview: 71+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-26  5:35 [PATCH 00/26] DMA-buf mapping types Alistair Popple
2026-10-26  5:35 ` [PATCH 01/26] dma-buf: Introduce " Alistair Popple
2026-10-26  7:00   ` sashiko-bot
2026-10-26  5:35 ` [PATCH 02/26] dma-buf: Add the SGT DMA mapping type Alistair Popple
2026-10-26  7:04   ` sashiko-bot
2026-10-26  5:35 ` [PATCH 03/26] dma-buf: Add dma_buf_mapping_attach() Alistair Popple
2026-10-26  7:20   ` sashiko-bot
2026-10-26  5:35 ` [PATCH 04/26] dma-buf: Route SGT related actions through attach->map_type Alistair Popple
2026-10-26  7:29   ` sashiko-bot
2026-10-26  5:35 ` [PATCH 05/26] dma-buf: Let the exporter select mapping type at pin/map Alistair Popple
2026-10-26  7:39   ` sashiko-bot
2026-10-26  8:03   ` Karl Mehltretter
2026-10-27  5:46     ` Alistair Popple
2026-10-26  5:35 ` [PATCH 06/26] dma-buf: Add match set queries for exporter placement decisions Alistair Popple
2026-10-26  7:42   ` sashiko-bot
2026-10-26  5:35 ` [PATCH 07/26] dma-buf: Add dma_buf_mapping_map() returning a type-tagged mapping Alistair Popple
2026-10-26  7:56   ` sashiko-bot
2026-10-26  5:35 ` [PATCH 08/26] dma-buf: Allow single exporter drivers to avoid the match_mapping function Alistair Popple
2026-10-26  7:58   ` sashiko-bot
2026-10-26  5:36 ` [PATCH 09/26] drm: Check the SGT ops for drm_gem_map_dma_buf() Alistair Popple
2026-10-26  8:02   ` sashiko-bot
2026-10-26  5:36 ` [PATCH 10/26] dma-buf: Convert all the simple exporters to use SGT mapping type Alistair Popple
2026-10-26  8:12   ` sashiko-bot
2026-10-26  5:36 ` [PATCH 11/26] drm/vmwgfx: Use match_mapping instead of dummy calls Alistair Popple
2026-10-26  8:13   ` sashiko-bot
2026-10-26  5:36 ` [PATCH 12/26] accel/habanalabs: Use the SGT_P2P mapping type Alistair Popple
2026-10-26  8:18   ` sashiko-bot
2026-10-26  5:36 ` [PATCH 13/26] drm/xe/dma-buf: Use the SGT " Alistair Popple
2026-10-26  8:34   ` sashiko-bot
2026-10-26  5:36 ` Alistair Popple [this message]
2026-10-26  8:46   ` [PATCH 14/26] drm/amdgpu: " sashiko-bot
2026-10-26  5:36 ` [PATCH 15/26] vfio/pci: Change the DMA-buf exporter to use mapping_type Alistair Popple
2026-10-26  9:00   ` sashiko-bot
2026-10-26  5:36 ` [PATCH 16/26] RDMA/uverbs: Use the SGT_P2P mapping type Alistair Popple
2026-10-26  9:16   ` sashiko-bot
2026-10-26  5:36 ` [PATCH 17/26] dma-buf: Update dma_buf_phys_vec_to_sgt() to use the SGT " Alistair Popple
2026-10-26  9:26   ` sashiko-bot
2026-10-26  5:36 ` [PATCH 18/26] iio: buffer: convert " Alistair Popple
2026-10-26  9:28   ` sashiko-bot
2026-10-26  5:36 ` [PATCH 19/26] functionfs: " Alistair Popple
2026-10-26  9:35   ` sashiko-bot
2026-10-26  5:36 ` [PATCH 20/26] dma-buf: Remove unused SGT stuff from the common structures Alistair Popple
2026-10-26  9:39   ` sashiko-bot
2026-10-26  5:36 ` [PATCH 21/26] treewide: Rename dma_buf_map_attachment(_unlocked) to dma_buf_sgt_ Alistair Popple
2026-10-26  9:49   ` sashiko-bot
2026-10-27 12:05   ` Christian König
2026-10-27 12:35     ` Jason Gunthorpe
2026-10-26  5:36 ` [PATCH 22/26] treewide: Rename dma_buf_unmap_attachment(_unlocked) to dma_buf_sgt_* Alistair Popple
2026-10-26  9:56   ` sashiko-bot
2026-10-26  5:36 ` [PATCH 23/26] treewide: Rename dma_buf_attach() to dma_buf_sgt_attach() Alistair Popple
2026-10-26 10:01   ` sashiko-bot
2026-10-27  2:15   ` Karl Mehltretter
2026-10-27  3:42     ` Mikko Perttunen
2026-10-27 12:33       ` Jason Gunthorpe
2026-10-27 13:34         ` Mikko Perttunen
2026-10-27 13:43           ` Christian König
2026-10-27 12:11     ` Christian König
2026-10-27 12:31     ` Jason Gunthorpe
2026-10-27 12:07   ` Christian König
2026-10-27 12:38     ` Jason Gunthorpe
2026-10-27 13:17       ` Christian König
2026-10-27 14:08         ` Jason Gunthorpe
2026-10-27 14:28           ` Christian König
2026-10-27 14:44             ` Jason Gunthorpe
2026-10-27 14:54               ` Christian König
2026-10-26  5:36 ` [PATCH 24/26] treewide: Rename dma_buf_dynamic_attach() to dma_buf_sgt_dynamic_attach() Alistair Popple
2026-10-26 10:13   ` sashiko-bot
2026-10-26  5:36 ` [PATCH 25/26] dma-buf: Add kunit tests for mapping type Alistair Popple
2026-10-26 10:19   ` sashiko-bot
2026-10-26  5:36 ` [PATCH 26/26] dma-buf: Add kunit tests for mapping type selection Alistair Popple
2026-10-26 10:22   ` sashiko-bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261026053623.202642-15-apopple@nvidia.com \
    --to=apopple@nvidia.com \
    --cc=aik@amd.com \
    --cc=alexander.deucher@amd.com \
    --cc=amd-gfx@lists.freedesktop.org \
    --cc=baolu.lu@linux.intel.com \
    --cc=christian.koenig@amd.com \
    --cc=dongwon.kim@intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=felix.kuehling@amd.com \
    --cc=intel-xe@lists.freedesktop.org \
    --cc=iommu@lists.linux.dev \
    --cc=jgg@nvidia.com \
    --cc=jhubbard@nvidia.com \
    --cc=kevin.tian@intel.com \
    --cc=kmehltretter@gmail.com \
    --cc=leonro@nvidia.com \
    --cc=linaro-mm-sig@lists.linaro.org \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-rdma@vger.kernel.org \
    --cc=matthew.brost@intel.com \
    --cc=simona.vetter@ffwll.ch \
    --cc=sumit.semwal@linaro.org \
    --cc=thomas.hellstrom@linux.intel.com \
    --cc=treding@nvidia.com \
    --cc=vivek.kasireddy@intel.com \
    --cc=yilun.xu@linux.intel.com \
    --cc=zhipingz@meta.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox