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 <[email protected]>
Cc: Oscar Mateo <[email protected]>
Cc: Mika Kuoppala <[email protected]>
Cc: Joonas Lahtinen <[email protected]>
Reviewed-by: Mika Kuoppala <[email protected]>
---
 drivers/gpu/drm/i915/i915_debugfs.c      | 25 ++--------
 drivers/gpu/drm/i915/i915_drv.h          |  2 +-
 drivers/gpu/drm/i915/intel_workarounds.c | 63 +++++++++++++++++-------
 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;
-- 
2.17.1

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to