Commit 6ad249ba authored by Chris Wilson's avatar Chris Wilson

drm/i915/gt: Incorporate the virtual engine into timeslicing

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: 3df2deed ("drm/i915/execlists: Enable timeslice on partial virtual engine dequeue")
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: default avatarTvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200519132046.22443-3-chris@chris-wilson.co.uk
parent 1ee05f9e
...@@ -1895,7 +1895,8 @@ static void defer_active(struct intel_engine_cs *engine) ...@@ -1895,7 +1895,8 @@ static void defer_active(struct intel_engine_cs *engine)
static bool static bool
need_timeslice(const struct intel_engine_cs *engine, 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; int hint;
...@@ -1903,6 +1904,24 @@ need_timeslice(const struct intel_engine_cs *engine, ...@@ -1903,6 +1904,24 @@ need_timeslice(const struct intel_engine_cs *engine,
return false; return false;
hint = engine->execlists.queue_priority_hint; 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)) if (!list_is_last(&rq->sched.link, &engine->active.requests))
hint = max(hint, rq_prio(list_next_entry(rq, sched.link))); hint = max(hint, rq_prio(list_next_entry(rq, sched.link)));
...@@ -1977,10 +1996,9 @@ static void set_timeslice(struct intel_engine_cs *engine) ...@@ -1977,10 +1996,9 @@ static void set_timeslice(struct intel_engine_cs *engine)
set_timer_ms(&engine->execlists.timer, duration); 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; struct intel_engine_execlists *execlists = &engine->execlists;
const int prio = queue_prio(execlists);
unsigned long duration; unsigned long duration;
if (!intel_engine_has_timeslices(engine)) if (!intel_engine_has_timeslices(engine))
...@@ -2140,7 +2158,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) ...@@ -2140,7 +2158,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
__unwind_incomplete_requests(engine); __unwind_incomplete_requests(engine);
last = NULL; last = NULL;
} else if (need_timeslice(engine, last) && } else if (need_timeslice(engine, last, rb) &&
timeslice_expired(execlists, last)) { timeslice_expired(execlists, last)) {
if (i915_request_completed(last)) { if (i915_request_completed(last)) {
tasklet_hi_schedule(&execlists->tasklet); tasklet_hi_schedule(&execlists->tasklet);
...@@ -2188,7 +2206,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) ...@@ -2188,7 +2206,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
* Even if ELSP[1] is occupied and not worthy * Even if ELSP[1] is occupied and not worthy
* of timeslices, our queue might be. * of timeslices, our queue might be.
*/ */
start_timeslice(engine); start_timeslice(engine, queue_prio(execlists));
return; return;
} }
} }
...@@ -2223,7 +2241,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) ...@@ -2223,7 +2241,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
if (last && !can_merge_rq(last, rq)) { if (last && !can_merge_rq(last, rq)) {
spin_unlock(&ve->base.active.lock); spin_unlock(&ve->base.active.lock);
start_timeslice(engine); start_timeslice(engine, rq_prio(rq));
return; /* leave this for another sibling */ return; /* leave this for another sibling */
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment