mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 04:34:03 +02:00
drm/amdgpu: fix aperture mapping leak
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: 9d0af8b4de ("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>
This commit is contained in:
parent
fa1531170d
commit
d871e99879
|
|
@ -4189,8 +4189,6 @@ static void amdgpu_device_unmap_mmio(struct amdgpu_device *adev)
|
||||||
|
|
||||||
iounmap(adev->rmmio);
|
iounmap(adev->rmmio);
|
||||||
adev->rmmio = NULL;
|
adev->rmmio = NULL;
|
||||||
if (adev->mman.aper_base_kaddr)
|
|
||||||
iounmap(adev->mman.aper_base_kaddr);
|
|
||||||
adev->mman.aper_base_kaddr = NULL;
|
adev->mman.aper_base_kaddr = NULL;
|
||||||
|
|
||||||
/* Memory manager related */
|
/* Memory manager related */
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
/* Change the size here instead of the init above so only lpfn is affected */
|
||||||
amdgpu_ttm_disable_buffer_funcs(adev);
|
amdgpu_ttm_disable_buffer_funcs(adev);
|
||||||
#ifdef CONFIG_64BIT
|
#ifdef CONFIG_64BIT
|
||||||
#ifdef CONFIG_X86
|
if (adev->gmc.xgmi.connected_to_cpu) {
|
||||||
if (adev->gmc.xgmi.connected_to_cpu)
|
void *kaddr = devm_memremap(adev->dev, adev->gmc.aper_base,
|
||||||
adev->mman.aper_base_kaddr = ioremap_cache(adev->gmc.aper_base,
|
adev->gmc.visible_vram_size,
|
||||||
adev->gmc.visible_vram_size);
|
MEMREMAP_WB);
|
||||||
|
if (IS_ERR(kaddr))
|
||||||
else if (adev->gmc.is_app_apu)
|
return PTR_ERR(kaddr);
|
||||||
|
adev->mman.aper_base_kaddr = (__force void __iomem *)kaddr;
|
||||||
|
} else if (adev->gmc.is_app_apu) {
|
||||||
DRM_DEBUG_DRIVER(
|
DRM_DEBUG_DRIVER(
|
||||||
"No need to ioremap when real vram size is 0\n");
|
"No need to ioremap when real vram size is 0\n");
|
||||||
else
|
} else {
|
||||||
#endif
|
adev->mman.aper_base_kaddr = devm_ioremap_wc(adev->dev,
|
||||||
adev->mman.aper_base_kaddr = ioremap_wc(adev->gmc.aper_base,
|
adev->gmc.aper_base,
|
||||||
adev->gmc.visible_vram_size);
|
adev->gmc.visible_vram_size);
|
||||||
|
if (!adev->mman.aper_base_kaddr)
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
amdgpu_ttm_init_vram_resv_regions(adev);
|
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)
|
void amdgpu_ttm_fini(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
int idx;
|
|
||||||
|
|
||||||
if (!adev->mman.initialized)
|
if (!adev->mman.initialized)
|
||||||
return;
|
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_FW_VRAM_USAGE);
|
||||||
amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_DRV_VRAM_USAGE);
|
amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_DRV_VRAM_USAGE);
|
||||||
|
|
||||||
if (drm_dev_enter(adev_to_drm(adev), &idx)) {
|
adev->mman.aper_base_kaddr = NULL;
|
||||||
|
|
||||||
if (adev->mman.aper_base_kaddr)
|
|
||||||
iounmap(adev->mman.aper_base_kaddr);
|
|
||||||
adev->mman.aper_base_kaddr = NULL;
|
|
||||||
|
|
||||||
drm_dev_exit(idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!adev->gmc.is_app_apu)
|
if (!adev->gmc.is_app_apu)
|
||||||
amdgpu_vram_mgr_fini(adev);
|
amdgpu_vram_mgr_fini(adev);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user