diff options
Diffstat (limited to 'drivers/gpu/drm/drm_syncobj.c')
-rw-r--r-- | drivers/gpu/drm/drm_syncobj.c | 359 |
1 files changed, 286 insertions, 73 deletions
diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index 5c2091dbd230..da8175d9c6ff 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c | |||
@@ -56,6 +56,9 @@ | |||
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 | |||
59 | struct drm_syncobj_stub_fence { | 62 | struct drm_syncobj_stub_fence { |
60 | struct dma_fence base; | 63 | struct dma_fence base; |
61 | spinlock_t lock; | 64 | spinlock_t lock; |
@@ -71,7 +74,29 @@ static const struct dma_fence_ops drm_syncobj_stub_fence_ops = { | |||
71 | .get_timeline_name = drm_syncobj_stub_fence_get_name, | 74 | .get_timeline_name = drm_syncobj_stub_fence_get_name, |
72 | }; | 75 | }; |
73 | 76 | ||
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; | ||
74 | 85 | ||
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 | } | ||
75 | /** | 100 | /** |
76 | * drm_syncobj_find - lookup and reference a sync object. | 101 | * drm_syncobj_find - lookup and reference a sync object. |
77 | * @file_private: drm file private pointer | 102 | * @file_private: drm file private pointer |
@@ -98,6 +123,27 @@ struct drm_syncobj *drm_syncobj_find(struct drm_file *file_private, | |||
98 | } | 123 | } |
99 | EXPORT_SYMBOL(drm_syncobj_find); | 124 | EXPORT_SYMBOL(drm_syncobj_find); |
100 | 125 | ||
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 | |||
101 | static void drm_syncobj_add_callback_locked(struct drm_syncobj *syncobj, | 147 | static void drm_syncobj_add_callback_locked(struct drm_syncobj *syncobj, |
102 | struct drm_syncobj_cb *cb, | 148 | struct drm_syncobj_cb *cb, |
103 | drm_syncobj_func_t func) | 149 | drm_syncobj_func_t func) |
@@ -106,55 +152,158 @@ static void drm_syncobj_add_callback_locked(struct drm_syncobj *syncobj, | |||
106 | list_add_tail(&cb->node, &syncobj->cb_list); | 152 | list_add_tail(&cb->node, &syncobj->cb_list); |
107 | } | 153 | } |
108 | 154 | ||
109 | static int drm_syncobj_fence_get_or_add_callback(struct drm_syncobj *syncobj, | 155 | static void drm_syncobj_fence_get_or_add_callback(struct drm_syncobj *syncobj, |
110 | struct dma_fence **fence, | 156 | struct dma_fence **fence, |
111 | struct drm_syncobj_cb *cb, | 157 | struct drm_syncobj_cb *cb, |
112 | drm_syncobj_func_t func) | 158 | drm_syncobj_func_t func) |
113 | { | 159 | { |
114 | int ret; | 160 | u64 pt_value = 0; |
115 | 161 | ||
116 | WARN_ON(*fence); | 162 | WARN_ON(*fence); |
117 | 163 | ||
118 | *fence = drm_syncobj_fence_get(syncobj); | 164 | if (syncobj->type == DRM_SYNCOBJ_TYPE_BINARY) { |
119 | if (*fence) | 165 | /*BINARY syncobj always wait on last pt */ |
120 | return 1; | 166 | pt_value = syncobj->signal_point; |
121 | 167 | ||
122 | spin_lock(&syncobj->lock); | 168 | if (pt_value == 0) |
123 | /* We've already tried once to get a fence and failed. Now that we | 169 | pt_value += DRM_SYNCOBJ_BINARY_POINT; |
124 | * have the lock, try one more time just to be sure we don't add a | ||
125 | * callback when a fence has already been set. | ||
126 | */ | ||
127 | if (syncobj->fence) { | ||
128 | *fence = dma_fence_get(rcu_dereference_protected(syncobj->fence, | ||
129 | lockdep_is_held(&syncobj->lock))); | ||
130 | ret = 1; | ||
131 | } else { | ||
132 | *fence = NULL; | ||
133 | drm_syncobj_add_callback_locked(syncobj, cb, func); | ||
134 | ret = 0; | ||
135 | } | 170 | } |
136 | spin_unlock(&syncobj->lock); | ||
137 | 171 | ||
138 | return ret; | 172 | mutex_lock(&syncobj->cb_mutex); |
173 | spin_lock(&syncobj->pt_lock); | ||
174 | *fence = drm_syncobj_find_signal_pt_for_point(syncobj, pt_value); | ||
175 | spin_unlock(&syncobj->pt_lock); | ||
176 | if (!*fence) | ||
177 | drm_syncobj_add_callback_locked(syncobj, cb, func); | ||
178 | mutex_unlock(&syncobj->cb_mutex); | ||
139 | } | 179 | } |
140 | 180 | ||
141 | void drm_syncobj_add_callback(struct drm_syncobj *syncobj, | 181 | static void drm_syncobj_remove_callback(struct drm_syncobj *syncobj, |
142 | struct drm_syncobj_cb *cb, | 182 | struct drm_syncobj_cb *cb) |
143 | drm_syncobj_func_t func) | ||
144 | { | 183 | { |
145 | spin_lock(&syncobj->lock); | 184 | mutex_lock(&syncobj->cb_mutex); |
146 | drm_syncobj_add_callback_locked(syncobj, cb, func); | 185 | list_del_init(&cb->node); |
147 | spin_unlock(&syncobj->lock); | 186 | mutex_unlock(&syncobj->cb_mutex); |
148 | } | 187 | } |
149 | 188 | ||
150 | void drm_syncobj_remove_callback(struct drm_syncobj *syncobj, | 189 | static void drm_syncobj_init(struct drm_syncobj *syncobj) |
151 | struct drm_syncobj_cb *cb) | ||
152 | { | 190 | { |
153 | spin_lock(&syncobj->lock); | 191 | spin_lock(&syncobj->pt_lock); |
154 | list_del_init(&cb->node); | 192 | syncobj->timeline_context = dma_fence_context_alloc(1); |
155 | spin_unlock(&syncobj->lock); | 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 | } | ||
200 | |||
201 | static void drm_syncobj_fini(struct drm_syncobj *syncobj) | ||
202 | { | ||
203 | struct drm_syncobj_signal_pt *signal_pt = NULL, *tmp; | ||
204 | |||
205 | spin_lock(&syncobj->pt_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 | } | ||
214 | |||
215 | static int drm_syncobj_create_signal_pt(struct drm_syncobj *syncobj, | ||
216 | struct dma_fence *fence, | ||
217 | u64 point) | ||
218 | { | ||
219 | struct drm_syncobj_signal_pt *signal_pt = | ||
220 | kzalloc(sizeof(struct drm_syncobj_signal_pt), GFP_KERNEL); | ||
221 | struct drm_syncobj_signal_pt *tail_pt; | ||
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; | ||
156 | } | 278 | } |
157 | 279 | ||
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 | } | ||
158 | /** | 307 | /** |
159 | * drm_syncobj_replace_fence - replace fence in a sync object. | 308 | * drm_syncobj_replace_fence - replace fence in a sync object. |
160 | * @syncobj: Sync object to replace fence in | 309 | * @syncobj: Sync object to replace fence in |
@@ -167,28 +316,30 @@ void drm_syncobj_replace_fence(struct drm_syncobj *syncobj, | |||
167 | u64 point, | 316 | u64 point, |
168 | struct dma_fence *fence) | 317 | struct dma_fence *fence) |
169 | { | 318 | { |
170 | struct dma_fence *old_fence; | 319 | u64 pt_value = point; |
171 | struct drm_syncobj_cb *cur, *tmp; | 320 | |
172 | 321 | drm_syncobj_garbage_collection(syncobj); | |
173 | if (fence) | 322 | if (syncobj->type == DRM_SYNCOBJ_TYPE_BINARY) { |
174 | dma_fence_get(fence); | 323 | if (!fence) { |
175 | 324 | drm_syncobj_fini(syncobj); | |
176 | spin_lock(&syncobj->lock); | 325 | drm_syncobj_init(syncobj); |
177 | 326 | return; | |
178 | old_fence = rcu_dereference_protected(syncobj->fence, | 327 | } |
179 | lockdep_is_held(&syncobj->lock)); | 328 | pt_value = syncobj->signal_point + |
180 | rcu_assign_pointer(syncobj->fence, fence); | 329 | DRM_SYNCOBJ_BINARY_POINT; |
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); | ||
181 | 335 | ||
182 | if (fence != old_fence) { | 336 | mutex_lock(&syncobj->cb_mutex); |
183 | list_for_each_entry_safe(cur, tmp, &syncobj->cb_list, node) { | 337 | list_for_each_entry_safe(cur, tmp, &syncobj->cb_list, node) { |
184 | list_del_init(&cur->node); | 338 | list_del_init(&cur->node); |
185 | cur->func(syncobj, cur); | 339 | cur->func(syncobj, cur); |
186 | } | 340 | } |
341 | mutex_unlock(&syncobj->cb_mutex); | ||
187 | } | 342 | } |
188 | |||
189 | spin_unlock(&syncobj->lock); | ||
190 | |||
191 | dma_fence_put(old_fence); | ||
192 | } | 343 | } |
193 | EXPORT_SYMBOL(drm_syncobj_replace_fence); | 344 | EXPORT_SYMBOL(drm_syncobj_replace_fence); |
194 | 345 | ||
@@ -211,35 +362,89 @@ static int drm_syncobj_assign_null_handle(struct drm_syncobj *syncobj) | |||
211 | return 0; | 362 | return 0; |
212 | } | 363 | } |
213 | 364 | ||
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 | |||
214 | /** | 423 | /** |
215 | * drm_syncobj_find_fence - lookup and reference the fence in a sync object | 424 | * drm_syncobj_find_fence - lookup and reference the fence in a sync object |
216 | * @file_private: drm file private pointer | 425 | * @file_private: drm file private pointer |
217 | * @handle: sync object handle to lookup. | 426 | * @handle: sync object handle to lookup. |
218 | * @point: timeline point | 427 | * @point: timeline point |
428 | * @flags: DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT or not | ||
219 | * @fence: out parameter for the fence | 429 | * @fence: out parameter for the fence |
220 | * | 430 | * |
221 | * This is just a convenience function that combines drm_syncobj_find() and | 431 | * This is just a convenience function that combines drm_syncobj_find() and |
222 | * drm_syncobj_fence_get(). | 432 | * drm_syncobj_lookup_fence(). |
223 | * | 433 | * |
224 | * Returns 0 on success or a negative error value on failure. On success @fence | 434 | * Returns 0 on success or a negative error value on failure. On success @fence |
225 | * contains a reference to the fence, which must be released by calling | 435 | * contains a reference to the fence, which must be released by calling |
226 | * dma_fence_put(). | 436 | * dma_fence_put(). |
227 | */ | 437 | */ |
228 | int drm_syncobj_find_fence(struct drm_file *file_private, | 438 | int drm_syncobj_find_fence(struct drm_file *file_private, |
229 | u32 handle, u64 point, | 439 | u32 handle, u64 point, u64 flags, |
230 | struct dma_fence **fence) | 440 | struct dma_fence **fence) |
231 | { | 441 | { |
232 | struct drm_syncobj *syncobj = drm_syncobj_find(file_private, handle); | 442 | struct drm_syncobj *syncobj = drm_syncobj_find(file_private, handle); |
233 | int ret = 0; | 443 | int ret; |
234 | |||
235 | if (!syncobj) | ||
236 | return -ENOENT; | ||
237 | 444 | ||
238 | *fence = drm_syncobj_fence_get(syncobj); | 445 | ret = drm_syncobj_search_fence(syncobj, point, flags, fence); |
239 | if (!*fence) { | 446 | if (syncobj) |
240 | ret = -EINVAL; | 447 | drm_syncobj_put(syncobj); |
241 | } | ||
242 | drm_syncobj_put(syncobj); | ||
243 | return ret; | 448 | return ret; |
244 | } | 449 | } |
245 | EXPORT_SYMBOL(drm_syncobj_find_fence); | 450 | EXPORT_SYMBOL(drm_syncobj_find_fence); |
@@ -255,7 +460,7 @@ void drm_syncobj_free(struct kref *kref) | |||
255 | struct drm_syncobj *syncobj = container_of(kref, | 460 | struct drm_syncobj *syncobj = container_of(kref, |
256 | struct drm_syncobj, | 461 | struct drm_syncobj, |
257 | refcount); | 462 | refcount); |
258 | drm_syncobj_replace_fence(syncobj, 0, NULL); | 463 | drm_syncobj_fini(syncobj); |
259 | kfree(syncobj); | 464 | kfree(syncobj); |
260 | } | 465 | } |
261 | EXPORT_SYMBOL(drm_syncobj_free); | 466 | EXPORT_SYMBOL(drm_syncobj_free); |
@@ -284,7 +489,13 @@ int drm_syncobj_create(struct drm_syncobj **out_syncobj, uint32_t flags, | |||
284 | 489 | ||
285 | kref_init(&syncobj->refcount); | 490 | kref_init(&syncobj->refcount); |
286 | INIT_LIST_HEAD(&syncobj->cb_list); | 491 | INIT_LIST_HEAD(&syncobj->cb_list); |
287 | spin_lock_init(&syncobj->lock); | 492 | spin_lock_init(&syncobj->pt_lock); |
493 | mutex_init(&syncobj->cb_mutex); | ||
494 | if (flags & DRM_SYNCOBJ_CREATE_TYPE_TIMELINE) | ||
495 | syncobj->type = DRM_SYNCOBJ_TYPE_TIMELINE; | ||
496 | else | ||
497 | syncobj->type = DRM_SYNCOBJ_TYPE_BINARY; | ||
498 | drm_syncobj_init(syncobj); | ||
288 | 499 | ||
289 | if (flags & DRM_SYNCOBJ_CREATE_SIGNALED) { | 500 | if (flags & DRM_SYNCOBJ_CREATE_SIGNALED) { |
290 | ret = drm_syncobj_assign_null_handle(syncobj); | 501 | ret = drm_syncobj_assign_null_handle(syncobj); |
@@ -497,7 +708,7 @@ static int drm_syncobj_export_sync_file(struct drm_file *file_private, | |||
497 | if (fd < 0) | 708 | if (fd < 0) |
498 | return fd; | 709 | return fd; |
499 | 710 | ||
500 | ret = drm_syncobj_find_fence(file_private, handle, 0, &fence); | 711 | ret = drm_syncobj_find_fence(file_private, handle, 0, 0, &fence); |
501 | if (ret) | 712 | if (ret) |
502 | goto err_put_fd; | 713 | goto err_put_fd; |
503 | 714 | ||
@@ -567,7 +778,8 @@ drm_syncobj_create_ioctl(struct drm_device *dev, void *data, | |||
567 | return -EOPNOTSUPP; | 778 | return -EOPNOTSUPP; |
568 | 779 | ||
569 | /* no valid flags yet */ | 780 | /* no valid flags yet */ |
570 | if (args->flags & ~DRM_SYNCOBJ_CREATE_SIGNALED) | 781 | if (args->flags & ~(DRM_SYNCOBJ_CREATE_SIGNALED | |
782 | DRM_SYNCOBJ_CREATE_TYPE_TIMELINE)) | ||
571 | return -EINVAL; | 783 | return -EINVAL; |
572 | 784 | ||
573 | return drm_syncobj_create_as_handle(file_private, | 785 | return drm_syncobj_create_as_handle(file_private, |
@@ -660,9 +872,8 @@ static void syncobj_wait_syncobj_func(struct drm_syncobj *syncobj, | |||
660 | struct syncobj_wait_entry *wait = | 872 | struct syncobj_wait_entry *wait = |
661 | container_of(cb, struct syncobj_wait_entry, syncobj_cb); | 873 | container_of(cb, struct syncobj_wait_entry, syncobj_cb); |
662 | 874 | ||
663 | /* This happens inside the syncobj lock */ | 875 | drm_syncobj_search_fence(syncobj, 0, 0, &wait->fence); |
664 | wait->fence = dma_fence_get(rcu_dereference_protected(syncobj->fence, | 876 | |
665 | lockdep_is_held(&syncobj->lock))); | ||
666 | wake_up_process(wait->task); | 877 | wake_up_process(wait->task); |
667 | } | 878 | } |
668 | 879 | ||
@@ -688,7 +899,8 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs, | |||
688 | signaled_count = 0; | 899 | signaled_count = 0; |
689 | for (i = 0; i < count; ++i) { | 900 | for (i = 0; i < count; ++i) { |
690 | entries[i].task = current; | 901 | entries[i].task = current; |
691 | entries[i].fence = drm_syncobj_fence_get(syncobjs[i]); | 902 | drm_syncobj_search_fence(syncobjs[i], 0, 0, |
903 | &entries[i].fence); | ||
692 | if (!entries[i].fence) { | 904 | if (!entries[i].fence) { |
693 | if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) { | 905 | if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) { |
694 | continue; | 906 | continue; |
@@ -953,12 +1165,13 @@ drm_syncobj_reset_ioctl(struct drm_device *dev, void *data, | |||
953 | if (ret < 0) | 1165 | if (ret < 0) |
954 | return ret; | 1166 | return ret; |
955 | 1167 | ||
956 | for (i = 0; i < args->count_handles; i++) | 1168 | for (i = 0; i < args->count_handles; i++) { |
957 | drm_syncobj_replace_fence(syncobjs[i], 0, NULL); | 1169 | drm_syncobj_fini(syncobjs[i]); |
958 | 1170 | drm_syncobj_init(syncobjs[i]); | |
1171 | } | ||
959 | drm_syncobj_array_free(syncobjs, args->count_handles); | 1172 | drm_syncobj_array_free(syncobjs, args->count_handles); |
960 | 1173 | ||
961 | return 0; | 1174 | return ret; |
962 | } | 1175 | } |
963 | 1176 | ||
964 | int | 1177 | int |