aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2019-08-17 11:23:00 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2019-08-17 13:03:12 -0400
commit0fc89b6802ba1fcc561b0c906e0cefd384e3b2e5 (patch)
tree41823e739112cb2030b60cf9b5d6cf3e814017dc
parentf86a802bf3a7c28e4c4ea032fa2e61398dbccd5d (diff)
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
-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);
129int dma_fence_signal_locked(struct dma_fence *fence) 129int dma_fence_signal_locked(struct dma_fence *fence)
130{ 130{
131 struct dma_fence_cb *cur, *tmp; 131 struct dma_fence_cb *cur, *tmp;
132 int ret = 0;
133 132
134 lockdep_assert_held(fence->lock); 133 lockdep_assert_held(fence->lock);
135 134
136 if (WARN_ON(!fence)) 135 if (unlikely(test_and_set_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
136 &fence->flags)))
137 return -EINVAL; 137 return -EINVAL;
138 138
139 if (test_and_set_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) { 139 fence->timestamp = ktime_get();
140 ret = -EINVAL; 140 set_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags);
141 141 trace_dma_fence_signaled(fence);
142 /*
143 * we might have raced with the unlocked dma_fence_signal,
144 * still run through all callbacks
145 */
146 } else {
147 fence->timestamp = ktime_get();
148 set_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags);
149 trace_dma_fence_signaled(fence);
150 }
151 142
152 if (!list_empty(&fence->cb_list)) { 143 if (!list_empty(&fence->cb_list)) {
153 list_for_each_entry_safe(cur, tmp, &fence->cb_list, node) { 144 list_for_each_entry_safe(cur, tmp, &fence->cb_list, node) {
@@ -156,7 +147,8 @@ int dma_fence_signal_locked(struct dma_fence *fence)
156 } 147 }
157 INIT_LIST_HEAD(&fence->cb_list); 148 INIT_LIST_HEAD(&fence->cb_list);
158 } 149 }
159 return ret; 150
151 return 0;
160} 152}
161EXPORT_SYMBOL(dma_fence_signal_locked); 153EXPORT_SYMBOL(dma_fence_signal_locked);
162 154
@@ -176,28 +168,16 @@ EXPORT_SYMBOL(dma_fence_signal_locked);
176int dma_fence_signal(struct dma_fence *fence) 168int dma_fence_signal(struct dma_fence *fence)
177{ 169{
178 unsigned long flags; 170 unsigned long flags;
171 int ret;
179 172
180 if (!fence) 173 if (!fence)
181 return -EINVAL; 174 return -EINVAL;
182 175
183 if (test_and_set_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) 176 spin_lock_irqsave(fence->lock, flags);
184 return -EINVAL; 177 ret = dma_fence_signal_locked(fence);
185 178 spin_unlock_irqrestore(fence->lock, flags);
186 fence->timestamp = ktime_get();
187 set_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags);
188 trace_dma_fence_signaled(fence);
189
190 if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags)) {
191 struct dma_fence_cb *cur, *tmp;
192 179
193 spin_lock_irqsave(fence->lock, flags); 180 return ret;
194 list_for_each_entry_safe(cur, tmp, &fence->cb_list, node) {
195 list_del_init(&cur->node);
196 cur->func(fence, cur);
197 }
198 spin_unlock_irqrestore(fence->lock, flags);
199 }
200 return 0;
201} 181}
202EXPORT_SYMBOL(dma_fence_signal); 182EXPORT_SYMBOL(dma_fence_signal);
203 183