[Intel-gfx] [PATCH 2/4] drm/i915: Steer multicast register readback in wa_verify

Matt Roper matthew.d.roper at intel.com
Thu Apr 30 23:15:27 UTC 2020


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.roper at 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



More information about the Intel-gfx mailing list