Re: [PATCH 3/4] drm/amd/pm: refactor user PPT policy save and restore
"Lazar, Lijo" <[email protected]> Fri, 31 Jul 2026 10:27:24 +0530
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <[email protected]> |
On 31-Jul-26 8:40 AM, Yang Wang wrote: > 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; This should be restore the current limit before a suspend/reset and not the default limit. The current limit could be set through out of band also, user profile values won't reflect that. Thanks, Lijo > + } 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);