[PATCH] drm/i915: Keep rbtree intact until retirements
Chris Wilson
chris at chris-wilson.co.uk
Wed Feb 26 22:09:06 UTC 2020
Fixes: b1e3177bd1d8 ("drm/i915: Coordinate i915_active with its own mutex")
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
---
drivers/gpu/drm/i915/i915_active.c | 47 +++++++++++++++++-------------
1 file changed, 26 insertions(+), 21 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c
index 0b12d5023800..fc6679a34cdb 100644
--- a/drivers/gpu/drm/i915/i915_active.c
+++ b/drivers/gpu/drm/i915/i915_active.c
@@ -620,8 +620,10 @@ static struct active_node *reuse_idle_barrier(struct i915_active *ref, u64 idx)
engine = __barrier_to_engine(node);
smp_rmb(); /* serialise with add_active_barriers */
if (is_barrier(&node->base) &&
- ____active_del_barrier(ref, node, engine))
+ ____active_del_barrier(ref, node, engine)) {
+ RCU_INIT_POINTER(node->base.fence, NULL);
goto match;
+ }
}
spin_unlock_irq(&ref->tree_lock);
@@ -629,7 +631,6 @@ static struct active_node *reuse_idle_barrier(struct i915_active *ref, u64 idx)
return NULL;
match:
- rb_erase(p, &ref->tree); /* Hide from waits and sibling allocations */
if (p == &ref->cache->node)
ref->cache = NULL;
spin_unlock_irq(&ref->tree_lock);
@@ -671,6 +672,7 @@ int i915_active_acquire_preallocate_barrier(struct i915_active *ref,
goto unwind;
}
+ RB_CLEAR_NODE(&node->node);
RCU_INIT_POINTER(node->base.fence, NULL);
node->base.cb.func = node_retire;
node->timeline = idx;
@@ -736,26 +738,29 @@ void i915_active_acquire_barrier(struct i915_active *ref)
llist_for_each_safe(pos, next, take_preallocated_barriers(ref)) {
struct active_node *node = barrier_from_ll(pos);
struct intel_engine_cs *engine = barrier_to_engine(node);
- struct rb_node **p, *parent;
-
- spin_lock_irqsave_nested(&ref->tree_lock, flags,
- SINGLE_DEPTH_NESTING);
- parent = NULL;
- p = &ref->tree.rb_node;
- while (*p) {
- struct active_node *it;
-
- parent = *p;
-
- it = rb_entry(parent, struct active_node, node);
- if (it->timeline < node->timeline)
- p = &parent->rb_right;
- else
- p = &parent->rb_left;
+
+ if (RB_EMPTY_NODE(&node->node)) {
+ struct rb_node **p, *parent;
+
+ spin_lock_irqsave_nested(&ref->tree_lock, flags,
+ SINGLE_DEPTH_NESTING);
+ parent = NULL;
+ p = &ref->tree.rb_node;
+ while (*p) {
+ struct active_node *it;
+
+ parent = *p;
+
+ it = rb_entry(parent, struct active_node, node);
+ if (it->timeline < node->timeline)
+ p = &parent->rb_right;
+ else
+ p = &parent->rb_left;
+ }
+ rb_link_node(&node->node, parent, p);
+ rb_insert_color(&node->node, &ref->tree);
+ spin_unlock_irqrestore(&ref->tree_lock, flags);
}
- rb_link_node(&node->node, parent, p);
- rb_insert_color(&node->node, &ref->tree);
- spin_unlock_irqrestore(&ref->tree_lock, flags);
GEM_BUG_ON(!intel_engine_pm_is_awake(engine));
llist_add(barrier_to_ll(node), &engine->barrier_tasks);
--
2.25.1
More information about the Intel-gfx-trybot
mailing list