From: Evan Quan Date: Mon, 8 Jun 2020 08:29:41 +0000 (+0800) Subject: drm/amd/powerplay: maximize code sharing around power limit X-Git-Tag: v5.9-rc1~51^2~25^2~151 X-Git-Url: https://git.kernel.dk/?a=commitdiff_plain;h=1e239fdd31cdf1729bc1e8b4538bf590bd28de57;p=linux-block.git drm/amd/powerplay: maximize code sharing around power limit Also cache the current and max power limits. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c index 0704a9c1d567..2c78271123f7 100644 --- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c @@ -1413,40 +1413,33 @@ static int arcturus_get_power_limit(struct smu_context *smu, uint32_t *limit, bool cap) { + struct smu_11_0_powerplay_table *powerplay_table = + (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table; PPTable_t *pptable = smu->smu_table.driver_pptable; - uint32_t asic_default_power_limit = 0; - int ret = 0; - int power_src; - - if (!smu->power_limit) { - if (smu_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) { - power_src = smu_power_get_index(smu, SMU_POWER_SOURCE_AC); - if (power_src < 0) - return -EINVAL; + uint32_t power_limit, od_percent; - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetPptLimit, - power_src << 16, &asic_default_power_limit); - if (ret) { - dev_err(smu->adev->dev, "[%s] get PPT limit failed!", __func__); - return ret; - } - } else { - /* the last hope to figure out the ppt limit */ - if (!pptable) { - dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!"); - return -EINVAL; - } - asic_default_power_limit = - pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0]; + if (smu_v11_0_get_current_power_limit(smu, &power_limit)) { + /* the last hope to figure out the ppt limit */ + if (!pptable) { + dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!"); + return -EINVAL; } + power_limit = + pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0]; + } + smu->current_power_limit = power_limit; + + if (smu->od_enabled) { + od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]); + + dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit); - smu->power_limit = asic_default_power_limit; + power_limit *= (100 + od_percent); + power_limit /= 100; } + smu->max_power_limit = power_limit; - if (cap) - *limit = smu_get_max_power_limit(smu); - else - *limit = smu->power_limit; + *limit = (cap ? smu->max_power_limit : smu->current_power_limit); return 0; } diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h index 9276320c09d0..574a793b5d26 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h @@ -382,6 +382,8 @@ struct smu_context bool od_enabled; uint32_t power_limit; uint32_t default_power_limit; + uint32_t current_power_limit; + uint32_t max_power_limit; /* soft pptable */ uint32_t ppt_offset_bytes; diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h index 9da2f26b7267..2e9939beb128 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h @@ -196,6 +196,9 @@ int smu_v11_0_get_enabled_mask(struct smu_context *smu, int smu_v11_0_notify_display_change(struct smu_context *smu); +int smu_v11_0_get_current_power_limit(struct smu_context *smu, + uint32_t *power_limit); + int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n); int smu_v11_0_get_current_clk_freq(struct smu_context *smu, diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c index e63498e747ac..b867f94ba559 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c @@ -1923,43 +1923,36 @@ static uint32_t navi10_get_pptable_power_limit(struct smu_context *smu) } static int navi10_get_power_limit(struct smu_context *smu, - uint32_t *limit, - bool cap) + uint32_t *limit, + bool cap) { + struct smu_11_0_powerplay_table *powerplay_table = + (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table; PPTable_t *pptable = smu->smu_table.driver_pptable; - uint32_t asic_default_power_limit = 0; - int ret = 0; - int power_src; - - if (!smu->power_limit) { - if (smu_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) { - power_src = smu_power_get_index(smu, SMU_POWER_SOURCE_AC); - if (power_src < 0) - return -EINVAL; + uint32_t power_limit, od_percent; - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetPptLimit, - power_src << 16, &asic_default_power_limit); - if (ret) { - dev_err(smu->adev->dev, "[%s] get PPT limit failed!", __func__); - return ret; - } - } else { - /* the last hope to figure out the ppt limit */ - if (!pptable) { - dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!"); - return -EINVAL; - } - asic_default_power_limit = - pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0]; + if (smu_v11_0_get_current_power_limit(smu, &power_limit)) { + /* the last hope to figure out the ppt limit */ + if (!pptable) { + dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!"); + return -EINVAL; } + power_limit = + pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0]; + } + smu->current_power_limit = power_limit; - smu->power_limit = asic_default_power_limit; + if (smu->od_enabled) { + od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]); + + dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit); + + power_limit *= (100 + od_percent); + power_limit /= 100; } + smu->max_power_limit = power_limit; - if (cap) - *limit = smu_get_max_power_limit(smu); - else - *limit = smu->power_limit; + *limit = (cap ? smu->max_power_limit : smu->current_power_limit); return 0; } diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index b83675227a6f..c427e233dfad 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c @@ -1747,40 +1747,33 @@ static int sienna_cichlid_get_power_limit(struct smu_context *smu, uint32_t *limit, bool cap) { + struct smu_11_0_7_powerplay_table *powerplay_table = + (struct smu_11_0_7_powerplay_table *)smu->smu_table.power_play_table; PPTable_t *pptable = smu->smu_table.driver_pptable; - uint32_t asic_default_power_limit = 0; - int ret = 0; - int power_src; - - if (!smu->power_limit) { - if (smu_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) { - power_src = smu_power_get_index(smu, SMU_POWER_SOURCE_AC); - if (power_src < 0) - return -EINVAL; - - ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetPptLimit, - power_src << 16, &asic_default_power_limit); - if (ret) { - dev_err(smu->adev->dev, "[%s] get PPT limit failed!", __func__); - return ret; - } - } else { - /* the last hope to figure out the ppt limit */ - if (!pptable) { - dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!"); - return -EINVAL; - } - asic_default_power_limit = - pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0]; + uint32_t power_limit, od_percent; + + if (smu_v11_0_get_current_power_limit(smu, &power_limit)) { + /* the last hope to figure out the ppt limit */ + if (!pptable) { + dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!"); + return -EINVAL; } + power_limit = + pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0]; + } + smu->current_power_limit = power_limit; + + if (smu->od_enabled) { + od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_7_ODSETTING_POWERPERCENTAGE]); + + dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit); - smu->power_limit = asic_default_power_limit; + power_limit *= (100 + od_percent); + power_limit /= 100; } + smu->max_power_limit = power_limit; - if (cap) - *limit = smu_get_max_power_limit(smu); - else - *limit = smu->power_limit; + *limit = (cap ? smu->max_power_limit : smu->current_power_limit); return 0; } diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c index 9421b4b50f60..53491c55abd8 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c +++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c @@ -1056,6 +1056,29 @@ int smu_v11_0_init_max_sustainable_clocks(struct smu_context *smu) return 0; } +int smu_v11_0_get_current_power_limit(struct smu_context *smu, + uint32_t *power_limit) +{ + int power_src; + int ret = 0; + + if (!smu_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) + return -EINVAL; + + power_src = smu_power_get_index(smu, SMU_POWER_SOURCE_AC); + if (power_src < 0) + return -EINVAL; + + ret = smu_send_smc_msg_with_param(smu, + SMU_MSG_GetPptLimit, + power_src << 16, + power_limit); + if (ret) + dev_err(smu->adev->dev, "[%s] get PPT limit failed!", __func__); + + return ret; +} + int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n) { int ret = 0;