[PATCH 1/2] do not rely on multicast

Tvrtko Ursulin tvrtko.ursulin at linux.intel.com
Wed Jul 24 15:38:19 UTC 2019


From: Tvrtko Ursulin <tvrtko.ursulin at intel.com>

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
---
 drivers/gpu/drm/i915/gt/intel_workarounds.c | 288 +++++++++++++++++---
 1 file changed, 248 insertions(+), 40 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
index 704ace01e7f5..ad91ec328802 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
@@ -922,24 +922,35 @@ void intel_gt_init_workarounds(struct drm_i915_private *i915)
 	wa_init_finish(wal);
 }
 
-static enum forcewake_domains
-wal_get_fw_for_rmw(struct intel_uncore *uncore, const struct i915_wa_list *wal)
+static bool slice_range(struct drm_i915_private *i915, u32 offset)
 {
-	enum forcewake_domains fw = 0;
-	struct i915_wa *wa;
-	unsigned int i;
+	/*
+	 * Registers in this range 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.
+	 */
+	if (INTEL_GEN(i915) >= 8 && (offset >= 0x9524 && offset <= 0x9524))
+		return true;
 
-	for (i = 0, wa = wal->list; i < wal->count; i++, wa++)
-		fw |= intel_uncore_forcewake_for_reg(uncore,
-						     wa->reg,
-						     FW_REG_READ |
-						     FW_REG_WRITE);
+	return false;
+}
 
-	return fw;
+static bool l3_range(struct drm_i915_private *i915, u32 offset)
+{
+	/*
+	 * Registers in this range 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.
+	 */
+	if (INTEL_GEN(i915) >= 8 && (offset >= 0xb100 && offset <= 0xb3ff))
+		return true;
+
+	return false;
 }
 
 static bool
-wa_verify(const struct i915_wa *wa, u32 cur, const char *name, const char *from)
+__wa_verify(const struct i915_wa *wa, u32 cur, const char *name,
+	    const char *from)
 {
 	if ((cur ^ wa->val) & wa->read) {
 		DRM_ERROR("%s workaround lost on %s! (%x=%x/%x, expected %x, mask=%x)\n",
@@ -953,9 +964,113 @@ wa_verify(const struct i915_wa *wa, u32 cur, const char *name, const char *from)
 	return true;
 }
 
+static bool
+wa_verify(const struct i915_wa *wa, struct intel_uncore *uncore,
+	  const char *name, const char *from)
+{
+	struct drm_i915_private *i915 = uncore->i915;
+	u32 offset = i915_mmio_reg_offset(wa->reg);
+	bool ok = true;
+
+	if (INTEL_GEN(i915) >= 11 && slice_range(i915, offset)) {
+		const struct sseu_dev_info *sseu = &RUNTIME_INFO(i915)->sseu;
+		u32 old_mcr, mcr, mcr_mask, val;
+		unsigned int s, ss;
+
+		old_mcr = intel_uncore_read_fw(uncore, GEN8_MCR_SELECTOR);
+
+		for (s = 0; s < I915_MAX_SLICES; s++) {
+			if (!(BIT(s) & sseu->slice_mask))
+				continue;
+
+			for (ss = 0; ss < I915_MAX_SUBSLICES; ss++) {
+				if (!(BIT(ss) & sseu->subslice_mask[s]))
+					continue;
+
+				if (INTEL_GEN(i915) >= 11) {
+					mcr = GEN11_MCR_SLICE(s) |
+					      GEN11_MCR_SUBSLICE(ss);
+					mcr_mask = GEN11_MCR_SLICE_MASK |
+						   GEN11_MCR_SUBSLICE_MASK;
+				} else {
+					mcr = GEN8_MCR_SLICE(s) |
+					      GEN8_MCR_SUBSLICE(ss);
+					mcr_mask = GEN8_MCR_SLICE_MASK |
+						   GEN8_MCR_SUBSLICE_MASK;
+				}
+
+				mcr |= old_mcr & ~(BIT(31) | mcr_mask);
+				intel_uncore_write_fw(uncore,
+						      GEN8_MCR_SELECTOR,
+						      mcr);
+				val = intel_uncore_read_fw(uncore, wa->reg);
+				DRM_DEBUG_DRIVER("s:ss=%u:%u reg=%x val=%x mcr=%x (old_mcr=%x)\n",
+						 s, ss, offset, val, mcr,
+						 old_mcr);
+				ok &= __wa_verify(wa, val, name, from);
+			}
+		}
+
+		intel_uncore_write_fw(uncore, GEN8_MCR_SELECTOR, old_mcr);
+	} else if (INTEL_GEN(i915) >= 11 && l3_range(i915, offset) &&
+		   is_power_of_2(RUNTIME_INFO(i915)->sseu.slice_mask)) {
+		u32 l3_fuse = intel_uncore_read_fw(&i915->uncore,
+						   GEN10_MIRROR_FUSE3) &
+			      GEN10_L3BANK_MASK;
+		u32 l3_en = ~(l3_fuse << GEN10_L3BANK_PAIR_COUNT | l3_fuse);
+		u32 old_mcr, mcr, mcr_mask, val;
+		unsigned int b;
+
+		old_mcr = intel_uncore_read_fw(uncore, GEN8_MCR_SELECTOR);
+
+		for (b = 0; b < (GEN10_L3BANK_PAIR_COUNT * 2); b++) {
+			if (!(BIT(b) & l3_en))
+				continue;
+
+			mcr = GEN11_MCR_SLICE(0) | GEN11_MCR_SUBSLICE(b);
+			mcr_mask = GEN11_MCR_SLICE_MASK |
+				   GEN11_MCR_SUBSLICE_MASK;
+			mcr |= old_mcr & ~(BIT(31) | mcr_mask);
+			intel_uncore_write_fw(uncore,
+					      GEN8_MCR_SELECTOR,
+					      mcr);
+			val = intel_uncore_read_fw(uncore, wa->reg);
+			DRM_DEBUG_DRIVER("l3b=%u reg=%x val=%x mcr=%x (old_mcr=%x)\n",
+					 b, offset, val, mcr, old_mcr);
+			ok &= __wa_verify(wa, val, name, from);
+		}
+
+		intel_uncore_write_fw(uncore, GEN8_MCR_SELECTOR, old_mcr);
+	} else {
+		ok = __wa_verify(wa,
+				 intel_uncore_read_fw(uncore, wa->reg),
+				 name,
+				 from);
+	}
+
+	return ok;
+}
+
+static enum forcewake_domains
+wal_get_fw_for_rmw(struct intel_uncore *uncore, const struct i915_wa_list *wal)
+{
+	enum forcewake_domains fw = 0;
+	struct i915_wa *wa;
+	unsigned int i;
+
+	for (i = 0, wa = wal->list; i < wal->count; i++, wa++)
+		fw |= intel_uncore_forcewake_for_reg(uncore,
+						     wa->reg,
+						     FW_REG_READ |
+						     FW_REG_WRITE);
+
+	return fw;
+}
+
 static void
 wa_list_apply(struct intel_uncore *uncore, const struct i915_wa_list *wal)
 {
+	struct drm_i915_private *i915 = uncore->i915;
 	enum forcewake_domains fw;
 	unsigned long flags;
 	struct i915_wa *wa;
@@ -970,11 +1085,96 @@ wa_list_apply(struct intel_uncore *uncore, const struct i915_wa_list *wal)
 	intel_uncore_forcewake_get__locked(uncore, fw);
 
 	for (i = 0, wa = wal->list; i < wal->count; i++, wa++) {
-		intel_uncore_rmw_fw(uncore, wa->reg, wa->mask, wa->val);
-		if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
-			wa_verify(wa,
-				  intel_uncore_read_fw(uncore, wa->reg),
-				  wal->name, "application");
+		u32 offset = i915_mmio_reg_offset(wa->reg);
+
+		if (INTEL_GEN(i915) >= 11 && slice_range(i915, offset)) {
+			const struct sseu_dev_info *sseu =
+				&RUNTIME_INFO(i915)->sseu;
+			u32 old_mcr, mcr, mcr_mask, val;
+			unsigned int s, ss;
+
+			old_mcr = intel_uncore_read_fw(uncore,
+						       GEN8_MCR_SELECTOR);
+
+			for (s = 0; s < I915_MAX_SLICES; s++) {
+				if (!(BIT(s) & sseu->slice_mask))
+					continue;
+
+				for (ss = 0; ss < I915_MAX_SUBSLICES; ss++) {
+					if (!(BIT(ss) & sseu->subslice_mask[s]))
+						continue;
+
+					if (INTEL_GEN(i915) >= 11) {
+						mcr = GEN11_MCR_SLICE(s) |
+						      GEN11_MCR_SUBSLICE(ss);
+						mcr_mask =
+							GEN11_MCR_SLICE_MASK |
+							GEN11_MCR_SUBSLICE_MASK;
+					} else {
+						mcr = GEN8_MCR_SLICE(s) |
+						      GEN8_MCR_SUBSLICE(ss);
+						mcr_mask =
+							GEN8_MCR_SLICE_MASK |
+							GEN8_MCR_SUBSLICE_MASK;
+					}
+
+					mcr |= old_mcr & ~(BIT(31) | mcr_mask);
+					intel_uncore_write_fw(uncore,
+							      GEN8_MCR_SELECTOR,
+							      mcr);
+					intel_uncore_rmw_fw(uncore, wa->reg,
+							    wa->mask, wa->val);
+					val = intel_uncore_read_fw(uncore,
+								   wa->reg);
+					DRM_DEBUG_DRIVER("s:ss=%u:%u reg=%x val=%x mcr=%x (old_mcr=%x)\n",
+							s, ss, offset, val, mcr,
+							old_mcr);
+					if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
+						__wa_verify(wa, val,
+							    wal->name,
+							    "application");
+				}
+			}
+
+			intel_uncore_write_fw(uncore, GEN8_MCR_SELECTOR, old_mcr);
+		} else if (INTEL_GEN(i915) >= 11 && l3_range(i915, offset) &&
+			is_power_of_2(RUNTIME_INFO(i915)->sseu.slice_mask)) {
+			u32 l3_fuse = intel_uncore_read_fw(&i915->uncore,
+							GEN10_MIRROR_FUSE3) &
+				GEN10_L3BANK_MASK;
+			u32 l3_en = ~(l3_fuse << GEN10_L3BANK_PAIR_COUNT | l3_fuse);
+			u32 old_mcr, mcr, mcr_mask, val;
+			unsigned int b;
+
+			old_mcr = intel_uncore_read_fw(uncore, GEN8_MCR_SELECTOR);
+
+			for (b = 0; b < (GEN10_L3BANK_PAIR_COUNT * 2); b++) {
+				if (!(BIT(b) & l3_en))
+					continue;
+
+				mcr = GEN11_MCR_SLICE(0) | GEN11_MCR_SUBSLICE(b);
+				mcr_mask = GEN11_MCR_SLICE_MASK |
+					GEN11_MCR_SUBSLICE_MASK;
+				mcr |= old_mcr & ~(BIT(31) | mcr_mask);
+				intel_uncore_write_fw(uncore,
+						GEN8_MCR_SELECTOR,
+						mcr);
+				intel_uncore_rmw_fw(uncore, wa->reg, wa->mask,
+						    wa->val);
+				val = intel_uncore_read_fw(uncore, wa->reg);
+				DRM_DEBUG_DRIVER("l3b=%u reg=%x val=%x mcr=%x (old_mcr=%x)\n",
+						b, offset, val, mcr, old_mcr);
+				if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
+					__wa_verify(wa, val, wal->name,
+						    "application");
+			}
+
+			intel_uncore_write_fw(uncore, GEN8_MCR_SELECTOR, old_mcr);
+		} else {
+			intel_uncore_rmw_fw(uncore, wa->reg, wa->mask, wa->val);
+			if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
+				wa_verify(wa, uncore, wal->name, "application");
+		}
 	}
 
 	intel_uncore_forcewake_put__locked(uncore, fw);
@@ -990,14 +1190,22 @@ static bool wa_list_verify(struct intel_uncore *uncore,
 			   const struct i915_wa_list *wal,
 			   const char *from)
 {
+	enum forcewake_domains fw;
+	unsigned long flags;
 	struct i915_wa *wa;
 	unsigned int i;
 	bool ok = true;
 
+	fw = wal_get_fw_for_rmw(uncore, wal);
+
+	spin_lock_irqsave(&uncore->lock, flags);
+	intel_uncore_forcewake_get__locked(uncore, fw);
+
 	for (i = 0, wa = wal->list; i < wal->count; i++, wa++)
-		ok &= wa_verify(wa,
-				intel_uncore_read(uncore, wa->reg),
-				wal->name, from);
+		ok &= wa_verify(wa, uncore, wal->name, from);
+
+	intel_uncore_forcewake_put__locked(uncore, fw);
+	spin_unlock_irqrestore(&uncore->lock, flags);
 
 	return ok;
 }
@@ -1427,19 +1635,6 @@ create_scratch(struct i915_address_space *vm, int count)
 	return ERR_PTR(err);
 }
 
-static bool mcr_range(struct drm_i915_private *i915, u32 offset)
-{
-	/*
-	 * Registers in this range 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.
-	 */
-	if (INTEL_GEN(i915) >= 8 && (offset >= 0xb100 && offset <= 0xb3ff))
-		return true;
-
-	return false;
-}
-
 static int
 wa_list_srm(struct i915_request *rq,
 	    const struct i915_wa_list *wal,
@@ -1455,7 +1650,7 @@ wa_list_srm(struct i915_request *rq,
 		srm++;
 
 	for (i = 0, wa = wal->list; i < wal->count; i++, wa++) {
-		if (!mcr_range(i915, i915_mmio_reg_offset(wa->reg)))
+		if (!l3_range(i915, i915_mmio_reg_offset(wa->reg)))
 			count++;
 	}
 
@@ -1466,7 +1661,7 @@ wa_list_srm(struct i915_request *rq,
 	for (i = 0, wa = wal->list; i < wal->count; i++, wa++) {
 		u32 offset = i915_mmio_reg_offset(wa->reg);
 
-		if (mcr_range(i915, offset))
+		if (l3_range(i915, offset))
 			continue;
 
 		*cs++ = srm;
@@ -1521,10 +1716,10 @@ static int engine_wa_list_verify(struct intel_context *ce,
 
 	err = 0;
 	for (i = 0, wa = wal->list; i < wal->count; i++, wa++) {
-		if (mcr_range(rq->i915, i915_mmio_reg_offset(wa->reg)))
+		if (l3_range(rq->i915, i915_mmio_reg_offset(wa->reg)))
 			continue;
 
-		if (!wa_verify(wa, results[i], wal->name, from))
+		if (!__wa_verify(wa, results[i], wal->name, from))
 			err = -ENXIO;
 	}
 
@@ -1539,9 +1734,22 @@ static int engine_wa_list_verify(struct intel_context *ce,
 int intel_engine_verify_workarounds(struct intel_engine_cs *engine,
 				    const char *from)
 {
-	return engine_wa_list_verify(engine->kernel_context,
-				     &engine->wa_list,
-				     from);
+	int ret;
+
+	ret = wa_list_verify(engine->uncore, &engine->wa_list, from) ?
+	      0 : -ENXIO;
+	if (ret)
+		DRM_ERROR("%s mmio workaround verification failed!\n",
+			  engine->name);
+
+	ret = engine_wa_list_verify(engine->kernel_context,
+				    &engine->wa_list,
+				    from);
+	if (ret)
+		DRM_ERROR("%s cs workaround verification failed!\n",
+			engine->name);
+
+	return ret;
 }
 
 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
-- 
2.20.1



More information about the Intel-gfx-trybot mailing list