import OT_8063_20170412 mali driver
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / gpu / mt8127 / mali / mali / common / mali_soft_job.c
CommitLineData
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_soft_job.h"
12#include "mali_osk.h"
6fa3eb70
S
13#include "mali_timeline.h"
14#include "mali_session.h"
15#include "mali_kernel_common.h"
16#include "mali_uk_types.h"
17#include "mali_scheduler.h"
bdc132d7 18#include "mali_executor.h"
6fa3eb70
S
19
20MALI_STATIC_INLINE void mali_soft_job_system_lock(struct mali_soft_job_system *system)
21{
22 MALI_DEBUG_ASSERT_POINTER(system);
23 _mali_osk_spinlock_irq_lock(system->lock);
24 MALI_DEBUG_PRINT(5, ("Mali Soft Job: soft system %p lock taken\n", system));
25 MALI_DEBUG_ASSERT(0 == system->lock_owner);
26 MALI_DEBUG_CODE(system->lock_owner = _mali_osk_get_tid());
27}
28
29MALI_STATIC_INLINE void mali_soft_job_system_unlock(struct mali_soft_job_system *system)
30{
31 MALI_DEBUG_ASSERT_POINTER(system);
32 MALI_DEBUG_PRINT(5, ("Mali Soft Job: releasing soft system %p lock\n", system));
33 MALI_DEBUG_ASSERT(_mali_osk_get_tid() == system->lock_owner);
34 MALI_DEBUG_CODE(system->lock_owner = 0);
35 _mali_osk_spinlock_irq_unlock(system->lock);
36}
37
38#if defined(DEBUG)
39MALI_STATIC_INLINE void mali_soft_job_system_assert_locked(struct mali_soft_job_system *system)
40{
41 MALI_DEBUG_ASSERT_POINTER(system);
42 MALI_DEBUG_ASSERT(_mali_osk_get_tid() == system->lock_owner);
43}
44#define MALI_ASSERT_SOFT_JOB_SYSTEM_LOCKED(system) mali_soft_job_system_assert_locked(system)
45#else
46#define MALI_ASSERT_SOFT_JOB_SYSTEM_LOCKED(system)
47#endif /* defined(DEBUG) */
48
49struct mali_soft_job_system *mali_soft_job_system_create(struct mali_session_data *session)
50{
6fa3eb70 51 struct mali_soft_job_system *system;
6fa3eb70
S
52
53 MALI_DEBUG_ASSERT_POINTER(session);
54
55 system = (struct mali_soft_job_system *) _mali_osk_calloc(1, sizeof(struct mali_soft_job_system));
56 if (NULL == system) {
57 return NULL;
58 }
59
60 system->session = session;
61
62 system->lock = _mali_osk_spinlock_irq_init(_MALI_OSK_LOCKFLAG_ORDERED, _MALI_OSK_LOCK_ORDER_SCHEDULER);
63 if (NULL == system->lock) {
64 mali_soft_job_system_destroy(system);
65 return NULL;
66 }
67 system->lock_owner = 0;
bdc132d7 68 system->last_job_id = 0;
6fa3eb70 69
6fa3eb70
S
70 _MALI_OSK_INIT_LIST_HEAD(&(system->jobs_used));
71
6fa3eb70
S
72 return system;
73}
74
75void mali_soft_job_system_destroy(struct mali_soft_job_system *system)
76{
77 MALI_DEBUG_ASSERT_POINTER(system);
78
79 /* All jobs should be free at this point. */
bdc132d7 80 MALI_DEBUG_ASSERT(_mali_osk_list_empty(&(system->jobs_used)));
6fa3eb70
S
81
82 if (NULL != system) {
83 if (NULL != system->lock) {
84 _mali_osk_spinlock_irq_term(system->lock);
85 }
86 _mali_osk_free(system);
87 }
88}
89
6fa3eb70
S
90static void mali_soft_job_system_free_job(struct mali_soft_job_system *system, struct mali_soft_job *job)
91{
92 MALI_DEBUG_ASSERT_POINTER(job);
93 MALI_DEBUG_ASSERT_POINTER(system);
94
95 mali_soft_job_system_lock(job->system);
96
6fa3eb70
S
97 MALI_DEBUG_ASSERT(MALI_SOFT_JOB_INVALID_ID != job->id);
98 MALI_DEBUG_ASSERT(system == job->system);
99
bdc132d7 100 _mali_osk_list_del(&(job->system_list));
6fa3eb70
S
101
102 mali_soft_job_system_unlock(job->system);
bdc132d7
S
103
104 _mali_osk_free(job);
6fa3eb70
S
105}
106
107MALI_STATIC_INLINE struct mali_soft_job *mali_soft_job_system_lookup_job(struct mali_soft_job_system *system, u32 job_id)
108{
bdc132d7
S
109 struct mali_soft_job *job, *tmp;
110
6fa3eb70
S
111 MALI_DEBUG_ASSERT_POINTER(system);
112 MALI_ASSERT_SOFT_JOB_SYSTEM_LOCKED(system);
113
bdc132d7
S
114 _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &system->jobs_used, struct mali_soft_job, system_list) {
115 if (job->id == job_id)
116 return job;
6fa3eb70
S
117 }
118
119 return NULL;
120}
121
122void mali_soft_job_destroy(struct mali_soft_job *job)
123{
124 MALI_DEBUG_ASSERT_POINTER(job);
125 MALI_DEBUG_ASSERT_POINTER(job->system);
126
127 MALI_DEBUG_PRINT(4, ("Mali Soft Job: destroying soft job %u (0x%08X)\n", job->id, job));
128
129 if (NULL != job) {
130 if (0 < _mali_osk_atomic_dec_return(&job->refcount)) return;
131
132 _mali_osk_atomic_term(&job->refcount);
133
134 if (NULL != job->activated_notification) {
135 _mali_osk_notification_delete(job->activated_notification);
136 job->activated_notification = NULL;
137 }
138
139 mali_soft_job_system_free_job(job->system, job);
140 }
141}
142
bdc132d7 143struct mali_soft_job *mali_soft_job_create(struct mali_soft_job_system *system, mali_soft_job_type type, u64 user_job)
6fa3eb70
S
144{
145 struct mali_soft_job *job;
146 _mali_osk_notification_t *notification = NULL;
147
148 MALI_DEBUG_ASSERT_POINTER(system);
bdc132d7
S
149 MALI_DEBUG_ASSERT((MALI_SOFT_JOB_TYPE_USER_SIGNALED == type) ||
150 (MALI_SOFT_JOB_TYPE_SELF_SIGNALED == type));
6fa3eb70 151
bdc132d7
S
152 notification = _mali_osk_notification_create(_MALI_NOTIFICATION_SOFT_ACTIVATED, sizeof(_mali_uk_soft_job_activated_s));
153 if (unlikely(NULL == notification)) {
154 MALI_PRINT_ERROR(("Mali Soft Job: failed to allocate notification"));
155 return NULL;
6fa3eb70
S
156 }
157
bdc132d7
S
158 job = _mali_osk_malloc(sizeof(struct mali_soft_job));
159 if (unlikely(NULL == job)) {
160 MALI_DEBUG_PRINT(2, ("Mali Soft Job: system alloc job failed. \n"));
6fa3eb70
S
161 return NULL;
162 }
163
bdc132d7
S
164 mali_soft_job_system_lock(system);
165
166 job->system = system;
167 job->id = system->last_job_id++;
168 job->state = MALI_SOFT_JOB_STATE_ALLOCATED;
169
170 _mali_osk_list_add(&(job->system_list), &(system->jobs_used));
171
6fa3eb70
S
172 job->type = type;
173 job->user_job = user_job;
174 job->activated = MALI_FALSE;
175
bdc132d7 176 job->activated_notification = notification;
6fa3eb70
S
177
178 _mali_osk_atomic_init(&job->refcount, 1);
179
180 MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_ALLOCATED == job->state);
181 MALI_DEBUG_ASSERT(system == job->system);
182 MALI_DEBUG_ASSERT(MALI_SOFT_JOB_INVALID_ID != job->id);
183
184 mali_soft_job_system_unlock(system);
185
186 return job;
187}
188
189mali_timeline_point mali_soft_job_start(struct mali_soft_job *job, struct mali_timeline_fence *fence)
190{
191 mali_timeline_point point;
192 struct mali_soft_job_system *system;
193
194 MALI_DEBUG_ASSERT_POINTER(job);
195 MALI_DEBUG_ASSERT_POINTER(fence);
196
197 MALI_DEBUG_ASSERT_POINTER(job->system);
198 system = job->system;
199
200 MALI_DEBUG_ASSERT_POINTER(system->session);
201 MALI_DEBUG_ASSERT_POINTER(system->session->timeline_system);
202
203 mali_soft_job_system_lock(system);
204
205 MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_ALLOCATED == job->state);
206 job->state = MALI_SOFT_JOB_STATE_STARTED;
207
208 mali_soft_job_system_unlock(system);
209
210 MALI_DEBUG_PRINT(4, ("Mali Soft Job: starting soft job %u (0x%08X)\n", job->id, job));
211
212 mali_timeline_tracker_init(&job->tracker, MALI_TIMELINE_TRACKER_SOFT, fence, job);
213 point = mali_timeline_system_add_tracker(system->session->timeline_system, &job->tracker, MALI_TIMELINE_SOFT);
214
215 return point;
216}
217
218static mali_bool mali_soft_job_is_activated(void *data)
219{
220 struct mali_soft_job *job;
221
222 job = (struct mali_soft_job *) data;
223 MALI_DEBUG_ASSERT_POINTER(job);
224
225 return job->activated;
226}
227
228_mali_osk_errcode_t mali_soft_job_system_signal_job(struct mali_soft_job_system *system, u32 job_id)
229{
230 struct mali_soft_job *job;
231 struct mali_timeline_system *timeline_system;
232 mali_scheduler_mask schedule_mask;
233
234 MALI_DEBUG_ASSERT_POINTER(system);
235
236 mali_soft_job_system_lock(system);
237
238 job = mali_soft_job_system_lookup_job(system, job_id);
239
bdc132d7
S
240 if ((NULL == job) || (MALI_SOFT_JOB_TYPE_USER_SIGNALED != job->type)
241 || !(MALI_SOFT_JOB_STATE_STARTED == job->state || MALI_SOFT_JOB_STATE_TIMED_OUT == job->state)) {
6fa3eb70
S
242 mali_soft_job_system_unlock(system);
243 MALI_PRINT_ERROR(("Mali Soft Job: invalid soft job id %u", job_id));
244 return _MALI_OSK_ERR_ITEM_NOT_FOUND;
245 }
246
247 if (MALI_SOFT_JOB_STATE_TIMED_OUT == job->state) {
248 job->state = MALI_SOFT_JOB_STATE_SIGNALED;
249 mali_soft_job_system_unlock(system);
250
251 MALI_DEBUG_ASSERT(MALI_TRUE == job->activated);
252 MALI_DEBUG_PRINT(4, ("Mali Soft Job: soft job %u (0x%08X) was timed out\n", job->id, job));
253 mali_soft_job_destroy(job);
254
255 return _MALI_OSK_ERR_TIMEOUT;
256 }
257
258 MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_STARTED == job->state);
259
260 job->state = MALI_SOFT_JOB_STATE_SIGNALED;
261 mali_soft_job_system_unlock(system);
262
263 /* Since the job now is in signaled state, timeouts from the timeline system will be
264 * ignored, and it is not possible to signal this job again. */
265
266 timeline_system = system->session->timeline_system;
267 MALI_DEBUG_ASSERT_POINTER(timeline_system);
268
269 /* Wait until activated. */
270 _mali_osk_wait_queue_wait_event(timeline_system->wait_queue, mali_soft_job_is_activated, (void *) job);
271
272 MALI_DEBUG_PRINT(4, ("Mali Soft Job: signaling soft job %u (0x%08X)\n", job->id, job));
273
274 schedule_mask = mali_timeline_tracker_release(&job->tracker);
bdc132d7 275 mali_executor_schedule_from_mask(schedule_mask, MALI_FALSE);
6fa3eb70
S
276
277 mali_soft_job_destroy(job);
278
279 return _MALI_OSK_ERR_OK;
280}
281
282static void mali_soft_job_send_activated_notification(struct mali_soft_job *job)
283{
284 if (NULL != job->activated_notification) {
285 _mali_uk_soft_job_activated_s *res = job->activated_notification->result_buffer;
286 res->user_job = job->user_job;
287 mali_session_send_notification(job->system->session, job->activated_notification);
288 }
289 job->activated_notification = NULL;
290}
291
bdc132d7 292mali_scheduler_mask mali_soft_job_system_activate_job(struct mali_soft_job *job)
6fa3eb70 293{
bdc132d7
S
294 mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;
295
6fa3eb70
S
296 MALI_DEBUG_ASSERT_POINTER(job);
297 MALI_DEBUG_ASSERT_POINTER(job->system);
298 MALI_DEBUG_ASSERT_POINTER(job->system->session);
299
300 MALI_DEBUG_PRINT(4, ("Mali Soft Job: Timeline activation for soft job %u (0x%08X).\n", job->id, job));
301
302 mali_soft_job_system_lock(job->system);
303
304 if (unlikely(job->system->session->is_aborting)) {
305 MALI_DEBUG_PRINT(3, ("Mali Soft Job: Soft job %u (0x%08X) activated while session is aborting.\n", job->id, job));
306
307 mali_soft_job_system_unlock(job->system);
308
309 /* Since we are in shutdown, we can ignore the scheduling bitmask. */
310 mali_timeline_tracker_release(&job->tracker);
311 mali_soft_job_destroy(job);
bdc132d7 312 return schedule_mask;
6fa3eb70
S
313 }
314
315 /* Send activated notification. */
316 mali_soft_job_send_activated_notification(job);
317
318 /* Wake up sleeping signaler. */
319 job->activated = MALI_TRUE;
6fa3eb70 320
bdc132d7
S
321 /* If job type is self signaled, release tracker, move soft job to free list, and scheduler at once */
322 if (MALI_SOFT_JOB_TYPE_SELF_SIGNALED == job->type) {
323 MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_STARTED == job->state);
324
325 job->state = MALI_SOFT_JOB_STATE_SIGNALED;
326 mali_soft_job_system_unlock(job->system);
327
328 schedule_mask |= mali_timeline_tracker_release(&job->tracker);
329
330 mali_soft_job_destroy(job);
331 } else {
332 _mali_osk_wait_queue_wake_up(job->tracker.system->wait_queue);
333
334 mali_soft_job_system_unlock(job->system);
335 }
336
337 return schedule_mask;
6fa3eb70
S
338}
339
340mali_scheduler_mask mali_soft_job_system_timeout_job(struct mali_soft_job *job)
341{
342 mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;
343
344 MALI_DEBUG_ASSERT_POINTER(job);
345 MALI_DEBUG_ASSERT_POINTER(job->system);
346 MALI_DEBUG_ASSERT_POINTER(job->system->session);
347 MALI_DEBUG_ASSERT(MALI_TRUE == job->activated);
348
349 MALI_DEBUG_PRINT(4, ("Mali Soft Job: Timeline timeout for soft job %u (0x%08X).\n", job->id, job));
350
351 mali_soft_job_system_lock(job->system);
352
353 MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_STARTED == job->state ||
bdc132d7 354 MALI_SOFT_JOB_STATE_SIGNALED == job->state);
6fa3eb70
S
355
356 if (unlikely(job->system->session->is_aborting)) {
357 /* The session is aborting. This job will be released and destroyed by @ref
358 * mali_soft_job_system_abort(). */
359 mali_soft_job_system_unlock(job->system);
360
361 return MALI_SCHEDULER_MASK_EMPTY;
362 }
363
364 if (MALI_SOFT_JOB_STATE_STARTED != job->state) {
365 MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_SIGNALED == job->state);
366
367 /* The job is about to be signaled, ignore timeout. */
368 MALI_DEBUG_PRINT(4, ("Mali Soft Job: Timeout on soft job %u (0x%08X) in signaled state.\n", job->id, job));
369 mali_soft_job_system_unlock(job->system);
370 return schedule_mask;
371 }
372
373 MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_STARTED == job->state);
374
375 job->state = MALI_SOFT_JOB_STATE_TIMED_OUT;
376 _mali_osk_atomic_inc(&job->refcount);
377
378 mali_soft_job_system_unlock(job->system);
379
380 schedule_mask = mali_timeline_tracker_release(&job->tracker);
381
382 mali_soft_job_destroy(job);
383
384 return schedule_mask;
385}
386
387void mali_soft_job_system_abort(struct mali_soft_job_system *system)
388{
6fa3eb70
S
389 struct mali_soft_job *job, *tmp;
390 _MALI_OSK_LIST_HEAD_STATIC_INIT(jobs);
391
392 MALI_DEBUG_ASSERT_POINTER(system);
393 MALI_DEBUG_ASSERT_POINTER(system->session);
394 MALI_DEBUG_ASSERT(system->session->is_aborting);
395
396 MALI_DEBUG_PRINT(3, ("Mali Soft Job: Aborting soft job system for session 0x%08X.\n", system->session));
397
398 mali_soft_job_system_lock(system);
399
bdc132d7
S
400 _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &system->jobs_used, struct mali_soft_job, system_list) {
401 MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_STARTED == job->state ||
402 MALI_SOFT_JOB_STATE_TIMED_OUT == job->state);
6fa3eb70
S
403
404 if (MALI_SOFT_JOB_STATE_STARTED == job->state) {
405 /* If the job has been activated, we have to release the tracker and destroy
406 * the job. If not, the tracker will be released and the job destroyed when
407 * it is activated. */
408 if (MALI_TRUE == job->activated) {
409 MALI_DEBUG_PRINT(3, ("Mali Soft Job: Aborting unsignaled soft job %u (0x%08X).\n", job->id, job));
410
411 job->state = MALI_SOFT_JOB_STATE_SIGNALED;
412 _mali_osk_list_move(&job->system_list, &jobs);
413 }
414 } else if (MALI_SOFT_JOB_STATE_TIMED_OUT == job->state) {
415 MALI_DEBUG_PRINT(3, ("Mali Soft Job: Aborting timed out soft job %u (0x%08X).\n", job->id, job));
416
417 /* We need to destroy this soft job. */
418 _mali_osk_list_move(&job->system_list, &jobs);
419 }
420 }
421
422 mali_soft_job_system_unlock(system);
423
424 /* Release and destroy jobs. */
425 _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &jobs, struct mali_soft_job, system_list) {
426 MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_SIGNALED == job->state ||
bdc132d7 427 MALI_SOFT_JOB_STATE_TIMED_OUT == job->state);
6fa3eb70
S
428
429 if (MALI_SOFT_JOB_STATE_SIGNALED == job->state) {
430 mali_timeline_tracker_release(&job->tracker);
431 }
432
433 /* Move job back to used list before destroying. */
434 _mali_osk_list_move(&job->system_list, &system->jobs_used);
435
436 mali_soft_job_destroy(job);
437 }
438}