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 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 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 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 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 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