drm/i915: Check waiter->seqno carefully in case of preemption
authorChris Wilson <chris@chris-wilson.co.uk>
Mon, 18 Sep 2017 16:27:34 +0000 (17:27 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Fri, 22 Sep 2017 11:47:19 +0000 (12:47 +0100)
If preemption occurs at precisely the right moment, we may decide that
the wait is complete even though the wait's request is no longer
executing (having been preempted). We handle this situation by double
checking that request following deciding whether the wait is complete.

Reported-by: Michał Winiarski <michal.winiarski@intel.com>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Michał Winiarski <michal.winiarski@intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20170918162734.21294-2-chris@chris-wilson.co.uk
Reviewed-by: Michał Winiarski <michal.winiarski@intel.com>
drivers/gpu/drm/i915/i915_irq.c

index 2190e42ba310b94427a228bae27280d13b8b7b19..bd38c6983eec7dcead1aa465f36bde9e0f9be239 100644 (file)
@@ -1053,10 +1053,13 @@ static void notify_ring(struct intel_engine_cs *engine)
                 */
                if (i915_seqno_passed(intel_engine_get_seqno(engine),
                                      wait->seqno)) {
+                       struct drm_i915_gem_request *waiter = wait->request;
+
                        wakeup = true;
                        if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
-                                     &wait->request->fence.flags))
-                               rq = i915_gem_request_get(wait->request);
+                                     &waiter->fence.flags) &&
+                           intel_wait_check_request(wait, waiter))
+                               rq = i915_gem_request_get(waiter);
                }
 
                if (wakeup)