drm/i915: keep track of used entries in MOCS table
authorLucas De Marchi <lucas.demarchi@intel.com>
Thu, 24 Jan 2019 00:06:02 +0000 (16:06 -0800)
committerLucas De Marchi <lucas.demarchi@intel.com>
Fri, 25 Jan 2019 03:34:34 +0000 (19:34 -0800)
Instead of considering we have defined entries for any index in the
table, let's keep track of the ones we explicitly defined. This will
allow Gen 11 to have it's new table defined in which we have holes of
undefined entries.

Repeated comments about the meaning of undefined entries were removed
since they are overly verbose and copy-pasted in several functions: now
the definition is in the top only.

v2: add helper function to get the index (from Chris)

Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: https://patchwork.freedesktop.org/patch/msgid/20190124000604.18861-6-lucas.demarchi@intel.com
drivers/gpu/drm/i915/intel_mocs.c

index 59dd747..e5f0e9d 100644 (file)
@@ -28,6 +28,7 @@
 struct drm_i915_mocs_entry {
        u32 control_value;
        u16 l3cc_value;
+       u16 used;
 };
 
 struct drm_i915_mocs_table {
@@ -75,6 +76,7 @@ struct drm_i915_mocs_table {
        [__idx] = { \
                .control_value = __control_value, \
                .l3cc_value = __l3cc_value, \
+               .used = 1, \
        }
 
 /*
@@ -187,6 +189,19 @@ static i915_reg_t mocs_register(enum intel_engine_id engine_id, int index)
        }
 }
 
+/*
+ * Get control_value from MOCS entry taking into account when it's not used:
+ * I915_MOCS_PTE's value is returned in this case.
+ */
+static u32 get_entry_control(const struct drm_i915_mocs_table *table,
+                            unsigned int index)
+{
+       if (table->table[index].used)
+               return table->table[index].control_value;
+
+       return table->table[I915_MOCS_PTE].control_value;
+}
+
 /**
  * intel_mocs_init_engine() - emit the mocs control table
  * @engine:    The engine for whom to emit the registers.
@@ -199,24 +214,25 @@ void intel_mocs_init_engine(struct intel_engine_cs *engine)
        struct drm_i915_private *dev_priv = engine->i915;
        struct drm_i915_mocs_table table;
        unsigned int index;
+       u32 unused_value;
 
        if (!get_mocs_settings(dev_priv, &table))
                return;
 
        GEM_BUG_ON(table.size > GEN9_NUM_MOCS_ENTRIES);
 
-       for (index = 0; index < table.size; index++)
-               I915_WRITE(mocs_register(engine->id, index),
-                          table.table[index].control_value);
+       /* Set unused values to PTE */
+       unused_value = table.table[I915_MOCS_PTE].control_value;
+
+       for (index = 0; index < table.size; index++) {
+               u32 value = get_entry_control(&table, index);
 
-       /*
-        * Now set the unused entries to PTE. These entries are officially
-        * undefined and no contract for the contents and settings is given
-        * for these entries.
-        */
+               I915_WRITE(mocs_register(engine->id, index), value);
+       }
+
+       /* All remaining entries are also unused */
        for (; index < GEN9_NUM_MOCS_ENTRIES; index++)
-               I915_WRITE(mocs_register(engine->id, index),
-                          table.table[I915_MOCS_PTE].control_value);
+               I915_WRITE(mocs_register(engine->id, index), unused_value);
 }
 
 /**
@@ -234,11 +250,15 @@ static int emit_mocs_control_table(struct i915_request *rq,
 {
        enum intel_engine_id engine = rq->engine->id;
        unsigned int index;
+       u32 unused_value;
        u32 *cs;
 
        if (WARN_ON(table->size > GEN9_NUM_MOCS_ENTRIES))
                return -ENODEV;
 
+       /* Set unused values to PTE */
+       unused_value = table->table[I915_MOCS_PTE].control_value;
+
        cs = intel_ring_begin(rq, 2 + 2 * GEN9_NUM_MOCS_ENTRIES);
        if (IS_ERR(cs))
                return PTR_ERR(cs);
@@ -246,18 +266,16 @@ static int emit_mocs_control_table(struct i915_request *rq,
        *cs++ = MI_LOAD_REGISTER_IMM(GEN9_NUM_MOCS_ENTRIES);
 
        for (index = 0; index < table->size; index++) {
+               u32 value = get_entry_control(table, index);
+
                *cs++ = i915_mmio_reg_offset(mocs_register(engine, index));
-               *cs++ = table->table[index].control_value;
+               *cs++ = value;
        }
 
-       /*
-        * Now set the unused entries to PTE. These entries are officially
-        * undefined and no contract for the contents and settings is given
-        * for these entries.
-        */
+       /* All remaining entries are also unused */
        for (; index < GEN9_NUM_MOCS_ENTRIES; index++) {
                *cs++ = i915_mmio_reg_offset(mocs_register(engine, index));
-               *cs++ = table->table[I915_MOCS_PTE].control_value;
+               *cs++ = unused_value;
        }
 
        *cs++ = MI_NOOP;
@@ -266,12 +284,24 @@ static int emit_mocs_control_table(struct i915_request *rq,
        return 0;
 }
 
+/*
+ * Get l3cc_value from MOCS entry taking into account when it's not used:
+ * I915_MOCS_PTE's value is returned in this case.
+ */
+static u16 get_entry_l3cc(const struct drm_i915_mocs_table *table,
+                         unsigned int index)
+{
+       if (table->table[index].used)
+               return table->table[index].l3cc_value;
+
+       return table->table[I915_MOCS_PTE].l3cc_value;
+}
+
 static inline u32 l3cc_combine(const struct drm_i915_mocs_table *table,
                               u16 low,
                               u16 high)
 {
-       return table->table[low].l3cc_value |
-              table->table[high].l3cc_value << 16;
+       return low | high << 16;
 }
 
 /**
@@ -288,12 +318,16 @@ static inline u32 l3cc_combine(const struct drm_i915_mocs_table *table,
 static int emit_mocs_l3cc_table(struct i915_request *rq,
                                const struct drm_i915_mocs_table *table)
 {
+       u16 unused_value;
        unsigned int i;
        u32 *cs;
 
        if (WARN_ON(table->size > GEN9_NUM_MOCS_ENTRIES))
                return -ENODEV;
 
+       /* Set unused values to PTE */
+       unused_value = table->table[I915_MOCS_PTE].l3cc_value;
+
        cs = intel_ring_begin(rq, 2 + GEN9_NUM_MOCS_ENTRIES);
        if (IS_ERR(cs))
                return PTR_ERR(cs);
@@ -301,25 +335,26 @@ static int emit_mocs_l3cc_table(struct i915_request *rq,
        *cs++ = MI_LOAD_REGISTER_IMM(GEN9_NUM_MOCS_ENTRIES / 2);
 
        for (i = 0; i < table->size / 2; i++) {
+               u16 low = get_entry_l3cc(table, 2 * i);
+               u16 high = get_entry_l3cc(table, 2 * i + 1);
+
                *cs++ = i915_mmio_reg_offset(GEN9_LNCFCMOCS(i));
-               *cs++ = l3cc_combine(table, 2 * i, 2 * i + 1);
+               *cs++ = l3cc_combine(table, low, high);
        }
 
+       /* Odd table size - 1 left over */
        if (table->size & 0x01) {
-               /* Odd table size - 1 left over */
+               u16 low = get_entry_l3cc(table, 2 * i);
+
                *cs++ = i915_mmio_reg_offset(GEN9_LNCFCMOCS(i));
-               *cs++ = l3cc_combine(table, 2 * i, I915_MOCS_PTE);
+               *cs++ = l3cc_combine(table, low, unused_value);
                i++;
        }
 
-       /*
-        * Now set the unused entries to PTE. These entries are officially
-        * undefined and no contract for the contents and settings is given
-        * for these entries.
-        */
+       /* All remaining entries are also unused */
        for (; i < GEN9_NUM_MOCS_ENTRIES / 2; i++) {
                *cs++ = i915_mmio_reg_offset(GEN9_LNCFCMOCS(i));
-               *cs++ = l3cc_combine(table, I915_MOCS_PTE, I915_MOCS_PTE);
+               *cs++ = l3cc_combine(table, unused_value, unused_value);
        }
 
        *cs++ = MI_NOOP;
@@ -346,25 +381,35 @@ void intel_mocs_init_l3cc_table(struct drm_i915_private *dev_priv)
 {
        struct drm_i915_mocs_table table;
        unsigned int i;
+       u16 unused_value;
 
        if (!get_mocs_settings(dev_priv, &table))
                return;
 
-       for (i = 0; i < table.size / 2; i++)
+       /* Set unused values to PTE */
+       unused_value = table.table[I915_MOCS_PTE].l3cc_value;
+
+       for (i = 0; i < table.size / 2; i++) {
+               u16 low = get_entry_l3cc(&table, 2 * i);
+               u16 high = get_entry_l3cc(&table, 2 * i + 1);
+
                I915_WRITE(GEN9_LNCFCMOCS(i),
-                          l3cc_combine(&table, 2 * i, 2 * i + 1));
+                          l3cc_combine(&table, low, high));
+       }
 
        /* Odd table size - 1 left over */
        if (table.size & 0x01) {
+               u16 low = get_entry_l3cc(&table, 2 * i);
+
                I915_WRITE(GEN9_LNCFCMOCS(i),
-                          l3cc_combine(&table, 2 * i, I915_MOCS_PTE));
+                          l3cc_combine(&table, low, unused_value));
                i++;
        }
 
-       /* Now set the rest of the table to PTE */
+       /* All remaining entries are also unused */
        for (; i < (GEN9_NUM_MOCS_ENTRIES / 2); i++)
                I915_WRITE(GEN9_LNCFCMOCS(i),
-                          l3cc_combine(&table, I915_MOCS_PTE, I915_MOCS_PTE));
+                          l3cc_combine(&table, unused_value, unused_value));
 }
 
 /**