73843f07c9905b2381f630d76cada013ea15bc04
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / mali400 / mali / common / mali_timeline_sync_fence.c
1 /*
2  * Copyright (C) 2013, 2015 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_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]);
92                 if (NULL == sync_fence) goto error;
93
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;
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);
108                 if (NULL == sync_fence) goto error;
109
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;
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);
124                 if (NULL == sync_fence_acc) goto error;
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         }
134
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) */