diff options
author | Eric Anholt <eric@anholt.net> | 2018-11-08 11:04:22 -0500 |
---|---|---|
committer | Christian König <christian.koenig@amd.com> | 2018-11-12 06:54:21 -0500 |
commit | 131280a162e7fc2a539bb939efd28dd0b964c62c (patch) | |
tree | bb1553618a976dc27dbe1e467917103bd5c22ece /drivers | |
parent | eb8dd3abeb4dffab6c373e87d09fc3b5858ac158 (diff) |
drm: Revert syncobj timeline changes.
Daniel suggested I submit this, since we're still seeing regressions
from it. This is a revert to before 48197bc564c7 ("drm: add syncobj
timeline support v9") and its followon fixes.
Fixes this on first V3D testcase execution:
[ 48.767088] ============================================
[ 48.772410] WARNING: possible recursive locking detected
[ 48.777739] 4.19.0-rc6+ #489 Not tainted
[ 48.781668] --------------------------------------------
[ 48.786993] shader_runner/3284 is trying to acquire lock:
[ 48.792408] ce309d7f (&(&array->lock)->rlock){....}, at: dma_fence_add_callback+0x30/0x23c
[ 48.800714]
[ 48.800714] but task is already holding lock:
[ 48.806559] c5952bd3 (&(&array->lock)->rlock){....}, at: dma_fence_add_callback+0x30/0x23c
[ 48.814862]
[ 48.814862] other info that might help us debug this:
[ 48.821410] Possible unsafe locking scenario:
[ 48.821410]
[ 48.827338] CPU0
[ 48.829788] ----
[ 48.832239] lock(&(&array->lock)->rlock);
[ 48.836434] lock(&(&array->lock)->rlock);
[ 48.840640]
[ 48.840640] *** DEADLOCK ***
[ 48.840640]
[ 48.846582] May be due to missing lock nesting notation
[ 130.763560] 1 lock held by cts-runner/3270:
[ 130.767745] #0: 7834b793 (&(&array->lock)->rlock){-...}, at: dma_fence_add_callback+0x30/0x23c
[ 130.776461]
stack backtrace:
[ 130.780825] CPU: 1 PID: 3270 Comm: cts-runner Not tainted 4.19.0-rc6+ #486
[ 130.787706] Hardware name: Broadcom STB (Flattened Device Tree)
[ 130.793645] [<c021269c>] (unwind_backtrace) from [<c020db1c>] (show_stack+0x10/0x14)
[ 130.801404] [<c020db1c>] (show_stack) from [<c0c2c4b0>] (dump_stack+0xa8/0xd4)
[ 130.808642] [<c0c2c4b0>] (dump_stack) from [<c0281a84>] (__lock_acquire+0x848/0x1a68)
[ 130.816483] [<c0281a84>] (__lock_acquire) from [<c02835d8>] (lock_acquire+0xd8/0x22c)
[ 130.824326] [<c02835d8>] (lock_acquire) from [<c0c49948>] (_raw_spin_lock_irqsave+0x54/0x68)
[ 130.832777] [<c0c49948>] (_raw_spin_lock_irqsave) from [<c086bf54>] (dma_fence_add_callback+0x30/0x23c)
[ 130.842183] [<c086bf54>] (dma_fence_add_callback) from [<c086d4c8>] (dma_fence_array_enable_signaling+0x58/0xec)
[ 130.852371] [<c086d4c8>] (dma_fence_array_enable_signaling) from [<c086c00c>] (dma_fence_add_callback+0xe8/0x23c)
[ 130.862647] [<c086c00c>] (dma_fence_add_callback) from [<c06d8774>] (drm_syncobj_wait_ioctl+0x518/0x614)
[ 130.872143] [<c06d8774>] (drm_syncobj_wait_ioctl) from [<c06b8458>] (drm_ioctl_kernel+0xb0/0xf0)
[ 130.880940] [<c06b8458>] (drm_ioctl_kernel) from [<c06b8818>] (drm_ioctl+0x1d8/0x390)
[ 130.888782] [<c06b8818>] (drm_ioctl) from [<c03a4510>] (do_vfs_ioctl+0xb0/0x8ac)
[ 130.896187] [<c03a4510>] (do_vfs_ioctl) from [<c03a4d40>] (ksys_ioctl+0x34/0x60)
[ 130.903593] [<c03a4d40>] (ksys_ioctl) from [<c0201000>] (ret_fast_syscall+0x0/0x28)
Cc: Chunming Zhou <david1.zhou@amd.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Eric Anholt <eric@anholt.net>
Acked-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Christian König <christian.koenig@amd.com>
Link: https://patchwork.freedesktop.org/patch/261044/
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/drm_syncobj.c | 359 |
1 files changed, 71 insertions, 288 deletions
diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index da2b85eec6cf..90e0a6dce086 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c | |||
@@ -56,9 +56,6 @@ | |||
56 | #include "drm_internal.h" | 56 | #include "drm_internal.h" |
57 | #include <drm/drm_syncobj.h> | 57 | #include <drm/drm_syncobj.h> |
58 | 58 | ||
59 | /* merge normal syncobj to timeline syncobj, the point interval is 1 */ | ||
60 | #define DRM_SYNCOBJ_BINARY_POINT 1 | ||
61 | |||
62 | struct drm_syncobj_stub_fence { | 59 | struct drm_syncobj_stub_fence { |
63 | struct dma_fence base; | 60 | struct dma_fence base; |
64 | spinlock_t lock; | 61 | spinlock_t lock; |
@@ -74,29 +71,7 @@ static const struct dma_fence_ops drm_syncobj_stub_fence_ops = { | |||
74 | .get_timeline_name = drm_syncobj_stub_fence_get_name, | 71 | .get_timeline_name = drm_syncobj_stub_fence_get_name, |
75 | }; | 72 | }; |
76 | 73 | ||
77 | struct drm_syncobj_signal_pt { | ||
78 | struct dma_fence_array *fence_array; | ||
79 | u64 value; | ||
80 | struct list_head list; | ||
81 | }; | ||
82 | |||
83 | static DEFINE_SPINLOCK(signaled_fence_lock); | ||
84 | static struct dma_fence signaled_fence; | ||
85 | 74 | ||
86 | static struct dma_fence *drm_syncobj_get_stub_fence(void) | ||
87 | { | ||
88 | spin_lock(&signaled_fence_lock); | ||
89 | if (!signaled_fence.ops) { | ||
90 | dma_fence_init(&signaled_fence, | ||
91 | &drm_syncobj_stub_fence_ops, | ||
92 | &signaled_fence_lock, | ||
93 | 0, 0); | ||
94 | dma_fence_signal_locked(&signaled_fence); | ||
95 | } | ||
96 | spin_unlock(&signaled_fence_lock); | ||
97 | |||
98 | return dma_fence_get(&signaled_fence); | ||
99 | } | ||
100 | /** | 75 | /** |
101 | * drm_syncobj_find - lookup and reference a sync object. | 76 | * drm_syncobj_find - lookup and reference a sync object. |
102 | * @file_private: drm file private pointer | 77 | * @file_private: drm file private pointer |
@@ -123,27 +98,6 @@ struct drm_syncobj *drm_syncobj_find(struct drm_file *file_private, | |||
123 | } | 98 | } |
124 | EXPORT_SYMBOL(drm_syncobj_find); | 99 | EXPORT_SYMBOL(drm_syncobj_find); |
125 | 100 | ||
126 | static struct dma_fence * | ||
127 | drm_syncobj_find_signal_pt_for_point(struct drm_syncobj *syncobj, | ||
128 | uint64_t point) | ||
129 | { | ||
130 | struct drm_syncobj_signal_pt *signal_pt; | ||
131 | |||
132 | if ((syncobj->type == DRM_SYNCOBJ_TYPE_TIMELINE) && | ||
133 | (point <= syncobj->timeline)) | ||
134 | return drm_syncobj_get_stub_fence(); | ||
135 | |||
136 | list_for_each_entry(signal_pt, &syncobj->signal_pt_list, list) { | ||
137 | if (point > signal_pt->value) | ||
138 | continue; | ||
139 | if ((syncobj->type == DRM_SYNCOBJ_TYPE_BINARY) && | ||
140 | (point != signal_pt->value)) | ||
141 | continue; | ||
142 | return dma_fence_get(&signal_pt->fence_array->base); | ||
143 | } | ||
144 | return NULL; | ||
145 | } | ||
146 | |||
147 | static void drm_syncobj_add_callback_locked(struct drm_syncobj *syncobj, | 101 | static void drm_syncobj_add_callback_locked(struct drm_syncobj *syncobj, |
148 | struct drm_syncobj_cb *cb, | 102 | struct drm_syncobj_cb *cb, |
149 | drm_syncobj_func_t func) | 103 | drm_syncobj_func_t func) |
@@ -152,158 +106,53 @@ static void drm_syncobj_add_callback_locked(struct drm_syncobj *syncobj, | |||
152 | list_add_tail(&cb->node, &syncobj->cb_list); | 106 | list_add_tail(&cb->node, &syncobj->cb_list); |
153 | } | 107 | } |
154 | 108 | ||
155 | static void drm_syncobj_fence_get_or_add_callback(struct drm_syncobj *syncobj, | 109 | static int drm_syncobj_fence_get_or_add_callback(struct drm_syncobj *syncobj, |
156 | struct dma_fence **fence, | 110 | struct dma_fence **fence, |
157 | struct drm_syncobj_cb *cb, | 111 | struct drm_syncobj_cb *cb, |
158 | drm_syncobj_func_t func) | 112 | drm_syncobj_func_t func) |
159 | { | 113 | { |
160 | u64 pt_value = 0; | 114 | int ret; |
161 | |||
162 | WARN_ON(*fence); | ||
163 | 115 | ||
164 | if (syncobj->type == DRM_SYNCOBJ_TYPE_BINARY) { | 116 | *fence = drm_syncobj_fence_get(syncobj); |
165 | /*BINARY syncobj always wait on last pt */ | 117 | if (*fence) |
166 | pt_value = syncobj->signal_point; | 118 | return 1; |
167 | 119 | ||
168 | if (pt_value == 0) | 120 | spin_lock(&syncobj->lock); |
169 | pt_value += DRM_SYNCOBJ_BINARY_POINT; | 121 | /* We've already tried once to get a fence and failed. Now that we |
170 | } | 122 | * have the lock, try one more time just to be sure we don't add a |
171 | 123 | * callback when a fence has already been set. | |
172 | mutex_lock(&syncobj->cb_mutex); | 124 | */ |
173 | spin_lock(&syncobj->pt_lock); | 125 | if (syncobj->fence) { |
174 | *fence = drm_syncobj_find_signal_pt_for_point(syncobj, pt_value); | 126 | *fence = dma_fence_get(rcu_dereference_protected(syncobj->fence, |
175 | spin_unlock(&syncobj->pt_lock); | 127 | lockdep_is_held(&syncobj->lock))); |
176 | if (!*fence) | 128 | ret = 1; |
129 | } else { | ||
130 | *fence = NULL; | ||
177 | drm_syncobj_add_callback_locked(syncobj, cb, func); | 131 | drm_syncobj_add_callback_locked(syncobj, cb, func); |
178 | mutex_unlock(&syncobj->cb_mutex); | 132 | ret = 0; |
179 | } | 133 | } |
180 | 134 | spin_unlock(&syncobj->lock); | |
181 | static void drm_syncobj_remove_callback(struct drm_syncobj *syncobj, | ||
182 | struct drm_syncobj_cb *cb) | ||
183 | { | ||
184 | mutex_lock(&syncobj->cb_mutex); | ||
185 | list_del_init(&cb->node); | ||
186 | mutex_unlock(&syncobj->cb_mutex); | ||
187 | } | ||
188 | 135 | ||
189 | static void drm_syncobj_init(struct drm_syncobj *syncobj) | 136 | return ret; |
190 | { | ||
191 | spin_lock(&syncobj->pt_lock); | ||
192 | syncobj->timeline_context = dma_fence_context_alloc(1); | ||
193 | syncobj->timeline = 0; | ||
194 | syncobj->signal_point = 0; | ||
195 | init_waitqueue_head(&syncobj->wq); | ||
196 | |||
197 | INIT_LIST_HEAD(&syncobj->signal_pt_list); | ||
198 | spin_unlock(&syncobj->pt_lock); | ||
199 | } | 137 | } |
200 | 138 | ||
201 | static void drm_syncobj_fini(struct drm_syncobj *syncobj) | 139 | void drm_syncobj_add_callback(struct drm_syncobj *syncobj, |
140 | struct drm_syncobj_cb *cb, | ||
141 | drm_syncobj_func_t func) | ||
202 | { | 142 | { |
203 | struct drm_syncobj_signal_pt *signal_pt = NULL, *tmp; | 143 | spin_lock(&syncobj->lock); |
204 | 144 | drm_syncobj_add_callback_locked(syncobj, cb, func); | |
205 | spin_lock(&syncobj->pt_lock); | 145 | spin_unlock(&syncobj->lock); |
206 | list_for_each_entry_safe(signal_pt, tmp, | ||
207 | &syncobj->signal_pt_list, list) { | ||
208 | list_del(&signal_pt->list); | ||
209 | dma_fence_put(&signal_pt->fence_array->base); | ||
210 | kfree(signal_pt); | ||
211 | } | ||
212 | spin_unlock(&syncobj->pt_lock); | ||
213 | } | 146 | } |
214 | 147 | ||
215 | static int drm_syncobj_create_signal_pt(struct drm_syncobj *syncobj, | 148 | void drm_syncobj_remove_callback(struct drm_syncobj *syncobj, |
216 | struct dma_fence *fence, | 149 | struct drm_syncobj_cb *cb) |
217 | u64 point) | ||
218 | { | 150 | { |
219 | struct drm_syncobj_signal_pt *signal_pt = | 151 | spin_lock(&syncobj->lock); |
220 | kzalloc(sizeof(struct drm_syncobj_signal_pt), GFP_KERNEL); | 152 | list_del_init(&cb->node); |
221 | struct drm_syncobj_signal_pt *tail_pt; | 153 | spin_unlock(&syncobj->lock); |
222 | struct dma_fence **fences; | ||
223 | int num_fences = 0; | ||
224 | int ret = 0, i; | ||
225 | |||
226 | if (!signal_pt) | ||
227 | return -ENOMEM; | ||
228 | if (!fence) | ||
229 | goto out; | ||
230 | |||
231 | fences = kmalloc_array(sizeof(void *), 2, GFP_KERNEL); | ||
232 | if (!fences) { | ||
233 | ret = -ENOMEM; | ||
234 | goto out; | ||
235 | } | ||
236 | fences[num_fences++] = dma_fence_get(fence); | ||
237 | /* timeline syncobj must take this dependency */ | ||
238 | if (syncobj->type == DRM_SYNCOBJ_TYPE_TIMELINE) { | ||
239 | spin_lock(&syncobj->pt_lock); | ||
240 | if (!list_empty(&syncobj->signal_pt_list)) { | ||
241 | tail_pt = list_last_entry(&syncobj->signal_pt_list, | ||
242 | struct drm_syncobj_signal_pt, list); | ||
243 | fences[num_fences++] = | ||
244 | dma_fence_get(&tail_pt->fence_array->base); | ||
245 | } | ||
246 | spin_unlock(&syncobj->pt_lock); | ||
247 | } | ||
248 | signal_pt->fence_array = dma_fence_array_create(num_fences, fences, | ||
249 | syncobj->timeline_context, | ||
250 | point, false); | ||
251 | if (!signal_pt->fence_array) { | ||
252 | ret = -ENOMEM; | ||
253 | goto fail; | ||
254 | } | ||
255 | |||
256 | spin_lock(&syncobj->pt_lock); | ||
257 | if (syncobj->signal_point >= point) { | ||
258 | DRM_WARN("A later signal is ready!"); | ||
259 | spin_unlock(&syncobj->pt_lock); | ||
260 | goto exist; | ||
261 | } | ||
262 | signal_pt->value = point; | ||
263 | list_add_tail(&signal_pt->list, &syncobj->signal_pt_list); | ||
264 | syncobj->signal_point = point; | ||
265 | spin_unlock(&syncobj->pt_lock); | ||
266 | wake_up_all(&syncobj->wq); | ||
267 | |||
268 | return 0; | ||
269 | exist: | ||
270 | dma_fence_put(&signal_pt->fence_array->base); | ||
271 | fail: | ||
272 | for (i = 0; i < num_fences; i++) | ||
273 | dma_fence_put(fences[i]); | ||
274 | kfree(fences); | ||
275 | out: | ||
276 | kfree(signal_pt); | ||
277 | return ret; | ||
278 | } | 154 | } |
279 | 155 | ||
280 | static void drm_syncobj_garbage_collection(struct drm_syncobj *syncobj) | ||
281 | { | ||
282 | struct drm_syncobj_signal_pt *signal_pt, *tmp, *tail_pt; | ||
283 | |||
284 | spin_lock(&syncobj->pt_lock); | ||
285 | tail_pt = list_last_entry(&syncobj->signal_pt_list, | ||
286 | struct drm_syncobj_signal_pt, | ||
287 | list); | ||
288 | list_for_each_entry_safe(signal_pt, tmp, | ||
289 | &syncobj->signal_pt_list, list) { | ||
290 | if (syncobj->type == DRM_SYNCOBJ_TYPE_BINARY && | ||
291 | signal_pt == tail_pt) | ||
292 | continue; | ||
293 | if (dma_fence_is_signaled(&signal_pt->fence_array->base)) { | ||
294 | syncobj->timeline = signal_pt->value; | ||
295 | list_del(&signal_pt->list); | ||
296 | dma_fence_put(&signal_pt->fence_array->base); | ||
297 | kfree(signal_pt); | ||
298 | } else { | ||
299 | /*signal_pt is in order in list, from small to big, so | ||
300 | * the later must not be signal either */ | ||
301 | break; | ||
302 | } | ||
303 | } | ||
304 | |||
305 | spin_unlock(&syncobj->pt_lock); | ||
306 | } | ||
307 | /** | 156 | /** |
308 | * drm_syncobj_replace_fence - replace fence in a sync object. | 157 | * drm_syncobj_replace_fence - replace fence in a sync object. |
309 | * @syncobj: Sync object to replace fence in | 158 | * @syncobj: Sync object to replace fence in |
@@ -316,30 +165,28 @@ void drm_syncobj_replace_fence(struct drm_syncobj *syncobj, | |||
316 | u64 point, | 165 | u64 point, |
317 | struct dma_fence *fence) | 166 | struct dma_fence *fence) |
318 | { | 167 | { |
319 | u64 pt_value = point; | 168 | struct dma_fence *old_fence; |
320 | 169 | struct drm_syncobj_cb *cur, *tmp; | |
321 | drm_syncobj_garbage_collection(syncobj); | 170 | |
322 | if (syncobj->type == DRM_SYNCOBJ_TYPE_BINARY) { | 171 | if (fence) |
323 | if (!fence) { | 172 | dma_fence_get(fence); |
324 | drm_syncobj_fini(syncobj); | 173 | |
325 | drm_syncobj_init(syncobj); | 174 | spin_lock(&syncobj->lock); |
326 | return; | 175 | |
327 | } | 176 | old_fence = rcu_dereference_protected(syncobj->fence, |
328 | pt_value = syncobj->signal_point + | 177 | lockdep_is_held(&syncobj->lock)); |
329 | DRM_SYNCOBJ_BINARY_POINT; | 178 | rcu_assign_pointer(syncobj->fence, fence); |
330 | } | ||
331 | drm_syncobj_create_signal_pt(syncobj, fence, pt_value); | ||
332 | if (fence) { | ||
333 | struct drm_syncobj_cb *cur, *tmp; | ||
334 | LIST_HEAD(cb_list); | ||
335 | 179 | ||
336 | mutex_lock(&syncobj->cb_mutex); | 180 | if (fence != old_fence) { |
337 | list_for_each_entry_safe(cur, tmp, &syncobj->cb_list, node) { | 181 | list_for_each_entry_safe(cur, tmp, &syncobj->cb_list, node) { |
338 | list_del_init(&cur->node); | 182 | list_del_init(&cur->node); |
339 | cur->func(syncobj, cur); | 183 | cur->func(syncobj, cur); |
340 | } | 184 | } |
341 | mutex_unlock(&syncobj->cb_mutex); | ||
342 | } | 185 | } |
186 | |||
187 | spin_unlock(&syncobj->lock); | ||
188 | |||
189 | dma_fence_put(old_fence); | ||
343 | } | 190 | } |
344 | EXPORT_SYMBOL(drm_syncobj_replace_fence); | 191 | EXPORT_SYMBOL(drm_syncobj_replace_fence); |
345 | 192 | ||
@@ -362,64 +209,6 @@ static int drm_syncobj_assign_null_handle(struct drm_syncobj *syncobj) | |||
362 | return 0; | 209 | return 0; |
363 | } | 210 | } |
364 | 211 | ||
365 | static int | ||
366 | drm_syncobj_point_get(struct drm_syncobj *syncobj, u64 point, u64 flags, | ||
367 | struct dma_fence **fence) | ||
368 | { | ||
369 | int ret = 0; | ||
370 | |||
371 | if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) { | ||
372 | ret = wait_event_interruptible(syncobj->wq, | ||
373 | point <= syncobj->signal_point); | ||
374 | if (ret < 0) | ||
375 | return ret; | ||
376 | } | ||
377 | spin_lock(&syncobj->pt_lock); | ||
378 | *fence = drm_syncobj_find_signal_pt_for_point(syncobj, point); | ||
379 | if (!*fence) | ||
380 | ret = -EINVAL; | ||
381 | spin_unlock(&syncobj->pt_lock); | ||
382 | return ret; | ||
383 | } | ||
384 | |||
385 | /** | ||
386 | * drm_syncobj_search_fence - lookup and reference the fence in a sync object or | ||
387 | * in a timeline point | ||
388 | * @syncobj: sync object pointer | ||
389 | * @point: timeline point | ||
390 | * @flags: DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT or not | ||
391 | * @fence: out parameter for the fence | ||
392 | * | ||
393 | * if flags is DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT, the function will block | ||
394 | * here until specific timeline points is reached. | ||
395 | * if not, you need a submit thread and block in userspace until all future | ||
396 | * timeline points have materialized, only then you can submit to the kernel, | ||
397 | * otherwise, function will fail to return fence. | ||
398 | * | ||
399 | * Returns 0 on success or a negative error value on failure. On success @fence | ||
400 | * contains a reference to the fence, which must be released by calling | ||
401 | * dma_fence_put(). | ||
402 | */ | ||
403 | int drm_syncobj_search_fence(struct drm_syncobj *syncobj, u64 point, | ||
404 | u64 flags, struct dma_fence **fence) | ||
405 | { | ||
406 | u64 pt_value = point; | ||
407 | |||
408 | if (!syncobj) | ||
409 | return -ENOENT; | ||
410 | |||
411 | drm_syncobj_garbage_collection(syncobj); | ||
412 | if (syncobj->type == DRM_SYNCOBJ_TYPE_BINARY) { | ||
413 | /*BINARY syncobj always wait on last pt */ | ||
414 | pt_value = syncobj->signal_point; | ||
415 | |||
416 | if (pt_value == 0) | ||
417 | pt_value += DRM_SYNCOBJ_BINARY_POINT; | ||
418 | } | ||
419 | return drm_syncobj_point_get(syncobj, pt_value, flags, fence); | ||
420 | } | ||
421 | EXPORT_SYMBOL(drm_syncobj_search_fence); | ||
422 | |||
423 | /** | 212 | /** |
424 | * drm_syncobj_find_fence - lookup and reference the fence in a sync object | 213 | * drm_syncobj_find_fence - lookup and reference the fence in a sync object |
425 | * @file_private: drm file private pointer | 214 | * @file_private: drm file private pointer |
@@ -429,7 +218,7 @@ EXPORT_SYMBOL(drm_syncobj_search_fence); | |||
429 | * @fence: out parameter for the fence | 218 | * @fence: out parameter for the fence |
430 | * | 219 | * |
431 | * This is just a convenience function that combines drm_syncobj_find() and | 220 | * This is just a convenience function that combines drm_syncobj_find() and |
432 | * drm_syncobj_lookup_fence(). | 221 | * drm_syncobj_fence_get(). |
433 | * | 222 | * |
434 | * Returns 0 on success or a negative error value on failure. On success @fence | 223 | * Returns 0 on success or a negative error value on failure. On success @fence |
435 | * contains a reference to the fence, which must be released by calling | 224 | * contains a reference to the fence, which must be released by calling |
@@ -440,11 +229,16 @@ int drm_syncobj_find_fence(struct drm_file *file_private, | |||
440 | struct dma_fence **fence) | 229 | struct dma_fence **fence) |
441 | { | 230 | { |
442 | struct drm_syncobj *syncobj = drm_syncobj_find(file_private, handle); | 231 | struct drm_syncobj *syncobj = drm_syncobj_find(file_private, handle); |
443 | int ret; | 232 | int ret = 0; |
444 | 233 | ||
445 | ret = drm_syncobj_search_fence(syncobj, point, flags, fence); | 234 | if (!syncobj) |
446 | if (syncobj) | 235 | return -ENOENT; |
447 | drm_syncobj_put(syncobj); | 236 | |
237 | *fence = drm_syncobj_fence_get(syncobj); | ||
238 | if (!*fence) { | ||
239 | ret = -EINVAL; | ||
240 | } | ||
241 | drm_syncobj_put(syncobj); | ||
448 | return ret; | 242 | return ret; |
449 | } | 243 | } |
450 | EXPORT_SYMBOL(drm_syncobj_find_fence); | 244 | EXPORT_SYMBOL(drm_syncobj_find_fence); |
@@ -460,7 +254,7 @@ void drm_syncobj_free(struct kref *kref) | |||
460 | struct drm_syncobj *syncobj = container_of(kref, | 254 | struct drm_syncobj *syncobj = container_of(kref, |
461 | struct drm_syncobj, | 255 | struct drm_syncobj, |
462 | refcount); | 256 | refcount); |
463 | drm_syncobj_fini(syncobj); | 257 | drm_syncobj_replace_fence(syncobj, 0, NULL); |
464 | kfree(syncobj); | 258 | kfree(syncobj); |
465 | } | 259 | } |
466 | EXPORT_SYMBOL(drm_syncobj_free); | 260 | EXPORT_SYMBOL(drm_syncobj_free); |
@@ -493,13 +287,7 @@ int drm_syncobj_create(struct drm_syncobj **out_syncobj, uint32_t flags, | |||
493 | 287 | ||
494 | kref_init(&syncobj->refcount); | 288 | kref_init(&syncobj->refcount); |
495 | INIT_LIST_HEAD(&syncobj->cb_list); | 289 | INIT_LIST_HEAD(&syncobj->cb_list); |
496 | spin_lock_init(&syncobj->pt_lock); | 290 | spin_lock_init(&syncobj->lock); |
497 | mutex_init(&syncobj->cb_mutex); | ||
498 | if (flags & DRM_SYNCOBJ_CREATE_TYPE_TIMELINE) | ||
499 | syncobj->type = DRM_SYNCOBJ_TYPE_TIMELINE; | ||
500 | else | ||
501 | syncobj->type = DRM_SYNCOBJ_TYPE_BINARY; | ||
502 | drm_syncobj_init(syncobj); | ||
503 | 291 | ||
504 | if (flags & DRM_SYNCOBJ_CREATE_SIGNALED) { | 292 | if (flags & DRM_SYNCOBJ_CREATE_SIGNALED) { |
505 | ret = drm_syncobj_assign_null_handle(syncobj); | 293 | ret = drm_syncobj_assign_null_handle(syncobj); |
@@ -782,8 +570,7 @@ drm_syncobj_create_ioctl(struct drm_device *dev, void *data, | |||
782 | return -EOPNOTSUPP; | 570 | return -EOPNOTSUPP; |
783 | 571 | ||
784 | /* no valid flags yet */ | 572 | /* no valid flags yet */ |
785 | if (args->flags & ~(DRM_SYNCOBJ_CREATE_SIGNALED | | 573 | if (args->flags & ~DRM_SYNCOBJ_CREATE_SIGNALED) |
786 | DRM_SYNCOBJ_CREATE_TYPE_TIMELINE)) | ||
787 | return -EINVAL; | 574 | return -EINVAL; |
788 | 575 | ||
789 | return drm_syncobj_create_as_handle(file_private, | 576 | return drm_syncobj_create_as_handle(file_private, |
@@ -876,8 +663,9 @@ static void syncobj_wait_syncobj_func(struct drm_syncobj *syncobj, | |||
876 | struct syncobj_wait_entry *wait = | 663 | struct syncobj_wait_entry *wait = |
877 | container_of(cb, struct syncobj_wait_entry, syncobj_cb); | 664 | container_of(cb, struct syncobj_wait_entry, syncobj_cb); |
878 | 665 | ||
879 | drm_syncobj_search_fence(syncobj, 0, 0, &wait->fence); | 666 | /* This happens inside the syncobj lock */ |
880 | 667 | wait->fence = dma_fence_get(rcu_dereference_protected(syncobj->fence, | |
668 | lockdep_is_held(&syncobj->lock))); | ||
881 | wake_up_process(wait->task); | 669 | wake_up_process(wait->task); |
882 | } | 670 | } |
883 | 671 | ||
@@ -903,8 +691,7 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs, | |||
903 | signaled_count = 0; | 691 | signaled_count = 0; |
904 | for (i = 0; i < count; ++i) { | 692 | for (i = 0; i < count; ++i) { |
905 | entries[i].task = current; | 693 | entries[i].task = current; |
906 | drm_syncobj_search_fence(syncobjs[i], 0, 0, | 694 | entries[i].fence = drm_syncobj_fence_get(syncobjs[i]); |
907 | &entries[i].fence); | ||
908 | if (!entries[i].fence) { | 695 | if (!entries[i].fence) { |
909 | if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) { | 696 | if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) { |
910 | continue; | 697 | continue; |
@@ -935,9 +722,6 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs, | |||
935 | 722 | ||
936 | if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) { | 723 | if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) { |
937 | for (i = 0; i < count; ++i) { | 724 | for (i = 0; i < count; ++i) { |
938 | if (entries[i].fence) | ||
939 | continue; | ||
940 | |||
941 | drm_syncobj_fence_get_or_add_callback(syncobjs[i], | 725 | drm_syncobj_fence_get_or_add_callback(syncobjs[i], |
942 | &entries[i].fence, | 726 | &entries[i].fence, |
943 | &entries[i].syncobj_cb, | 727 | &entries[i].syncobj_cb, |
@@ -1169,13 +953,12 @@ drm_syncobj_reset_ioctl(struct drm_device *dev, void *data, | |||
1169 | if (ret < 0) | 953 | if (ret < 0) |
1170 | return ret; | 954 | return ret; |
1171 | 955 | ||
1172 | for (i = 0; i < args->count_handles; i++) { | 956 | for (i = 0; i < args->count_handles; i++) |
1173 | drm_syncobj_fini(syncobjs[i]); | 957 | drm_syncobj_replace_fence(syncobjs[i], 0, NULL); |
1174 | drm_syncobj_init(syncobjs[i]); | 958 | |
1175 | } | ||
1176 | drm_syncobj_array_free(syncobjs, args->count_handles); | 959 | drm_syncobj_array_free(syncobjs, args->count_handles); |
1177 | 960 | ||
1178 | return ret; | 961 | return 0; |
1179 | } | 962 | } |
1180 | 963 | ||
1181 | int | 964 | int |