drm/i915: request ring to be pinned above GUC_WOPCM_TOP
authorDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Fri, 23 Dec 2016 23:56:21 +0000 (15:56 -0800)
committerChris Wilson <chris@chris-wilson.co.uk>
Sat, 24 Dec 2016 10:06:59 +0000 (10:06 +0000)
GuC will validate the ring offset and fail if it is in the
[0, GUC_WOPCM_TOP) range. The bias is conditionally applied only
if GuC loading is enabled (we can't check for guc submission enabled as
in other cases because HuC loading requires this fix).

Note that the default context is processed before enable_guc_loading is
sanitized, so we might still apply the bias to its ring even if it is
not needed.

v2: compute the value during ctx init and pass it to
    intel_ring_pin (Chris), updated commit message

Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Arkadiusz Hiler <arkadiusz.hiler@intel.com>
Cc: Anusha Srivatsa <anusha.srivatsa@intel.com>
Cc: MichaƂ Winiarski <michal.winiarski@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1482537382-28584-1-git-send-email-daniele.ceraolospurio@intel.com
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem_context.c
drivers/gpu/drm/i915/intel_lrc.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_ringbuffer.h

index 32e2d743102522665ac2f16db1326c275f65246b..5194686ea524ba13196882bad532071d088fa10c 100644 (file)
@@ -1087,6 +1087,7 @@ struct i915_gem_context {
        int priority; /* greater priorities are serviced first */
 
        u32 ggtt_alignment;
+       u32 ggtt_offset_bias;
 
        struct intel_context {
                struct i915_vma *state;
index 15b25c1b1f4dac8809fd29555c1823160aa53b0f..48e4ed5bb209a4eb1f0b5f13e6c82beaad18afc6 100644 (file)
@@ -335,6 +335,15 @@ __create_hw_context(struct drm_i915_private *dev_priv,
                             GEN8_CTX_ADDRESSING_MODE_SHIFT;
        ATOMIC_INIT_NOTIFIER_HEAD(&ctx->status_notifier);
 
+       /* GuC requires the ring to be placed above GUC_WOPCM_TOP. If GuC is not
+        * present or not in use we still need a small bias as ring wraparound
+        * at offset 0 sometimes hangs. No idea why.
+        */
+       if (HAS_GUC(dev_priv) && i915.enable_guc_loading)
+               ctx->ggtt_offset_bias = GUC_WOPCM_TOP;
+       else
+               ctx->ggtt_offset_bias = 4096;
+
        return ctx;
 
 err_pid:
index d322d3c11201d1ee044c92bcc1d74c90199d2367..cec9037baf655259cbd4015dd528db279e763d31 100644 (file)
@@ -796,7 +796,7 @@ static int execlists_context_pin(struct intel_engine_cs *engine,
                goto unpin_vma;
        }
 
-       ret = intel_ring_pin(ce->ring);
+       ret = intel_ring_pin(ce->ring, ctx->ggtt_offset_bias);
        if (ret)
                goto unpin_map;
 
index 69ccf4fd22f0c7958519df6abe060f6182e8d1c5..e84d488e167adfceac22d43e1f7e1e3ef09495ef 100644 (file)
@@ -1805,10 +1805,9 @@ static int init_phys_status_page(struct intel_engine_cs *engine)
        return 0;
 }
 
-int intel_ring_pin(struct intel_ring *ring)
+int intel_ring_pin(struct intel_ring *ring, unsigned int offset_bias)
 {
-       /* Ring wraparound at offset 0 sometimes hangs. No idea why. */
-       unsigned int flags = PIN_GLOBAL | PIN_OFFSET_BIAS | 4096;
+       unsigned int flags;
        enum i915_map_type map;
        struct i915_vma *vma = ring->vma;
        void *addr;
@@ -1818,6 +1817,9 @@ int intel_ring_pin(struct intel_ring *ring)
 
        map = HAS_LLC(ring->engine->i915) ? I915_MAP_WB : I915_MAP_WC;
 
+       flags = PIN_GLOBAL;
+       if (offset_bias)
+               flags |= PIN_OFFSET_BIAS | offset_bias;
        if (vma->obj->stolen)
                flags |= PIN_MAPPABLE;
 
@@ -2046,7 +2048,8 @@ static int intel_init_ring_buffer(struct intel_engine_cs *engine)
                        goto error;
        }
 
-       ret = intel_ring_pin(ring);
+       /* Ring wraparound at offset 0 sometimes hangs. No idea why. */
+       ret = intel_ring_pin(ring, 4096);
        if (ret) {
                intel_ring_free(ring);
                goto error;
index 0969de7d5ab737f93c76c6d247edd47e373811c3..79c2b8d72322cf58cacd3f732c5a55ce0ef68f3b 100644 (file)
@@ -483,7 +483,7 @@ intel_write_status_page(struct intel_engine_cs *engine,
 
 struct intel_ring *
 intel_engine_create_ring(struct intel_engine_cs *engine, int size);
-int intel_ring_pin(struct intel_ring *ring);
+int intel_ring_pin(struct intel_ring *ring, unsigned int offset_bias);
 void intel_ring_unpin(struct intel_ring *ring);
 void intel_ring_free(struct intel_ring *ring);