<div dir="ltr"><div dir="ltr">On Tue, Nov 12, 2024 at 1:18 AM Lazar, Lijo <<a href="mailto:lijo.lazar@amd.com">lijo.lazar@amd.com</a>> wrote:</div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
<br>
On 11/9/2024 11:01 AM, Alex Deucher wrote:<br>
> smu->workload_mask is IP specific and should not be messed with in<br>
> the common code. The mask bits vary across SMU versions.<br>
> <br>
> Move all handling of smu->workload_mask in to the backends and<br>
> simplify the code.  Store the user's preference in smu->power_profile_mode<br>
> which will be reflected in sysfs.  For internal driver profile<br>
> switches for KFD or VCN, just update the workload mask so that the<br>
> user's preference is retained.  Remove all of the extra now unused<br>
> workload related elements in the smu structure.<br>
> <br>
> Fixes: 8cc438be5d49 ("drm/amd/pm: correct the workload setting")<br>
> Signed-off-by: Alex Deucher <<a href="mailto:alexander.deucher@amd.com" target="_blank">alexander.deucher@amd.com</a>><br>
> Cc: Kenneth Feng <<a href="mailto:kenneth.feng@amd.com" target="_blank">kenneth.feng@amd.com</a>><br>
> Cc: Lijo Lazar <<a href="mailto:lijo.lazar@amd.com" target="_blank">lijo.lazar@amd.com</a>><br>
> ---<br>
>  drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c     | 108 ++++++------------<br>
>  drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h |  11 +-<br>
>  .../gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c |  20 ++--<br>
>  .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c   |  20 ++--<br>
>  .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c   |  21 ++--<br>
>  .../gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c  |  17 +--<br>
>  .../gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c   |  17 +--<br>
>  .../drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c  |  33 +++---<br>
>  .../drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c  |  21 ++--<br>
>  .../drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c  |  24 ++--<br>
>  drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c        |   8 --<br>
>  drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h        |   2 -<br>
>  12 files changed, 132 insertions(+), 170 deletions(-)<br>
> <br>
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c<br>
> index c3a6b6f20455..162a3289855c 100644<br>
> --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c<br>
> +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c<br>
> @@ -1268,9 +1268,6 @@ static int smu_sw_init(struct amdgpu_ip_block *ip_block)<br>
>       INIT_WORK(&smu->interrupt_work, smu_interrupt_work_fn);<br>
>       atomic64_set(&smu->throttle_int_counter, 0);<br>
>       smu->watermarks_bitmap = 0;<br>
> -     smu->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;<br>
> -     smu->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;<br>
> -     smu->user_dpm_profile.user_workload_mask = 0;<br>
>  <br>
>       for (i = 0; i < adev->vcn.num_vcn_inst; i++)<br>
>               atomic_set(&smu->smu_power.power_gate.vcn_gated[i], 1);<br>
> @@ -1278,33 +1275,12 @@ static int smu_sw_init(struct amdgpu_ip_block *ip_block)<br>
>       atomic_set(&smu->smu_power.power_gate.vpe_gated, 1);<br>
>       atomic_set(&smu->smu_power.power_gate.umsch_mm_gated, 1);<br>
>  <br>
> -     smu->workload_priority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0;<br>
> -     smu->workload_priority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1;<br>
> -     smu->workload_priority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2;<br>
> -     smu->workload_priority[PP_SMC_POWER_PROFILE_VIDEO] = 3;<br>
> -     smu->workload_priority[PP_SMC_POWER_PROFILE_VR] = 4;<br>
> -     smu->workload_priority[PP_SMC_POWER_PROFILE_COMPUTE] = 5;<br>
> -     smu->workload_priority[PP_SMC_POWER_PROFILE_CUSTOM] = 6;<br>
> -<br>
>       if (smu->is_apu ||<br>
> -         !smu_is_workload_profile_available(smu, PP_SMC_POWER_PROFILE_FULLSCREEN3D)) {<br>
> -             smu->driver_workload_mask =<br>
> -                     1 << smu->workload_priority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];<br>
> -     } else {<br>
> -             smu->driver_workload_mask =<br>
> -                     1 << smu->workload_priority[PP_SMC_POWER_PROFILE_FULLSCREEN3D];<br>
> -             smu->default_power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;<br>
> -     }<br>
> -<br>
> -     smu->workload_mask = smu->driver_workload_mask |<br>
> -                                                     smu->user_dpm_profile.user_workload_mask;<br>
> -     smu->workload_setting[0] = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;<br>
> -     smu->workload_setting[1] = PP_SMC_POWER_PROFILE_FULLSCREEN3D;<br>
> -     smu->workload_setting[2] = PP_SMC_POWER_PROFILE_POWERSAVING;<br>
> -     smu->workload_setting[3] = PP_SMC_POWER_PROFILE_VIDEO;<br>
> -     smu->workload_setting[4] = PP_SMC_POWER_PROFILE_VR;<br>
> -     smu->workload_setting[5] = PP_SMC_POWER_PROFILE_COMPUTE;<br>
> -     smu->workload_setting[6] = PP_SMC_POWER_PROFILE_CUSTOM;<br>
> +         !smu_is_workload_profile_available(smu, PP_SMC_POWER_PROFILE_FULLSCREEN3D))<br>
> +             smu->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;<br>
> +     else<br>
> +             smu->power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;<br>
> +<br>
>       smu->display_config = &adev->pm.pm_display_cfg;<br>
>  <br>
>       smu->smu_dpm.dpm_level = AMD_DPM_FORCED_LEVEL_AUTO;<br>
> @@ -2252,24 +2228,23 @@ static int smu_enable_umd_pstate(void *handle,<br>
>  }<br>
>  <br>
>  static int smu_bump_power_profile_mode(struct smu_context *smu,<br>
> -                                        long *param,<br>
> -                                        uint32_t param_size)<br>
> +                                    long *param,<br>
> +                                    uint32_t param_size,<br>
> +                                    bool enable)<br>
>  {<br>
>       int ret = 0;<br>
>  <br>
>       if (smu->ppt_funcs->set_power_profile_mode)<br>
> -             ret = smu->ppt_funcs->set_power_profile_mode(smu, param, param_size);<br>
> +             ret = smu->ppt_funcs->set_power_profile_mode(smu, param, param_size, enable);<br>
>  <br>
>       return ret;<br>
>  }<br>
>  <br>
>  static int smu_adjust_power_state_dynamic(struct smu_context *smu,<br>
>                                         enum amd_dpm_forced_level level,<br>
> -                                       bool skip_display_settings,<br>
> -                                       bool init)<br>
> +                                       bool skip_display_settings)<br>
>  {<br>
>       int ret = 0;<br>
> -     int index = 0;<br>
>       long workload[1];<br>
>       struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);<br>
>  <br>
> @@ -2307,13 +2282,10 @@ static int smu_adjust_power_state_dynamic(struct smu_context *smu,<br>
>       }<br>
>  <br>
>       if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL &&<br>
> -             smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM) {<br>
> -             index = fls(smu->workload_mask);<br>
> -             index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;<br>
> -             workload[0] = smu->workload_setting[index];<br>
> +         smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM) {<br>
> +             workload[0] = smu->power_profile_mode;<br>
>  <br>
> -             if (init || smu->power_profile_mode != workload[0])<br>
> -                     smu_bump_power_profile_mode(smu, workload, 0);<br>
> +             smu_bump_power_profile_mode(smu, workload, 0, true);<br>
>       }<br>
>  <br>
>       return ret;<br>
> @@ -2333,13 +2305,13 @@ static int smu_handle_task(struct smu_context *smu,<br>
>               ret = smu_pre_display_config_changed(smu);<br>
>               if (ret)<br>
>                       return ret;<br>
> -             ret = smu_adjust_power_state_dynamic(smu, level, false, false);<br>
> +             ret = smu_adjust_power_state_dynamic(smu, level, false);<br>
>               break;<br>
>       case AMD_PP_TASK_COMPLETE_INIT:<br>
> -             ret = smu_adjust_power_state_dynamic(smu, level, true, true);<br>
> +             ret = smu_adjust_power_state_dynamic(smu, level, true);<br>
>               break;<br>
>       case AMD_PP_TASK_READJUST_POWER_STATE:<br>
> -             ret = smu_adjust_power_state_dynamic(smu, level, true, false);<br>
> +             ret = smu_adjust_power_state_dynamic(smu, level, true);<br>
>               break;<br>
>       default:<br>
>               break;<br>
> @@ -2361,12 +2333,11 @@ static int smu_handle_dpm_task(void *handle,<br>
>  <br>
>  static int smu_switch_power_profile(void *handle,<br>
>                                   enum PP_SMC_POWER_PROFILE type,<br>
> -                                 bool en)<br>
> +                                 bool enable)<br>
>  {<br>
>       struct smu_context *smu = handle;<br>
>       struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);<br>
>       long workload[1];<br>
> -     uint32_t index;<br>
>  <br>
>       if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)<br>
>               return -EOPNOTSUPP;<br>
> @@ -2374,24 +2345,15 @@ static int smu_switch_power_profile(void *handle,<br>
>       if (!(type < PP_SMC_POWER_PROFILE_CUSTOM))<br>
>               return -EINVAL;<br>
>  <br>
> -     if (!en) {<br>
> -             smu->driver_workload_mask &= ~(1 << smu->workload_priority[type]);<br>
> -             index = fls(smu->workload_mask);<br>
> -             index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;<br>
> -             workload[0] = smu->workload_setting[index];<br>
> -     } else {<br>
> -             smu->driver_workload_mask |= (1 << smu->workload_priority[type]);<br>
> -             index = fls(smu->workload_mask);<br>
> -             index = index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;<br>
> -             workload[0] = smu->workload_setting[index];<br>
> -     }<br>
> +     /* don't disable the user's preference */<br>
> +     if (!enable && type == smu->power_profile_mode)<br>
> +             return 0;<br>
>  <br>
> -     smu->workload_mask = smu->driver_workload_mask |<br>
> -                                              smu->user_dpm_profile.user_workload_mask;<br>
> +     workload[0] = type;<br>
>  <br>
>       if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL &&<br>
> -             smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM)<br>
> -             smu_bump_power_profile_mode(smu, workload, 0);<br>
> +         smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM)<br>
> +             smu_bump_power_profile_mode(smu, workload, 0, enable);<br>
>  <br>
>       return 0;<br>
>  }<br>
> @@ -3090,21 +3052,25 @@ static int smu_set_power_profile_mode(void *handle,<br>
>                                     uint32_t param_size)<br>
>  {<br>
>       struct smu_context *smu = handle;<br>
> -     int ret;<br>
> +     long workload[1];<br>
> +     int ret = 0;<br>
>  <br>
>       if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled ||<br>
>           !smu->ppt_funcs->set_power_profile_mode)<br>
>               return -EOPNOTSUPP;<br>
>  <br>
> -     if (smu->user_dpm_profile.user_workload_mask &<br>
> -        (1 << smu->workload_priority[param[param_size]]))<br>
> -        return 0;<br>
> -<br>
> -     smu->user_dpm_profile.user_workload_mask =<br>
> -             (1 << smu->workload_priority[param[param_size]]);<br>
> -     smu->workload_mask = smu->user_dpm_profile.user_workload_mask |<br>
> -             smu->driver_workload_mask;<br>
> -     ret = smu_bump_power_profile_mode(smu, param, param_size);<br>
> +     if (param[param_size] != smu->power_profile_mode) {<br>
> +             /* clear the old user preference */<br>
> +             workload[0] = smu->power_profile_mode;<br>
> +             ret = smu_bump_power_profile_mode(smu, workload, 0, false);<br>
<br>
What if internal driver call has set the same profile preference? Once<br>
this is done, that setting is lost. There is a check to make sure that<br>
user setting is not lost, but the same is not done here and cannot be<br>
done with a single profile mode value.<br></blockquote><div><br></div><div>Yeah, I think we need to ref count the workload hints so we keep the mask up to date.</div><div><br></div><div>Alex<br></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
Thanks,<br>
Lijo<br>
<br>
> +             if (ret)<br>
> +                     return ret;<br>
> +             /* set the new user preference */<br>
> +             ret = smu_bump_power_profile_mode(smu, param, param_size, true);<br>
> +             if (!ret)<br>
> +                     /* store the user's preference */<br>
> +                     smu->power_profile_mode = param[param_size];<br>
> +     }<br>
>  <br>
>       return ret;<br>
>  }<br>
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h<br>
> index fa93a8879113..cd2db06d752b 100644<br>
> --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h<br>
> +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h<br>
> @@ -240,7 +240,6 @@ struct smu_user_dpm_profile {<br>
>       /* user clock state information */<br>
>       uint32_t clk_mask[SMU_CLK_COUNT];<br>
>       uint32_t clk_dependency;<br>
> -     uint32_t user_workload_mask;<br>
>  };<br>
>  <br>
>  #define SMU_TABLE_INIT(tables, table_id, s, a, d)    \<br>
> @@ -557,12 +556,10 @@ struct smu_context {<br>
>       uint32_t hard_min_uclk_req_from_dal;<br>
>       bool disable_uclk_switch;<br>
>  <br>
> +     /* backend specific workload mask */<br>
>       uint32_t workload_mask;<br>
> -     uint32_t driver_workload_mask;<br>
> -     uint32_t workload_priority[WORKLOAD_POLICY_MAX];<br>
> -     uint32_t workload_setting[WORKLOAD_POLICY_MAX];<br>
> +     /* default/user workload preference */<br>
>       uint32_t power_profile_mode;<br>
> -     uint32_t default_power_profile_mode;<br>
>       bool pm_enabled;<br>
>       bool is_apu;<br>
>  <br>
> @@ -734,8 +731,10 @@ struct pptable_funcs {<br>
>        *                          create/set custom power profile modes.<br>
>        * &input: Power profile mode parameters.<br>
>        * &size: Size of &input.<br>
> +      * &enable: enable/disable the profile<br>
>        */<br>
> -     int (*set_power_profile_mode)(struct smu_context *smu, long *input, uint32_t size);<br>
> +     int (*set_power_profile_mode)(struct smu_context *smu, long *input,<br>
> +                                   uint32_t size, bool enable);<br>
>  <br>
>       /**<br>
>        * @dpm_set_vcn_enable: Enable/disable VCN engine dynamic power<br>
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c<br>
> index 4b36c230e43a..1e44cf6fec4b 100644<br>
> --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c<br>
> +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c<br>
> @@ -1443,7 +1443,8 @@ static int arcturus_get_power_profile_mode(struct smu_context *smu,<br>
>  <br>
>  static int arcturus_set_power_profile_mode(struct smu_context *smu,<br>
>                                          long *input,<br>
> -                                        uint32_t size)<br>
> +                                        uint32_t size,<br>
> +                                        bool enable)<br>
>  {<br>
>       DpmActivityMonitorCoeffInt_t activity_monitor;<br>
>       int workload_type = 0;<br>
> @@ -1455,8 +1456,9 @@ static int arcturus_set_power_profile_mode(struct smu_context *smu,<br>
>               return -EINVAL;<br>
>       }<br>
>  <br>
> -     if ((profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) &&<br>
> -          (smu->smc_fw_version >= 0x360d00)) {<br>
> +     if (enable &&<br>
> +         (profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) &&<br>
> +         (smu->smc_fw_version >= 0x360d00)) {<br>
>               if (size != 10)<br>
>                       return -EINVAL;<br>
>  <br>
> @@ -1520,18 +1522,18 @@ static int arcturus_set_power_profile_mode(struct smu_context *smu,<br>
>               return -EINVAL;<br>
>       }<br>
>  <br>
> +     if (enable)<br>
> +             smu->workload_mask |= (1 << workload_type);<br>
> +     else<br>
> +             smu->workload_mask &= ~(1 << workload_type);<br>
>       ret = smu_cmn_send_smc_msg_with_param(smu,<br>
>                                         SMU_MSG_SetWorkloadMask,<br>
>                                         smu->workload_mask,<br>
>                                         NULL);<br>
> -     if (ret) {<br>
> +     if (ret)<br>
>               dev_err(smu->adev->dev, "Fail to set workload type %d\n", workload_type);<br>
> -             return ret;<br>
> -     }<br>
> -<br>
> -     smu_cmn_assign_power_profile(smu);<br>
>  <br>
> -     return 0;<br>
> +     return ret;<br>
>  }<br>
>  <br>
>  static int arcturus_set_performance_level(struct smu_context *smu,<br>
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c<br>
> index 211635dabed8..d944a9f954d0 100644<br>
> --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c<br>
> +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c<br>
> @@ -2006,19 +2006,19 @@ static int navi10_get_power_profile_mode(struct smu_context *smu, char *buf)<br>
>       return size;<br>
>  }<br>
>  <br>
> -static int navi10_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)<br>
> +static int navi10_set_power_profile_mode(struct smu_context *smu, long *input,<br>
> +                                      uint32_t size, bool enable)<br>
>  {<br>
>       DpmActivityMonitorCoeffInt_t activity_monitor;<br>
>       int workload_type, ret = 0;<br>
> +     uint32_t profile_mode = input[size];<br>
>  <br>
> -     smu->power_profile_mode = input[size];<br>
> -<br>
> -     if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {<br>
> -             dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode);<br>
> +     if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {<br>
> +             dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode);<br>
>               return -EINVAL;<br>
>       }<br>
>  <br>
> -     if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {<br>
> +     if (enable && profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {<br>
>               if (size != 10)<br>
>                       return -EINVAL;<br>
>  <br>
> @@ -2080,16 +2080,18 @@ static int navi10_set_power_profile_mode(struct smu_context *smu, long *input, u<br>
>       /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */<br>
>       workload_type = smu_cmn_to_asic_specific_index(smu,<br>
>                                                      CMN2ASIC_MAPPING_WORKLOAD,<br>
> -                                                    smu->power_profile_mode);<br>
> +                                                    profile_mode);<br>
>       if (workload_type < 0)<br>
>               return -EINVAL;<br>
>  <br>
> +     if (enable)<br>
> +             smu->workload_mask |= (1 << workload_type);<br>
> +     else<br>
> +             smu->workload_mask &= ~(1 << workload_type);<br>
>       ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,<br>
>                                   smu->workload_mask, NULL);<br>
>       if (ret)<br>
>               dev_err(smu->adev->dev, "[%s] Failed to set work load mask!", __func__);<br>
> -     else<br>
> -             smu_cmn_assign_power_profile(smu);<br>
>  <br>
>       return ret;<br>
>  }<br>
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c<br>
> index 844532a9b641..4967e087088b 100644<br>
> --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c<br>
> +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c<br>
> @@ -1704,22 +1704,23 @@ static int sienna_cichlid_get_power_profile_mode(struct smu_context *smu, char *<br>
>       return size;<br>
>  }<br>
>  <br>
> -static int sienna_cichlid_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)<br>
> +static int sienna_cichlid_set_power_profile_mode(struct smu_context *smu,<br>
> +                                              long *input, uint32_t size,<br>
> +                                              bool enable)<br>
>  {<br>
>  <br>
>       DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;<br>
>       DpmActivityMonitorCoeffInt_t *activity_monitor =<br>
>               &(activity_monitor_external.DpmActivityMonitorCoeffInt);<br>
> +     uint32_t profile_mode = input[size];<br>
>       int workload_type, ret = 0;<br>
>  <br>
> -     smu->power_profile_mode = input[size];<br>
> -<br>
> -     if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {<br>
> -             dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode);<br>
> +     if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {<br>
> +             dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode);<br>
>               return -EINVAL;<br>
>       }<br>
>  <br>
> -     if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {<br>
> +     if (enable && profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {<br>
>               if (size != 10)<br>
>                       return -EINVAL;<br>
>  <br>
> @@ -1781,16 +1782,18 @@ static int sienna_cichlid_set_power_profile_mode(struct smu_context *smu, long *<br>
>       /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */<br>
>       workload_type = smu_cmn_to_asic_specific_index(smu,<br>
>                                                      CMN2ASIC_MAPPING_WORKLOAD,<br>
> -                                                    smu->power_profile_mode);<br>
> +                                                    profile_mode);<br>
>       if (workload_type < 0)<br>
>               return -EINVAL;<br>
>  <br>
> +     if (enable)<br>
> +             smu->workload_mask |= (1 << workload_type);<br>
> +     else<br>
> +             smu->workload_mask &= ~(1 << workload_type);<br>
>       ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,<br>
>                                   smu->workload_mask, NULL);<br>
>       if (ret)<br>
>               dev_err(smu->adev->dev, "[%s] Failed to set work load mask!", __func__);<br>
> -     else<br>
> -             smu_cmn_assign_power_profile(smu);<br>
>  <br>
>       return ret;<br>
>  }<br>
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c<br>
> index f89c487dce72..b5dba4826f81 100644<br>
> --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c<br>
> +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c<br>
> @@ -1056,7 +1056,8 @@ static int vangogh_get_power_profile_mode(struct smu_context *smu,<br>
>       return size;<br>
>  }<br>
>  <br>
> -static int vangogh_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)<br>
> +static int vangogh_set_power_profile_mode(struct smu_context *smu, long *input,<br>
> +                                       uint32_t size, bool enable)<br>
>  {<br>
>       int workload_type, ret;<br>
>       uint32_t profile_mode = input[size];<br>
> @@ -1067,7 +1068,7 @@ static int vangogh_set_power_profile_mode(struct smu_context *smu, long *input,<br>
>       }<br>
>  <br>
>       if (profile_mode == PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT ||<br>
> -                     profile_mode == PP_SMC_POWER_PROFILE_POWERSAVING)<br>
> +         profile_mode == PP_SMC_POWER_PROFILE_POWERSAVING)<br>
>               return 0;<br>
>  <br>
>       /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */<br>
> @@ -1080,18 +1081,18 @@ static int vangogh_set_power_profile_mode(struct smu_context *smu, long *input,<br>
>               return -EINVAL;<br>
>       }<br>
>  <br>
> +     if (enable)<br>
> +             smu->workload_mask |= (1 << workload_type);<br>
> +     else<br>
> +             smu->workload_mask &= ~(1 << workload_type);<br>
>       ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify,<br>
>                                   smu->workload_mask,<br>
>                                   NULL);<br>
> -     if (ret) {<br>
> +     if (ret)<br>
>               dev_err_once(smu->adev->dev, "Fail to set workload type %d\n",<br>
>                                       workload_type);<br>
> -             return ret;<br>
> -     }<br>
> -<br>
> -     smu_cmn_assign_power_profile(smu);<br>
>  <br>
> -     return 0;<br>
> +     return ret;<br>
>  }<br>
>  <br>
>  static int vangogh_set_soft_freq_limited_range(struct smu_context *smu,<br>
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c<br>
> index 75a9ea87f419..2d1eae79ab9d 100644<br>
> --- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c<br>
> +++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c<br>
> @@ -864,7 +864,8 @@ static int renoir_force_clk_levels(struct smu_context *smu,<br>
>       return ret;<br>
>  }<br>
>  <br>
> -static int renoir_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)<br>
> +static int renoir_set_power_profile_mode(struct smu_context *smu, long *input,<br>
> +                                      uint32_t size, bool enable)<br>
>  {<br>
>       int workload_type, ret;<br>
>       uint32_t profile_mode = input[size];<br>
> @@ -875,7 +876,7 @@ static int renoir_set_power_profile_mode(struct smu_context *smu, long *input, u<br>
>       }<br>
>  <br>
>       if (profile_mode == PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT ||<br>
> -                     profile_mode == PP_SMC_POWER_PROFILE_POWERSAVING)<br>
> +         profile_mode == PP_SMC_POWER_PROFILE_POWERSAVING)<br>
>               return 0;<br>
>  <br>
>       /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */<br>
> @@ -891,17 +892,17 @@ static int renoir_set_power_profile_mode(struct smu_context *smu, long *input, u<br>
>               return -EINVAL;<br>
>       }<br>
>  <br>
> +     if (enable)<br>
> +             smu->workload_mask |= (1 << workload_type);<br>
> +     else<br>
> +             smu->workload_mask &= ~(1 << workload_type);<br>
>       ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify,<br>
>                                   smu->workload_mask,<br>
>                                   NULL);<br>
> -     if (ret) {<br>
> +     if (ret)<br>
>               dev_err_once(smu->adev->dev, "Fail to set workload type %d\n", workload_type);<br>
> -             return ret;<br>
> -     }<br>
>  <br>
> -     smu_cmn_assign_power_profile(smu);<br>
> -<br>
> -     return 0;<br>
> +     return ret;<br>
>  }<br>
>  <br>
>  static int renoir_set_peak_clock_by_device(struct smu_context *smu)<br>
> 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<br>
> index 80c6b1e523aa..3cc734331891 100644<br>
> --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c<br>
> +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c<br>
> @@ -2573,22 +2573,22 @@ static int smu_v13_0_0_get_power_profile_mode(struct smu_context *smu,<br>
>  <br>
>  static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu,<br>
>                                             long *input,<br>
> -                                           uint32_t size)<br>
> +                                           uint32_t size,<br>
> +                                           bool enable)<br>
>  {<br>
>       DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;<br>
>       DpmActivityMonitorCoeffInt_t *activity_monitor =<br>
>               &(activity_monitor_external.DpmActivityMonitorCoeffInt);<br>
> +     uint32_t profile_mode = input[size];<br>
>       int workload_type, ret = 0;<br>
>       u32 workload_mask;<br>
>  <br>
> -     smu->power_profile_mode = input[size];<br>
> -<br>
> -     if (smu->power_profile_mode >= PP_SMC_POWER_PROFILE_COUNT) {<br>
> -             dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode);<br>
> +     if (profile_mode >= PP_SMC_POWER_PROFILE_COUNT) {<br>
> +             dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode);<br>
>               return -EINVAL;<br>
>       }<br>
>  <br>
> -     if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {<br>
> +     if (enable && profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {<br>
>               if (size != 9)<br>
>                       return -EINVAL;<br>
>  <br>
> @@ -2641,13 +2641,18 @@ static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu,<br>
>       /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */<br>
>       workload_type = smu_cmn_to_asic_specific_index(smu,<br>
>                                                      CMN2ASIC_MAPPING_WORKLOAD,<br>
> -                                                    smu->power_profile_mode);<br>
> +                                                    profile_mode);<br>
>  <br>
>       if (workload_type < 0)<br>
>               return -EINVAL;<br>
>  <br>
>       workload_mask = 1 << workload_type;<br>
>  <br>
> +     if (enable)<br>
> +             smu->workload_mask |= workload_mask;<br>
> +     else<br>
> +             smu->workload_mask &= ~workload_mask;<br>
> +<br>
>       /* Add optimizations for SMU13.0.0/10.  Reuse the power saving profile */<br>
>       if ((amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 0) &&<br>
>            ((smu->adev->pm.fw_version == 0x004e6601) ||<br>
> @@ -2658,25 +2663,13 @@ static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu,<br>
>                                                              CMN2ASIC_MAPPING_WORKLOAD,<br>
>                                                              PP_SMC_POWER_PROFILE_POWERSAVING);<br>
>               if (workload_type >= 0)<br>
> -                     workload_mask |= 1 << workload_type;<br>
> +                     smu->workload_mask |= 1 << workload_type;<br>
>       }<br>
>  <br>
> -     smu->workload_mask |= workload_mask;<br>
>       ret = smu_cmn_send_smc_msg_with_param(smu,<br>
>                                              SMU_MSG_SetWorkloadMask,<br>
>                                              smu->workload_mask,<br>
>                                              NULL);<br>
> -     if (!ret) {<br>
> -             smu_cmn_assign_power_profile(smu);<br>
> -             if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_POWERSAVING) {<br>
> -                     workload_type = smu_cmn_to_asic_specific_index(smu,<br>
> -                                                            CMN2ASIC_MAPPING_WORKLOAD,<br>
> -                                                            PP_SMC_POWER_PROFILE_FULLSCREEN3D);<br>
> -                     smu->power_profile_mode = smu->workload_mask & (1 << workload_type)<br>
> -                                                                             ? PP_SMC_POWER_PROFILE_FULLSCREEN3D<br>
> -                                                                             : PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;<br>
> -             }<br>
> -     }<br>
>  <br>
>       return ret;<br>
>  }<br>
> 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<br>
> index c5d3e25cc967..1aafd23857f0 100644<br>
> --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c<br>
> +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c<br>
> @@ -2528,22 +2528,23 @@ do {                                                                                                  \<br>
>       return result;<br>
>  }<br>
>  <br>
> -static int smu_v13_0_7_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)<br>
> +static int smu_v13_0_7_set_power_profile_mode(struct smu_context *smu,<br>
> +                                           long *input, uint32_t size,<br>
> +                                           bool enable)<br>
>  {<br>
>  <br>
>       DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;<br>
>       DpmActivityMonitorCoeffInt_t *activity_monitor =<br>
>               &(activity_monitor_external.DpmActivityMonitorCoeffInt);<br>
> +     uint32_t profile_mode = input[size];<br>
>       int workload_type, ret = 0;<br>
>  <br>
> -     smu->power_profile_mode = input[size];<br>
> -<br>
> -     if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_WINDOW3D) {<br>
> -             dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode);<br>
> +     if (profile_mode > PP_SMC_POWER_PROFILE_WINDOW3D) {<br>
> +             dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode);<br>
>               return -EINVAL;<br>
>       }<br>
>  <br>
> -     if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {<br>
> +     if (enable && profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {<br>
>               if (size != 8)<br>
>                       return -EINVAL;<br>
>  <br>
> @@ -2590,17 +2591,19 @@ static int smu_v13_0_7_set_power_profile_mode(struct smu_context *smu, long *inp<br>
>       /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */<br>
>       workload_type = smu_cmn_to_asic_specific_index(smu,<br>
>                                                      CMN2ASIC_MAPPING_WORKLOAD,<br>
> -                                                    smu->power_profile_mode);<br>
> +                                                    profile_mode);<br>
>       if (workload_type < 0)<br>
>               return -EINVAL;<br>
>  <br>
> +     if (enable)<br>
> +             smu->workload_mask |= (1 << workload_type);<br>
> +     else<br>
> +             smu->workload_mask &= ~(1 << workload_type);<br>
>       ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,<br>
>                                   smu->workload_mask, NULL);<br>
>  <br>
>       if (ret)<br>
>               dev_err(smu->adev->dev, "[%s] Failed to set work load mask!", __func__);<br>
> -     else<br>
> -             smu_cmn_assign_power_profile(smu);<br>
>  <br>
>       return ret;<br>
>  }<br>
> 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<br>
> index 59b369eff30f..695480833603 100644<br>
> --- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c<br>
> +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c<br>
> @@ -1719,21 +1719,22 @@ static int smu_v14_0_2_get_power_profile_mode(struct smu_context *smu,<br>
>  <br>
>  static int smu_v14_0_2_set_power_profile_mode(struct smu_context *smu,<br>
>                                             long *input,<br>
> -                                           uint32_t size)<br>
> +                                           uint32_t size,<br>
> +                                           bool enable)<br>
>  {<br>
>       DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;<br>
>       DpmActivityMonitorCoeffInt_t *activity_monitor =<br>
>               &(activity_monitor_external.DpmActivityMonitorCoeffInt);<br>
> +     uint32_t profile_mode = input[size];<br>
>       int workload_type, ret = 0;<br>
>       uint32_t current_profile_mode = smu->power_profile_mode;<br>
> -     smu->power_profile_mode = input[size];<br>
>  <br>
> -     if (smu->power_profile_mode >= PP_SMC_POWER_PROFILE_COUNT) {<br>
> -             dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode);<br>
> +     if (profile_mode >= PP_SMC_POWER_PROFILE_COUNT) {<br>
> +             dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode);<br>
>               return -EINVAL;<br>
>       }<br>
>  <br>
> -     if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {<br>
> +     if (enable && profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {<br>
>               if (size != 9)<br>
>                       return -EINVAL;<br>
>  <br>
> @@ -1783,7 +1784,7 @@ static int smu_v14_0_2_set_power_profile_mode(struct smu_context *smu,<br>
>               }<br>
>       }<br>
>  <br>
> -     if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_COMPUTE)<br>
> +     if (profile_mode == PP_SMC_POWER_PROFILE_COMPUTE)<br>
>               smu_v14_0_deep_sleep_control(smu, false);<br>
>       else if (current_profile_mode == PP_SMC_POWER_PROFILE_COMPUTE)<br>
>               smu_v14_0_deep_sleep_control(smu, true);<br>
> @@ -1791,15 +1792,16 @@ static int smu_v14_0_2_set_power_profile_mode(struct smu_context *smu,<br>
>       /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */<br>
>       workload_type = smu_cmn_to_asic_specific_index(smu,<br>
>                                                      CMN2ASIC_MAPPING_WORKLOAD,<br>
> -                                                    smu->power_profile_mode);<br>
> +                                                    profile_mode);<br>
>       if (workload_type < 0)<br>
>               return -EINVAL;<br>
>  <br>
> +     if (enable)<br>
> +             smu->workload_mask |= (1 << workload_type);<br>
> +     else<br>
> +             smu->workload_mask &= ~(1 << workload_type);<br>
>       ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,<br>
> -                                                                               smu->workload_mask, NULL);<br>
> -<br>
> -     if (!ret)<br>
> -             smu_cmn_assign_power_profile(smu);<br>
> +                                           smu->workload_mask, NULL);<br>
>  <br>
>       return ret;<br>
>  }<br>
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c<br>
> index fd2aa949538e..63c4f75fa118 100644<br>
> --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c<br>
> +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c<br>
> @@ -1141,14 +1141,6 @@ int smu_cmn_set_mp1_state(struct smu_context *smu,<br>
>       return ret;<br>
>  }<br>
>  <br>
> -void smu_cmn_assign_power_profile(struct smu_context *smu)<br>
> -{<br>
> -     uint32_t index;<br>
> -     index = fls(smu->workload_mask);<br>
> -     index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;<br>
> -     smu->power_profile_mode = smu->workload_setting[index];<br>
> -}<br>
> -<br>
>  bool smu_cmn_is_audio_func_enabled(struct amdgpu_device *adev)<br>
>  {<br>
>       struct pci_dev *p = NULL;<br>
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h<br>
> index 8a801e389659..1de685defe85 100644<br>
> --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h<br>
> +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h<br>
> @@ -130,8 +130,6 @@ void smu_cmn_init_soft_gpu_metrics(void *table, uint8_t frev, uint8_t crev);<br>
>  int smu_cmn_set_mp1_state(struct smu_context *smu,<br>
>                         enum pp_mp1_state mp1_state);<br>
>  <br>
> -void smu_cmn_assign_power_profile(struct smu_context *smu);<br>
> -<br>
>  /*<br>
>   * Helper function to make sysfs_emit_at() happy. Align buf to<br>
>   * the current page boundary and record the offset.<br>
</blockquote></div></div>