The HW only accepts offsets within ring->size, and fails peculiarly if
the RING_HEAD or RING_TAIL is set to ring->size. Therefore whenever we
set ring->head/ring->tail we want to make sure it is within value (using
intel_ring_wrap()).

Signed-off-by: Chris Wilson <[email protected]>
Cc: Joonas Lahtinen <[email protected]>
Cc: Mika Kuoppala <[email protected]>
Cc: Matthew Auld <[email protected]>
Cc: Tvrtko Ursulin <[email protected]>
---
 drivers/gpu/drm/i915/intel_ringbuffer.c |  5 +++++
 drivers/gpu/drm/i915/intel_ringbuffer.h | 12 ++++++++++++
 2 files changed, 17 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c 
b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 6ac3b65373fe..9fac0e0f078e 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -496,6 +496,10 @@ static int init_ring_common(struct intel_engine_cs *engine)
                DRM_DEBUG_DRIVER("%s initialization failed [head=%08x], 
fudging\n",
                                 engine->name, I915_READ_HEAD(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);
        I915_WRITE_HEAD(engine, ring->head);
        I915_WRITE_TAIL(engine, ring->tail);
@@ -1064,6 +1068,7 @@ int intel_ring_pin(struct intel_ring *ring,
 
 void intel_ring_reset(struct intel_ring *ring, u32 tail)
 {
+       tail = intel_ring_wrap(ring, tail);
        ring->tail = tail;
        ring->head = tail;
        ring->emit = tail;
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h 
b/drivers/gpu/drm/i915/intel_ringbuffer.h
index b44c67849749..1d8140ac2016 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -805,6 +805,18 @@ static inline u32 intel_ring_wrap(const struct intel_ring 
*ring, u32 pos)
        return pos & (ring->size - 1);
 }
 
+static inline bool
+intel_ring_offset_valid(const struct intel_ring *ring, u32 pos)
+{
+       if (pos & -ring->size) /* must be strictly within the ring */
+               return false;
+
+       if (!IS_ALIGNED(pos, 8)) /* must be qword aligned */
+               return false;
+
+       return true;
+}
+
 static inline u32 intel_ring_offset(const struct i915_request *rq, void *addr)
 {
        /* Don't write ring->size (equivalent to 0) as that hangs some GPUs. */
-- 
2.17.1

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to