aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/gpu/drm/i915/gt/intel_lrc.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2020-02-20 07:50:20 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2020-02-20 13:27:23 +0000
commit66940061a52fba730fdb49e133502e19be684202 (patch)
tree95e7e36c40ff4e23a8fb5daf9c94e432cb212e92 /drivers/gpu/drm/i915/gt/intel_lrc.c
parentdrm/i915: remove the other slab_dependencies (diff)
downloadwireguard-linux-66940061a52fba730fdb49e133502e19be684202.tar.xz
wireguard-linux-66940061a52fba730fdb49e133502e19be684202.zip
drm/i915/gt: Protect signaler walk with RCU
While we know that the waiters cannot disappear as we walk our list (only that they might be added), the same cannot be said for our signalers as they may be completed by the HW and retired as we process this request. Ergo we need to use rcu to protect the list iteration and remember to mark up the list_del_rcu. v2: Mark the deps as safe-for-rcu Fixes: 793c22617367 ("drm/i915/gt: Protect execlists_hold/unhold from new waiters") Fixes: 32ff621fd744 ("drm/i915/gt: Allow temporary suspension of inflight requests") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Chris Wilson <chris@chris-wilson.co.uk> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com> Cc: Matthew Auld <matthew.auld@intel.com> Reviewed-by: Matthew Auld <matthew.auld@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200220075025.1539375-1-chris@chris-wilson.co.uk
Diffstat (limited to 'drivers/gpu/drm/i915/gt/intel_lrc.c')
-rw-r--r--drivers/gpu/drm/i915/gt/intel_lrc.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c
index ba31cbe8c68e..47561dc29304 100644
--- a/drivers/gpu/drm/i915/gt/intel_lrc.c
+++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
@@ -1668,9 +1668,9 @@ last_active(const struct intel_engine_execlists *execlists)
wait_link)
#define for_each_signaler(p__, rq__) \
- list_for_each_entry_lockless(p__, \
- &(rq__)->sched.signalers_list, \
- signal_link)
+ list_for_each_entry_rcu(p__, \
+ &(rq__)->sched.signalers_list, \
+ signal_link)
static void defer_request(struct i915_request *rq, struct list_head * const pl)
{
@@ -2533,11 +2533,13 @@ unlock:
static bool hold_request(const struct i915_request *rq)
{
struct i915_dependency *p;
+ bool result = false;
/*
* If one of our ancestors is on hold, we must also be on hold,
* otherwise we will bypass it and execute before it.
*/
+ rcu_read_lock();
for_each_signaler(p, rq) {
const struct i915_request *s =
container_of(p->signaler, typeof(*s), sched);
@@ -2545,11 +2547,13 @@ static bool hold_request(const struct i915_request *rq)
if (s->engine != rq->engine)
continue;
- if (i915_request_on_hold(s))
- return true;
+ result = i915_request_on_hold(s);
+ if (result)
+ break;
}
+ rcu_read_unlock();
- return false;
+ return result;
}
static void __execlists_unhold(struct i915_request *rq)