Skip to content

Commit

Permalink
drm/i915/execlists: Track active elements during dequeue
Browse files Browse the repository at this point in the history
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: 44d0a9c ("drm/i915/execlists: Skip redundant resubmission")
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200311092624.10012-2-chris@chris-wilson.co.uk
(cherry picked from commit 60ef5b7)
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
  • Loading branch information
Chris Wilson authored and Jani Nikula committed Mar 16, 2020
1 parent fb33c65 commit 9777d8b
Showing 1 changed file with 12 additions and 20 deletions.
32 changes: 12 additions & 20 deletions drivers/gpu/drm/i915/gt/intel_lrc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1600,17 +1600,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, \
Expand Down Expand Up @@ -1740,11 +1729,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;

Expand All @@ -1755,13 +1742,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 inline void clear_ports(struct i915_request **ports, int count)
Expand All @@ -1774,6 +1762,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;
Expand Down Expand Up @@ -1828,7 +1817,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)) {
ENGINE_TRACE(engine,
Expand Down Expand Up @@ -2110,7 +2102,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));
Expand All @@ -2121,7 +2113,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
clear_ports(port + 1, last_port - port);

execlists_submit_ports(engine);
set_preempt_timeout(engine);
set_preempt_timeout(engine, *active);
} else {
skip_submit:
ring_set_paused(engine, 0);
Expand Down

0 comments on commit 9777d8b

Please sign in to comment.