Merge tag 'v3.16-rc4' into drm-intel-next-queued
[linux-drm-fsl-dcu.git] / drivers / gpu / drm / i915 / i915_irq.c
index 73f1849cfb753ef646e6da183c776b0092467987..1c1ec22bc7ef0807e268e0a9a0fe69d627e804ae 100644 (file)
@@ -2433,7 +2433,7 @@ static void i915_error_work_func(struct work_struct *work)
                         * updates before
                         * the counter increment.
                         */
-                       smp_mb__before_atomic_inc();
+                       smp_mb__before_atomic();
                        atomic_inc(&dev_priv->gpu_error.reset_counter);
 
                        kobject_uevent_env(&dev->primary->kdev->kobj,
@@ -2878,10 +2878,14 @@ 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 */
@@ -2889,7 +2893,13 @@ static int semaphore_passed(struct intel_engine_cs *ring)
        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)
@@ -2898,7 +2908,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