drm/i915/gt: Add a safety submission flush in the heartbeat
authorChris Wilson <chris@chris-wilson.co.uk>
Mon, 15 Jun 2020 16:50:13 +0000 (17:50 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Mon, 15 Jun 2020 17:32:28 +0000 (18:32 +0100)
Just in case everything fails (like for example "missed interrupt
syndrome" on Sandybridge), always flush the submission tasklet from the
heartbeat. This papers over such issues, but will still appear as a
second long glitch, and prevents us from detecting it unless we happen
to be performing a timed test.

v2: We rely on flush_submission() synchronizing with the tasklet on
another CPU.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200615165013.22973-3-chris@chris-wilson.co.uk
drivers/gpu/drm/i915/gt/intel_engine_cs.c
drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c

index d613cf31970ce7950273b7f930cac0e241330ebf..31049e0bdb5726ab89911ff01348f446c0633a9b 100644 (file)
@@ -1094,19 +1094,18 @@ void intel_engine_flush_submission(struct intel_engine_cs *engine)
 {
        struct tasklet_struct *t = &engine->execlists.tasklet;
 
-       if (__tasklet_is_scheduled(t)) {
-               local_bh_disable();
-               if (tasklet_trylock(t)) {
-                       /* Must wait for any GPU reset in progress. */
-                       if (__tasklet_is_enabled(t))
-                               t->func(t->data);
-                       tasklet_unlock(t);
-               }
-               local_bh_enable();
+       /* Synchronise and wait for the tasklet on another CPU */
+       tasklet_kill(t);
+
+       /* Having cancelled the tasklet, ensure that is run */
+       local_bh_disable();
+       if (tasklet_trylock(t)) {
+               /* Must wait for any GPU reset in progress. */
+               if (__tasklet_is_enabled(t))
+                       t->func(t->data);
+               tasklet_unlock(t);
        }
-
-       /* Otherwise flush the tasklet if it was running on another cpu */
-       tasklet_unlock_wait(t);
+       local_bh_enable();
 }
 
 /**
index f67ad937eefb795314aa018765501fc8919e3ff9..cd20fb549b38447f141fccc3bd61a08de5a4fe63 100644 (file)
@@ -65,6 +65,9 @@ static void heartbeat(struct work_struct *wrk)
        struct intel_context *ce = engine->kernel_context;
        struct i915_request *rq;
 
+       /* Just in case everything has gone horribly wrong, give it a kick */
+       intel_engine_flush_submission(engine);
+
        rq = engine->heartbeat.systole;
        if (rq && i915_request_completed(rq)) {
                i915_request_put(rq);