[PATCH 2/7] drm/amd/powerplay: maximize code sharing around power limit

Evan Quan evan.quan at amd.com
Mon Jun 8 10:52:29 UTC 2020


Also cache the current and max power limits.

Change-Id: Ida2ce964736bee2e558522441d3505f84c4e00f4
Signed-off-by: Evan Quan <evan.quan at amd.com>
---
 drivers/gpu/drm/amd/powerplay/arcturus_ppt.c  | 49 ++++++++---------
 .../gpu/drm/amd/powerplay/inc/amdgpu_smu.h    |  2 +
 drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h |  3 ++
 drivers/gpu/drm/amd/powerplay/navi10_ppt.c    | 53 ++++++++-----------
 .../drm/amd/powerplay/sienna_cichlid_ppt.c    | 51 ++++++++----------
 drivers/gpu/drm/amd/powerplay/smu_v11_0.c     | 23 ++++++++
 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 acb9a3cec7ee..358c903c4a86 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;
-- 
2.27.0



More information about the amd-gfx mailing list