[Intel-gfx] [PATCH 5/8] drm/i915/gt: Incorporate the virtual engine into timeslicing
Tvrtko Ursulin
tvrtko.ursulin at linux.intel.com
Mon May 18 10:36:15 UTC 2020
On 18/05/2020 09:14, Chris Wilson wrote:
> It was quite the oversight to only factor in the normal queue to decide
> the timeslicing switch priority. By leaving out the next virtual request
> from the priority decision, we would not timeslice the current engine if
> there was an available virtual request.
>
> Testcase: igt/gem_exec_balancer/sliced
> Fixes: 3df2deed411e ("drm/i915/execlists: Enable timeslice on partial virtual engine dequeue")
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> Cc: Mika Kuoppala <mika.kuoppala at linux.intel.com>
> Cc: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
> ---
> drivers/gpu/drm/i915/gt/intel_lrc.c | 32 ++++++++++++++++++++++-------
> 1 file changed, 25 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c
> index 05486e801a63..120efb3eaf96 100644
> --- a/drivers/gpu/drm/i915/gt/intel_lrc.c
> +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
> @@ -1895,7 +1895,8 @@ static void defer_active(struct intel_engine_cs *engine)
>
> static bool
> need_timeslice(const struct intel_engine_cs *engine,
> - const struct i915_request *rq)
> + const struct i915_request *rq,
> + const struct rb_node *rb)
> {
> int hint;
>
> @@ -1903,6 +1904,24 @@ need_timeslice(const struct intel_engine_cs *engine,
> return false;
>
> hint = engine->execlists.queue_priority_hint;
> +
> + if (rb) {
> + const struct virtual_engine *ve =
> + rb_entry(rb, typeof(*ve), nodes[engine->id].rb);
> + const struct intel_engine_cs *inflight =
> + intel_context_inflight(&ve->context);
> +
> + if (!inflight || inflight == engine) {
> + struct i915_request *next;
> +
> + rcu_read_lock();
> + next = READ_ONCE(ve->request);
> + if (next)
> + hint = max(hint, rq_prio(next));
> + rcu_read_unlock();
> + }
> + }
> +
> if (!list_is_last(&rq->sched.link, &engine->active.requests))
> hint = max(hint, rq_prio(list_next_entry(rq, sched.link)));
>
> @@ -1977,10 +1996,9 @@ static void set_timeslice(struct intel_engine_cs *engine)
> set_timer_ms(&engine->execlists.timer, duration);
> }
>
> -static void start_timeslice(struct intel_engine_cs *engine)
> +static void start_timeslice(struct intel_engine_cs *engine, int prio)
> {
> struct intel_engine_execlists *execlists = &engine->execlists;
> - const int prio = queue_prio(execlists);
> unsigned long duration;
>
> if (!intel_engine_has_timeslices(engine))
> @@ -2140,7 +2158,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
> __unwind_incomplete_requests(engine);
>
> last = NULL;
> - } else if (need_timeslice(engine, last) &&
> + } else if (need_timeslice(engine, last, rb) &&
> timeslice_expired(execlists, last)) {
> if (i915_request_completed(last)) {
> tasklet_hi_schedule(&execlists->tasklet);
> @@ -2188,7 +2206,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
> * Even if ELSP[1] is occupied and not worthy
> * of timeslices, our queue might be.
> */
> - start_timeslice(engine);
> + start_timeslice(engine, queue_prio(execlists));
> return;
> }
> }
> @@ -2223,7 +2241,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
>
> if (last && !can_merge_rq(last, rq)) {
> spin_unlock(&ve->base.active.lock);
> - start_timeslice(engine);
> + start_timeslice(engine, rq_prio(rq));
> return; /* leave this for another sibling */
> }
>
> @@ -5519,7 +5537,7 @@ static void virtual_submission_tasklet(unsigned long data)
> submit_engine:
> GEM_BUG_ON(RB_EMPTY_NODE(&node->rb));
> node->prio = prio;
> - if (first && prio > sibling->execlists.queue_priority_hint)
> + if (first && prio >= sibling->execlists.queue_priority_hint)
I got the rest but not why this is needed?
Regards,
Tvrtko
> tasklet_hi_schedule(&sibling->execlists.tasklet);
>
> spin_unlock(&sibling->active.lock);
>
More information about the Intel-gfx
mailing list