drm/i915/ringbuffer: Serialize load of PD_DIR
authorChris Wilson <chris@chris-wilson.co.uk>
Mon, 11 Jun 2018 17:18:25 +0000 (18:18 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Tue, 12 Jun 2018 08:10:04 +0000 (09:10 +0100)
After triggering the mm switch with a load of PD_DIR, which may be
deferred unto the MI_SET_CONTEXT on rcs, serialise the next commands
with that load by posting a read of PD_DIR (or else those subsequent
commands may access the stale page tables).

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Cc: Matthew Auld <matthew.william.auld@gmail.com>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180611171825.13678-2-chris@chris-wilson.co.uk
drivers/gpu/drm/i915/intel_engine_cs.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_ringbuffer.h

index d1cf8b4926abe2f73644d179c1e52a43520bf7d6..d278fed8cb31d955322bf50ef15aa84b6d62a977 100644 (file)
@@ -499,7 +499,8 @@ void intel_engine_setup_common(struct intel_engine_cs *engine)
        intel_engine_init_cmd_parser(engine);
 }
 
-int intel_engine_create_scratch(struct intel_engine_cs *engine, int size)
+int intel_engine_create_scratch(struct intel_engine_cs *engine,
+                               unsigned int size)
 {
        struct drm_i915_gem_object *obj;
        struct i915_vma *vma;
@@ -533,7 +534,7 @@ err_unref:
        return ret;
 }
 
-static void intel_engine_cleanup_scratch(struct intel_engine_cs *engine)
+void intel_engine_cleanup_scratch(struct intel_engine_cs *engine)
 {
        i915_vma_unpin_and_release(&engine->scratch);
 }
index bb4af8f84a22cd433064e6390cc786549d66d0a2..735622dc73ec2d47031ca91bb742ba4b90cf8eb4 100644 (file)
@@ -1361,8 +1361,9 @@ intel_ring_context_pin(struct intel_engine_cs *engine,
 
 static int intel_init_ring_buffer(struct intel_engine_cs *engine)
 {
-       struct intel_ring *ring;
        struct i915_timeline *timeline;
+       struct intel_ring *ring;
+       unsigned int size;
        int err;
 
        intel_engine_setup_common(engine);
@@ -1388,12 +1389,21 @@ static int intel_init_ring_buffer(struct intel_engine_cs *engine)
        GEM_BUG_ON(engine->buffer);
        engine->buffer = ring;
 
-       err = intel_engine_init_common(engine);
+       size = PAGE_SIZE;
+       if (HAS_BROKEN_CS_TLB(engine->i915))
+               size = I830_WA_SIZE;
+       err = intel_engine_create_scratch(engine, size);
        if (err)
                goto err_unpin;
 
+       err = intel_engine_init_common(engine);
+       if (err)
+               goto err_scratch;
+
        return 0;
 
+err_scratch:
+       intel_engine_cleanup_scratch(engine);
 err_unpin:
        intel_ring_unpin(ring);
 err_ring:
@@ -1455,6 +1465,25 @@ static int load_pd_dir(struct i915_request *rq,
        return 0;
 }
 
+static int flush_pd_dir(struct i915_request *rq)
+{
+       const struct intel_engine_cs * const engine = rq->engine;
+       u32 *cs;
+
+       cs = intel_ring_begin(rq, 4);
+       if (IS_ERR(cs))
+               return PTR_ERR(cs);
+
+       /* Stall until the page table load is complete */
+       *cs++ = MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT;
+       *cs++ = i915_mmio_reg_offset(RING_PP_DIR_BASE(engine));
+       *cs++ = i915_ggtt_offset(engine->scratch);
+       *cs++ = MI_NOOP;
+
+       intel_ring_advance(rq, cs);
+       return 0;
+}
+
 static inline int mi_set_context(struct i915_request *rq, u32 flags)
 {
        struct drm_i915_private *i915 = rq->i915;
@@ -1638,6 +1667,12 @@ static int switch_context(struct i915_request *rq)
                        goto err_mm;
        }
 
+       if (ppgtt) {
+               ret = flush_pd_dir(rq);
+               if (ret)
+                       goto err_mm;
+       }
+
        if (ctx->remap_slice) {
                for (i = 0; i < MAX_L3_SLICES; i++) {
                        if (!(ctx->remap_slice & BIT(i)))
@@ -2158,16 +2193,6 @@ int intel_init_render_ring_buffer(struct intel_engine_cs *engine)
        if (ret)
                return ret;
 
-       if (INTEL_GEN(dev_priv) >= 6) {
-               ret = intel_engine_create_scratch(engine, PAGE_SIZE);
-               if (ret)
-                       return ret;
-       } else if (HAS_BROKEN_CS_TLB(dev_priv)) {
-               ret = intel_engine_create_scratch(engine, I830_WA_SIZE);
-               if (ret)
-                       return ret;
-       }
-
        return 0;
 }
 
index e9494557aaa12a4eab806f036d6fbb382e3d3fb2..2c35dd3525a6e40748f17e7bb73e85ce32a69d91 100644 (file)
@@ -869,9 +869,12 @@ void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno);
 
 void intel_engine_setup_common(struct intel_engine_cs *engine);
 int intel_engine_init_common(struct intel_engine_cs *engine);
-int intel_engine_create_scratch(struct intel_engine_cs *engine, int size);
 void intel_engine_cleanup_common(struct intel_engine_cs *engine);
 
+int intel_engine_create_scratch(struct intel_engine_cs *engine,
+                               unsigned int size);
+void intel_engine_cleanup_scratch(struct intel_engine_cs *engine);
+
 int intel_init_render_ring_buffer(struct intel_engine_cs *engine);
 int intel_init_bsd_ring_buffer(struct intel_engine_cs *engine);
 int intel_init_blt_ring_buffer(struct intel_engine_cs *engine);