[PATCH] drm/amdgpu/smu_v11: Unify and fix power limits
Quan, Evan
Evan.Quan at amd.com
Mon Nov 11 04:03:12 UTC 2019
If smu_get_pptable_power_limit() is designed to be used internally, the second argument "lock_needed" can be dropped.
Except that, the patch is reviewed-by: Evan Quan <evan.quan at amd.com>
> -----Original Message-----
> From: amd-gfx <amd-gfx-bounces at lists.freedesktop.org> On Behalf Of Matt
> Coffin
> Sent: Saturday, November 9, 2019 7:54 AM
> To: amd-gfx at lists.freedesktop.org
> Cc: Matt Coffin <mcoffin13 at gmail.com>
> Subject: [PATCH] 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.
> ---
> drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 18 ++++++++-
> drivers/gpu/drm/amd/powerplay/arcturus_ppt.c | 22 +++++-----
> .../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, 83 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
> b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
> index 66faea66a8e9..6bf940f1edfb 100644
> --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
> +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
> @@ -1107,7 +1107,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;
> }
> @@ -2509,3 +2509,19 @@ int smu_get_dpm_clock_table(struct smu_context
> *smu,
>
> return ret;
> }
> +
> +uint32_t smu_get_pptable_power_limit(struct smu_context *smu, bool
> lock_needed)
> +{
> + uint32_t ret = 0;
> +
> + if (lock_needed)
> + mutex_lock(&smu->mutex);
> +
> + if (smu->ppt_funcs->get_pptable_power_limit)
> + ret = smu->ppt_funcs->get_pptable_power_limit(smu);
> +
> + if (lock_needed)
> + mutex_unlock(&smu->mutex);
> +
> + return ret;
> +}
> diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c
> b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c
> index 3099ac256bd3..ebb9c8064867 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,12 @@ static void arcturus_i2c_eeprom_control_fini(struct
> i2c_adapter *control)
> i2c_del_adapter(control);
> }
>
> +static uint32_t arcterus_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 +2159,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 = arcterus_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..9d0193569b05 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, bool
> lock_needed);
> +
> #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 154b57a4dbbb..0ba7a7292bea 100644
> --- a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h
> +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h
> @@ -252,4 +252,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 4fbdf0e507f3..36cf313754e4 100644
> --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
> +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
> @@ -1633,17 +1633,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)
> @@ -1666,17 +1671,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;
>
> @@ -2024,6 +2023,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 c4f67ee8840e..814d2256ff8e 100644
> --- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
> +++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
> @@ -24,6 +24,8 @@
> #include <linux/module.h>
> #include <linux/pci.h>
>
> +#define SMU_11_0_PARTIAL_PPTABLE
> +
> #include "pp_debug.h"
> #include "amdgpu.h"
> #include "amdgpu_smu.h"
> @@ -31,6 +33,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, false);
> +
> + 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 5b21386f558d..0b4892833808 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_POWERPERCE
> NTAGE]);
>
> return 0;
> }
> --
> 2.23.0
>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
More information about the amd-gfx
mailing list