mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-27 00:04:47 +08:00
drm/i915/execlists: Track active elements during dequeue
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: 44d0a9c05b
("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
This commit is contained in:
parent
408464b4cb
commit
60ef5b7ac6
@ -1678,17 +1678,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, \
|
||||
@ -1827,11 +1816,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;
|
||||
|
||||
@ -1842,13 +1829,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)
|
||||
@ -1861,6 +1849,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;
|
||||
@ -1915,7 +1904,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,
|
||||
@ -2201,7 +2193,7 @@ done:
|
||||
* 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));
|
||||
@ -2212,7 +2204,7 @@ done:
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user