1
2
3
4
5
6
7
8
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
17#include <linux/file.h>
18#include <linux/seq_file.h>
19#include <linux/module.h>
20
21struct mali_sync_pt {
22 struct sync_pt sync_pt;
23 struct mali_sync_flag *flag;
24 struct sync_timeline *sync_tl;
25};
26
27
28
29
30
31struct mali_sync_flag {
32 struct sync_timeline *sync_tl;
33 u32 point;
34 int status;
35 struct kref refcount;
36};
37
38
39
40
41
42struct mali_sync_timeline_container {
43 struct sync_timeline sync_timeline;
44 struct mali_timeline *timeline;
45};
46
47MALI_STATIC_INLINE struct mali_sync_pt *to_mali_sync_pt(struct sync_pt *pt)
48{
49 return container_of(pt, struct mali_sync_pt, sync_pt);
50}
51
52MALI_STATIC_INLINE struct mali_sync_timeline_container *to_mali_sync_tl_container(struct sync_timeline *sync_tl)
53{
54 return container_of(sync_tl, struct mali_sync_timeline_container, sync_timeline);
55}
56
57static struct sync_pt *timeline_dup(struct sync_pt *pt)
58{
59 struct mali_sync_pt *mpt, *new_mpt;
60 struct sync_pt *new_pt;
61
62 MALI_DEBUG_ASSERT_POINTER(pt);
63 mpt = to_mali_sync_pt(pt);
64
65 new_pt = sync_pt_create(mpt->sync_tl, sizeof(struct mali_sync_pt));
66 if (NULL == new_pt) return NULL;
67
68 new_mpt = to_mali_sync_pt(new_pt);
69
70 mali_sync_flag_get(mpt->flag);
71 new_mpt->flag = mpt->flag;
72 new_mpt->sync_tl = mpt->sync_tl;
73
74 return new_pt;
75}
76
77static int timeline_has_signaled(struct sync_pt *pt)
78{
79 struct mali_sync_pt *mpt;
80
81 MALI_DEBUG_ASSERT_POINTER(pt);
82 mpt = to_mali_sync_pt(pt);
83
84 MALI_DEBUG_ASSERT_POINTER(mpt->flag);
85
86 return mpt->flag->status;
87}
88
89static int timeline_compare(struct sync_pt *pta, struct sync_pt *ptb)
90{
91 struct mali_sync_pt *mpta;
92 struct mali_sync_pt *mptb;
93 u32 a, b;
94
95 MALI_DEBUG_ASSERT_POINTER(pta);
96 MALI_DEBUG_ASSERT_POINTER(ptb);
97 mpta = to_mali_sync_pt(pta);
98 mptb = to_mali_sync_pt(ptb);
99
100 MALI_DEBUG_ASSERT_POINTER(mpta->flag);
101 MALI_DEBUG_ASSERT_POINTER(mptb->flag);
102
103 a = mpta->flag->point;
104 b = mptb->flag->point;
105
106 if (a == b) return 0;
107
108 return ((b - a) < (a - b) ? -1 : 1);
109}
110
111static void timeline_free_pt(struct sync_pt *pt)
112{
113 struct mali_sync_pt *mpt;
114
115 MALI_DEBUG_ASSERT_POINTER(pt);
116 mpt = to_mali_sync_pt(pt);
117
118 mali_sync_flag_put(mpt->flag);
119}
120
121static void timeline_release(struct sync_timeline *sync_timeline)
122{
123 module_put(THIS_MODULE);
124}
125
126#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
127static void timeline_print_pt(struct seq_file *s, struct sync_pt *sync_pt)
128{
129 struct mali_sync_pt *mpt;
130
131 MALI_DEBUG_ASSERT_POINTER(s);
132 MALI_DEBUG_ASSERT_POINTER(sync_pt);
133
134 mpt = to_mali_sync_pt(sync_pt);
135
136
137
138
139 if (mpt->flag) {
140 seq_printf(s, "%u", mpt->flag->point);
141 } else {
142 seq_printf(s, "uninitialized");
143 }
144}
145
146#else
147static void timeline_pt_value_str(struct sync_pt *pt, char *str, int size)
148{
149 struct mali_sync_pt *mpt;
150
151 MALI_DEBUG_ASSERT_POINTER(str);
152 MALI_DEBUG_ASSERT_POINTER(pt);
153
154 mpt = to_mali_sync_pt(pt);
155
156
157
158
159 if (mpt->flag) {
160 _mali_osk_snprintf(str, size, "%u", mpt->flag->point);
161 } else {
162 _mali_osk_snprintf(str, size, "uninitialized");
163 }
164}
165
166static void timeline_value_str(struct sync_timeline *timeline, char *str, int size)
167{
168 struct mali_sync_timeline_container *mali_sync_tl;
169
170 MALI_DEBUG_ASSERT_POINTER(timeline);
171 MALI_DEBUG_ASSERT_POINTER(str);
172
173 mali_sync_tl = to_mali_sync_tl_container(timeline);
174
175 MALI_DEBUG_ASSERT_POINTER(mali_sync_tl);
176
177 if (NULL != mali_sync_tl->timeline) {
178 _mali_osk_snprintf(str, size, "oldest (%u) next (%u)\n", mali_sync_tl->timeline->point_oldest,
179 mali_sync_tl->timeline->point_next);
180 }
181}
182#endif
183
184static struct sync_timeline_ops mali_timeline_ops = {
185 .driver_name = "Mali",
186 .dup = timeline_dup,
187 .has_signaled = timeline_has_signaled,
188 .compare = timeline_compare,
189 .free_pt = timeline_free_pt,
190 .release_obj = timeline_release,
191#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
192 .print_pt = timeline_print_pt,
193#else
194 .pt_value_str = timeline_pt_value_str,
195 .timeline_value_str = timeline_value_str,
196#endif
197};
198
199struct sync_timeline *mali_sync_timeline_create(struct mali_timeline *timeline, const char *name)
200{
201 struct sync_timeline *sync_tl;
202 struct mali_sync_timeline_container *mali_sync_tl;
203
204 sync_tl = sync_timeline_create(&mali_timeline_ops, sizeof(struct mali_sync_timeline_container), name);
205 if (NULL == sync_tl) return NULL;
206
207 mali_sync_tl = to_mali_sync_tl_container(sync_tl);
208 mali_sync_tl->timeline = timeline;
209
210
211
212
213
214
215 __module_get(THIS_MODULE);
216
217 return sync_tl;
218}
219
220mali_bool mali_sync_timeline_is_ours(struct sync_timeline *sync_tl)
221{
222 MALI_DEBUG_ASSERT_POINTER(sync_tl);
223 return (sync_tl->ops == &mali_timeline_ops) ? MALI_TRUE : MALI_FALSE;
224}
225
226s32 mali_sync_fence_fd_alloc(struct sync_fence *sync_fence)
227{
228 s32 fd = -1;
229
230 fd = get_unused_fd();
231 if (fd < 0) {
232 sync_fence_put(sync_fence);
233 return -1;
234 }
235 sync_fence_install(sync_fence, fd);
236
237 return fd;
238}
239
240struct sync_fence *mali_sync_fence_merge(struct sync_fence *sync_fence1, struct sync_fence *sync_fence2)
241{
242 struct sync_fence *sync_fence;
243
244 MALI_DEBUG_ASSERT_POINTER(sync_fence1);
245 MALI_DEBUG_ASSERT_POINTER(sync_fence1);
246
247 sync_fence = sync_fence_merge("mali_merge_fence", sync_fence1, sync_fence2);
248 sync_fence_put(sync_fence1);
249 sync_fence_put(sync_fence2);
250
251 return sync_fence;
252}
253
254struct sync_fence *mali_sync_timeline_create_signaled_fence(struct sync_timeline *sync_tl)
255{
256 struct mali_sync_flag *flag;
257 struct sync_fence *sync_fence;
258
259 MALI_DEBUG_ASSERT_POINTER(sync_tl);
260
261 flag = mali_sync_flag_create(sync_tl, 0);
262 if (NULL == flag) return NULL;
263
264 sync_fence = mali_sync_flag_create_fence(flag);
265
266 mali_sync_flag_signal(flag, 0);
267 mali_sync_flag_put(flag);
268
269 return sync_fence;
270}
271
272struct mali_sync_flag *mali_sync_flag_create(struct sync_timeline *sync_tl, mali_timeline_point point)
273{
274 struct mali_sync_flag *flag;
275
276 if (NULL == sync_tl) return NULL;
277
278 flag = _mali_osk_calloc(1, sizeof(*flag));
279 if (NULL == flag) return NULL;
280
281 flag->sync_tl = sync_tl;
282 flag->point = point;
283
284 flag->status = 0;
285 kref_init(&flag->refcount);
286
287 return flag;
288}
289
290void mali_sync_flag_get(struct mali_sync_flag *flag)
291{
292 MALI_DEBUG_ASSERT_POINTER(flag);
293 kref_get(&flag->refcount);
294}
295
296
297
298
299
300
301static void mali_sync_flag_free(struct kref *ref)
302{
303 struct mali_sync_flag *flag;
304
305 MALI_DEBUG_ASSERT_POINTER(ref);
306 flag = container_of(ref, struct mali_sync_flag, refcount);
307
308 _mali_osk_free(flag);
309}
310
311void mali_sync_flag_put(struct mali_sync_flag *flag)
312{
313 MALI_DEBUG_ASSERT_POINTER(flag);
314 kref_put(&flag->refcount, mali_sync_flag_free);
315}
316
317void mali_sync_flag_signal(struct mali_sync_flag *flag, int error)
318{
319 MALI_DEBUG_ASSERT_POINTER(flag);
320
321 MALI_DEBUG_ASSERT(0 == flag->status);
322 flag->status = (0 > error) ? error : 1;
323
324 _mali_osk_write_mem_barrier();
325
326 sync_timeline_signal(flag->sync_tl);
327}
328
329
330
331
332
333
334
335
336
337static struct sync_pt *mali_sync_flag_create_pt(struct mali_sync_flag *flag)
338{
339 struct sync_pt *pt;
340 struct mali_sync_pt *mpt;
341
342 MALI_DEBUG_ASSERT_POINTER(flag);
343 MALI_DEBUG_ASSERT_POINTER(flag->sync_tl);
344
345 pt = sync_pt_create(flag->sync_tl, sizeof(struct mali_sync_pt));
346 if (NULL == pt) return NULL;
347
348 mali_sync_flag_get(flag);
349
350 mpt = to_mali_sync_pt(pt);
351 mpt->flag = flag;
352 mpt->sync_tl = flag->sync_tl;
353
354 return pt;
355}
356
357struct sync_fence *mali_sync_flag_create_fence(struct mali_sync_flag *flag)
358{
359 struct sync_pt *sync_pt;
360 struct sync_fence *sync_fence;
361
362 MALI_DEBUG_ASSERT_POINTER(flag);
363 MALI_DEBUG_ASSERT_POINTER(flag->sync_tl);
364
365 sync_pt = mali_sync_flag_create_pt(flag);
366 if (NULL == sync_pt) return NULL;
367
368 sync_fence = sync_fence_create("mali_flag_fence", sync_pt);
369 if (NULL == sync_fence) {
370 sync_pt_free(sync_pt);
371 return NULL;
372 }
373
374 return sync_fence;
375}
376