|
@@ -96,6 +96,7 @@ static struct sync_timeline *sync_timeline_create(const char *name)
|
|
|
obj->context = dma_fence_context_alloc(1);
|
|
|
strlcpy(obj->name, name, sizeof(obj->name));
|
|
|
|
|
|
+ obj->pt_tree = RB_ROOT;
|
|
|
INIT_LIST_HEAD(&obj->pt_list);
|
|
|
spin_lock_init(&obj->lock);
|
|
|
|
|
@@ -142,9 +143,13 @@ static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc)
|
|
|
|
|
|
obj->value += inc;
|
|
|
|
|
|
- list_for_each_entry_safe(pt, next, &obj->pt_list, link)
|
|
|
- if (dma_fence_is_signaled_locked(&pt->base))
|
|
|
- list_del_init(&pt->link);
|
|
|
+ list_for_each_entry_safe(pt, next, &obj->pt_list, link) {
|
|
|
+ if (!dma_fence_is_signaled_locked(&pt->base))
|
|
|
+ break;
|
|
|
+
|
|
|
+ list_del_init(&pt->link);
|
|
|
+ rb_erase(&pt->node, &obj->pt_tree);
|
|
|
+ }
|
|
|
|
|
|
spin_unlock_irq(&obj->lock);
|
|
|
}
|
|
@@ -174,8 +179,38 @@ static struct sync_pt *sync_pt_create(struct sync_timeline *obj,
|
|
|
INIT_LIST_HEAD(&pt->link);
|
|
|
|
|
|
spin_lock_irq(&obj->lock);
|
|
|
- if (!dma_fence_is_signaled_locked(&pt->base))
|
|
|
- list_add_tail(&pt->link, &obj->pt_list);
|
|
|
+ if (!dma_fence_is_signaled_locked(&pt->base)) {
|
|
|
+ struct rb_node **p = &obj->pt_tree.rb_node;
|
|
|
+ struct rb_node *parent = NULL;
|
|
|
+
|
|
|
+ while (*p) {
|
|
|
+ struct sync_pt *other;
|
|
|
+ int cmp;
|
|
|
+
|
|
|
+ parent = *p;
|
|
|
+ other = rb_entry(parent, typeof(*pt), node);
|
|
|
+ cmp = value - other->base.seqno;
|
|
|
+ if (cmp > 0) {
|
|
|
+ p = &parent->rb_right;
|
|
|
+ } else if (cmp < 0) {
|
|
|
+ p = &parent->rb_left;
|
|
|
+ } else {
|
|
|
+ if (dma_fence_get_rcu(&other->base)) {
|
|
|
+ dma_fence_put(&pt->base);
|
|
|
+ pt = other;
|
|
|
+ goto unlock;
|
|
|
+ }
|
|
|
+ p = &parent->rb_left;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ rb_link_node(&pt->node, parent, p);
|
|
|
+ rb_insert_color(&pt->node, &obj->pt_tree);
|
|
|
+
|
|
|
+ parent = rb_next(&pt->node);
|
|
|
+ list_add_tail(&pt->link,
|
|
|
+ parent ? &rb_entry(parent, typeof(*pt), node)->link : &obj->pt_list);
|
|
|
+ }
|
|
|
+unlock:
|
|
|
spin_unlock_irq(&obj->lock);
|
|
|
|
|
|
return pt;
|
|
@@ -202,8 +237,10 @@ static void timeline_fence_release(struct dma_fence *fence)
|
|
|
unsigned long flags;
|
|
|
|
|
|
spin_lock_irqsave(fence->lock, flags);
|
|
|
- if (!list_empty(&pt->link))
|
|
|
+ if (!list_empty(&pt->link)) {
|
|
|
list_del(&pt->link);
|
|
|
+ rb_erase(&pt->node, &parent->pt_tree);
|
|
|
+ }
|
|
|
spin_unlock_irqrestore(fence->lock, flags);
|
|
|
}
|
|
|
|