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