summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd
diff options
context:
space:
mode:
authorEvan Quan <evan.quan@amd.com>2019-07-30 22:52:37 -0500
committerAlex Deucher <alexander.deucher@amd.com>2019-07-30 23:48:35 -0500
commitb4af964e75c4163fe3baf98193495f7921a4b3b7 (patch)
tree33309a9111c245cd1184d4faa69b073ca7510b22 /drivers/gpu/drm/amd
parent1f23cadbe0775559b3152a4f1fcb566d8cf6f571 (diff)
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>
Diffstat (limited to 'drivers/gpu/drm/amd')
-rw-r--r--drivers/gpu/drm/amd/powerplay/amdgpu_smu.c2
-rw-r--r--drivers/gpu/drm/amd/powerplay/arcturus_ppt.c51
-rw-r--r--drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h4
-rw-r--r--drivers/gpu/drm/amd/powerplay/navi10_ppt.c51
-rw-r--r--drivers/gpu/drm/amd/powerplay/smu_v11_0.c55
5 files changed, 116 insertions, 47 deletions
diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
index b1e0e2a4aca1..13b2c8a60232 100644
--- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
@@ -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;
}
diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c
index c67a9914ce7b..9360f5a25b69 100644
--- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c
@@ -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)
diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
index 76edb2ccf160..1ecd73cd768c 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
@@ -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) \
diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
index 5ae19ae58807..106352a4fb82 100644
--- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
@@ -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)
diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
index 89f4c9e19642..35669e80a246 100644
--- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
+++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
@@ -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,