162306a36Sopenharmony_ci// SPDX-License-Identifier: MIT
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright © 2018 Intel Corporation
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/crc32.h>
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include "gem/i915_gem_stolen.h"
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include "i915_memcpy.h"
1162306a36Sopenharmony_ci#include "i915_selftest.h"
1262306a36Sopenharmony_ci#include "intel_gpu_commands.h"
1362306a36Sopenharmony_ci#include "selftests/igt_reset.h"
1462306a36Sopenharmony_ci#include "selftests/igt_atomic.h"
1562306a36Sopenharmony_ci#include "selftests/igt_spinner.h"
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_cistatic int
1862306a36Sopenharmony_ci__igt_reset_stolen(struct intel_gt *gt,
1962306a36Sopenharmony_ci		   intel_engine_mask_t mask,
2062306a36Sopenharmony_ci		   const char *msg)
2162306a36Sopenharmony_ci{
2262306a36Sopenharmony_ci	struct i915_ggtt *ggtt = gt->ggtt;
2362306a36Sopenharmony_ci	const struct resource *dsm = &gt->i915->dsm.stolen;
2462306a36Sopenharmony_ci	resource_size_t num_pages, page;
2562306a36Sopenharmony_ci	struct intel_engine_cs *engine;
2662306a36Sopenharmony_ci	intel_wakeref_t wakeref;
2762306a36Sopenharmony_ci	enum intel_engine_id id;
2862306a36Sopenharmony_ci	struct igt_spinner spin;
2962306a36Sopenharmony_ci	long max, count;
3062306a36Sopenharmony_ci	void *tmp;
3162306a36Sopenharmony_ci	u32 *crc;
3262306a36Sopenharmony_ci	int err;
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	if (!drm_mm_node_allocated(&ggtt->error_capture))
3562306a36Sopenharmony_ci		return 0;
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci	num_pages = resource_size(dsm) >> PAGE_SHIFT;
3862306a36Sopenharmony_ci	if (!num_pages)
3962306a36Sopenharmony_ci		return 0;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	crc = kmalloc_array(num_pages, sizeof(u32), GFP_KERNEL);
4262306a36Sopenharmony_ci	if (!crc)
4362306a36Sopenharmony_ci		return -ENOMEM;
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	tmp = kmalloc(PAGE_SIZE, GFP_KERNEL);
4662306a36Sopenharmony_ci	if (!tmp) {
4762306a36Sopenharmony_ci		err = -ENOMEM;
4862306a36Sopenharmony_ci		goto err_crc;
4962306a36Sopenharmony_ci	}
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	igt_global_reset_lock(gt);
5262306a36Sopenharmony_ci	wakeref = intel_runtime_pm_get(gt->uncore->rpm);
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	err = igt_spinner_init(&spin, gt);
5562306a36Sopenharmony_ci	if (err)
5662306a36Sopenharmony_ci		goto err_lock;
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	for_each_engine(engine, gt, id) {
5962306a36Sopenharmony_ci		struct intel_context *ce;
6062306a36Sopenharmony_ci		struct i915_request *rq;
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci		if (!(mask & engine->mask))
6362306a36Sopenharmony_ci			continue;
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci		if (!intel_engine_can_store_dword(engine))
6662306a36Sopenharmony_ci			continue;
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci		ce = intel_context_create(engine);
6962306a36Sopenharmony_ci		if (IS_ERR(ce)) {
7062306a36Sopenharmony_ci			err = PTR_ERR(ce);
7162306a36Sopenharmony_ci			goto err_spin;
7262306a36Sopenharmony_ci		}
7362306a36Sopenharmony_ci		rq = igt_spinner_create_request(&spin, ce, MI_ARB_CHECK);
7462306a36Sopenharmony_ci		intel_context_put(ce);
7562306a36Sopenharmony_ci		if (IS_ERR(rq)) {
7662306a36Sopenharmony_ci			err = PTR_ERR(rq);
7762306a36Sopenharmony_ci			goto err_spin;
7862306a36Sopenharmony_ci		}
7962306a36Sopenharmony_ci		i915_request_add(rq);
8062306a36Sopenharmony_ci	}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	for (page = 0; page < num_pages; page++) {
8362306a36Sopenharmony_ci		dma_addr_t dma = (dma_addr_t)dsm->start + (page << PAGE_SHIFT);
8462306a36Sopenharmony_ci		void __iomem *s;
8562306a36Sopenharmony_ci		void *in;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci		ggtt->vm.insert_page(&ggtt->vm, dma,
8862306a36Sopenharmony_ci				     ggtt->error_capture.start,
8962306a36Sopenharmony_ci				     i915_gem_get_pat_index(gt->i915,
9062306a36Sopenharmony_ci							    I915_CACHE_NONE),
9162306a36Sopenharmony_ci				     0);
9262306a36Sopenharmony_ci		mb();
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci		s = io_mapping_map_wc(&ggtt->iomap,
9562306a36Sopenharmony_ci				      ggtt->error_capture.start,
9662306a36Sopenharmony_ci				      PAGE_SIZE);
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci		if (!__drm_mm_interval_first(&gt->i915->mm.stolen,
9962306a36Sopenharmony_ci					     page << PAGE_SHIFT,
10062306a36Sopenharmony_ci					     ((page + 1) << PAGE_SHIFT) - 1))
10162306a36Sopenharmony_ci			memset_io(s, STACK_MAGIC, PAGE_SIZE);
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci		in = (void __force *)s;
10462306a36Sopenharmony_ci		if (i915_memcpy_from_wc(tmp, in, PAGE_SIZE))
10562306a36Sopenharmony_ci			in = tmp;
10662306a36Sopenharmony_ci		crc[page] = crc32_le(0, in, PAGE_SIZE);
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci		io_mapping_unmap(s);
10962306a36Sopenharmony_ci	}
11062306a36Sopenharmony_ci	mb();
11162306a36Sopenharmony_ci	ggtt->vm.clear_range(&ggtt->vm, ggtt->error_capture.start, PAGE_SIZE);
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	if (mask == ALL_ENGINES) {
11462306a36Sopenharmony_ci		intel_gt_reset(gt, mask, NULL);
11562306a36Sopenharmony_ci	} else {
11662306a36Sopenharmony_ci		for_each_engine(engine, gt, id) {
11762306a36Sopenharmony_ci			if (mask & engine->mask)
11862306a36Sopenharmony_ci				intel_engine_reset(engine, NULL);
11962306a36Sopenharmony_ci		}
12062306a36Sopenharmony_ci	}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	max = -1;
12362306a36Sopenharmony_ci	count = 0;
12462306a36Sopenharmony_ci	for (page = 0; page < num_pages; page++) {
12562306a36Sopenharmony_ci		dma_addr_t dma = (dma_addr_t)dsm->start + (page << PAGE_SHIFT);
12662306a36Sopenharmony_ci		void __iomem *s;
12762306a36Sopenharmony_ci		void *in;
12862306a36Sopenharmony_ci		u32 x;
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci		ggtt->vm.insert_page(&ggtt->vm, dma,
13162306a36Sopenharmony_ci				     ggtt->error_capture.start,
13262306a36Sopenharmony_ci				     i915_gem_get_pat_index(gt->i915,
13362306a36Sopenharmony_ci							    I915_CACHE_NONE),
13462306a36Sopenharmony_ci				     0);
13562306a36Sopenharmony_ci		mb();
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci		s = io_mapping_map_wc(&ggtt->iomap,
13862306a36Sopenharmony_ci				      ggtt->error_capture.start,
13962306a36Sopenharmony_ci				      PAGE_SIZE);
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci		in = (void __force *)s;
14262306a36Sopenharmony_ci		if (i915_memcpy_from_wc(tmp, in, PAGE_SIZE))
14362306a36Sopenharmony_ci			in = tmp;
14462306a36Sopenharmony_ci		x = crc32_le(0, in, PAGE_SIZE);
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci		if (x != crc[page] &&
14762306a36Sopenharmony_ci		    !__drm_mm_interval_first(&gt->i915->mm.stolen,
14862306a36Sopenharmony_ci					     page << PAGE_SHIFT,
14962306a36Sopenharmony_ci					     ((page + 1) << PAGE_SHIFT) - 1)) {
15062306a36Sopenharmony_ci			pr_debug("unused stolen page %pa modified by GPU reset\n",
15162306a36Sopenharmony_ci				 &page);
15262306a36Sopenharmony_ci			if (count++ == 0)
15362306a36Sopenharmony_ci				igt_hexdump(in, PAGE_SIZE);
15462306a36Sopenharmony_ci			max = page;
15562306a36Sopenharmony_ci		}
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci		io_mapping_unmap(s);
15862306a36Sopenharmony_ci	}
15962306a36Sopenharmony_ci	mb();
16062306a36Sopenharmony_ci	ggtt->vm.clear_range(&ggtt->vm, ggtt->error_capture.start, PAGE_SIZE);
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	if (count > 0) {
16362306a36Sopenharmony_ci		pr_info("%s reset clobbered %ld pages of stolen, last clobber at page %ld\n",
16462306a36Sopenharmony_ci			msg, count, max);
16562306a36Sopenharmony_ci	}
16662306a36Sopenharmony_ci	if (max >= I915_GEM_STOLEN_BIAS >> PAGE_SHIFT) {
16762306a36Sopenharmony_ci		pr_err("%s reset clobbered unreserved area [above %x] of stolen; may cause severe faults\n",
16862306a36Sopenharmony_ci		       msg, I915_GEM_STOLEN_BIAS);
16962306a36Sopenharmony_ci		err = -EINVAL;
17062306a36Sopenharmony_ci	}
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_cierr_spin:
17362306a36Sopenharmony_ci	igt_spinner_fini(&spin);
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_cierr_lock:
17662306a36Sopenharmony_ci	intel_runtime_pm_put(gt->uncore->rpm, wakeref);
17762306a36Sopenharmony_ci	igt_global_reset_unlock(gt);
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	kfree(tmp);
18062306a36Sopenharmony_cierr_crc:
18162306a36Sopenharmony_ci	kfree(crc);
18262306a36Sopenharmony_ci	return err;
18362306a36Sopenharmony_ci}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_cistatic int igt_reset_device_stolen(void *arg)
18662306a36Sopenharmony_ci{
18762306a36Sopenharmony_ci	return __igt_reset_stolen(arg, ALL_ENGINES, "device");
18862306a36Sopenharmony_ci}
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_cistatic int igt_reset_engines_stolen(void *arg)
19162306a36Sopenharmony_ci{
19262306a36Sopenharmony_ci	struct intel_gt *gt = arg;
19362306a36Sopenharmony_ci	struct intel_engine_cs *engine;
19462306a36Sopenharmony_ci	enum intel_engine_id id;
19562306a36Sopenharmony_ci	int err;
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	if (!intel_has_reset_engine(gt))
19862306a36Sopenharmony_ci		return 0;
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	for_each_engine(engine, gt, id) {
20162306a36Sopenharmony_ci		err = __igt_reset_stolen(gt, engine->mask, engine->name);
20262306a36Sopenharmony_ci		if (err)
20362306a36Sopenharmony_ci			return err;
20462306a36Sopenharmony_ci	}
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	return 0;
20762306a36Sopenharmony_ci}
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_cistatic int igt_global_reset(void *arg)
21062306a36Sopenharmony_ci{
21162306a36Sopenharmony_ci	struct intel_gt *gt = arg;
21262306a36Sopenharmony_ci	unsigned int reset_count;
21362306a36Sopenharmony_ci	intel_wakeref_t wakeref;
21462306a36Sopenharmony_ci	int err = 0;
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	/* Check that we can issue a global GPU reset */
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	igt_global_reset_lock(gt);
21962306a36Sopenharmony_ci	wakeref = intel_runtime_pm_get(gt->uncore->rpm);
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	reset_count = i915_reset_count(&gt->i915->gpu_error);
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci	intel_gt_reset(gt, ALL_ENGINES, NULL);
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	if (i915_reset_count(&gt->i915->gpu_error) == reset_count) {
22662306a36Sopenharmony_ci		pr_err("No GPU reset recorded!\n");
22762306a36Sopenharmony_ci		err = -EINVAL;
22862306a36Sopenharmony_ci	}
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	intel_runtime_pm_put(gt->uncore->rpm, wakeref);
23162306a36Sopenharmony_ci	igt_global_reset_unlock(gt);
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	if (intel_gt_is_wedged(gt))
23462306a36Sopenharmony_ci		err = -EIO;
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	return err;
23762306a36Sopenharmony_ci}
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_cistatic int igt_wedged_reset(void *arg)
24062306a36Sopenharmony_ci{
24162306a36Sopenharmony_ci	struct intel_gt *gt = arg;
24262306a36Sopenharmony_ci	intel_wakeref_t wakeref;
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	/* Check that we can recover a wedged device with a GPU reset */
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	igt_global_reset_lock(gt);
24762306a36Sopenharmony_ci	wakeref = intel_runtime_pm_get(gt->uncore->rpm);
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	intel_gt_set_wedged(gt);
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	GEM_BUG_ON(!intel_gt_is_wedged(gt));
25262306a36Sopenharmony_ci	intel_gt_reset(gt, ALL_ENGINES, NULL);
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	intel_runtime_pm_put(gt->uncore->rpm, wakeref);
25562306a36Sopenharmony_ci	igt_global_reset_unlock(gt);
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	return intel_gt_is_wedged(gt) ? -EIO : 0;
25862306a36Sopenharmony_ci}
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_cistatic int igt_atomic_reset(void *arg)
26162306a36Sopenharmony_ci{
26262306a36Sopenharmony_ci	struct intel_gt *gt = arg;
26362306a36Sopenharmony_ci	const typeof(*igt_atomic_phases) *p;
26462306a36Sopenharmony_ci	int err = 0;
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci	/* Check that the resets are usable from atomic context */
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	intel_gt_pm_get(gt);
26962306a36Sopenharmony_ci	igt_global_reset_lock(gt);
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	/* Flush any requests before we get started and check basics */
27262306a36Sopenharmony_ci	if (!igt_force_reset(gt))
27362306a36Sopenharmony_ci		goto unlock;
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci	for (p = igt_atomic_phases; p->name; p++) {
27662306a36Sopenharmony_ci		intel_engine_mask_t awake;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci		GEM_TRACE("__intel_gt_reset under %s\n", p->name);
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci		awake = reset_prepare(gt);
28162306a36Sopenharmony_ci		p->critical_section_begin();
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci		err = __intel_gt_reset(gt, ALL_ENGINES);
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci		p->critical_section_end();
28662306a36Sopenharmony_ci		reset_finish(gt, awake);
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci		if (err) {
28962306a36Sopenharmony_ci			pr_err("__intel_gt_reset failed under %s\n", p->name);
29062306a36Sopenharmony_ci			break;
29162306a36Sopenharmony_ci		}
29262306a36Sopenharmony_ci	}
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	/* As we poke around the guts, do a full reset before continuing. */
29562306a36Sopenharmony_ci	igt_force_reset(gt);
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ciunlock:
29862306a36Sopenharmony_ci	igt_global_reset_unlock(gt);
29962306a36Sopenharmony_ci	intel_gt_pm_put(gt);
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	return err;
30262306a36Sopenharmony_ci}
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_cistatic int igt_atomic_engine_reset(void *arg)
30562306a36Sopenharmony_ci{
30662306a36Sopenharmony_ci	struct intel_gt *gt = arg;
30762306a36Sopenharmony_ci	const typeof(*igt_atomic_phases) *p;
30862306a36Sopenharmony_ci	struct intel_engine_cs *engine;
30962306a36Sopenharmony_ci	enum intel_engine_id id;
31062306a36Sopenharmony_ci	int err = 0;
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	/* Check that the resets are usable from atomic context */
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	if (!intel_has_reset_engine(gt))
31562306a36Sopenharmony_ci		return 0;
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	if (intel_uc_uses_guc_submission(&gt->uc))
31862306a36Sopenharmony_ci		return 0;
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	intel_gt_pm_get(gt);
32162306a36Sopenharmony_ci	igt_global_reset_lock(gt);
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	/* Flush any requests before we get started and check basics */
32462306a36Sopenharmony_ci	if (!igt_force_reset(gt))
32562306a36Sopenharmony_ci		goto out_unlock;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	for_each_engine(engine, gt, id) {
32862306a36Sopenharmony_ci		struct tasklet_struct *t = &engine->sched_engine->tasklet;
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci		if (t->func)
33162306a36Sopenharmony_ci			tasklet_disable(t);
33262306a36Sopenharmony_ci		intel_engine_pm_get(engine);
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci		for (p = igt_atomic_phases; p->name; p++) {
33562306a36Sopenharmony_ci			GEM_TRACE("intel_engine_reset(%s) under %s\n",
33662306a36Sopenharmony_ci				  engine->name, p->name);
33762306a36Sopenharmony_ci			if (strcmp(p->name, "softirq"))
33862306a36Sopenharmony_ci				local_bh_disable();
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci			p->critical_section_begin();
34162306a36Sopenharmony_ci			err = __intel_engine_reset_bh(engine, NULL);
34262306a36Sopenharmony_ci			p->critical_section_end();
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci			if (strcmp(p->name, "softirq"))
34562306a36Sopenharmony_ci				local_bh_enable();
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci			if (err) {
34862306a36Sopenharmony_ci				pr_err("intel_engine_reset(%s) failed under %s\n",
34962306a36Sopenharmony_ci				       engine->name, p->name);
35062306a36Sopenharmony_ci				break;
35162306a36Sopenharmony_ci			}
35262306a36Sopenharmony_ci		}
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci		intel_engine_pm_put(engine);
35562306a36Sopenharmony_ci		if (t->func) {
35662306a36Sopenharmony_ci			tasklet_enable(t);
35762306a36Sopenharmony_ci			tasklet_hi_schedule(t);
35862306a36Sopenharmony_ci		}
35962306a36Sopenharmony_ci		if (err)
36062306a36Sopenharmony_ci			break;
36162306a36Sopenharmony_ci	}
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	/* As we poke around the guts, do a full reset before continuing. */
36462306a36Sopenharmony_ci	igt_force_reset(gt);
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ciout_unlock:
36762306a36Sopenharmony_ci	igt_global_reset_unlock(gt);
36862306a36Sopenharmony_ci	intel_gt_pm_put(gt);
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci	return err;
37162306a36Sopenharmony_ci}
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ciint intel_reset_live_selftests(struct drm_i915_private *i915)
37462306a36Sopenharmony_ci{
37562306a36Sopenharmony_ci	static const struct i915_subtest tests[] = {
37662306a36Sopenharmony_ci		SUBTEST(igt_global_reset), /* attempt to recover GPU first */
37762306a36Sopenharmony_ci		SUBTEST(igt_reset_device_stolen),
37862306a36Sopenharmony_ci		SUBTEST(igt_reset_engines_stolen),
37962306a36Sopenharmony_ci		SUBTEST(igt_wedged_reset),
38062306a36Sopenharmony_ci		SUBTEST(igt_atomic_reset),
38162306a36Sopenharmony_ci		SUBTEST(igt_atomic_engine_reset),
38262306a36Sopenharmony_ci	};
38362306a36Sopenharmony_ci	struct intel_gt *gt = to_gt(i915);
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	if (!intel_has_gpu_reset(gt))
38662306a36Sopenharmony_ci		return 0;
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	if (intel_gt_is_wedged(gt))
38962306a36Sopenharmony_ci		return -EIO; /* we're long past hope of a successful reset */
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	return intel_gt_live_subtests(tests, gt);
39262306a36Sopenharmony_ci}
393