User can change power limit between [0, 1] * max power limit. Set power limit to 0, restore to max power limit. Change-Id: I177415e2ded23118764219dd24d9028d7ffb4283 Signed-off-by: Rex Zhu <Rex.Zhu at amd.com> --- drivers/gpu/drm/amd/include/kgd_pp_interface.h | 2 + drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 61 ++++++++++++++++++++++ drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | 1 + .../gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c | 4 +- drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c | 1 + .../gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c | 7 +-- drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 3 ++ 7 files changed, 74 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index 1fc995b..0572949 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -283,6 +283,8 @@ struct amd_pm_funcs { uint32_t mc_addr_low, uint32_t mc_addr_hi, uint32_t size); + int (*set_power_limit)(void *handle, uint32_t n); + int (*get_power_limit)(void *handle, uint32_t *limit, bool default_limit); /* export to DC */ u32 (*get_sclk)(void *handle, bool low); u32 (*get_mclk)(void *handle, bool low); diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index 86c5e28..ac148d4 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c @@ -1231,6 +1231,65 @@ static int pp_dpm_notify_smu_memory_info(void *handle, return ret; } +static int pp_set_power_limit(void *handle, uint32_t limit) +{ + struct pp_hwmgr *hwmgr; + struct pp_instance *pp_handle = (struct pp_instance *)handle; + int ret = 0; + + ret = pp_check(pp_handle); + + if (ret) + return ret; + + hwmgr = pp_handle->hwmgr; + + if (hwmgr->hwmgr_func->set_power_limit == NULL) { + pr_info("%s was not implemented.\n", __func__); + return -EINVAL; + } + + if (limit == 0) + limit = hwmgr->default_power_limit; + + if (limit > hwmgr->default_power_limit) + return -EINVAL; + + mutex_lock(&pp_handle->pp_lock); + hwmgr->hwmgr_func->set_power_limit(hwmgr, limit); + hwmgr->power_limit = limit; + mutex_unlock(&pp_handle->pp_lock); + return ret; +} + +static int pp_get_power_limit(void *handle, uint32_t *limit, bool default_limit) +{ + struct pp_hwmgr *hwmgr; + struct pp_instance *pp_handle = (struct pp_instance *)handle; + int ret = 0; + + ret = pp_check(pp_handle); + + if (ret) + return ret; + + if (limit == NULL) + return -EINVAL; + + hwmgr = pp_handle->hwmgr; + + mutex_lock(&pp_handle->pp_lock); + + if (default_limit) + *limit = hwmgr->default_power_limit; + else + *limit = hwmgr->power_limit; + + mutex_unlock(&pp_handle->pp_lock); + + return ret; +} + static int pp_display_configuration_change(void *handle, const struct amd_pp_display_configuration *display_config) { @@ -1503,6 +1562,8 @@ static int pp_get_display_mode_validation_clocks(void *handle, .get_power_profile_mode = pp_get_power_profile_mode, .set_power_profile_mode = pp_set_power_profile_mode, .odn_edit_dpm_table = pp_odn_edit_dpm_table, + .set_power_limit = pp_set_power_limit, + .get_power_limit = pp_get_power_limit, /* export to DC */ .get_sclk = pp_dpm_get_sclk, .get_mclk = pp_dpm_get_mclk, diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index 8b8de2f..c83296f 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -5140,6 +5140,7 @@ static int smu7_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint .odn_edit_dpm_table = smu7_odn_edit_dpm_table, .get_power_profile_mode = smu7_get_power_profile_mode, .set_power_profile_mode = smu7_set_power_profile_mode, + .set_power_limit = smu7_set_power_limit, }; uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock, diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c index 85ca16a..53fd4af 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c @@ -903,12 +903,12 @@ int smu7_enable_power_containment(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE((0 == smc_result), "Failed to enable PkgPwrTracking in SMC.", result = -1;); if (0 == smc_result) { - uint32_t default_limit = + hwmgr->default_power_limit = hwmgr->power_limit = (uint32_t)(cac_table->usMaximumPowerDeliveryLimit * 256); data->power_containment_features |= POWERCONTAINMENT_FEATURE_PkgPwrLimit; - if (smu7_set_power_limit(hwmgr, default_limit)) + if (smu7_set_power_limit(hwmgr, hwmgr->power_limit)) pr_err("Failed to set Default Power Limit in SMC!"); } } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index 47b8583..5a08f33 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -5152,6 +5152,7 @@ static int vega10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, ui .start_thermal_controller = vega10_start_thermal_controller, .get_power_profile_mode = vega10_get_power_profile_mode, .set_power_profile_mode = vega10_set_power_profile_mode, + .set_power_limit = vega10_set_power_limit, }; int vega10_hwmgr_init(struct pp_hwmgr *hwmgr) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c index 598a194..981c9e5 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c @@ -1357,10 +1357,11 @@ int vega10_enable_power_containment(struct pp_hwmgr *hwmgr) struct phm_ppt_v2_information *table_info = (struct phm_ppt_v2_information *)(hwmgr->pptable); struct phm_tdp_table *tdp_table = table_info->tdp_table; - uint32_t default_pwr_limit = - (uint32_t)(tdp_table->usMaximumPowerDeliveryLimit); int result = 0; + hwmgr->default_power_limit = hwmgr->power_limit = + (uint32_t)(tdp_table->usMaximumPowerDeliveryLimit); + if (PP_CAP(PHM_PlatformCaps_PowerContainment)) { if (data->smu_features[GNLD_PPT].supported) PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, @@ -1374,7 +1375,7 @@ int vega10_enable_power_containment(struct pp_hwmgr *hwmgr) "Attempt to enable PPT feature Failed!", data->smu_features[GNLD_TDC].supported = false); - result = vega10_set_power_limit(hwmgr, default_pwr_limit); + result = vega10_set_power_limit(hwmgr, hwmgr->power_limit); PP_ASSERT_WITH_CODE(!result, "Failed to set Default Power Limit in SMC!", return result); diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index e79c2cf..376af67 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -348,6 +348,7 @@ struct pp_hwmgr_func { int (*odn_edit_dpm_table)(struct pp_hwmgr *hwmgr, enum PP_OD_DPM_TABLE_COMMAND type, long *input, uint32_t size); + int (*set_power_limit)(struct pp_hwmgr *hwmgr, uint32_t n); }; struct pp_table_func { @@ -760,6 +761,8 @@ struct pp_hwmgr { uint32_t pstate_sclk; uint32_t pstate_mclk; bool od_enabled; + uint32_t power_limit; + uint32_t default_power_limit; }; struct cgs_irq_src_funcs { -- 1.9.1