drm/i915: Move register white-listing to the common workaround framework
authorTvrtko Ursulin <tvrtko.ursulin@intel.com>
Mon, 3 Dec 2018 12:50:12 +0000 (12:50 +0000)
committerTvrtko Ursulin <tvrtko.ursulin@intel.com>
Tue, 4 Dec 2018 12:23:21 +0000 (12:23 +0000)
Instead of having a separate list of white-listed registers we can
trivially move this to the common workarounds framework.

This brings us one step closer to the goal of driving all workaround
classes using the same code.

v2:
 * Use GEM_DEBUG_WARN_ON for the sanity check. (Chris Wilson)

v3:
 * API rename. (Chris Wilson)

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: https://patchwork.freedesktop.org/patch/msgid/20181203125014.3219-6-tvrtko.ursulin@linux.intel.com
drivers/gpu/drm/i915/intel_engine_cs.c
drivers/gpu/drm/i915/intel_lrc.c
drivers/gpu/drm/i915/intel_ringbuffer.h
drivers/gpu/drm/i915/intel_workarounds.c
drivers/gpu/drm/i915/intel_workarounds.h
drivers/gpu/drm/i915/selftests/intel_workarounds.c

index ef5d202e9d45513c3a1bd0d225fb1dd5949fe2e3..496462d77ebc1e97caa9c356f5aa2a872cfa5edf 100644 (file)
@@ -725,6 +725,7 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine)
        i915_timeline_fini(&engine->timeline);
 
        intel_wa_list_free(&engine->wa_list);
+       intel_wa_list_free(&engine->whitelist);
 }
 
 u64 intel_engine_get_active_head(const struct intel_engine_cs *engine)
index a5d6663ceafd0712a26835921b23d738e41abffe..92e1f08e1483162b73d8e6936b671a14632044b4 100644 (file)
@@ -1652,7 +1652,7 @@ static int gen8_init_render_ring(struct intel_engine_cs *engine)
        if (ret)
                return ret;
 
-       intel_whitelist_workarounds_apply(engine);
+       intel_engine_apply_whitelist(engine);
 
        /* We need to disable the AsyncFlip performance optimisations in order
         * to use MI_WAIT_FOR_EVENT within the CS. It should already be
@@ -1675,7 +1675,7 @@ static int gen9_init_render_ring(struct intel_engine_cs *engine)
        if (ret)
                return ret;
 
-       intel_whitelist_workarounds_apply(engine);
+       intel_engine_apply_whitelist(engine);
 
        return 0;
 }
@@ -2307,6 +2307,7 @@ int logical_render_ring_init(struct intel_engine_cs *engine)
                          ret);
        }
 
+       intel_engine_init_whitelist(engine);
        intel_engine_init_workarounds(engine);
 
        return 0;
index 3abac391a73908196552c0ad61ca101ae9212c9e..7b110e221749153db5ba55b6ef1e8f9093446c6d 100644 (file)
@@ -437,6 +437,7 @@ struct intel_engine_cs {
        struct intel_hw_status_page status_page;
        struct i915_ctx_workarounds wa_ctx;
        struct i915_wa_list wa_list;
+       struct i915_wa_list whitelist;
        struct i915_vma *scratch;
 
        u32             irq_keep_mask; /* always keep these interrupts */
index c53d4388930b7b8420303b9a68c0e901874ced25..d920a6256c838c6c5b79655b92e48b93b2b93313 100644 (file)
@@ -1011,29 +1011,20 @@ bool intel_gt_verify_workarounds(struct drm_i915_private *dev_priv,
        return wa_list_verify(dev_priv, &dev_priv->gt_wa_list, from);
 }
 
-struct whitelist {
-       i915_reg_t reg[RING_MAX_NONPRIV_SLOTS];
-       unsigned int count;
-       u32 nopid;
-};
-
-static void whitelist_reg(struct whitelist *w, i915_reg_t reg)
+static void
+whitelist_reg(struct i915_wa_list *wal, i915_reg_t reg)
 {
-       if (GEM_DEBUG_WARN_ON(w->count >= RING_MAX_NONPRIV_SLOTS))
-               return;
-
-       w->reg[w->count++] = reg;
-}
+       struct i915_wa wa = {
+               .reg = reg
+       };
 
-static void bdw_whitelist_build(struct whitelist *w)
-{
-}
+       if (GEM_DEBUG_WARN_ON(wal->count >= RING_MAX_NONPRIV_SLOTS))
+               return;
 
-static void chv_whitelist_build(struct whitelist *w)
-{
+       wal_add(wal, &wa);
 }
 
-static void gen9_whitelist_build(struct whitelist *w)
+static void gen9_whitelist_build(struct i915_wa_list *w)
 {
        /* WaVFEStateAfterPipeControlwithMediaStateClear:skl,bxt,glk,cfl */
        whitelist_reg(w, GEN9_CTX_PREEMPT_REG);
@@ -1045,7 +1036,7 @@ static void gen9_whitelist_build(struct whitelist *w)
        whitelist_reg(w, GEN8_HDC_CHICKEN1);
 }
 
-static void skl_whitelist_build(struct whitelist *w)
+static void skl_whitelist_build(struct i915_wa_list *w)
 {
        gen9_whitelist_build(w);
 
@@ -1053,12 +1044,12 @@ static void skl_whitelist_build(struct whitelist *w)
        whitelist_reg(w, GEN8_L3SQCREG4);
 }
 
-static void bxt_whitelist_build(struct whitelist *w)
+static void bxt_whitelist_build(struct i915_wa_list *w)
 {
        gen9_whitelist_build(w);
 }
 
-static void kbl_whitelist_build(struct whitelist *w)
+static void kbl_whitelist_build(struct i915_wa_list *w)
 {
        gen9_whitelist_build(w);
 
@@ -1066,7 +1057,7 @@ static void kbl_whitelist_build(struct whitelist *w)
        whitelist_reg(w, GEN8_L3SQCREG4);
 }
 
-static void glk_whitelist_build(struct whitelist *w)
+static void glk_whitelist_build(struct i915_wa_list *w)
 {
        gen9_whitelist_build(w);
 
@@ -1074,18 +1065,18 @@ static void glk_whitelist_build(struct whitelist *w)
        whitelist_reg(w, GEN9_SLICE_COMMON_ECO_CHICKEN1);
 }
 
-static void cfl_whitelist_build(struct whitelist *w)
+static void cfl_whitelist_build(struct i915_wa_list *w)
 {
        gen9_whitelist_build(w);
 }
 
-static void cnl_whitelist_build(struct whitelist *w)
+static void cnl_whitelist_build(struct i915_wa_list *w)
 {
        /* WaEnablePreemptionGranularityControlByUMD:cnl */
        whitelist_reg(w, GEN8_CS_CHICKEN1);
 }
 
-static void icl_whitelist_build(struct whitelist *w)
+static void icl_whitelist_build(struct i915_wa_list *w)
 {
        /* WaAllowUMDToModifyHalfSliceChicken7:icl */
        whitelist_reg(w, GEN9_HALF_SLICE_CHICKEN7);
@@ -1094,22 +1085,21 @@ static void icl_whitelist_build(struct whitelist *w)
        whitelist_reg(w, GEN10_SAMPLER_MODE);
 }
 
-static struct whitelist *whitelist_build(struct intel_engine_cs *engine,
-                                        struct whitelist *w)
+void intel_engine_init_whitelist(struct intel_engine_cs *engine)
 {
        struct drm_i915_private *i915 = engine->i915;
+       struct i915_wa_list *w = &engine->whitelist;
 
        GEM_BUG_ON(engine->id != RCS);
 
-       w->count = 0;
-       w->nopid = i915_mmio_reg_offset(RING_NOPID(engine->mmio_base));
+       wa_init_start(w, "whitelist");
 
        if (INTEL_GEN(i915) < 8)
-               return NULL;
+               return;
        else if (IS_BROADWELL(i915))
-               bdw_whitelist_build(w);
+               return;
        else if (IS_CHERRYVIEW(i915))
-               chv_whitelist_build(w);
+               return;
        else if (IS_SKYLAKE(i915))
                skl_whitelist_build(w);
        else if (IS_BROXTON(i915))
@@ -1127,37 +1117,30 @@ static struct whitelist *whitelist_build(struct intel_engine_cs *engine,
        else
                MISSING_CASE(INTEL_GEN(i915));
 
-       return w;
+       wa_init_finish(w);
 }
 
-static void whitelist_apply(struct intel_engine_cs *engine,
-                           const struct whitelist *w)
+void intel_engine_apply_whitelist(struct intel_engine_cs *engine)
 {
        struct drm_i915_private *dev_priv = engine->i915;
+       const struct i915_wa_list *wal = &engine->whitelist;
        const u32 base = engine->mmio_base;
+       struct i915_wa *wa;
        unsigned int i;
 
-       if (!w)
+       if (!wal->count)
                return;
 
-       intel_uncore_forcewake_get(engine->i915, FORCEWAKE_ALL);
-
-       for (i = 0; i < w->count; i++)
-               I915_WRITE_FW(RING_FORCE_TO_NONPRIV(base, i),
-                             i915_mmio_reg_offset(w->reg[i]));
+       for (i = 0, wa = wal->list; i < wal->count; i++, wa++)
+               I915_WRITE(RING_FORCE_TO_NONPRIV(base, i),
+                          i915_mmio_reg_offset(wa->reg));
 
        /* And clear the rest just in case of garbage */
        for (; i < RING_MAX_NONPRIV_SLOTS; i++)
-               I915_WRITE_FW(RING_FORCE_TO_NONPRIV(base, i), w->nopid);
-
-       intel_uncore_forcewake_put(engine->i915, FORCEWAKE_ALL);
-}
+               I915_WRITE(RING_FORCE_TO_NONPRIV(base, i),
+                          i915_mmio_reg_offset(RING_NOPID(base)));
 
-void intel_whitelist_workarounds_apply(struct intel_engine_cs *engine)
-{
-       struct whitelist w;
-
-       whitelist_apply(engine, whitelist_build(engine, &w));
+       DRM_DEBUG_DRIVER("Applied %u %s workarounds\n", wal->count, wal->name);
 }
 
 static void rcs_engine_wa_init(struct intel_engine_cs *engine)
index 8822e6035f8d1d8868c57c66185880e6a9161188..3f99bfcb4a036a642e2b35d644c9e418e3705ed4 100644 (file)
@@ -35,7 +35,8 @@ void intel_gt_apply_workarounds(struct drm_i915_private *dev_priv);
 bool intel_gt_verify_workarounds(struct drm_i915_private *dev_priv,
                                 const char *from);
 
-void intel_whitelist_workarounds_apply(struct intel_engine_cs *engine);
+void intel_engine_init_whitelist(struct intel_engine_cs *engine);
+void intel_engine_apply_whitelist(struct intel_engine_cs *engine);
 
 void intel_engine_init_workarounds(struct intel_engine_cs *engine);
 void intel_engine_apply_workarounds(struct intel_engine_cs *engine);
index d76a048c3954403363b1e796552098493a404682..67017d5175b8c6cfcb8c5df8b2a90314f517b621 100644 (file)
@@ -94,17 +94,23 @@ err_obj:
        return ERR_PTR(err);
 }
 
-static u32 get_whitelist_reg(const struct whitelist *w, unsigned int i)
+static u32
+get_whitelist_reg(const struct intel_engine_cs *engine, unsigned int i)
 {
-       return i < w->count ? i915_mmio_reg_offset(w->reg[i]) : w->nopid;
+       i915_reg_t reg = i < engine->whitelist.count ?
+                        engine->whitelist.list[i].reg :
+                        RING_NOPID(engine->mmio_base);
+
+       return i915_mmio_reg_offset(reg);
 }
 
-static void print_results(const struct whitelist *w, const u32 *results)
+static void
+print_results(const struct intel_engine_cs *engine, const u32 *results)
 {
        unsigned int i;
 
        for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) {
-               u32 expected = get_whitelist_reg(w, i);
+               u32 expected = get_whitelist_reg(engine, i);
                u32 actual = results[i];
 
                pr_info("RING_NONPRIV[%d]: expected 0x%08x, found 0x%08x\n",
@@ -112,8 +118,7 @@ static void print_results(const struct whitelist *w, const u32 *results)
        }
 }
 
-static int check_whitelist(const struct whitelist *w,
-                          struct i915_gem_context *ctx,
+static int check_whitelist(struct i915_gem_context *ctx,
                           struct intel_engine_cs *engine)
 {
        struct drm_i915_gem_object *results;
@@ -141,11 +146,11 @@ static int check_whitelist(const struct whitelist *w,
        }
 
        for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) {
-               u32 expected = get_whitelist_reg(w, i);
+               u32 expected = get_whitelist_reg(engine, i);
                u32 actual = vaddr[i];
 
                if (expected != actual) {
-                       print_results(w, vaddr);
+                       print_results(engine, vaddr);
                        pr_err("Invalid RING_NONPRIV[%d], expected 0x%08x, found 0x%08x\n",
                               i, expected, actual);
 
@@ -217,7 +222,6 @@ err:
 
 static int check_whitelist_across_reset(struct intel_engine_cs *engine,
                                        int (*reset)(struct intel_engine_cs *),
-                                       const struct whitelist *w,
                                        const char *name)
 {
        struct drm_i915_private *i915 = engine->i915;
@@ -227,7 +231,7 @@ static int check_whitelist_across_reset(struct intel_engine_cs *engine,
        int err;
 
        pr_info("Checking %d whitelisted registers (RING_NONPRIV) [%s]\n",
-               w->count, name);
+               engine->whitelist.count, name);
 
        if (want_spin) {
                err = igt_spinner_init(&spin, i915);
@@ -239,7 +243,7 @@ static int check_whitelist_across_reset(struct intel_engine_cs *engine,
        if (IS_ERR(ctx))
                return PTR_ERR(ctx);
 
-       err = check_whitelist(w, ctx, engine);
+       err = check_whitelist(ctx, engine);
        if (err) {
                pr_err("Invalid whitelist *before* %s reset!\n", name);
                goto out;
@@ -263,7 +267,7 @@ static int check_whitelist_across_reset(struct intel_engine_cs *engine,
                goto out;
        }
 
-       err = check_whitelist(w, ctx, engine);
+       err = check_whitelist(ctx, engine);
        if (err) {
                pr_err("Whitelist not preserved in context across %s reset!\n",
                       name);
@@ -276,7 +280,7 @@ static int check_whitelist_across_reset(struct intel_engine_cs *engine,
        if (IS_ERR(ctx))
                return PTR_ERR(ctx);
 
-       err = check_whitelist(w, ctx, engine);
+       err = check_whitelist(ctx, engine);
        if (err) {
                pr_err("Invalid whitelist *after* %s reset in fresh context!\n",
                       name);
@@ -292,22 +296,18 @@ static int live_reset_whitelist(void *arg)
 {
        struct drm_i915_private *i915 = arg;
        struct intel_engine_cs *engine = i915->engine[RCS];
-       struct whitelist w;
        int err = 0;
 
        /* If we reset the gpu, we should not lose the RING_NONPRIV */
 
-       if (!engine)
-               return 0;
-
-       if (!whitelist_build(engine, &w))
+       if (!engine || engine->whitelist.count == 0)
                return 0;
 
        igt_global_reset_lock(i915);
 
        if (intel_has_reset_engine(i915)) {
                err = check_whitelist_across_reset(engine,
-                                                  do_engine_reset, &w,
+                                                  do_engine_reset,
                                                   "engine");
                if (err)
                        goto out;
@@ -315,7 +315,7 @@ static int live_reset_whitelist(void *arg)
 
        if (intel_has_gpu_reset(i915)) {
                err = check_whitelist_across_reset(engine,
-                                                  do_device_reset, &w,
+                                                  do_device_reset,
                                                   "device");
                if (err)
                        goto out;