1 /* $NetBSD: selftest_reset.c,v 1.2 2021/12/18 23:45:30 riastradh Exp $ */
2
3 // SPDX-License-Identifier: MIT
4 /*
5 * Copyright © 2018 Intel Corporation
6 */
7
8 #include <sys/cdefs.h>
9 __KERNEL_RCSID(0, "$NetBSD: selftest_reset.c,v 1.2 2021/12/18 23:45:30 riastradh Exp $");
10
11 #include "i915_selftest.h"
12 #include "selftests/igt_reset.h"
13 #include "selftests/igt_atomic.h"
14
igt_global_reset(void * arg)15 static int igt_global_reset(void *arg)
16 {
17 struct intel_gt *gt = arg;
18 unsigned int reset_count;
19 intel_wakeref_t wakeref;
20 int err = 0;
21
22 /* Check that we can issue a global GPU reset */
23
24 igt_global_reset_lock(gt);
25 wakeref = intel_runtime_pm_get(gt->uncore->rpm);
26
27 reset_count = i915_reset_count(>->i915->gpu_error);
28
29 intel_gt_reset(gt, ALL_ENGINES, NULL);
30
31 if (i915_reset_count(>->i915->gpu_error) == reset_count) {
32 pr_err("No GPU reset recorded!\n");
33 err = -EINVAL;
34 }
35
36 intel_runtime_pm_put(gt->uncore->rpm, wakeref);
37 igt_global_reset_unlock(gt);
38
39 if (intel_gt_is_wedged(gt))
40 err = -EIO;
41
42 return err;
43 }
44
igt_wedged_reset(void * arg)45 static int igt_wedged_reset(void *arg)
46 {
47 struct intel_gt *gt = arg;
48 intel_wakeref_t wakeref;
49
50 /* Check that we can recover a wedged device with a GPU reset */
51
52 igt_global_reset_lock(gt);
53 wakeref = intel_runtime_pm_get(gt->uncore->rpm);
54
55 intel_gt_set_wedged(gt);
56
57 GEM_BUG_ON(!intel_gt_is_wedged(gt));
58 intel_gt_reset(gt, ALL_ENGINES, NULL);
59
60 intel_runtime_pm_put(gt->uncore->rpm, wakeref);
61 igt_global_reset_unlock(gt);
62
63 return intel_gt_is_wedged(gt) ? -EIO : 0;
64 }
65
igt_atomic_reset(void * arg)66 static int igt_atomic_reset(void *arg)
67 {
68 struct intel_gt *gt = arg;
69 const typeof(*igt_atomic_phases) *p;
70 int err = 0;
71
72 /* Check that the resets are usable from atomic context */
73
74 intel_gt_pm_get(gt);
75 igt_global_reset_lock(gt);
76
77 /* Flush any requests before we get started and check basics */
78 if (!igt_force_reset(gt))
79 goto unlock;
80
81 for (p = igt_atomic_phases; p->name; p++) {
82 intel_engine_mask_t awake;
83
84 GEM_TRACE("__intel_gt_reset under %s\n", p->name);
85
86 awake = reset_prepare(gt);
87 p->critical_section_begin();
88
89 err = __intel_gt_reset(gt, ALL_ENGINES);
90
91 p->critical_section_end();
92 reset_finish(gt, awake);
93
94 if (err) {
95 pr_err("__intel_gt_reset failed under %s\n", p->name);
96 break;
97 }
98 }
99
100 /* As we poke around the guts, do a full reset before continuing. */
101 igt_force_reset(gt);
102
103 unlock:
104 igt_global_reset_unlock(gt);
105 intel_gt_pm_put(gt);
106
107 return err;
108 }
109
igt_atomic_engine_reset(void * arg)110 static int igt_atomic_engine_reset(void *arg)
111 {
112 struct intel_gt *gt = arg;
113 const typeof(*igt_atomic_phases) *p;
114 struct intel_engine_cs *engine;
115 enum intel_engine_id id;
116 int err = 0;
117
118 /* Check that the resets are usable from atomic context */
119
120 if (!intel_has_reset_engine(gt))
121 return 0;
122
123 if (USES_GUC_SUBMISSION(gt->i915))
124 return 0;
125
126 intel_gt_pm_get(gt);
127 igt_global_reset_lock(gt);
128
129 /* Flush any requests before we get started and check basics */
130 if (!igt_force_reset(gt))
131 goto out_unlock;
132
133 for_each_engine(engine, gt, id) {
134 tasklet_disable(&engine->execlists.tasklet);
135 intel_engine_pm_get(engine);
136
137 for (p = igt_atomic_phases; p->name; p++) {
138 GEM_TRACE("intel_engine_reset(%s) under %s\n",
139 engine->name, p->name);
140
141 p->critical_section_begin();
142 err = intel_engine_reset(engine, NULL);
143 p->critical_section_end();
144
145 if (err) {
146 pr_err("intel_engine_reset(%s) failed under %s\n",
147 engine->name, p->name);
148 break;
149 }
150 }
151
152 intel_engine_pm_put(engine);
153 tasklet_enable(&engine->execlists.tasklet);
154 if (err)
155 break;
156 }
157
158 /* As we poke around the guts, do a full reset before continuing. */
159 igt_force_reset(gt);
160
161 out_unlock:
162 igt_global_reset_unlock(gt);
163 intel_gt_pm_put(gt);
164
165 return err;
166 }
167
intel_reset_live_selftests(struct drm_i915_private * i915)168 int intel_reset_live_selftests(struct drm_i915_private *i915)
169 {
170 static const struct i915_subtest tests[] = {
171 SUBTEST(igt_global_reset), /* attempt to recover GPU first */
172 SUBTEST(igt_wedged_reset),
173 SUBTEST(igt_atomic_reset),
174 SUBTEST(igt_atomic_engine_reset),
175 };
176 struct intel_gt *gt = &i915->gt;
177
178 if (!intel_has_gpu_reset(gt))
179 return 0;
180
181 if (intel_gt_is_wedged(gt))
182 return -EIO; /* we're long past hope of a successful reset */
183
184 return intel_gt_live_subtests(tests, gt);
185 }
186