[PATCH] do not rely on multicast
Tvrtko Ursulin
tvrtko.ursulin at linux.intel.com
Wed Jul 24 07:08:35 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 | 287 +++++++++++++++++---
1 file changed, 247 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..362d1bcc6964 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,21 @@ 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);
+ bool ok = true;
+
+ ok &= wa_list_verify(engine->uncore, &engine->wa_list, from);
+ if (!ok)
+ DRM_ERROR("%s mmio workaround verification failed!\n",
+ engine->name);
+
+ ok = engine_wa_list_verify(engine->kernel_context,
+ &engine->wa_list,
+ from) == 0;
+ if (!ok)
+ DRM_ERROR("%s cs workaround verification failed!\n",
+ engine->name);
+
+ return ok;
}
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
--
2.20.1
More information about the Intel-gfx-trybot
mailing list