Merge tag 'virtio-fs-5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi...
[linux-2.6-microblaze.git] / drivers / dma-buf / dma-fence.c
index 59ac96e..2c136ae 100644 (file)
@@ -60,7 +60,7 @@ static atomic64_t dma_fence_context_counter = ATOMIC64_INIT(1);
  *
  * - Then there's also implicit fencing, where the synchronization points are
  *   implicitly passed around as part of shared &dma_buf instances. Such
- *   implicit fences are stored in &struct reservation_object through the
+ *   implicit fences are stored in &struct dma_resv through the
  *   &dma_buf.resv pointer.
  */
 
@@ -129,31 +129,27 @@ EXPORT_SYMBOL(dma_fence_context_alloc);
 int dma_fence_signal_locked(struct dma_fence *fence)
 {
        struct dma_fence_cb *cur, *tmp;
-       int ret = 0;
+       struct list_head cb_list;
 
        lockdep_assert_held(fence->lock);
 
-       if (WARN_ON(!fence))
+       if (unlikely(test_and_set_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
+                                     &fence->flags)))
                return -EINVAL;
 
-       if (test_and_set_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
-               ret = -EINVAL;
+       /* Stash the cb_list before replacing it with the timestamp */
+       list_replace(&fence->cb_list, &cb_list);
 
-               /*
-                * we might have raced with the unlocked dma_fence_signal,
-                * still run through all callbacks
-                */
-       } else {
-               fence->timestamp = ktime_get();
-               set_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags);
-               trace_dma_fence_signaled(fence);
-       }
+       fence->timestamp = ktime_get();
+       set_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags);
+       trace_dma_fence_signaled(fence);
 
-       list_for_each_entry_safe(cur, tmp, &fence->cb_list, node) {
-               list_del_init(&cur->node);
+       list_for_each_entry_safe(cur, tmp, &cb_list, node) {
+               INIT_LIST_HEAD(&cur->node);
                cur->func(fence, cur);
        }
-       return ret;
+
+       return 0;
 }
 EXPORT_SYMBOL(dma_fence_signal_locked);
 
@@ -173,28 +169,16 @@ EXPORT_SYMBOL(dma_fence_signal_locked);
 int dma_fence_signal(struct dma_fence *fence)
 {
        unsigned long flags;
+       int ret;
 
        if (!fence)
                return -EINVAL;
 
-       if (test_and_set_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
-               return -EINVAL;
-
-       fence->timestamp = ktime_get();
-       set_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags);
-       trace_dma_fence_signaled(fence);
-
-       if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags)) {
-               struct dma_fence_cb *cur, *tmp;
+       spin_lock_irqsave(fence->lock, flags);
+       ret = dma_fence_signal_locked(fence);
+       spin_unlock_irqrestore(fence->lock, flags);
 
-               spin_lock_irqsave(fence->lock, flags);
-               list_for_each_entry_safe(cur, tmp, &fence->cb_list, node) {
-                       list_del_init(&cur->node);
-                       cur->func(fence, cur);
-               }
-               spin_unlock_irqrestore(fence->lock, flags);
-       }
-       return 0;
+       return ret;
 }
 EXPORT_SYMBOL(dma_fence_signal);
 
@@ -248,7 +232,8 @@ void dma_fence_release(struct kref *kref)
 
        trace_dma_fence_destroy(fence);
 
-       if (WARN(!list_empty(&fence->cb_list),
+       if (WARN(!list_empty(&fence->cb_list) &&
+                !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags),
                 "Fence %s:%s:%llx:%llx released with pending signals!\n",
                 fence->ops->get_driver_name(fence),
                 fence->ops->get_timeline_name(fence),