drm/i915: Add functions to emit register offsets to the ring
[deliverable/linux.git] / drivers / gpu / drm / i915 / intel_ringbuffer.c
index 6e6b8db996ef2450c615a71ef10b7ffcbbc62479..75f29d81af1620e5b975c8213ee844174d4b97ae 100644 (file)
@@ -717,7 +717,7 @@ static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct i915_workarounds *w = &dev_priv->workarounds;
 
-       if (WARN_ON_ONCE(w->count == 0))
+       if (w->count == 0)
                return 0;
 
        ring->gpu_caches_dirty = true;
@@ -731,7 +731,7 @@ static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req)
 
        intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(w->count));
        for (i = 0; i < w->count; i++) {
-               intel_ring_emit(ring, w->reg[i].addr);
+               intel_ring_emit_reg(ring, w->reg[i].addr);
                intel_ring_emit(ring, w->reg[i].value);
        }
        intel_ring_emit(ring, MI_NOOP);
@@ -800,42 +800,29 @@ static int wa_add(struct drm_i915_private *dev_priv,
 
 #define WA_WRITE(addr, val) WA_REG(addr, 0xffffffff, val)
 
-static int bdw_init_workarounds(struct intel_engine_cs *ring)
+static int gen8_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 */
+       /* WaDisableAsyncFlipPerfMode:bdw,chv */
        WA_SET_BIT_MASKED(MI_MODE, ASYNC_FLIP_PERF_DISABLE);
 
-       /* WaDisablePartialInstShootdown:bdw */
-       /* WaDisableThreadStallDopClockGating:bdw (pre-production) */
+       /* WaDisablePartialInstShootdown:bdw,chv */
        WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
-                         PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE |
-                         STALL_DOP_GATING_DISABLE);
-
-       /* WaDisableDopClockGating:bdw */
-       WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2,
-                         DOP_CLOCK_GATING_DISABLE);
-
-       WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
-                         GEN8_SAMPLER_POWER_BYPASS_DIS);
+                         PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
 
        /* Use Force Non-Coherent whenever executing a 3D context. This is a
         * workaround for for a possible hang in the unlikely event a TLB
         * invalidation occurs during a PSD flush.
         */
+       /* WaForceEnableNonCoherent:bdw,chv */
+       /* WaHdcDisableFetchWhenMasked:bdw,chv */
        WA_SET_BIT_MASKED(HDC_CHICKEN0,
-                         /* WaForceEnableNonCoherent:bdw */
-                         HDC_FORCE_NON_COHERENT |
-                         /* WaForceContextSaveRestoreNonCoherent:bdw */
-                         HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT |
-                         /* WaHdcDisableFetchWhenMasked:bdw */
                          HDC_DONOT_FETCH_MEM_WHEN_MASKED |
-                         /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */
-                         (IS_BDW_GT3(dev) ? HDC_FENCE_DEST_SLM_DISABLE : 0));
+                         HDC_FORCE_NON_COHERENT);
 
        /* From the Haswell PRM, Command Reference: Registers, CACHE_MODE_0:
         * "The Hierarchical Z RAW Stall Optimization allows non-overlapping
@@ -843,13 +830,12 @@ static int bdw_init_workarounds(struct intel_engine_cs *ring)
         *  stalling waiting for the earlier ones to write to Hierarchical Z
         *  buffer."
         *
-        * This optimization is off by default for Broadwell; turn it on.
+        * This optimization is off by default for BDW and CHV; turn it on.
         */
        WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE);
 
-       /* Wa4x4STCOptimizationDisable:bdw */
-       WA_SET_BIT_MASKED(CACHE_MODE_1,
-                         GEN8_4x4_STC_OPTIMIZATION_DISABLE);
+       /* Wa4x4STCOptimizationDisable:bdw,chv */
+       WA_SET_BIT_MASKED(CACHE_MODE_1, GEN8_4x4_STC_OPTIMIZATION_DISABLE);
 
        /*
         * BSpec recommends 8x4 when MSAA is used,
@@ -866,56 +852,51 @@ static int bdw_init_workarounds(struct intel_engine_cs *ring)
        return 0;
 }
 
-static int chv_init_workarounds(struct intel_engine_cs *ring)
+static int bdw_init_workarounds(struct intel_engine_cs *ring)
 {
+       int ret;
        struct drm_device *dev = ring->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING);
+       ret = gen8_init_workarounds(ring);
+       if (ret)
+               return ret;
 
-       /* WaDisableAsyncFlipPerfMode:chv */
-       WA_SET_BIT_MASKED(MI_MODE, ASYNC_FLIP_PERF_DISABLE);
+       /* WaDisableThreadStallDopClockGating:bdw (pre-production) */
+       WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE);
 
-       /* WaDisablePartialInstShootdown:chv */
-       /* WaDisableThreadStallDopClockGating:chv */
-       WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
-                         PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE |
-                         STALL_DOP_GATING_DISABLE);
+       /* WaDisableDopClockGating:bdw */
+       WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2,
+                         DOP_CLOCK_GATING_DISABLE);
+
+       WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
+                         GEN8_SAMPLER_POWER_BYPASS_DIS);
 
-       /* Use Force Non-Coherent whenever executing a 3D context. This is a
-        * workaround for a possible hang in the unlikely event a TLB
-        * invalidation occurs during a PSD flush.
-        */
-       /* WaForceEnableNonCoherent:chv */
-       /* WaHdcDisableFetchWhenMasked:chv */
        WA_SET_BIT_MASKED(HDC_CHICKEN0,
-                         HDC_FORCE_NON_COHERENT |
-                         HDC_DONOT_FETCH_MEM_WHEN_MASKED);
+                         /* WaForceContextSaveRestoreNonCoherent:bdw */
+                         HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT |
+                         /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */
+                         (IS_BDW_GT3(dev) ? HDC_FENCE_DEST_SLM_DISABLE : 0));
 
-       /* According to the CACHE_MODE_0 default value documentation, some
-        * CHV platforms disable this optimization by default.  Turn it on.
-        */
-       WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE);
+       return 0;
+}
+
+static int chv_init_workarounds(struct intel_engine_cs *ring)
+{
+       int ret;
+       struct drm_device *dev = ring->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       ret = gen8_init_workarounds(ring);
+       if (ret)
+               return ret;
 
-       /* Wa4x4STCOptimizationDisable:chv */
-       WA_SET_BIT_MASKED(CACHE_MODE_1,
-                         GEN8_4x4_STC_OPTIMIZATION_DISABLE);
+       /* WaDisableThreadStallDopClockGating:chv */
+       WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE);
 
        /* Improve HiZ throughput on CHV. */
        WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X);
 
-       /*
-        * BSpec recommends 8x4 when MSAA is used,
-        * however in practice 16x4 seems fastest.
-        *
-        * Note that PS/WM thread counts depend on the WIZ hashing
-        * disable bit, which we don't touch here, but it's good
-        * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM).
-        */
-       WA_SET_FIELD_MASKED(GEN7_GT_MODE,
-                           GEN6_WIZ_HASHING_MASK,
-                           GEN6_WIZ_HASHING_16x4);
-
        return 0;
 }
 
@@ -925,6 +906,14 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring)
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t tmp;
 
+       /* WaEnableLbsSlaRetryTimerDecrement:skl */
+       I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) |
+                  GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE);
+
+       /* WaDisableKillLogic:bxt,skl */
+       I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
+                  ECOCHK_DIS_TLB);
+
        /* WaDisablePartialInstShootdown:skl,bxt */
        WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
                          PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
@@ -933,17 +922,15 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring)
        WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
                          GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC);
 
-       if ((IS_SKYLAKE(dev) && (INTEL_REVID(dev) == SKL_REVID_A0 ||
-           INTEL_REVID(dev) == SKL_REVID_B0)) ||
-           (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0)) {
-               /* WaDisableDgMirrorFixInHalfSliceChicken5:skl,bxt */
+       /* WaDisableDgMirrorFixInHalfSliceChicken5:skl,bxt */
+       if (IS_SKL_REVID(dev, 0, SKL_REVID_B0) ||
+           IS_BXT_REVID(dev, 0, BXT_REVID_A1))
                WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5,
                                  GEN9_DG_MIRROR_FIX_ENABLE);
-       }
 
-       if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0) ||
-           (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0)) {
-               /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */
+       /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */
+       if (IS_SKL_REVID(dev, 0, SKL_REVID_B0) ||
+           IS_BXT_REVID(dev, 0, BXT_REVID_A1)) {
                WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1,
                                  GEN9_RHWO_OPTIMIZATION_DISABLE);
                /*
@@ -953,36 +940,41 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring)
                 */
        }
 
-       if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) >= SKL_REVID_C0) ||
-           IS_BROXTON(dev)) {
-               /* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt */
+       /* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt */
+       if (IS_SKL_REVID(dev, SKL_REVID_C0, REVID_FOREVER) || IS_BROXTON(dev))
                WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7,
                                  GEN9_ENABLE_YV12_BUGFIX);
-       }
 
        /* Wa4x4STCOptimizationDisable:skl,bxt */
-       WA_SET_BIT_MASKED(CACHE_MODE_1, GEN8_4x4_STC_OPTIMIZATION_DISABLE);
-
        /* WaDisablePartialResolveInVc:skl,bxt */
-       WA_SET_BIT_MASKED(CACHE_MODE_1, GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE);
+       WA_SET_BIT_MASKED(CACHE_MODE_1, (GEN8_4x4_STC_OPTIMIZATION_DISABLE |
+                                        GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE));
 
        /* WaCcsTlbPrefetchDisable:skl,bxt */
        WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5,
                          GEN9_CCS_TLB_PREFETCH_ENABLE);
 
        /* WaDisableMaskBasedCammingInRCC:skl,bxt */
-       if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) == SKL_REVID_C0) ||
-           (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0))
+       if (IS_SKL_REVID(dev, SKL_REVID_C0, SKL_REVID_C0) ||
+           IS_BXT_REVID(dev, 0, BXT_REVID_A1))
                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))
+       if (IS_SKL_REVID(dev, SKL_REVID_F0, SKL_REVID_F0) ||
+           IS_BXT_REVID(dev, BXT_REVID_B0, REVID_FOREVER))
                tmp |= HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE;
        WA_SET_BIT_MASKED(HDC_CHICKEN0, tmp);
 
+       /* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt */
+       if (IS_SKYLAKE(dev) || IS_BXT_REVID(dev, 0, BXT_REVID_B0))
+               WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
+                                 GEN8_SAMPLER_POWER_BYPASS_DIS);
+
+       /* WaDisableSTUnitPowerOptimization:skl,bxt */
+       WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE);
+
        return 0;
 }
 
@@ -1028,20 +1020,46 @@ static int skl_tune_iz_hashing(struct intel_engine_cs *ring)
        return 0;
 }
 
-
 static int skl_init_workarounds(struct intel_engine_cs *ring)
 {
+       int ret;
        struct drm_device *dev = ring->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       gen9_init_workarounds(ring);
+       ret = gen9_init_workarounds(ring);
+       if (ret)
+               return ret;
+
+       if (IS_SKL_REVID(dev, 0, SKL_REVID_D0)) {
+               /* WaDisableHDCInvalidation:skl */
+               I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
+                          BDW_DISABLE_HDC_INVALIDATION);
+
+               /* WaDisableChickenBitTSGBarrierAckForFFSliceCS:skl */
+               I915_WRITE(FF_SLICE_CS_CHICKEN2,
+                          _MASKED_BIT_ENABLE(GEN9_TSG_BARRIER_ACK_DISABLE));
+       }
+
+       /* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes
+        * involving this register should also be added to WA batch as required.
+        */
+       if (IS_SKL_REVID(dev, 0, SKL_REVID_E0))
+               /* WaDisableLSQCROPERFforOCL:skl */
+               I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) |
+                          GEN8_LQSC_RO_PERF_DIS);
+
+       /* WaEnableGapsTsvCreditFix:skl */
+       if (IS_SKL_REVID(dev, SKL_REVID_C0, REVID_FOREVER)) {
+               I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
+                                          GEN9_GAPS_TSV_CREDIT_DISABLE));
+       }
 
        /* WaDisablePowerCompilerClockGating:skl */
-       if (INTEL_REVID(dev) == SKL_REVID_B0)
+       if (IS_SKL_REVID(dev, SKL_REVID_B0, SKL_REVID_B0))
                WA_SET_BIT_MASKED(HIZ_CHICKEN,
                                  BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE);
 
-       if (INTEL_REVID(dev) <= SKL_REVID_D0) {
+       if (IS_SKL_REVID(dev, 0, SKL_REVID_D0)) {
                /*
                 *Use Force Non-Coherent whenever executing a 3D context. This
                 * is a workaround for a possible hang in the unlikely event
@@ -1052,36 +1070,48 @@ 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 */
+       /* WaBarrierPerformanceFixDisable:skl */
+       if (IS_SKL_REVID(dev, SKL_REVID_C0, SKL_REVID_D0))
                WA_SET_BIT_MASKED(HDC_CHICKEN0,
                                  HDC_FENCE_DEST_SLM_DISABLE |
                                  HDC_BARRIER_PERFORMANCE_DISABLE);
 
        /* WaDisableSbeCacheDispatchPortSharing:skl */
-       if (INTEL_REVID(dev) <= SKL_REVID_F0) {
+       if (IS_SKL_REVID(dev, 0, SKL_REVID_F0))
                WA_SET_BIT_MASKED(
                        GEN7_HALF_SLICE_CHICKEN1,
                        GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
-       }
 
        return skl_tune_iz_hashing(ring);
 }
 
 static int bxt_init_workarounds(struct intel_engine_cs *ring)
 {
+       int ret;
        struct drm_device *dev = ring->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       gen9_init_workarounds(ring);
+       ret = gen9_init_workarounds(ring);
+       if (ret)
+               return ret;
+
+       /* WaStoreMultiplePTEenable:bxt */
+       /* This is a requirement according to Hardware specification */
+       if (IS_BXT_REVID(dev, 0, BXT_REVID_A1))
+               I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF);
+
+       /* WaSetClckGatingDisableMedia:bxt */
+       if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) {
+               I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) &
+                                           ~GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE));
+       }
 
        /* WaDisableThreadStallDopClockGating:bxt */
        WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
                          STALL_DOP_GATING_DISABLE);
 
        /* WaDisableSbeCacheDispatchPortSharing:bxt */
-       if (INTEL_REVID(dev) <= BXT_REVID_B0) {
+       if (IS_BXT_REVID(dev, 0, BXT_REVID_B0)) {
                WA_SET_BIT_MASKED(
                        GEN7_HALF_SLICE_CHICKEN1,
                        GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
@@ -1283,7 +1313,7 @@ static int gen6_signal(struct drm_i915_gem_request *signaller_req,
                if (mbox_reg != GEN6_NOSYNC) {
                        u32 seqno = i915_gem_request_get_seqno(signaller_req);
                        intel_ring_emit(signaller, MI_LOAD_REGISTER_IMM(1));
-                       intel_ring_emit(signaller, mbox_reg);
+                       intel_ring_emit_reg(signaller, mbox_reg);
                        intel_ring_emit(signaller, seqno);
                }
        }
@@ -1964,11 +1994,35 @@ static int init_phys_status_page(struct intel_engine_cs *ring)
 
 void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf)
 {
-       iounmap(ringbuf->virtual_start);
+       if (HAS_LLC(ringbuf->obj->base.dev) && !ringbuf->obj->stolen)
+               vunmap(ringbuf->virtual_start);
+       else
+               iounmap(ringbuf->virtual_start);
        ringbuf->virtual_start = NULL;
        i915_gem_object_ggtt_unpin(ringbuf->obj);
 }
 
+static u32 *vmap_obj(struct drm_i915_gem_object *obj)
+{
+       struct sg_page_iter sg_iter;
+       struct page **pages;
+       void *addr;
+       int i;
+
+       pages = drm_malloc_ab(obj->base.size >> PAGE_SHIFT, sizeof(*pages));
+       if (pages == NULL)
+               return NULL;
+
+       i = 0;
+       for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0)
+               pages[i++] = sg_page_iter_page(&sg_iter);
+
+       addr = vmap(pages, i, 0, PAGE_KERNEL);
+       drm_free_large(pages);
+
+       return addr;
+}
+
 int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev,
                                     struct intel_ringbuffer *ringbuf)
 {
@@ -1976,34 +2030,52 @@ int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev,
        struct drm_i915_gem_object *obj = ringbuf->obj;
        int ret;
 
-       ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE);
-       if (ret)
-               return ret;
+       if (HAS_LLC(dev_priv) && !obj->stolen) {
+               ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, 0);
+               if (ret)
+                       return ret;
 
-       ret = i915_gem_object_set_to_gtt_domain(obj, true);
-       if (ret) {
-               i915_gem_object_ggtt_unpin(obj);
-               return ret;
-       }
+               ret = i915_gem_object_set_to_cpu_domain(obj, true);
+               if (ret) {
+                       i915_gem_object_ggtt_unpin(obj);
+                       return ret;
+               }
+
+               ringbuf->virtual_start = vmap_obj(obj);
+               if (ringbuf->virtual_start == NULL) {
+                       i915_gem_object_ggtt_unpin(obj);
+                       return -ENOMEM;
+               }
+       } else {
+               ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE);
+               if (ret)
+                       return ret;
+
+               ret = i915_gem_object_set_to_gtt_domain(obj, true);
+               if (ret) {
+                       i915_gem_object_ggtt_unpin(obj);
+                       return ret;
+               }
 
-       ringbuf->virtual_start = ioremap_wc(dev_priv->gtt.mappable_base +
-                       i915_gem_obj_ggtt_offset(obj), ringbuf->size);
-       if (ringbuf->virtual_start == NULL) {
-               i915_gem_object_ggtt_unpin(obj);
-               return -EINVAL;
+               ringbuf->virtual_start = ioremap_wc(dev_priv->gtt.mappable_base +
+                                                   i915_gem_obj_ggtt_offset(obj), ringbuf->size);
+               if (ringbuf->virtual_start == NULL) {
+                       i915_gem_object_ggtt_unpin(obj);
+                       return -EINVAL;
+               }
        }
 
        return 0;
 }
 
-void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf)
+static void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf)
 {
        drm_gem_object_unreference(&ringbuf->obj->base);
        ringbuf->obj = NULL;
 }
 
-int intel_alloc_ringbuffer_obj(struct drm_device *dev,
-                              struct intel_ringbuffer *ringbuf)
+static int intel_alloc_ringbuffer_obj(struct drm_device *dev,
+                                     struct intel_ringbuffer *ringbuf)
 {
        struct drm_i915_gem_object *obj;
 
@@ -2023,6 +2095,54 @@ int intel_alloc_ringbuffer_obj(struct drm_device *dev,
        return 0;
 }
 
+struct intel_ringbuffer *
+intel_engine_create_ringbuffer(struct intel_engine_cs *engine, int size)
+{
+       struct intel_ringbuffer *ring;
+       int ret;
+
+       ring = kzalloc(sizeof(*ring), GFP_KERNEL);
+       if (ring == NULL) {
+               DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s\n",
+                                engine->name);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       ring->ring = engine;
+       list_add(&ring->link, &engine->buffers);
+
+       ring->size = size;
+       /* Workaround an erratum on the i830 which causes a hang if
+        * the TAIL pointer points to within the last 2 cachelines
+        * of the buffer.
+        */
+       ring->effective_size = size;
+       if (IS_I830(engine->dev) || IS_845G(engine->dev))
+               ring->effective_size -= 2 * CACHELINE_BYTES;
+
+       ring->last_retired_head = -1;
+       intel_ring_update_space(ring);
+
+       ret = intel_alloc_ringbuffer_obj(engine->dev, ring);
+       if (ret) {
+               DRM_DEBUG_DRIVER("Failed to allocate ringbuffer %s: %d\n",
+                                engine->name, ret);
+               list_del(&ring->link);
+               kfree(ring);
+               return ERR_PTR(ret);
+       }
+
+       return ring;
+}
+
+void
+intel_ringbuffer_free(struct intel_ringbuffer *ring)
+{
+       intel_destroy_ringbuffer_obj(ring);
+       list_del(&ring->link);
+       kfree(ring);
+}
+
 static int intel_init_ring_buffer(struct drm_device *dev,
                                  struct intel_engine_cs *ring)
 {
@@ -2031,22 +2151,21 @@ static int intel_init_ring_buffer(struct drm_device *dev,
 
        WARN_ON(ring->buffer);
 
-       ringbuf = kzalloc(sizeof(*ringbuf), GFP_KERNEL);
-       if (!ringbuf)
-               return -ENOMEM;
-       ring->buffer = ringbuf;
-
        ring->dev = dev;
        INIT_LIST_HEAD(&ring->active_list);
        INIT_LIST_HEAD(&ring->request_list);
        INIT_LIST_HEAD(&ring->execlist_queue);
+       INIT_LIST_HEAD(&ring->buffers);
        i915_gem_batch_pool_init(dev, &ring->batch_pool);
-       ringbuf->size = 32 * PAGE_SIZE;
-       ringbuf->ring = ring;
        memset(ring->semaphore.sync_seqno, 0, sizeof(ring->semaphore.sync_seqno));
 
        init_waitqueue_head(&ring->irq_queue);
 
+       ringbuf = intel_engine_create_ringbuffer(ring, 32 * PAGE_SIZE);
+       if (IS_ERR(ringbuf))
+               return PTR_ERR(ringbuf);
+       ring->buffer = ringbuf;
+
        if (I915_NEED_GFX_HWS(dev)) {
                ret = init_status_page(ring);
                if (ret)
@@ -2058,15 +2177,6 @@ static int intel_init_ring_buffer(struct drm_device *dev,
                        goto error;
        }
 
-       WARN_ON(ringbuf->obj);
-
-       ret = intel_alloc_ringbuffer_obj(dev, ringbuf);
-       if (ret) {
-               DRM_ERROR("Failed to allocate ringbuffer %s: %d\n",
-                               ring->name, ret);
-               goto error;
-       }
-
        ret = intel_pin_and_map_ringbuffer_obj(dev, ringbuf);
        if (ret) {
                DRM_ERROR("Failed to pin and map ringbuffer %s: %d\n",
@@ -2075,14 +2185,6 @@ static int intel_init_ring_buffer(struct drm_device *dev,
                goto error;
        }
 
-       /* Workaround an erratum on the i830 which causes a hang if
-        * the TAIL pointer points to within the last 2 cachelines
-        * of the buffer.
-        */
-       ringbuf->effective_size = ringbuf->size;
-       if (IS_I830(dev) || IS_845G(dev))
-               ringbuf->effective_size -= 2 * CACHELINE_BYTES;
-
        ret = i915_cmd_parser_init_ring(ring);
        if (ret)
                goto error;
@@ -2090,7 +2192,7 @@ static int intel_init_ring_buffer(struct drm_device *dev,
        return 0;
 
 error:
-       kfree(ringbuf);
+       intel_ringbuffer_free(ringbuf);
        ring->buffer = NULL;
        return ret;
 }
@@ -2098,19 +2200,18 @@ error:
 void intel_cleanup_ring_buffer(struct intel_engine_cs *ring)
 {
        struct drm_i915_private *dev_priv;
-       struct intel_ringbuffer *ringbuf;
 
        if (!intel_ring_initialized(ring))
                return;
 
        dev_priv = to_i915(ring->dev);
-       ringbuf = ring->buffer;
 
        intel_stop_ring_buffer(ring);
        WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0);
 
-       intel_unpin_ringbuffer_obj(ringbuf);
-       intel_destroy_ringbuffer_obj(ringbuf);
+       intel_unpin_ringbuffer_obj(ring->buffer);
+       intel_ringbuffer_free(ring->buffer);
+       ring->buffer = NULL;
 
        if (ring->cleanup)
                ring->cleanup(ring);
@@ -2119,9 +2220,6 @@ void intel_cleanup_ring_buffer(struct intel_engine_cs *ring)
 
        i915_cmd_parser_fini_ring(ring);
        i915_gem_batch_pool_fini(&ring->batch_pool);
-
-       kfree(ringbuf);
-       ring->buffer = NULL;
 }
 
 static int ring_wait_for_space(struct intel_engine_cs *ring, int n)
@@ -2608,6 +2706,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
                        GEN8_RING_SEMAPHORE_INIT;
                }
        } else if (INTEL_INFO(dev)->gen >= 6) {
+               ring->init_context = intel_rcs_ctx_init;
                ring->add_request = gen6_add_request;
                ring->flush = gen7_render_ring_flush;
                if (INTEL_INFO(dev)->gen == 6)
This page took 0.031849 seconds and 5 git commands to generate.