Skip to content

Commit

Permalink
drm/i915: Reorder semaphore deadlock check
Browse files Browse the repository at this point in the history
If a semaphore is waiting on another ring, which in turn happens to be
waiting on the first ring, but that second semaphore has been signalled,
we will be able to kick the second ring and so can treat the first ring
as a valid WAIT and not as HUNG.

v2: Be paranoid and cap the potential recursion depth whilst visiting
the semaphore signallers. (Mika)

References: https://bugs.freedesktop.org/show_bug.cgi?id=54226
References: https://bugs.freedesktop.org/show_bug.cgi?id=75502
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Cc: stable@vger.kernel.org
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
  • Loading branch information
Chris Wilson authored and Jani Nikula committed Jun 11, 2014
1 parent eee73b4 commit 4be1738
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 5 deletions.
18 changes: 14 additions & 4 deletions drivers/gpu/drm/i915/i915_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -2847,18 +2847,28 @@ static int semaphore_passed(struct intel_engine_cs *ring)
struct intel_engine_cs *signaller;
u32 seqno, ctl;

ring->hangcheck.deadlock = true;
ring->hangcheck.deadlock++;

signaller = semaphore_waits_for(ring, &seqno);
if (signaller == NULL || signaller->hangcheck.deadlock)
if (signaller == NULL)
return -1;

/* Prevent pathological recursion due to driver bugs */
if (signaller->hangcheck.deadlock >= I915_NUM_RINGS)
return -1;

/* cursory check for an unkickable deadlock */
ctl = I915_READ_CTL(signaller);
if (ctl & RING_WAIT_SEMAPHORE && semaphore_passed(signaller) < 0)
return -1;

return i915_seqno_passed(signaller->get_seqno(signaller, false), seqno);
if (i915_seqno_passed(signaller->get_seqno(signaller, false), seqno))
return 1;

if (signaller->hangcheck.deadlock)
return -1;

return 0;
}

static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv)
Expand All @@ -2867,7 +2877,7 @@ static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv)
int i;

for_each_ring(ring, dev_priv, i)
ring->hangcheck.deadlock = false;
ring->hangcheck.deadlock = 0;
}

static enum intel_ring_hangcheck_action
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915/intel_ringbuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ struct intel_ring_hangcheck {
u32 seqno;
int score;
enum intel_ring_hangcheck_action action;
bool deadlock;
int deadlock;
};

struct intel_ringbuffer {
Expand Down

0 comments on commit 4be1738

Please sign in to comment.