360f56aa4b826c0c09681edc7c852c1715276d7d
[linux-block.git] / drivers / gpu / drm / i915 / gt / selftest_rps.c
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2020 Intel Corporation
4  */
5
6 #include <linux/sort.h>
7
8 #include "intel_engine_pm.h"
9 #include "intel_gt_pm.h"
10 #include "intel_rc6.h"
11 #include "selftest_rps.h"
12 #include "selftests/igt_flush_test.h"
13 #include "selftests/igt_spinner.h"
14 #include "selftests/librapl.h"
15
16 static void dummy_rps_work(struct work_struct *wrk)
17 {
18 }
19
20 static void sleep_for_ei(struct intel_rps *rps, int timeout_us)
21 {
22         /* Flush any previous EI */
23         usleep_range(timeout_us, 2 * timeout_us);
24
25         /* Reset the interrupt status */
26         rps_disable_interrupts(rps);
27         GEM_BUG_ON(rps->pm_iir);
28         rps_enable_interrupts(rps);
29
30         /* And then wait for the timeout, for real this time */
31         usleep_range(2 * timeout_us, 3 * timeout_us);
32 }
33
34 static int __rps_up_interrupt(struct intel_rps *rps,
35                               struct intel_engine_cs *engine,
36                               struct igt_spinner *spin)
37 {
38         struct intel_uncore *uncore = engine->uncore;
39         struct i915_request *rq;
40         u32 timeout;
41
42         if (!intel_engine_can_store_dword(engine))
43                 return 0;
44
45         mutex_lock(&rps->lock);
46         GEM_BUG_ON(!rps->active);
47         intel_rps_set(rps, rps->min_freq);
48         mutex_unlock(&rps->lock);
49
50         rq = igt_spinner_create_request(spin, engine->kernel_context, MI_NOOP);
51         if (IS_ERR(rq))
52                 return PTR_ERR(rq);
53
54         i915_request_get(rq);
55         i915_request_add(rq);
56
57         if (!igt_wait_for_spinner(spin, rq)) {
58                 pr_err("%s: RPS spinner did not start\n",
59                        engine->name);
60                 i915_request_put(rq);
61                 intel_gt_set_wedged(engine->gt);
62                 return -EIO;
63         }
64
65         if (!rps->active) {
66                 pr_err("%s: RPS not enabled on starting spinner\n",
67                        engine->name);
68                 igt_spinner_end(spin);
69                 i915_request_put(rq);
70                 return -EINVAL;
71         }
72
73         if (!(rps->pm_events & GEN6_PM_RP_UP_THRESHOLD)) {
74                 pr_err("%s: RPS did not register UP interrupt\n",
75                        engine->name);
76                 i915_request_put(rq);
77                 return -EINVAL;
78         }
79
80         if (rps->last_freq != rps->min_freq) {
81                 pr_err("%s: RPS did not program min frequency\n",
82                        engine->name);
83                 i915_request_put(rq);
84                 return -EINVAL;
85         }
86
87         timeout = intel_uncore_read(uncore, GEN6_RP_UP_EI);
88         timeout = GT_PM_INTERVAL_TO_US(engine->i915, timeout);
89
90         sleep_for_ei(rps, timeout);
91         GEM_BUG_ON(i915_request_completed(rq));
92
93         igt_spinner_end(spin);
94         i915_request_put(rq);
95
96         if (rps->cur_freq != rps->min_freq) {
97                 pr_err("%s: Frequency unexpectedly changed [up], now %d!\n",
98                        engine->name, intel_rps_read_actual_frequency(rps));
99                 return -EINVAL;
100         }
101
102         if (!(rps->pm_iir & GEN6_PM_RP_UP_THRESHOLD)) {
103                 pr_err("%s: UP interrupt not recorded for spinner, pm_iir:%x, prev_up:%x, up_threshold:%x, up_ei:%x\n",
104                        engine->name, rps->pm_iir,
105                        intel_uncore_read(uncore, GEN6_RP_PREV_UP),
106                        intel_uncore_read(uncore, GEN6_RP_UP_THRESHOLD),
107                        intel_uncore_read(uncore, GEN6_RP_UP_EI));
108                 return -EINVAL;
109         }
110
111         return 0;
112 }
113
114 static int __rps_down_interrupt(struct intel_rps *rps,
115                                 struct intel_engine_cs *engine)
116 {
117         struct intel_uncore *uncore = engine->uncore;
118         u32 timeout;
119
120         mutex_lock(&rps->lock);
121         GEM_BUG_ON(!rps->active);
122         intel_rps_set(rps, rps->max_freq);
123         mutex_unlock(&rps->lock);
124
125         if (!(rps->pm_events & GEN6_PM_RP_DOWN_THRESHOLD)) {
126                 pr_err("%s: RPS did not register DOWN interrupt\n",
127                        engine->name);
128                 return -EINVAL;
129         }
130
131         if (rps->last_freq != rps->max_freq) {
132                 pr_err("%s: RPS did not program max frequency\n",
133                        engine->name);
134                 return -EINVAL;
135         }
136
137         timeout = intel_uncore_read(uncore, GEN6_RP_DOWN_EI);
138         timeout = GT_PM_INTERVAL_TO_US(engine->i915, timeout);
139
140         sleep_for_ei(rps, timeout);
141
142         if (rps->cur_freq != rps->max_freq) {
143                 pr_err("%s: Frequency unexpectedly changed [down], now %d!\n",
144                        engine->name,
145                        intel_rps_read_actual_frequency(rps));
146                 return -EINVAL;
147         }
148
149         if (!(rps->pm_iir & (GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_DOWN_TIMEOUT))) {
150                 pr_err("%s: DOWN interrupt not recorded for idle, pm_iir:%x, prev_down:%x, down_threshold:%x, down_ei:%x [prev_up:%x, up_threshold:%x, up_ei:%x]\n",
151                        engine->name, rps->pm_iir,
152                        intel_uncore_read(uncore, GEN6_RP_PREV_DOWN),
153                        intel_uncore_read(uncore, GEN6_RP_DOWN_THRESHOLD),
154                        intel_uncore_read(uncore, GEN6_RP_DOWN_EI),
155                        intel_uncore_read(uncore, GEN6_RP_PREV_UP),
156                        intel_uncore_read(uncore, GEN6_RP_UP_THRESHOLD),
157                        intel_uncore_read(uncore, GEN6_RP_UP_EI));
158                 return -EINVAL;
159         }
160
161         return 0;
162 }
163
164 int live_rps_interrupt(void *arg)
165 {
166         struct intel_gt *gt = arg;
167         struct intel_rps *rps = &gt->rps;
168         void (*saved_work)(struct work_struct *wrk);
169         struct intel_engine_cs *engine;
170         enum intel_engine_id id;
171         struct igt_spinner spin;
172         u32 pm_events;
173         int err = 0;
174
175         /*
176          * First, let's check whether or not we are receiving interrupts.
177          */
178
179         if (!rps->enabled || rps->max_freq <= rps->min_freq)
180                 return 0;
181
182         intel_gt_pm_get(gt);
183         pm_events = rps->pm_events;
184         intel_gt_pm_put(gt);
185         if (!pm_events) {
186                 pr_err("No RPS PM events registered, but RPS is enabled?\n");
187                 return -ENODEV;
188         }
189
190         if (igt_spinner_init(&spin, gt))
191                 return -ENOMEM;
192
193         intel_gt_pm_wait_for_idle(gt);
194         saved_work = rps->work.func;
195         rps->work.func = dummy_rps_work;
196
197         for_each_engine(engine, gt, id) {
198                 /* Keep the engine busy with a spinner; expect an UP! */
199                 if (pm_events & GEN6_PM_RP_UP_THRESHOLD) {
200                         intel_gt_pm_wait_for_idle(engine->gt);
201                         GEM_BUG_ON(rps->active);
202
203                         intel_engine_pm_get(engine);
204                         err = __rps_up_interrupt(rps, engine, &spin);
205                         intel_engine_pm_put(engine);
206                         if (err)
207                                 goto out;
208
209                         intel_gt_pm_wait_for_idle(engine->gt);
210                 }
211
212                 /* Keep the engine awake but idle and check for DOWN */
213                 if (pm_events & GEN6_PM_RP_DOWN_THRESHOLD) {
214                         intel_engine_pm_get(engine);
215                         intel_rc6_disable(&gt->rc6);
216
217                         err = __rps_down_interrupt(rps, engine);
218
219                         intel_rc6_enable(&gt->rc6);
220                         intel_engine_pm_put(engine);
221                         if (err)
222                                 goto out;
223                 }
224         }
225
226 out:
227         if (igt_flush_test(gt->i915))
228                 err = -EIO;
229
230         igt_spinner_fini(&spin);
231
232         intel_gt_pm_wait_for_idle(gt);
233         rps->work.func = saved_work;
234
235         return err;
236 }
237
238 static u64 __measure_power(int duration_ms)
239 {
240         u64 dE, dt;
241
242         dt = ktime_get();
243         dE = librapl_energy_uJ();
244         usleep_range(1000 * duration_ms, 2000 * duration_ms);
245         dE = librapl_energy_uJ() - dE;
246         dt = ktime_get() - dt;
247
248         return div64_u64(1000 * 1000 * dE, dt);
249 }
250
251 static int cmp_u64(const void *A, const void *B)
252 {
253         const u64 *a = A, *b = B;
254
255         if (a < b)
256                 return -1;
257         else if (a > b)
258                 return 1;
259         else
260                 return 0;
261 }
262
263 static u64 measure_power_at(struct intel_rps *rps, int freq)
264 {
265         u64 x[5];
266         int i;
267
268         mutex_lock(&rps->lock);
269         GEM_BUG_ON(!rps->active);
270         intel_rps_set(rps, freq);
271         mutex_unlock(&rps->lock);
272
273         msleep(20); /* more than enough time to stabilise! */
274
275         i = read_cagf(rps);
276         if (i != freq)
277                 pr_notice("Running at %x [%uMHz], not target %x [%uMHz]\n",
278                           i, intel_gpu_freq(rps, i),
279                           freq, intel_gpu_freq(rps, freq));
280
281         for (i = 0; i < 5; i++)
282                 x[i] = __measure_power(5);
283
284         /* A simple triangle filter for better result stability */
285         sort(x, 5, sizeof(*x), cmp_u64, NULL);
286         return div_u64(x[1] + 2 * x[2] + x[3], 4);
287 }
288
289 int live_rps_power(void *arg)
290 {
291         struct intel_gt *gt = arg;
292         struct intel_rps *rps = &gt->rps;
293         void (*saved_work)(struct work_struct *wrk);
294         struct intel_engine_cs *engine;
295         enum intel_engine_id id;
296         struct igt_spinner spin;
297         int err = 0;
298
299         /*
300          * Our fundamental assumption is that running at lower frequency
301          * actually saves power. Let's see if our RAPL measurement support
302          * that theory.
303          */
304
305         if (!rps->enabled || rps->max_freq <= rps->min_freq)
306                 return 0;
307
308         if (!librapl_energy_uJ())
309                 return 0;
310
311         if (igt_spinner_init(&spin, gt))
312                 return -ENOMEM;
313
314         intel_gt_pm_wait_for_idle(gt);
315         saved_work = rps->work.func;
316         rps->work.func = dummy_rps_work;
317
318         for_each_engine(engine, gt, id) {
319                 struct i915_request *rq;
320                 u64 min, max;
321
322                 if (!intel_engine_can_store_dword(engine))
323                         continue;
324
325                 rq = igt_spinner_create_request(&spin,
326                                                 engine->kernel_context,
327                                                 MI_NOOP);
328                 if (IS_ERR(rq)) {
329                         err = PTR_ERR(rq);
330                         break;
331                 }
332
333                 i915_request_add(rq);
334
335                 if (!igt_wait_for_spinner(&spin, rq)) {
336                         pr_err("%s: RPS spinner did not start\n",
337                                engine->name);
338                         intel_gt_set_wedged(engine->gt);
339                         err = -EIO;
340                         break;
341                 }
342
343                 max = measure_power_at(rps, rps->max_freq);
344                 min = measure_power_at(rps, rps->min_freq);
345
346                 igt_spinner_end(&spin);
347
348                 pr_info("%s: min:%llumW @ %uMHz, max:%llumW @ %uMHz\n",
349                         engine->name,
350                         min, intel_gpu_freq(rps, rps->min_freq),
351                         max, intel_gpu_freq(rps, rps->max_freq));
352                 if (11 * min > 10 * max) {
353                         pr_err("%s: did not conserve power when setting lower frequency!\n",
354                                engine->name);
355                         err = -EINVAL;
356                         break;
357                 }
358
359                 if (igt_flush_test(gt->i915)) {
360                         err = -EIO;
361                         break;
362                 }
363         }
364
365         igt_spinner_fini(&spin);
366
367         intel_gt_pm_wait_for_idle(gt);
368         rps->work.func = saved_work;
369
370         return err;
371 }