diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3191-drm-amd-powerplay-make-power-limit-retrieval-as-asic.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3191-drm-amd-powerplay-make-power-limit-retrieval-as-asic.patch | 291 |
1 files changed, 291 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3191-drm-amd-powerplay-make-power-limit-retrieval-as-asic.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3191-drm-amd-powerplay-make-power-limit-retrieval-as-asic.patch new file mode 100644 index 00000000..2d0be82e --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3191-drm-amd-powerplay-make-power-limit-retrieval-as-asic.patch @@ -0,0 +1,291 @@ +From 91d5d2e644a961f4a6cf8cf1040bb6ba5d7d7559 Mon Sep 17 00:00:00 2001 +From: Evan Quan <evan.quan@amd.com> +Date: Tue, 30 Jul 2019 22:52:37 -0500 +Subject: [PATCH 3191/4256] drm/amd/powerplay: make power limit retrieval as + asic specific + +The power limit retrieval should be done per asic. Since we may +need to lookup in the pptable and that's really asic specific. + +Signed-off-by: Evan Quan <evan.quan@amd.com> +Reviewed-by: Kenneth Feng <kenneth.feng@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +--- + drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 2 +- + drivers/gpu/drm/amd/powerplay/arcturus_ppt.c | 51 +++++++++++++++++ + .../gpu/drm/amd/powerplay/inc/amdgpu_smu.h | 4 +- + drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 51 +++++++++++++++++ + drivers/gpu/drm/amd/powerplay/smu_v11_0.c | 55 ++++--------------- + 5 files changed, 116 insertions(+), 47 deletions(-) + +diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +index 3f615d4624c7..330cc3258e61 100644 +--- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c ++++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +@@ -1136,7 +1136,7 @@ static int smu_smc_table_hw_init(struct smu_context *smu, + if (ret) + return ret; + +- ret = smu_get_power_limit(smu, &smu->default_power_limit, false); ++ ret = smu_get_power_limit(smu, &smu->default_power_limit, true); + if (ret) + return ret; + } +diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c +index ceb9a85bb1c8..97a247a234a8 100644 +--- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c ++++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c +@@ -1325,6 +1325,56 @@ arcturus_get_profiling_clk_mask(struct smu_context *smu, + return 0; + } + ++static int arcturus_get_power_limit(struct smu_context *smu, ++ uint32_t *limit, ++ bool asic_default) ++{ ++ PPTable_t *pptable = smu->smu_table.driver_pptable; ++ uint32_t asic_default_power_limit; ++ int ret = 0; ++ int power_src; ++ ++ if (!smu->default_power_limit || ++ !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); ++ if (ret) { ++ pr_err("[%s] get PPT limit failed!", __func__); ++ return ret; ++ } ++ smu_read_smc_arg(smu, &asic_default_power_limit); ++ } else { ++ /* the last hope to figure out the ppt limit */ ++ if (!pptable) { ++ pr_err("Cannot get PPT limit due to pptable missing!"); ++ return -EINVAL; ++ } ++ asic_default_power_limit = ++ pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0]; ++ } ++ ++ if (smu->od_enabled) { ++ asic_default_power_limit *= (100 + smu->smu_table.TDPODLimit); ++ asic_default_power_limit /= 100; ++ } ++ ++ smu->default_power_limit = asic_default_power_limit; ++ smu->power_limit = asic_default_power_limit; ++ } ++ ++ if (asic_default) ++ *limit = smu->default_power_limit; ++ else ++ *limit = smu->power_limit; ++ ++ return 0; ++} ++ + static void arcturus_dump_pptable(struct smu_context *smu) + { + struct smu_table_context *table_context = &smu->smu_table; +@@ -1790,6 +1840,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = { + .get_profiling_clk_mask = arcturus_get_profiling_clk_mask, + /* debug (internal used) */ + .dump_pptable = arcturus_dump_pptable, ++ .get_power_limit = arcturus_get_power_limit, + }; + + void arcturus_set_ppt_funcs(struct smu_context *smu) +diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h +index 76edb2ccf160..1ecd73cd768c 100644 +--- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h ++++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h +@@ -450,6 +450,7 @@ struct pptable_funcs { + int (*set_performance_level)(struct smu_context *smu, enum amd_dpm_forced_level level); + int (*display_disable_memory_clock_switch)(struct smu_context *smu, bool disable_memory_clock_switch); + void (*dump_pptable)(struct smu_context *smu); ++ int (*get_power_limit)(struct smu_context *smu, uint32_t *limit, bool asic_default); + }; + + struct smu_funcs +@@ -482,7 +483,6 @@ struct smu_funcs + int (*set_allowed_mask)(struct smu_context *smu); + int (*get_enabled_mask)(struct smu_context *smu, uint32_t *feature_mask, uint32_t num); + int (*notify_display_change)(struct smu_context *smu); +- int (*get_power_limit)(struct smu_context *smu, uint32_t *limit, bool def); + int (*set_power_limit)(struct smu_context *smu, uint32_t n); + int (*get_current_clk_freq)(struct smu_context *smu, enum smu_clk_type clk_id, uint32_t *value); + int (*init_max_sustainable_clocks)(struct smu_context *smu); +@@ -611,7 +611,7 @@ struct smu_funcs + #define smu_set_default_od8_settings(smu) \ + ((smu)->ppt_funcs->set_default_od8_settings ? (smu)->ppt_funcs->set_default_od8_settings((smu)) : 0) + #define smu_get_power_limit(smu, limit, def) \ +- ((smu)->funcs->get_power_limit ? (smu)->funcs->get_power_limit((smu), (limit), (def)) : 0) ++ ((smu)->ppt_funcs->get_power_limit ? (smu)->ppt_funcs->get_power_limit((smu), (limit), (def)) : 0) + #define smu_set_power_limit(smu, limit) \ + ((smu)->funcs->set_power_limit ? (smu)->funcs->set_power_limit((smu), (limit)) : 0) + #define smu_get_current_clk_freq(smu, clk_id, value) \ +diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +index f04a54e8e164..f3adb713784a 100644 +--- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c ++++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +@@ -1508,6 +1508,56 @@ static int navi10_display_disable_memory_clock_switch(struct smu_context *smu, + return ret; + } + ++static int navi10_get_power_limit(struct smu_context *smu, ++ uint32_t *limit, ++ bool asic_default) ++{ ++ PPTable_t *pptable = smu->smu_table.driver_pptable; ++ uint32_t asic_default_power_limit; ++ int ret = 0; ++ int power_src; ++ ++ if (!smu->default_power_limit || ++ !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); ++ if (ret) { ++ pr_err("[%s] get PPT limit failed!", __func__); ++ return ret; ++ } ++ smu_read_smc_arg(smu, &asic_default_power_limit); ++ } else { ++ /* the last hope to figure out the ppt limit */ ++ if (!pptable) { ++ pr_err("Cannot get PPT limit due to pptable missing!"); ++ return -EINVAL; ++ } ++ asic_default_power_limit = ++ pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0]; ++ } ++ ++ if (smu->od_enabled) { ++ asic_default_power_limit *= (100 + smu->smu_table.TDPODLimit); ++ asic_default_power_limit /= 100; ++ } ++ ++ smu->default_power_limit = asic_default_power_limit; ++ smu->power_limit = asic_default_power_limit; ++ } ++ ++ if (asic_default) ++ *limit = smu->default_power_limit; ++ else ++ *limit = smu->power_limit; ++ ++ return 0; ++} ++ + static const struct pptable_funcs navi10_ppt_funcs = { + .tables_init = navi10_tables_init, + .alloc_dpm_context = navi10_allocate_dpm_context, +@@ -1545,6 +1595,7 @@ static const struct pptable_funcs navi10_ppt_funcs = { + .set_performance_level = navi10_set_performance_level, + .get_thermal_temperature_range = navi10_get_thermal_temperature_range, + .display_disable_memory_clock_switch = navi10_display_disable_memory_clock_switch, ++ .get_power_limit = navi10_get_power_limit, + }; + + void navi10_set_ppt_funcs(struct smu_context *smu) +diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c +index 3457e06a5f70..0588dd8cd1ba 100644 +--- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c ++++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c +@@ -1012,64 +1012,32 @@ static int smu_v11_0_init_max_sustainable_clocks(struct smu_context *smu) + return 0; + } + +-static int smu_v11_0_get_power_limit(struct smu_context *smu, +- uint32_t *limit, +- bool get_default) ++static int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n) + { + int ret = 0; +- int power_src; + +- power_src = smu_power_get_index(smu, SMU_POWER_SOURCE_AC); +- if (power_src < 0) ++ if (n > smu->default_power_limit) { ++ pr_err("New power limit is over the max allowed %d\n", ++ smu->default_power_limit); + return -EINVAL; +- +- if (get_default) { +- mutex_lock(&smu->mutex); +- *limit = smu->default_power_limit; +- if (smu->od_enabled) { +- *limit *= (100 + smu->smu_table.TDPODLimit); +- *limit /= 100; +- } +- mutex_unlock(&smu->mutex); +- } else { +- ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetPptLimit, +- power_src << 16); +- if (ret) { +- pr_err("[%s] get PPT limit failed!", __func__); +- return ret; +- } +- smu_read_smc_arg(smu, limit); +- smu->power_limit = *limit; + } + +- return ret; +-} +- +-static int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n) +-{ +- uint32_t max_power_limit; +- int ret = 0; +- + if (n == 0) + n = smu->default_power_limit; + +- max_power_limit = smu->default_power_limit; +- +- if (smu->od_enabled) { +- max_power_limit *= (100 + smu->smu_table.TDPODLimit); +- max_power_limit /= 100; ++ if (!smu_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) { ++ pr_err("Setting new power limit is not supported!\n"); ++ return -EOPNOTSUPP; + } +- if (n > max_power_limit) +- return -EINVAL; + +- if (smu_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) +- ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetPptLimit, n); ++ ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetPptLimit, n); + if (ret) { +- pr_err("[%s] Set power limit Failed!", __func__); ++ pr_err("[%s] Set power limit Failed!\n", __func__); + return ret; + } ++ smu->power_limit = n; + +- return ret; ++ return 0; + } + + static int smu_v11_0_get_current_clk_freq(struct smu_context *smu, +@@ -1749,7 +1717,6 @@ static const struct smu_funcs smu_v11_0_funcs = { + .get_enabled_mask = smu_v11_0_get_enabled_mask, + .system_features_control = smu_v11_0_system_features_control, + .notify_display_change = smu_v11_0_notify_display_change, +- .get_power_limit = smu_v11_0_get_power_limit, + .set_power_limit = smu_v11_0_set_power_limit, + .get_current_clk_freq = smu_v11_0_get_current_clk_freq, + .init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks, +-- +2.17.1 + |