diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2017-03-29 08:13:15 -0400 |
---|---|---|
committer | Jani Nikula <jani.nikula@intel.com> | 2017-03-29 08:45:48 -0400 |
commit | dd68f2ba0720e76c3a5bfa3f639c546f926792f5 (patch) | |
tree | 3bc6d688394d47f5e99c1a11694ebf61c25374c9 | |
parent | aa62acfd63e7367872291c15290cb9c29d140926 (diff) |
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: a3aabe86a340 ("drm/i915/execlists: Reinitialise context image after GPU hang")
Signed-off-by: Chris 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.uk
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
(cherry picked from commit 450362d3fe866b14304f309b5fffba0c33fbfbc3)
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170329121315.1290-1-chris@chris-wilson.co.uk
-rw-r--r-- | drivers/gpu/drm/i915/intel_lrc.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.h | 8 |
2 files changed, 10 insertions, 2 deletions
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 471af3b480ad..91555d4e9129 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c | |||
@@ -1440,7 +1440,9 @@ static void reset_common_ring(struct intel_engine_cs *engine, | |||
1440 | GEM_BUG_ON(request->ctx != port[0].request->ctx); | 1440 | GEM_BUG_ON(request->ctx != port[0].request->ctx); |
1441 | 1441 | ||
1442 | /* Reset WaIdleLiteRestore:bdw,skl as well */ | 1442 | /* Reset WaIdleLiteRestore:bdw,skl as well */ |
1443 | request->tail = request->wa_tail - WA_TAIL_DWORDS * sizeof(u32); | 1443 | request->tail = |
1444 | intel_ring_wrap(request->ring, | ||
1445 | request->wa_tail - WA_TAIL_DWORDS*sizeof(u32)); | ||
1444 | } | 1446 | } |
1445 | 1447 | ||
1446 | static int intel_logical_ring_emit_pdps(struct drm_i915_gem_request *req) | 1448 | static int intel_logical_ring_emit_pdps(struct drm_i915_gem_request *req) |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 13dccb18cd43..8cb2078c5bfc 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h | |||
@@ -521,11 +521,17 @@ static inline void intel_ring_advance(struct intel_ring *ring) | |||
521 | */ | 521 | */ |
522 | } | 522 | } |
523 | 523 | ||
524 | static inline u32 | ||
525 | intel_ring_wrap(const struct intel_ring *ring, u32 pos) | ||
526 | { | ||
527 | return pos & (ring->size - 1); | ||
528 | } | ||
529 | |||
524 | static inline u32 intel_ring_offset(struct intel_ring *ring, void *addr) | 530 | static inline u32 intel_ring_offset(struct intel_ring *ring, void *addr) |
525 | { | 531 | { |
526 | /* Don't write ring->size (equivalent to 0) as that hangs some GPUs. */ | 532 | /* Don't write ring->size (equivalent to 0) as that hangs some GPUs. */ |
527 | u32 offset = addr - ring->vaddr; | 533 | u32 offset = addr - ring->vaddr; |
528 | return offset & (ring->size - 1); | 534 | return intel_ring_wrap(ring, offset); |
529 | } | 535 | } |
530 | 536 | ||
531 | int __intel_ring_space(int head, int tail, int size); | 537 | int __intel_ring_space(int head, int tail, int size); |