[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