diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2018-06-15 13:02:07 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2018-06-15 13:27:04 +0100 |
commit | 548764bb7ce050afdba15892fb4add79d15974db (patch) | |
tree | 9e5c1e5b0acdd7507b7d7c42f5218cca1bab836d /drivers/gpu/drm/i915/intel_workarounds.c | |
parent | 2edd53272120ea3fd32193ef7f921580a534e218 (diff) |
drm/i915: Keep the ctx workarounds tightly packed
For each platform, we have a few registers that are rewritten with
different values -- they are not part of a sequence, just different parts
of a masked register set at different times (e.g. platform and gen
workarounds). Consolidate these into a single register write to keep the
table compact, important since we are running of room in the current
fixed sized buffer.
While adjusting the construction of the wa table, make it non fatal so
that the driver still loads but keeping the warning and extra details
for inspection.
Inspecting the changes for a Kabylake system,
Before:
Address val mask read
0x07014 0x20002000 0x00002000 0x00002100
0x0E194 0x01000100 0x00000100 0x00000114
0x0E4F0 0x81008100 0x00008100 0xFFFF8120
0x0E184 0x00200020 0x00000020 0x00000022
0x0E194 0x00140014 0x00000014 0x00000114
0x07004 0x00420042 0x00000042 0x000029C2
0x0E188 0x00080000 0x00000008 0x00008030
0x07300 0x80208020 0x00008020 0x00008830
0x07300 0x00100010 0x00000010 0x00008830
0x0E184 0x00020002 0x00000002 0x00000022
0x0E180 0x20002000 0x00002000 0x00002000
0x02580 0x00010000 0x00000001 0x00000004
0x02580 0x00060004 0x00000006 0x00000004
0x07014 0x01000100 0x00000100 0x00002100
0x0E100 0x00100010 0x00000010 0x00008050
After:
Address val mask read
0x02580 0x00070004 0x00000007 0x00000004
0x07004 0x00420042 0x00000042 0x000029C2
0x07014 0x21002100 0x00002100 0x00002100
0x07300 0x80308030 0x00008030 0x00008830
0x0E100 0x00100010 0x00000010 0x00008050
0x0E180 0x20002000 0x00002000 0x00002000
0x0E184 0x00220022 0x00000022 0x00000022
0x0E188 0x00080000 0x00000008 0x00008030
0x0E194 0x01140114 0x00000114 0x00000114
0x0E4F0 0x81008100 0x00008100 0xFFFF8120
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Oscar Mateo <oscar.mateo@intel.com>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180615120207.13952-1-chris@chris-wilson.co.uk
Diffstat (limited to 'drivers/gpu/drm/i915/intel_workarounds.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_workarounds.c | 63 |
1 files changed, 46 insertions, 17 deletions
diff --git a/drivers/gpu/drm/i915/intel_workarounds.c b/drivers/gpu/drm/i915/intel_workarounds.c index 24b929ce3341..f8bb32e974f6 100644 --- a/drivers/gpu/drm/i915/intel_workarounds.c +++ b/drivers/gpu/drm/i915/intel_workarounds.c @@ -48,29 +48,58 @@ * - Public functions to init or apply the given workaround type. */ -static int wa_add(struct drm_i915_private *dev_priv, - i915_reg_t addr, - const u32 mask, const u32 val) +static void wa_add(struct drm_i915_private *i915, + i915_reg_t reg, const u32 mask, const u32 val) { - const unsigned int idx = dev_priv->workarounds.count; + struct i915_workarounds *wa = &i915->workarounds; + unsigned int start = 0, end = wa->count; + unsigned int addr = i915_mmio_reg_offset(reg); + struct i915_wa_reg *r; + + while (start < end) { + unsigned int mid = start + (end - start) / 2; + + if (wa->reg[mid].addr < addr) { + start = mid + 1; + } else if (wa->reg[mid].addr > addr) { + end = mid; + } else { + r = &wa->reg[mid]; + + if ((mask & ~r->mask) == 0) { + DRM_ERROR("Discarding overwritten w/a for reg %04x (mask: %08x, value: %08x)\n", + addr, r->mask, r->value); + + r->value &= ~mask; + } + + r->value |= val; + r->mask |= mask; + return; + } + } - if (WARN_ON(idx >= I915_MAX_WA_REGS)) - return -ENOSPC; + if (WARN_ON_ONCE(wa->count >= I915_MAX_WA_REGS)) { + DRM_ERROR("Dropping w/a for reg %04x (mask: %08x, value: %08x)\n", + addr, mask, val); + return; + } - dev_priv->workarounds.reg[idx].addr = addr; - dev_priv->workarounds.reg[idx].value = val; - dev_priv->workarounds.reg[idx].mask = mask; + r = &wa->reg[wa->count++]; + r->addr = addr; + r->value = val; + r->mask = mask; - dev_priv->workarounds.count++; + while (r-- > wa->reg) { + GEM_BUG_ON(r[0].addr == r[1].addr); + if (r[1].addr > r[0].addr) + break; - return 0; + swap(r[1], r[0]); + } } -#define WA_REG(addr, mask, val) do { \ - const int r = wa_add(dev_priv, (addr), (mask), (val)); \ - if (r) \ - return r; \ - } while (0) +#define WA_REG(addr, mask, val) wa_add(dev_priv, (addr), (mask), (val)) #define WA_SET_BIT_MASKED(addr, mask) \ WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask)) @@ -540,7 +569,7 @@ int intel_ctx_workarounds_emit(struct i915_request *rq) *cs++ = MI_LOAD_REGISTER_IMM(w->count); for (i = 0; i < w->count; i++) { - *cs++ = i915_mmio_reg_offset(w->reg[i].addr); + *cs++ = w->reg[i].addr; *cs++ = w->reg[i].value; } *cs++ = MI_NOOP; |