]> Git Repo - J-linux.git/blob - drivers/gpu/drm/i915/gt/selftest_slpc.c
PM: sleep: Fix runtime PM based cpuidle support
[J-linux.git] / drivers / gpu / drm / i915 / gt / selftest_slpc.c
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2021 Intel Corporation
4  */
5
6 #define NUM_STEPS 5
7 #define H2G_DELAY 50000
8 #define delay_for_h2g() usleep_range(H2G_DELAY, H2G_DELAY + 10000)
9 #define FREQUENCY_REQ_UNIT      DIV_ROUND_CLOSEST(GT_FREQUENCY_MULTIPLIER, \
10                                                   GEN9_FREQ_SCALER)
11
12 static int slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 freq)
13 {
14         int ret;
15
16         ret = intel_guc_slpc_set_min_freq(slpc, freq);
17         if (ret)
18                 pr_err("Could not set min frequency to [%u]\n", freq);
19         else /* Delay to ensure h2g completes */
20                 delay_for_h2g();
21
22         return ret;
23 }
24
25 static int slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 freq)
26 {
27         int ret;
28
29         ret = intel_guc_slpc_set_max_freq(slpc, freq);
30         if (ret)
31                 pr_err("Could not set maximum frequency [%u]\n",
32                        freq);
33         else /* Delay to ensure h2g completes */
34                 delay_for_h2g();
35
36         return ret;
37 }
38
39 static int live_slpc_clamp_min(void *arg)
40 {
41         struct drm_i915_private *i915 = arg;
42         struct intel_gt *gt = &i915->gt;
43         struct intel_guc_slpc *slpc = &gt->uc.guc.slpc;
44         struct intel_rps *rps = &gt->rps;
45         struct intel_engine_cs *engine;
46         enum intel_engine_id id;
47         struct igt_spinner spin;
48         u32 slpc_min_freq, slpc_max_freq;
49         int err = 0;
50
51         if (!intel_uc_uses_guc_slpc(&gt->uc))
52                 return 0;
53
54         if (igt_spinner_init(&spin, gt))
55                 return -ENOMEM;
56
57         if (intel_guc_slpc_get_max_freq(slpc, &slpc_max_freq)) {
58                 pr_err("Could not get SLPC max freq\n");
59                 return -EIO;
60         }
61
62         if (intel_guc_slpc_get_min_freq(slpc, &slpc_min_freq)) {
63                 pr_err("Could not get SLPC min freq\n");
64                 return -EIO;
65         }
66
67         if (slpc_min_freq == slpc_max_freq) {
68                 pr_err("Min/Max are fused to the same value\n");
69                 return -EINVAL;
70         }
71
72         intel_gt_pm_wait_for_idle(gt);
73         intel_gt_pm_get(gt);
74         for_each_engine(engine, gt, id) {
75                 struct i915_request *rq;
76                 u32 step, min_freq, req_freq;
77                 u32 act_freq, max_act_freq;
78
79                 if (!intel_engine_can_store_dword(engine))
80                         continue;
81
82                 /* Go from min to max in 5 steps */
83                 step = (slpc_max_freq - slpc_min_freq) / NUM_STEPS;
84                 max_act_freq = slpc_min_freq;
85                 for (min_freq = slpc_min_freq; min_freq < slpc_max_freq;
86                                         min_freq += step) {
87                         err = slpc_set_min_freq(slpc, min_freq);
88                         if (err)
89                                 break;
90
91                         st_engine_heartbeat_disable(engine);
92
93                         rq = igt_spinner_create_request(&spin,
94                                                         engine->kernel_context,
95                                                         MI_NOOP);
96                         if (IS_ERR(rq)) {
97                                 err = PTR_ERR(rq);
98                                 st_engine_heartbeat_enable(engine);
99                                 break;
100                         }
101
102                         i915_request_add(rq);
103
104                         if (!igt_wait_for_spinner(&spin, rq)) {
105                                 pr_err("%s: Spinner did not start\n",
106                                        engine->name);
107                                 igt_spinner_end(&spin);
108                                 st_engine_heartbeat_enable(engine);
109                                 intel_gt_set_wedged(engine->gt);
110                                 err = -EIO;
111                                 break;
112                         }
113
114                         /* Wait for GuC to detect business and raise
115                          * requested frequency if necessary.
116                          */
117                         delay_for_h2g();
118
119                         req_freq = intel_rps_read_punit_req_frequency(rps);
120
121                         /* GuC requests freq in multiples of 50/3 MHz */
122                         if (req_freq < (min_freq - FREQUENCY_REQ_UNIT)) {
123                                 pr_err("SWReq is %d, should be at least %d\n", req_freq,
124                                        min_freq - FREQUENCY_REQ_UNIT);
125                                 igt_spinner_end(&spin);
126                                 st_engine_heartbeat_enable(engine);
127                                 err = -EINVAL;
128                                 break;
129                         }
130
131                         act_freq =  intel_rps_read_actual_frequency(rps);
132                         if (act_freq > max_act_freq)
133                                 max_act_freq = act_freq;
134
135                         igt_spinner_end(&spin);
136                         st_engine_heartbeat_enable(engine);
137                 }
138
139                 pr_info("Max actual frequency for %s was %d\n",
140                         engine->name, max_act_freq);
141
142                 /* Actual frequency should rise above min */
143                 if (max_act_freq == slpc_min_freq) {
144                         pr_err("Actual freq did not rise above min\n");
145                         err = -EINVAL;
146                 }
147
148                 if (err)
149                         break;
150         }
151
152         /* Restore min/max frequencies */
153         slpc_set_max_freq(slpc, slpc_max_freq);
154         slpc_set_min_freq(slpc, slpc_min_freq);
155
156         if (igt_flush_test(gt->i915))
157                 err = -EIO;
158
159         intel_gt_pm_put(gt);
160         igt_spinner_fini(&spin);
161         intel_gt_pm_wait_for_idle(gt);
162
163         return err;
164 }
165
166 static int live_slpc_clamp_max(void *arg)
167 {
168         struct drm_i915_private *i915 = arg;
169         struct intel_gt *gt = &i915->gt;
170         struct intel_guc_slpc *slpc;
171         struct intel_rps *rps;
172         struct intel_engine_cs *engine;
173         enum intel_engine_id id;
174         struct igt_spinner spin;
175         int err = 0;
176         u32 slpc_min_freq, slpc_max_freq;
177
178         slpc = &gt->uc.guc.slpc;
179         rps = &gt->rps;
180
181         if (!intel_uc_uses_guc_slpc(&gt->uc))
182                 return 0;
183
184         if (igt_spinner_init(&spin, gt))
185                 return -ENOMEM;
186
187         if (intel_guc_slpc_get_max_freq(slpc, &slpc_max_freq)) {
188                 pr_err("Could not get SLPC max freq\n");
189                 return -EIO;
190         }
191
192         if (intel_guc_slpc_get_min_freq(slpc, &slpc_min_freq)) {
193                 pr_err("Could not get SLPC min freq\n");
194                 return -EIO;
195         }
196
197         if (slpc_min_freq == slpc_max_freq) {
198                 pr_err("Min/Max are fused to the same value\n");
199                 return -EINVAL;
200         }
201
202         intel_gt_pm_wait_for_idle(gt);
203         intel_gt_pm_get(gt);
204         for_each_engine(engine, gt, id) {
205                 struct i915_request *rq;
206                 u32 max_freq, req_freq;
207                 u32 act_freq, max_act_freq;
208                 u32 step;
209
210                 if (!intel_engine_can_store_dword(engine))
211                         continue;
212
213                 /* Go from max to min in 5 steps */
214                 step = (slpc_max_freq - slpc_min_freq) / NUM_STEPS;
215                 max_act_freq = slpc_min_freq;
216                 for (max_freq = slpc_max_freq; max_freq > slpc_min_freq;
217                                         max_freq -= step) {
218                         err = slpc_set_max_freq(slpc, max_freq);
219                         if (err)
220                                 break;
221
222                         st_engine_heartbeat_disable(engine);
223
224                         rq = igt_spinner_create_request(&spin,
225                                                         engine->kernel_context,
226                                                         MI_NOOP);
227                         if (IS_ERR(rq)) {
228                                 st_engine_heartbeat_enable(engine);
229                                 err = PTR_ERR(rq);
230                                 break;
231                         }
232
233                         i915_request_add(rq);
234
235                         if (!igt_wait_for_spinner(&spin, rq)) {
236                                 pr_err("%s: SLPC spinner did not start\n",
237                                        engine->name);
238                                 igt_spinner_end(&spin);
239                                 st_engine_heartbeat_enable(engine);
240                                 intel_gt_set_wedged(engine->gt);
241                                 err = -EIO;
242                                 break;
243                         }
244
245                         delay_for_h2g();
246
247                         /* Verify that SWREQ indeed was set to specific value */
248                         req_freq = intel_rps_read_punit_req_frequency(rps);
249
250                         /* GuC requests freq in multiples of 50/3 MHz */
251                         if (req_freq > (max_freq + FREQUENCY_REQ_UNIT)) {
252                                 pr_err("SWReq is %d, should be at most %d\n", req_freq,
253                                        max_freq + FREQUENCY_REQ_UNIT);
254                                 igt_spinner_end(&spin);
255                                 st_engine_heartbeat_enable(engine);
256                                 err = -EINVAL;
257                                 break;
258                         }
259
260                         act_freq =  intel_rps_read_actual_frequency(rps);
261                         if (act_freq > max_act_freq)
262                                 max_act_freq = act_freq;
263
264                         st_engine_heartbeat_enable(engine);
265                         igt_spinner_end(&spin);
266
267                         if (err)
268                                 break;
269                 }
270
271                 pr_info("Max actual frequency for %s was %d\n",
272                         engine->name, max_act_freq);
273
274                 /* Actual frequency should rise above min */
275                 if (max_act_freq == slpc_min_freq) {
276                         pr_err("Actual freq did not rise above min\n");
277                         err = -EINVAL;
278                 }
279
280                 if (igt_flush_test(gt->i915)) {
281                         err = -EIO;
282                         break;
283                 }
284
285                 if (err)
286                         break;
287         }
288
289         /* Restore min/max freq */
290         slpc_set_max_freq(slpc, slpc_max_freq);
291         slpc_set_min_freq(slpc, slpc_min_freq);
292
293         intel_gt_pm_put(gt);
294         igt_spinner_fini(&spin);
295         intel_gt_pm_wait_for_idle(gt);
296
297         return err;
298 }
299
300 int intel_slpc_live_selftests(struct drm_i915_private *i915)
301 {
302         static const struct i915_subtest tests[] = {
303                 SUBTEST(live_slpc_clamp_max),
304                 SUBTEST(live_slpc_clamp_min),
305         };
306
307         if (intel_gt_is_wedged(&i915->gt))
308                 return 0;
309
310         return i915_live_subtests(tests, i915);
311 }
This page took 0.049868 seconds and 4 git commands to generate.