Skip to contentSkip to conversation

FAILED: patch "[PATCH] drm/amdgpu: hold a runtime PM reference for P2P dma-buf" failed to apply to 6.12-stable tree

PATCH New [email protected] 2 participants 3 messages Sep 22

Subsystems (3)
lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

The patch below does not apply to the 6.12-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.

To reproduce the conflict and resubmit, you may use the following commands:

git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.12.y
git checkout FETCH_HEAD
git cherry-pick -x 636139603b99d2e3a18a46cf3f8d39313ce8042e
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026092255-footer-unscathed-ed09@gregkh' --subject-prefix 'PATCH 6.12.y' 'HEAD^..'

Possible dependencies:

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From 636139603b99d2e3a18a46cf3f8d39313ce8042e Mon Sep 17 00:00:00 2001
From: Mike Lothian <[email protected]>
Date: Sat, 12 Sep 2026 00:29:08 +0100
Subject: [PATCH] drm/amdgpu: hold a runtime PM reference for P2P dma-buf
attachments
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

amdgpu_dma_buf_map() adds VRAM to the allowed domains for a peer2peer attachment. GTT is only a fallback placement when VRAM is preferred, so ttm_bo_validate() migrates the buffer from GTT into VRAM. While the exporting device is runtime suspended its SDMA rings are down and the move fails:

amdgpu: Move buffer fallback to memcpy unavailable

An importer on a second GPU reaches this holding no runtime PM reference on the exporter, e.g. a compositor on the APU submitting a frame that references a buffer exported by an idle dGPU:

amdgpu_cs_ioctl -> amdgpu_cs_parser_bos -> amdgpu_cs_bo_validate

    -> ttm_bo_validate -> amdgpu_bo_move -> dma_buf_map_attachment
      -> amdgpu_dma_buf_map -> ttm_bo_validate -> amdgpu_bo_move

Pinning a dma-buf into VRAM has the same requirement, which commit 030631e97b20 ("drm/amdgpu: revert "take runtime pm reference when we attach a buffer" v2") called out as the one case that would need the reference back.

Take it in attach and drop it in detach. pm_runtime_get_if_active() never resumes the device, so it cannot deadlock against the reservation taken during resume, which is why the old pm_runtime_get_sync() had to go. If the device is not active, clear peer2peer instead: the buffer then stays in GTT, which remains accessible while the GPU is powered down. If runtime PM is disabled, take a plain reference so the put in detach stays balanced.

Fixes 030631e97b20 ("drm/amdgpu: revert "take runtime pm reference when we attach a buffer" v2")
Assisted-by Claude:Opus-5 [Claude Code]
(cherry picked from commit 062ff15e30a48d14fb7d7558eba84f8dc97197f0)
drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +42 -1
index b33c300e26e2..9adf3eed8822 100644
@@ -43,6 +43,7 @@
 #include <linux/dma-buf.h>
 #include <linux/dma-fence-array.h>
 #include <linux/pci-p2pdma.h>
+#include <linux/pm_runtime.h>
 
 static const struct dma_buf_attach_ops amdgpu_dma_buf_attach_ops;
 
@@ -100,15 +101,54 @@ static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf,
 	    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)
-		return r;
+		goto err_pm_put;
 
 	amdgpu_vm_bo_update_shared(bo);
 
 	dma_resv_unlock(bo->tbo.base.resv);
 
 	return 0;
+
+err_pm_put:
+	if (attach->peer2peer)
+		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
+	return r;
+}
+
+/**
+ * amdgpu_dma_buf_detach - &dma_buf_ops.detach implementation
+ *
+ * @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().
+ */
+static void amdgpu_dma_buf_detach(struct dma_buf *dmabuf,
+				  struct dma_buf_attachment *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);
+
+	if (attach->peer2peer)
+		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
 }
 
 /**
@@ -350,6 +390,7 @@ static void amdgpu_dma_buf_vunmap(struct dma_buf *dma_buf, struct iosys_map *map
 
 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,
maintainer
#1 lore raw

PATCH 1/2 drm: add drm_memory_stats_is_zero

From: Yunxiang Li <[email protected]>

[ Upstream commit fd265d9e0c3358e6b9fe244d8f5d2824fda1c0dc ]

Add a helper to check if the memory stats is zero, this will be used to check for memory accounting errors.

Stable-dep-of: 636139603b99 ("drm/amdgpu: hold a runtime PM reference for P2P dma-buf attachments")

---
 drivers/gpu/drm/drm_file.c | 10 ++++++++++
 include/drm/drm_file.h     |  1 +
 2 files changed, 11 insertions(+)
drivers/gpu/drm/drm_file.c +10 -0
index e2cf118ff01d3..99ffbea8b6a8d 100644
@@ -840,6 +840,16 @@ static void print_size(struct drm_printer *p, const char *stat,
 	drm_printf(p, "drm-%s-%s:\t%llu%s\n", stat, region, sz, units[u]);
 }
 
+int drm_memory_stats_is_zero(const struct drm_memory_stats *stats)
+{
+	return (stats->shared == 0 &&
+		stats->private == 0 &&
+		stats->resident == 0 &&
+		stats->purgeable == 0 &&
+		stats->active == 0);
+}
+EXPORT_SYMBOL(drm_memory_stats_is_zero);
+
 /**
  * drm_print_memory_stats - A helper to print memory stats
  * @p: The printer to print output to
include/drm/drm_file.h +1 -0
index 2bc88d2d4a84e..92d0f9c5d788c 100644
@@ -485,6 +485,7 @@ struct drm_memory_stats {
 
 enum drm_gem_object_status;
 
+int drm_memory_stats_is_zero(const struct drm_memory_stats *stats);
 void drm_print_memory_stats(struct drm_printer *p,
 			    const struct drm_memory_stats *stats,
 			    enum drm_gem_object_status supported_status,
Signature · 1 line
2.53.0
maintainer
#2 lore raw

PATCH 2/2 drm/amdgpu: hold a runtime PM reference for P2P dma-buf attachments

From: Mike Lothian <[email protected]>

[ Upstream commit 636139603b99d2e3a18a46cf3f8d39313ce8042e ]

amdgpu_dma_buf_map() adds VRAM to the allowed domains for a peer2peer attachment. GTT is only a fallback placement when VRAM is preferred, so ttm_bo_validate() migrates the buffer from GTT into VRAM. While the exporting device is runtime suspended its SDMA rings are down and the move fails:

amdgpu: Move buffer fallback to memcpy unavailable

An importer on a second GPU reaches this holding no runtime PM reference on the exporter, e.g. a compositor on the APU submitting a frame that references a buffer exported by an idle dGPU:

amdgpu_cs_ioctl -> amdgpu_cs_parser_bos -> amdgpu_cs_bo_validate

    -> ttm_bo_validate -> amdgpu_bo_move -> dma_buf_map_attachment
      -> amdgpu_dma_buf_map -> ttm_bo_validate -> amdgpu_bo_move

Pinning a dma-buf into VRAM has the same requirement, which commit 030631e97b20 ("drm/amdgpu: revert "take runtime pm reference when we attach a buffer" v2") called out as the one case that would need the reference back.

Take it in attach and drop it in detach. pm_runtime_get_if_active() never resumes the device, so it cannot deadlock against the reservation taken during resume, which is why the old pm_runtime_get_sync() had to go. If the device is not active, clear peer2peer instead: the buffer then stays in GTT, which remains accessible while the GPU is powered down. If runtime PM is disabled, take a plain reference so the put in detach stays balanced.

Fixes 030631e97b20 ("drm/amdgpu: revert "take runtime pm reference when we attach a buffer" v2")
Assisted-by Claude:Opus-5 [Claude Code]
(cherry picked from commit 062ff15e30a48d14fb7d7558eba84f8dc97197f0)
[ omitted err_pm_put cleanup because this branch lacks the reservation-locking failure path. ]
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 36 +++++++++++++++++++++
 1 file changed, 36 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +36 -0
index 0b576481f2314..e6cc6c88cb60e 100644
@@ -41,6 +41,7 @@
 #include <linux/dma-buf.h>
 #include <linux/dma-fence-array.h>
 #include <linux/pci-p2pdma.h>
+#include <linux/pm_runtime.h>
 
 static const struct dma_buf_attach_ops amdgpu_dma_buf_attach_ops;
 
@@ -97,9 +98,43 @@ static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf,
 	    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);
+	}
+
 	return 0;
 }
 
+/**
+ * amdgpu_dma_buf_detach - &dma_buf_ops.detach implementation
+ *
+ * @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().
+ */
+static void amdgpu_dma_buf_detach(struct dma_buf *dmabuf,
+				  struct dma_buf_attachment *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);
+
+	if (attach->peer2peer)
+		pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
+}
+
 /**
  * amdgpu_dma_buf_pin - &dma_buf_ops.pin implementation
  *
@@ -270,6 +305,7 @@ static int amdgpu_dma_buf_begin_cpu_access(struct dma_buf *dma_buf,
 
 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,
Signature · 1 line
2.53.0