Commit f6a7c21c authored by Chris Wilson's avatar Chris Wilson
Browse files

drm/i915/execlists: Verify we don't submit two identical CCIDs

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: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarMika Kuoppala <mika.kuoppala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200428184751.11257-3-chris@chris-wilson.co.uk
parent 5c4a53e3
Loading
Loading
Loading
Loading
+28 −9
Original line number Diff line number Diff line
@@ -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;