[PATCH v2] drm/amd/pm: correct the workload setting

Lazar, Lijo lijo.lazar at amd.com
Tue Oct 29 03:48:13 UTC 2024



On 10/28/2024 11:42 PM, Alex Deucher wrote:
> On Thu, Oct 24, 2024 at 5:18 AM Kenneth Feng <kenneth.feng at amd.com> wrote:
>>
>> Correct the workload setting in order not to mix the setting
>> with the end user. Update the workload mask accordingly.
>>
>> v2: changes as below:
>> 1. the end user can not erase the workload from driver except default workload.
>> 2. always shows the real highest priority workoad to the end user.
>> 3. the real workload mask is combined with driver workload mask and end user workload mask.
> 
> I think this can be simplified.  We just need to store the user
> workload profile and the mask of all of the currently active workload
> profiles (the user selected profile and the any transient ones like
> COMPUTE for KFD, VIDEO for VCN, and POWERSAVE for SMU13, etc.).  At
> init time, the driver sets the user workload profile to FS3D or
> DEFAULT per the current logic.  Add a new parameter to
> ppt_funcs->set_power_profile_mode(), bool
> update_user_workload_profile, which we set to true in
> smu_set_power_profile_mode() which is used by the sysfs code to set
> the user workload profile, and set to false in
> smu_switch_power_profile() which is used internally for KFD and VCN.
> Then the user workload profile would only get changed when the user
> changes it via sysfs.  Meanwhile KFD and VCN can add their workload
> types dynamically at runtime.
> 

I think this approach doesn't work if we want to restore the user
settings after a suspend/resume case (unless we expect it to be user
driven).

Thanks,
Lijo

> Alex
> 
>>
>> Signed-off-by: Kenneth Feng <kenneth.feng at amd.com>
>> ---
>>  drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c     | 44 +++++++++++++------
>>  drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h |  5 ++-
>>  .../drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c  | 31 +++++++++++--
>>  .../drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c  | 25 +++++++++--
>>  .../drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c  | 28 +++++++++---
>>  5 files changed, 106 insertions(+), 27 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
>> index 8d4aee4e2287..1de576461a70 100644
>> --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
>> +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
>> @@ -1261,25 +1261,31 @@ static int smu_sw_init(struct amdgpu_ip_block *ip_block)
>>         smu->watermarks_bitmap = 0;
>>         smu->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
>>         smu->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
>> +       smu->user_dpm_profile.user_workload_mask = 0;
>> +       smu->user_dpm_profile.prev_user_workload_mask = 0;
>>
>>         atomic_set(&smu->smu_power.power_gate.vcn_gated, 1);
>>         atomic_set(&smu->smu_power.power_gate.jpeg_gated, 1);
>>         atomic_set(&smu->smu_power.power_gate.vpe_gated, 1);
>>         atomic_set(&smu->smu_power.power_gate.umsch_mm_gated, 1);
>>
>> -       smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0;
>> -       smu->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1;
>> -       smu->workload_prority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2;
>> -       smu->workload_prority[PP_SMC_POWER_PROFILE_VIDEO] = 3;
>> -       smu->workload_prority[PP_SMC_POWER_PROFILE_VR] = 4;
>> -       smu->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 5;
>> -       smu->workload_prority[PP_SMC_POWER_PROFILE_CUSTOM] = 6;
>> +       smu->workload_priority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0;
>> +       smu->workload_priority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1;
>> +       smu->workload_priority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2;
>> +       smu->workload_priority[PP_SMC_POWER_PROFILE_VIDEO] = 3;
>> +       smu->workload_priority[PP_SMC_POWER_PROFILE_VR] = 4;
>> +       smu->workload_priority[PP_SMC_POWER_PROFILE_COMPUTE] = 5;
>> +       smu->workload_priority[PP_SMC_POWER_PROFILE_CUSTOM] = 6;
>>
>>         if (smu->is_apu ||
>> -           !smu_is_workload_profile_available(smu, PP_SMC_POWER_PROFILE_FULLSCREEN3D))
>> -               smu->workload_mask = 1 << smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
>> -       else
>> -               smu->workload_mask = 1 << smu->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D];
>> +           !smu_is_workload_profile_available(smu, PP_SMC_POWER_PROFILE_FULLSCREEN3D)) {
>> +               smu->workload_mask = 1 << smu->workload_priority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
>> +       } else {
>> +               smu->workload_mask = 1 << smu->workload_priority[PP_SMC_POWER_PROFILE_FULLSCREEN3D];
>> +               smu->default_power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
>> +       }
>> +
>> +       smu->driver_workload_mask = smu->workload_mask;
>>
>>         smu->workload_setting[0] = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
>>         smu->workload_setting[1] = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
>> @@ -2354,12 +2360,14 @@ static int smu_switch_power_profile(void *handle,
>>                 return -EINVAL;
>>
>>         if (!en) {
>> -               smu->workload_mask &= ~(1 << smu->workload_prority[type]);
>> +               smu->workload_mask &= ~(1 << smu->workload_priority[type]);
>> +               smu->driver_workload_mask &= ~(1 << smu->workload_priority[type]);
>>                 index = fls(smu->workload_mask);
>>                 index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
>>                 workload[0] = smu->workload_setting[index];
>>         } else {
>> -               smu->workload_mask |= (1 << smu->workload_prority[type]);
>> +               smu->workload_mask |= (1 << smu->workload_priority[type]);
>> +               smu->driver_workload_mask |= (1 << smu->workload_priority[type]);
>>                 index = fls(smu->workload_mask);
>>                 index = index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
>>                 workload[0] = smu->workload_setting[index];
>> @@ -3054,12 +3062,20 @@ static int smu_set_power_profile_mode(void *handle,
>>                                       uint32_t param_size)
>>  {
>>         struct smu_context *smu = handle;
>> +       int ret;
>>
>>         if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled ||
>>             !smu->ppt_funcs->set_power_profile_mode)
>>                 return -EOPNOTSUPP;
>>
>> -       return smu_bump_power_profile_mode(smu, param, param_size);
>> +       smu->user_dpm_profile.prev_user_workload_mask =
>> +                       smu->user_dpm_profile.user_workload_mask;
>> +       smu->user_dpm_profile.user_workload_mask = (1 << smu->workload_priority[param[param_size]]);
>> +       ret = smu_bump_power_profile_mode(smu, param, param_size);
>> +       smu->user_dpm_profile.prev_user_workload_mask =
>> +                       smu->user_dpm_profile.user_workload_mask;
>> +
>> +       return ret;
>>  }
>>
>>  static int smu_get_fan_control_mode(void *handle, u32 *fan_mode)
>> 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 8bb32b3f0d9c..88294d986b36 100644
>> --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
>> +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
>> @@ -240,6 +240,8 @@ struct smu_user_dpm_profile {
>>         /* user clock state information */
>>         uint32_t clk_mask[SMU_CLK_COUNT];
>>         uint32_t clk_dependency;
>> +       uint32_t user_workload_mask;
>> +       uint32_t prev_user_workload_mask;
>>  };
>>
>>  #define SMU_TABLE_INIT(tables, table_id, s, a, d)      \
>> @@ -557,7 +559,8 @@ struct smu_context {
>>         bool disable_uclk_switch;
>>
>>         uint32_t workload_mask;
>> -       uint32_t workload_prority[WORKLOAD_POLICY_MAX];
>> +       uint32_t driver_workload_mask;
>> +       uint32_t workload_priority[WORKLOAD_POLICY_MAX];
>>         uint32_t workload_setting[WORKLOAD_POLICY_MAX];
>>         uint32_t power_profile_mode;
>>         uint32_t default_power_profile_mode;
>> diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
>> index 3e2277abc754..0733fd3efd8b 100644
>> --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
>> +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
>> @@ -2474,9 +2474,22 @@ static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu,
>>                 &(activity_monitor_external.DpmActivityMonitorCoeffInt);
>>         int workload_type, ret = 0;
>>         u32 workload_mask;
>> +       uint32_t index;
>>
>>         smu->power_profile_mode = input[size];
>>
>> +       if (smu->user_dpm_profile.prev_user_workload_mask !=
>> +               smu->user_dpm_profile.user_workload_mask) {
>> +               if (smu->workload_mask & smu->user_dpm_profile.prev_user_workload_mask &&
>> +                       !(smu->driver_workload_mask & smu->user_dpm_profile.prev_user_workload_mask))
>> +                       smu->workload_mask &= ~smu->user_dpm_profile.prev_user_workload_mask;
>> +
>> +               if (input[size] != smu->default_power_profile_mode) {
>> +                       smu->workload_mask &= ~(1 << smu->workload_priority[smu->default_power_profile_mode]);
>> +                       smu->driver_workload_mask &= ~(1 << smu->workload_priority[smu->default_power_profile_mode]);
>> +               }
>> +       }
> 
> This is repeated in several places and could be split out into a
> helper function.
> 
>> +
>>         if (smu->power_profile_mode >= PP_SMC_POWER_PROFILE_COUNT) {
>>                 dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode);
>>                 return -EINVAL;
>> @@ -2555,12 +2568,24 @@ static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu,
>>                         workload_mask |= 1 << workload_type;
>>         }
>>
>> +       smu->workload_mask |= workload_mask;
>>         ret = smu_cmn_send_smc_msg_with_param(smu,
>>                                                SMU_MSG_SetWorkloadMask,
>> -                                              workload_mask,
>> +                                              smu->workload_mask,
>>                                                NULL);
>> -       if (!ret)
>> -               smu->workload_mask = workload_mask;
>> +       if (!ret) {
>> +               index = fls(smu->workload_mask);
>> +               index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
>> +               smu->power_profile_mode = smu->workload_setting[index];
>> +               if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_POWERSAVING) {
>> +                       workload_type = smu_cmn_to_asic_specific_index(smu,
>> +                                                              CMN2ASIC_MAPPING_WORKLOAD,
>> +                                                              PP_SMC_POWER_PROFILE_FULLSCREEN3D);
>> +                       smu->power_profile_mode = smu->workload_mask & (1 << workload_type)
>> +                                                                               ? PP_SMC_POWER_PROFILE_FULLSCREEN3D
>> +                                                                               : PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
>> +               }
>> +       }
>>
>>         return ret;
>>  }
>> diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
>> index 23f13388455f..2323c74ee50b 100644
>> --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
>> +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
>> @@ -2429,9 +2429,22 @@ static int smu_v13_0_7_set_power_profile_mode(struct smu_context *smu, long *inp
>>         DpmActivityMonitorCoeffInt_t *activity_monitor =
>>                 &(activity_monitor_external.DpmActivityMonitorCoeffInt);
>>         int workload_type, ret = 0;
>> +       uint32_t index;
>>
>>         smu->power_profile_mode = input[size];
>>
>> +       if (smu->user_dpm_profile.prev_user_workload_mask !=
>> +               smu->user_dpm_profile.user_workload_mask) {
>> +               if (smu->workload_mask & smu->user_dpm_profile.prev_user_workload_mask &&
>> +                       !(smu->driver_workload_mask & smu->user_dpm_profile.prev_user_workload_mask))
>> +                       smu->workload_mask &= ~smu->user_dpm_profile.prev_user_workload_mask;
>> +
>> +               if (input[size] != smu->default_power_profile_mode) {
>> +                       smu->workload_mask &= ~(1 << smu->workload_priority[smu->default_power_profile_mode]);
>> +                       smu->driver_workload_mask &= ~(1 << smu->workload_priority[smu->default_power_profile_mode]);
>> +               }
>> +       }
>> +
>>         if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_WINDOW3D) {
>>                 dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode);
>>                 return -EINVAL;
>> @@ -2487,13 +2500,19 @@ static int smu_v13_0_7_set_power_profile_mode(struct smu_context *smu, long *inp
>>                                                        smu->power_profile_mode);
>>         if (workload_type < 0)
>>                 return -EINVAL;
>> +
>> +       smu->workload_mask |= (1 << workload_type);
>>         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
>> -                                   1 << workload_type, NULL);
>> +                                   smu->workload_mask, NULL);
>>
>>         if (ret)
>>                 dev_err(smu->adev->dev, "[%s] Failed to set work load mask!", __func__);
>> -       else
>> -               smu->workload_mask = (1 << workload_type);
>> +
>> +       if (!ret) {
>> +               index = fls(smu->workload_mask);
>> +               index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
>> +               smu->power_profile_mode = smu->workload_setting[index];
>> +       }
>>
>>         return ret;
>>  }
>> diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
>> index cefe10b95d8e..c2fd47f04e2d 100644
>> --- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
>> +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
>> @@ -1787,9 +1787,22 @@ static int smu_v14_0_2_set_power_profile_mode(struct smu_context *smu,
>>         DpmActivityMonitorCoeffInt_t *activity_monitor =
>>                 &(activity_monitor_external.DpmActivityMonitorCoeffInt);
>>         int workload_type, ret = 0;
>> +       uint32_t index;
>>         uint32_t current_profile_mode = smu->power_profile_mode;
>>         smu->power_profile_mode = input[size];
>>
>> +       if (smu->user_dpm_profile.prev_user_workload_mask !=
>> +               smu->user_dpm_profile.user_workload_mask) {
>> +               if (smu->workload_mask & smu->user_dpm_profile.prev_user_workload_mask &&
>> +                       !(smu->driver_workload_mask & smu->user_dpm_profile.prev_user_workload_mask))
>> +                       smu->workload_mask &= ~smu->user_dpm_profile.prev_user_workload_mask;
>> +
>> +               if (input[size] != smu->default_power_profile_mode) {
>> +                       smu->workload_mask &= ~(1 << smu->workload_priority[smu->default_power_profile_mode]);
>> +                       smu->driver_workload_mask &= ~(1 << smu->workload_priority[smu->default_power_profile_mode]);
>> +               }
>> +       }
>> +
>>         if (smu->power_profile_mode >= PP_SMC_POWER_PROFILE_COUNT) {
>>                 dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode);
>>                 return -EINVAL;
>> @@ -1857,12 +1870,15 @@ static int smu_v14_0_2_set_power_profile_mode(struct smu_context *smu,
>>         if (workload_type < 0)
>>                 return -EINVAL;
>>
>> -       ret = smu_cmn_send_smc_msg_with_param(smu,
>> -                                              SMU_MSG_SetWorkloadMask,
>> -                                              1 << workload_type,
>> -                                              NULL);
>> -       if (!ret)
>> -               smu->workload_mask = 1 << workload_type;
>> +       smu->workload_mask |= (1 << workload_type);
>> +       ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
>> +                                                                                 smu->workload_mask, NULL);
>> +
>> +       if (!ret) {
>> +               index = fls(smu->workload_mask);
>> +               index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
>> +               smu->power_profile_mode = smu->workload_setting[index];
>> +       }
>>
>>         return ret;
>>  }
>> --
>> 2.34.1
>>


More information about the amd-gfx mailing list