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>
This commit is contained in:
Родитель
1f23cadbe0
Коммит
b4af964e75
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1323,6 +1323,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;
|
||||
|
@ -1788,6 +1838,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)
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -1509,6 +1509,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,
|
||||
|
@ -1546,6 +1596,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)
|
||||
|
|
|
@ -1015,64 +1015,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)
|
||||
{
|
||||
int ret = 0;
|
||||
int power_src;
|
||||
|
||||
power_src = smu_power_get_index(smu, SMU_POWER_SOURCE_AC);
|
||||
if (power_src < 0)
|
||||
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 > smu->default_power_limit) {
|
||||
pr_err("New power limit is over the max allowed %d\n",
|
||||
smu->default_power_limit);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -1753,7 +1721,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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче