Skip to content

Commit

Permalink
drm/i915/gt: Incorporate the virtual engine into timeslicing
Browse files Browse the repository at this point in the history
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: 3df2dee ("drm/i915/execlists: Enable timeslice on partial virtual engine dequeue")
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200519132046.22443-3-chris@chris-wilson.co.uk
  • Loading branch information
Chris Wilson committed May 19, 2020
1 parent 1ee05f9 commit 6ad249b
Showing 1 changed file with 24 additions and 6 deletions.
30 changes: 24 additions & 6 deletions drivers/gpu/drm/i915/gt/intel_lrc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1895,14 +1895,33 @@ 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;

if (!intel_engine_has_timeslices(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)));

Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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 */
}

Expand Down

0 comments on commit 6ad249b

Please sign in to comment.