Home | History | Annotate | Line # | Download | only in gt
      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(&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 
     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