[PATCH 3/4] drm/amd/pm: refactor user PPT policy save and restore
Yang Wang <[email protected]> Fri, 31 Jul 2026 11:10:21 +0800
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <2a1bf8c187a6b6a67169fda0e6551a062af56c77.1785467079.git.kevinyang.wang@amd.com> |
The existing user policy representation has three ambiguities: - A numeric value cannot distinguish explicit zero from an unset policy. - One value per controller cannot preserve independent AC and DC requests. - Suspend-only restore misses runtime resume, GPU reset, and table reload. Refactor policy storage and restore as follows: - Store values and validity masks by power source and PPT controller. - Save writes against the active source. - Restore the active source after default SMU setup. - Reapply the target policy after live AC/DC transitions. - Use the target source default when no explicit request exists. The late-init path now covers system resume, runtime resume, GPU reset, and custom PPTable reload. Common code owns persistent policy; PMFW continues to own effective current limits. Signed-off-by: Yang Wang <[email protected]> --- drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 2 +- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 89 +++++++++++++------ drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 5 +- 3 files changed, 68 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index c3688b3b12cc..ce526db4d24a 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -508,7 +508,7 @@ void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev) amdgpu_dpm_notify_ac_dc(adev); if (is_support_sw_smu(adev)) - smu_set_ac_dc(adev->powerplay.pp_handle); + smu_set_ac_dc(adev->powerplay.pp_handle, true); mutex_unlock(&adev->pm.mutex); } diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 99d42446cfc8..43d5dd7dce7e 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -488,12 +488,52 @@ static void smu_set_user_clk_dependencies(struct smu_context *smu, enum smu_clk_ return; } +static void smu_restore_ppt_limits(struct smu_context *smu, + bool restore_defaults) +{ + enum smu_power_src_type power_source; + struct smu_ppt_limit_range *range; + uint32_t restore_mask; + uint32_t limit; + int i, ret; + + power_source = smu->adev->pm.ac_power ? + SMU_POWER_SOURCE_AC : SMU_POWER_SOURCE_DC; + restore_mask = smu->user_dpm_profile.ppt_limit_user_mask[power_source] & + smu->ppt_limits.supported_mask; + if (!restore_mask && !restore_defaults) + return; + + smu->user_dpm_profile.flags |= SMU_DPM_USER_PROFILE_RESTORE; + + for (i = SMU_PPT_LIMIT_PPT0; i < SMU_LIMIT_TYPE_COUNT; i++) { + if (!(smu->ppt_limits.supported_mask & BIT(i))) + continue; + + if (restore_mask & BIT(i)) { + limit = smu->user_dpm_profile.ppt_limits[power_source][i]; + } else if (restore_defaults) { + range = &smu->ppt_limits.range[power_source][i]; + limit = range->default_value; + } else { + continue; + } + + ret = smu_set_ppt_limit(smu, i, limit); + if (ret) + dev_err(smu->adev->dev, + "Failed to restore PPT%d limit: %d\n", i, ret); + } + + smu->user_dpm_profile.flags &= ~SMU_DPM_USER_PROFILE_RESTORE; +} + /** * smu_restore_dpm_user_profile - reinstate user dpm profile * * @smu: smu_context pointer * - * Restore saved user power limits, clock frequencies and fan settings. + * Restore saved user clock frequencies and fan settings. */ static void smu_restore_dpm_user_profile(struct smu_context *smu) { @@ -509,17 +549,6 @@ static void smu_restore_dpm_user_profile(struct smu_context *smu) /* Enable restore flag */ smu->user_dpm_profile.flags |= SMU_DPM_USER_PROFILE_RESTORE; - /* set the user dpm power limits */ - for (int i = SMU_PPT_LIMIT_PPT0; i < SMU_LIMIT_TYPE_COUNT; i++) { - if (!smu->user_dpm_profile.ppt_limits[i]) - continue; - ret = smu_set_ppt_limit(smu, i, - smu->user_dpm_profile.ppt_limits[i]); - if (ret) - dev_err(smu->adev->dev, - "Failed to set %d PPT limit value\n", i); - } - /* set the user dpm clock configurations */ if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { enum smu_clk_type clk_type; @@ -932,7 +961,7 @@ static int smu_late_init(struct amdgpu_ip_block *ip_block) * is unnecessary. */ adev->pm.ac_power = power_supply_is_system_supplied() > 0; - smu_set_ac_dc(smu); + smu_set_ac_dc(smu, false); if ((amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 1)) || (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 3))) @@ -967,6 +996,8 @@ static int smu_late_init(struct amdgpu_ip_block *ip_block) return ret; } + if (adev->in_suspend) + smu_restore_ppt_limits(smu, false); smu_restore_dpm_user_profile(smu); return 0; @@ -2746,7 +2777,7 @@ static int smu_set_watermarks_for_clock_ranges(void *handle, return smu_set_watermarks_table(smu, clock_ranges); } -int smu_set_ac_dc(struct smu_context *smu) +int smu_set_ac_dc(struct smu_context *smu, bool restore_ppt_policy) { int ret = 0; @@ -2754,17 +2785,22 @@ int smu_set_ac_dc(struct smu_context *smu) return -EOPNOTSUPP; /* controlled by firmware */ - if (smu->dc_controlled_by_gpio) - return 0; + if (!smu->dc_controlled_by_gpio) { + ret = smu_set_power_source(smu, + smu->adev->pm.ac_power ? + SMU_POWER_SOURCE_AC : + SMU_POWER_SOURCE_DC); + if (ret) { + dev_err(smu->adev->dev, "Failed to switch to %s mode!\n", + smu->adev->pm.ac_power ? "AC" : "DC"); + return ret; + } + } - ret = smu_set_power_source(smu, - smu->adev->pm.ac_power ? SMU_POWER_SOURCE_AC : - SMU_POWER_SOURCE_DC); - if (ret) - dev_err(smu->adev->dev, "Failed to switch to %s mode!\n", - smu->adev->pm.ac_power ? "AC" : "DC"); + if (restore_ppt_policy) + smu_restore_ppt_limits(smu, true); - return ret; + return 0; } const struct amd_ip_funcs smu_ip_funcs = { @@ -3020,8 +3056,11 @@ static int smu_set_ppt_limit(void *handle, uint32_t limit_type, uint32_t limit) ret = smu->ppt_funcs->set_ppt_limit(smu, limit_type, limit); if (ret) return ret; - if (!(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) - smu->user_dpm_profile.ppt_limits[limit_type] = limit; + if (!(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) { + smu->user_dpm_profile.ppt_limits[power_source][limit_type] = limit; + smu->user_dpm_profile.ppt_limit_user_mask[power_source] |= + BIT(limit_type); + } return 0; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index 3d32ee723b8e..698197a285e3 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -251,7 +251,8 @@ enum smu_memory_pool_size { struct smu_user_dpm_profile { uint32_t fan_mode; - uint32_t ppt_limits[SMU_LIMIT_TYPE_COUNT]; + uint32_t ppt_limits[SMU_POWER_SOURCE_COUNT][SMU_LIMIT_TYPE_COUNT]; + uint32_t ppt_limit_user_mask[SMU_POWER_SOURCE_COUNT]; uint32_t fan_speed_pwm; uint32_t fan_speed_rpm; uint32_t flags; @@ -1953,7 +1954,7 @@ int smu_set_soft_freq_range(struct smu_context *smu, enum pp_clock_type clk_type int smu_set_gfx_power_up_by_imu(struct smu_context *smu); -int smu_set_ac_dc(struct smu_context *smu); +int smu_set_ac_dc(struct smu_context *smu, bool restore_ppt_policy); int smu_set_xgmi_plpd_mode(struct smu_context *smu, enum pp_xgmi_plpd_mode mode); -- 2.54.0