From: Chris Wilson <chris@chris-wilson.co.uk>
Date: Mon, 11 Jun 2018 18:18:25 +0100
Subject: drm/i915/ringbuffer: Serialize load of PD_DIR
Git-commit: d9d117e40d4ffc03438177eeac83d96dfeee76be
Patch-mainline: v4.19-rc1
References: FATE#326289 FATE#326079 FATE#326049 FATE#322398 FATE#326166
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
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
drivers/gpu/drm/i915/intel_engine_cs.c | 5 +--
drivers/gpu/drm/i915/intel_ringbuffer.c | 49 ++++++++++++++++++++++++--------
drivers/gpu/drm/i915/intel_ringbuffer.h | 5 ++-
3 files changed, 44 insertions(+), 15 deletions(-)
--- a/drivers/gpu/drm/i915/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/intel_engine_cs.c
@@ -499,7 +499,8 @@ void intel_engine_setup_common(struct in
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);
}
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -1363,8 +1363,9 @@ intel_ring_context_pin(struct intel_engi
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);
@@ -1390,12 +1391,21 @@ static int intel_init_ring_buffer(struct
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:
@@ -1457,6 +1467,25 @@ static int load_pd_dir(struct i915_reque
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;
@@ -1640,6 +1669,12 @@ static int switch_context(struct i915_re
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)))
@@ -2160,16 +2195,6 @@ int intel_init_render_ring_buffer(struct
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;
}
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -868,9 +868,12 @@ void intel_engine_init_global_seqno(stru
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);