drm/i915: Refactor execlists default context pinning
[deliverable/linux.git] / drivers / gpu / drm / i915 / intel_mocs.c
index fed7bea19cc94c41bf34352b6fb9b1a7b4c9f398..6ba4bf7f2a89bc45eef78b49e42f336666fafc3a 100644 (file)
@@ -128,9 +128,9 @@ static const struct drm_i915_mocs_entry broxton_mocs_table[] = {
 
 /**
  * get_mocs_settings()
- * @dev:        DRM device.
+ * @dev_priv:  i915 device.
  * @table:      Output table that will be made to point at appropriate
- *              MOCS values for the device.
+ *           MOCS values for the device.
  *
  * This function will return the values of the MOCS table that needs to
  * be programmed for the platform. It will return the values that need
@@ -138,28 +138,28 @@ static const struct drm_i915_mocs_entry broxton_mocs_table[] = {
  *
  * Return: true if there are applicable MOCS settings for the device.
  */
-static bool get_mocs_settings(struct drm_device *dev,
+static bool get_mocs_settings(struct drm_i915_private *dev_priv,
                              struct drm_i915_mocs_table *table)
 {
        bool result = false;
 
-       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
+       if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
                table->size  = ARRAY_SIZE(skylake_mocs_table);
                table->table = skylake_mocs_table;
                result = true;
-       } else if (IS_BROXTON(dev)) {
+       } else if (IS_BROXTON(dev_priv)) {
                table->size  = ARRAY_SIZE(broxton_mocs_table);
                table->table = broxton_mocs_table;
                result = true;
        } else {
-               WARN_ONCE(INTEL_INFO(dev)->gen >= 9,
+               WARN_ONCE(INTEL_INFO(dev_priv)->gen >= 9,
                          "Platform that should have a MOCS table does not.\n");
        }
 
        return result;
 }
 
-static i915_reg_t mocs_register(enum intel_ring_id ring, int index)
+static i915_reg_t mocs_register(enum intel_engine_id ring, int index)
 {
        switch (ring) {
        case RCS:
@@ -178,11 +178,50 @@ static i915_reg_t mocs_register(enum intel_ring_id ring, int index)
        }
 }
 
+/**
+ * intel_mocs_init_engine() - emit the mocs control table
+ * @engine:    The engine for whom to emit the registers.
+ *
+ * This function simply emits a MI_LOAD_REGISTER_IMM command for the
+ * given table starting at the given address.
+ *
+ * Return: 0 on success, otherwise the error status.
+ */
+int intel_mocs_init_engine(struct intel_engine_cs *engine)
+{
+       struct drm_i915_private *dev_priv = to_i915(engine->dev);
+       struct drm_i915_mocs_table table;
+       unsigned int index;
+
+       if (!get_mocs_settings(dev_priv, &table))
+               return 0;
+
+       if (WARN_ON(table.size > GEN9_NUM_MOCS_ENTRIES))
+               return -ENODEV;
+
+       for (index = 0; index < table.size; index++)
+               I915_WRITE(mocs_register(engine->id, index),
+                          table.table[index].control_value);
+
+       /*
+        * Ok, now set the unused entries to uncached. These entries
+        * are officially undefined and no contract for the contents
+        * and settings is given for these entries.
+        *
+        * Entry 0 in the table is uncached - so we are just writing
+        * that value to all the used entries.
+        */
+       for (; index < GEN9_NUM_MOCS_ENTRIES; index++)
+               I915_WRITE(mocs_register(engine->id, index),
+                          table.table[0].control_value);
+
+       return 0;
+}
+
 /**
  * emit_mocs_control_table() - emit the mocs control table
  * @req:       Request to set up the MOCS table for.
  * @table:     The values to program into the control regs.
- * @ring:      The engine for whom to emit the registers.
  *
  * This function simply emits a MI_LOAD_REGISTER_IMM command for the
  * given table starting at the given address.
@@ -190,27 +229,26 @@ static i915_reg_t mocs_register(enum intel_ring_id ring, int index)
  * Return: 0 on success, otherwise the error status.
  */
 static int emit_mocs_control_table(struct drm_i915_gem_request *req,
-                                  const struct drm_i915_mocs_table *table,
-                                  enum intel_ring_id ring)
+                                  const struct drm_i915_mocs_table *table)
 {
        struct intel_ringbuffer *ringbuf = req->ringbuf;
+       enum intel_engine_id engine = req->engine->id;
        unsigned int index;
        int ret;
 
        if (WARN_ON(table->size > GEN9_NUM_MOCS_ENTRIES))
                return -ENODEV;
 
-       ret = intel_logical_ring_begin(req, 2 + 2 * GEN9_NUM_MOCS_ENTRIES);
-       if (ret) {
-               DRM_DEBUG("intel_logical_ring_begin failed %d\n", ret);
+       ret = intel_ring_begin(req, 2 + 2 * GEN9_NUM_MOCS_ENTRIES);
+       if (ret)
                return ret;
-       }
 
        intel_logical_ring_emit(ringbuf,
                                MI_LOAD_REGISTER_IMM(GEN9_NUM_MOCS_ENTRIES));
 
        for (index = 0; index < table->size; index++) {
-               intel_logical_ring_emit_reg(ringbuf, mocs_register(ring, index));
+               intel_logical_ring_emit_reg(ringbuf,
+                                           mocs_register(engine, index));
                intel_logical_ring_emit(ringbuf,
                                        table->table[index].control_value);
        }
@@ -224,8 +262,10 @@ static int emit_mocs_control_table(struct drm_i915_gem_request *req,
         * that value to all the used entries.
         */
        for (; index < GEN9_NUM_MOCS_ENTRIES; index++) {
-               intel_logical_ring_emit_reg(ringbuf, mocs_register(ring, index));
-               intel_logical_ring_emit(ringbuf, table->table[0].control_value);
+               intel_logical_ring_emit_reg(ringbuf,
+                                           mocs_register(engine, index));
+               intel_logical_ring_emit(ringbuf,
+                                       table->table[0].control_value);
        }
 
        intel_logical_ring_emit(ringbuf, MI_NOOP);
@@ -234,6 +274,14 @@ static int emit_mocs_control_table(struct drm_i915_gem_request *req,
        return 0;
 }
 
+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;
+}
+
 /**
  * emit_mocs_l3cc_table() - emit the mocs control table
  * @req:       Request to set up the MOCS table for.
@@ -249,39 +297,31 @@ static int emit_mocs_l3cc_table(struct drm_i915_gem_request *req,
                                const struct drm_i915_mocs_table *table)
 {
        struct intel_ringbuffer *ringbuf = req->ringbuf;
-       unsigned int count;
        unsigned int i;
-       u32 value;
-       u32 filler = (table->table[0].l3cc_value & 0xffff) |
-                       ((table->table[0].l3cc_value & 0xffff) << 16);
        int ret;
 
        if (WARN_ON(table->size > GEN9_NUM_MOCS_ENTRIES))
                return -ENODEV;
 
-       ret = intel_logical_ring_begin(req, 2 + GEN9_NUM_MOCS_ENTRIES);
-       if (ret) {
-               DRM_DEBUG("intel_logical_ring_begin failed %d\n", ret);
+       ret = intel_ring_begin(req, 2 + GEN9_NUM_MOCS_ENTRIES);
+       if (ret)
                return ret;
-       }
 
        intel_logical_ring_emit(ringbuf,
                        MI_LOAD_REGISTER_IMM(GEN9_NUM_MOCS_ENTRIES / 2));
 
-       for (i = 0, count = 0; i < table->size / 2; i++, count += 2) {
-               value = (table->table[count].l3cc_value & 0xffff) |
-                       ((table->table[count + 1].l3cc_value & 0xffff) << 16);
-
+       for (i = 0; i < table->size/2; i++) {
                intel_logical_ring_emit_reg(ringbuf, GEN9_LNCFCMOCS(i));
-               intel_logical_ring_emit(ringbuf, value);
+               intel_logical_ring_emit(ringbuf,
+                                       l3cc_combine(table, 2*i, 2*i+1));
        }
 
        if (table->size & 0x01) {
                /* Odd table size - 1 left over */
-               value = (table->table[count].l3cc_value & 0xffff) |
-                       ((table->table[0].l3cc_value & 0xffff) << 16);
-       } else
-               value = filler;
+               intel_logical_ring_emit_reg(ringbuf, GEN9_LNCFCMOCS(i));
+               intel_logical_ring_emit(ringbuf, l3cc_combine(table, 2*i, 0));
+               i++;
+       }
 
        /*
         * Now set the rest of the table to uncached - use entry 0 as
@@ -290,9 +330,7 @@ static int emit_mocs_l3cc_table(struct drm_i915_gem_request *req,
         */
        for (; i < GEN9_NUM_MOCS_ENTRIES / 2; i++) {
                intel_logical_ring_emit_reg(ringbuf, GEN9_LNCFCMOCS(i));
-               intel_logical_ring_emit(ringbuf, value);
-
-               value = filler;
+               intel_logical_ring_emit(ringbuf, l3cc_combine(table, 0, 0));
        }
 
        intel_logical_ring_emit(ringbuf, MI_NOOP);
@@ -301,6 +339,47 @@ static int emit_mocs_l3cc_table(struct drm_i915_gem_request *req,
        return 0;
 }
 
+/**
+ * intel_mocs_init_l3cc_table() - program the mocs control table
+ * @dev:      The the device to be programmed.
+ *
+ * This function simply programs the mocs registers for the given table
+ * starting at the given address. This register set is  programmed in pairs.
+ *
+ * These registers may get programmed more than once, it is simpler to
+ * re-program 32 registers than maintain the state of when they were programmed.
+ * We are always reprogramming with the same values and this only on context
+ * start.
+ *
+ * Return: Nothing.
+ */
+void intel_mocs_init_l3cc_table(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = to_i915(dev);
+       struct drm_i915_mocs_table table;
+       unsigned int i;
+
+       if (!get_mocs_settings(dev_priv, &table))
+               return;
+
+       for (i = 0; i < table.size/2; i++)
+               I915_WRITE(GEN9_LNCFCMOCS(i), l3cc_combine(&table, 2*i, 2*i+1));
+
+       /* Odd table size - 1 left over */
+       if (table.size & 0x01) {
+               I915_WRITE(GEN9_LNCFCMOCS(i), l3cc_combine(&table, 2*i, 0));
+               i++;
+       }
+
+       /*
+        * Now set the rest of the table to uncached - use entry 0 as
+        * this will be uncached. Leave the last pair as initialised as
+        * they are reserved by the hardware.
+        */
+       for (; i < (GEN9_NUM_MOCS_ENTRIES / 2); i++)
+               I915_WRITE(GEN9_LNCFCMOCS(i), l3cc_combine(&table, 0, 0));
+}
+
 /**
  * intel_rcs_context_init_mocs() - program the MOCS register.
  * @req:       Request to set up the MOCS tables for.
@@ -322,17 +401,11 @@ int intel_rcs_context_init_mocs(struct drm_i915_gem_request *req)
        struct drm_i915_mocs_table t;
        int ret;
 
-       if (get_mocs_settings(req->ring->dev, &t)) {
-               struct drm_i915_private *dev_priv = req->i915;
-               struct intel_engine_cs *ring;
-               enum intel_ring_id ring_id;
-
-               /* Program the control registers */
-               for_each_ring(ring, dev_priv, ring_id) {
-                       ret = emit_mocs_control_table(req, &t, ring_id);
-                       if (ret)
-                               return ret;
-               }
+       if (get_mocs_settings(req->i915, &t)) {
+               /* Program the RCS control registers */
+               ret = emit_mocs_control_table(req, &t);
+               if (ret)
+                       return ret;
 
                /* Now program the l3cc registers */
                ret = emit_mocs_l3cc_table(req, &t);
This page took 0.029375 seconds and 5 git commands to generate.