summaryrefslogtreecommitdiffstats
path: root/drivers/dma-buf
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2019-08-17 17:23:00 +0200
committerChris Wilson <chris@chris-wilson.co.uk>2019-08-17 19:03:12 +0200
commit0fc89b6802ba1fcc561b0c906e0cefd384e3b2e5 (patch)
tree41823e739112cb2030b60cf9b5d6cf3e814017dc /drivers/dma-buf
parentdma-fence: Avoid list_del during fence->cb_list iteration (diff)
downloadlinux-0fc89b6802ba1fcc561b0c906e0cefd384e3b2e5.tar.xz
linux-0fc89b6802ba1fcc561b0c906e0cefd384e3b2e5.zip
dma-fence: Simply wrap dma_fence_signal_locked with dma_fence_signal
Currently dma_fence_signal() tries to avoid the spinlock and only takes it if absolutely required to walk the callback list. However, to allow for some users to surreptitiously insert lazy signal callbacks that do not depend on enabling the signaling mechanism around every fence, we always need to notify the callbacks on signaling. As such, we will always need to take the spinlock and dma_fence_signal() effectively becomes a clone of dma_fence_signal_locked(). v2: Update the test_and_set_bit() before entering the spinlock. v3: Drop the test_[and_set]_bit() before the spinlock, it's a caller error so expected to be very unlikely. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Christian König <christian.koenig@amd.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Reviewed-by: Christian König <christian.koenig@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20190817152300.5370-1-chris@chris-wilson.co.uk
Diffstat (limited to 'drivers/dma-buf')
-rw-r--r--drivers/dma-buf/dma-fence.c44
1 files changed, 12 insertions, 32 deletions
diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c
index ff0cd6eae766..8a6d0250285d 100644
--- a/drivers/dma-buf/dma-fence.c
+++ b/drivers/dma-buf/dma-fence.c
@@ -129,25 +129,16 @@ EXPORT_SYMBOL(dma_fence_context_alloc);
int dma_fence_signal_locked(struct dma_fence *fence)
{
struct dma_fence_cb *cur, *tmp;
- int ret = 0;
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;
-
- /*
- * 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);
if (!list_empty(&fence->cb_list)) {
list_for_each_entry_safe(cur, tmp, &fence->cb_list, node) {
@@ -156,7 +147,8 @@ int dma_fence_signal_locked(struct dma_fence *fence)
}
INIT_LIST_HEAD(&fence->cb_list);
}
- return ret;
+
+ return 0;
}
EXPORT_SYMBOL(dma_fence_signal_locked);
@@ -176,28 +168,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);