aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3191-drm-amd-powerplay-make-power-limit-retrieval-as-asic.patch
diff options
context:
space:
mode:
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.patch291
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
+