Skip to content

Commit

Permalink
drm/amd/powerplay: make power limit retrieval as asic specific
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Evan Quan authored and alexdeucher committed Jul 31, 2019
1 parent 1f23cad commit b4af964
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 47 deletions.
2 changes: 1 addition & 1 deletion drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
Expand Up @@ -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;
}
Expand Down
51 changes: 51 additions & 0 deletions drivers/gpu/drm/amd/powerplay/arcturus_ppt.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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) \
Expand Down
51 changes: 51 additions & 0 deletions drivers/gpu/drm/amd/powerplay/navi10_ppt.c
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand Down
55 changes: 11 additions & 44 deletions drivers/gpu/drm/amd/powerplay/smu_v11_0.c
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit b4af964

Please sign in to comment.