Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[linux-block.git] / drivers / gpu / drm / i915 / selftests / intel_workarounds.c
1 /*
2  * SPDX-License-Identifier: MIT
3  *
4  * Copyright © 2018 Intel Corporation
5  */
6
7 #include "../i915_selftest.h"
8
9 #include "igt_flush_test.h"
10 #include "igt_reset.h"
11 #include "igt_spinner.h"
12 #include "igt_wedge_me.h"
13 #include "mock_context.h"
14
15 static struct drm_i915_gem_object *
16 read_nonprivs(struct i915_gem_context *ctx, struct intel_engine_cs *engine)
17 {
18         struct drm_i915_gem_object *result;
19         struct i915_request *rq;
20         struct i915_vma *vma;
21         const u32 base = engine->mmio_base;
22         u32 srm, *cs;
23         int err;
24         int i;
25
26         result = i915_gem_object_create_internal(engine->i915, PAGE_SIZE);
27         if (IS_ERR(result))
28                 return result;
29
30         i915_gem_object_set_cache_level(result, I915_CACHE_LLC);
31
32         cs = i915_gem_object_pin_map(result, I915_MAP_WB);
33         if (IS_ERR(cs)) {
34                 err = PTR_ERR(cs);
35                 goto err_obj;
36         }
37         memset(cs, 0xc5, PAGE_SIZE);
38         i915_gem_object_unpin_map(result);
39
40         vma = i915_vma_instance(result, &engine->i915->ggtt.vm, NULL);
41         if (IS_ERR(vma)) {
42                 err = PTR_ERR(vma);
43                 goto err_obj;
44         }
45
46         err = i915_vma_pin(vma, 0, 0, PIN_GLOBAL);
47         if (err)
48                 goto err_obj;
49
50         intel_runtime_pm_get(engine->i915);
51         rq = i915_request_alloc(engine, ctx);
52         intel_runtime_pm_put(engine->i915);
53         if (IS_ERR(rq)) {
54                 err = PTR_ERR(rq);
55                 goto err_pin;
56         }
57
58         err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
59         if (err)
60                 goto err_req;
61
62         srm = MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT;
63         if (INTEL_GEN(ctx->i915) >= 8)
64                 srm++;
65
66         cs = intel_ring_begin(rq, 4 * RING_MAX_NONPRIV_SLOTS);
67         if (IS_ERR(cs)) {
68                 err = PTR_ERR(cs);
69                 goto err_req;
70         }
71
72         for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) {
73                 *cs++ = srm;
74                 *cs++ = i915_mmio_reg_offset(RING_FORCE_TO_NONPRIV(base, i));
75                 *cs++ = i915_ggtt_offset(vma) + sizeof(u32) * i;
76                 *cs++ = 0;
77         }
78         intel_ring_advance(rq, cs);
79
80         i915_gem_object_get(result);
81         i915_gem_object_set_active_reference(result);
82
83         i915_request_add(rq);
84         i915_vma_unpin(vma);
85
86         return result;
87
88 err_req:
89         i915_request_add(rq);
90 err_pin:
91         i915_vma_unpin(vma);
92 err_obj:
93         i915_gem_object_put(result);
94         return ERR_PTR(err);
95 }
96
97 static u32
98 get_whitelist_reg(const struct intel_engine_cs *engine, unsigned int i)
99 {
100         i915_reg_t reg = i < engine->whitelist.count ?
101                          engine->whitelist.list[i].reg :
102                          RING_NOPID(engine->mmio_base);
103
104         return i915_mmio_reg_offset(reg);
105 }
106
107 static void
108 print_results(const struct intel_engine_cs *engine, const u32 *results)
109 {
110         unsigned int i;
111
112         for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) {
113                 u32 expected = get_whitelist_reg(engine, i);
114                 u32 actual = results[i];
115
116                 pr_info("RING_NONPRIV[%d]: expected 0x%08x, found 0x%08x\n",
117                         i, expected, actual);
118         }
119 }
120
121 static int check_whitelist(struct i915_gem_context *ctx,
122                            struct intel_engine_cs *engine)
123 {
124         struct drm_i915_gem_object *results;
125         struct igt_wedge_me wedge;
126         u32 *vaddr;
127         int err;
128         int i;
129
130         results = read_nonprivs(ctx, engine);
131         if (IS_ERR(results))
132                 return PTR_ERR(results);
133
134         err = 0;
135         igt_wedge_on_timeout(&wedge, ctx->i915, HZ / 5) /* a safety net! */
136                 err = i915_gem_object_set_to_cpu_domain(results, false);
137         if (i915_terminally_wedged(&ctx->i915->gpu_error))
138                 err = -EIO;
139         if (err)
140                 goto out_put;
141
142         vaddr = i915_gem_object_pin_map(results, I915_MAP_WB);
143         if (IS_ERR(vaddr)) {
144                 err = PTR_ERR(vaddr);
145                 goto out_put;
146         }
147
148         for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) {
149                 u32 expected = get_whitelist_reg(engine, i);
150                 u32 actual = vaddr[i];
151
152                 if (expected != actual) {
153                         print_results(engine, vaddr);
154                         pr_err("Invalid RING_NONPRIV[%d], expected 0x%08x, found 0x%08x\n",
155                                i, expected, actual);
156
157                         err = -EINVAL;
158                         break;
159                 }
160         }
161
162         i915_gem_object_unpin_map(results);
163 out_put:
164         i915_gem_object_put(results);
165         return err;
166 }
167
168 static int do_device_reset(struct intel_engine_cs *engine)
169 {
170         set_bit(I915_RESET_HANDOFF, &engine->i915->gpu_error.flags);
171         i915_reset(engine->i915, ENGINE_MASK(engine->id), "live_workarounds");
172         return 0;
173 }
174
175 static int do_engine_reset(struct intel_engine_cs *engine)
176 {
177         return i915_reset_engine(engine, "live_workarounds");
178 }
179
180 static int
181 switch_to_scratch_context(struct intel_engine_cs *engine,
182                           struct igt_spinner *spin)
183 {
184         struct i915_gem_context *ctx;
185         struct i915_request *rq;
186         int err = 0;
187
188         ctx = kernel_context(engine->i915);
189         if (IS_ERR(ctx))
190                 return PTR_ERR(ctx);
191
192         intel_runtime_pm_get(engine->i915);
193
194         if (spin)
195                 rq = igt_spinner_create_request(spin, ctx, engine, MI_NOOP);
196         else
197                 rq = i915_request_alloc(engine, ctx);
198
199         intel_runtime_pm_put(engine->i915);
200
201         kernel_context_close(ctx);
202
203         if (IS_ERR(rq)) {
204                 spin = NULL;
205                 err = PTR_ERR(rq);
206                 goto err;
207         }
208
209         i915_request_add(rq);
210
211         if (spin && !igt_wait_for_spinner(spin, rq)) {
212                 pr_err("Spinner failed to start\n");
213                 err = -ETIMEDOUT;
214         }
215
216 err:
217         if (err && spin)
218                 igt_spinner_end(spin);
219
220         return err;
221 }
222
223 static int check_whitelist_across_reset(struct intel_engine_cs *engine,
224                                         int (*reset)(struct intel_engine_cs *),
225                                         const char *name)
226 {
227         struct drm_i915_private *i915 = engine->i915;
228         bool want_spin = reset == do_engine_reset;
229         struct i915_gem_context *ctx;
230         struct igt_spinner spin;
231         int err;
232
233         pr_info("Checking %d whitelisted registers (RING_NONPRIV) [%s]\n",
234                 engine->whitelist.count, name);
235
236         if (want_spin) {
237                 err = igt_spinner_init(&spin, i915);
238                 if (err)
239                         return err;
240         }
241
242         ctx = kernel_context(i915);
243         if (IS_ERR(ctx))
244                 return PTR_ERR(ctx);
245
246         err = check_whitelist(ctx, engine);
247         if (err) {
248                 pr_err("Invalid whitelist *before* %s reset!\n", name);
249                 goto out;
250         }
251
252         err = switch_to_scratch_context(engine, want_spin ? &spin : NULL);
253         if (err)
254                 goto out;
255
256         intel_runtime_pm_get(i915);
257         err = reset(engine);
258         intel_runtime_pm_put(i915);
259
260         if (want_spin) {
261                 igt_spinner_end(&spin);
262                 igt_spinner_fini(&spin);
263         }
264
265         if (err) {
266                 pr_err("%s reset failed\n", name);
267                 goto out;
268         }
269
270         err = check_whitelist(ctx, engine);
271         if (err) {
272                 pr_err("Whitelist not preserved in context across %s reset!\n",
273                        name);
274                 goto out;
275         }
276
277         kernel_context_close(ctx);
278
279         ctx = kernel_context(i915);
280         if (IS_ERR(ctx))
281                 return PTR_ERR(ctx);
282
283         err = check_whitelist(ctx, engine);
284         if (err) {
285                 pr_err("Invalid whitelist *after* %s reset in fresh context!\n",
286                        name);
287                 goto out;
288         }
289
290 out:
291         kernel_context_close(ctx);
292         return err;
293 }
294
295 static int live_reset_whitelist(void *arg)
296 {
297         struct drm_i915_private *i915 = arg;
298         struct intel_engine_cs *engine = i915->engine[RCS];
299         int err = 0;
300
301         /* If we reset the gpu, we should not lose the RING_NONPRIV */
302
303         if (!engine || engine->whitelist.count == 0)
304                 return 0;
305
306         igt_global_reset_lock(i915);
307
308         if (intel_has_reset_engine(i915)) {
309                 err = check_whitelist_across_reset(engine,
310                                                    do_engine_reset,
311                                                    "engine");
312                 if (err)
313                         goto out;
314         }
315
316         if (intel_has_gpu_reset(i915)) {
317                 err = check_whitelist_across_reset(engine,
318                                                    do_device_reset,
319                                                    "device");
320                 if (err)
321                         goto out;
322         }
323
324 out:
325         igt_global_reset_unlock(i915);
326         return err;
327 }
328
329 static bool verify_gt_engine_wa(struct drm_i915_private *i915, const char *str)
330 {
331         struct intel_engine_cs *engine;
332         enum intel_engine_id id;
333         bool ok = true;
334
335         ok &= intel_gt_verify_workarounds(i915, str);
336
337         for_each_engine(engine, i915, id)
338                 ok &= intel_engine_verify_workarounds(engine, str);
339
340         return ok;
341 }
342
343 static int
344 live_gpu_reset_gt_engine_workarounds(void *arg)
345 {
346         struct drm_i915_private *i915 = arg;
347         struct i915_gpu_error *error = &i915->gpu_error;
348         bool ok;
349
350         if (!intel_has_gpu_reset(i915))
351                 return 0;
352
353         pr_info("Verifying after GPU reset...\n");
354
355         igt_global_reset_lock(i915);
356
357         ok = verify_gt_engine_wa(i915, "before reset");
358         if (!ok)
359                 goto out;
360
361         intel_runtime_pm_get(i915);
362         set_bit(I915_RESET_HANDOFF, &error->flags);
363         i915_reset(i915, ALL_ENGINES, "live_workarounds");
364         intel_runtime_pm_put(i915);
365
366         ok = verify_gt_engine_wa(i915, "after reset");
367
368 out:
369         igt_global_reset_unlock(i915);
370
371         return ok ? 0 : -ESRCH;
372 }
373
374 static int
375 live_engine_reset_gt_engine_workarounds(void *arg)
376 {
377         struct drm_i915_private *i915 = arg;
378         struct intel_engine_cs *engine;
379         struct i915_gem_context *ctx;
380         struct igt_spinner spin;
381         enum intel_engine_id id;
382         struct i915_request *rq;
383         int ret = 0;
384
385         if (!intel_has_reset_engine(i915))
386                 return 0;
387
388         ctx = kernel_context(i915);
389         if (IS_ERR(ctx))
390                 return PTR_ERR(ctx);
391
392         igt_global_reset_lock(i915);
393
394         for_each_engine(engine, i915, id) {
395                 bool ok;
396
397                 pr_info("Verifying after %s reset...\n", engine->name);
398
399                 ok = verify_gt_engine_wa(i915, "before reset");
400                 if (!ok) {
401                         ret = -ESRCH;
402                         goto err;
403                 }
404
405                 intel_runtime_pm_get(i915);
406                 i915_reset_engine(engine, "live_workarounds");
407                 intel_runtime_pm_put(i915);
408
409                 ok = verify_gt_engine_wa(i915, "after idle reset");
410                 if (!ok) {
411                         ret = -ESRCH;
412                         goto err;
413                 }
414
415                 ret = igt_spinner_init(&spin, i915);
416                 if (ret)
417                         goto err;
418
419                 intel_runtime_pm_get(i915);
420
421                 rq = igt_spinner_create_request(&spin, ctx, engine, MI_NOOP);
422                 if (IS_ERR(rq)) {
423                         ret = PTR_ERR(rq);
424                         igt_spinner_fini(&spin);
425                         intel_runtime_pm_put(i915);
426                         goto err;
427                 }
428
429                 i915_request_add(rq);
430
431                 if (!igt_wait_for_spinner(&spin, rq)) {
432                         pr_err("Spinner failed to start\n");
433                         igt_spinner_fini(&spin);
434                         intel_runtime_pm_put(i915);
435                         ret = -ETIMEDOUT;
436                         goto err;
437                 }
438
439                 i915_reset_engine(engine, "live_workarounds");
440
441                 intel_runtime_pm_put(i915);
442
443                 igt_spinner_end(&spin);
444                 igt_spinner_fini(&spin);
445
446                 ok = verify_gt_engine_wa(i915, "after busy reset");
447                 if (!ok) {
448                         ret = -ESRCH;
449                         goto err;
450                 }
451         }
452
453 err:
454         igt_global_reset_unlock(i915);
455         kernel_context_close(ctx);
456
457         igt_flush_test(i915, I915_WAIT_LOCKED);
458
459         return ret;
460 }
461
462 int intel_workarounds_live_selftests(struct drm_i915_private *i915)
463 {
464         static const struct i915_subtest tests[] = {
465                 SUBTEST(live_reset_whitelist),
466                 SUBTEST(live_gpu_reset_gt_engine_workarounds),
467                 SUBTEST(live_engine_reset_gt_engine_workarounds),
468         };
469         int err;
470
471         if (i915_terminally_wedged(&i915->gpu_error))
472                 return 0;
473
474         mutex_lock(&i915->drm.struct_mutex);
475         err = i915_subtests(tests, i915);
476         mutex_unlock(&i915->drm.struct_mutex);
477
478         return err;
479 }