@@ -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;
@@ -335,6 +335,15 @@ static int assign_hw_id(struct drm_i915_private *dev_priv, unsigned *out)
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:
@@ -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;
@@ -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 = PIN_GLOBAL;
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;
+ 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;
@@ -483,7 +483,7 @@ struct intel_engine_cs {
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);