[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