drm/i915: Split i915_ppgtt_init_hw() in half - generic and per ring
authorJohn Harrison <John.C.Harrison@Intel.com>
Thu, 18 Jun 2015 12:11:20 +0000 (13:11 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Tue, 23 Jun 2015 12:02:06 +0000 (14:02 +0200)
The i915_gem_init_hw() function calls a bunch of smaller initialisation
functions. Multiple of which have generic sections and per ring sections. This
means multiple passes are done over the rings. Each pass writes data to the ring
which floats around in that ring's OLR until some random point in the future
when an add_request() is done by some random other piece of code.

This patch breaks i915_ppgtt_init_hw() in two with the per ring initialisation
now being done in i915_ppgtt_init_ring(). The ring looping is now done at the
top level in i915_gem_init_hw().

v2: Fix dumb loop variable re-use.

For: VIZ-5115
Signed-off-by: John Harrison <John.C.Harrison@Intel.com>
Reviewed-by: Tomas Elf <tomas.elf@intel.com> (v1)
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_gem_gtt.h

index 1a3a65d022389bae429f6d3f3e2d83c76fe0ce94..9522e861a733d697531a8c460a451ef699cf26c0 100644 (file)
@@ -5015,7 +5015,7 @@ i915_gem_init_hw(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_engine_cs *ring;
-       int ret, i;
+       int ret, i, j;
 
        if (INTEL_INFO(dev)->gen < 6 && !intel_enable_gtt())
                return -EIO;
@@ -5052,19 +5052,32 @@ i915_gem_init_hw(struct drm_device *dev)
         */
        init_unused_rings(dev);
 
+       ret = i915_ppgtt_init_hw(dev);
+       if (ret) {
+               DRM_ERROR("PPGTT enable HW failed %d\n", ret);
+               goto out;
+       }
+
+       /* Need to do basic initialisation of all rings first: */
        for_each_ring(ring, dev_priv, i) {
                ret = ring->init_hw(ring);
                if (ret)
                        goto out;
        }
 
-       for (i = 0; i < NUM_L3_SLICES(dev); i++)
-               i915_gem_l3_remap(&dev_priv->ring[RCS], i);
+       /* Now it is safe to go back round and do everything else: */
+       for_each_ring(ring, dev_priv, i) {
+               if (ring->id == RCS) {
+                       for (j = 0; j < NUM_L3_SLICES(dev); j++)
+                               i915_gem_l3_remap(ring, j);
+               }
 
-       ret = i915_ppgtt_init_hw(dev);
-       if (ret && ret != -EIO) {
-               DRM_ERROR("PPGTT enable failed %d\n", ret);
-               i915_gem_cleanup_ringbuffer(dev);
+               ret = i915_ppgtt_init_ring(ring);
+               if (ret && ret != -EIO) {
+                       DRM_ERROR("PPGTT enable ring #%d failed %d\n", i, ret);
+                       i915_gem_cleanup_ringbuffer(dev);
+                       goto out;
+               }
        }
 
        ret = i915_gem_context_enable(dev_priv);
index d7ea81aa5cebf1ffb53a5e63e259754f5ef53fbe..f8ecea22748a9b6cebf5048b017bfc597e64b9c2 100644 (file)
@@ -1550,11 +1550,6 @@ int i915_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt)
 
 int i915_ppgtt_init_hw(struct drm_device *dev)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
-       struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
-       int i, ret = 0;
-
        /* In the case of execlists, PPGTT is enabled by the context descriptor
         * and the PDPs are contained within the context itself.  We don't
         * need to do anything here. */
@@ -1573,16 +1568,23 @@ int i915_ppgtt_init_hw(struct drm_device *dev)
        else
                MISSING_CASE(INTEL_INFO(dev)->gen);
 
-       if (ppgtt) {
-               for_each_ring(ring, dev_priv, i) {
-                       ret = ppgtt->switch_mm(ppgtt, ring);
-                       if (ret != 0)
-                               return ret;
-               }
-       }
+       return 0;
+}
 
-       return ret;
+int i915_ppgtt_init_ring(struct intel_engine_cs *ring)
+{
+       struct drm_i915_private *dev_priv = ring->dev->dev_private;
+       struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
+
+       if (i915.enable_execlists)
+               return 0;
+
+       if (!ppgtt)
+               return 0;
+
+       return ppgtt->switch_mm(ppgtt, ring);
 }
+
 struct i915_hw_ppgtt *
 i915_ppgtt_create(struct drm_device *dev, struct drm_i915_file_private *fpriv)
 {
index 0d46dd20bf717507fddbf22830e053322d399f32..0caa9ebb615b0f5339c7a1e3270015f1cded5f68 100644 (file)
@@ -475,6 +475,7 @@ void i915_global_gtt_cleanup(struct drm_device *dev);
 
 int i915_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt);
 int i915_ppgtt_init_hw(struct drm_device *dev);
+int i915_ppgtt_init_ring(struct intel_engine_cs *ring);
 void i915_ppgtt_release(struct kref *kref);
 struct i915_hw_ppgtt *i915_ppgtt_create(struct drm_device *dev,
                                        struct drm_i915_file_private *fpriv);