Correct the workload setting in order not to mix the setting with the end user. Update the workload mask accordingly. Signed-off-by: Kenneth Feng <kenneth.feng@xxxxxxx> --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 17 ++++++-- drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 4 +- .../drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c | 39 +++++++++++++++-- .../drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c | 33 ++++++++++++--- .../drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c | 42 ++++++++++++++++--- 5 files changed, 115 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index accc96a03bd9..f1984736ff4a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1252,7 +1252,8 @@ static int smu_sw_init(struct amdgpu_ip_block *ip_block) atomic64_set(&smu->throttle_int_counter, 0); 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_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; + smu->driver_workload_mask = 0; atomic_set(&smu->smu_power.power_gate.vcn_gated, 1); atomic_set(&smu->smu_power.power_gate.jpeg_gated, 1); @@ -1267,10 +1268,12 @@ static int smu_sw_init(struct amdgpu_ip_block *ip_block) smu->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 5; smu->workload_prority[PP_SMC_POWER_PROFILE_CUSTOM] = 6; - if (smu->is_apu) + if (smu->is_apu) { smu->workload_mask = 1 << smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT]; - else + } else { smu->workload_mask = 1 << smu->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D]; + smu->user_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D; + } smu->workload_setting[0] = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; smu->workload_setting[1] = PP_SMC_POWER_PROFILE_FULLSCREEN3D; @@ -2346,11 +2349,13 @@ static int smu_switch_power_profile(void *handle, if (!en) { smu->workload_mask &= ~(1 << smu->workload_prority[type]); + smu->driver_workload_mask &= ~(1 << smu->workload_prority[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->driver_workload_mask |= (1 << smu->workload_prority[type]); index = fls(smu->workload_mask); index = index <= WORKLOAD_POLICY_MAX ? index - 1 : 0; workload[0] = smu->workload_setting[index]; @@ -3045,12 +3050,16 @@ 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; + smu->user_profile_mode_setting = true; + ret = smu_bump_power_profile_mode(smu, param, param_size); + smu->user_profile_mode_setting = false; - return smu_bump_power_profile_mode(smu, param, param_size); + 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..e43b23dd3457 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -557,10 +557,11 @@ struct smu_context { bool disable_uclk_switch; uint32_t workload_mask; + uint32_t driver_workload_mask; uint32_t workload_prority[WORKLOAD_POLICY_MAX]; uint32_t workload_setting[WORKLOAD_POLICY_MAX]; uint32_t power_profile_mode; - uint32_t default_power_profile_mode; + uint32_t user_profile_mode; bool pm_enabled; bool is_apu; @@ -572,6 +573,7 @@ struct smu_context { bool uploading_custom_pp_table; bool dc_controlled_by_gpio; + bool user_profile_mode_setting; struct work_struct throttling_logging_work; atomic64_t throttle_int_counter; 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..7250b2bad198 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 @@ -2433,7 +2433,7 @@ static int smu_v13_0_0_get_power_profile_mode(struct smu_context *smu, } size += sysfs_emit_at(buf, size, "%2d %14s%s:\n", - i, amdgpu_pp_profile_name[i], (i == smu->power_profile_mode) ? "*" : " "); + i, amdgpu_pp_profile_name[i], (i == smu->user_profile_mode) ? "*" : " "); size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d\n", " ", @@ -2474,9 +2474,27 @@ 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 current_user_profile_mode; + uint32_t index; + + if (smu->user_profile_mode_setting && smu->user_profile_mode == input[size]) + return 0; smu->power_profile_mode = input[size]; + if (smu->user_profile_mode_setting) { + current_user_profile_mode = smu->user_profile_mode; + smu->user_profile_mode = input[size]; + workload_type = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_WORKLOAD, + current_user_profile_mode); + if (workload_type < 0) + return -EINVAL; + + if (!(smu->driver_workload_mask & (1 << workload_type))) + smu->workload_mask &= ~(1 << workload_type); + } + 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 +2573,25 @@ 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..8afd43e78ebc 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 @@ -2367,7 +2367,7 @@ static int smu_v13_0_7_get_power_profile_mode(struct smu_context *smu, char *buf size += sysfs_emit_at(buf, size, " "); for (i = 0; i <= PP_SMC_POWER_PROFILE_WINDOW3D; i++) size += sysfs_emit_at(buf, size, "%d %-14s%s", i, amdgpu_pp_profile_name[i], - (i == smu->power_profile_mode) ? "* " : " "); + (i == smu->user_profile_mode) ? "* " : " "); size += sysfs_emit_at(buf, size, "\n"); @@ -2429,9 +2429,27 @@ 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 current_user_profile_mode; + uint32_t index; + + if (smu->user_profile_mode_setting && smu->user_profile_mode == input[size]) + return 0; smu->power_profile_mode = input[size]; + if (smu->user_profile_mode_setting) { + current_user_profile_mode = smu->user_profile_mode; + smu->user_profile_mode = input[size]; + workload_type = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_WORKLOAD, + current_user_profile_mode); + if (workload_type < 0) + return -EINVAL; + + if (!(smu->driver_workload_mask & (1 << workload_type))) + smu->workload_mask &= ~(1 << workload_type); + } + 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 +2505,18 @@ 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) + if (ret) { dev_err(smu->adev->dev, "[%s] Failed to set work load mask!", __func__); - else - smu->workload_mask = (1 << workload_type); + } else { + 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..d88bf9bad313 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 @@ -1747,7 +1747,7 @@ static int smu_v14_0_2_get_power_profile_mode(struct smu_context *smu, } size += sysfs_emit_at(buf, size, "%2d %14s%s:\n", - i, amdgpu_pp_profile_name[i], (i == smu->power_profile_mode) ? "*" : " "); + i, amdgpu_pp_profile_name[i], (i == smu->user_profile_mode) ? "*" : " "); size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d\n", " ", @@ -1787,9 +1787,27 @@ 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 current_profile_mode = smu->power_profile_mode; + uint32_t current_user_profile_mode; + uint32_t index; + + if (smu->user_profile_mode_setting && smu->user_profile_mode == input[size]) + return 0; + smu->power_profile_mode = input[size]; + if (smu->user_profile_mode_setting) { + current_user_profile_mode = smu->user_profile_mode; + smu->user_profile_mode = input[size]; + workload_type = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_WORKLOAD, + current_user_profile_mode); + if (workload_type < 0) + return -EINVAL; + + if (!(smu->driver_workload_mask & (1 << workload_type))) + smu->workload_mask &= ~(1 << workload_type); + } + 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; @@ -1845,9 +1863,16 @@ static int smu_v14_0_2_set_power_profile_mode(struct smu_context *smu, } } + workload_type = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_WORKLOAD, + PP_SMC_POWER_PROFILE_COMPUTE); + + if (workload_type < 0) + return -EINVAL; + if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_COMPUTE) smu_v14_0_deep_sleep_control(smu, false); - else if (current_profile_mode == PP_SMC_POWER_PROFILE_COMPUTE) + else if (smu->workload_mask & (1 << workload_type)) smu_v14_0_deep_sleep_control(smu, true); /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ @@ -1857,12 +1882,17 @@ static int smu_v14_0_2_set_power_profile_mode(struct smu_context *smu, 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, + smu->workload_mask, NULL); - if (!ret) - 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; } -- 2.34.1