drm/i915: Reduce nested prepare_remote_context() to a trylock
On context retiring, we may invoke the kernel_context to unpin this
context. Elsewhere, we may use the kernel_context to modify this
context. This currently leads to an AB-BA lock inversion, so we need to
back-off from the contended lock, and repeat.
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=111732
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Fixes: a9877da2d6
("drm/i915/oa: Reconfigure contexts on the fly")
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191126065521.2331017-1-chris@chris-wilson.co.uk
This commit is contained in:
parent
5766a5ffc6
commit
58b4c1a07a
1 changed files with 17 additions and 4 deletions
|
@ -310,10 +310,23 @@ int intel_context_prepare_remote_request(struct intel_context *ce,
|
||||||
GEM_BUG_ON(rq->hw_context == ce);
|
GEM_BUG_ON(rq->hw_context == ce);
|
||||||
|
|
||||||
if (rcu_access_pointer(rq->timeline) != tl) { /* timeline sharing! */
|
if (rcu_access_pointer(rq->timeline) != tl) { /* timeline sharing! */
|
||||||
err = mutex_lock_interruptible_nested(&tl->mutex,
|
/*
|
||||||
SINGLE_DEPTH_NESTING);
|
* Ideally, we just want to insert our foreign fence as
|
||||||
if (err)
|
* a barrier into the remove context, such that this operation
|
||||||
return err;
|
* occurs after all current operations in that context, and
|
||||||
|
* all future operations must occur after this.
|
||||||
|
*
|
||||||
|
* Currently, the timeline->last_request tracking is guarded
|
||||||
|
* by its mutex and so we must obtain that to atomically
|
||||||
|
* insert our barrier. However, since we already hold our
|
||||||
|
* timeline->mutex, we must be careful against potential
|
||||||
|
* inversion if we are the kernel_context as the remote context
|
||||||
|
* will itself poke at the kernel_context when it needs to
|
||||||
|
* unpin. Ergo, if already locked, we drop both locks and
|
||||||
|
* try again (through the magic of userspace repeating EAGAIN).
|
||||||
|
*/
|
||||||
|
if (!mutex_trylock(&tl->mutex))
|
||||||
|
return -EAGAIN;
|
||||||
|
|
||||||
/* Queue this switch after current activity by this context. */
|
/* Queue this switch after current activity by this context. */
|
||||||
err = i915_active_fence_set(&tl->last_request, rq);
|
err = i915_active_fence_set(&tl->last_request, rq);
|
||||||
|
|
Loading…
Add table
Reference in a new issue