amdgpu_dma_buf_map() adds VRAM to the allowed domains for a peer2peer
attachment, so ttm_bo_validate() can migrate 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

Taking a reference here would deadlock: the reservation is held across
these callbacks and is also taken during resume, which is why
commit 030631e97b20 ("drm/amdgpu: revert "take runtime pm reference
when we attach a buffer" v2") removed it.  GTT stays accessible while
the GPU is powered down, so leaving the buffer there is safe.

Only request VRAM when the device can perform the move.

Fixes: 030631e97b20 ("drm/amdgpu: revert "take runtime pm reference when we 
attach a buffer" v2")
Cc: [email protected]
Signed-off-by: Mike Lothian <[email protected]>
Assisted-by: Claude:Opus-5 [Claude Code]
---

Is this the failure that commit c52feb436539 ("drm/amdgpu: Disable
runtime PM for externally attached dGPUs") was working around?  That
commit explains how to detect external attachment but not what breaks,
so I can't tell which.

If it is the same thing, could the pci_is_thunderbolt_attached() ||
dev_is_removable() check there be narrowed or dropped on top of this,
so eGPU users keep runtime PM?

I can't test that here: this box hits the bug by missing that check.
The dGPU is on an oculink port off a native AMD root port, so
pci_is_thunderbolt_attached() is false, dev_is_removable() is empty,
and runtime PM stays enabled.

Reproduced on a HawkPoint APU [1002:1900] driving the display with a
Navi 48 [Radeon AI PRO R9700] [1002:7551] on oculink for render
offload.  Without the patch kwin_wayland hits the call chain above
within a minute of the dGPU autosuspending and the desktop stops
repainting until it resumes.  With the patch the map stays in GTT
(ttm_bo_validate() returns 0, mem_type TTM_PL_TT) and the dGPU keeps
autosuspending.

 drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
index b33c300e26e2..d1dae5f3fee5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -191,7 +191,8 @@ 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) {
+                   attach->peer2peer &&
+                   adev->mman.buffer_funcs_enabled) {
                        bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
                        domains |= AMDGPU_GEM_DOMAIN_VRAM;
                }
-- 
2.55.0

Reply via email to