Commit 93d35bbd authored by Chris Wilson's avatar Chris Wilson Committed by Greg Kroah-Hartman

drm/i915/execlists: Track active elements during dequeue

commit 9777d8b2 upstream.

Record the initial active element we use when building the next ELSP
submission, so that we can compare against it latter to see if there's
no change.

Fixes: 44d0a9c0 ("drm/i915/execlists: Skip redundant resubmission")
Signed-off-by: default avatarChris Wilson <[email protected]>
Reviewed-by: default avatarMika Kuoppala <[email protected]>
Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
(cherry picked from commit 60ef5b7a)
Signed-off-by: default avatarJani Nikula <[email protected]>
Signed-off-by: default avatarGreg Kroah-Hartman <[email protected]>
parent 64f78be8
......@@ -1422,17 +1422,6 @@ static void virtual_xfer_breadcrumbs(struct virtual_engine *ve,
spin_unlock(&old->breadcrumbs.irq_lock);
}
static struct i915_request *
last_active(const struct intel_engine_execlists *execlists)
{
struct i915_request * const *last = READ_ONCE(execlists->active);
while (*last && i915_request_completed(*last))
last++;
return *last;
}
#define for_each_waiter(p__, rq__) \
list_for_each_entry_lockless(p__, \
&(rq__)->sched.waiters_list, \
......@@ -1562,11 +1551,9 @@ static void record_preemption(struct intel_engine_execlists *execlists)
(void)I915_SELFTEST_ONLY(execlists->preempt_hang.count++);
}
static unsigned long active_preempt_timeout(struct intel_engine_cs *engine)
static unsigned long active_preempt_timeout(struct intel_engine_cs *engine,
const struct i915_request *rq)
{
struct i915_request *rq;
rq = last_active(&engine->execlists);
if (!rq)
return 0;
......@@ -1577,13 +1564,14 @@ static unsigned long active_preempt_timeout(struct intel_engine_cs *engine)
return READ_ONCE(engine->props.preempt_timeout_ms);
}
static void set_preempt_timeout(struct intel_engine_cs *engine)
static void set_preempt_timeout(struct intel_engine_cs *engine,
const struct i915_request *rq)
{
if (!intel_engine_has_preempt_reset(engine))
return;
set_timer_ms(&engine->execlists.preempt,
active_preempt_timeout(engine));
active_preempt_timeout(engine, rq));
}
static void execlists_dequeue(struct intel_engine_cs *engine)
......@@ -1591,6 +1579,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
struct intel_engine_execlists * const execlists = &engine->execlists;
struct i915_request **port = execlists->pending;
struct i915_request ** const last_port = port + execlists->port_mask;
struct i915_request * const *active;
struct i915_request *last;
struct rb_node *rb;
bool submit = false;
......@@ -1645,7 +1634,10 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
* i.e. we will retrigger preemption following the ack in case
* of trouble.
*/
last = last_active(execlists);
active = READ_ONCE(execlists->active);
while ((last = *active) && i915_request_completed(last))
active++;
if (last) {
if (need_preempt(engine, last, rb)) {
GEM_TRACE("%s: preempting last=%llx:%lld, prio=%d, hint=%d\n",
......@@ -1930,7 +1922,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
* Skip if we ended up with exactly the same set of requests,
* e.g. trying to timeslice a pair of ordered contexts
*/
if (!memcmp(execlists->active, execlists->pending,
if (!memcmp(active, execlists->pending,
(port - execlists->pending + 1) * sizeof(*port))) {
do
execlists_schedule_out(fetch_and_zero(port));
......@@ -1942,7 +1934,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
memset(port + 1, 0, (last_port - port) * sizeof(*port));
execlists_submit_ports(engine);
set_preempt_timeout(engine);
set_preempt_timeout(engine, *active);
} else {
skip_submit:
ring_set_paused(engine, 0);
......
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