1932309fbSMichal Wajdeczko // SPDX-License-Identifier: MIT
2932309fbSMichal Wajdeczko /*
3932309fbSMichal Wajdeczko  * Copyright © 2018 Intel Corporation
4932309fbSMichal Wajdeczko  */
5932309fbSMichal Wajdeczko 
6932309fbSMichal Wajdeczko #include "i915_selftest.h"
7932309fbSMichal Wajdeczko #include "selftests/igt_reset.h"
8f6470c9bSMichal Wajdeczko #include "selftests/igt_atomic.h"
9932309fbSMichal Wajdeczko 
10932309fbSMichal Wajdeczko static int igt_global_reset(void *arg)
11932309fbSMichal Wajdeczko {
12932309fbSMichal Wajdeczko 	struct drm_i915_private *i915 = arg;
13932309fbSMichal Wajdeczko 	unsigned int reset_count;
14932309fbSMichal Wajdeczko 	int err = 0;
15932309fbSMichal Wajdeczko 
16932309fbSMichal Wajdeczko 	/* Check that we can issue a global GPU reset */
17932309fbSMichal Wajdeczko 
18932309fbSMichal Wajdeczko 	igt_global_reset_lock(i915);
19932309fbSMichal Wajdeczko 
20932309fbSMichal Wajdeczko 	reset_count = i915_reset_count(&i915->gpu_error);
21932309fbSMichal Wajdeczko 
22932309fbSMichal Wajdeczko 	i915_reset(i915, ALL_ENGINES, NULL);
23932309fbSMichal Wajdeczko 
24932309fbSMichal Wajdeczko 	if (i915_reset_count(&i915->gpu_error) == reset_count) {
25932309fbSMichal Wajdeczko 		pr_err("No GPU reset recorded!\n");
26932309fbSMichal Wajdeczko 		err = -EINVAL;
27932309fbSMichal Wajdeczko 	}
28932309fbSMichal Wajdeczko 
29932309fbSMichal Wajdeczko 	igt_global_reset_unlock(i915);
30932309fbSMichal Wajdeczko 
31932309fbSMichal Wajdeczko 	if (i915_reset_failed(i915))
32932309fbSMichal Wajdeczko 		err = -EIO;
33932309fbSMichal Wajdeczko 
34932309fbSMichal Wajdeczko 	return err;
35932309fbSMichal Wajdeczko }
36932309fbSMichal Wajdeczko 
37932309fbSMichal Wajdeczko static int igt_wedged_reset(void *arg)
38932309fbSMichal Wajdeczko {
39932309fbSMichal Wajdeczko 	struct drm_i915_private *i915 = arg;
40932309fbSMichal Wajdeczko 	intel_wakeref_t wakeref;
41932309fbSMichal Wajdeczko 
42932309fbSMichal Wajdeczko 	/* Check that we can recover a wedged device with a GPU reset */
43932309fbSMichal Wajdeczko 
44932309fbSMichal Wajdeczko 	igt_global_reset_lock(i915);
45932309fbSMichal Wajdeczko 	wakeref = intel_runtime_pm_get(i915);
46932309fbSMichal Wajdeczko 
47932309fbSMichal Wajdeczko 	i915_gem_set_wedged(i915);
48932309fbSMichal Wajdeczko 
49932309fbSMichal Wajdeczko 	GEM_BUG_ON(!i915_reset_failed(i915));
50932309fbSMichal Wajdeczko 	i915_reset(i915, ALL_ENGINES, NULL);
51932309fbSMichal Wajdeczko 
52932309fbSMichal Wajdeczko 	intel_runtime_pm_put(i915, wakeref);
53932309fbSMichal Wajdeczko 	igt_global_reset_unlock(i915);
54932309fbSMichal Wajdeczko 
55932309fbSMichal Wajdeczko 	return i915_reset_failed(i915) ? -EIO : 0;
56932309fbSMichal Wajdeczko }
57932309fbSMichal Wajdeczko 
58f6470c9bSMichal Wajdeczko static int igt_atomic_reset(void *arg)
59f6470c9bSMichal Wajdeczko {
60f6470c9bSMichal Wajdeczko 	struct drm_i915_private *i915 = arg;
61f6470c9bSMichal Wajdeczko 	const typeof(*igt_atomic_phases) *p;
62f6470c9bSMichal Wajdeczko 	int err = 0;
63f6470c9bSMichal Wajdeczko 
64f6470c9bSMichal Wajdeczko 	/* Check that the resets are usable from atomic context */
65f6470c9bSMichal Wajdeczko 
66f6470c9bSMichal Wajdeczko 	igt_global_reset_lock(i915);
67f6470c9bSMichal Wajdeczko 	mutex_lock(&i915->drm.struct_mutex);
68f6470c9bSMichal Wajdeczko 
69f6470c9bSMichal Wajdeczko 	/* Flush any requests before we get started and check basics */
70f6470c9bSMichal Wajdeczko 	if (!igt_force_reset(i915))
71f6470c9bSMichal Wajdeczko 		goto unlock;
72f6470c9bSMichal Wajdeczko 
73f6470c9bSMichal Wajdeczko 	for (p = igt_atomic_phases; p->name; p++) {
74f6470c9bSMichal Wajdeczko 		GEM_TRACE("intel_gpu_reset under %s\n", p->name);
75f6470c9bSMichal Wajdeczko 
76f6470c9bSMichal Wajdeczko 		p->critical_section_begin();
77f6470c9bSMichal Wajdeczko 		err = intel_gpu_reset(i915, ALL_ENGINES);
78f6470c9bSMichal Wajdeczko 		p->critical_section_end();
79f6470c9bSMichal Wajdeczko 
80f6470c9bSMichal Wajdeczko 		if (err) {
81f6470c9bSMichal Wajdeczko 			pr_err("intel_gpu_reset failed under %s\n", p->name);
82f6470c9bSMichal Wajdeczko 			break;
83f6470c9bSMichal Wajdeczko 		}
84f6470c9bSMichal Wajdeczko 	}
85f6470c9bSMichal Wajdeczko 
86f6470c9bSMichal Wajdeczko 	/* As we poke around the guts, do a full reset before continuing. */
87f6470c9bSMichal Wajdeczko 	igt_force_reset(i915);
88f6470c9bSMichal Wajdeczko 
89f6470c9bSMichal Wajdeczko unlock:
90f6470c9bSMichal Wajdeczko 	mutex_unlock(&i915->drm.struct_mutex);
91f6470c9bSMichal Wajdeczko 	igt_global_reset_unlock(i915);
92f6470c9bSMichal Wajdeczko 
93f6470c9bSMichal Wajdeczko 	return err;
94f6470c9bSMichal Wajdeczko }
95f6470c9bSMichal Wajdeczko 
96932309fbSMichal Wajdeczko int intel_reset_live_selftests(struct drm_i915_private *i915)
97932309fbSMichal Wajdeczko {
98932309fbSMichal Wajdeczko 	static const struct i915_subtest tests[] = {
99932309fbSMichal Wajdeczko 		SUBTEST(igt_global_reset), /* attempt to recover GPU first */
100932309fbSMichal Wajdeczko 		SUBTEST(igt_wedged_reset),
101f6470c9bSMichal Wajdeczko 		SUBTEST(igt_atomic_reset),
102932309fbSMichal Wajdeczko 	};
103932309fbSMichal Wajdeczko 	intel_wakeref_t wakeref;
104932309fbSMichal Wajdeczko 	int err = 0;
105932309fbSMichal Wajdeczko 
106932309fbSMichal Wajdeczko 	if (!intel_has_gpu_reset(i915))
107932309fbSMichal Wajdeczko 		return 0;
108932309fbSMichal Wajdeczko 
109932309fbSMichal Wajdeczko 	if (i915_terminally_wedged(i915))
110932309fbSMichal Wajdeczko 		return -EIO; /* we're long past hope of a successful reset */
111932309fbSMichal Wajdeczko 
112932309fbSMichal Wajdeczko 	with_intel_runtime_pm(i915, wakeref)
113932309fbSMichal Wajdeczko 		err = i915_subtests(tests, i915);
114932309fbSMichal Wajdeczko 
115932309fbSMichal Wajdeczko 	return err;
116932309fbSMichal Wajdeczko }
117