Reads of multicast registers give the value for slice/subslice 0 by
default unless we manually steer them to a specific slice/subslice.  If
slice/subslice 0 are fused off in hardware, we'll always read back a
value of 0 rather than the value we wrote into the multicast register.
Although wa_init_mcr() sets up some initial steering to a valid
slice/subslice at startup, we appear to later lose that steering setting
in some cases.  Let's handle this more explicitly and have wa_verify use
intel_read_subslice_reg() to directly steer the readback of workaround
registers in an MCR range to a valid slice/subslice.

Signed-off-by: Matt Roper <matthew.d.ro...@intel.com>
---
 drivers/gpu/drm/i915/gt/intel_engine.h        |  3 +
 drivers/gpu/drm/i915/gt/intel_engine_cs.c     | 17 ++--
 drivers/gpu/drm/i915/gt/intel_workarounds.c   | 98 ++++++++++++-------
 .../gpu/drm/i915/gt/intel_workarounds_types.h |  2 +
 4 files changed, 73 insertions(+), 47 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h 
b/drivers/gpu/drm/i915/gt/intel_engine.h
index d10e52ff059f..54d1fa233a8a 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine.h
@@ -214,6 +214,9 @@ int intel_ring_submission_setup(struct intel_engine_cs 
*engine);
 int intel_engine_stop_cs(struct intel_engine_cs *engine);
 void intel_engine_cancel_stop_cs(struct intel_engine_cs *engine);
 
+u32 intel_read_subslice_reg(struct intel_uncore *uncore,
+                           int slice, int subslice, i915_reg_t reg);
+
 void intel_engine_set_hwsp_writemask(struct intel_engine_cs *engine, u32 mask);
 
 u64 intel_engine_get_active_head(const struct intel_engine_cs *engine);
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c 
b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
index c9e46c5ced43..3ee17aa9928e 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
@@ -951,12 +951,11 @@ const char *i915_cache_level_str(struct drm_i915_private 
*i915, int type)
        }
 }
 
-static u32
-read_subslice_reg(const struct intel_engine_cs *engine,
-                 int slice, int subslice, i915_reg_t reg)
+u32
+intel_read_subslice_reg(struct intel_uncore *uncore,
+                       int slice, int subslice, i915_reg_t reg)
 {
-       struct drm_i915_private *i915 = engine->i915;
-       struct intel_uncore *uncore = engine->uncore;
+       struct drm_i915_private *i915 = uncore->i915;
        u32 mcr_mask, mcr_ss, mcr, old_mcr, val;
        enum forcewake_domains fw_domains;
 
@@ -1027,11 +1026,11 @@ void intel_engine_get_instdone(const struct 
intel_engine_cs *engine,
                }
                for_each_instdone_slice_subslice(i915, sseu, slice, subslice) {
                        instdone->sampler[slice][subslice] =
-                               read_subslice_reg(engine, slice, subslice,
-                                                 GEN7_SAMPLER_INSTDONE);
+                               intel_read_subslice_reg(uncore, slice, subslice,
+                                                       GEN7_SAMPLER_INSTDONE);
                        instdone->row[slice][subslice] =
-                               read_subslice_reg(engine, slice, subslice,
-                                                 GEN7_ROW_INSTDONE);
+                               intel_read_subslice_reg(uncore, slice, subslice,
+                                                       GEN7_ROW_INSTDONE);
                }
                break;
        case 7:
diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c 
b/drivers/gpu/drm/i915/gt/intel_workarounds.c
index 4a255de13394..73a3937c689b 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
@@ -56,6 +56,7 @@ static void wa_init_start(struct i915_wa_list *wal, const 
char *name, const char
 {
        wal->name = name;
        wal->engine_name = engine_name;
+       wal->mcrslice = wal->mcrss = 0;
 }
 
 #define WA_LIST_CHUNK (1 << 4)
@@ -863,6 +864,8 @@ wa_init_mcr(struct drm_i915_private *i915, struct 
i915_wa_list *wal)
        }
 
        drm_dbg(&i915->drm, "MCR slice/subslice = %x\n", mcr);
+       wal->mcrslice = slice;
+       wal->mcrss = subslice;
 
        wa_write_masked_or(wal, GEN8_MCR_SELECTOR, mcr_mask, mcr);
 }
@@ -1006,7 +1009,8 @@ wal_get_fw_for_rmw(struct intel_uncore *uncore, const 
struct i915_wa_list *wal)
 }
 
 static bool
-wa_verify(const struct i915_wa *wa, u32 cur, const char *name, const char 
*from)
+wa_verify(struct drm_i915_private *i915, const struct i915_wa *wa, u32 cur,
+         const char *name, const char *from)
 {
        if ((cur ^ wa->set) & wa->read) {
                DRM_ERROR("%s workaround lost on %s! (%x=%x/%x, expected %x)\n",
@@ -1019,6 +1023,38 @@ wa_verify(const struct i915_wa *wa, u32 cur, const char 
*name, const char *from)
        return true;
 }
 
+static const struct {
+       u32 start;
+       u32 end;
+} mcr_ranges_gen8[] = {
+       { .start = 0x5500, .end = 0x55ff },
+       { .start = 0x7000, .end = 0x7fff },
+       { .start = 0x9400, .end = 0x97ff },
+       { .start = 0xb000, .end = 0xb3ff },
+       { .start = 0xe000, .end = 0xe7ff },
+       {},
+};
+
+static bool mcr_range(struct drm_i915_private *i915, u32 offset)
+{
+       int i;
+
+       if (INTEL_GEN(i915) < 8)
+               return false;
+
+       /*
+        * Registers in these ranges are affected by the MCR selector
+        * which only controls CPU initiated MMIO. Routing does not
+        * work for CS access so we cannot verify them on this path.
+        */
+       for (i = 0; mcr_ranges_gen8[i].start; i++)
+               if (offset >= mcr_ranges_gen8[i].start &&
+                   offset <= mcr_ranges_gen8[i].end)
+                       return true;
+
+       return false;
+}
+
 static void
 wa_list_apply(struct intel_uncore *uncore, const struct i915_wa_list *wal)
 {
@@ -1040,10 +1076,28 @@ wa_list_apply(struct intel_uncore *uncore, const struct 
i915_wa_list *wal)
                        intel_uncore_rmw_fw(uncore, wa->reg, wa->clr, wa->set);
                else
                        intel_uncore_write_fw(uncore, wa->reg, wa->set);
-               if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
-                       wa_verify(wa,
-                                 intel_uncore_read_fw(uncore, wa->reg),
+               if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) {
+                       u32 readout;
+
+                       /*
+                        * Reads of multicast registers default to slice 0,
+                        * subslice 0 unless we steer them to a specific
+                        * slice/subslice instance.  If the first slice/subslice
+                        * is fused off, regular reads will come back as 0's
+                        * rather than the value we applied.
+                        */
+                       if (mcr_range(uncore->i915,
+                                     i915_mmio_reg_offset(wa->reg)))
+                               readout = intel_read_subslice_reg(uncore,
+                                                                 wal->mcrslice,
+                                                                 wal->mcrss,
+                                                                 wa->reg);
+                       else
+                               readout = intel_uncore_read_fw(uncore, wa->reg);
+
+                       wa_verify(uncore->i915, wa, readout,
                                  wal->name, "application");
+               }
        }
 
        intel_uncore_forcewake_put__locked(uncore, fw);
@@ -1064,7 +1118,7 @@ static bool wa_list_verify(struct intel_uncore *uncore,
        bool ok = true;
 
        for (i = 0, wa = wal->list; i < wal->count; i++, wa++)
-               ok &= wa_verify(wa,
+               ok &= wa_verify(uncore->i915, wa,
                                intel_uncore_read(uncore, wa->reg),
                                wal->name, from);
 
@@ -1665,38 +1719,6 @@ create_scratch(struct i915_address_space *vm, int count)
        return ERR_PTR(err);
 }
 
-static const struct {
-       u32 start;
-       u32 end;
-} mcr_ranges_gen8[] = {
-       { .start = 0x5500, .end = 0x55ff },
-       { .start = 0x7000, .end = 0x7fff },
-       { .start = 0x9400, .end = 0x97ff },
-       { .start = 0xb000, .end = 0xb3ff },
-       { .start = 0xe000, .end = 0xe7ff },
-       {},
-};
-
-static bool mcr_range(struct drm_i915_private *i915, u32 offset)
-{
-       int i;
-
-       if (INTEL_GEN(i915) < 8)
-               return false;
-
-       /*
-        * Registers in these ranges are affected by the MCR selector
-        * which only controls CPU initiated MMIO. Routing does not
-        * work for CS access so we cannot verify them on this path.
-        */
-       for (i = 0; mcr_ranges_gen8[i].start; i++)
-               if (offset >= mcr_ranges_gen8[i].start &&
-                   offset <= mcr_ranges_gen8[i].end)
-                       return true;
-
-       return false;
-}
-
 static int
 wa_list_srm(struct i915_request *rq,
            const struct i915_wa_list *wal,
@@ -1794,7 +1816,7 @@ static int engine_wa_list_verify(struct intel_context *ce,
                if (mcr_range(rq->i915, i915_mmio_reg_offset(wa->reg)))
                        continue;
 
-               if (!wa_verify(wa, results[i], wal->name, from))
+               if (!wa_verify(rq->i915, wa, results[i], wal->name, from))
                        err = -ENXIO;
        }
 
diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds_types.h 
b/drivers/gpu/drm/i915/gt/intel_workarounds_types.h
index d166a7145720..a881ea470aa4 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds_types.h
@@ -24,6 +24,8 @@ struct i915_wa_list {
        struct i915_wa  *list;
        unsigned int    count;
        unsigned int    wa_count;
+       u32             mcrslice;
+       u32             mcrss;
 };
 
 #endif /* __INTEL_WORKAROUNDS_TYPES_H__ */
-- 
2.24.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to