aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.14.71/3525-drm-amd-pp-Expose-set-get_power_limit-for-DGPU.patch
blob: 0428da98545d4382b8b9673a6d72ce0a970e8e23 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
From e541ffbf3778c98812210414be9e11db579fcf53 Mon Sep 17 00:00:00 2001
From: Rex Zhu <Rex.Zhu@amd.com>
Date: Mon, 29 Jan 2018 18:04:18 +0800
Subject: [PATCH 3525/4131] drm/amd/pp: Expose set/get_power_limit for DGPU

User can change power limit between
[0, 1] * max power limit.

Set power limit to 0, restore to max power limit.

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Rex Zhu <Rex.Zhu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/include/kgd_pp_interface.h     |  2 +
 drivers/gpu/drm/amd/powerplay/amd_powerplay.c      | 61 ++++++++++++++++++++++
 drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c   |  1 +
 .../gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c   |  8 +--
 drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c |  1 +
 .../gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c |  7 +--
 drivers/gpu/drm/amd/powerplay/inc/hwmgr.h          |  3 ++
 7 files changed, 77 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
index 4f69fe8..22c2fa3 100644
--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
@@ -283,6 +283,8 @@ struct amd_pm_funcs {
 					uint32_t mc_addr_low,
 					uint32_t mc_addr_hi,
 					uint32_t size);
+	int (*set_power_limit)(void *handle, uint32_t n);
+	int (*get_power_limit)(void *handle, uint32_t *limit, bool default_limit);
 /* export to DC */
 	u32 (*get_sclk)(void *handle, bool low);
 	u32 (*get_mclk)(void *handle, bool low);
diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
index 59464a9..e772bf6 100644
--- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
+++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
@@ -1237,6 +1237,65 @@ static int pp_dpm_notify_smu_memory_info(void *handle,
 	return ret;
 }
 
+static int pp_set_power_limit(void *handle, uint32_t limit)
+{
+	struct pp_hwmgr *hwmgr;
+	struct pp_instance *pp_handle = (struct pp_instance *)handle;
+	int ret = 0;
+
+	ret = pp_check(pp_handle);
+
+	if (ret)
+		return ret;
+
+	hwmgr = pp_handle->hwmgr;
+
+	if (hwmgr->hwmgr_func->set_power_limit == NULL) {
+		pr_info("%s was not implemented.\n", __func__);
+		return -EINVAL;
+	}
+
+	if (limit == 0)
+		limit = hwmgr->default_power_limit;
+
+	if (limit > hwmgr->default_power_limit)
+		return -EINVAL;
+
+	mutex_lock(&pp_handle->pp_lock);
+	hwmgr->hwmgr_func->set_power_limit(hwmgr, limit);
+	hwmgr->power_limit = limit;
+	mutex_unlock(&pp_handle->pp_lock);
+	return ret;
+}
+
+static int pp_get_power_limit(void *handle, uint32_t *limit, bool default_limit)
+{
+	struct pp_hwmgr *hwmgr;
+	struct pp_instance *pp_handle = (struct pp_instance *)handle;
+	int ret = 0;
+
+	ret = pp_check(pp_handle);
+
+	if (ret)
+		return ret;
+
+	if (limit == NULL)
+		return -EINVAL;
+
+	hwmgr = pp_handle->hwmgr;
+
+	mutex_lock(&pp_handle->pp_lock);
+
+	if (default_limit)
+		*limit = hwmgr->default_power_limit;
+	else
+		*limit = hwmgr->power_limit;
+
+	mutex_unlock(&pp_handle->pp_lock);
+
+	return ret;
+}
+
 static int pp_display_configuration_change(void *handle,
 	const struct amd_pp_display_configuration *display_config)
 {
@@ -1531,6 +1590,8 @@ const struct amd_pm_funcs pp_dpm_funcs = {
 	.get_power_profile_mode = pp_get_power_profile_mode,
 	.set_power_profile_mode = pp_set_power_profile_mode,
 	.odn_edit_dpm_table = pp_odn_edit_dpm_table,
+	.set_power_limit = pp_set_power_limit,
+	.get_power_limit = pp_get_power_limit,
 /* export to DC */
 	.get_sclk = pp_dpm_get_sclk,
 	.get_mclk = pp_dpm_get_mclk,
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
index dffa670..e2bb09c 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
@@ -4983,6 +4983,7 @@ static const struct pp_hwmgr_func smu7_hwmgr_funcs = {
 	.get_max_high_clocks = smu7_get_max_high_clocks,
 	.get_thermal_temperature_range = smu7_get_thermal_temperature_range,
 	.odn_edit_dpm_table = smu7_odn_edit_dpm_table,
+	.set_power_limit = smu7_set_power_limit,
 };
 
 uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock,
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c
index ac80fc3..8080c65 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c
@@ -900,6 +900,8 @@ int smu7_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n)
 {
 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
 
+	n = (n & 0xff) << 8;
+
 	if (data->power_containment_features &
 			POWERCONTAINMENT_FEATURE_PkgPwrLimit)
 		return smum_send_msg_to_smc_with_parameter(hwmgr,
@@ -946,12 +948,12 @@ int smu7_enable_power_containment(struct pp_hwmgr *hwmgr)
 			PP_ASSERT_WITH_CODE((0 == smc_result),
 					"Failed to enable PkgPwrTracking in SMC.", result = -1;);
 			if (0 == smc_result) {
-				uint32_t default_limit =
-					(uint32_t)(cac_table->usMaximumPowerDeliveryLimit * 256);
+				hwmgr->default_power_limit = hwmgr->power_limit =
+						cac_table->usMaximumPowerDeliveryLimit;
 				data->power_containment_features |=
 						POWERCONTAINMENT_FEATURE_PkgPwrLimit;
 
-				if (smu7_set_power_limit(hwmgr, default_limit))
+				if (smu7_set_power_limit(hwmgr, hwmgr->power_limit))
 					pr_err("Failed to set Default Power Limit in SMC!");
 			}
 		}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
index d2cd6e6..3ca2788 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
@@ -5158,6 +5158,7 @@ static const struct pp_hwmgr_func vega10_hwmgr_funcs = {
 	.start_thermal_controller = vega10_start_thermal_controller,
 	.get_power_profile_mode = vega10_get_power_profile_mode,
 	.set_power_profile_mode = vega10_set_power_profile_mode,
+	.set_power_limit = vega10_set_power_limit,
 };
 
 int vega10_hwmgr_init(struct pp_hwmgr *hwmgr)
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c
index 598a194..981c9e5 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c
@@ -1357,10 +1357,11 @@ int vega10_enable_power_containment(struct pp_hwmgr *hwmgr)
 	struct phm_ppt_v2_information *table_info =
 			(struct phm_ppt_v2_information *)(hwmgr->pptable);
 	struct phm_tdp_table *tdp_table = table_info->tdp_table;
-	uint32_t default_pwr_limit =
-			(uint32_t)(tdp_table->usMaximumPowerDeliveryLimit);
 	int result = 0;
 
+	hwmgr->default_power_limit = hwmgr->power_limit =
+			(uint32_t)(tdp_table->usMaximumPowerDeliveryLimit);
+
 	if (PP_CAP(PHM_PlatformCaps_PowerContainment)) {
 		if (data->smu_features[GNLD_PPT].supported)
 			PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
@@ -1374,7 +1375,7 @@ int vega10_enable_power_containment(struct pp_hwmgr *hwmgr)
 					"Attempt to enable PPT feature Failed!",
 					data->smu_features[GNLD_TDC].supported = false);
 
-		result = vega10_set_power_limit(hwmgr, default_pwr_limit);
+		result = vega10_set_power_limit(hwmgr, hwmgr->power_limit);
 		PP_ASSERT_WITH_CODE(!result,
 				"Failed to set Default Power Limit in SMC!",
 				return result);
diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
index 4d96439..c0f9cea 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
@@ -347,6 +347,7 @@ struct pp_hwmgr_func {
 	int (*odn_edit_dpm_table)(struct pp_hwmgr *hwmgr,
 					enum PP_OD_DPM_TABLE_COMMAND type,
 					long *input, uint32_t size);
+	int (*set_power_limit)(struct pp_hwmgr *hwmgr, uint32_t n);
 	int (*set_mmhub_powergating_by_smu)(struct pp_hwmgr *hwmgr);
 };
 
@@ -759,6 +760,8 @@ struct pp_hwmgr {
 	uint32_t pstate_sclk;
 	uint32_t pstate_mclk;
 	bool od_enabled;
+	uint32_t power_limit;
+	uint32_t default_power_limit;
 };
 
 struct cgs_irq_src_funcs {
-- 
2.7.4