Re: [PATCH] drm/amd/pm: Track current PPT limit for restore

"Lazar, Lijo" <[email protected]> Thu, 6 Aug 2026 13:32:30 +0530
Newsgroups org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>

On 06-Aug-26 1:26 PM, Wang, Yang(Kevin) wrote:
> AMD General
> 
>> Driver triggers resets which could relaod the whole FW. In such cases driver
>> remains responsible for restoring the last known power limit. The current
>> method doesn't do that.
> 
> No, the original code already contains this restore logic, include suspend/resume + gpu recovery, and save/restore logic has been verified on Navi21 and Navi48 ASICs.
> 
> And the if no user edit power limit from user side, the driver will skip restore power limit, in this case, the driver will use default value after firmware reloading.
> 
> btw, your change will break gpu od + power limit logic in navi3x/navi4x.

This patch doesn't break that. Whatever user has set as the last limit 
will be the current limit in Navi3x/Navi4x case. That will be restored. 
If user hasn't edited limit, current limit will be equivalent to default 
limit and then it's not set again.

> 
> So What issue you have facing now ?
> 

Driver remains responsible for restoring the state triggered by inband 
actions like suspend/resume or reset as OOB doesn't monitor everything. 
In such cases, driver being the inband owner needs to restore the proper 
state after the event.

Thanks,
Lijo
> Best Regards,
> Kevin
> 
>> -----Original Message-----
>> From: Lazar, Lijo <[email protected]>
>> Sent: Thursday, August 6, 2026 3:48 PM
>> To: Wang, Yang(Kevin) <[email protected]>; amd-
>> [email protected]
>> Cc: Zhang, Hawking <[email protected]>; Deucher, Alexander
>> <[email protected]>; Kamal, Asad <[email protected]>
>> Subject: Re: [PATCH] drm/amd/pm: Track current PPT limit for restore
>>
>>
>>
>> On 06-Aug-26 1:03 PM, Wang, Yang(Kevin) wrote:
>>> AMD General
>>>
>>> I do not agree with adding a read-to-cache path for the current PPT limit.
>>>
>>> The current limit is PMFW runtime state. A read of that state must remain an
>> observation; it must not implicitly create or update driver-owned persistent
>> policy.
>>> This separation is intentional: the driver keeps immutable capabilities from
>> the PPTable and restores only limits that it successfully programmed itself.
>>>
>>> Caching a value returned by GetPptLimit would turn a potentially transient
>> or out-of-band PMFW state into a value that the driver replays after suspend
>> or reset.
>>>
>>> There is no ownership, notification, or synchronization mechanism that
>> makes such a cache authoritative, so it can only become stale.
>>> and the existing user_dpm_profile policy *CACHE ALREADY* handles the
>> supported driver-owned update path.
>>>
>>
>> The existing path also doesn't have any synchronization with out-of-band, so
>> the same argument holds. i.e., it overwrites whatever set by external source.
>>> If no bug fix or feature improve, please drop this patch.
>>
>> Driver triggers resets which could relaod the whole FW. In such cases driver
>> remains responsible for restoring the last known power limit. The current
>> method doesn't do that.
>>
>> I will add a bug fix tag as the previous patch doesn't restore the current limit
>> properly.
>>
>> Thanks,
>> Lijo
>>
>>>
>>> Best Regards,
>>> Kevin
>>>
>>>> -----Original Message-----
>>>> From: Lazar, Lijo <[email protected]>
>>>> Sent: Thursday, August 6, 2026 2:14 PM
>>>> To: [email protected]
>>>> Cc: Zhang, Hawking <[email protected]>; Deucher, Alexander
>>>> <[email protected]>; Kamal, Asad <[email protected]>;
>> Wang,
>>>> Yang(Kevin) <[email protected]>
>>>> Subject: [PATCH] drm/amd/pm: Track current PPT limit for restore
>>>>
>>>> Cache the applied PPT limit in the ppt limit range and refresh it on
>>>> every get and set. Initialize with the default value on fresh load; a
>>>> value equal to default is treated as unset.
>>>>
>>>> On suspend or reset recovery, restore the cached current limit when
>>>> it differs from the default, falling back to the default otherwise.
>>>> This replaces the user- mask based restore, covering limits changed
>>>> outside the user profile path as well.
>>>>
>>>> Signed-off-by: Lijo Lazar <[email protected]>
>>>> ---
>>>>    drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c     | 39
>> +++++++++++++----
>>>> --
>>>>    drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h |  1 +
>>>>    2 files changed, 29 insertions(+), 11 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
>>>> b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
>>>> index f45cd4e31415..7edd919a7832 100644
>>>> --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
>>>> +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
>>>> @@ -495,16 +495,11 @@ static void smu_restore_ppt_limits(struct
>>>> smu_context *smu,  {
>>>>         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;
>>>>
>>>> @@ -512,14 +507,14 @@ static void smu_restore_ppt_limits(struct
>>>> smu_context *smu,
>>>>                 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];
>>>> +             range = &smu->ppt_limits.range[power_source][i];
>>>> +             if (range->current_value &&
>>>> +                 range->current_value != range->default_value)
>>>> +                     limit = range->current_value;
>>>> +             else if (restore_defaults)
>>>>                         limit = range->default_value;
>>>> -             } else {
>>>> +             else
>>>>                         continue;
>>>> -             }
>>>>
>>>>                 ret = smu_set_ppt_limit(smu, i, limit);
>>>>                 if (ret)
>>>> @@ -875,6 +870,21 @@ static int smu_early_init(struct amdgpu_ip_block
>>>> *ip_block)
>>>>         return smu_init_microcode(smu);
>>>>    }
>>>>
>>>> +static void smu_init_ppt_limits_current(struct smu_context *smu) {
>>>> +     struct smu_ppt_limit_range *range;
>>>> +     int i, j;
>>>> +
>>>> +     for (i = SMU_POWER_SOURCE_AC; i < SMU_POWER_SOURCE_COUNT;
>>>> i++) {
>>>> +             for (j = SMU_PPT_LIMIT_PPT0; j < SMU_LIMIT_TYPE_COUNT;
>>>> j++) {
>>>> +                     if (!(smu->ppt_limits.supported_mask & BIT(j)))
>>>> +                             continue;
>>>> +                     range = &smu->ppt_limits.range[i][j];
>>>> +                     range->current_value = range->default_value;
>>>> +             }
>>>> +     }
>>>> +}
>>>> +
>>>>    static int smu_set_default_dpm_table(struct smu_context *smu)  {
>>>>         struct amdgpu_device *adev = smu->adev; @@ -1911,6 +1921,9 @@
>>>> static int smu_smc_hw_setup(struct smu_context *smu)
>>>>         if (ret)
>>>>                 dev_err(adev->dev, "Error during wbrf init call\n");
>>>>
>>>> +     if (!adev->in_suspend && !amdgpu_reset_in_recovery(adev))
>>>> +             smu_init_ppt_limits_current(smu);
>>>> +
>>>>         return ret;
>>>>    }
>>>>
>>>> @@ -2999,6 +3012,9 @@ int smu_get_ppt_limit(void *handle,
>>>>         switch (limit_level) {
>>>>         case SMU_PPT_LIMIT_CURRENT:
>>>>                 ret = smu_get_asic_ppt_limit(smu, limit_type, limit);
>>>> +             if (!ret)
>>>> +                     smu-
>>>>> ppt_limits.range[power_source][limit_type].current_value =
>>>> +                             *limit;
>>>>                 break;
>>>>         case SMU_PPT_LIMIT_DEFAULT:
>>>>                 *limit = smu-
>>>>> ppt_limits.range[power_source][limit_type].default_value;
>>>> @@ -3061,6 +3077,7 @@ 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;
>>>> +     range->current_value = 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]
>>>> |= 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 92658eb3886d..5222b48eba25 100644
>>>> --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
>>>> +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
>>>> @@ -229,6 +229,7 @@ enum smu_ppt_limit_level {
>>>>
>>>>    struct smu_ppt_limit_range {
>>>>         uint32_t default_value;
>>>> +     uint32_t current_value;
>>>>         uint32_t min;
>>>>         uint32_t max;
>>>>         uint32_t od_min;
>>>> --
>>>> 2.49.0
>>>
>