[PATCH 65/98] drm/i915/execlists: Switch to rb_root_cached
Chris Wilson
chris at chris-wilson.co.uk
Fri Apr 27 11:10:48 UTC 2018
The kernel recently gained an augmented rbtree with the purpose of
cacheing the leftmost element of the rbtree, a frequent optimisation to
avoid calls to rb_first() which is also employed by the
execlists->queue. Switch from our open-coded cache to the library.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
drivers/gpu/drm/i915/intel_engine_cs.c | 7 ++---
drivers/gpu/drm/i915/intel_guc_submission.c | 11 +++-----
drivers/gpu/drm/i915/intel_lrc.c | 31 ++++++++-------------
drivers/gpu/drm/i915/intel_ringbuffer.h | 7 +----
4 files changed, 19 insertions(+), 37 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
index 54b3169f44c4..e0ed87a1c372 100644
--- a/drivers/gpu/drm/i915/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/intel_engine_cs.c
@@ -505,8 +505,7 @@ static void intel_engine_init_execlist(struct intel_engine_cs *engine)
GEM_BUG_ON(execlists_num_ports(execlists) > EXECLIST_MAX_PORTS);
execlists->queue_priority = INT_MIN;
- execlists->queue = RB_ROOT;
- execlists->first = NULL;
+ execlists->queue = RB_ROOT_CACHED;
hrtimer_init(&execlists->preempt_timer,
CLOCK_MONOTONIC, HRTIMER_MODE_REL);
@@ -980,7 +979,7 @@ bool intel_engine_is_idle(struct intel_engine_cs *engine)
return false;
/* ELSP is empty, but there are ready requests? */
- if (READ_ONCE(engine->execlists.first))
+ if (!RB_EMPTY_ROOT(&engine->execlists.queue.rb_root))
return false;
/* Ring stopped? */
@@ -1450,7 +1449,7 @@ void intel_engine_dump(struct intel_engine_cs *engine,
last = NULL;
count = 0;
drm_printf(m, "\t\tQueue priority: %d\n", execlists->queue_priority);
- for (rb = execlists->first; rb; rb = rb_next(rb)) {
+ for (rb = rb_first_cached(&execlists->queue); rb; rb = rb_next(rb)) {
struct i915_priolist *p =
rb_entry(rb, typeof(*p), node);
diff --git a/drivers/gpu/drm/i915/intel_guc_submission.c b/drivers/gpu/drm/i915/intel_guc_submission.c
index 78d0014a34fc..a72df81114cc 100644
--- a/drivers/gpu/drm/i915/intel_guc_submission.c
+++ b/drivers/gpu/drm/i915/intel_guc_submission.c
@@ -693,8 +693,6 @@ static void guc_dequeue(struct intel_engine_cs *engine)
struct rb_node *rb;
spin_lock_irqsave(&engine->timeline.lock, flags);
- rb = execlists->first;
- GEM_BUG_ON(rb_first(&execlists->queue) != rb);
if (port_isset(port)) {
if (intel_engine_has_preemption(engine)) {
@@ -717,7 +715,7 @@ static void guc_dequeue(struct intel_engine_cs *engine)
}
GEM_BUG_ON(port_isset(port));
- while (rb) {
+ while ((rb = rb_first_cached(&execlists->queue))) {
struct i915_priolist *p = to_priolist(rb);
struct i915_request *rq, *rn;
@@ -742,8 +740,7 @@ static void guc_dequeue(struct intel_engine_cs *engine)
submit = true;
}
- rb = rb_next(rb);
- rb_erase(&p->node, &execlists->queue);
+ rb_erase_cached(&p->node, &execlists->queue);
INIT_LIST_HEAD(&p->requests);
if (p->priority != I915_PRIORITY_NORMAL)
kmem_cache_free(engine->i915->priorities, p);
@@ -751,7 +748,6 @@ static void guc_dequeue(struct intel_engine_cs *engine)
done:
execlists_clear_active(execlists, EXECLISTS_ACTIVE_PREEMPT_TIMEOUT);
execlists->queue_priority = rb ? to_priolist(rb)->priority : INT_MIN;
- execlists->first = rb;
if (submit) {
port_assign(port, last);
execlists_user_begin(execlists, execlists->port);
@@ -761,7 +757,8 @@ static void guc_dequeue(struct intel_engine_cs *engine)
/* We must always keep the beast fed if we have work piled up */
GEM_BUG_ON(port_isset(execlists->port) &&
!execlists_is_active(execlists, EXECLISTS_ACTIVE_USER));
- GEM_BUG_ON(execlists->first && !port_isset(execlists->port));
+ GEM_BUG_ON(rb_first_cached(&execlists->queue) &&
+ !port_isset(execlists->port));
unlock:
spin_unlock_irqrestore(&engine->timeline.lock, flags);
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 1892c41f472b..9248a5d8e573 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -274,7 +274,7 @@ lookup_priolist(struct intel_engine_cs *engine,
find_priolist:
/* most positive priority is scheduled first, equal priorities fifo */
rb = NULL;
- parent = &execlists->queue.rb_node;
+ parent = &execlists->queue.rb_root.rb_node;
while (*parent) {
rb = *parent;
p = to_priolist(rb);
@@ -312,10 +312,7 @@ lookup_priolist(struct intel_engine_cs *engine,
p->priority = prio;
INIT_LIST_HEAD(&p->requests);
rb_link_node(&p->node, rb, parent);
- rb_insert_color(&p->node, &execlists->queue);
-
- if (first)
- execlists->first = &p->node;
+ rb_insert_color_cached(&p->node, &execlists->queue, first);
return p;
}
@@ -712,8 +709,6 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
*/
spin_lock_irqsave(&engine->timeline.lock, flags);
- rb = execlists->first;
- GEM_BUG_ON(rb_first(&execlists->queue) != rb);
if (last) {
/*
@@ -778,7 +773,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
last->tail = last->wa_tail;
}
- while (rb) {
+ while ((rb = rb_first_cached(&execlists->queue))) {
struct i915_priolist *p = to_priolist(rb);
struct i915_request *rq, *rn;
@@ -837,8 +832,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
submit = true;
}
- rb = rb_next(rb);
- rb_erase(&p->node, &execlists->queue);
+ rb_erase_cached(&p->node, &execlists->queue);
INIT_LIST_HEAD(&p->requests);
if (p->priority != I915_PRIORITY_NORMAL)
kmem_cache_free(engine->i915->priorities, p);
@@ -866,12 +860,12 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
execlists->queue_priority =
port != execlists->port ? rq_prio(last) : INT_MIN;
- execlists->first = rb;
if (submit)
port_assign(port, last);
/* We must always keep the beast fed if we have work piled up */
- GEM_BUG_ON(execlists->first && !port_isset(execlists->port));
+ GEM_BUG_ON(rb_first_cached(&execlists->queue) &&
+ !port_isset(execlists->port));
unlock:
spin_unlock_irqrestore(&engine->timeline.lock, flags);
@@ -1034,8 +1028,7 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine)
}
/* Flush the queued requests to the timeline list (for retiring). */
- rb = execlists->first;
- while (rb) {
+ while ((rb = rb_first_cached(&execlists->queue))) {
struct i915_priolist *p = to_priolist(rb);
list_for_each_entry_safe(rq, rn, &p->requests, sched.link) {
@@ -1045,8 +1038,7 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine)
__i915_request_submit(rq);
}
- rb = rb_next(rb);
- rb_erase(&p->node, &execlists->queue);
+ rb_erase_cached(&p->node, &execlists->queue);
INIT_LIST_HEAD(&p->requests);
if (p->priority != I915_PRIORITY_NORMAL)
kmem_cache_free(engine->i915->priorities, p);
@@ -1055,8 +1047,7 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine)
/* Remaining _unready_ requests will be nop'ed when submitted */
execlists->queue_priority = INT_MIN;
- execlists->queue = RB_ROOT;
- execlists->first = NULL;
+ execlists->queue = RB_ROOT_CACHED;
GEM_BUG_ON(port_isset(execlists->port));
spin_unlock(&engine->timeline.lock);
@@ -1341,7 +1332,7 @@ static void execlists_submit_request(struct i915_request *request)
submit_queue(engine,
rq_prio(request), request->gem_context->preempt_timeout);
- GEM_BUG_ON(!engine->execlists.first);
+ GEM_BUG_ON(RB_EMPTY_ROOT(&engine->execlists.queue.rb_root));
GEM_BUG_ON(list_empty(&request->sched.link));
spin_unlock_irqrestore(&engine->timeline.lock, flags);
@@ -1962,7 +1953,7 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine)
enable_execlists(engine);
/* After a GPU reset, we may have requests to replay */
- if (execlists->first)
+ if (!RB_EMPTY_ROOT(&execlists->queue.rb_root))
tasklet_schedule(&execlists->tasklet);
return 0;
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 03ac5d89a3dd..1e3709e20632 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -292,12 +292,7 @@ struct intel_engine_execlists {
/**
* @queue: queue of requests, in priority lists
*/
- struct rb_root queue;
-
- /**
- * @first: leftmost level in priority @queue
- */
- struct rb_node *first;
+ struct rb_root_cached queue;
/**
* @fw_domains: forcewake domains for irq tasklet
--
2.17.0
More information about the Intel-gfx-trybot
mailing list