aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2018-06-15 08:02:07 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2018-06-15 08:27:04 -0400
commit548764bb7ce050afdba15892fb4add79d15974db (patch)
tree9e5c1e5b0acdd7507b7d7c42f5218cca1bab836d
parent2edd53272120ea3fd32193ef7f921580a534e218 (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
-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)
3378 3378
3379static int i915_wa_registers(struct seq_file *m, void *unused) 3379static int i915_wa_registers(struct seq_file *m, void *unused)
3380{ 3380{
3381 struct drm_i915_private *dev_priv = node_to_i915(m->private); 3381 struct i915_workarounds *wa = &node_to_i915(m->private)->workarounds;
3382 struct i915_workarounds *workarounds = &dev_priv->workarounds;
3383 int i; 3382 int i;
3384 3383
3385 intel_runtime_pm_get(dev_priv); 3384 seq_printf(m, "Workarounds applied: %d\n", wa->count);
3386 3385 for (i = 0; i < wa->count; ++i)
3387 seq_printf(m, "Workarounds applied: %d\n", workarounds->count); 3386 seq_printf(m, "0x%X: 0x%08X, mask: 0x%08X\n",
3388 for (i = 0; i < workarounds->count; ++i) { 3387 wa->reg[i].addr, wa->reg[i].value, wa->reg[i].mask);
3389 i915_reg_t addr;
3390 u32 mask, value, read;
3391 bool ok;
3392
3393 addr = workarounds->reg[i].addr;
3394 mask = workarounds->reg[i].mask;
3395 value = workarounds->reg[i].value;
3396 read = I915_READ(addr);
3397 ok = (value & mask) == (read & mask);
3398 seq_printf(m, "0x%X: 0x%08X, mask: 0x%08X, read: 0x%08x, status: %s\n",
3399 i915_mmio_reg_offset(addr), value, mask, read, ok ? "OK" : "FAIL");
3400 }
3401
3402 intel_runtime_pm_put(dev_priv);
3403 3388
3404 return 0; 3389 return 0;
3405} 3390}
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 {
1305}; 1305};
1306 1306
1307struct i915_wa_reg { 1307struct i915_wa_reg {
1308 i915_reg_t addr; 1308 u32 addr;
1309 u32 value; 1309 u32 value;
1310 /* bitmask representing WA bits */ 1310 /* bitmask representing WA bits */
1311 u32 mask; 1311 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 @@
48 * - Public functions to init or apply the given workaround type. 48 * - Public functions to init or apply the given workaround type.
49 */ 49 */
50 50
51static int wa_add(struct drm_i915_private *dev_priv, 51static void wa_add(struct drm_i915_private *i915,
52 i915_reg_t addr, 52 i915_reg_t reg, const u32 mask, const u32 val)
53 const u32 mask, const u32 val)
54{ 53{
55 const unsigned int idx = dev_priv->workarounds.count; 54 struct i915_workarounds *wa = &i915->workarounds;
55 unsigned int start = 0, end = wa->count;
56 unsigned int addr = i915_mmio_reg_offset(reg);
57 struct i915_wa_reg *r;
58
59 while (start < end) {
60 unsigned int mid = start + (end - start) / 2;
61
62 if (wa->reg[mid].addr < addr) {
63 start = mid + 1;
64 } else if (wa->reg[mid].addr > addr) {
65 end = mid;
66 } else {
67 r = &wa->reg[mid];
68
69 if ((mask & ~r->mask) == 0) {
70 DRM_ERROR("Discarding overwritten w/a for reg %04x (mask: %08x, value: %08x)\n",
71 addr, r->mask, r->value);
72
73 r->value &= ~mask;
74 }
75
76 r->value |= val;
77 r->mask |= mask;
78 return;
79 }
80 }
56 81
57 if (WARN_ON(idx >= I915_MAX_WA_REGS)) 82 if (WARN_ON_ONCE(wa->count >= I915_MAX_WA_REGS)) {
58 return -ENOSPC; 83 DRM_ERROR("Dropping w/a for reg %04x (mask: %08x, value: %08x)\n",
84 addr, mask, val);
85 return;
86 }
59 87
60 dev_priv->workarounds.reg[idx].addr = addr; 88 r = &wa->reg[wa->count++];
61 dev_priv->workarounds.reg[idx].value = val; 89 r->addr = addr;
62 dev_priv->workarounds.reg[idx].mask = mask; 90 r->value = val;
91 r->mask = mask;
63 92
64 dev_priv->workarounds.count++; 93 while (r-- > wa->reg) {
94 GEM_BUG_ON(r[0].addr == r[1].addr);
95 if (r[1].addr > r[0].addr)
96 break;
65 97
66 return 0; 98 swap(r[1], r[0]);
99 }
67} 100}
68 101
69#define WA_REG(addr, mask, val) do { \ 102#define WA_REG(addr, mask, val) wa_add(dev_priv, (addr), (mask), (val))
70 const int r = wa_add(dev_priv, (addr), (mask), (val)); \
71 if (r) \
72 return r; \
73 } while (0)
74 103
75#define WA_SET_BIT_MASKED(addr, mask) \ 104#define WA_SET_BIT_MASKED(addr, mask) \
76 WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask)) 105 WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask))
@@ -540,7 +569,7 @@ int intel_ctx_workarounds_emit(struct i915_request *rq)
540 569
541 *cs++ = MI_LOAD_REGISTER_IMM(w->count); 570 *cs++ = MI_LOAD_REGISTER_IMM(w->count);
542 for (i = 0; i < w->count; i++) { 571 for (i = 0; i < w->count; i++) {
543 *cs++ = i915_mmio_reg_offset(w->reg[i].addr); 572 *cs++ = w->reg[i].addr;
544 *cs++ = w->reg[i].value; 573 *cs++ = w->reg[i].value;
545 } 574 }
546 *cs++ = MI_NOOP; 575 *cs++ = MI_NOOP;