Skip to content

Commit c0fa92e

Browse files
icklerodrigovivi
authored andcommitted
drm/i915: Protect request peeking with RCU
Since the execlists_active() is no longer protected by the engine->active.lock, we need to protect the request pointer with RCU to prevent it being freed as we evaluate whether or not we need to preempt. Fixes: df40306 ("drm/i915/execlists: Lift process_csb() out of the irq-off spinlock") Signed-off-by: Chris Wilson <[email protected]> Cc: Mika Kuoppala <[email protected]> Cc: Tvrtko Ursulin <[email protected]> Reviewed-by: Mika Kuoppala <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] (cherry picked from commit 7d14863) Signed-off-by: Joonas Lahtinen <[email protected]> (cherry picked from commit 8eb4704) (cherry picked from commit 7e27238e149ce4f00d9cd801fe3aa0ea55e986a2) Signed-off-by: Rodrigo Vivi <[email protected]>
1 parent 2d691ae commit c0fa92e

File tree

1 file changed

+39
-11
lines changed

1 file changed

+39
-11
lines changed

drivers/gpu/drm/i915/i915_scheduler.c

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,37 @@ static inline int rq_prio(const struct i915_request *rq)
177177
return rq->sched.attr.priority | __NO_PREEMPTION;
178178
}
179179

180-
static void kick_submission(struct intel_engine_cs *engine, int prio)
180+
static inline bool need_preempt(int prio, int active)
181181
{
182-
const struct i915_request *inflight = *engine->execlists.active;
182+
/*
183+
* Allow preemption of low -> normal -> high, but we do
184+
* not allow low priority tasks to preempt other low priority
185+
* tasks under the impression that latency for low priority
186+
* tasks does not matter (as much as background throughput),
187+
* so kiss.
188+
*/
189+
return prio >= max(I915_PRIORITY_NORMAL, active);
190+
}
191+
192+
static void kick_submission(struct intel_engine_cs *engine,
193+
const struct i915_request *rq,
194+
int prio)
195+
{
196+
const struct i915_request *inflight;
197+
198+
/*
199+
* We only need to kick the tasklet once for the high priority
200+
* new context we add into the queue.
201+
*/
202+
if (prio <= engine->execlists.queue_priority_hint)
203+
return;
204+
205+
rcu_read_lock();
206+
207+
/* Nothing currently active? We're overdue for a submission! */
208+
inflight = execlists_active(&engine->execlists);
209+
if (!inflight)
210+
goto unlock;
183211

184212
/*
185213
* If we are already the currently executing context, don't
@@ -188,10 +216,15 @@ static void kick_submission(struct intel_engine_cs *engine, int prio)
188216
* tasklet, i.e. we have not change the priority queue
189217
* sufficiently to oust the running context.
190218
*/
191-
if (!inflight || !i915_scheduler_need_preempt(prio, rq_prio(inflight)))
192-
return;
219+
if (inflight->hw_context == rq->hw_context)
220+
goto unlock;
193221

194-
tasklet_hi_schedule(&engine->execlists.tasklet);
222+
engine->execlists.queue_priority_hint = prio;
223+
if (need_preempt(prio, rq_prio(inflight)))
224+
tasklet_hi_schedule(&engine->execlists.tasklet);
225+
226+
unlock:
227+
rcu_read_unlock();
195228
}
196229

197230
static void __i915_schedule(struct i915_sched_node *node,
@@ -317,13 +350,8 @@ static void __i915_schedule(struct i915_sched_node *node,
317350
list_move_tail(&node->link, cache.priolist);
318351
}
319352

320-
if (prio <= engine->execlists.queue_priority_hint)
321-
continue;
322-
323-
engine->execlists.queue_priority_hint = prio;
324-
325353
/* Defer (tasklet) submission until after all of our updates. */
326-
kick_submission(engine, prio);
354+
kick_submission(engine, node_to_request(node), prio);
327355
}
328356

329357
spin_unlock(&engine->active.lock);

0 commit comments

Comments
 (0)