Skip to content

Commit 73abde4

Browse files
mcoffinalexdeucher
authored andcommitted
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) Reviewed-by: Evan Quan <[email protected]> Signed-off-by: Matt Coffin <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
1 parent 7f3353f commit 73abde4

File tree

8 files changed

+78
-28
lines changed

8 files changed

+78
-28
lines changed

drivers/gpu/drm/amd/powerplay/amdgpu_smu.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1109,7 +1109,7 @@ static int smu_smc_table_hw_init(struct smu_context *smu,
11091109
if (ret)
11101110
return ret;
11111111

1112-
ret = smu_get_power_limit(smu, &smu->default_power_limit, true, false);
1112+
ret = smu_get_power_limit(smu, &smu->default_power_limit, false, false);
11131113
if (ret)
11141114
return ret;
11151115
}
@@ -2511,3 +2511,13 @@ int smu_get_dpm_clock_table(struct smu_context *smu,
25112511

25122512
return ret;
25132513
}
2514+
2515+
uint32_t smu_get_pptable_power_limit(struct smu_context *smu)
2516+
{
2517+
uint32_t ret = 0;
2518+
2519+
if (smu->ppt_funcs->get_pptable_power_limit)
2520+
ret = smu->ppt_funcs->get_pptable_power_limit(smu);
2521+
2522+
return ret;
2523+
}

drivers/gpu/drm/amd/powerplay/arcturus_ppt.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,15 +1261,14 @@ arcturus_get_profiling_clk_mask(struct smu_context *smu,
12611261

12621262
static int arcturus_get_power_limit(struct smu_context *smu,
12631263
uint32_t *limit,
1264-
bool asic_default)
1264+
bool cap)
12651265
{
12661266
PPTable_t *pptable = smu->smu_table.driver_pptable;
12671267
uint32_t asic_default_power_limit = 0;
12681268
int ret = 0;
12691269
int power_src;
12701270

1271-
if (!smu->default_power_limit ||
1272-
!smu->power_limit) {
1271+
if (!smu->power_limit) {
12731272
if (smu_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
12741273
power_src = smu_power_get_index(smu, SMU_POWER_SOURCE_AC);
12751274
if (power_src < 0)
@@ -1292,17 +1291,11 @@ static int arcturus_get_power_limit(struct smu_context *smu,
12921291
pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
12931292
}
12941293

1295-
if (smu->od_enabled) {
1296-
asic_default_power_limit *= (100 + smu->smu_table.TDPODLimit);
1297-
asic_default_power_limit /= 100;
1298-
}
1299-
1300-
smu->default_power_limit = asic_default_power_limit;
13011294
smu->power_limit = asic_default_power_limit;
13021295
}
13031296

1304-
if (asic_default)
1305-
*limit = smu->default_power_limit;
1297+
if (cap)
1298+
*limit = smu_v11_0_get_max_power_limit(smu);
13061299
else
13071300
*limit = smu->power_limit;
13081301

@@ -2070,6 +2063,13 @@ static void arcturus_i2c_eeprom_control_fini(struct i2c_adapter *control)
20702063
i2c_del_adapter(control);
20712064
}
20722065

2066+
static uint32_t arcturus_get_pptable_power_limit(struct smu_context *smu)
2067+
{
2068+
PPTable_t *pptable = smu->smu_table.driver_pptable;
2069+
2070+
return pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
2071+
}
2072+
20732073
static const struct pptable_funcs arcturus_ppt_funcs = {
20742074
/* translate smu index into arcturus specific index */
20752075
.get_smu_msg_index = arcturus_get_smu_msg_index,
@@ -2160,6 +2160,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = {
21602160
.get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq,
21612161
.set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range,
21622162
.override_pcie_parameters = smu_v11_0_override_pcie_parameters,
2163+
.get_pptable_power_limit = arcturus_get_pptable_power_limit,
21632164
};
21642165

21652166
void arcturus_set_ppt_funcs(struct smu_context *smu)

drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,6 @@ struct smu_table_context
261261
struct smu_table *tables;
262262
struct smu_table memory_pool;
263263
uint8_t thermal_controller_type;
264-
uint16_t TDPODLimit;
265264

266265
void *overdrive_table;
267266
};
@@ -548,6 +547,7 @@ struct pptable_funcs {
548547
int (*get_dpm_ultimate_freq)(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t *min, uint32_t *max);
549548
int (*set_soft_freq_limited_range)(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t min, uint32_t max);
550549
int (*override_pcie_parameters)(struct smu_context *smu);
550+
uint32_t (*get_pptable_power_limit)(struct smu_context *smu);
551551
};
552552

553553
int smu_load_microcode(struct smu_context *smu);
@@ -717,4 +717,6 @@ int smu_get_uclk_dpm_states(struct smu_context *smu,
717717
int smu_get_dpm_clock_table(struct smu_context *smu,
718718
struct dpm_clocks *clock_table);
719719

720+
uint32_t smu_get_pptable_power_limit(struct smu_context *smu);
721+
720722
#endif

drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,4 +252,6 @@ int smu_v11_0_override_pcie_parameters(struct smu_context *smu);
252252

253253
int smu_v11_0_set_default_od_settings(struct smu_context *smu, bool initialize, size_t overdrive_table_size);
254254

255+
uint32_t smu_v11_0_get_max_power_limit(struct smu_context *smu);
256+
255257
#endif

drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_pptable.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,9 @@ struct smu_11_0_powerplay_table
141141
struct smu_11_0_power_saving_clock_table power_saving_clock;
142142
struct smu_11_0_overdrive_table overdrive_table;
143143

144+
#ifndef SMU_11_0_PARTIAL_PPTABLE
144145
PPTable_t smc_pptable; //PPTable_t in smu11_driver_if.h
146+
#endif
145147
} __attribute__((packed));
146148

147149
#endif

drivers/gpu/drm/amd/powerplay/navi10_ppt.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1633,17 +1633,22 @@ static int navi10_display_disable_memory_clock_switch(struct smu_context *smu,
16331633
return ret;
16341634
}
16351635

1636+
static uint32_t navi10_get_pptable_power_limit(struct smu_context *smu)
1637+
{
1638+
PPTable_t *pptable = smu->smu_table.driver_pptable;
1639+
return pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
1640+
}
1641+
16361642
static int navi10_get_power_limit(struct smu_context *smu,
16371643
uint32_t *limit,
1638-
bool asic_default)
1644+
bool cap)
16391645
{
16401646
PPTable_t *pptable = smu->smu_table.driver_pptable;
16411647
uint32_t asic_default_power_limit = 0;
16421648
int ret = 0;
16431649
int power_src;
16441650

1645-
if (!smu->default_power_limit ||
1646-
!smu->power_limit) {
1651+
if (!smu->power_limit) {
16471652
if (smu_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
16481653
power_src = smu_power_get_index(smu, SMU_POWER_SOURCE_AC);
16491654
if (power_src < 0)
@@ -1666,17 +1671,11 @@ static int navi10_get_power_limit(struct smu_context *smu,
16661671
pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
16671672
}
16681673

1669-
if (smu->od_enabled) {
1670-
asic_default_power_limit *= (100 + smu->smu_table.TDPODLimit);
1671-
asic_default_power_limit /= 100;
1672-
}
1673-
1674-
smu->default_power_limit = asic_default_power_limit;
16751674
smu->power_limit = asic_default_power_limit;
16761675
}
16771676

1678-
if (asic_default)
1679-
*limit = smu->default_power_limit;
1677+
if (cap)
1678+
*limit = smu_v11_0_get_max_power_limit(smu);
16801679
else
16811680
*limit = smu->power_limit;
16821681

@@ -2024,6 +2023,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
20242023
.override_pcie_parameters = smu_v11_0_override_pcie_parameters,
20252024
.set_default_od_settings = navi10_set_default_od_settings,
20262025
.od_edit_dpm_table = navi10_od_edit_dpm_table,
2026+
.get_pptable_power_limit = navi10_get_pptable_power_limit,
20272027
};
20282028

20292029
void navi10_set_ppt_funcs(struct smu_context *smu)

drivers/gpu/drm/amd/powerplay/smu_v11_0.c

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,16 @@
2424
#include <linux/module.h>
2525
#include <linux/pci.h>
2626

27+
#define SMU_11_0_PARTIAL_PPTABLE
28+
2729
#include "pp_debug.h"
2830
#include "amdgpu.h"
2931
#include "amdgpu_smu.h"
3032
#include "smu_internal.h"
3133
#include "atomfirmware.h"
3234
#include "amdgpu_atomfirmware.h"
3335
#include "smu_v11_0.h"
36+
#include "smu_v11_0_pptable.h"
3437
#include "soc15_common.h"
3538
#include "atom.h"
3639
#include "amd_pcie.h"
@@ -1045,13 +1048,44 @@ int smu_v11_0_init_max_sustainable_clocks(struct smu_context *smu)
10451048
return 0;
10461049
}
10471050

1051+
uint32_t smu_v11_0_get_max_power_limit(struct smu_context *smu) {
1052+
uint32_t od_limit, max_power_limit;
1053+
struct smu_11_0_powerplay_table *powerplay_table = NULL;
1054+
struct smu_table_context *table_context = &smu->smu_table;
1055+
powerplay_table = table_context->power_play_table;
1056+
1057+
max_power_limit = smu_get_pptable_power_limit(smu);
1058+
1059+
if (!max_power_limit) {
1060+
// If we couldn't get the table limit, fall back on first-read value
1061+
if (!smu->default_power_limit)
1062+
smu->default_power_limit = smu->power_limit;
1063+
max_power_limit = smu->default_power_limit;
1064+
}
1065+
1066+
if (smu->od_enabled) {
1067+
od_limit = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
1068+
1069+
pr_debug("ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_limit, smu->default_power_limit);
1070+
1071+
max_power_limit *= (100 + od_limit);
1072+
max_power_limit /= 100;
1073+
}
1074+
1075+
return max_power_limit;
1076+
}
1077+
10481078
int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n)
10491079
{
10501080
int ret = 0;
1081+
uint32_t max_power_limit;
1082+
1083+
max_power_limit = smu_v11_0_get_max_power_limit(smu);
10511084

1052-
if (n > smu->default_power_limit) {
1053-
pr_err("New power limit is over the max allowed %d\n",
1054-
smu->default_power_limit);
1085+
if (n > max_power_limit) {
1086+
pr_err("New power limit (%d) is over the max allowed %d\n",
1087+
n,
1088+
max_power_limit);
10551089
return -EINVAL;
10561090
}
10571091

drivers/gpu/drm/amd/powerplay/vega20_ppt.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,6 @@ static int vega20_store_powerplay_table(struct smu_context *smu)
466466
sizeof(PPTable_t));
467467

468468
table_context->thermal_controller_type = powerplay_table->ucThermalControllerType;
469-
table_context->TDPODLimit = le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingsMax[ATOM_VEGA20_ODSETTING_POWERPERCENTAGE]);
470469

471470
return 0;
472471
}

0 commit comments

Comments
 (0)