RE: [PATCH 3/4] drm/amd/pm: refactor user PPT policy save and restore
"Wang, Yang(Kevin)" <[email protected]> Fri, 31 Jul 2026 08:05:31 +0000
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <BN9PR12MB52114F26DFDDB7845449E15482C82@BN9PR12MB5211.namprd12.prod.outlook.com> |
AMD General > -----Original Message----- > From: Lazar, Lijo <[email protected]> > Sent: Friday, July 31, 2026 3:45 PM > To: Wang, Yang(Kevin) <[email protected]>; amd- > [email protected] > Cc: Deucher, Alexander <[email protected]>; Zhang, Hawking > <[email protected]>; Feng, Kenneth <[email protected]> > Subject: Re: [PATCH 3/4] drm/amd/pm: refactor user PPT policy save and > restore > > > > On 31-Jul-26 12:21 PM, Wang, Yang(Kevin) wrote: > > AMD General > > > >> -----Original Message----- > >> From: Lazar, Lijo <[email protected]> > >> Sent: Friday, July 31, 2026 12:57 PM > >> To: Wang, Yang(Kevin) <[email protected]>; amd- > >> [email protected] > >> Cc: Deucher, Alexander <[email protected]>; Zhang, Hawking > >> <[email protected]>; Feng, Kenneth <[email protected]> > >> Subject: Re: [PATCH 3/4] drm/amd/pm: refactor user PPT policy save > >> and restore > >> > >> > >> > >> 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 poli= cy. > >>> - 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 =3D smu->adev->pm.ac_power ? > >>> + SMU_POWER_SOURCE_AC : SMU_POWER_SOURCE_DC; > >>> + restore_mask =3D 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 |=3D > >> SMU_DPM_USER_PROFILE_RESTORE; > >>> + > >>> + for (i =3D 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 =3D smu- > >>> user_dpm_profile.ppt_limits[power_source][i]; > >>> + } else if (restore_defaults) { > >>> + range =3D &smu->ppt_limits.range[power_source][i]= ; > >>> + limit =3D 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. > > > > Please check the call sites. > > > > The quoted default path is an opt-in fallback for AC/DC policy restore,= and it > is not used for suspend or GPU reset. > > Suspend and reset invoke smu_restore_ppt_limits(smu, false), which repl= ays > only limits recorded in user_dpm_profile. > > > > Yes, I'm specifically talking about late_init path. It gets called after = a suspend > or reset. It's about a case where user dpm limit is not present. > > > The profile intentionally does not represent out-of-band state, and > > the amdgpu driver has no ownership or synchronization contract for PMFW > limits changed outside the driver. > > Supporting that use case requires separate policy and should be address= ed > in a separate change. > > > > This only requires restoring the current limit after a suspend or reset w= hen > called from smu late init if a user specified limit is not found. > It doesn't need to revert to default limit. Yes, the restore function takes no action if no custom limits are set by th= e user. And the logic has been verified on the target system, including suspend, re= set and default cases. Best Regards, Kevin > > Thanks, > Lijo > > > Best Regards, > > Kevin > >> Thanks, > >> Lijo > >> > >>> + } else { > >>> + continue; > >>> + } > >>> + > >>> + ret =3D 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 &=3D > >> ~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 settin= gs. > >>> + * 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 |=3D > >> SMU_DPM_USER_PROFILE_RESTORE; > >>> > >>> - /* set the user dpm power limits */ > >>> - for (int i =3D SMU_PPT_LIMIT_PPT0; i < SMU_LIMIT_TYPE_COUNT; i++)= { > >>> - if (!smu->user_dpm_profile.ppt_limits[i]) > >>> - continue; > >>> - ret =3D 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 =3D=3D > >> 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 =3D 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) =3D=3D IP_VERSION(13, = 0, > >>> 1)) > >> || > >>> (amdgpu_ip_version(adev, MP1_HWIP, 0) =3D=3D 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 =3D 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 =3D 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 =3D 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 =3D { @@ -3020,8 +3056,11 @= @ > >>> static int smu_set_ppt_limit(void *handle, uint32_t limit_type, > >>> uint32_t > >> limit) > >>> ret =3D 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] =3D limit; > >>> + if (!(smu->user_dpm_profile.flags & > >> SMU_DPM_USER_PROFILE_RESTORE)) { > >>> + smu- > >>> user_dpm_profile.ppt_limits[power_source][limit_type] =3D limit; > >>> + smu->user_dpm_profile.ppt_limit_user_mask[power_source] > >> |=3D > >>> + 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); > >