xref: /netbsd-src/sys/external/bsd/drm2/dist/drm/i915/gt/selftest_reset.c (revision 41ec02673d281bbb3d38e6c78504ce6e30c228c1)
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(&gt->i915->gpu_error);
28 
29 	intel_gt_reset(gt, ALL_ENGINES, NULL);
30 
31 	if (i915_reset_count(&gt->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