From: Matt Roper <matthew.d.roper@intel.com>
To: intel-gfx@lists.freedesktop.org
Cc: chris@chris-wilson.co.uk
Subject: [Intel-gfx] [PATCH 2/4] drm/i915: Steer multicast register readback in wa_verify
Date: Thu, 30 Apr 2020 16:15:27 -0700 [thread overview]
Message-ID: <20200430231529.295556-3-matthew.d.roper@intel.com> (raw)
In-Reply-To: <20200430231529.295556-1-matthew.d.roper@intel.com>
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@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
next prev parent reply other threads:[~2020-04-30 23:16 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-04-30 23:15 [Intel-gfx] [PATCH 0/4] Steer multicast register workaround verification Matt Roper
2020-04-30 23:15 ` [Intel-gfx] [PATCH 1/4] drm/i915: Setup multicast register steering for all gen >= 10 Matt Roper
2020-04-30 23:15 ` Matt Roper [this message]
2020-04-30 23:15 ` [Intel-gfx] [PATCH 3/4] drm/i915: Don't skip verification of MCR engine workarounds Matt Roper
2020-04-30 23:15 ` [Intel-gfx] [PATCH 4/4] drm/i915: Add MCR ranges for gen11 and gen12 Matt Roper
2020-05-01 0:03 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for Steer multicast register workaround verification Patchwork
2020-05-01 0:21 ` [Intel-gfx] ✗ Fi.CI.BAT: failure " Patchwork
2020-05-01 8:01 ` [Intel-gfx] [PATCH 0/4] " Tvrtko Ursulin
2020-05-01 16:05 ` Matt Roper
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200430231529.295556-3-matthew.d.roper@intel.com \
--to=matthew.d.roper@intel.com \
--cc=chris@chris-wilson.co.uk \
--cc=intel-gfx@lists.freedesktop.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox