1 /*
2 * Copyright (C) 2012-2017 ARM Limited. All rights reserved.
3 *
4 * This program is free software and is provided to you under the terms of the GNU General Public License version 2
5 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
6 *
7 * A copy of the licence is included with the program, and can also be obtained from Free Software
8 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
9 */
10
11 #include "mali_sync.h"
12
13 #include "mali_osk.h"
14 #include "mali_kernel_common.h"
15 #include "mali_timeline.h"
16 #include "mali_executor.h"
17
18 #include <linux/file.h>
19 #include <linux/seq_file.h>
20 #include <linux/module.h>
21
22 struct mali_sync_pt {
23 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
24 struct sync_pt sync_pt;
25 #else
26 struct mali_internal_sync_point sync_pt;
27 #endif
28 struct mali_sync_flag *flag;
29 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
30 struct sync_timeline *sync_tl; /**< Sync timeline this pt is connected to. */
31 #else
32 struct mali_internal_sync_timeline *sync_tl; /**< Sync timeline this pt is connected to. */
33 #endif
34 };
35
36 /**
37 * The sync flag is used to connect sync fences to the Mali Timeline system. Sync fences can be
38 * created from a sync flag, and when the flag is signaled, the sync fences will also be signaled.
39 */
40 struct mali_sync_flag {
41 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
42 struct sync_timeline *sync_tl; /**< Sync timeline this flag is connected to. */
43 #else
44 struct mali_internal_sync_timeline *sync_tl; /**< Sync timeline this flag is connected to. */
45 #endif
46 u32 point; /**< Point on timeline. */
47 int status; /**< 0 if unsignaled, 1 if signaled without error or negative if signaled with error. */
48 struct kref refcount; /**< Reference count. */
49 };
50
51 /**
52 * Mali sync timeline is used to connect mali timeline to sync_timeline.
53 * When fence timeout can print more detailed mali timeline system info.
54 */
55 struct mali_sync_timeline_container {
56 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
57 struct sync_timeline sync_timeline;
58 #else
59 struct mali_internal_sync_timeline sync_timeline;
60 #endif
61 struct mali_timeline *timeline;
62 };
63
64 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
to_mali_sync_pt(struct sync_pt * pt)65 MALI_STATIC_INLINE struct mali_sync_pt *to_mali_sync_pt(struct sync_pt *pt)
66 #else
67 MALI_STATIC_INLINE struct mali_sync_pt *to_mali_sync_pt(struct mali_internal_sync_point *pt)
68 #endif
69 {
70 return container_of(pt, struct mali_sync_pt, sync_pt);
71 }
72
73 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
to_mali_sync_tl_container(struct sync_timeline * sync_tl)74 MALI_STATIC_INLINE struct mali_sync_timeline_container *to_mali_sync_tl_container(struct sync_timeline *sync_tl)
75 #else
76 MALI_STATIC_INLINE struct mali_sync_timeline_container *to_mali_sync_tl_container(struct mali_internal_sync_timeline *sync_tl)
77 #endif
78 {
79 return container_of(sync_tl, struct mali_sync_timeline_container, sync_timeline);
80 }
81
82 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
timeline_has_signaled(struct sync_pt * pt)83 static int timeline_has_signaled(struct sync_pt *pt)
84 #else
85 static int timeline_has_signaled(struct mali_internal_sync_point *pt)
86 #endif
87 {
88 struct mali_sync_pt *mpt;
89
90 MALI_DEBUG_ASSERT_POINTER(pt);
91 mpt = to_mali_sync_pt(pt);
92
93 MALI_DEBUG_ASSERT_POINTER(mpt->flag);
94
95 return mpt->flag->status;
96 }
97
98 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
timeline_free_pt(struct sync_pt * pt)99 static void timeline_free_pt(struct sync_pt *pt)
100 #else
101 static void timeline_free_pt(struct mali_internal_sync_point *pt)
102 #endif
103 {
104 struct mali_sync_pt *mpt;
105
106 MALI_DEBUG_ASSERT_POINTER(pt);
107 mpt = to_mali_sync_pt(pt);
108
109 mali_sync_flag_put(mpt->flag);
110 }
111
112 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
timeline_release(struct sync_timeline * sync_timeline)113 static void timeline_release(struct sync_timeline *sync_timeline)
114 #else
115 static void timeline_release(struct mali_internal_sync_timeline *sync_timeline)
116 #endif
117 {
118 struct mali_sync_timeline_container *mali_sync_tl = NULL;
119 struct mali_timeline *mali_tl = NULL;
120
121 MALI_DEBUG_ASSERT_POINTER(sync_timeline);
122
123 mali_sync_tl = to_mali_sync_tl_container(sync_timeline);
124 MALI_DEBUG_ASSERT_POINTER(mali_sync_tl);
125
126 mali_tl = mali_sync_tl->timeline;
127
128 /* always signaled timeline didn't have mali container */
129 if (mali_tl) {
130 if (NULL != mali_tl->spinlock) {
131 mali_spinlock_reentrant_term(mali_tl->spinlock);
132 }
133 _mali_osk_free(mali_tl);
134 }
135
136 module_put(THIS_MODULE);
137 }
138
139 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
timeline_dup(struct sync_pt * pt)140 static struct sync_pt *timeline_dup(struct sync_pt *pt)
141 {
142 struct mali_sync_pt *mpt, *new_mpt;
143 struct sync_pt *new_pt;
144 MALI_DEBUG_ASSERT_POINTER(pt);
145
146 mpt = to_mali_sync_pt(pt);
147
148 new_pt = sync_pt_create(mpt->sync_tl, sizeof(struct mali_sync_pt));
149 if (NULL == new_pt) return NULL;
150
151 new_mpt = to_mali_sync_pt(new_pt);
152
153 mali_sync_flag_get(mpt->flag);
154 new_mpt->flag = mpt->flag;
155 new_mpt->sync_tl = mpt->sync_tl;
156
157 return new_pt;
158 }
159
timeline_compare(struct sync_pt * pta,struct sync_pt * ptb)160 static int timeline_compare(struct sync_pt *pta, struct sync_pt *ptb)
161 {
162 struct mali_sync_pt *mpta;
163 struct mali_sync_pt *mptb;
164 u32 a, b;
165
166 MALI_DEBUG_ASSERT_POINTER(pta);
167 MALI_DEBUG_ASSERT_POINTER(ptb);
168 mpta = to_mali_sync_pt(pta);
169 mptb = to_mali_sync_pt(ptb);
170
171 MALI_DEBUG_ASSERT_POINTER(mpta->flag);
172 MALI_DEBUG_ASSERT_POINTER(mptb->flag);
173
174 a = mpta->flag->point;
175 b = mptb->flag->point;
176
177 if (a == b) return 0;
178
179 return ((b - a) < (a - b) ? -1 : 1);
180 }
181 #endif
182
183 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
timeline_print_pt(struct seq_file * s,struct sync_pt * sync_pt)184 static void timeline_print_pt(struct seq_file *s, struct sync_pt *sync_pt)
185 {
186 struct mali_sync_pt *mpt;
187
188 MALI_DEBUG_ASSERT_POINTER(s);
189 MALI_DEBUG_ASSERT_POINTER(sync_pt);
190
191 mpt = to_mali_sync_pt(sync_pt);
192
193 /* It is possible this sync point is just under construct,
194 * make sure the flag is valid before accessing it
195 */
196 if (mpt->flag) {
197 seq_printf(s, "%u", mpt->flag->point);
198 } else {
199 seq_printf(s, "uninitialized");
200 }
201 }
202
timeline_print_obj(struct seq_file * s,struct sync_timeline * sync_tl)203 static void timeline_print_obj(struct seq_file *s, struct sync_timeline *sync_tl)
204 {
205 struct mali_sync_timeline_container *mali_sync_tl = NULL;
206 struct mali_timeline *mali_tl = NULL;
207
208 MALI_DEBUG_ASSERT_POINTER(sync_tl);
209
210 mali_sync_tl = to_mali_sync_tl_container(sync_tl);
211 MALI_DEBUG_ASSERT_POINTER(mali_sync_tl);
212
213 mali_tl = mali_sync_tl->timeline;
214
215 if (NULL != mali_tl) {
216 seq_printf(s, "oldest (%u) ", mali_tl->point_oldest);
217 seq_printf(s, "next (%u)", mali_tl->point_next);
218 seq_printf(s, "\n");
219
220 #if defined(MALI_TIMELINE_DEBUG_FUNCTIONS)
221 {
222 u32 tid = _mali_osk_get_tid();
223 struct mali_timeline_system *system = mali_tl->system;
224
225 mali_spinlock_reentrant_wait(mali_tl->spinlock, tid);
226 if (!mali_tl->destroyed) {
227 mali_spinlock_reentrant_wait(system->spinlock, tid);
228 mali_timeline_debug_print_timeline(mali_tl, s);
229 mali_spinlock_reentrant_signal(system->spinlock, tid);
230 }
231 mali_spinlock_reentrant_signal(mali_tl->spinlock, tid);
232
233 /* dump job queue status and group running status */
234 mali_executor_status_dump();
235 }
236 #endif
237 }
238 }
239 #elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
timeline_pt_value_str(struct sync_pt * pt,char * str,int size)240 static void timeline_pt_value_str(struct sync_pt *pt, char *str, int size)
241 {
242 struct mali_sync_pt *mpt;
243
244 MALI_DEBUG_ASSERT_POINTER(str);
245 MALI_DEBUG_ASSERT_POINTER(pt);
246
247 mpt = to_mali_sync_pt(pt);
248
249 /* It is possible this sync point is just under construct,
250 * make sure the flag is valid before accessing it
251 */
252 if (mpt->flag) {
253 _mali_osk_snprintf(str, size, "%u", mpt->flag->point);
254 } else {
255 _mali_osk_snprintf(str, size, "uninitialized");
256 }
257 }
258
timeline_value_str(struct sync_timeline * timeline,char * str,int size)259 static void timeline_value_str(struct sync_timeline *timeline, char *str, int size)
260 {
261 struct mali_sync_timeline_container *mali_sync_tl = NULL;
262 struct mali_timeline *mali_tl = NULL;
263
264 MALI_DEBUG_ASSERT_POINTER(timeline);
265
266 mali_sync_tl = to_mali_sync_tl_container(timeline);
267 MALI_DEBUG_ASSERT_POINTER(mali_sync_tl);
268
269 mali_tl = mali_sync_tl->timeline;
270
271 if (NULL != mali_tl) {
272 _mali_osk_snprintf(str, size, "oldest (%u) ", mali_tl->point_oldest);
273 _mali_osk_snprintf(str, size, "next (%u)", mali_tl->point_next);
274 _mali_osk_snprintf(str, size, "\n");
275
276 #if defined(MALI_TIMELINE_DEBUG_FUNCTIONS)
277 {
278 u32 tid = _mali_osk_get_tid();
279 struct mali_timeline_system *system = mali_tl->system;
280
281 mali_spinlock_reentrant_wait(mali_tl->spinlock, tid);
282 if (!mali_tl->destroyed) {
283 mali_spinlock_reentrant_wait(system->spinlock, tid);
284 mali_timeline_debug_direct_print_timeline(mali_tl);
285 mali_spinlock_reentrant_signal(system->spinlock, tid);
286 }
287 mali_spinlock_reentrant_signal(mali_tl->spinlock, tid);
288
289 /* dump job queue status and group running status */
290 mali_executor_status_dump();
291 }
292 #endif
293 }
294 }
295 #else
timeline_print_sync_pt(struct mali_internal_sync_point * sync_pt)296 static void timeline_print_sync_pt(struct mali_internal_sync_point *sync_pt)
297 {
298 struct mali_sync_pt *mpt;
299
300 MALI_DEBUG_ASSERT_POINTER(sync_pt);
301
302 mpt = to_mali_sync_pt(sync_pt);
303
304 if (mpt->flag) {
305 MALI_DEBUG_PRINT(2, ("mali_internal_sync_pt: %u\n", mpt->flag->point));
306 } else {
307 MALI_DEBUG_PRINT(2, ("uninitialized\n", mpt->flag->point));
308 }
309 }
310 #endif
311
312 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
313 static struct sync_timeline_ops mali_timeline_ops = {
314 .driver_name = "Mali",
315 .dup = timeline_dup,
316 .has_signaled = timeline_has_signaled,
317 .compare = timeline_compare,
318 .free_pt = timeline_free_pt,
319 .release_obj = timeline_release,
320 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
321 .print_pt = timeline_print_pt,
322 .print_obj = timeline_print_obj,
323 #else
324 .pt_value_str = timeline_pt_value_str,
325 .timeline_value_str = timeline_value_str,
326 #endif
327 };
328
mali_sync_timeline_create(struct mali_timeline * timeline,const char * name)329 struct sync_timeline *mali_sync_timeline_create(struct mali_timeline *timeline, const char *name)
330 {
331 struct sync_timeline *sync_tl;
332 struct mali_sync_timeline_container *mali_sync_tl;
333
334 sync_tl = sync_timeline_create(&mali_timeline_ops, sizeof(struct mali_sync_timeline_container), name);
335 if (NULL == sync_tl) return NULL;
336
337 mali_sync_tl = to_mali_sync_tl_container(sync_tl);
338 mali_sync_tl->timeline = timeline;
339
340 /* Grab a reference on the module to ensure the callbacks are present
341 * as long some timeline exists. The reference is released when the
342 * timeline is freed.
343 * Since this function is called from a ioctl on an open file we know
344 * we already have a reference, so using __module_get is safe. */
345 __module_get(THIS_MODULE);
346
347 return sync_tl;
348 }
349
mali_sync_fence_fd_alloc(struct sync_fence * sync_fence)350 s32 mali_sync_fence_fd_alloc(struct sync_fence *sync_fence)
351 {
352 s32 fd = -1;
353
354 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)
355 fd = get_unused_fd();
356 #else
357 fd = get_unused_fd_flags(0);
358 #endif
359
360 if (fd < 0) {
361 sync_fence_put(sync_fence);
362 return -1;
363 }
364 sync_fence_install(sync_fence, fd);
365
366 return fd;
367 }
368
mali_sync_fence_merge(struct sync_fence * sync_fence1,struct sync_fence * sync_fence2)369 struct sync_fence *mali_sync_fence_merge(struct sync_fence *sync_fence1, struct sync_fence *sync_fence2)
370 {
371 struct sync_fence *sync_fence;
372
373 MALI_DEBUG_ASSERT_POINTER(sync_fence1);
374 MALI_DEBUG_ASSERT_POINTER(sync_fence1);
375
376 sync_fence = sync_fence_merge("mali_merge_fence", sync_fence1, sync_fence2);
377 sync_fence_put(sync_fence1);
378 sync_fence_put(sync_fence2);
379
380 return sync_fence;
381 }
382
mali_sync_timeline_create_signaled_fence(struct sync_timeline * sync_tl)383 struct sync_fence *mali_sync_timeline_create_signaled_fence(struct sync_timeline *sync_tl)
384 {
385 struct mali_sync_flag *flag;
386 struct sync_fence *sync_fence;
387
388 MALI_DEBUG_ASSERT_POINTER(sync_tl);
389
390 flag = mali_sync_flag_create(sync_tl, 0);
391 if (NULL == flag) return NULL;
392
393 sync_fence = mali_sync_flag_create_fence(flag);
394
395 mali_sync_flag_signal(flag, 0);
396 mali_sync_flag_put(flag);
397
398 return sync_fence;
399 }
400
mali_sync_flag_create(struct sync_timeline * sync_tl,mali_timeline_point point)401 struct mali_sync_flag *mali_sync_flag_create(struct sync_timeline *sync_tl, mali_timeline_point point)
402 {
403 struct mali_sync_flag *flag;
404
405 if (NULL == sync_tl) return NULL;
406
407 flag = _mali_osk_calloc(1, sizeof(*flag));
408 if (NULL == flag) return NULL;
409
410 flag->sync_tl = sync_tl;
411 flag->point = point;
412
413 flag->status = 0;
414 kref_init(&flag->refcount);
415
416 return flag;
417 }
418
419 /**
420 * Create a sync point attached to given sync flag.
421 *
422 * @note Sync points must be triggered in *exactly* the same order as they are created.
423 *
424 * @param flag Sync flag.
425 * @return New sync point if successful, NULL if not.
426 */
mali_sync_flag_create_pt(struct mali_sync_flag * flag)427 static struct sync_pt *mali_sync_flag_create_pt(struct mali_sync_flag *flag)
428 {
429 struct sync_pt *pt;
430 struct mali_sync_pt *mpt;
431
432 MALI_DEBUG_ASSERT_POINTER(flag);
433 MALI_DEBUG_ASSERT_POINTER(flag->sync_tl);
434
435 pt = sync_pt_create(flag->sync_tl, sizeof(struct mali_sync_pt));
436 if (NULL == pt) return NULL;
437
438 mali_sync_flag_get(flag);
439
440 mpt = to_mali_sync_pt(pt);
441 mpt->flag = flag;
442 mpt->sync_tl = flag->sync_tl;
443
444 return pt;
445 }
446
mali_sync_flag_create_fence(struct mali_sync_flag * flag)447 struct sync_fence *mali_sync_flag_create_fence(struct mali_sync_flag *flag)
448 {
449 struct sync_pt *sync_pt;
450 struct sync_fence *sync_fence;
451
452 MALI_DEBUG_ASSERT_POINTER(flag);
453 MALI_DEBUG_ASSERT_POINTER(flag->sync_tl);
454
455 sync_pt = mali_sync_flag_create_pt(flag);
456 if (NULL == sync_pt) return NULL;
457
458 sync_fence = sync_fence_create("mali_flag_fence", sync_pt);
459 if (NULL == sync_fence) {
460 sync_pt_free(sync_pt);
461 return NULL;
462 }
463
464 return sync_fence;
465 }
466 #else
467 static struct mali_internal_sync_timeline_ops mali_timeline_ops = {
468 .driver_name = "Mali",
469 .has_signaled = timeline_has_signaled,
470 .free_pt = timeline_free_pt,
471 .release_obj = timeline_release,
472 .print_sync_pt = timeline_print_sync_pt,
473 };
474
mali_sync_timeline_create(struct mali_timeline * timeline,const char * name)475 struct mali_internal_sync_timeline *mali_sync_timeline_create(struct mali_timeline *timeline, const char *name)
476 {
477 struct mali_internal_sync_timeline *sync_tl;
478 struct mali_sync_timeline_container *mali_sync_tl;
479
480 sync_tl = mali_internal_sync_timeline_create(&mali_timeline_ops, sizeof(struct mali_sync_timeline_container), name);
481 if (NULL == sync_tl) return NULL;
482
483 mali_sync_tl = to_mali_sync_tl_container(sync_tl);
484 mali_sync_tl->timeline = timeline;
485
486 /* Grab a reference on the module to ensure the callbacks are present
487 * as long some timeline exists. The reference is released when the
488 * timeline is freed.
489 * Since this function is called from a ioctl on an open file we know
490 * we already have a reference, so using __module_get is safe. */
491 __module_get(THIS_MODULE);
492
493 return sync_tl;
494 }
495
mali_sync_fence_fd_alloc(struct mali_internal_sync_fence * sync_fence)496 s32 mali_sync_fence_fd_alloc(struct mali_internal_sync_fence *sync_fence)
497 {
498 s32 fd = -1;
499
500 fd = get_unused_fd_flags(0);
501
502 if (fd < 0) {
503 fput(sync_fence->file);
504 return -1;
505 }
506 fd_install(fd, sync_fence->file);
507 return fd;
508 }
509
mali_sync_fence_merge(struct mali_internal_sync_fence * sync_fence1,struct mali_internal_sync_fence * sync_fence2)510 struct mali_internal_sync_fence *mali_sync_fence_merge(struct mali_internal_sync_fence *sync_fence1, struct mali_internal_sync_fence *sync_fence2)
511 {
512 struct mali_internal_sync_fence *sync_fence;
513
514 MALI_DEBUG_ASSERT_POINTER(sync_fence1);
515 MALI_DEBUG_ASSERT_POINTER(sync_fence1);
516
517 sync_fence = mali_internal_sync_fence_merge(sync_fence1, sync_fence2);
518 fput(sync_fence1->file);
519 fput(sync_fence2->file);
520
521 return sync_fence;
522 }
523
mali_sync_timeline_create_signaled_fence(struct mali_internal_sync_timeline * sync_tl)524 struct mali_internal_sync_fence *mali_sync_timeline_create_signaled_fence(struct mali_internal_sync_timeline *sync_tl)
525 {
526 struct mali_sync_flag *flag;
527 struct mali_internal_sync_fence *sync_fence;
528
529 MALI_DEBUG_ASSERT_POINTER(sync_tl);
530
531 flag = mali_sync_flag_create(sync_tl, 0);
532 if (NULL == flag) return NULL;
533
534 sync_fence = mali_sync_flag_create_fence(flag);
535
536 mali_sync_flag_signal(flag, 0);
537 mali_sync_flag_put(flag);
538
539 return sync_fence;
540 }
541
mali_sync_flag_create(struct mali_internal_sync_timeline * sync_tl,mali_timeline_point point)542 struct mali_sync_flag *mali_sync_flag_create(struct mali_internal_sync_timeline *sync_tl, mali_timeline_point point)
543 {
544 struct mali_sync_flag *flag;
545
546 if (NULL == sync_tl) return NULL;
547
548 flag = _mali_osk_calloc(1, sizeof(*flag));
549 if (NULL == flag) return NULL;
550
551 flag->sync_tl = sync_tl;
552 flag->point = point;
553
554 flag->status = 0;
555 kref_init(&flag->refcount);
556
557 return flag;
558 }
559
560 /**
561 * Create a sync point attached to given sync flag.
562 *
563 * @note Sync points must be triggered in *exactly* the same order as they are created.
564 *
565 * @param flag Sync flag.
566 * @return New sync point if successful, NULL if not.
567 */
mali_sync_flag_create_pt(struct mali_sync_flag * flag)568 static struct mali_internal_sync_point *mali_sync_flag_create_pt(struct mali_sync_flag *flag)
569 {
570 struct mali_internal_sync_point *pt;
571 struct mali_sync_pt *mpt;
572
573 MALI_DEBUG_ASSERT_POINTER(flag);
574 MALI_DEBUG_ASSERT_POINTER(flag->sync_tl);
575
576 pt = mali_internal_sync_point_create(flag->sync_tl, sizeof(struct mali_sync_pt));
577
578 if (pt == NULL) {
579 MALI_PRINT_ERROR(("Mali sync: sync_pt creation failed\n"));
580 return NULL;
581 }
582 mali_sync_flag_get(flag);
583
584 mpt = to_mali_sync_pt(pt);
585 mpt->flag = flag;
586 mpt->sync_tl = flag->sync_tl;
587
588 return pt;
589 }
590
mali_sync_flag_create_fence(struct mali_sync_flag * flag)591 struct mali_internal_sync_fence *mali_sync_flag_create_fence(struct mali_sync_flag *flag)
592 {
593 struct mali_internal_sync_point *sync_pt;
594 struct mali_internal_sync_fence *sync_fence;
595
596 MALI_DEBUG_ASSERT_POINTER(flag);
597 MALI_DEBUG_ASSERT_POINTER(flag->sync_tl);
598
599 sync_pt = mali_sync_flag_create_pt(flag);
600 if (NULL == sync_pt) {
601 MALI_PRINT_ERROR(("Mali sync: sync_pt creation failed\n"));
602 return NULL;
603 }
604 sync_fence = (struct mali_internal_sync_fence *)sync_file_create(&sync_pt->base);
605 if (NULL == sync_fence) {
606 MALI_PRINT_ERROR(("Mali sync: sync_fence creation failed\n"));
607 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
608 dma_fence_put(&sync_pt->base);
609 #else
610 fence_put(&sync_pt->base);
611 #endif
612 return NULL;
613 }
614
615 /* 'sync_pt' no longer needs to hold a refcount of '*sync_pt', to put it off. */
616 dma_fence_put(&sync_pt->base);
617 sync_pt = NULL;
618
619 return sync_fence;
620 }
621 #endif
622
mali_sync_flag_get(struct mali_sync_flag * flag)623 void mali_sync_flag_get(struct mali_sync_flag *flag)
624 {
625 MALI_DEBUG_ASSERT_POINTER(flag);
626 kref_get(&flag->refcount);
627 }
628
629 /**
630 * Free sync flag.
631 *
632 * @param ref kref object embedded in sync flag that should be freed.
633 */
mali_sync_flag_free(struct kref * ref)634 static void mali_sync_flag_free(struct kref *ref)
635 {
636 struct mali_sync_flag *flag;
637
638 MALI_DEBUG_ASSERT_POINTER(ref);
639 flag = container_of(ref, struct mali_sync_flag, refcount);
640
641 _mali_osk_free(flag);
642 }
643
mali_sync_flag_put(struct mali_sync_flag * flag)644 void mali_sync_flag_put(struct mali_sync_flag *flag)
645 {
646 MALI_DEBUG_ASSERT_POINTER(flag);
647 kref_put(&flag->refcount, mali_sync_flag_free);
648 }
649
mali_sync_flag_signal(struct mali_sync_flag * flag,int error)650 void mali_sync_flag_signal(struct mali_sync_flag *flag, int error)
651 {
652 MALI_DEBUG_ASSERT_POINTER(flag);
653
654 MALI_DEBUG_ASSERT(0 == flag->status);
655 flag->status = (0 > error) ? error : 1;
656
657 _mali_osk_write_mem_barrier();
658 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
659 sync_timeline_signal(flag->sync_tl);
660 #else
661 mali_internal_sync_timeline_signal(flag->sync_tl);
662 #endif
663 }
664
665
666