xref: /OK3568_Linux_fs/kernel/drivers/gpu/arm/mali400/mali/linux/mali_sync.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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