summaryrefslogtreecommitdiff
path: root/drivers/dma-buf/sw_sync.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dma-buf/sw_sync.c')
-rw-r--r--drivers/dma-buf/sw_sync.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c
index dec6d8529392..b0ee084a7fdc 100644
--- a/drivers/dma-buf/sw_sync.c
+++ b/drivers/dma-buf/sw_sync.c
@@ -213,11 +213,21 @@ 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 (!fence_is_signaled_locked(&pt->base))
+ if (!timeline_fence_signaled(&pt->base))
break;
list_del_init(&pt->link);
rb_erase(&pt->node, &obj->pt_tree);
+
+ /*
+ * A signal callback may release the last reference to this
+ * fence, causing it to be freed. That operation has to be
+ * last to avoid a use after free inside this loop, and must
+ * be after we remove the fence from the timeline in order to
+ * prevent deadlocking on timeline->lock inside
+ * timeline_fence_release().
+ */
+ fence_signal_locked(&pt->base);
}
spin_unlock_irq(&obj->lock);