summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorEvan Quan <evan.quan@amd.com>2020-06-08 16:29:41 +0800
committerAlex Deucher <alexander.deucher@amd.com>2020-07-01 01:59:18 -0400
commit1e239fdd31cdf1729bc1e8b4538bf590bd28de57 (patch)
treeff280969d4229b84aa1b3b97f0ee376549be3dc5 /drivers/gpu/drm
parentf3bc9aecebbc8f58e13477567afc697dfa6becaf (diff)
drm/amd/powerplay: maximize code sharing around power limit
Also cache the current and max power limits. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/amd/powerplay/arcturus_ppt.c49
-rw-r--r--drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h2
-rw-r--r--drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h3
-rw-r--r--drivers/gpu/drm/amd/powerplay/navi10_ppt.c53
-rw-r--r--drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c51
-rw-r--r--drivers/gpu/drm/amd/powerplay/smu_v11_0.c23
6 files changed, 94 insertions, 87 deletions
diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c
index 0704a9c1d567..2c78271123f7 100644
--- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c
@@ -1413,40 +1413,33 @@ static int arcturus_get_power_limit(struct smu_context *smu,
uint32_t *limit,
bool cap)
{
+ struct smu_11_0_powerplay_table *powerplay_table =
+ (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table;
PPTable_t *pptable = smu->smu_table.driver_pptable;
- uint32_t asic_default_power_limit = 0;
- int ret = 0;
- int power_src;
-
- if (!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;
+ uint32_t power_limit, od_percent;
- ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetPptLimit,
- power_src << 16, &asic_default_power_limit);
- if (ret) {
- dev_err(smu->adev->dev, "[%s] get PPT limit failed!", __func__);
- return ret;
- }
- } else {
- /* the last hope to figure out the ppt limit */
- if (!pptable) {
- dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!");
- return -EINVAL;
- }
- asic_default_power_limit =
- pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
+ if (smu_v11_0_get_current_power_limit(smu, &power_limit)) {
+ /* the last hope to figure out the ppt limit */
+ if (!pptable) {
+ dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!");
+ return -EINVAL;
}
+ power_limit =
+ pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
+ }
+ smu->current_power_limit = power_limit;
+
+ if (smu->od_enabled) {
+ od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
+
+ dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit);
- smu->power_limit = asic_default_power_limit;
+ power_limit *= (100 + od_percent);
+ power_limit /= 100;
}
+ smu->max_power_limit = power_limit;
- if (cap)
- *limit = smu_get_max_power_limit(smu);
- else
- *limit = smu->power_limit;
+ *limit = (cap ? smu->max_power_limit : smu->current_power_limit);
return 0;
}
diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
index 9276320c09d0..574a793b5d26 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
@@ -382,6 +382,8 @@ struct smu_context
bool od_enabled;
uint32_t power_limit;
uint32_t default_power_limit;
+ uint32_t current_power_limit;
+ uint32_t max_power_limit;
/* soft pptable */
uint32_t ppt_offset_bytes;
diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h
index 9da2f26b7267..2e9939beb128 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h
@@ -196,6 +196,9 @@ int smu_v11_0_get_enabled_mask(struct smu_context *smu,
int smu_v11_0_notify_display_change(struct smu_context *smu);
+int smu_v11_0_get_current_power_limit(struct smu_context *smu,
+ uint32_t *power_limit);
+
int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n);
int smu_v11_0_get_current_clk_freq(struct smu_context *smu,
diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
index e63498e747ac..b867f94ba559 100644
--- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
@@ -1923,43 +1923,36 @@ static uint32_t navi10_get_pptable_power_limit(struct smu_context *smu)
}
static int navi10_get_power_limit(struct smu_context *smu,
- uint32_t *limit,
- bool cap)
+ uint32_t *limit,
+ bool cap)
{
+ struct smu_11_0_powerplay_table *powerplay_table =
+ (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table;
PPTable_t *pptable = smu->smu_table.driver_pptable;
- uint32_t asic_default_power_limit = 0;
- int ret = 0;
- int power_src;
-
- if (!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;
+ uint32_t power_limit, od_percent;
- ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetPptLimit,
- power_src << 16, &asic_default_power_limit);
- if (ret) {
- dev_err(smu->adev->dev, "[%s] get PPT limit failed!", __func__);
- return ret;
- }
- } else {
- /* the last hope to figure out the ppt limit */
- if (!pptable) {
- dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!");
- return -EINVAL;
- }
- asic_default_power_limit =
- pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
+ if (smu_v11_0_get_current_power_limit(smu, &power_limit)) {
+ /* the last hope to figure out the ppt limit */
+ if (!pptable) {
+ dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!");
+ return -EINVAL;
}
+ power_limit =
+ pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
+ }
+ smu->current_power_limit = power_limit;
- smu->power_limit = asic_default_power_limit;
+ if (smu->od_enabled) {
+ od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
+
+ dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit);
+
+ power_limit *= (100 + od_percent);
+ power_limit /= 100;
}
+ smu->max_power_limit = power_limit;
- if (cap)
- *limit = smu_get_max_power_limit(smu);
- else
- *limit = smu->power_limit;
+ *limit = (cap ? smu->max_power_limit : smu->current_power_limit);
return 0;
}
diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c
index b83675227a6f..c427e233dfad 100644
--- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c
+++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c
@@ -1747,40 +1747,33 @@ static int sienna_cichlid_get_power_limit(struct smu_context *smu,
uint32_t *limit,
bool cap)
{
+ struct smu_11_0_7_powerplay_table *powerplay_table =
+ (struct smu_11_0_7_powerplay_table *)smu->smu_table.power_play_table;
PPTable_t *pptable = smu->smu_table.driver_pptable;
- uint32_t asic_default_power_limit = 0;
- int ret = 0;
- int power_src;
-
- if (!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, &asic_default_power_limit);
- if (ret) {
- dev_err(smu->adev->dev, "[%s] get PPT limit failed!", __func__);
- return ret;
- }
- } else {
- /* the last hope to figure out the ppt limit */
- if (!pptable) {
- dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!");
- return -EINVAL;
- }
- asic_default_power_limit =
- pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
+ uint32_t power_limit, od_percent;
+
+ if (smu_v11_0_get_current_power_limit(smu, &power_limit)) {
+ /* the last hope to figure out the ppt limit */
+ if (!pptable) {
+ dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!");
+ return -EINVAL;
}
+ power_limit =
+ pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0];
+ }
+ smu->current_power_limit = power_limit;
+
+ if (smu->od_enabled) {
+ od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_7_ODSETTING_POWERPERCENTAGE]);
+
+ dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit);
- smu->power_limit = asic_default_power_limit;
+ power_limit *= (100 + od_percent);
+ power_limit /= 100;
}
+ smu->max_power_limit = power_limit;
- if (cap)
- *limit = smu_get_max_power_limit(smu);
- else
- *limit = smu->power_limit;
+ *limit = (cap ? smu->max_power_limit : smu->current_power_limit);
return 0;
}
diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
index 9421b4b50f60..53491c55abd8 100644
--- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
+++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
@@ -1056,6 +1056,29 @@ int smu_v11_0_init_max_sustainable_clocks(struct smu_context *smu)
return 0;
}
+int smu_v11_0_get_current_power_limit(struct smu_context *smu,
+ uint32_t *power_limit)
+{
+ int power_src;
+ int ret = 0;
+
+ if (!smu_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT))
+ return -EINVAL;
+
+ 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,
+ power_limit);
+ if (ret)
+ dev_err(smu->adev->dev, "[%s] get PPT limit failed!", __func__);
+
+ return ret;
+}
+
int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n)
{
int ret = 0;