Blob Blame History Raw
From c06403045aad6ae2edd935f6309e0c72e118c6de Mon Sep 17 00:00:00 2001
From: Evan Quan <evan.quan@amd.com>
Date: Thu, 11 Jul 2019 14:36:44 +0800
Subject: drm/amd/powerplay: input check for unsupported message/clock index
Git-commit: c06403045aad6ae2edd935f6309e0c72e118c6de
Patch-mainline: v5.4-rc1
References: bsc#1152489

This can avoid them to be handled in a wrong way without notice.
Since not all SMU messages/clocks are supported on every SMU11 ASIC.

Signed-off-by: Evan Quan <evan.quan@amd.com>
Reviewed-by: Feifei Xu <Feifei.Xu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 18 +++++++----
 drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 31 ++++++++++++++-----
 drivers/gpu/drm/amd/powerplay/smu_v11_0.c  | 35 ++++++++++++++++++----
 drivers/gpu/drm/amd/powerplay/vega20_ppt.c | 31 ++++++++++++++-----
 4 files changed, 90 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
index c8048b865161..ec1904e47927 100644
--- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
@@ -331,7 +331,7 @@ int smu_update_table(struct smu_context *smu, enum smu_table_id table_index, int
 	int ret = 0;
 	int table_id = smu_table_get_index(smu, table_index);
 
-	if (!table_data || table_id >= smu_table->table_count)
+	if (!table_data || table_id >= smu_table->table_count || table_id < 0)
 		return -EINVAL;
 
 	table = &smu_table->tables[table_index];
@@ -462,10 +462,12 @@ int smu_feature_init_dpm(struct smu_context *smu)
 int smu_feature_is_enabled(struct smu_context *smu, enum smu_feature_mask mask)
 {
 	struct smu_feature *feature = &smu->smu_feature;
-	uint32_t feature_id;
+	int feature_id;
 	int ret = 0;
 
 	feature_id = smu_feature_get_index(smu, mask);
+	if (feature_id < 0)
+		return 0;
 
 	WARN_ON(feature_id > feature->feature_num);
 
@@ -480,10 +482,12 @@ int smu_feature_set_enabled(struct smu_context *smu, enum smu_feature_mask mask,
 			    bool enable)
 {
 	struct smu_feature *feature = &smu->smu_feature;
-	uint32_t feature_id;
+	int feature_id;
 	int ret = 0;
 
 	feature_id = smu_feature_get_index(smu, mask);
+	if (feature_id < 0)
+		return -EINVAL;
 
 	WARN_ON(feature_id > feature->feature_num);
 
@@ -506,10 +510,12 @@ int smu_feature_set_enabled(struct smu_context *smu, enum smu_feature_mask mask,
 int smu_feature_is_supported(struct smu_context *smu, enum smu_feature_mask mask)
 {
 	struct smu_feature *feature = &smu->smu_feature;
-	uint32_t feature_id;
+	int feature_id;
 	int ret = 0;
 
 	feature_id = smu_feature_get_index(smu, mask);
+	if (feature_id < 0)
+		return 0;
 
 	WARN_ON(feature_id > feature->feature_num);
 
@@ -525,10 +531,12 @@ int smu_feature_set_supported(struct smu_context *smu,
 			      bool enable)
 {
 	struct smu_feature *feature = &smu->smu_feature;
-	uint32_t feature_id;
+	int feature_id;
 	int ret = 0;
 
 	feature_id = smu_feature_get_index(smu, mask);
+	if (feature_id < 0)
+		return -EINVAL;
 
 	WARN_ON(feature_id > feature->feature_num);
 
diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
index f6b1c8b2b2d6..7061ff14333f 100644
--- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
@@ -216,8 +216,10 @@ static int navi10_get_smu_msg_index(struct smu_context *smc, uint32_t index)
 		return -EINVAL;
 
 	mapping = navi10_message_map[index];
-	if (!(mapping.valid_mapping))
+	if (!(mapping.valid_mapping)) {
+		pr_warn("Unsupported SMU message: %d\n", index);
 		return -EINVAL;
+	}
 
 	return mapping.map_to;
 }
@@ -230,8 +232,10 @@ static int navi10_get_smu_clk_index(struct smu_context *smc, uint32_t index)
 		return -EINVAL;
 
 	mapping = navi10_clk_map[index];
-	if (!(mapping.valid_mapping))
+	if (!(mapping.valid_mapping)) {
+		pr_warn("Unsupported SMU clock: %d\n", index);
 		return -EINVAL;
+	}
 
 	return mapping.map_to;
 }
@@ -244,8 +248,10 @@ static int navi10_get_smu_feature_index(struct smu_context *smc, uint32_t index)
 		return -EINVAL;
 
 	mapping = navi10_feature_mask_map[index];
-	if (!(mapping.valid_mapping))
+	if (!(mapping.valid_mapping)) {
+		pr_warn("Unsupported SMU feature: %d\n", index);
 		return -EINVAL;
+	}
 
 	return mapping.map_to;
 }
@@ -258,8 +264,10 @@ static int navi10_get_smu_table_index(struct smu_context *smc, uint32_t index)
 		return -EINVAL;
 
 	mapping = navi10_table_map[index];
-	if (!(mapping.valid_mapping))
+	if (!(mapping.valid_mapping)) {
+		pr_warn("Unsupported SMU table: %d\n", index);
 		return -EINVAL;
+	}
 
 	return mapping.map_to;
 }
@@ -272,8 +280,10 @@ static int navi10_get_pwr_src_index(struct smu_context *smc, uint32_t index)
 		return -EINVAL;
 
 	mapping = navi10_pwr_src_map[index];
-	if (!(mapping.valid_mapping))
+	if (!(mapping.valid_mapping)) {
+		pr_warn("Unsupported power source: %d\n", index);
 		return -EINVAL;
+	}
 
 	return mapping.map_to;
 }
@@ -287,8 +297,10 @@ static int navi10_get_workload_type(struct smu_context *smu, enum PP_SMC_POWER_P
 		return -EINVAL;
 
 	mapping = navi10_workload_map[profile];
-	if (!(mapping.valid_mapping))
+	if (!(mapping.valid_mapping)) {
+		pr_warn("Unsupported workload: %d\n", (int)profile);
 		return -EINVAL;
+	}
 
 	return mapping.map_to;
 }
@@ -969,7 +981,7 @@ static int navi10_get_power_profile_mode(struct smu_context *smu, char *buf)
 {
 	DpmActivityMonitorCoeffInt_t activity_monitor;
 	uint32_t i, size = 0;
-	uint16_t workload_type = 0;
+	int16_t workload_type = 0;
 	static const char *profile_name[] = {
 					"BOOTUP_DEFAULT",
 					"3D_FULL_SCREEN",
@@ -1002,6 +1014,9 @@ static int navi10_get_power_profile_mode(struct smu_context *smu, char *buf)
 	for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
 		/* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
 		workload_type = smu_workload_get_type(smu, i);
+		if (workload_type < 0)
+			return -EINVAL;
+
 		result = smu_update_table(smu,
 					  SMU_TABLE_ACTIVITY_MONITOR_COEFF, workload_type,
 					  (void *)(&activity_monitor), false);
@@ -1130,6 +1145,8 @@ static int navi10_set_power_profile_mode(struct smu_context *smu, long *input, u
 
 	/* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
 	workload_type = smu_workload_get_type(smu, smu->power_profile_mode);
+	if (workload_type < 0)
+		return -EINVAL;
 	smu_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
 				    1 << workload_type);
 
diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
index 3505b92a6540..9f3a84fbb9cf 100644
--- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
+++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
@@ -937,11 +937,17 @@ smu_v11_0_get_max_sustainable_clock(struct smu_context *smu, uint32_t *clock,
 				    enum smu_clk_type clock_select)
 {
 	int ret = 0;
+	int clk_id;
 
 	if (!smu->pm_enabled)
 		return ret;
+
+	clk_id = smu_clk_get_index(smu, clock_select);
+	if (clk_id < 0)
+		return -EINVAL;
+
 	ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetDcModeMaxDpmFreq,
-					  smu_clk_get_index(smu, clock_select) << 16);
+					  clk_id << 16);
 	if (ret) {
 		pr_err("[GetMaxSustainableClock] Failed to get max DC clock from SMC!");
 		return ret;
@@ -956,7 +962,7 @@ smu_v11_0_get_max_sustainable_clock(struct smu_context *smu, uint32_t *clock,
 
 	/* if DC limit is zero, return AC limit */
 	ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetMaxDpmFreq,
-					  smu_clk_get_index(smu, clock_select) << 16);
+					  clk_id << 16);
 	if (ret) {
 		pr_err("[GetMaxSustainableClock] failed to get max AC clock from SMC!");
 		return ret;
@@ -1052,6 +1058,11 @@ static int smu_v11_0_get_power_limit(struct smu_context *smu,
 				     bool get_default)
 {
 	int ret = 0;
+	int power_src;
+
+	power_src = smu_power_get_index(smu, SMU_POWER_SOURCE_AC);
+	if (power_src < 0)
+		return -EINVAL;
 
 	if (get_default) {
 		mutex_lock(&smu->mutex);
@@ -1063,7 +1074,7 @@ static int smu_v11_0_get_power_limit(struct smu_context *smu,
 		mutex_unlock(&smu->mutex);
 	} else {
 		ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetPptLimit,
-			smu_power_get_index(smu, SMU_POWER_SOURCE_AC) << 16);
+			power_src << 16);
 		if (ret) {
 			pr_err("[%s] get PPT limit failed!", __func__);
 			return ret;
@@ -1106,16 +1117,21 @@ static int smu_v11_0_get_current_clk_freq(struct smu_context *smu,
 {
 	int ret = 0;
 	uint32_t freq = 0;
+	int asic_clk_id;
 
 	if (clk_id >= SMU_CLK_COUNT || !value)
 		return -EINVAL;
 
+	asic_clk_id = smu_clk_get_index(smu, clk_id);
+	if (asic_clk_id < 0)
+		return -EINVAL;
+
 	/* if don't has GetDpmClockFreq Message, try get current clock by SmuMetrics_t */
-	if (smu_msg_get_index(smu, SMU_MSG_GetDpmClockFreq) == 0)
+	if (smu_msg_get_index(smu, SMU_MSG_GetDpmClockFreq) < 0)
 		ret =  smu_get_current_clk_freq_by_table(smu, clk_id, &freq);
 	else {
 		ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetDpmClockFreq,
-						  (smu_clk_get_index(smu, clk_id) << 16));
+						  (asic_clk_id << 16));
 		if (ret)
 			return ret;
 
@@ -1295,6 +1311,7 @@ smu_v11_0_display_clock_voltage_request(struct smu_context *smu,
 	int ret = 0;
 	enum smu_clk_type clk_select = 0;
 	uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000;
+	int clk_id;
 
 	if (!smu->pm_enabled)
 		return -EINVAL;
@@ -1326,9 +1343,15 @@ smu_v11_0_display_clock_voltage_request(struct smu_context *smu,
 		if (ret)
 			goto failed;
 
+		clk_id = smu_clk_get_index(smu, clk_select);
+		if (clk_id < 0) {
+			ret = -EINVAL;
+			goto failed;
+		}
+
 		mutex_lock(&smu->mutex);
 		ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinByFreq,
-			(smu_clk_get_index(smu, clk_select) << 16) | clk_freq);
+			(clk_id << 16) | clk_freq);
 		mutex_unlock(&smu->mutex);
 	}
 
diff --git a/drivers/gpu/drm/amd/powerplay/vega20_ppt.c b/drivers/gpu/drm/amd/powerplay/vega20_ppt.c
index af54fee0aed2..080956ea0570 100644
--- a/drivers/gpu/drm/amd/powerplay/vega20_ppt.c
+++ b/drivers/gpu/drm/amd/powerplay/vega20_ppt.c
@@ -231,8 +231,10 @@ static int vega20_get_smu_table_index(struct smu_context *smc, uint32_t index)
 		return -EINVAL;
 
 	mapping = vega20_table_map[index];
-	if (!(mapping.valid_mapping))
+	if (!(mapping.valid_mapping)) {
+		pr_warn("Unsupported SMU table: %d\n", index);
 		return -EINVAL;
+	}
 
 	return mapping.map_to;
 }
@@ -245,8 +247,10 @@ static int vega20_get_pwr_src_index(struct smu_context *smc, uint32_t index)
 		return -EINVAL;
 
 	mapping = vega20_pwr_src_map[index];
-	if (!(mapping.valid_mapping))
+	if (!(mapping.valid_mapping)) {
+		pr_warn("Unsupported power source: %d\n", index);
 		return -EINVAL;
+	}
 
 	return mapping.map_to;
 }
@@ -259,8 +263,10 @@ static int vega20_get_smu_feature_index(struct smu_context *smc, uint32_t index)
 		return -EINVAL;
 
 	mapping = vega20_feature_mask_map[index];
-	if (!(mapping.valid_mapping))
+	if (!(mapping.valid_mapping)) {
+		pr_warn("Unsupported SMU feature: %d\n", index);
 		return -EINVAL;
+	}
 
 	return mapping.map_to;
 }
@@ -273,8 +279,10 @@ static int vega20_get_smu_clk_index(struct smu_context *smc, uint32_t index)
 		return -EINVAL;
 
 	mapping = vega20_clk_map[index];
-	if (!(mapping.valid_mapping))
+	if (!(mapping.valid_mapping)) {
+		pr_warn("Unsupported SMU clock: %d\n", index);
 		return -EINVAL;
+	}
 
 	return mapping.map_to;
 }
@@ -287,8 +295,10 @@ static int vega20_get_smu_msg_index(struct smu_context *smc, uint32_t index)
 		return -EINVAL;
 
 	mapping = vega20_message_map[index];
-	if (!(mapping.valid_mapping))
+	if (!(mapping.valid_mapping)) {
+		pr_warn("Unsupported SMU message: %d\n", index);
 		return -EINVAL;
+	}
 
 	return mapping.map_to;
 }
@@ -301,8 +311,10 @@ static int vega20_get_workload_type(struct smu_context *smu, enum PP_SMC_POWER_P
 		return -EINVAL;
 
 	mapping = vega20_workload_map[profile];
-	if (!(mapping.valid_mapping))
+	if (!(mapping.valid_mapping)) {
+		pr_warn("Unsupported SMU workload: %d\n", (int)profile);
 		return -EINVAL;
+	}
 
 	return mapping.map_to;
 }
@@ -1778,7 +1790,7 @@ static int vega20_get_power_profile_mode(struct smu_context *smu, char *buf)
 {
 	DpmActivityMonitorCoeffInt_t activity_monitor;
 	uint32_t i, size = 0;
-	uint16_t workload_type = 0;
+	int16_t workload_type = 0;
 	static const char *profile_name[] = {
 					"BOOTUP_DEFAULT",
 					"3D_FULL_SCREEN",
@@ -1811,6 +1823,9 @@ static int vega20_get_power_profile_mode(struct smu_context *smu, char *buf)
 	for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
 		/* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
 		workload_type = smu_workload_get_type(smu, i);
+		if (workload_type < 0)
+			return -EINVAL;
+
 		result = smu_update_table(smu,
 					  SMU_TABLE_ACTIVITY_MONITOR_COEFF, workload_type,
 					  (void *)(&activity_monitor), false);
@@ -1963,6 +1978,8 @@ static int vega20_set_power_profile_mode(struct smu_context *smu, long *input, u
 
 	/* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
 	workload_type = smu_workload_get_type(smu, smu->power_profile_mode);
+	if (workload_type < 0)
+		return -EINVAL;
 	smu_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
 				    1 << workload_type);
 
-- 
2.28.0