aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2018-06-15 13:02:07 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2018-06-15 13:27:04 +0100
commit548764bb7ce050afdba15892fb4add79d15974db (patch)
tree9e5c1e5b0acdd7507b7d7c42f5218cca1bab836d
parentdrm/i915/dp: Add support for HBR3 and TPS4 during link training (diff)
downloadlinux-dev-548764bb7ce050afdba15892fb4add79d15974db.tar.xz
linux-dev-548764bb7ce050afdba15892fb4add79d15974db.zip
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
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c25
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h2
-rw-r--r--drivers/gpu/drm/i915/intel_workarounds.c63
3 files changed, 52 insertions, 38 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 99d3272d82d8..c400f42a54ec 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -3378,28 +3378,13 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused)
static int i915_wa_registers(struct seq_file *m, void *unused)
{
- struct drm_i915_private *dev_priv = node_to_i915(m->private);
- struct i915_workarounds *workarounds = &dev_priv->workarounds;
+ struct i915_workarounds *wa = &node_to_i915(m->private)->workarounds;
int i;
- intel_runtime_pm_get(dev_priv);
-
- seq_printf(m, "Workarounds applied: %d\n", workarounds->count);
- for (i = 0; i < workarounds->count; ++i) {
- i915_reg_t addr;
- u32 mask, value, read;
- bool ok;
-
- addr = workarounds->reg[i].addr;
- mask = workarounds->reg[i].mask;
- value = workarounds->reg[i].value;
- read = I915_READ(addr);
- ok = (value & mask) == (read & mask);
- seq_printf(m, "0x%X: 0x%08X, mask: 0x%08X, read: 0x%08x, status: %s\n",
- i915_mmio_reg_offset(addr), value, mask, read, ok ? "OK" : "FAIL");
- }
-
- intel_runtime_pm_put(dev_priv);
+ seq_printf(m, "Workarounds applied: %d\n", wa->count);
+ for (i = 0; i < wa->count; ++i)
+ seq_printf(m, "0x%X: 0x%08X, mask: 0x%08X\n",
+ wa->reg[i].addr, wa->reg[i].value, wa->reg[i].mask);
return 0;
}
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 74dd88d8563e..ea389771f917 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1305,7 +1305,7 @@ struct i915_frontbuffer_tracking {
};
struct i915_wa_reg {
- i915_reg_t addr;
+ u32 addr;
u32 value;
/* bitmask representing WA bits */
u32 mask;
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;