{
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_engine_cs *engine;
-       int ret, j;
+       int ret;
 
        /* Carefully retire all requests without writing to the rings */
        for_each_engine(engine, dev_priv) {
        i915_gem_retire_requests(dev);
 
        /* Finally reset hw state */
-       for_each_engine(engine, dev_priv) {
+       for_each_engine(engine, dev_priv)
                intel_ring_init_seqno(engine, seqno);
 
-               for (j = 0; j < ARRAY_SIZE(engine->semaphore.sync_seqno); j++)
-                       engine->semaphore.sync_seqno[j] = 0;
-       }
-
        return 0;
 }
 
 
 {
        struct drm_i915_private *dev_priv = to_i915(engine->dev);
 
+       /* Our semaphore implementation is strictly monotonic (i.e. we proceed
+        * so long as the semaphore value in the register/page is greater
+        * than the sync value), so whenever we reset the seqno,
+        * so long as we reset the tracking semaphore value to 0, it will
+        * always be before the next request's seqno. If we don't reset
+        * the semaphore value, then when the seqno moves backwards all
+        * future waits will complete instantly (causing rendering corruption).
+        */
        if (INTEL_INFO(dev_priv)->gen == 6 || INTEL_INFO(dev_priv)->gen == 7) {
                I915_WRITE(RING_SYNC_0(engine->mmio_base), 0);
                I915_WRITE(RING_SYNC_1(engine->mmio_base), 0);
                if (HAS_VEBOX(dev_priv))
                        I915_WRITE(RING_SYNC_2(engine->mmio_base), 0);
        }
+       memset(engine->semaphore.sync_seqno, 0,
+              sizeof(engine->semaphore.sync_seqno));
 
        engine->set_seqno(engine, seqno);
+
        engine->hangcheck.seqno = seqno;
 }