From: John Harrison <[email protected]>

The GPU scheduler can cause requests to complete out of order. For example,
because one request pre-empted others that had already been submitted. This
means the simple seqno comparison is not necessarily valid. Instead, a check
against what the scheduler is currently doing must be made to determine if a
request has really completed.

Change-Id: I149250a8f9382586514ca324aba1c53063b83e19
For: VIZ-1587
Signed-off-by: John Harrison <[email protected]>
---
 drivers/gpu/drm/i915/i915_drv.h       |  2 ++
 drivers/gpu/drm/i915/i915_gem.c       | 13 +++++++++++--
 drivers/gpu/drm/i915/i915_scheduler.c | 31 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_scheduler.h |  2 ++
 4 files changed, 46 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 7d2a494..58f53ec 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2238,6 +2238,8 @@ struct drm_i915_gem_request {
        /** process identifier submitting this request */
        struct pid *pid;
 
+       struct i915_scheduler_queue_entry       *scheduler_qe;
+
        /**
         * The ELSP only accepts two elements at a time, so we queue
         * context/tail pairs on a given queue (ring->execlist_queue) until the
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 56405cd..e3c4032 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2772,6 +2772,7 @@ void i915_gem_request_notify(struct intel_engine_cs *ring)
 {
        struct drm_i915_gem_request *req, *req_next;
        unsigned long flags;
+       bool complete;
        u32 seqno;
        LIST_HEAD(free_list);
 
@@ -2785,8 +2786,13 @@ void i915_gem_request_notify(struct intel_engine_cs 
*ring)
        spin_lock_irqsave(&ring->fence_lock, flags);
        list_for_each_entry_safe(req, req_next, &ring->fence_signal_list, 
signal_list) {
                if (!req->cancelled) {
-                       if (!i915_seqno_passed(seqno, req->seqno))
-                               continue;
+                       if (i915_scheduler_is_request_tracked(req, &complete, 
NULL)) {
+                               if (!complete)
+                                       continue;
+                       } else {
+                               if (!i915_seqno_passed(seqno, req->seqno))
+                                       continue;
+                       }
 
                        fence_signal_locked(&req->fence);
                        trace_i915_gem_request_complete(req);
@@ -2811,6 +2817,9 @@ void i915_gem_request_notify(struct intel_engine_cs *ring)
 
                i915_gem_request_unreference(req);
        }
+
+       /* Necessary? Or does the fence_signal() call do an implicit wakeup? */
+       wake_up_all(&ring->irq_queue);
 }
 
 static void i915_fence_timeline_value_str(struct fence *fence, char *str, int 
size)
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c 
b/drivers/gpu/drm/i915/i915_scheduler.c
index 71d8df7..0d1cbe3 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -119,6 +119,9 @@ int i915_scheduler_queue_execbuffer(struct 
i915_scheduler_queue_entry *qe)
        node->stamp  = stamp;
        i915_gem_request_reference(node->params.request);
 
+       BUG_ON(node->params.request->scheduler_qe);
+       node->params.request->scheduler_qe = node;
+
        /* Need to determine the number of incomplete entries in the list as
         * that will be the maximum size of the dependency list.
         *
@@ -363,6 +366,13 @@ static void i915_scheduler_seqno_complete(struct 
intel_engine_cs *ring, uint32_t
                got_changes = true;
        }
 
+       /*
+        * Avoid issues with requests not being signalled because their
+        * interrupt has already passed.
+        */
+       if (got_changes)
+               i915_gem_request_notify(ring);
+
        /* Should submit new work here if flight list is empty but the DRM
         * mutex lock might not be available if a '__wait_request()' call is
         * blocking the system. */
@@ -504,6 +514,7 @@ int i915_scheduler_remove(struct intel_engine_cs *ring)
                        
i915_gem_execbuff_release_batch_obj(node->params.batch_obj);
 
                /* Free everything that is owned by the node: */
+               node->params.request->scheduler_qe = NULL;
                i915_gem_request_unreference(node->params.request);
                kfree(node->params.cliprects);
                kfree(node->dep_list);
@@ -774,3 +785,23 @@ static int i915_scheduler_remove_dependent(struct 
i915_scheduler *scheduler,
 
        return 0;
 }
+
+bool i915_scheduler_is_request_tracked(struct drm_i915_gem_request *req,
+                                      bool *completed, bool *busy)
+{
+       struct drm_i915_private *dev_priv = req->ring->dev->dev_private;
+       struct i915_scheduler   *scheduler = dev_priv->scheduler;
+
+       if (!scheduler)
+               return false;
+
+       if (req->scheduler_qe == NULL)
+               return false;
+
+       if (completed)
+               *completed = I915_SQS_IS_COMPLETE(req->scheduler_qe);
+       if (busy)
+               *busy      = I915_SQS_IS_QUEUED(req->scheduler_qe);
+
+       return true;
+}
diff --git a/drivers/gpu/drm/i915/i915_scheduler.h 
b/drivers/gpu/drm/i915/i915_scheduler.h
index 0c5fc7f..6b2585a 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.h
+++ b/drivers/gpu/drm/i915/i915_scheduler.h
@@ -87,5 +87,7 @@ enum {
 int         i915_scheduler_init(struct drm_device *dev);
 int         i915_scheduler_queue_execbuffer(struct i915_scheduler_queue_entry 
*qe);
 int         i915_scheduler_handle_irq(struct intel_engine_cs *ring);
+bool        i915_scheduler_is_request_tracked(struct drm_i915_gem_request *req,
+                                             bool *completed, bool *busy);
 
 #endif  /* _I915_SCHEDULER_H_ */
-- 
1.9.1

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to