After a GPU reset the level reported through
power_dpm_force_performance_level no longer matches the hardware. The reset
reinitialises PMFW, which comes back on its default curve, while
smu_dpm.dpm_level still holds the level the user forced.
On an SMU 14.0.1 APU this shows up as gfxclk dropping from 2.8GHz to 600MHz
while sysfs still reports high, with no thermal or power event involved:
before level: high freq: 2799000000
amdgpu 0000:c5:00.0: MODE2 reset
amdgpu 0000:c5:00.0: SMU is resumed successfully!
after level: high freq: 600000000
smu_late_init() already tries to re-apply the level after the reset:
smu_handle_task(smu, smu->smu_dpm.dpm_level, AMD_PP_TASK_COMPLETE_INIT);
but smu_adjust_power_state_dynamic() only programs the hardware when
if (smu_dpm_ctx->dpm_level != level)
and smu_dpm_ctx is &smu->smu_dpm, so the level is compared against itself.
The branch is never taken for this caller and
smu_asic_set_performance_level() is never called.
Syncing the cached level with the state PMFW came back in, before
re-applying the forced level, makes that call effective again. The reset
then no longer changes the level the user asked for.
Tested on an SMU 14.0.1 APU, triggering resets through
debugfs/amdgpu_gpu_recover and reading the level and gfxclk either side:
level before reset 1 reset 2 reset 3
high 2784MHz 2799MHz 2799MHz 2799MHz
low 605MHz 600MHz 600MHz
manual 600MHz 600MHz 603MHz
profile_peak 2260MHz 2799MHz 2799MHz
profile_standard 705MHz 700MHz 700MHz
auto 600MHz 601MHz 600MHz 600MHz
The level is retained across every reset, with no drift over repeats, and
auto is left on its own curve rather than being pinned high. profile_peak
sets a ceiling rather than a floor, so its sampled clock varies with load.
17 MODE2 resets over the run with no instability.
A suspend/resume cycle also keeps the level: high at 2784MHz before suspend,
high at 2799MHz after resume.
The change is scoped to reset recovery. PMFW retains its state across
s2idle, so on resume the forced level still applies and nothing needs
re-applying.
This is the only configuration I have available to test. The change is in
generic SMU code, so it applies to every ASIC going through
smu_late_init().
v2: restore the forced level instead of reporting the default after the
reset, as the driver is expected to keep the level the user asked for
and the reset often goes unnoticed (Lijo)
Priya Hosur (1):
drm/amd/pm: restore the forced performance level after a reset
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
--
2.43.0