Merge tag 'drm-intel-next-2019-05-24' of git://anongit.freedesktop.org/drm/drm-intel...
[linux-2.6-microblaze.git] / drivers / gpu / drm / i915 / gt / selftest_reset.c
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2018 Intel Corporation
4  */
5
6 #include "i915_selftest.h"
7 #include "selftests/igt_reset.h"
8 #include "selftests/igt_atomic.h"
9
10 static int igt_global_reset(void *arg)
11 {
12         struct drm_i915_private *i915 = arg;
13         unsigned int reset_count;
14         int err = 0;
15
16         /* Check that we can issue a global GPU reset */
17
18         igt_global_reset_lock(i915);
19
20         reset_count = i915_reset_count(&i915->gpu_error);
21
22         i915_reset(i915, ALL_ENGINES, NULL);
23
24         if (i915_reset_count(&i915->gpu_error) == reset_count) {
25                 pr_err("No GPU reset recorded!\n");
26                 err = -EINVAL;
27         }
28
29         igt_global_reset_unlock(i915);
30
31         if (i915_reset_failed(i915))
32                 err = -EIO;
33
34         return err;
35 }
36
37 static int igt_wedged_reset(void *arg)
38 {
39         struct drm_i915_private *i915 = arg;
40         intel_wakeref_t wakeref;
41
42         /* Check that we can recover a wedged device with a GPU reset */
43
44         igt_global_reset_lock(i915);
45         wakeref = intel_runtime_pm_get(i915);
46
47         i915_gem_set_wedged(i915);
48
49         GEM_BUG_ON(!i915_reset_failed(i915));
50         i915_reset(i915, ALL_ENGINES, NULL);
51
52         intel_runtime_pm_put(i915, wakeref);
53         igt_global_reset_unlock(i915);
54
55         return i915_reset_failed(i915) ? -EIO : 0;
56 }
57
58 static int igt_atomic_reset(void *arg)
59 {
60         struct drm_i915_private *i915 = arg;
61         const typeof(*igt_atomic_phases) *p;
62         int err = 0;
63
64         /* Check that the resets are usable from atomic context */
65
66         igt_global_reset_lock(i915);
67         mutex_lock(&i915->drm.struct_mutex);
68
69         /* Flush any requests before we get started and check basics */
70         if (!igt_force_reset(i915))
71                 goto unlock;
72
73         for (p = igt_atomic_phases; p->name; p++) {
74                 GEM_TRACE("intel_gpu_reset under %s\n", p->name);
75
76                 p->critical_section_begin();
77                 reset_prepare(i915);
78                 err = intel_gpu_reset(i915, ALL_ENGINES);
79                 reset_finish(i915);
80                 p->critical_section_end();
81
82                 if (err) {
83                         pr_err("intel_gpu_reset failed under %s\n", p->name);
84                         break;
85                 }
86         }
87
88         /* As we poke around the guts, do a full reset before continuing. */
89         igt_force_reset(i915);
90
91 unlock:
92         mutex_unlock(&i915->drm.struct_mutex);
93         igt_global_reset_unlock(i915);
94
95         return err;
96 }
97
98 int intel_reset_live_selftests(struct drm_i915_private *i915)
99 {
100         static const struct i915_subtest tests[] = {
101                 SUBTEST(igt_global_reset), /* attempt to recover GPU first */
102                 SUBTEST(igt_wedged_reset),
103                 SUBTEST(igt_atomic_reset),
104         };
105         intel_wakeref_t wakeref;
106         int err = 0;
107
108         if (!intel_has_gpu_reset(i915))
109                 return 0;
110
111         if (i915_terminally_wedged(i915))
112                 return -EIO; /* we're long past hope of a successful reset */
113
114         with_intel_runtime_pm(i915, wakeref)
115                 err = i915_subtests(tests, i915);
116
117         return err;
118 }