Commit b4af964e authored by Evan Quan's avatar Evan Quan Committed by Alex Deucher

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: default avatarEvan Quan <evan.quan@amd.com>
Reviewed-by: default avatarKenneth Feng <kenneth.feng@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 1f23cadb
......@@ -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)
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,
......@@ -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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment