drm/i915: Reorder semaphore deadlock check
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>
This commit is contained in:
parent
eee73b4626
commit
4be173813e
|
@ -2847,10 +2847,14 @@ static int semaphore_passed(struct intel_engine_cs *ring)
|
||||||
struct intel_engine_cs *signaller;
|
struct intel_engine_cs *signaller;
|
||||||
u32 seqno, ctl;
|
u32 seqno, ctl;
|
||||||
|
|
||||||
ring->hangcheck.deadlock = true;
|
ring->hangcheck.deadlock++;
|
||||||
|
|
||||||
signaller = semaphore_waits_for(ring, &seqno);
|
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;
|
return -1;
|
||||||
|
|
||||||
/* cursory check for an unkickable deadlock */
|
/* cursory check for an unkickable deadlock */
|
||||||
|
@ -2858,7 +2862,13 @@ static int semaphore_passed(struct intel_engine_cs *ring)
|
||||||
if (ctl & RING_WAIT_SEMAPHORE && semaphore_passed(signaller) < 0)
|
if (ctl & RING_WAIT_SEMAPHORE && semaphore_passed(signaller) < 0)
|
||||||
return -1;
|
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)
|
static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv)
|
||||||
|
@ -2867,7 +2877,7 @@ static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for_each_ring(ring, dev_priv, i)
|
for_each_ring(ring, dev_priv, i)
|
||||||
ring->hangcheck.deadlock = false;
|
ring->hangcheck.deadlock = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum intel_ring_hangcheck_action
|
static enum intel_ring_hangcheck_action
|
||||||
|
|
|
@ -55,7 +55,7 @@ struct intel_ring_hangcheck {
|
||||||
u32 seqno;
|
u32 seqno;
|
||||||
int score;
|
int score;
|
||||||
enum intel_ring_hangcheck_action action;
|
enum intel_ring_hangcheck_action action;
|
||||||
bool deadlock;
|
int deadlock;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct intel_ringbuffer {
|
struct intel_ringbuffer {
|
||||||
|
|
Loading…
Reference in New Issue