.. | .. |
---|
193 | 193 | */ |
---|
194 | 194 | static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc) |
---|
195 | 195 | { |
---|
| 196 | + LIST_HEAD(signalled); |
---|
196 | 197 | struct sync_pt *pt, *next; |
---|
197 | 198 | |
---|
198 | 199 | trace_sync_timeline(obj); |
---|
.. | .. |
---|
205 | 206 | if (!timeline_fence_signaled(&pt->base)) |
---|
206 | 207 | break; |
---|
207 | 208 | |
---|
208 | | - list_del_init(&pt->link); |
---|
| 209 | + dma_fence_get(&pt->base); |
---|
| 210 | + |
---|
| 211 | + list_move_tail(&pt->link, &signalled); |
---|
209 | 212 | rb_erase(&pt->node, &obj->pt_tree); |
---|
210 | 213 | |
---|
211 | | - /* |
---|
212 | | - * A signal callback may release the last reference to this |
---|
213 | | - * fence, causing it to be freed. That operation has to be |
---|
214 | | - * last to avoid a use after free inside this loop, and must |
---|
215 | | - * be after we remove the fence from the timeline in order to |
---|
216 | | - * prevent deadlocking on timeline->lock inside |
---|
217 | | - * timeline_fence_release(). |
---|
218 | | - */ |
---|
219 | 214 | dma_fence_signal_locked(&pt->base); |
---|
220 | 215 | } |
---|
221 | 216 | |
---|
222 | 217 | spin_unlock_irq(&obj->lock); |
---|
| 218 | + |
---|
| 219 | + list_for_each_entry_safe(pt, next, &signalled, link) { |
---|
| 220 | + list_del_init(&pt->link); |
---|
| 221 | + dma_fence_put(&pt->base); |
---|
| 222 | + } |
---|
223 | 223 | } |
---|
224 | 224 | |
---|
225 | 225 | /** |
---|