aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4419-drm-amdgpu-smu_v11-Unify-and-fix-power-limits.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4419-drm-amdgpu-smu_v11-Unify-and-fix-power-limits.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4419-drm-amdgpu-smu_v11-Unify-and-fix-power-limits.patch318
1 files changed, 318 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4419-drm-amdgpu-smu_v11-Unify-and-fix-power-limits.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4419-drm-amdgpu-smu_v11-Unify-and-fix-power-limits.patch
new file mode 100644
index 00000000..5ab66eeb
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4419-drm-amdgpu-smu_v11-Unify-and-fix-power-limits.patch
@@ -0,0 +1,318 @@
+From bded65628b641bb8cb50be6190abf36500a91624 Mon Sep 17 00:00:00 2001
+From: Matt Coffin <mcoffin13@gmail.com>
+Date: Mon, 11 Nov 2019 11:36:31 -0700
+Subject: [PATCH 4419/4736] drm/amdgpu/smu_v11: Unify and fix power limits
+
+[Why]
+On Navi10, and presumably arcterus, updating pp_table via sysfs would
+not re-scale the maximum possible power limit one can set. On navi10,
+the SMU code ignored the power percentage overdrive setting entirely,
+and would not allow you to exceed the default power limit at all.
+
+[How]
+Adding a function to the SMU interface to get the pptable version of the
+default power limit allows ASIC-specific code to provide the correct
+maximum-settable power limit for the current pptable.
+
+v3: fix spelling (Alex)
+
+Change-Id: Idfa0d2ec64da34520e2928e5011ac3c54bf60a4d
+Reviewed-by: Evan Quan <evan.quan@amd.com>
+Signed-off-by: Matt Coffin <mcoffin13@gmail.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 12 +++++-
+ drivers/gpu/drm/amd/powerplay/arcturus_ppt.c | 23 ++++++-----
+ .../gpu/drm/amd/powerplay/inc/amdgpu_smu.h | 4 +-
+ drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h | 2 +
+ .../drm/amd/powerplay/inc/smu_v11_0_pptable.h | 2 +
+ drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 22 +++++-----
+ drivers/gpu/drm/amd/powerplay/smu_v11_0.c | 40 +++++++++++++++++--
+ drivers/gpu/drm/amd/powerplay/vega20_ppt.c | 1 -
+ 8 files changed, 78 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
+index 76a4154b3be2..df5487fae20a 100644
+--- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
++++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
+@@ -1109,7 +1109,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, true, false);
++ ret = smu_get_power_limit(smu, &smu->default_power_limit, false, false);
+ if (ret)
+ return ret;
+ }
+@@ -2511,3 +2511,13 @@ int smu_get_dpm_clock_table(struct smu_context *smu,
+
+ return ret;
+ }
++
++uint32_t smu_get_pptable_power_limit(struct smu_context *smu)
++{
++ uint32_t ret = 0;
++
++ if (smu->ppt_funcs->get_pptable_power_limit)
++ ret = smu->ppt_funcs->get_pptable_power_limit(smu);
++
++ return ret;
++}
+diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c
+index 4315a887e918..6d1401b30aaf 100644
+--- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c
++++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c
+@@ -1261,15 +1261,14 @@ arcturus_get_profiling_clk_mask(struct smu_context *smu,
+
+ static int arcturus_get_power_limit(struct smu_context *smu,
+ uint32_t *limit,
+- bool asic_default)
++ bool cap)
+ {
+ PPTable_t *pptable = smu->smu_table.driver_pptable;
+ uint32_t asic_default_power_limit = 0;
+ int ret = 0;
+ int power_src;
+
+- if (!smu->default_power_limit ||
+- !smu->power_limit) {
++ 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)
+@@ -1292,17 +1291,11 @@ static int arcturus_get_power_limit(struct smu_context *smu,
+ 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;
++ if (cap)
++ *limit = smu_v11_0_get_max_power_limit(smu);
+ else
+ *limit = smu->power_limit;
+
+@@ -2070,6 +2063,13 @@ static void arcturus_i2c_eeprom_control_fini(struct i2c_adapter *control)
+ i2c_del_adapter(control);
+ }
+
++static uint32_t arcturus_get_pptable_power_limit(struct smu_context *smu)
++{
++ PPTable_t *pptable = smu->smu_table.driver_pptable;
++
++ return pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
++}
++
+ static const struct pptable_funcs arcturus_ppt_funcs = {
+ /* translate smu index into arcturus specific index */
+ .get_smu_msg_index = arcturus_get_smu_msg_index,
+@@ -2160,6 +2160,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = {
+ .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq,
+ .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range,
+ .override_pcie_parameters = smu_v11_0_override_pcie_parameters,
++ .get_pptable_power_limit = arcturus_get_pptable_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 8120e7587585..999445c5c010 100644
+--- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
++++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
+@@ -261,7 +261,6 @@ struct smu_table_context
+ struct smu_table *tables;
+ struct smu_table memory_pool;
+ uint8_t thermal_controller_type;
+- uint16_t TDPODLimit;
+
+ void *overdrive_table;
+ };
+@@ -548,6 +547,7 @@ struct pptable_funcs {
+ int (*get_dpm_ultimate_freq)(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t *min, uint32_t *max);
+ int (*set_soft_freq_limited_range)(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t min, uint32_t max);
+ int (*override_pcie_parameters)(struct smu_context *smu);
++ uint32_t (*get_pptable_power_limit)(struct smu_context *smu);
+ };
+
+ int smu_load_microcode(struct smu_context *smu);
+@@ -717,4 +717,6 @@ int smu_get_uclk_dpm_states(struct smu_context *smu,
+ int smu_get_dpm_clock_table(struct smu_context *smu,
+ struct dpm_clocks *clock_table);
+
++uint32_t smu_get_pptable_power_limit(struct smu_context *smu);
++
+ #endif
+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 0ec6ed0456e0..0269fac1a77b 100644
+--- a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h
++++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h
+@@ -253,4 +253,6 @@ int smu_v11_0_override_pcie_parameters(struct smu_context *smu);
+
+ int smu_v11_0_set_default_od_settings(struct smu_context *smu, bool initialize, size_t overdrive_table_size);
+
++uint32_t smu_v11_0_get_max_power_limit(struct smu_context *smu);
++
+ #endif
+diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_pptable.h b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_pptable.h
+index 86cdc3393eac..b2f96a101124 100644
+--- a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_pptable.h
++++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_pptable.h
+@@ -141,7 +141,9 @@ struct smu_11_0_powerplay_table
+ struct smu_11_0_power_saving_clock_table power_saving_clock;
+ struct smu_11_0_overdrive_table overdrive_table;
+
++#ifndef SMU_11_0_PARTIAL_PPTABLE
+ PPTable_t smc_pptable; //PPTable_t in smu11_driver_if.h
++#endif
+ } __attribute__((packed));
+
+ #endif
+diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
+index 5c6ffbd0d884..17ccdb74f4e2 100644
+--- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
++++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
+@@ -1632,17 +1632,22 @@ static int navi10_display_disable_memory_clock_switch(struct smu_context *smu,
+ return ret;
+ }
+
++static uint32_t navi10_get_pptable_power_limit(struct smu_context *smu)
++{
++ PPTable_t *pptable = smu->smu_table.driver_pptable;
++ return pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
++}
++
+ static int navi10_get_power_limit(struct smu_context *smu,
+ uint32_t *limit,
+- bool asic_default)
++ bool cap)
+ {
+ PPTable_t *pptable = smu->smu_table.driver_pptable;
+ uint32_t asic_default_power_limit = 0;
+ int ret = 0;
+ int power_src;
+
+- if (!smu->default_power_limit ||
+- !smu->power_limit) {
++ 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)
+@@ -1665,17 +1670,11 @@ static int navi10_get_power_limit(struct smu_context *smu,
+ 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;
++ if (cap)
++ *limit = smu_v11_0_get_max_power_limit(smu);
+ else
+ *limit = smu->power_limit;
+
+@@ -2023,6 +2022,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
+ .override_pcie_parameters = smu_v11_0_override_pcie_parameters,
+ .set_default_od_settings = navi10_set_default_od_settings,
+ .od_edit_dpm_table = navi10_od_edit_dpm_table,
++ .get_pptable_power_limit = navi10_get_pptable_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 13ae44ca3504..928877f73dfd 100644
+--- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
++++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
+@@ -20,6 +20,8 @@
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
++#define SMU_11_0_PARTIAL_PPTABLE
++
+ #include "pp_debug.h"
+ #include <linux/firmware.h>
+ #include "amdgpu.h"
+@@ -28,6 +30,7 @@
+ #include "atomfirmware.h"
+ #include "amdgpu_atomfirmware.h"
+ #include "smu_v11_0.h"
++#include "smu_v11_0_pptable.h"
+ #include "soc15_common.h"
+ #include "atom.h"
+ #include "amd_pcie.h"
+@@ -1045,13 +1048,44 @@ int smu_v11_0_init_max_sustainable_clocks(struct smu_context *smu)
+ return 0;
+ }
+
++uint32_t smu_v11_0_get_max_power_limit(struct smu_context *smu) {
++ uint32_t od_limit, max_power_limit;
++ struct smu_11_0_powerplay_table *powerplay_table = NULL;
++ struct smu_table_context *table_context = &smu->smu_table;
++ powerplay_table = table_context->power_play_table;
++
++ max_power_limit = smu_get_pptable_power_limit(smu);
++
++ if (!max_power_limit) {
++ // If we couldn't get the table limit, fall back on first-read value
++ if (!smu->default_power_limit)
++ smu->default_power_limit = smu->power_limit;
++ max_power_limit = smu->default_power_limit;
++ }
++
++ if (smu->od_enabled) {
++ od_limit = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
++
++ pr_debug("ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_limit, smu->default_power_limit);
++
++ max_power_limit *= (100 + od_limit);
++ max_power_limit /= 100;
++ }
++
++ return max_power_limit;
++}
++
+ int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n)
+ {
+ int ret = 0;
++ uint32_t max_power_limit;
++
++ max_power_limit = smu_v11_0_get_max_power_limit(smu);
+
+- if (n > smu->default_power_limit) {
+- pr_err("New power limit is over the max allowed %d\n",
+- smu->default_power_limit);
++ if (n > max_power_limit) {
++ pr_err("New power limit (%d) is over the max allowed %d\n",
++ n,
++ max_power_limit);
+ return -EINVAL;
+ }
+
+diff --git a/drivers/gpu/drm/amd/powerplay/vega20_ppt.c b/drivers/gpu/drm/amd/powerplay/vega20_ppt.c
+index e00ffbbde791..399697a2ad7f 100644
+--- a/drivers/gpu/drm/amd/powerplay/vega20_ppt.c
++++ b/drivers/gpu/drm/amd/powerplay/vega20_ppt.c
+@@ -466,7 +466,6 @@ static int vega20_store_powerplay_table(struct smu_context *smu)
+ sizeof(PPTable_t));
+
+ table_context->thermal_controller_type = powerplay_table->ucThermalControllerType;
+- table_context->TDPODLimit = le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingsMax[ATOM_VEGA20_ODSETTING_POWERPERCENTAGE]);
+
+ return 0;
+ }
+--
+2.17.1
+