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->runtime_pm); 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->runtime_pm, 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 intel_gt_pm_get(&i915->gt); 67 igt_global_reset_lock(i915); 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 reset_prepare(i915); 77 p->critical_section_begin(); 78 79 err = intel_gpu_reset(i915, ALL_ENGINES); 80 81 p->critical_section_end(); 82 reset_finish(i915); 83 84 if (err) { 85 pr_err("intel_gpu_reset failed under %s\n", p->name); 86 break; 87 } 88 } 89 90 /* As we poke around the guts, do a full reset before continuing. */ 91 igt_force_reset(i915); 92 93 unlock: 94 igt_global_reset_unlock(i915); 95 intel_gt_pm_put(&i915->gt); 96 97 return err; 98 } 99 100 static int igt_atomic_engine_reset(void *arg) 101 { 102 struct drm_i915_private *i915 = arg; 103 const typeof(*igt_atomic_phases) *p; 104 struct intel_engine_cs *engine; 105 enum intel_engine_id id; 106 int err = 0; 107 108 /* Check that the resets are usable from atomic context */ 109 110 if (!intel_has_reset_engine(i915)) 111 return 0; 112 113 if (USES_GUC_SUBMISSION(i915)) 114 return 0; 115 116 intel_gt_pm_get(&i915->gt); 117 igt_global_reset_lock(i915); 118 119 /* Flush any requests before we get started and check basics */ 120 if (!igt_force_reset(i915)) 121 goto out_unlock; 122 123 for_each_engine(engine, i915, id) { 124 tasklet_disable_nosync(&engine->execlists.tasklet); 125 intel_engine_pm_get(engine); 126 127 for (p = igt_atomic_phases; p->name; p++) { 128 GEM_TRACE("i915_reset_engine(%s) under %s\n", 129 engine->name, p->name); 130 131 p->critical_section_begin(); 132 err = i915_reset_engine(engine, NULL); 133 p->critical_section_end(); 134 135 if (err) { 136 pr_err("i915_reset_engine(%s) failed under %s\n", 137 engine->name, p->name); 138 break; 139 } 140 } 141 142 intel_engine_pm_put(engine); 143 tasklet_enable(&engine->execlists.tasklet); 144 if (err) 145 break; 146 } 147 148 /* As we poke around the guts, do a full reset before continuing. */ 149 igt_force_reset(i915); 150 151 out_unlock: 152 igt_global_reset_unlock(i915); 153 intel_gt_pm_put(&i915->gt); 154 155 return err; 156 } 157 158 int intel_reset_live_selftests(struct drm_i915_private *i915) 159 { 160 static const struct i915_subtest tests[] = { 161 SUBTEST(igt_global_reset), /* attempt to recover GPU first */ 162 SUBTEST(igt_wedged_reset), 163 SUBTEST(igt_atomic_reset), 164 SUBTEST(igt_atomic_engine_reset), 165 }; 166 intel_wakeref_t wakeref; 167 int err = 0; 168 169 if (!intel_has_gpu_reset(i915)) 170 return 0; 171 172 if (i915_terminally_wedged(i915)) 173 return -EIO; /* we're long past hope of a successful reset */ 174 175 with_intel_runtime_pm(&i915->runtime_pm, wakeref) 176 err = i915_subtests(tests, i915); 177 178 return err; 179 } 180