Commit eeec73f8 authored by Chris Wilson's avatar Chris Wilson

drm/i915/gt: Skip rmw for masked registers

A masked register does not need rmw to update, and it is best not to use
such a sequence.
Reported-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: default avatarTvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200131235035.3522102-1-chris@chris-wilson.co.uk
parent faea1792
...@@ -116,17 +116,17 @@ static void _wa_add(struct i915_wa_list *wal, const struct i915_wa *wa) ...@@ -116,17 +116,17 @@ static void _wa_add(struct i915_wa_list *wal, const struct i915_wa *wa)
} else { } else {
wa_ = &wal->list[mid]; wa_ = &wal->list[mid];
if ((wa->mask & ~wa_->mask) == 0) { if ((wa->clr | wa_->clr) && !(wa->clr & ~wa_->clr)) {
DRM_ERROR("Discarding overwritten w/a for reg %04x (mask: %08x, value: %08x)\n", DRM_ERROR("Discarding overwritten w/a for reg %04x (clear: %08x, set: %08x)\n",
i915_mmio_reg_offset(wa_->reg), i915_mmio_reg_offset(wa_->reg),
wa_->mask, wa_->val); wa_->clr, wa_->set);
wa_->val &= ~wa->mask; wa_->set &= ~wa->clr;
} }
wal->wa_count++; wal->wa_count++;
wa_->val |= wa->val; wa_->set |= wa->set;
wa_->mask |= wa->mask; wa_->clr |= wa->clr;
wa_->read |= wa->read; wa_->read |= wa->read;
return; return;
} }
...@@ -147,13 +147,13 @@ static void _wa_add(struct i915_wa_list *wal, const struct i915_wa *wa) ...@@ -147,13 +147,13 @@ static void _wa_add(struct i915_wa_list *wal, const struct i915_wa *wa)
} }
} }
static void wa_add(struct i915_wa_list *wal, i915_reg_t reg, u32 mask, static void wa_add(struct i915_wa_list *wal, i915_reg_t reg,
u32 val, u32 read_mask) u32 clear, u32 set, u32 read_mask)
{ {
struct i915_wa wa = { struct i915_wa wa = {
.reg = reg, .reg = reg,
.mask = mask, .clr = clear,
.val = val, .set = set,
.read = read_mask, .read = read_mask,
}; };
...@@ -161,38 +161,43 @@ static void wa_add(struct i915_wa_list *wal, i915_reg_t reg, u32 mask, ...@@ -161,38 +161,43 @@ static void wa_add(struct i915_wa_list *wal, i915_reg_t reg, u32 mask,
} }
static void static void
wa_write_masked_or(struct i915_wa_list *wal, i915_reg_t reg, u32 mask, wa_write_masked_or(struct i915_wa_list *wal, i915_reg_t reg, u32 clear, u32 set)
u32 val)
{ {
wa_add(wal, reg, mask, val, mask); wa_add(wal, reg, clear, set, clear);
} }
static void static void
wa_masked_en(struct i915_wa_list *wal, i915_reg_t reg, u32 val) wa_write(struct i915_wa_list *wal, i915_reg_t reg, u32 set)
{
wa_write_masked_or(wal, reg, ~0, set);
}
static void
wa_write_or(struct i915_wa_list *wal, i915_reg_t reg, u32 set)
{ {
wa_write_masked_or(wal, reg, val, _MASKED_BIT_ENABLE(val)); wa_write_masked_or(wal, reg, set, set);
} }
static void static void
wa_write(struct i915_wa_list *wal, i915_reg_t reg, u32 val) wa_masked_en(struct i915_wa_list *wal, i915_reg_t reg, u32 val)
{ {
wa_write_masked_or(wal, reg, ~0, val); wa_add(wal, reg, 0, _MASKED_BIT_ENABLE(val), val);
} }
static void static void
wa_write_or(struct i915_wa_list *wal, i915_reg_t reg, u32 val) wa_masked_dis(struct i915_wa_list *wal, i915_reg_t reg, u32 val)
{ {
wa_write_masked_or(wal, reg, val, val); wa_add(wal, reg, 0, _MASKED_BIT_DISABLE(val), val);
} }
#define WA_SET_BIT_MASKED(addr, mask) \ #define WA_SET_BIT_MASKED(addr, mask) \
wa_write_masked_or(wal, (addr), (mask), _MASKED_BIT_ENABLE(mask)) wa_masked_en(wal, (addr), (mask))
#define WA_CLR_BIT_MASKED(addr, mask) \ #define WA_CLR_BIT_MASKED(addr, mask) \
wa_write_masked_or(wal, (addr), (mask), _MASKED_BIT_DISABLE(mask)) wa_masked_dis(wal, (addr), (mask))
#define WA_SET_FIELD_MASKED(addr, mask, value) \ #define WA_SET_FIELD_MASKED(addr, mask, value) \
wa_write_masked_or(wal, (addr), (mask), _MASKED_FIELD((mask), (value))) wa_write_masked_or(wal, (addr), 0, _MASKED_FIELD((mask), (value)))
static void gen8_ctx_workarounds_init(struct intel_engine_cs *engine, static void gen8_ctx_workarounds_init(struct intel_engine_cs *engine,
struct i915_wa_list *wal) struct i915_wa_list *wal)
...@@ -662,7 +667,7 @@ int intel_engine_emit_ctx_wa(struct i915_request *rq) ...@@ -662,7 +667,7 @@ int intel_engine_emit_ctx_wa(struct i915_request *rq)
*cs++ = MI_LOAD_REGISTER_IMM(wal->count); *cs++ = MI_LOAD_REGISTER_IMM(wal->count);
for (i = 0, wa = wal->list; i < wal->count; i++, wa++) { for (i = 0, wa = wal->list; i < wal->count; i++, wa++) {
*cs++ = i915_mmio_reg_offset(wa->reg); *cs++ = i915_mmio_reg_offset(wa->reg);
*cs++ = wa->val; *cs++ = wa->set;
} }
*cs++ = MI_NOOP; *cs++ = MI_NOOP;
...@@ -991,11 +996,10 @@ wal_get_fw_for_rmw(struct intel_uncore *uncore, const struct i915_wa_list *wal) ...@@ -991,11 +996,10 @@ wal_get_fw_for_rmw(struct intel_uncore *uncore, const struct i915_wa_list *wal)
static bool 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) { if ((cur ^ wa->set) & wa->read) {
DRM_ERROR("%s workaround lost on %s! (%x=%x/%x, expected %x, mask=%x)\n", DRM_ERROR("%s workaround lost on %s! (%x=%x/%x, expected %x)\n",
name, from, i915_mmio_reg_offset(wa->reg), name, from, i915_mmio_reg_offset(wa->reg),
cur, cur & wa->read, cur, cur & wa->read, wa->set);
wa->val, wa->mask);
return false; return false;
} }
...@@ -1020,7 +1024,10 @@ wa_list_apply(struct intel_uncore *uncore, const struct i915_wa_list *wal) ...@@ -1020,7 +1024,10 @@ wa_list_apply(struct intel_uncore *uncore, const struct i915_wa_list *wal)
intel_uncore_forcewake_get__locked(uncore, fw); intel_uncore_forcewake_get__locked(uncore, fw);
for (i = 0, wa = wal->list; i < wal->count; i++, wa++) { for (i = 0, wa = wal->list; i < wal->count; i++, wa++) {
intel_uncore_rmw_fw(uncore, wa->reg, wa->mask, wa->val); if (wa->clr)
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)) if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
wa_verify(wa, wa_verify(wa,
intel_uncore_read_fw(uncore, wa->reg), intel_uncore_read_fw(uncore, wa->reg),
......
...@@ -13,8 +13,8 @@ ...@@ -13,8 +13,8 @@
struct i915_wa { struct i915_wa {
i915_reg_t reg; i915_reg_t reg;
u32 mask; u32 clr;
u32 val; u32 set;
u32 read; u32 read;
}; };
......
...@@ -2803,7 +2803,7 @@ static int i915_wa_registers(struct seq_file *m, void *unused) ...@@ -2803,7 +2803,7 @@ static int i915_wa_registers(struct seq_file *m, void *unused)
for (wa = wal->list; count--; wa++) for (wa = wal->list; count--; wa++)
seq_printf(m, "0x%X: 0x%08X, mask: 0x%08X\n", seq_printf(m, "0x%X: 0x%08X, mask: 0x%08X\n",
i915_mmio_reg_offset(wa->reg), i915_mmio_reg_offset(wa->reg),
wa->val, wa->mask); wa->set, wa->clr);
seq_printf(m, "\n"); seq_printf(m, "\n");
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment