drm/i915/ringbuffer: 2-step restart
authorChris Wilson <chris@chris-wilson.co.uk>
Mon, 26 Nov 2018 12:28:21 +0000 (12:28 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Mon, 26 Nov 2018 14:20:43 +0000 (14:20 +0000)
We may be simply restarting too fast for the culmudgeonly gen3/gen4 as
we still see missing interrupts following a reset. So let's try
restarting a little slower, first wake up the ring empty and then tell
it about the work it has to perform.

References: https://bugs.freedesktop.org/show_bug.cgi?id=108735
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20181126122821.4537-1-chris@chris-wilson.co.uk
drivers/gpu/drm/i915/intel_ringbuffer.c

index 87eebc13c0d86bb2649c58654b618240d9a0a76e..e18a64d418433c0f2d96d0367fd3d58109c0a6a0 100644 (file)
@@ -546,10 +546,11 @@ static int init_ring_common(struct intel_engine_cs *engine)
        /* Check that the ring offsets point within the ring! */
        GEM_BUG_ON(!intel_ring_offset_valid(ring, ring->head));
        GEM_BUG_ON(!intel_ring_offset_valid(ring, ring->tail));
-
        intel_ring_update_space(ring);
+
+       /* First wake the ring up to an empty/idle ring */
        I915_WRITE_HEAD(engine, ring->head);
-       I915_WRITE_TAIL(engine, ring->tail);
+       I915_WRITE_TAIL(engine, ring->head);
        (void)I915_READ_TAIL(engine);
 
        I915_WRITE_CTL(engine, RING_CTL_SIZE(ring->size) | RING_VALID);
@@ -574,6 +575,12 @@ static int init_ring_common(struct intel_engine_cs *engine)
        if (INTEL_GEN(dev_priv) > 2)
                I915_WRITE_MODE(engine, _MASKED_BIT_DISABLE(STOP_RING));
 
+       /* Now awake, let it get started */
+       if (ring->tail != ring->head) {
+               I915_WRITE_TAIL(engine, ring->tail);
+               (void)I915_READ_TAIL(engine);
+       }
+
        /* Papering over lost _interrupts_ immediately following the restart */
        intel_engine_wakeup(engine);
 out: