[PATCH 3/3] wa

Tvrtko Ursulin tvrtko.ursulin at linux.intel.com
Tue Apr 27 12:35:09 UTC 2021


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   | 81 +++++++++++++++----
 .../gpu/drm/i915/gt/intel_workarounds_types.h |  4 +
 .../gpu/drm/i915/gt/selftest_workarounds.c    |  4 +-
 3 files changed, 70 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
index 8513d7896e6d..481e20684f71 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
@@ -52,8 +52,11 @@
  * - Public functions to init or apply the given workaround type.
  */
 
-static void wa_init_start(struct i915_wa_list *wal, const char *name, const char *engine_name)
+static void
+wa_init_start(struct drm_i915_private *i915, struct i915_wa_list *wal,
+	      const char *name, const char *engine_name)
 {
+	wal->i915 = i915;
 	wal->name = name;
 	wal->engine_name = engine_name;
 }
@@ -81,6 +84,55 @@ static void wa_init_finish(struct i915_wa_list *wal)
 			 wal->wa_count, wal->name, wal->engine_name);
 }
 
+static void
+log_bad_wa(const struct i915_wa_list *wal, const struct i915_wa *wa,
+	   const char *msg)
+{
+	drm_err(&wal->i915->drm,
+		"Discarding %s workaround! (reg=%x %s=%x set=%x)\n",
+		msg, i915_mmio_reg_offset(wa->reg), wa->mask ? "mask" : "clear",
+		wa->mask ?: wa->clr, wa->set);
+}
+
+static bool
+check_conflict(const struct i915_wa_list *wal,
+	       const struct i915_wa *old,
+	       const struct i915_wa *new)
+{
+	u32 new_mask, old_mask, common;
+
+	if (new->clr && new->mask) {
+		log_bad_wa(wal, new, "mixed masked and regular");
+		return true;
+	}
+
+	if (new->set && new->clr && (new->set & ~new->clr)) {
+		log_bad_wa(wal, new, "write outside the mask");
+		return true;
+	}
+
+	if (new->mask) {
+		new_mask = new->mask;
+		old_mask = old->mask;
+	} else {
+		new_mask = new->clr;
+		old_mask = old->clr;
+	}
+
+	common = new_mask & old_mask;
+	if (common) {
+		if ((new->set & common) != (old->set & common)) {
+			log_bad_wa(wal, new, "conflicting");
+			return true;
+		} else if (new_mask == old_mask) {
+			log_bad_wa(wal, new, "duplicate");
+			return true;
+		}
+	}
+
+	return false;
+}
+
 static void _wa_add(struct i915_wa_list *wal, const struct i915_wa *wa)
 {
 	unsigned int addr = i915_mmio_reg_offset(wa->reg);
@@ -118,19 +170,14 @@ static void _wa_add(struct i915_wa_list *wal, const struct i915_wa *wa)
 		} else {
 			wa_ = &wal->list[mid];
 
-			if ((wa->clr | wa_->clr) && !(wa->clr & ~wa_->clr)) {
-				DRM_ERROR("Discarding overwritten w/a for reg %04x (clear: %08x, set: %08x)\n",
-					  i915_mmio_reg_offset(wa_->reg),
-					  wa_->clr, wa_->set);
-
-				wa_->set &= ~wa->clr;
+			if (!check_conflict(wal, wa_, wa)) {
+				wal->wa_count++;
+				wa_->set |= wa->set;
+				wa_->clr |= wa->clr;
+				wa_->mask |= wa->mask;
+				wa_->read |= wa->read;
+				return;
 			}
-
-			wal->wa_count++;
-			wa_->set |= wa->set;
-			wa_->clr |= wa->clr;
-			wa_->read |= wa->read;
-			return;
 		}
 	}
 
@@ -708,7 +755,7 @@ __intel_engine_init_ctx_wa(struct intel_engine_cs *engine,
 	if (engine->class != RENDER_CLASS)
 		return;
 
-	wa_init_start(wal, name, engine->name);
+	wa_init_start(engine->i915, wal, name, engine->name);
 
 	if (IS_DG1(i915))
 		dg1_ctx_workarounds_init(engine, wal);
@@ -1224,7 +1271,7 @@ void intel_gt_init_workarounds(struct drm_i915_private *i915)
 {
 	struct i915_wa_list *wal = &i915->gt_wa_list;
 
-	wa_init_start(wal, "GT", "global");
+	wa_init_start(i915, wal, "GT", "global");
 	gt_init_workarounds(i915, wal);
 	wa_init_finish(wal);
 }
@@ -1567,7 +1614,7 @@ void intel_engine_init_whitelist(struct intel_engine_cs *engine)
 	struct drm_i915_private *i915 = engine->i915;
 	struct i915_wa_list *w = &engine->whitelist;
 
-	wa_init_start(w, "whitelist", engine->name);
+	wa_init_start(engine->i915, w, "whitelist", engine->name);
 
 	if (IS_DG1(i915))
 		dg1_whitelist_build(engine);
@@ -2088,7 +2135,7 @@ void intel_engine_init_workarounds(struct intel_engine_cs *engine)
 	if (INTEL_GEN(engine->i915) < 4)
 		return;
 
-	wa_init_start(wal, "engine", engine->name);
+	wa_init_start(engine->i915, wal, "engine", engine->name);
 	engine_init_workarounds(engine, wal);
 	wa_init_finish(wal);
 }
diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds_types.h b/drivers/gpu/drm/i915/gt/intel_workarounds_types.h
index 9abe077435f2..f4d9e7625ec3 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds_types.h
@@ -10,6 +10,8 @@
 
 #include "i915_reg.h"
 
+struct drm_i915_private;
+
 struct i915_wa {
 	i915_reg_t	reg;
 	u32		clr;
@@ -19,6 +21,8 @@ struct i915_wa {
 };
 
 struct i915_wa_list {
+	struct drm_i915_private *i915;
+
 	const char	*name;
 	const char	*engine_name;
 	struct i915_wa	*list;
diff --git a/drivers/gpu/drm/i915/gt/selftest_workarounds.c b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
index 64937ec3f2dc..536cbe7889cc 100644
--- a/drivers/gpu/drm/i915/gt/selftest_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
@@ -64,14 +64,14 @@ reference_lists_init(struct intel_gt *gt, struct wa_lists *lists)
 
 	memset(lists, 0, sizeof(*lists));
 
-	wa_init_start(&lists->gt_wa_list, "GT_REF", "global");
+	wa_init_start(gt->i915, &lists->gt_wa_list, "GT_REF", "global");
 	gt_init_workarounds(gt->i915, &lists->gt_wa_list);
 	wa_init_finish(&lists->gt_wa_list);
 
 	for_each_engine(engine, gt, id) {
 		struct i915_wa_list *wal = &lists->engine[id].wa_list;
 
-		wa_init_start(wal, "REF", engine->name);
+		wa_init_start(gt->i915, wal, "REF", engine->name);
 		engine_init_workarounds(engine, wal);
 		wa_init_finish(wal);
 
-- 
2.30.2



More information about the Intel-gfx-trybot mailing list