2 * Copyright (C) 2013-2014 ARM Limited. All rights reserved.
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.
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.
11 #include "mali_timeline_sync_fence.h"
14 #include "mali_kernel_common.h"
15 #include "mali_sync.h"
17 #if defined(CONFIG_SYNC)
20 * Creates a sync fence tracker and a sync fence. Adds sync fence tracker to Timeline system and
21 * returns sync fence. The sync fence will be signaled when the sync fence tracker is activated.
23 * @param timeline Timeline.
24 * @param point Point on timeline.
25 * @return Sync fence that will be signaled when tracker is activated.
27 static struct sync_fence *mali_timeline_sync_fence_create_and_add_tracker(struct mali_timeline *timeline, mali_timeline_point point)
29 struct mali_timeline_sync_fence_tracker *sync_fence_tracker;
30 struct sync_fence *sync_fence;
31 struct mali_timeline_fence fence;
33 MALI_DEBUG_ASSERT_POINTER(timeline);
34 MALI_DEBUG_ASSERT(MALI_TIMELINE_NO_POINT != point);
36 /* Allocate sync fence tracker. */
37 sync_fence_tracker = _mali_osk_calloc(1, sizeof(struct mali_timeline_sync_fence_tracker));
38 if (NULL == sync_fence_tracker) {
39 MALI_PRINT_ERROR(("Mali Timeline: sync_fence_tracker allocation failed\n"));
43 /* Create sync flag. */
44 MALI_DEBUG_ASSERT_POINTER(timeline->sync_tl);
45 sync_fence_tracker->flag = mali_sync_flag_create(timeline->sync_tl, point);
46 if (NULL == sync_fence_tracker->flag) {
47 MALI_PRINT_ERROR(("Mali Timeline: sync_flag creation failed\n"));
48 _mali_osk_free(sync_fence_tracker);
52 /* Create sync fence from sync flag. */
53 sync_fence = mali_sync_flag_create_fence(sync_fence_tracker->flag);
54 if (NULL == sync_fence) {
55 MALI_PRINT_ERROR(("Mali Timeline: sync_fence creation failed\n"));
56 mali_sync_flag_put(sync_fence_tracker->flag);
57 _mali_osk_free(sync_fence_tracker);
61 /* Setup fence for tracker. */
62 _mali_osk_memset(&fence, 0, sizeof(struct mali_timeline_fence));
64 fence.points[timeline->id] = point;
66 /* Finally, add the tracker to Timeline system. */
67 mali_timeline_tracker_init(&sync_fence_tracker->tracker, MALI_TIMELINE_TRACKER_SYNC, &fence, sync_fence_tracker);
68 point = mali_timeline_system_add_tracker(timeline->system, &sync_fence_tracker->tracker, MALI_TIMELINE_NONE);
69 MALI_DEBUG_ASSERT(MALI_TIMELINE_NO_POINT == point);
74 s32 mali_timeline_sync_fence_create(struct mali_timeline_system *system, struct mali_timeline_fence *fence)
77 struct sync_fence *sync_fence_acc = NULL;
79 MALI_DEBUG_ASSERT_POINTER(system);
80 MALI_DEBUG_ASSERT_POINTER(fence);
82 for (i = 0; i < MALI_TIMELINE_MAX; ++i) {
83 struct mali_timeline *timeline;
84 struct sync_fence *sync_fence;
86 if (MALI_TIMELINE_NO_POINT == fence->points[i]) continue;
88 timeline = system->timelines[i];
89 MALI_DEBUG_ASSERT_POINTER(timeline);
91 sync_fence = mali_timeline_sync_fence_create_and_add_tracker(timeline, fence->points[i]);
92 if (NULL == sync_fence) goto error;
94 if (NULL != sync_fence_acc) {
95 /* Merge sync fences. */
96 sync_fence_acc = mali_sync_fence_merge(sync_fence_acc, sync_fence);
97 if (NULL == sync_fence_acc) goto error;
99 /* This was the first sync fence created. */
100 sync_fence_acc = sync_fence;
104 if (-1 != fence->sync_fd) {
105 struct sync_fence *sync_fence;
107 sync_fence = sync_fence_fdget(fence->sync_fd);
108 if (NULL == sync_fence) goto error;
110 if (NULL != sync_fence_acc) {
111 sync_fence_acc = mali_sync_fence_merge(sync_fence_acc, sync_fence);
112 if (NULL == sync_fence_acc) goto error;
114 sync_fence_acc = sync_fence;
118 if (NULL == sync_fence_acc) {
119 MALI_DEBUG_ASSERT_POINTER(system->signaled_sync_tl);
121 /* There was nothing to wait on, so return an already signaled fence. */
123 sync_fence_acc = mali_sync_timeline_create_signaled_fence(system->signaled_sync_tl);
124 if (NULL == sync_fence_acc) goto error;
127 /* Return file descriptor for the accumulated sync fence. */
128 return mali_sync_fence_fd_alloc(sync_fence_acc);
131 if (NULL != sync_fence_acc) {
132 sync_fence_put(sync_fence_acc);
138 void mali_timeline_sync_fence_activate(struct mali_timeline_sync_fence_tracker *sync_fence_tracker)
140 mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;
142 MALI_DEBUG_ASSERT_POINTER(sync_fence_tracker);
143 MALI_DEBUG_ASSERT_POINTER(sync_fence_tracker->flag);
145 MALI_DEBUG_PRINT(4, ("Mali Timeline: activation for sync fence tracker\n"));
147 /* Signal flag and release reference. */
148 mali_sync_flag_signal(sync_fence_tracker->flag, 0);
149 mali_sync_flag_put(sync_fence_tracker->flag);
151 /* Nothing can wait on this tracker, so nothing to schedule after release. */
152 schedule_mask = mali_timeline_tracker_release(&sync_fence_tracker->tracker);
153 MALI_DEBUG_ASSERT(MALI_SCHEDULER_MASK_EMPTY == schedule_mask);
155 _mali_osk_free(sync_fence_tracker);
158 #endif /* defined(CONFIG_SYNC) */