]> git.baikalelectronics.ru Git - kernel.git/commitdiff
drm/i915/execlists: Handle copying default context state for atomic reset
authorChris Wilson <chris@chris-wilson.co.uk>
Fri, 18 May 2018 09:02:11 +0000 (10:02 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Sat, 19 May 2018 11:50:58 +0000 (12:50 +0100)
We want to be able to reset the GPU from inside a timer callback
(hardirq context). One step requires us to copy the default context
state over to the guilty context, which means we need to plan in advance
to have that object accessible from within an atomic context. The atomic
context prevents us from pinning the object or from peeking into the
shmemfs backing store (all may sleep), so we choose to pin the
default_state into memory when the engine becomes active. This
compromise allows us to swap out the default state when idle, when
required.

References: 5692251c254a ("drm/i915/lrc: Scrub the GPU state of the guilty hanging request")
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180518090212.5349-2-chris@chris-wilson.co.uk
drivers/gpu/drm/i915/intel_engine_cs.c
drivers/gpu/drm/i915/intel_lrc.c
drivers/gpu/drm/i915/intel_ringbuffer.h

index 847797215a73240419609cbe53c83a6ec3a2938d..0c1f084ee5936e10418c88216aec3cf70a7f378c 100644 (file)
@@ -1091,6 +1091,11 @@ void intel_engines_park(struct drm_i915_private *i915)
                if (engine->park)
                        engine->park(engine);
 
+               if (engine->pinned_default_state) {
+                       i915_gem_object_unpin_map(engine->default_state);
+                       engine->pinned_default_state = NULL;
+               }
+
                i915_gem_batch_pool_fini(&engine->batch_pool);
                engine->execlists.no_priolist = false;
        }
@@ -1108,6 +1113,16 @@ void intel_engines_unpark(struct drm_i915_private *i915)
        enum intel_engine_id id;
 
        for_each_engine(engine, i915, id) {
+               void *map;
+
+               /* Pin the default state for fast resets from atomic context. */
+               map = NULL;
+               if (engine->default_state)
+                       map = i915_gem_object_pin_map(engine->default_state,
+                                                     I915_MAP_WB);
+               if (!IS_ERR_OR_NULL(map))
+                       engine->pinned_default_state = map;
+
                if (engine->unpark)
                        engine->unpark(engine);
 
index 9abd26f22b477c8344b9ab0a49234d6d5a86bf0d..46e7bf4a30a97de828ed4ee8c49847c858ab73c1 100644 (file)
@@ -1965,17 +1965,10 @@ static void execlists_reset(struct intel_engine_cs *engine,
         * to recreate its own state.
         */
        regs = request->hw_context->lrc_reg_state;
-       if (engine->default_state) {
-               void *defaults;
-
-               defaults = i915_gem_object_pin_map(engine->default_state,
-                                                  I915_MAP_WB);
-               if (!IS_ERR(defaults)) {
-                       memcpy(regs, /* skip restoring the vanilla PPHWSP */
-                              defaults + LRC_STATE_PN * PAGE_SIZE,
-                              engine->context_size - PAGE_SIZE);
-                       i915_gem_object_unpin_map(engine->default_state);
-               }
+       if (engine->pinned_default_state) {
+               memcpy(regs, /* skip restoring the vanilla PPHWSP */
+                      engine->pinned_default_state + LRC_STATE_PN * PAGE_SIZE,
+                      engine->context_size - PAGE_SIZE);
        }
        execlists_init_reg_state(regs,
                                 request->gem_context, engine, request->ring);
index 20c4e13efc0decc919b713d7b2ade159371fc0bf..acef385c4c80ddf293e898f715d504454b7ea177 100644 (file)
@@ -342,6 +342,7 @@ struct intel_engine_cs {
        struct i915_timeline timeline;
 
        struct drm_i915_gem_object *default_state;
+       void *pinned_default_state;
 
        atomic_t irq_count;
        unsigned long irq_posted;