Commit 7edb503f authored by Perry Yuan's avatar Perry Yuan Committed by Alex Deucher
Browse files

drm/amd/pm: Disable MMIO access during SMU Mode 1 reset



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: default avatarPerry Yuan <perry.yuan@amd.com>
Reviewed-by: default avatarYifan Zhang <yifan1.zhang@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent bd8150a1
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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)
+6 −1
Original line number Diff line number Diff line
@@ -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;
}
+7 −2
Original line number Diff line number Diff line
@@ -2069,11 +2069,16 @@ 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;
}