Commit 450362d3 authored by Chris Wilson's avatar Chris Wilson

drm/i915/execlists: Wrap tail pointer after reset tweaking

If the request->wa_tail is 0 (because it landed exactly on the end of
the ringbuffer), when we reconstruct request->tail following a reset we
fill in an illegal value (-8 or 0x001ffff8). As a result, RING_HEAD is
never able to catch up with RING_TAIL and the GPU spins endlessly. If
the ring contains a couple of breadcrumbs, even our hangcheck is unable
to catch the busy-looping as the ACTHD and seqno continually advance.

v2: Move the wrap into a common intel_ring_wrap().

Fixes: a3aabe86 ("drm/i915/execlists: Reinitialise context image after GPU hang")
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
Cc: <stable@vger.kernel.org> # v4.10+
Link: http://patchwork.freedesktop.org/patch/msgid/20170327130009.4678-1-chris@chris-wilson.co.ukReviewed-by: default avatarMika Kuoppala <mika.kuoppala@intel.com>
parent f9407ae1
...@@ -1278,7 +1278,9 @@ static void reset_common_ring(struct intel_engine_cs *engine, ...@@ -1278,7 +1278,9 @@ static void reset_common_ring(struct intel_engine_cs *engine,
GEM_BUG_ON(request->ctx != port[0].request->ctx); GEM_BUG_ON(request->ctx != port[0].request->ctx);
/* Reset WaIdleLiteRestore:bdw,skl as well */ /* Reset WaIdleLiteRestore:bdw,skl as well */
request->tail = request->wa_tail - WA_TAIL_DWORDS * sizeof(u32); request->tail =
intel_ring_wrap(request->ring,
request->wa_tail - WA_TAIL_DWORDS*sizeof(u32));
GEM_BUG_ON(!IS_ALIGNED(request->tail, 8)); GEM_BUG_ON(!IS_ALIGNED(request->tail, 8));
} }
......
...@@ -515,12 +515,18 @@ intel_ring_advance(struct drm_i915_gem_request *req, u32 *cs) ...@@ -515,12 +515,18 @@ intel_ring_advance(struct drm_i915_gem_request *req, u32 *cs)
} }
static inline u32 static inline u32
intel_ring_offset(struct drm_i915_gem_request *req, void *addr) intel_ring_wrap(const struct intel_ring *ring, u32 pos)
{
return pos & (ring->size - 1);
}
static inline u32
intel_ring_offset(const struct drm_i915_gem_request *req, void *addr)
{ {
/* Don't write ring->size (equivalent to 0) as that hangs some GPUs. */ /* Don't write ring->size (equivalent to 0) as that hangs some GPUs. */
u32 offset = addr - req->ring->vaddr; u32 offset = addr - req->ring->vaddr;
GEM_BUG_ON(offset > req->ring->size); GEM_BUG_ON(offset > req->ring->size);
return offset & (req->ring->size - 1); return intel_ring_wrap(req->ring, offset);
} }
void intel_ring_update_space(struct intel_ring *ring); void intel_ring_update_space(struct intel_ring *ring);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment