|
Thomas Zimmermann |
ebf85e |
From 79f0f4724d9c502d65d08917709a60e4a8cb4972 Mon Sep 17 00:00:00 2001
|
|
Thomas Zimmermann |
ebf85e |
From: Chris Wilson <chris@chris-wilson.co.uk>
|
|
Thomas Zimmermann |
ebf85e |
Date: Fri, 21 Jul 2017 13:32:34 +0100
|
|
Thomas Zimmermann |
ebf85e |
Subject: [PATCH] drm/i915/selftests: Exercise independence of per-engine resets
|
|
Thomas Zimmermann |
ebf85e |
Git-commit: 79f0f4724d9c502d65d08917709a60e4a8cb4972
|
|
Thomas Zimmermann |
ebf85e |
Patch-mainline: v4.14-rc1
|
|
Thomas Zimmermann |
ebf85e |
References: FATE#322643 bsc#1055900
|
|
Thomas Zimmermann |
ebf85e |
|
|
Thomas Zimmermann |
ebf85e |
If all goes well, resetting one engine should not affect the operation of
|
|
Thomas Zimmermann |
ebf85e |
any others. So to test this, we setup a continuous stream of requests
|
|
Thomas Zimmermann |
ebf85e |
onto to each of the "innocent" engines whilst constantly resetting our
|
|
Thomas Zimmermann |
ebf85e |
target engine.
|
|
Thomas Zimmermann |
ebf85e |
|
|
Thomas Zimmermann |
ebf85e |
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
|
|
Thomas Zimmermann |
ebf85e |
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
|
|
Thomas Zimmermann |
ebf85e |
Cc: Michel Thierry <michel.thierry@intel.com>
|
|
Thomas Zimmermann |
ebf85e |
Reviewed-by: Michel Thierry <michel.thierry@intel.com>
|
|
Thomas Zimmermann |
ebf85e |
Link: https://patchwork.freedesktop.org/patch/msgid/20170721123238.16428-16-chris@chris-wilson.co.uk
|
|
Thomas Zimmermann |
ebf85e |
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Thomas Zimmermann |
ebf85e |
Acked-by: Takashi Iwai <tiwai@suse.de>
|
|
Thomas Zimmermann |
ebf85e |
|
|
Thomas Zimmermann |
ebf85e |
---
|
|
Thomas Zimmermann |
ebf85e |
drivers/gpu/drm/i915/selftests/intel_hangcheck.c | 164 +++++++++++++++++++++++
|
|
Thomas Zimmermann |
ebf85e |
drivers/gpu/drm/i915/selftests/mock_context.c | 8 +
|
|
Thomas Zimmermann |
ebf85e |
drivers/gpu/drm/i915/selftests/mock_context.h | 3
|
|
Thomas Zimmermann |
ebf85e |
3 files changed, 175 insertions(+)
|
|
Thomas Zimmermann |
ebf85e |
|
|
Thomas Zimmermann |
ebf85e |
--- a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c
|
|
Thomas Zimmermann |
ebf85e |
+++ b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c
|
|
Thomas Zimmermann |
ebf85e |
@@ -22,8 +22,13 @@
|
|
Thomas Zimmermann |
ebf85e |
*
|
|
Thomas Zimmermann |
ebf85e |
*/
|
|
Thomas Zimmermann |
ebf85e |
|
|
Thomas Zimmermann |
ebf85e |
+#include <linux/kthread.h>
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
#include "../i915_selftest.h"
|
|
Thomas Zimmermann |
ebf85e |
|
|
Thomas Zimmermann |
ebf85e |
+#include "mock_context.h"
|
|
Thomas Zimmermann |
ebf85e |
+#include "mock_drm.h"
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
struct hang {
|
|
Thomas Zimmermann |
ebf85e |
struct drm_i915_private *i915;
|
|
Thomas Zimmermann |
ebf85e |
struct drm_i915_gem_object *hws;
|
|
Thomas Zimmermann |
ebf85e |
@@ -372,6 +377,164 @@ static int igt_reset_engine(void *arg)
|
|
Thomas Zimmermann |
ebf85e |
return err;
|
|
Thomas Zimmermann |
ebf85e |
}
|
|
Thomas Zimmermann |
ebf85e |
|
|
Thomas Zimmermann |
ebf85e |
+static int active_engine(void *data)
|
|
Thomas Zimmermann |
ebf85e |
+{
|
|
Thomas Zimmermann |
ebf85e |
+ struct intel_engine_cs *engine = data;
|
|
Thomas Zimmermann |
ebf85e |
+ struct drm_i915_gem_request *rq[2] = {};
|
|
Thomas Zimmermann |
ebf85e |
+ struct i915_gem_context *ctx[2];
|
|
Thomas Zimmermann |
ebf85e |
+ struct drm_file *file;
|
|
Thomas Zimmermann |
ebf85e |
+ unsigned long count = 0;
|
|
Thomas Zimmermann |
ebf85e |
+ int err = 0;
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ file = mock_file(engine->i915);
|
|
Thomas Zimmermann |
ebf85e |
+ if (IS_ERR(file))
|
|
Thomas Zimmermann |
ebf85e |
+ return PTR_ERR(file);
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ mutex_lock(&engine->i915->drm.struct_mutex);
|
|
Thomas Zimmermann |
ebf85e |
+ ctx[0] = live_context(engine->i915, file);
|
|
Thomas Zimmermann |
ebf85e |
+ mutex_unlock(&engine->i915->drm.struct_mutex);
|
|
Thomas Zimmermann |
ebf85e |
+ if (IS_ERR(ctx[0])) {
|
|
Thomas Zimmermann |
ebf85e |
+ err = PTR_ERR(ctx[0]);
|
|
Thomas Zimmermann |
ebf85e |
+ goto err_file;
|
|
Thomas Zimmermann |
ebf85e |
+ }
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ mutex_lock(&engine->i915->drm.struct_mutex);
|
|
Thomas Zimmermann |
ebf85e |
+ ctx[1] = live_context(engine->i915, file);
|
|
Thomas Zimmermann |
ebf85e |
+ mutex_unlock(&engine->i915->drm.struct_mutex);
|
|
Thomas Zimmermann |
ebf85e |
+ if (IS_ERR(ctx[1])) {
|
|
Thomas Zimmermann |
ebf85e |
+ err = PTR_ERR(ctx[1]);
|
|
Thomas Zimmermann |
ebf85e |
+ i915_gem_context_put(ctx[0]);
|
|
Thomas Zimmermann |
ebf85e |
+ goto err_file;
|
|
Thomas Zimmermann |
ebf85e |
+ }
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ while (!kthread_should_stop()) {
|
|
Thomas Zimmermann |
ebf85e |
+ unsigned int idx = count++ & 1;
|
|
Thomas Zimmermann |
ebf85e |
+ struct drm_i915_gem_request *old = rq[idx];
|
|
Thomas Zimmermann |
ebf85e |
+ struct drm_i915_gem_request *new;
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ mutex_lock(&engine->i915->drm.struct_mutex);
|
|
Thomas Zimmermann |
ebf85e |
+ new = i915_gem_request_alloc(engine, ctx[idx]);
|
|
Thomas Zimmermann |
ebf85e |
+ if (IS_ERR(new)) {
|
|
Thomas Zimmermann |
ebf85e |
+ mutex_unlock(&engine->i915->drm.struct_mutex);
|
|
Thomas Zimmermann |
ebf85e |
+ err = PTR_ERR(new);
|
|
Thomas Zimmermann |
ebf85e |
+ break;
|
|
Thomas Zimmermann |
ebf85e |
+ }
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ rq[idx] = i915_gem_request_get(new);
|
|
Thomas Zimmermann |
ebf85e |
+ i915_add_request(new);
|
|
Thomas Zimmermann |
ebf85e |
+ mutex_unlock(&engine->i915->drm.struct_mutex);
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ if (old) {
|
|
Thomas Zimmermann |
ebf85e |
+ i915_wait_request(old, 0, MAX_SCHEDULE_TIMEOUT);
|
|
Thomas Zimmermann |
ebf85e |
+ i915_gem_request_put(old);
|
|
Thomas Zimmermann |
ebf85e |
+ }
|
|
Thomas Zimmermann |
ebf85e |
+ }
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ for (count = 0; count < ARRAY_SIZE(rq); count++)
|
|
Thomas Zimmermann |
ebf85e |
+ i915_gem_request_put(rq[count]);
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+err_file:
|
|
Thomas Zimmermann |
ebf85e |
+ mock_file_free(engine->i915, file);
|
|
Thomas Zimmermann |
ebf85e |
+ return err;
|
|
Thomas Zimmermann |
ebf85e |
+}
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+static int igt_reset_active_engines(void *arg)
|
|
Thomas Zimmermann |
ebf85e |
+{
|
|
Thomas Zimmermann |
ebf85e |
+ struct drm_i915_private *i915 = arg;
|
|
Thomas Zimmermann |
ebf85e |
+ struct intel_engine_cs *engine, *active;
|
|
Thomas Zimmermann |
ebf85e |
+ enum intel_engine_id id, tmp;
|
|
Thomas Zimmermann |
ebf85e |
+ int err = 0;
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ /* Check that issuing a reset on one engine does not interfere
|
|
Thomas Zimmermann |
ebf85e |
+ * with any other engine.
|
|
Thomas Zimmermann |
ebf85e |
+ */
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ if (!intel_has_reset_engine(i915))
|
|
Thomas Zimmermann |
ebf85e |
+ return 0;
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ for_each_engine(engine, i915, id) {
|
|
Thomas Zimmermann |
ebf85e |
+ struct task_struct *threads[I915_NUM_ENGINES];
|
|
Thomas Zimmermann |
ebf85e |
+ unsigned long resets[I915_NUM_ENGINES];
|
|
Thomas Zimmermann |
ebf85e |
+ unsigned long global = i915_reset_count(&i915->gpu_error);
|
|
Thomas Zimmermann |
ebf85e |
+ IGT_TIMEOUT(end_time);
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ memset(threads, 0, sizeof(threads));
|
|
Thomas Zimmermann |
ebf85e |
+ for_each_engine(active, i915, tmp) {
|
|
Thomas Zimmermann |
ebf85e |
+ struct task_struct *tsk;
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ if (active == engine)
|
|
Thomas Zimmermann |
ebf85e |
+ continue;
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ resets[tmp] = i915_reset_engine_count(&i915->gpu_error,
|
|
Thomas Zimmermann |
ebf85e |
+ active);
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ tsk = kthread_run(active_engine, active,
|
|
Thomas Zimmermann |
ebf85e |
+ "igt/%s", active->name);
|
|
Thomas Zimmermann |
ebf85e |
+ if (IS_ERR(tsk)) {
|
|
Thomas Zimmermann |
ebf85e |
+ err = PTR_ERR(tsk);
|
|
Thomas Zimmermann |
ebf85e |
+ goto unwind;
|
|
Thomas Zimmermann |
ebf85e |
+ }
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ threads[tmp] = tsk;
|
|
Thomas Zimmermann |
ebf85e |
+ get_task_struct(tsk);
|
|
Thomas Zimmermann |
ebf85e |
+ }
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ set_bit(I915_RESET_ENGINE + engine->id, &i915->gpu_error.flags);
|
|
Thomas Zimmermann |
ebf85e |
+ do {
|
|
Thomas Zimmermann |
ebf85e |
+ err = i915_reset_engine(engine);
|
|
Thomas Zimmermann |
ebf85e |
+ if (err) {
|
|
Thomas Zimmermann |
ebf85e |
+ pr_err("i915_reset_engine(%s) failed, err=%d\n",
|
|
Thomas Zimmermann |
ebf85e |
+ engine->name, err);
|
|
Thomas Zimmermann |
ebf85e |
+ break;
|
|
Thomas Zimmermann |
ebf85e |
+ }
|
|
Thomas Zimmermann |
ebf85e |
+ } while (time_before(jiffies, end_time));
|
|
Thomas Zimmermann |
ebf85e |
+ clear_bit(I915_RESET_ENGINE + engine->id,
|
|
Thomas Zimmermann |
ebf85e |
+ &i915->gpu_error.flags);
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+unwind:
|
|
Thomas Zimmermann |
ebf85e |
+ for_each_engine(active, i915, tmp) {
|
|
Thomas Zimmermann |
ebf85e |
+ int ret;
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ if (!threads[tmp])
|
|
Thomas Zimmermann |
ebf85e |
+ continue;
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ ret = kthread_stop(threads[tmp]);
|
|
Thomas Zimmermann |
ebf85e |
+ if (ret) {
|
|
Thomas Zimmermann |
ebf85e |
+ pr_err("kthread for active engine %s failed, err=%d\n",
|
|
Thomas Zimmermann |
ebf85e |
+ active->name, ret);
|
|
Thomas Zimmermann |
ebf85e |
+ if (!err)
|
|
Thomas Zimmermann |
ebf85e |
+ err = ret;
|
|
Thomas Zimmermann |
ebf85e |
+ }
|
|
Thomas Zimmermann |
ebf85e |
+ put_task_struct(threads[tmp]);
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ if (resets[tmp] != i915_reset_engine_count(&i915->gpu_error,
|
|
Thomas Zimmermann |
ebf85e |
+ active)) {
|
|
Thomas Zimmermann |
ebf85e |
+ pr_err("Innocent engine %s was reset (count=%ld)\n",
|
|
Thomas Zimmermann |
ebf85e |
+ active->name,
|
|
Thomas Zimmermann |
ebf85e |
+ i915_reset_engine_count(&i915->gpu_error,
|
|
Thomas Zimmermann |
ebf85e |
+ active) - resets[tmp]);
|
|
Thomas Zimmermann |
ebf85e |
+ err = -EIO;
|
|
Thomas Zimmermann |
ebf85e |
+ }
|
|
Thomas Zimmermann |
ebf85e |
+ }
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ if (global != i915_reset_count(&i915->gpu_error)) {
|
|
Thomas Zimmermann |
ebf85e |
+ pr_err("Global reset (count=%ld)!\n",
|
|
Thomas Zimmermann |
ebf85e |
+ i915_reset_count(&i915->gpu_error) - global);
|
|
Thomas Zimmermann |
ebf85e |
+ err = -EIO;
|
|
Thomas Zimmermann |
ebf85e |
+ }
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ if (err)
|
|
Thomas Zimmermann |
ebf85e |
+ break;
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ cond_resched();
|
|
Thomas Zimmermann |
ebf85e |
+ }
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ if (i915_terminally_wedged(&i915->gpu_error))
|
|
Thomas Zimmermann |
ebf85e |
+ err = -EIO;
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ return err;
|
|
Thomas Zimmermann |
ebf85e |
+}
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
static u32 fake_hangcheck(struct drm_i915_gem_request *rq)
|
|
Thomas Zimmermann |
ebf85e |
{
|
|
Thomas Zimmermann |
ebf85e |
u32 reset_count;
|
|
Thomas Zimmermann |
ebf85e |
@@ -689,6 +852,7 @@ int intel_hangcheck_live_selftests(struc
|
|
Thomas Zimmermann |
ebf85e |
SUBTEST(igt_hang_sanitycheck),
|
|
Thomas Zimmermann |
ebf85e |
SUBTEST(igt_global_reset),
|
|
Thomas Zimmermann |
ebf85e |
SUBTEST(igt_reset_engine),
|
|
Thomas Zimmermann |
ebf85e |
+ SUBTEST(igt_reset_active_engines),
|
|
Thomas Zimmermann |
ebf85e |
SUBTEST(igt_wait_reset),
|
|
Thomas Zimmermann |
ebf85e |
SUBTEST(igt_reset_queue),
|
|
Thomas Zimmermann |
ebf85e |
SUBTEST(igt_render_engine_reset_fallback),
|
|
Thomas Zimmermann |
ebf85e |
--- a/drivers/gpu/drm/i915/selftests/mock_context.c
|
|
Thomas Zimmermann |
ebf85e |
+++ b/drivers/gpu/drm/i915/selftests/mock_context.c
|
|
Thomas Zimmermann |
ebf85e |
@@ -95,3 +95,11 @@ void mock_init_contexts(struct drm_i915_
|
|
Thomas Zimmermann |
ebf85e |
INIT_WORK(&i915->contexts.free_work, contexts_free_worker);
|
|
Thomas Zimmermann |
ebf85e |
init_llist_head(&i915->contexts.free_list);
|
|
Thomas Zimmermann |
ebf85e |
}
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+struct i915_gem_context *
|
|
Thomas Zimmermann |
ebf85e |
+live_context(struct drm_i915_private *i915, struct drm_file *file)
|
|
Thomas Zimmermann |
ebf85e |
+{
|
|
Thomas Zimmermann |
ebf85e |
+ lockdep_assert_held(&i915->drm.struct_mutex);
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
+ return i915_gem_create_context(i915, file->driver_priv);
|
|
Thomas Zimmermann |
ebf85e |
+}
|
|
Thomas Zimmermann |
ebf85e |
--- a/drivers/gpu/drm/i915/selftests/mock_context.h
|
|
Thomas Zimmermann |
ebf85e |
+++ b/drivers/gpu/drm/i915/selftests/mock_context.h
|
|
Thomas Zimmermann |
ebf85e |
@@ -33,4 +33,7 @@ mock_context(struct drm_i915_private *i9
|
|
Thomas Zimmermann |
ebf85e |
|
|
Thomas Zimmermann |
ebf85e |
void mock_context_close(struct i915_gem_context *ctx);
|
|
Thomas Zimmermann |
ebf85e |
|
|
Thomas Zimmermann |
ebf85e |
+struct i915_gem_context *
|
|
Thomas Zimmermann |
ebf85e |
+live_context(struct drm_i915_private *i915, struct drm_file *file);
|
|
Thomas Zimmermann |
ebf85e |
+
|
|
Thomas Zimmermann |
ebf85e |
#endif /* !__MOCK_CONTEXT_H */
|