summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2019-11-21 10:35:46 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2019-11-21 12:14:45 +0000
commitc95d31c3df1b9ff29bcd85c47324e16d430bbd5a (patch)
tree338abef8d2d085dedf84bb4a6816c82ea1e6c770
parent090a82e9166fbefdb8d371431d4a7f514b3acb86 (diff)
drm/i915/execlists: Lock the request while validating it during promotion
Since the request is already on the HW as we perform its validation, it and even its subsequent barrier may be concurrently retired before we process the assertions. If it is retired already and so off the HW, our assertions become void and we need to ignore them. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112363 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20191121103546.146487-1-chris@chris-wilson.co.uk
-rw-r--r--drivers/gpu/drm/i915/gt/intel_lrc.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c
index b65bc06855b0..da72794f3707 100644
--- a/drivers/gpu/drm/i915/gt/intel_lrc.c
+++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
@@ -1291,38 +1291,53 @@ assert_pending_valid(const struct intel_engine_execlists *execlists,
}
for (port = execlists->pending; (rq = *port); port++) {
+ unsigned long flags;
+ bool ok = true;
+
if (ce == rq->hw_context) {
GEM_TRACE_ERR("Dup context:%llx in pending[%zd]\n",
ce->timeline->fence_context,
port - execlists->pending);
return false;
}
-
ce = rq->hw_context;
+
+ /* Hold tightly onto the lock to prevent concurrent retires! */
+ spin_lock_irqsave_nested(&rq->lock, flags,
+ SINGLE_DEPTH_NESTING);
+
if (i915_request_completed(rq))
- continue;
+ goto unlock;
if (i915_active_is_idle(&ce->active) &&
!i915_gem_context_is_kernel(ce->gem_context)) {
GEM_TRACE_ERR("Inactive context:%llx in pending[%zd]\n",
ce->timeline->fence_context,
port - execlists->pending);
- return false;
+ ok = false;
+ goto unlock;
}
if (!i915_vma_is_pinned(ce->state)) {
GEM_TRACE_ERR("Unpinned context:%llx in pending[%zd]\n",
ce->timeline->fence_context,
port - execlists->pending);
- return false;
+ ok = false;
+ goto unlock;
}
if (!i915_vma_is_pinned(ce->ring->vma)) {
GEM_TRACE_ERR("Unpinned ring:%llx in pending[%zd]\n",
ce->timeline->fence_context,
port - execlists->pending);
- return false;
+ ok = false;
+ goto unlock;
}
+
+unlock:
+ spin_unlock_irqrestore(&rq->lock, flags);
+ if (!ok)
+ return false;
}
return ce;