aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-06-06 05:22:29 -0400
committerJani Nikula <jani.nikula@intel.com>2014-06-11 04:06:43 -0400
commit4be173813e57c7298103a83155c2391b5b167b4c (patch)
tree594dce46be8caef7687d138cfc21ef580da6f01d /drivers
parenteee73b46261325eb140d899b5371f49b02d88f63 (diff)
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c18
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.h2
2 files changed, 15 insertions, 5 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index cf288a95347c..69aaa1100986 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2847,10 +2847,14 @@ static int semaphore_passed(struct intel_engine_cs *ring)
2847 struct intel_engine_cs *signaller; 2847 struct intel_engine_cs *signaller;
2848 u32 seqno, ctl; 2848 u32 seqno, ctl;
2849 2849
2850 ring->hangcheck.deadlock = true; 2850 ring->hangcheck.deadlock++;
2851 2851
2852 signaller = semaphore_waits_for(ring, &seqno); 2852 signaller = semaphore_waits_for(ring, &seqno);
2853 if (signaller == NULL || signaller->hangcheck.deadlock) 2853 if (signaller == NULL)
2854 return -1;
2855
2856 /* Prevent pathological recursion due to driver bugs */
2857 if (signaller->hangcheck.deadlock >= I915_NUM_RINGS)
2854 return -1; 2858 return -1;
2855 2859
2856 /* cursory check for an unkickable deadlock */ 2860 /* cursory check for an unkickable deadlock */
@@ -2858,7 +2862,13 @@ static int semaphore_passed(struct intel_engine_cs *ring)
2858 if (ctl & RING_WAIT_SEMAPHORE && semaphore_passed(signaller) < 0) 2862 if (ctl & RING_WAIT_SEMAPHORE && semaphore_passed(signaller) < 0)
2859 return -1; 2863 return -1;
2860 2864
2861 return i915_seqno_passed(signaller->get_seqno(signaller, false), seqno); 2865 if (i915_seqno_passed(signaller->get_seqno(signaller, false), seqno))
2866 return 1;
2867
2868 if (signaller->hangcheck.deadlock)
2869 return -1;
2870
2871 return 0;
2862} 2872}
2863 2873
2864static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv) 2874static 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)
2867 int i; 2877 int i;
2868 2878
2869 for_each_ring(ring, dev_priv, i) 2879 for_each_ring(ring, dev_priv, i)
2870 ring->hangcheck.deadlock = false; 2880 ring->hangcheck.deadlock = 0;
2871} 2881}
2872 2882
2873static enum intel_ring_hangcheck_action 2883static enum intel_ring_hangcheck_action
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 910c83cf7d44..e72017bdcd7f 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -55,7 +55,7 @@ struct intel_ring_hangcheck {
55 u32 seqno; 55 u32 seqno;
56 int score; 56 int score;
57 enum intel_ring_hangcheck_action action; 57 enum intel_ring_hangcheck_action action;
58 bool deadlock; 58 int deadlock;
59}; 59};
60 60
61struct intel_ringbuffer { 61struct intel_ringbuffer {