Commit | Line | Data |
---|---|---|
6fa3eb70 S |
1 | /* |
2 | * This confidential and proprietary software may be used only as | |
3 | * authorised by a licensing agreement from ARM Limited | |
bdc132d7 | 4 | * (C) COPYRIGHT 2013, 2015 ARM Limited |
6fa3eb70 S |
5 | * ALL RIGHTS RESERVED |
6 | * The entire notice above must be reproduced on all authorised | |
7 | * copies and copies may only be made to the extent permitted | |
8 | * by a licensing agreement from ARM Limited. | |
9 | */ | |
10 | ||
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) | |
18 | ||
19 | /** | |
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. | |
22 | * | |
23 | * @param timeline Timeline. | |
24 | * @param point Point on timeline. | |
25 | * @return Sync fence that will be signaled when tracker is activated. | |
26 | */ | |
27 | static struct sync_fence *mali_timeline_sync_fence_create_and_add_tracker(struct mali_timeline *timeline, mali_timeline_point point) | |
28 | { | |
29 | struct mali_timeline_sync_fence_tracker *sync_fence_tracker; | |
30 | struct sync_fence *sync_fence; | |
31 | struct mali_timeline_fence fence; | |
32 | ||
33 | MALI_DEBUG_ASSERT_POINTER(timeline); | |
34 | MALI_DEBUG_ASSERT(MALI_TIMELINE_NO_POINT != point); | |
35 | ||
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")); | |
40 | return NULL; | |
41 | } | |
42 | ||
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); | |
49 | return NULL; | |
50 | } | |
51 | ||
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); | |
58 | return NULL; | |
59 | } | |
60 | ||
61 | /* Setup fence for tracker. */ | |
62 | _mali_osk_memset(&fence, 0, sizeof(struct mali_timeline_fence)); | |
63 | fence.sync_fd = -1; | |
64 | fence.points[timeline->id] = point; | |
65 | ||
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); | |
70 | ||
71 | return sync_fence; | |
72 | } | |
73 | ||
74 | s32 mali_timeline_sync_fence_create(struct mali_timeline_system *system, struct mali_timeline_fence *fence) | |
75 | { | |
76 | u32 i; | |
77 | struct sync_fence *sync_fence_acc = NULL; | |
78 | ||
79 | MALI_DEBUG_ASSERT_POINTER(system); | |
80 | MALI_DEBUG_ASSERT_POINTER(fence); | |
81 | ||
82 | for (i = 0; i < MALI_TIMELINE_MAX; ++i) { | |
83 | struct mali_timeline *timeline; | |
84 | struct sync_fence *sync_fence; | |
85 | ||
86 | if (MALI_TIMELINE_NO_POINT == fence->points[i]) continue; | |
87 | ||
88 | timeline = system->timelines[i]; | |
89 | MALI_DEBUG_ASSERT_POINTER(timeline); | |
90 | ||
91 | sync_fence = mali_timeline_sync_fence_create_and_add_tracker(timeline, fence->points[i]); | |
bdc132d7 S |
92 | if (NULL == sync_fence) goto error; |
93 | ||
6fa3eb70 S |
94 | if (NULL != sync_fence_acc) { |
95 | /* Merge sync fences. */ | |
96 | sync_fence_acc = mali_sync_fence_merge(sync_fence_acc, sync_fence); | |
bdc132d7 | 97 | if (NULL == sync_fence_acc) goto error; |
6fa3eb70 S |
98 | } else { |
99 | /* This was the first sync fence created. */ | |
100 | sync_fence_acc = sync_fence; | |
101 | } | |
102 | } | |
103 | ||
104 | if (-1 != fence->sync_fd) { | |
105 | struct sync_fence *sync_fence; | |
106 | ||
107 | sync_fence = sync_fence_fdget(fence->sync_fd); | |
bdc132d7 S |
108 | if (NULL == sync_fence) goto error; |
109 | ||
6fa3eb70 S |
110 | if (NULL != sync_fence_acc) { |
111 | sync_fence_acc = mali_sync_fence_merge(sync_fence_acc, sync_fence); | |
bdc132d7 | 112 | if (NULL == sync_fence_acc) goto error; |
6fa3eb70 S |
113 | } else { |
114 | sync_fence_acc = sync_fence; | |
115 | } | |
116 | } | |
117 | ||
118 | if (NULL == sync_fence_acc) { | |
119 | MALI_DEBUG_ASSERT_POINTER(system->signaled_sync_tl); | |
120 | ||
121 | /* There was nothing to wait on, so return an already signaled fence. */ | |
122 | ||
123 | sync_fence_acc = mali_sync_timeline_create_signaled_fence(system->signaled_sync_tl); | |
bdc132d7 | 124 | if (NULL == sync_fence_acc) goto error; |
6fa3eb70 S |
125 | } |
126 | ||
127 | /* Return file descriptor for the accumulated sync fence. */ | |
128 | return mali_sync_fence_fd_alloc(sync_fence_acc); | |
129 | ||
130 | error: | |
131 | if (NULL != sync_fence_acc) { | |
132 | sync_fence_put(sync_fence_acc); | |
133 | } | |
bdc132d7 | 134 | |
6fa3eb70 S |
135 | return -1; |
136 | } | |
137 | ||
138 | void mali_timeline_sync_fence_activate(struct mali_timeline_sync_fence_tracker *sync_fence_tracker) | |
139 | { | |
140 | mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY; | |
141 | ||
142 | MALI_DEBUG_ASSERT_POINTER(sync_fence_tracker); | |
143 | MALI_DEBUG_ASSERT_POINTER(sync_fence_tracker->flag); | |
144 | ||
145 | MALI_DEBUG_PRINT(4, ("Mali Timeline: activation for sync fence tracker\n")); | |
146 | ||
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); | |
150 | ||
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); | |
154 | ||
155 | _mali_osk_free(sync_fence_tracker); | |
156 | } | |
157 | ||
158 | #endif /* defined(CONFIG_SYNC) */ |