]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/amd/pm: Disable MMIO access during SMU Mode 1 reset
authorPerry Yuan <perry.yuan@amd.com>
Thu, 25 Dec 2025 08:43:49 +0000 (16:43 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 5 Jan 2026 22:00:00 +0000 (17:00 -0500)
During Mode 1 reset, the ASIC undergoes a reset cycle and becomes
temporarily inaccessible via PCIe. Any attempt to access MMIO registers
during this window (e.g., from interrupt handlers or other driver threads)
can result in uncompleted PCIe transactions, leading to NMI panics or
system hangs.

To prevent this, set the `no_hw_access` flag to true immediately after
triggering the reset. This signals other driver components to skip
register accesses while the device is offline.

A memory barrier `smp_mb()` is added to ensure the flag update is
globally visible to all cores before the driver enters the sleep/wait
state.

Signed-off-by: Perry Yuan <perry.yuan@amd.com>
Reviewed-by: Yifan Zhang <yifan1.zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c

index 8f3ca5a30cc648820f546d80da78b14c3bca53cb..dd5d9da1c5a8bbddd33fdc02b89a884d3e15602b 100644 (file)
@@ -5723,6 +5723,9 @@ int amdgpu_device_mode1_reset(struct amdgpu_device *adev)
        if (ret)
                goto mode1_reset_failed;
 
+       /* enable mmio access after mode 1 reset completed */
+       adev->no_hw_access = false;
+
        amdgpu_device_load_pci_state(adev->pdev);
        ret = amdgpu_psp_wait_for_bootloader(adev);
        if (ret)
index aa26107b0e8c74db4c3da76480b0f30494e20d52..c95dbee06f49c84ecc8e8012bbca54fb284b85cc 100644 (file)
@@ -2850,8 +2850,13 @@ static int smu_v13_0_0_mode1_reset(struct smu_context *smu)
                break;
        }
 
-       if (!ret)
+       if (!ret) {
+               /* disable mmio access while doing mode 1 reset*/
+               smu->adev->no_hw_access = true;
+               /* ensure no_hw_access is globally visible before any MMIO */
+               smp_mb();
                msleep(SMU13_MODE1_RESET_WAIT_TIME_IN_MS);
+       }
 
        return ret;
 }
index af1bc7b4350b4d8a6681f896126f32ea6cc21a89..b1016debdf065d0e1fa090b8db1fd7252fa1a3ff 100644 (file)
@@ -2069,10 +2069,15 @@ static int smu_v14_0_2_mode1_reset(struct smu_context *smu)
 
        ret = smu_cmn_send_debug_smc_msg(smu, DEBUGSMC_MSG_Mode1Reset);
        if (!ret) {
-               if (amdgpu_emu_mode == 1)
+               if (amdgpu_emu_mode == 1) {
                        msleep(50000);
-               else
+               } else {
+                       /* disable mmio access while doing mode 1 reset*/
+                       smu->adev->no_hw_access = true;
+                       /* ensure no_hw_access is globally visible before any MMIO */
+                       smp_mb();
                        msleep(1000);
+               }
        }
 
        return ret;