drm/i915: Update flush_all_caches() to take request structures
[deliverable/linux.git] / drivers / gpu / drm / i915 / intel_ringbuffer.c
index 461b9befa776945cca24470932eb5430e3986830..48ca73e7aaa6b4a9832f21ec7289d8a13b56ca6c 100644 (file)
@@ -81,7 +81,7 @@ bool intel_ring_stopped(struct intel_engine_cs *ring)
        return dev_priv->gpu_error.stop_rings & intel_ring_flag(ring);
 }
 
-void __intel_ring_advance(struct intel_engine_cs *ring)
+static void __intel_ring_advance(struct intel_engine_cs *ring)
 {
        struct intel_ringbuffer *ringbuf = ring->buffer;
        ringbuf->tail &= ringbuf->size - 1;
@@ -703,10 +703,10 @@ err:
        return ret;
 }
 
-static int intel_ring_workarounds_emit(struct intel_engine_cs *ring,
-                                      struct intel_context *ctx)
+static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req)
 {
        int ret, i;
+       struct intel_engine_cs *ring = req->ring;
        struct drm_device *dev = ring->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct i915_workarounds *w = &dev_priv->workarounds;
@@ -715,7 +715,7 @@ static int intel_ring_workarounds_emit(struct intel_engine_cs *ring,
                return 0;
 
        ring->gpu_caches_dirty = true;
-       ret = intel_ring_flush_all_caches(ring);
+       ret = intel_ring_flush_all_caches(req);
        if (ret)
                return ret;
 
@@ -733,7 +733,7 @@ static int intel_ring_workarounds_emit(struct intel_engine_cs *ring,
        intel_ring_advance(ring);
 
        ring->gpu_caches_dirty = true;
-       ret = intel_ring_flush_all_caches(ring);
+       ret = intel_ring_flush_all_caches(req);
        if (ret)
                return ret;
 
@@ -742,16 +742,15 @@ static int intel_ring_workarounds_emit(struct intel_engine_cs *ring,
        return 0;
 }
 
-static int intel_rcs_ctx_init(struct intel_engine_cs *ring,
-                             struct intel_context *ctx)
+static int intel_rcs_ctx_init(struct drm_i915_gem_request *req)
 {
        int ret;
 
-       ret = intel_ring_workarounds_emit(ring, ctx);
+       ret = intel_ring_workarounds_emit(req);
        if (ret != 0)
                return ret;
 
-       ret = i915_gem_render_state_init(ring);
+       ret = i915_gem_render_state_init(req);
        if (ret)
                DRM_ERROR("init render state: %d\n", ret);
 
@@ -800,6 +799,11 @@ static int bdw_init_workarounds(struct intel_engine_cs *ring)
        struct drm_device *dev = ring->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
+       WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING);
+
+       /* WaDisableAsyncFlipPerfMode:bdw */
+       WA_SET_BIT_MASKED(MI_MODE, ASYNC_FLIP_PERF_DISABLE);
+
        /* WaDisablePartialInstShootdown:bdw */
        /* WaDisableThreadStallDopClockGating:bdw (pre-production) */
        WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
@@ -853,9 +857,6 @@ static int bdw_init_workarounds(struct intel_engine_cs *ring)
                            GEN6_WIZ_HASHING_MASK,
                            GEN6_WIZ_HASHING_16x4);
 
-       /* WaProgramL3SqcReg1Default:bdw */
-       WA_WRITE(GEN8_L3SQCREG1, BDW_WA_L3SQCREG1_DEFAULT);
-
        return 0;
 }
 
@@ -864,6 +865,11 @@ static int chv_init_workarounds(struct intel_engine_cs *ring)
        struct drm_device *dev = ring->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
+       WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING);
+
+       /* WaDisableAsyncFlipPerfMode:chv */
+       WA_SET_BIT_MASKED(MI_MODE, ASYNC_FLIP_PERF_DISABLE);
+
        /* WaDisablePartialInstShootdown:chv */
        /* WaDisableThreadStallDopClockGating:chv */
        WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
@@ -904,13 +910,6 @@ static int chv_init_workarounds(struct intel_engine_cs *ring)
                            GEN6_WIZ_HASHING_MASK,
                            GEN6_WIZ_HASHING_16x4);
 
-       if (INTEL_REVID(dev) == SKL_REVID_C0 ||
-           INTEL_REVID(dev) == SKL_REVID_D0)
-               /* WaBarrierPerformanceFixDisable:skl */
-               WA_SET_BIT_MASKED(HDC_CHICKEN0,
-                                 HDC_FENCE_DEST_SLM_DISABLE |
-                                 HDC_BARRIER_PERFORMANCE_DISABLE);
-
        return 0;
 }
 
@@ -918,6 +917,7 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring)
 {
        struct drm_device *dev = ring->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       uint32_t tmp;
 
        /* WaDisablePartialInstShootdown:skl,bxt */
        WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
@@ -967,6 +967,13 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring)
                WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0,
                                  PIXEL_MASK_CAMMING_DISABLE);
 
+       /* WaForceContextSaveRestoreNonCoherent:skl,bxt */
+       tmp = HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT;
+       if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) == SKL_REVID_F0) ||
+           (IS_BROXTON(dev) && INTEL_REVID(dev) >= BXT_REVID_B0))
+               tmp |= HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE;
+       WA_SET_BIT_MASKED(HDC_CHICKEN0, tmp);
+
        return 0;
 }
 
@@ -1036,6 +1043,13 @@ static int skl_init_workarounds(struct intel_engine_cs *ring)
                                  HDC_FORCE_NON_COHERENT);
        }
 
+       if (INTEL_REVID(dev) == SKL_REVID_C0 ||
+           INTEL_REVID(dev) == SKL_REVID_D0)
+               /* WaBarrierPerformanceFixDisable:skl */
+               WA_SET_BIT_MASKED(HDC_CHICKEN0,
+                                 HDC_FENCE_DEST_SLM_DISABLE |
+                                 HDC_BARRIER_PERFORMANCE_DISABLE);
+
        return skl_tune_iz_hashing(ring);
 }
 
@@ -1057,10 +1071,6 @@ static int bxt_init_workarounds(struct intel_engine_cs *ring)
                        GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
        }
 
-       /* WaForceContextSaveRestoreNonCoherent:bxt */
-       WA_SET_BIT_MASKED(HDC_CHICKEN0,
-                         HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT);
-
        return 0;
 }
 
@@ -1104,9 +1114,9 @@ static int init_render_ring(struct intel_engine_cs *ring)
         * to use MI_WAIT_FOR_EVENT within the CS. It should already be
         * programmed to '1' on all products.
         *
-        * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv,bdw,chv
+        * WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv
         */
-       if (INTEL_INFO(dev)->gen >= 6 && INTEL_INFO(dev)->gen < 9)
+       if (INTEL_INFO(dev)->gen >= 6 && INTEL_INFO(dev)->gen < 8)
                I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE));
 
        /* Required for the hardware to program scanline values for waiting */
@@ -1131,7 +1141,7 @@ static int init_render_ring(struct intel_engine_cs *ring)
                           _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB));
        }
 
-       if (INTEL_INFO(dev)->gen >= 6)
+       if (INTEL_INFO(dev)->gen >= 6 && INTEL_INFO(dev)->gen < 8)
                I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING));
 
        if (HAS_L3_DPF(dev))
@@ -2099,15 +2109,19 @@ static int ring_wait_for_space(struct intel_engine_cs *ring, int n)
 {
        struct intel_ringbuffer *ringbuf = ring->buffer;
        struct drm_i915_gem_request *request;
-       int ret, new_space;
+       unsigned space;
+       int ret;
+
+       /* The whole point of reserving space is to not wait! */
+       WARN_ON(ringbuf->reserved_in_use);
 
        if (intel_ring_space(ringbuf) >= n)
                return 0;
 
        list_for_each_entry(request, &ring->request_list, list) {
-               new_space = __intel_ring_space(request->postfix, ringbuf->tail,
-                                      ringbuf->size);
-               if (new_space >= n)
+               space = __intel_ring_space(request->postfix, ringbuf->tail,
+                                          ringbuf->size);
+               if (space >= n)
                        break;
        }
 
@@ -2118,10 +2132,7 @@ static int ring_wait_for_space(struct intel_engine_cs *ring, int n)
        if (ret)
                return ret;
 
-       i915_gem_retire_requests_ring(ring);
-
-       WARN_ON(intel_ring_space(ringbuf) < new_space);
-
+       ringbuf->space = space;
        return 0;
 }
 
@@ -2131,6 +2142,9 @@ static int intel_wrap_ring_buffer(struct intel_engine_cs *ring)
        struct intel_ringbuffer *ringbuf = ring->buffer;
        int rem = ringbuf->size - ringbuf->tail;
 
+       /* Can't wrap if space has already been reserved! */
+       WARN_ON(ringbuf->reserved_in_use);
+
        if (ringbuf->space < rem) {
                int ret = ring_wait_for_space(ring, rem);
                if (ret)
@@ -2151,24 +2165,25 @@ static int intel_wrap_ring_buffer(struct intel_engine_cs *ring)
 int intel_ring_idle(struct intel_engine_cs *ring)
 {
        struct drm_i915_gem_request *req;
-       int ret;
 
        /* We need to add any requests required to flush the objects and ring */
-       if (ring->outstanding_lazy_request) {
-               ret = i915_add_request(ring);
-               if (ret)
-                       return ret;
-       }
+       WARN_ON(ring->outstanding_lazy_request);
+       if (ring->outstanding_lazy_request)
+               i915_add_request(ring->outstanding_lazy_request);
 
        /* Wait upon the last request to be completed */
        if (list_empty(&ring->request_list))
                return 0;
 
        req = list_entry(ring->request_list.prev,
-                          struct drm_i915_gem_request,
-                          list);
+                       struct drm_i915_gem_request,
+                       list);
 
-       return i915_wait_request(req);
+       /* Make sure we do not trigger any retires */
+       return __i915_wait_request(req,
+                                  atomic_read(&to_i915(ring->dev)->gpu_error.reset_counter),
+                                  to_i915(ring->dev)->mm.interruptible,
+                                  NULL, NULL);
 }
 
 int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request)
@@ -2177,16 +2192,77 @@ int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request)
        return 0;
 }
 
-static int __intel_ring_prepare(struct intel_engine_cs *ring,
-                               int bytes)
+void intel_ring_reserved_space_reserve(struct intel_ringbuffer *ringbuf, int size)
+{
+       /* NB: Until request management is fully tidied up and the OLR is
+        * removed, there are too many ways for get false hits on this
+        * anti-recursion check! */
+       /*WARN_ON(ringbuf->reserved_size);*/
+       WARN_ON(ringbuf->reserved_in_use);
+
+       ringbuf->reserved_size = size;
+
+       /*
+        * Really need to call _begin() here but that currently leads to
+        * recursion problems! This will be fixed later but for now just
+        * return and hope for the best. Note that there is only a real
+        * problem if the create of the request never actually calls _begin()
+        * but if they are not submitting any work then why did they create
+        * the request in the first place?
+        */
+}
+
+void intel_ring_reserved_space_cancel(struct intel_ringbuffer *ringbuf)
+{
+       WARN_ON(ringbuf->reserved_in_use);
+
+       ringbuf->reserved_size   = 0;
+       ringbuf->reserved_in_use = false;
+}
+
+void intel_ring_reserved_space_use(struct intel_ringbuffer *ringbuf)
+{
+       WARN_ON(ringbuf->reserved_in_use);
+
+       ringbuf->reserved_in_use = true;
+       ringbuf->reserved_tail   = ringbuf->tail;
+}
+
+void intel_ring_reserved_space_end(struct intel_ringbuffer *ringbuf)
+{
+       WARN_ON(!ringbuf->reserved_in_use);
+       WARN(ringbuf->tail > ringbuf->reserved_tail + ringbuf->reserved_size,
+            "request reserved size too small: %d vs %d!\n",
+            ringbuf->tail - ringbuf->reserved_tail, ringbuf->reserved_size);
+
+       ringbuf->reserved_size   = 0;
+       ringbuf->reserved_in_use = false;
+}
+
+static int __intel_ring_prepare(struct intel_engine_cs *ring, int bytes)
 {
        struct intel_ringbuffer *ringbuf = ring->buffer;
        int ret;
 
+       /*
+        * Add on the reserved size to the request to make sure that after
+        * the intended commands have been emitted, there is guaranteed to
+        * still be enough free space to send them to the hardware.
+        */
+       if (!ringbuf->reserved_in_use)
+               bytes += ringbuf->reserved_size;
+
        if (unlikely(ringbuf->tail + bytes > ringbuf->effective_size)) {
                ret = intel_wrap_ring_buffer(ring);
                if (unlikely(ret))
                        return ret;
+
+               if(ringbuf->reserved_size) {
+                       uint32_t size = ringbuf->reserved_size;
+
+                       intel_ring_reserved_space_cancel(ringbuf);
+                       intel_ring_reserved_space_reserve(ringbuf, size);
+               }
        }
 
        if (unlikely(ringbuf->space < bytes)) {
@@ -2201,6 +2277,7 @@ static int __intel_ring_prepare(struct intel_engine_cs *ring,
 int intel_ring_begin(struct intel_engine_cs *ring,
                     int num_dwords)
 {
+       struct drm_i915_gem_request *req;
        struct drm_i915_private *dev_priv = ring->dev->dev_private;
        int ret;
 
@@ -2214,7 +2291,7 @@ int intel_ring_begin(struct intel_engine_cs *ring,
                return ret;
 
        /* Preallocate the olr before touching the ring */
-       ret = i915_gem_request_alloc(ring, ring->default_context);
+       ret = i915_gem_request_alloc(ring, ring->default_context, &req);
        if (ret)
                return ret;
 
@@ -2815,8 +2892,9 @@ int intel_init_vebox_ring_buffer(struct drm_device *dev)
 }
 
 int
-intel_ring_flush_all_caches(struct intel_engine_cs *ring)
+intel_ring_flush_all_caches(struct drm_i915_gem_request *req)
 {
+       struct intel_engine_cs *ring = req->ring;
        int ret;
 
        if (!ring->gpu_caches_dirty)
@@ -2833,8 +2911,9 @@ intel_ring_flush_all_caches(struct intel_engine_cs *ring)
 }
 
 int
-intel_ring_invalidate_all_caches(struct intel_engine_cs *ring)
+intel_ring_invalidate_all_caches(struct drm_i915_gem_request *req)
 {
+       struct intel_engine_cs *ring = req->ring;
        uint32_t flush_domains;
        int ret;
 
This page took 0.032118 seconds and 5 git commands to generate.