xref: /OK3568_Linux_fs/kernel/drivers/gpu/arm/mali400/mali/common/mali_timeline_sync_fence.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright (C) 2013, 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 #include <linux/file.h>
11 #include "mali_timeline_sync_fence.h"
12 
13 #include "mali_osk.h"
14 #include "mali_kernel_common.h"
15 #include "mali_sync.h"
16 
17 #if defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE)
18 /**
19  * Creates a sync fence tracker and a sync fence.  Adds sync fence tracker to Timeline system and
20  * returns sync fence.  The sync fence will be signaled when the sync fence tracker is activated.
21  *
22  * @param timeline Timeline.
23  * @param point Point on timeline.
24  * @return Sync fence that will be signaled when tracker is activated.
25  */
26 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
mali_timeline_sync_fence_create_and_add_tracker(struct mali_timeline * timeline,mali_timeline_point point)27 static struct sync_fence *mali_timeline_sync_fence_create_and_add_tracker(struct mali_timeline *timeline, mali_timeline_point point)
28 #else
29 static struct mali_internal_sync_fence *mali_timeline_sync_fence_create_and_add_tracker(struct mali_timeline *timeline, mali_timeline_point point)
30 #endif
31 {
32 	struct mali_timeline_sync_fence_tracker *sync_fence_tracker;
33 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
34 	struct sync_fence                       *sync_fence;
35 #else
36 	struct mali_internal_sync_fence                       *sync_fence;
37 #endif
38 	struct mali_timeline_fence               fence;
39 
40 	MALI_DEBUG_ASSERT_POINTER(timeline);
41 	MALI_DEBUG_ASSERT(MALI_TIMELINE_NO_POINT != point);
42 
43 	/* Allocate sync fence tracker. */
44 	sync_fence_tracker = _mali_osk_calloc(1, sizeof(struct mali_timeline_sync_fence_tracker));
45 	if (NULL == sync_fence_tracker) {
46 		MALI_PRINT_ERROR(("Mali Timeline: sync_fence_tracker allocation failed\n"));
47 		return NULL;
48 	}
49 
50 	/* Create sync flag. */
51 	MALI_DEBUG_ASSERT_POINTER(timeline->sync_tl);
52 	sync_fence_tracker->flag = mali_sync_flag_create(timeline->sync_tl, point);
53 	if (NULL == sync_fence_tracker->flag) {
54 		MALI_PRINT_ERROR(("Mali Timeline: sync_flag creation failed\n"));
55 		_mali_osk_free(sync_fence_tracker);
56 		return NULL;
57 	}
58 
59 	/* Create sync fence from sync flag. */
60 	sync_fence = mali_sync_flag_create_fence(sync_fence_tracker->flag);
61 	if (NULL == sync_fence) {
62 		MALI_PRINT_ERROR(("Mali Timeline: sync_fence creation failed\n"));
63 		mali_sync_flag_put(sync_fence_tracker->flag);
64 		_mali_osk_free(sync_fence_tracker);
65 		return NULL;
66 	}
67 
68 	/* Setup fence for tracker. */
69 	_mali_osk_memset(&fence, 0, sizeof(struct mali_timeline_fence));
70 	fence.sync_fd = -1;
71 	fence.points[timeline->id] = point;
72 
73 	/* Finally, add the tracker to Timeline system. */
74 	mali_timeline_tracker_init(&sync_fence_tracker->tracker, MALI_TIMELINE_TRACKER_SYNC, &fence, sync_fence_tracker);
75 	point = mali_timeline_system_add_tracker(timeline->system, &sync_fence_tracker->tracker, MALI_TIMELINE_NONE);
76 	MALI_DEBUG_ASSERT(MALI_TIMELINE_NO_POINT == point);
77 
78 	return sync_fence;
79 }
80 
mali_timeline_sync_fence_create(struct mali_timeline_system * system,struct mali_timeline_fence * fence)81 s32 mali_timeline_sync_fence_create(struct mali_timeline_system *system, struct mali_timeline_fence *fence)
82 {
83 	u32 i;
84 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
85 	struct sync_fence *sync_fence_acc = NULL;
86 #else
87 	struct mali_internal_sync_fence *sync_fence_acc = NULL;
88 #endif
89 	MALI_DEBUG_ASSERT_POINTER(system);
90 	MALI_DEBUG_ASSERT_POINTER(fence);
91 
92 	for (i = 0; i < MALI_TIMELINE_MAX; ++i) {
93 		struct mali_timeline *timeline;
94 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
95 		struct sync_fence *sync_fence;
96 #else
97 		struct mali_internal_sync_fence *sync_fence;
98 #endif
99 		if (MALI_TIMELINE_NO_POINT == fence->points[i]) continue;
100 
101 		timeline = system->timelines[i];
102 		MALI_DEBUG_ASSERT_POINTER(timeline);
103 
104 		sync_fence = mali_timeline_sync_fence_create_and_add_tracker(timeline, fence->points[i]);
105 		if (NULL == sync_fence) goto error;
106 
107 		if (NULL != sync_fence_acc) {
108 			/* Merge sync fences. */
109 			sync_fence_acc = mali_sync_fence_merge(sync_fence_acc, sync_fence);
110 			if (NULL == sync_fence_acc) goto error;
111 		} else {
112 			/* This was the first sync fence created. */
113 			sync_fence_acc = sync_fence;
114 		}
115 	}
116 
117 	if (-1 != fence->sync_fd) {
118 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
119 		struct sync_fence *sync_fence;
120 		sync_fence = sync_fence_fdget(fence->sync_fd);
121 #else
122 		struct mali_internal_sync_fence *sync_fence;
123 		sync_fence = mali_internal_sync_fence_fdget(fence->sync_fd);
124 #endif
125 
126 		if (NULL == sync_fence) goto error;
127 
128 		if (NULL != sync_fence_acc) {
129 			sync_fence_acc = mali_sync_fence_merge(sync_fence_acc, sync_fence);
130 			if (NULL == sync_fence_acc) goto error;
131 		} else {
132 			sync_fence_acc = sync_fence;
133 		}
134 	}
135 
136 	if (NULL == sync_fence_acc) {
137 		MALI_DEBUG_ASSERT_POINTER(system->signaled_sync_tl);
138 
139 		/* There was nothing to wait on, so return an already signaled fence. */
140 
141 		sync_fence_acc = mali_sync_timeline_create_signaled_fence(system->signaled_sync_tl);
142 		if (NULL == sync_fence_acc) goto error;
143 	}
144 
145 	/* Return file descriptor for the accumulated sync fence. */
146 	return mali_sync_fence_fd_alloc(sync_fence_acc);
147 
148 error:
149 	if (NULL != sync_fence_acc) {
150 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)
151 		sync_fence_put(sync_fence_acc);
152 #else
153 		fput(sync_fence_acc->file);
154 #endif
155 	}
156 
157 	return -1;
158 }
159 
mali_timeline_sync_fence_activate(struct mali_timeline_sync_fence_tracker * sync_fence_tracker)160 void mali_timeline_sync_fence_activate(struct mali_timeline_sync_fence_tracker *sync_fence_tracker)
161 {
162 	mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;
163 
164 	MALI_DEBUG_ASSERT_POINTER(sync_fence_tracker);
165 	MALI_DEBUG_ASSERT_POINTER(sync_fence_tracker->flag);
166 
167 	MALI_DEBUG_PRINT(4, ("Mali Timeline: activation for sync fence tracker\n"));
168 
169 	/* Signal flag and release reference. */
170 	mali_sync_flag_signal(sync_fence_tracker->flag, 0);
171 	mali_sync_flag_put(sync_fence_tracker->flag);
172 
173 	/* Nothing can wait on this tracker, so nothing to schedule after release. */
174 	schedule_mask = mali_timeline_tracker_release(&sync_fence_tracker->tracker);
175 	MALI_DEBUG_ASSERT(MALI_SCHEDULER_MASK_EMPTY == schedule_mask);
176 
177 	_mali_osk_free(sync_fence_tracker);
178 }
179 #endif /* defined(CONFIG_SYNC) || defined(CONFIG_SYNC_FILE) */
180