]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/amdgpu: fix aperture mapping leak
authorAsad Kamal <asad.kamal@amd.com>
Sun, 14 Jun 2026 04:50:28 +0000 (12:50 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 1 Jul 2026 16:59:16 +0000 (12:59 -0400)
amdgpu_pci_remove() calls drm_dev_unplug() before invoking the driver
fini routines. This causes drm_dev_enter() in amdgpu_ttm_fini() to
always return false, so iounmap(aper_base_kaddr) never runs on normal
driver unload, leaving an orphaned entry in the x86 PAT interval tree.

On connected_to_cpu hardware, the aperture is mapped write-back (WB) via
ioremap_cache(). On reload, IP discovery calls memremap(..., MEMREMAP_WC)
over the same range. The WC vs WB conflict causes:

  ioremap error for 0x..., requested 0x1, got 0x0
  amdgpu: discovery failed: -2

Fix by switching to devres-managed mappings so cleanup is guaranteed
regardless of drm_dev_enter() state:

- connected_to_cpu path: devm_memremap(MEMREMAP_WB). For
  IORESOURCE_SYSTEM_RAM ranges this takes the try_ram_remap() shortcut,
  returning __va(offset) from the existing kernel direct map. No new
  ioremap VA or PAT entry is created, so there is nothing to orphan.

- dGPU path: devm_ioremap_wc() registers iounmap() as a devres action,
  guaranteeing cleanup at device_del() time.

Also remove iounmap(aper_base_kaddr) from amdgpu_device_unmap_mmio()
since the mapping is now devres-owned.

v2: Remove redundant x86_64 guard (Lijo)

Fixes: 9d0af8b4def0 ("drm/amdgpu: pre-map device buffer as cached for A+A config")
Signed-off-by: Asad Kamal <asad.kamal@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit d871e99879cb5fd1fa798b006b4888887e63a17a)
Cc: stable@vger.kernel.org
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c

index 211d30f03d25f199f4aea597cf71193dd1606c01..8d6502a9430671bfec6dee6dc8fce5708fd9bde5 100644 (file)
@@ -4184,8 +4184,6 @@ static void amdgpu_device_unmap_mmio(struct amdgpu_device *adev)
 
        iounmap(adev->rmmio);
        adev->rmmio = NULL;
-       if (adev->mman.aper_base_kaddr)
-               iounmap(adev->mman.aper_base_kaddr);
        adev->mman.aper_base_kaddr = NULL;
 
        /* Memory manager related */
index 16c060badaee1a61b4eb9fa61edc9642a5189372..00b5317f77f84c54889244436d3a689853e9ba59 100644 (file)
@@ -2118,18 +2118,23 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
        /* Change the size here instead of the init above so only lpfn is affected */
        amdgpu_ttm_disable_buffer_funcs(adev);
 #ifdef CONFIG_64BIT
-#ifdef CONFIG_X86
-       if (adev->gmc.xgmi.connected_to_cpu)
-               adev->mman.aper_base_kaddr = ioremap_cache(adev->gmc.aper_base,
-                               adev->gmc.visible_vram_size);
-
-       else if (adev->gmc.is_app_apu)
+       if (adev->gmc.xgmi.connected_to_cpu) {
+               void *kaddr = devm_memremap(adev->dev, adev->gmc.aper_base,
+                                           adev->gmc.visible_vram_size,
+                                           MEMREMAP_WB);
+               if (IS_ERR(kaddr))
+                       return PTR_ERR(kaddr);
+               adev->mman.aper_base_kaddr = (__force void __iomem *)kaddr;
+       } else if (adev->gmc.is_app_apu) {
                DRM_DEBUG_DRIVER(
                        "No need to ioremap when real vram size is 0\n");
-       else
-#endif
-               adev->mman.aper_base_kaddr = ioremap_wc(adev->gmc.aper_base,
-                               adev->gmc.visible_vram_size);
+       } else {
+               adev->mman.aper_base_kaddr = devm_ioremap_wc(adev->dev,
+                                                            adev->gmc.aper_base,
+                                                            adev->gmc.visible_vram_size);
+               if (!adev->mman.aper_base_kaddr)
+                       return -ENOMEM;
+       }
 #endif
 
        amdgpu_ttm_init_vram_resv_regions(adev);
@@ -2246,8 +2251,6 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
  */
 void amdgpu_ttm_fini(struct amdgpu_device *adev)
 {
-       int idx;
-
        if (!adev->mman.initialized)
                return;
 
@@ -2270,14 +2273,7 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev)
        amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_FW_VRAM_USAGE);
        amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_DRV_VRAM_USAGE);
 
-       if (drm_dev_enter(adev_to_drm(adev), &idx)) {
-
-               if (adev->mman.aper_base_kaddr)
-                       iounmap(adev->mman.aper_base_kaddr);
-               adev->mman.aper_base_kaddr = NULL;
-
-               drm_dev_exit(idx);
-       }
+       adev->mman.aper_base_kaddr = NULL;
 
        if (!adev->gmc.is_app_apu)
                amdgpu_vram_mgr_fini(adev);