drm/i915: Fuse per-context workaround handling with the common framework
authorTvrtko Ursulin <tvrtko.ursulin@intel.com>
Mon, 3 Dec 2018 13:33:57 +0000 (13:33 +0000)
committerTvrtko Ursulin <tvrtko.ursulin@intel.com>
Tue, 4 Dec 2018 12:23:22 +0000 (12:23 +0000)
Convert the per context workaround handling code to run against the newly
introduced common workaround framework and fuse the two to use the
existing smarter list add helper, the one which does the sorted insert and
merges registers where possible.

This completes migration of all four classes of workarounds onto the
common framework.

Existing macros are kept untouched for smaller code churn.

v2:
 * Rename to list name ctx_wa_list and move from dev_priv to engine.

v3:
 * API rename and parameters tweaking. (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/20181203133357.10341-1-tvrtko.ursulin@linux.intel.com
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem_context.c
drivers/gpu/drm/i915/intel_engine_cs.c
drivers/gpu/drm/i915/intel_lrc.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_ringbuffer.h
drivers/gpu/drm/i915/intel_workarounds.c
drivers/gpu/drm/i915/intel_workarounds.h

index 129b9a6f8309f7a18ce763dcf5934120736d18a4..38dcee1ca062483272948bce3a7d9af2b4c83a7d 100644 (file)
@@ -3375,13 +3375,15 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused)
 
 static int i915_wa_registers(struct seq_file *m, void *unused)
 {
-       struct i915_workarounds *wa = &node_to_i915(m->private)->workarounds;
-       int i;
+       struct drm_i915_private *i915 = node_to_i915(m->private);
+       const struct i915_wa_list *wal = &i915->engine[RCS]->ctx_wa_list;
+       struct i915_wa *wa;
+       unsigned int i;
 
-       seq_printf(m, "Workarounds applied: %d\n", wa->count);
-       for (i = 0; i < wa->count; ++i)
+       seq_printf(m, "Workarounds applied: %u\n", wal->count);
+       for (i = 0, wa = wal->list; i < wal->count; i++, wa++)
                seq_printf(m, "0x%X: 0x%08X, mask: 0x%08X\n",
-                          wa->reg[i].addr, wa->reg[i].value, wa->reg[i].mask);
+                          i915_mmio_reg_offset(wa->reg), wa->val, wa->mask);
 
        return 0;
 }
index d725390d5a481fb62fcbf42907333519d79a2243..23a3dc6f3907ffbdbfbeb828d7a8acd4578ee5d9 100644 (file)
@@ -1190,20 +1190,6 @@ struct i915_frontbuffer_tracking {
        unsigned flip_bits;
 };
 
-struct i915_wa_reg {
-       u32 addr;
-       u32 value;
-       /* bitmask representing WA bits */
-       u32 mask;
-};
-
-#define I915_MAX_WA_REGS 16
-
-struct i915_workarounds {
-       struct i915_wa_reg reg[I915_MAX_WA_REGS];
-       u32 count;
-};
-
 struct i915_virtual_gpu {
        bool active;
        u32 caps;
@@ -1653,7 +1639,6 @@ struct drm_i915_private {
 
        int dpio_phy_iosf_port[I915_NUM_PHYS_VLV];
 
-       struct i915_workarounds workarounds;
        struct i915_wa_list gt_wa_list;
 
        struct i915_frontbuffer_tracking fb_tracking;
index b97963db0287ab51a2cdf5e599bb5b01ac13c35f..371c070870951d6d1523d828ebfc9874a56e1977 100644 (file)
@@ -535,16 +535,12 @@ static bool needs_preempt_context(struct drm_i915_private *i915)
 int i915_gem_contexts_init(struct drm_i915_private *dev_priv)
 {
        struct i915_gem_context *ctx;
-       int ret;
 
        /* Reassure ourselves we are only called once */
        GEM_BUG_ON(dev_priv->kernel_context);
        GEM_BUG_ON(dev_priv->preempt_context);
 
-       ret = intel_ctx_workarounds_init(dev_priv);
-       if (ret)
-               return ret;
-
+       intel_engine_init_ctx_wa(dev_priv->engine[RCS]);
        init_contexts(dev_priv);
 
        /* lowest priority; idle task */
index 496462d77ebc1e97caa9c356f5aa2a872cfa5edf..6b427bc52f7813736fdb807d007f0cb32db78f09 100644 (file)
@@ -724,6 +724,7 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine)
 
        i915_timeline_fini(&engine->timeline);
 
+       intel_wa_list_free(&engine->ctx_wa_list);
        intel_wa_list_free(&engine->wa_list);
        intel_wa_list_free(&engine->whitelist);
 }
index 92e1f08e1483162b73d8e6936b671a14632044b4..87227fd9ae5fe0e534a860b08cd90d4f079cc032 100644 (file)
@@ -2087,7 +2087,7 @@ static int gen8_init_rcs_context(struct i915_request *rq)
 {
        int ret;
 
-       ret = intel_ctx_workarounds_emit(rq);
+       ret = intel_engine_emit_ctx_wa(rq);
        if (ret)
                return ret;
 
index 81b10d85b73879c4c1b5cddbca83ea36a7a700a5..7f88df5bff090088cc18509af030c4089f4f3feb 100644 (file)
@@ -656,7 +656,7 @@ static int intel_rcs_ctx_init(struct i915_request *rq)
 {
        int ret;
 
-       ret = intel_ctx_workarounds_emit(rq);
+       ret = intel_engine_emit_ctx_wa(rq);
        if (ret != 0)
                return ret;
 
index 7b110e221749153db5ba55b6ef1e8f9093446c6d..927bb21a2b0b814c61d2714f837d5885789aecf4 100644 (file)
@@ -436,6 +436,7 @@ struct intel_engine_cs {
 
        struct intel_hw_status_page status_page;
        struct i915_ctx_workarounds wa_ctx;
+       struct i915_wa_list ctx_wa_list;
        struct i915_wa_list wa_list;
        struct i915_wa_list whitelist;
        struct i915_vma *scratch;
index d920a6256c838c6c5b79655b92e48b93b2b93313..e52bd3f5d526476dc14f5af25f55791ae69570c1 100644 (file)
@@ -59,61 +59,87 @@ static void wa_init_finish(struct i915_wa_list *wal)
                return;
 
        DRM_DEBUG_DRIVER("Initialized %u %s workarounds\n",
-                        wal->count, wal->name);
+                        wal->wa_count, wal->name);
 }
 
-static void wa_add(struct drm_i915_private *i915,
-                  i915_reg_t reg, const u32 mask, const u32 val)
+static void _wa_add(struct i915_wa_list *wal, const struct i915_wa *wa)
 {
-       struct i915_workarounds *wa = &i915->workarounds;
-       unsigned int start = 0, end = wa->count;
-       unsigned int addr = i915_mmio_reg_offset(reg);
-       struct i915_wa_reg *r;
+       unsigned int addr = i915_mmio_reg_offset(wa->reg);
+       unsigned int start = 0, end = wal->count;
+       const unsigned int grow = 1 << 4;
+       struct i915_wa *wa_;
+
+       GEM_BUG_ON(!is_power_of_2(grow));
+
+       if (IS_ALIGNED(wal->count, grow)) { /* Either uninitialized or full. */
+               struct i915_wa *list;
+
+               list = kmalloc_array(ALIGN(wal->count + 1, grow), sizeof(*wa),
+                                    GFP_KERNEL);
+               if (!list) {
+                       DRM_ERROR("No space for workaround init!\n");
+                       return;
+               }
+
+               if (wal->list)
+                       memcpy(list, wal->list, sizeof(*wa) * wal->count);
+
+               wal->list = list;
+       }
 
        while (start < end) {
                unsigned int mid = start + (end - start) / 2;
 
-               if (wa->reg[mid].addr < addr) {
+               if (i915_mmio_reg_offset(wal->list[mid].reg) < addr) {
                        start = mid + 1;
-               } else if (wa->reg[mid].addr > addr) {
+               } else if (i915_mmio_reg_offset(wal->list[mid].reg) > addr) {
                        end = mid;
                } else {
-                       r = &wa->reg[mid];
+                       wa_ = &wal->list[mid];
 
-                       if ((mask & ~r->mask) == 0) {
+                       if ((wa->mask & ~wa_->mask) == 0) {
                                DRM_ERROR("Discarding overwritten w/a for reg %04x (mask: %08x, value: %08x)\n",
-                                         addr, r->mask, r->value);
+                                         i915_mmio_reg_offset(wa_->reg),
+                                         wa_->mask, wa_->val);
 
-                               r->value &= ~mask;
+                               wa_->val &= ~wa->mask;
                        }
 
-                       r->value |= val;
-                       r->mask  |= mask;
+                       wal->wa_count++;
+                       wa_->val |= wa->val;
+                       wa_->mask |= wa->mask;
                        return;
                }
        }
 
-       if (WARN_ON_ONCE(wa->count >= I915_MAX_WA_REGS)) {
-               DRM_ERROR("Dropping w/a for reg %04x (mask: %08x, value: %08x)\n",
-                         addr, mask, val);
-               return;
-       }
+       wal->wa_count++;
+       wa_ = &wal->list[wal->count++];
+       *wa_ = *wa;
 
-       r = &wa->reg[wa->count++];
-       r->addr  = addr;
-       r->value = val;
-       r->mask  = mask;
-
-       while (r-- > wa->reg) {
-               GEM_BUG_ON(r[0].addr == r[1].addr);
-               if (r[1].addr > r[0].addr)
+       while (wa_-- > wal->list) {
+               GEM_BUG_ON(i915_mmio_reg_offset(wa_[0].reg) ==
+                          i915_mmio_reg_offset(wa_[1].reg));
+               if (i915_mmio_reg_offset(wa_[1].reg) >
+                   i915_mmio_reg_offset(wa_[0].reg))
                        break;
 
-               swap(r[1], r[0]);
+               swap(wa_[1], wa_[0]);
        }
 }
 
-#define WA_REG(addr, mask, val) wa_add(dev_priv, (addr), (mask), (val))
+static void
+__wa_add(struct i915_wa_list *wal, i915_reg_t reg, u32 mask, u32 val)
+{
+       struct i915_wa wa = {
+               .reg = reg,
+               .mask = mask,
+               .val = val
+       };
+
+       _wa_add(wal, &wa);
+}
+
+#define WA_REG(addr, mask, val) __wa_add(wal, (addr), (mask), (val))
 
 #define WA_SET_BIT_MASKED(addr, mask) \
        WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask))
@@ -124,8 +150,10 @@ static void wa_add(struct drm_i915_private *i915,
 #define WA_SET_FIELD_MASKED(addr, mask, value) \
        WA_REG(addr, (mask), _MASKED_FIELD(mask, value))
 
-static int gen8_ctx_workarounds_init(struct drm_i915_private *dev_priv)
+static void gen8_ctx_workarounds_init(struct intel_engine_cs *engine)
 {
+       struct i915_wa_list *wal = &engine->ctx_wa_list;
+
        WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING);
 
        /* WaDisableAsyncFlipPerfMode:bdw,chv */
@@ -169,17 +197,14 @@ static int gen8_ctx_workarounds_init(struct drm_i915_private *dev_priv)
        WA_SET_FIELD_MASKED(GEN7_GT_MODE,
                            GEN6_WIZ_HASHING_MASK,
                            GEN6_WIZ_HASHING_16x4);
-
-       return 0;
 }
 
-static int bdw_ctx_workarounds_init(struct drm_i915_private *dev_priv)
+static void bdw_ctx_workarounds_init(struct intel_engine_cs *engine)
 {
-       int ret;
+       struct drm_i915_private *i915 = engine->i915;
+       struct i915_wa_list *wal = &engine->ctx_wa_list;
 
-       ret = gen8_ctx_workarounds_init(dev_priv);
-       if (ret)
-               return ret;
+       gen8_ctx_workarounds_init(engine);
 
        /* WaDisableThreadStallDopClockGating:bdw (pre-production) */
        WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE);
@@ -199,31 +224,28 @@ static int bdw_ctx_workarounds_init(struct drm_i915_private *dev_priv)
                          /* WaForceContextSaveRestoreNonCoherent:bdw */
                          HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT |
                          /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */
-                         (IS_BDW_GT3(dev_priv) ? HDC_FENCE_DEST_SLM_DISABLE : 0));
-
-       return 0;
+                         (IS_BDW_GT3(i915) ? HDC_FENCE_DEST_SLM_DISABLE : 0));
 }
 
-static int chv_ctx_workarounds_init(struct drm_i915_private *dev_priv)
+static void chv_ctx_workarounds_init(struct intel_engine_cs *engine)
 {
-       int ret;
+       struct i915_wa_list *wal = &engine->ctx_wa_list;
 
-       ret = gen8_ctx_workarounds_init(dev_priv);
-       if (ret)
-               return ret;
+       gen8_ctx_workarounds_init(engine);
 
        /* WaDisableThreadStallDopClockGating:chv */
        WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE);
 
        /* Improve HiZ throughput on CHV. */
        WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X);
-
-       return 0;
 }
 
-static int gen9_ctx_workarounds_init(struct drm_i915_private *dev_priv)
+static void gen9_ctx_workarounds_init(struct intel_engine_cs *engine)
 {
-       if (HAS_LLC(dev_priv)) {
+       struct drm_i915_private *i915 = engine->i915;
+       struct i915_wa_list *wal = &engine->ctx_wa_list;
+
+       if (HAS_LLC(i915)) {
                /* WaCompressedResourceSamplerPbeMediaNewHashMode:skl,kbl
                 *
                 * Must match Display Engine. See
@@ -242,7 +264,7 @@ static int gen9_ctx_workarounds_init(struct drm_i915_private *dev_priv)
                          PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
 
        /* Syncing dependencies between camera and graphics:skl,bxt,kbl */
-       if (!IS_COFFEELAKE(dev_priv))
+       if (!IS_COFFEELAKE(i915))
                WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
                                  GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC);
 
@@ -285,9 +307,7 @@ static int gen9_ctx_workarounds_init(struct drm_i915_private *dev_priv)
                          HDC_FORCE_NON_COHERENT);
 
        /* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt,kbl,cfl */
-       if (IS_SKYLAKE(dev_priv) ||
-           IS_KABYLAKE(dev_priv) ||
-           IS_COFFEELAKE(dev_priv))
+       if (IS_SKYLAKE(i915) || IS_KABYLAKE(i915) || IS_COFFEELAKE(i915))
                WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
                                  GEN8_SAMPLER_POWER_BYPASS_DIS);
 
@@ -314,14 +334,14 @@ static int gen9_ctx_workarounds_init(struct drm_i915_private *dev_priv)
                            GEN9_PREEMPT_GPGPU_COMMAND_LEVEL);
 
        /* WaClearHIZ_WM_CHICKEN3:bxt,glk */
-       if (IS_GEN9_LP(dev_priv))
+       if (IS_GEN9_LP(i915))
                WA_SET_BIT_MASKED(GEN9_WM_CHICKEN3, GEN9_FACTOR_IN_CLR_VAL_HIZ);
-
-       return 0;
 }
 
-static int skl_tune_iz_hashing(struct drm_i915_private *dev_priv)
+static void skl_tune_iz_hashing(struct intel_engine_cs *engine)
 {
+       struct drm_i915_private *i915 = engine->i915;
+       struct i915_wa_list *wal = &engine->ctx_wa_list;
        u8 vals[3] = { 0, 0, 0 };
        unsigned int i;
 
@@ -332,7 +352,7 @@ static int skl_tune_iz_hashing(struct drm_i915_private *dev_priv)
                 * Only consider slices where one, and only one, subslice has 7
                 * EUs
                 */
-               if (!is_power_of_2(INTEL_INFO(dev_priv)->sseu.subslice_7eu[i]))
+               if (!is_power_of_2(INTEL_INFO(i915)->sseu.subslice_7eu[i]))
                        continue;
 
                /*
@@ -341,12 +361,12 @@ static int skl_tune_iz_hashing(struct drm_i915_private *dev_priv)
                 *
                 * ->    0 <= ss <= 3;
                 */
-               ss = ffs(INTEL_INFO(dev_priv)->sseu.subslice_7eu[i]) - 1;
+               ss = ffs(INTEL_INFO(i915)->sseu.subslice_7eu[i]) - 1;
                vals[i] = 3 - ss;
        }
 
        if (vals[0] == 0 && vals[1] == 0 && vals[2] == 0)
-               return 0;
+               return;
 
        /* Tune IZ hashing. See intel_device_info_runtime_init() */
        WA_SET_FIELD_MASKED(GEN7_GT_MODE,
@@ -356,28 +376,19 @@ static int skl_tune_iz_hashing(struct drm_i915_private *dev_priv)
                            GEN9_IZ_HASHING(2, vals[2]) |
                            GEN9_IZ_HASHING(1, vals[1]) |
                            GEN9_IZ_HASHING(0, vals[0]));
-
-       return 0;
 }
 
-static int skl_ctx_workarounds_init(struct drm_i915_private *dev_priv)
+static void skl_ctx_workarounds_init(struct intel_engine_cs *engine)
 {
-       int ret;
-
-       ret = gen9_ctx_workarounds_init(dev_priv);
-       if (ret)
-               return ret;
-
-       return skl_tune_iz_hashing(dev_priv);
+       gen9_ctx_workarounds_init(engine);
+       skl_tune_iz_hashing(engine);
 }
 
-static int bxt_ctx_workarounds_init(struct drm_i915_private *dev_priv)
+static void bxt_ctx_workarounds_init(struct intel_engine_cs *engine)
 {
-       int ret;
+       struct i915_wa_list *wal = &engine->ctx_wa_list;
 
-       ret = gen9_ctx_workarounds_init(dev_priv);
-       if (ret)
-               return ret;
+       gen9_ctx_workarounds_init(engine);
 
        /* WaDisableThreadStallDopClockGating:bxt */
        WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
@@ -386,52 +397,41 @@ static int bxt_ctx_workarounds_init(struct drm_i915_private *dev_priv)
        /* WaToEnableHwFixForPushConstHWBug:bxt */
        WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
                          GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
-
-       return 0;
 }
 
-static int kbl_ctx_workarounds_init(struct drm_i915_private *dev_priv)
+static void kbl_ctx_workarounds_init(struct intel_engine_cs *engine)
 {
-       int ret;
+       struct drm_i915_private *i915 = engine->i915;
+       struct i915_wa_list *wal = &engine->ctx_wa_list;
 
-       ret = gen9_ctx_workarounds_init(dev_priv);
-       if (ret)
-               return ret;
+       gen9_ctx_workarounds_init(engine);
 
        /* WaToEnableHwFixForPushConstHWBug:kbl */
-       if (IS_KBL_REVID(dev_priv, KBL_REVID_C0, REVID_FOREVER))
+       if (IS_KBL_REVID(i915, KBL_REVID_C0, REVID_FOREVER))
                WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
                                  GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
 
        /* WaDisableSbeCacheDispatchPortSharing:kbl */
        WA_SET_BIT_MASKED(GEN7_HALF_SLICE_CHICKEN1,
                          GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
-
-       return 0;
 }
 
-static int glk_ctx_workarounds_init(struct drm_i915_private *dev_priv)
+static void glk_ctx_workarounds_init(struct intel_engine_cs *engine)
 {
-       int ret;
+       struct i915_wa_list *wal = &engine->ctx_wa_list;
 
-       ret = gen9_ctx_workarounds_init(dev_priv);
-       if (ret)
-               return ret;
+       gen9_ctx_workarounds_init(engine);
 
        /* WaToEnableHwFixForPushConstHWBug:glk */
        WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
                          GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
-
-       return 0;
 }
 
-static int cfl_ctx_workarounds_init(struct drm_i915_private *dev_priv)
+static void cfl_ctx_workarounds_init(struct intel_engine_cs *engine)
 {
-       int ret;
+       struct i915_wa_list *wal = &engine->ctx_wa_list;
 
-       ret = gen9_ctx_workarounds_init(dev_priv);
-       if (ret)
-               return ret;
+       gen9_ctx_workarounds_init(engine);
 
        /* WaToEnableHwFixForPushConstHWBug:cfl */
        WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
@@ -440,18 +440,19 @@ static int cfl_ctx_workarounds_init(struct drm_i915_private *dev_priv)
        /* WaDisableSbeCacheDispatchPortSharing:cfl */
        WA_SET_BIT_MASKED(GEN7_HALF_SLICE_CHICKEN1,
                          GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
-
-       return 0;
 }
 
-static int cnl_ctx_workarounds_init(struct drm_i915_private *dev_priv)
+static void cnl_ctx_workarounds_init(struct intel_engine_cs *engine)
 {
+       struct drm_i915_private *i915 = engine->i915;
+       struct i915_wa_list *wal = &engine->ctx_wa_list;
+
        /* WaForceContextSaveRestoreNonCoherent:cnl */
        WA_SET_BIT_MASKED(CNL_HDC_CHICKEN0,
                          HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT);
 
        /* WaThrottleEUPerfToAvoidTDBackPressure:cnl(pre-prod) */
-       if (IS_CNL_REVID(dev_priv, CNL_REVID_B0, CNL_REVID_B0))
+       if (IS_CNL_REVID(i915, CNL_REVID_B0, CNL_REVID_B0))
                WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, THROTTLE_12_5);
 
        /* WaDisableReplayBufferBankArbitrationOptimization:cnl */
@@ -459,7 +460,7 @@ static int cnl_ctx_workarounds_init(struct drm_i915_private *dev_priv)
                          GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
 
        /* WaDisableEnhancedSBEVertexCaching:cnl (pre-prod) */
-       if (IS_CNL_REVID(dev_priv, 0, CNL_REVID_B0))
+       if (IS_CNL_REVID(i915, 0, CNL_REVID_B0))
                WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
                                  GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE);
 
@@ -479,16 +480,17 @@ static int cnl_ctx_workarounds_init(struct drm_i915_private *dev_priv)
 
        /* WaDisableEarlyEOT:cnl */
        WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, DISABLE_EARLY_EOT);
-
-       return 0;
 }
 
-static int icl_ctx_workarounds_init(struct drm_i915_private *dev_priv)
+static void icl_ctx_workarounds_init(struct intel_engine_cs *engine)
 {
+       struct drm_i915_private *i915 = engine->i915;
+       struct i915_wa_list *wal = &engine->ctx_wa_list;
+
        /* Wa_1604370585:icl (pre-prod)
         * Formerly known as WaPushConstantDereferenceHoldDisable
         */
-       if (IS_ICL_REVID(dev_priv, ICL_REVID_A0, ICL_REVID_B0))
+       if (IS_ICL_REVID(i915, ICL_REVID_A0, ICL_REVID_B0))
                WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2,
                                  PUSH_CONSTANT_DEREF_DISABLE);
 
@@ -504,7 +506,7 @@ static int icl_ctx_workarounds_init(struct drm_i915_private *dev_priv)
        /* Wa_2006611047:icl (pre-prod)
         * Formerly known as WaDisableImprovedTdlClkGating
         */
-       if (IS_ICL_REVID(dev_priv, ICL_REVID_A0, ICL_REVID_A0))
+       if (IS_ICL_REVID(i915, ICL_REVID_A0, ICL_REVID_A0))
                WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2,
                                  GEN11_TDL_CLOCK_GATING_FIX_DISABLE);
 
@@ -513,70 +515,67 @@ static int icl_ctx_workarounds_init(struct drm_i915_private *dev_priv)
                          GEN11_STATE_CACHE_REDIRECT_TO_CS);
 
        /* Wa_2006665173:icl (pre-prod) */
-       if (IS_ICL_REVID(dev_priv, ICL_REVID_A0, ICL_REVID_A0))
+       if (IS_ICL_REVID(i915, ICL_REVID_A0, ICL_REVID_A0))
                WA_SET_BIT_MASKED(GEN11_COMMON_SLICE_CHICKEN3,
                                  GEN11_BLEND_EMB_FIX_DISABLE_IN_RCC);
-
-       return 0;
 }
 
-int intel_ctx_workarounds_init(struct drm_i915_private *dev_priv)
+void intel_engine_init_ctx_wa(struct intel_engine_cs *engine)
 {
-       int err = 0;
-
-       dev_priv->workarounds.count = 0;
-
-       if (INTEL_GEN(dev_priv) < 8)
-               err = 0;
-       else if (IS_BROADWELL(dev_priv))
-               err = bdw_ctx_workarounds_init(dev_priv);
-       else if (IS_CHERRYVIEW(dev_priv))
-               err = chv_ctx_workarounds_init(dev_priv);
-       else if (IS_SKYLAKE(dev_priv))
-               err = skl_ctx_workarounds_init(dev_priv);
-       else if (IS_BROXTON(dev_priv))
-               err = bxt_ctx_workarounds_init(dev_priv);
-       else if (IS_KABYLAKE(dev_priv))
-               err = kbl_ctx_workarounds_init(dev_priv);
-       else if (IS_GEMINILAKE(dev_priv))
-               err = glk_ctx_workarounds_init(dev_priv);
-       else if (IS_COFFEELAKE(dev_priv))
-               err = cfl_ctx_workarounds_init(dev_priv);
-       else if (IS_CANNONLAKE(dev_priv))
-               err = cnl_ctx_workarounds_init(dev_priv);
-       else if (IS_ICELAKE(dev_priv))
-               err = icl_ctx_workarounds_init(dev_priv);
+       struct drm_i915_private *i915 = engine->i915;
+       struct i915_wa_list *wal = &engine->ctx_wa_list;
+
+       wa_init_start(wal, "context");
+
+       if (INTEL_GEN(i915) < 8)
+               return;
+       else if (IS_BROADWELL(i915))
+               bdw_ctx_workarounds_init(engine);
+       else if (IS_CHERRYVIEW(i915))
+               chv_ctx_workarounds_init(engine);
+       else if (IS_SKYLAKE(i915))
+               skl_ctx_workarounds_init(engine);
+       else if (IS_BROXTON(i915))
+               bxt_ctx_workarounds_init(engine);
+       else if (IS_KABYLAKE(i915))
+               kbl_ctx_workarounds_init(engine);
+       else if (IS_GEMINILAKE(i915))
+               glk_ctx_workarounds_init(engine);
+       else if (IS_COFFEELAKE(i915))
+               cfl_ctx_workarounds_init(engine);
+       else if (IS_CANNONLAKE(i915))
+               cnl_ctx_workarounds_init(engine);
+       else if (IS_ICELAKE(i915))
+               icl_ctx_workarounds_init(engine);
        else
-               MISSING_CASE(INTEL_GEN(dev_priv));
-       if (err)
-               return err;
+               MISSING_CASE(INTEL_GEN(i915));
 
-       DRM_DEBUG_DRIVER("Number of context specific w/a: %d\n",
-                        dev_priv->workarounds.count);
-       return 0;
+       wa_init_finish(wal);
 }
 
-int intel_ctx_workarounds_emit(struct i915_request *rq)
+int intel_engine_emit_ctx_wa(struct i915_request *rq)
 {
-       struct i915_workarounds *w = &rq->i915->workarounds;
+       struct i915_wa_list *wal = &rq->engine->ctx_wa_list;
+       struct i915_wa *wa;
+       unsigned int i;
        u32 *cs;
-       int ret, i;
+       int ret;
 
-       if (w->count == 0)
+       if (wal->count == 0)
                return 0;
 
        ret = rq->engine->emit_flush(rq, EMIT_BARRIER);
        if (ret)
                return ret;
 
-       cs = intel_ring_begin(rq, (w->count * 2 + 2));
+       cs = intel_ring_begin(rq, (wal->count * 2 + 2));
        if (IS_ERR(cs))
                return PTR_ERR(cs);
 
-       *cs++ = MI_LOAD_REGISTER_IMM(w->count);
-       for (i = 0; i < w->count; i++) {
-               *cs++ = w->reg[i].addr;
-               *cs++ = w->reg[i].value;
+       *cs++ = MI_LOAD_REGISTER_IMM(wal->count);
+       for (i = 0, wa = wal->list; i < wal->count; i++, wa++) {
+               *cs++ = i915_mmio_reg_offset(wa->reg);
+               *cs++ = wa->val;
        }
        *cs++ = MI_NOOP;
 
@@ -589,32 +588,6 @@ int intel_ctx_workarounds_emit(struct i915_request *rq)
        return 0;
 }
 
-static void
-wal_add(struct i915_wa_list *wal, const struct i915_wa *wa)
-{
-       const unsigned int grow = 1 << 4;
-
-       GEM_BUG_ON(!is_power_of_2(grow));
-
-       if (IS_ALIGNED(wal->count, grow)) { /* Either uninitialized or full. */
-               struct i915_wa *list;
-
-               list = kmalloc_array(ALIGN(wal->count + 1, grow), sizeof(*wa),
-                                    GFP_KERNEL);
-               if (!list) {
-                       DRM_ERROR("No space for workaround init!\n");
-                       return;
-               }
-
-               if (wal->list)
-                       memcpy(list, wal->list, sizeof(*wa) * wal->count);
-
-               wal->list = list;
-       }
-
-       wal->list[wal->count++] = *wa;
-}
-
 static void
 wa_masked_en(struct i915_wa_list *wal, i915_reg_t reg, u32 val)
 {
@@ -624,7 +597,7 @@ wa_masked_en(struct i915_wa_list *wal, i915_reg_t reg, u32 val)
                .val = _MASKED_BIT_ENABLE(val)
        };
 
-       wal_add(wal, &wa);
+       _wa_add(wal, &wa);
 }
 
 static void
@@ -637,7 +610,7 @@ wa_write_masked_or(struct i915_wa_list *wal, i915_reg_t reg, u32 mask,
                .val = val
        };
 
-       wal_add(wal, &wa);
+       _wa_add(wal, &wa);
 }
 
 static void
@@ -1021,7 +994,7 @@ whitelist_reg(struct i915_wa_list *wal, i915_reg_t reg)
        if (GEM_DEBUG_WARN_ON(wal->count >= RING_MAX_NONPRIV_SLOTS))
                return;
 
-       wal_add(wal, &wa);
+       _wa_add(wal, &wa);
 }
 
 static void gen9_whitelist_build(struct i915_wa_list *w)
index 3f99bfcb4a036a642e2b35d644c9e418e3705ed4..7c734714b05edc51027e269197602abefc541813 100644 (file)
@@ -19,6 +19,7 @@ struct i915_wa_list {
        const char      *name;
        struct i915_wa  *list;
        unsigned int    count;
+       unsigned int    wa_count;
 };
 
 static inline void intel_wa_list_free(struct i915_wa_list *wal)
@@ -27,8 +28,8 @@ static inline void intel_wa_list_free(struct i915_wa_list *wal)
        memset(wal, 0, sizeof(*wal));
 }
 
-int intel_ctx_workarounds_init(struct drm_i915_private *dev_priv);
-int intel_ctx_workarounds_emit(struct i915_request *rq);
+void intel_engine_init_ctx_wa(struct intel_engine_cs *engine);
+int intel_engine_emit_ctx_wa(struct i915_request *rq);
 
 void intel_gt_init_workarounds(struct drm_i915_private *dev_priv);
 void intel_gt_apply_workarounds(struct drm_i915_private *dev_priv);