drm/i915/execlists: Verify we don't submit two identical CCIDs
authorChris Wilson <chris@chris-wilson.co.uk>
Tue, 28 Apr 2020 18:47:51 +0000 (19:47 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Tue, 28 Apr 2020 21:17:36 +0000 (22:17 +0100)
Check that we do not submit two contexts into ELSP with the same CCID
[upper portion of the descriptor].

References: https://gitlab.freedesktop.org/drm/intel/-/issues/1793
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200428184751.11257-3-chris@chris-wilson.co.uk
drivers/gpu/drm/i915/gt/intel_lrc.c

index 05e2bb483db3a40c3f8be1850ef30877ea5761ac..90acc3d2440b8e53485b83460440a8c9f54f6f46 100644 (file)
@@ -1612,9 +1612,12 @@ static __maybe_unused bool
 assert_pending_valid(const struct intel_engine_execlists *execlists,
                     const char *msg)
 {
+       struct intel_engine_cs *engine =
+               container_of(execlists, typeof(*engine), execlists);
        struct i915_request * const *port, *rq;
        struct intel_context *ce = NULL;
        bool sentinel = false;
+       u32 ccid = -1;
 
        trace_ports(execlists, msg, execlists->pending);
 
@@ -1623,13 +1626,14 @@ assert_pending_valid(const struct intel_engine_execlists *execlists,
                return true;
 
        if (!execlists->pending[0]) {
-               GEM_TRACE_ERR("Nothing pending for promotion!\n");
+               GEM_TRACE_ERR("%s: Nothing pending for promotion!\n",
+                             engine->name);
                return false;
        }
 
        if (execlists->pending[execlists_num_ports(execlists)]) {
-               GEM_TRACE_ERR("Excess pending[%d] for promotion!\n",
-                             execlists_num_ports(execlists));
+               GEM_TRACE_ERR("%s: Excess pending[%d] for promotion!\n",
+                             engine->name, execlists_num_ports(execlists));
                return false;
        }
 
@@ -1641,20 +1645,31 @@ assert_pending_valid(const struct intel_engine_execlists *execlists,
                GEM_BUG_ON(!i915_request_is_active(rq));
 
                if (ce == rq->context) {
-                       GEM_TRACE_ERR("Dup context:%llx in pending[%zd]\n",
+                       GEM_TRACE_ERR("%s: Dup context:%llx in pending[%zd]\n",
+                                     engine->name,
                                      ce->timeline->fence_context,
                                      port - execlists->pending);
                        return false;
                }
                ce = rq->context;
 
+               if (ccid == ce->lrc.ccid) {
+                       GEM_TRACE_ERR("%s: Dup ccid:%x context:%llx in pending[%zd]\n",
+                                     engine->name,
+                                     ccid, ce->timeline->fence_context,
+                                     port - execlists->pending);
+                       return false;
+               }
+               ccid = ce->lrc.ccid;
+
                /*
                 * Sentinels are supposed to be lonely so they flush the
                 * current exection off the HW. Check that they are the
                 * only request in the pending submission.
                 */
                if (sentinel) {
-                       GEM_TRACE_ERR("context:%llx after sentinel in pending[%zd]\n",
+                       GEM_TRACE_ERR("%s: context:%llx after sentinel in pending[%zd]\n",
+                                     engine->name,
                                      ce->timeline->fence_context,
                                      port - execlists->pending);
                        return false;
@@ -1662,7 +1677,8 @@ assert_pending_valid(const struct intel_engine_execlists *execlists,
 
                sentinel = i915_request_has_sentinel(rq);
                if (sentinel && port != execlists->pending) {
-                       GEM_TRACE_ERR("sentinel context:%llx not in prime position[%zd]\n",
+                       GEM_TRACE_ERR("%s: sentinel context:%llx not in prime position[%zd]\n",
+                                     engine->name,
                                      ce->timeline->fence_context,
                                      port - execlists->pending);
                        return false;
@@ -1677,7 +1693,8 @@ assert_pending_valid(const struct intel_engine_execlists *execlists,
 
                if (i915_active_is_idle(&ce->active) &&
                    !intel_context_is_barrier(ce)) {
-                       GEM_TRACE_ERR("Inactive context:%llx in pending[%zd]\n",
+                       GEM_TRACE_ERR("%s: Inactive context:%llx in pending[%zd]\n",
+                                     engine->name,
                                      ce->timeline->fence_context,
                                      port - execlists->pending);
                        ok = false;
@@ -1685,7 +1702,8 @@ assert_pending_valid(const struct intel_engine_execlists *execlists,
                }
 
                if (!i915_vma_is_pinned(ce->state)) {
-                       GEM_TRACE_ERR("Unpinned context:%llx in pending[%zd]\n",
+                       GEM_TRACE_ERR("%s: Unpinned context:%llx in pending[%zd]\n",
+                                     engine->name,
                                      ce->timeline->fence_context,
                                      port - execlists->pending);
                        ok = false;
@@ -1693,7 +1711,8 @@ assert_pending_valid(const struct intel_engine_execlists *execlists,
                }
 
                if (!i915_vma_is_pinned(ce->ring->vma)) {
-                       GEM_TRACE_ERR("Unpinned ring:%llx in pending[%zd]\n",
+                       GEM_TRACE_ERR("%s: Unpinned ring:%llx in pending[%zd]\n",
+                                     engine->name,
                                      ce->timeline->fence_context,
                                      port - execlists->pending);
                        ok = false;