We currently require that our per-engine reset can be called from any context, even hardirq, and in the future wish to perform the device reset without holding struct_mutex (which requires some lockless shenanigans that demand the lowlevel intel_reset_gpu() be able to be used in atomic context). Test that we meet the current requirements by calling i915_reset_engine() from under various atomic contexts. Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> Cc: Mika Kuoppala <mika.kuoppala@xxxxxxxxxxxxxxx> --- .../gpu/drm/i915/selftests/intel_hangcheck.c | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c index 51d0e2bed9e1..df4c076c02ae 100644 --- a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c +++ b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c @@ -1473,6 +1473,106 @@ static int igt_handle_error(void *arg) return err; } +static void __preempt_begin(void) +{ + preempt_disable(); +} + +static void __preempt_end(void) +{ + preempt_enable(); +} + +static void __softirq_begin(void) +{ + local_bh_disable(); +} + +static void __softirq_end(void) +{ + local_bh_enable(); +} + +static void __hardirq_begin(void) +{ + local_irq_disable(); +} + +static void __hardirq_end(void) +{ + local_irq_enable(); +} + +static int igt_atomic_reset(void *arg) +{ + static const struct { + const char *name; + void (*critical_section_begin)(void); + void (*critical_section_end)(void); + } phases[] = { + { "preempt", __preempt_begin, __preempt_end }, + { "softirq", __softirq_begin, __softirq_end }, + { "hardirq", __hardirq_begin, __hardirq_end }, + { } + }; + struct drm_i915_private *i915 = arg; + int err = 0; + + /* Check that the resets are usable from atomic context */ + + if (USES_GUC_SUBMISSION(i915)) + return 0; /* guc is dead; long live the guc */ + + global_reset_lock(i915); + mutex_lock(&i915->drm.struct_mutex); + + /* Flush any requests before we get started and check basics */ + i915_gem_set_wedged(i915); + i915_reset(i915, 0, NULL); + if (i915_terminally_wedged(&i915->gpu_error)) + goto out; + + if (intel_has_reset_engine(i915)) { + struct intel_engine_cs *engine; + enum intel_engine_id id; + + for_each_engine(engine, i915, id) { + struct tasklet_struct * const t = + &engine->execlists.tasklet; + const typeof(*phases) *p; + + for (p = phases; p->name; p++) { + GEM_TRACE("i915_reset_engine(%s) under %s\n", + engine->name, p->name); + + tasklet_disable_nosync(t); + p->critical_section_begin(); + + err = i915_reset_engine(engine, NULL); + + p->critical_section_end(); + tasklet_enable(t); + + if (err) { + pr_err("i915_reset_engine(%s) failed under %s\n", + engine->name, p->name); + goto out; + } + } + } + } + +out: + /* As we poke around the guts, do a full reset before continuing. */ + i915_gem_set_wedged(i915); + i915_reset(i915, 0, NULL); + + mutex_unlock(&i915->drm.struct_mutex); + global_reset_unlock(i915); + + return err; +} + int intel_hangcheck_live_selftests(struct drm_i915_private *i915) { static const struct i915_subtest tests[] = { @@ -1487,6 +1587,7 @@ int intel_hangcheck_live_selftests(struct drm_i915_private *i915) SUBTEST(igt_reset_evict_ppgtt), SUBTEST(igt_reset_evict_fence), SUBTEST(igt_handle_error), + SUBTEST(igt_atomic_reset), }; bool saved_hangcheck; int err; -- 2.19.1 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx