Merge tag 'lsk-v3.10-android-14.11'
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / mali400 / mali / common / mali_pp_job.h
1 /*
2  * This confidential and proprietary software may be used only as
3  * authorised by a licensing agreement from ARM Limited
4  * (C) COPYRIGHT 2011-2014 ARM Limited
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 #ifndef __MALI_PP_JOB_H__
12 #define __MALI_PP_JOB_H__
13
14 #include "mali_osk.h"
15 #include "mali_osk_list.h"
16 #include "mali_uk_types.h"
17 #include "mali_session.h"
18 #include "mali_kernel_common.h"
19 #include "regs/mali_200_regs.h"
20 #include "mali_kernel_core.h"
21 #include "mali_dma.h"
22 #include "mali_dlbu.h"
23 #include "mali_timeline.h"
24 #if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH)
25 #include "linux/mali_memory_dma_buf.h"
26 #endif
27
28 /**
29  * The structure represents a PP job, including all sub-jobs
30  * (This struct unfortunately needs to be public because of how the _mali_osk_list_*
31  * mechanism works)
32  */
33 struct mali_pp_job {
34         _mali_osk_list_t list;                             /**< Used to link jobs together in the scheduler queue */
35         struct mali_session_data *session;                 /**< Session which submitted this job */
36         _mali_osk_list_t session_list;                     /**< Used to link jobs together in the session job list */
37         _mali_osk_list_t session_fb_lookup_list;           /**< Used to link jobs together from the same frame builder in the session */
38         _mali_uk_pp_start_job_s uargs;                     /**< Arguments from user space */
39         mali_dma_cmd_buf dma_cmd_buf;                      /**< Command buffer for starting job using Mali-450 DMA unit */
40         u32 id;                                            /**< Identifier for this job in kernel space (sequential numbering) */
41         u32 cache_order;                                   /**< Cache order used for L2 cache flushing (sequential numbering) */
42         u32 perf_counter_value0[_MALI_PP_MAX_SUB_JOBS];    /**< Value of performance counter 0 (to be returned to user space), one for each sub job */
43         u32 perf_counter_value1[_MALI_PP_MAX_SUB_JOBS];    /**< Value of performance counter 1 (to be returned to user space), one for each sub job */
44         u32 sub_jobs_num;                                  /**< Number of subjobs; set to 1 for Mali-450 if DLBU is used, otherwise equals number of PP cores */
45         u32 sub_jobs_started;                              /**< Total number of sub-jobs started (always started in ascending order) */
46         u32 sub_jobs_completed;                            /**< Number of completed sub-jobs in this superjob */
47         u32 sub_job_errors;                                /**< Bitfield with errors (errors for each single sub-job is or'ed together) */
48         u32 pid;                                           /**< Process ID of submitting process */
49         u32 tid;                                           /**< Thread ID of submitting thread */
50         _mali_osk_notification_t *finished_notification;   /**< Notification sent back to userspace on job complete */
51         u32 num_memory_cookies;                            /**< Number of memory cookies attached to job */
52         u32 *memory_cookies;                               /**< Memory cookies attached to job */
53 #if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH)
54         struct mali_dma_buf_attachment **dma_bufs;         /**< Array of DMA-bufs used by job */
55         u32 num_dma_bufs;                                  /**< Number of DMA-bufs used by job */
56 #endif
57         struct mali_timeline_tracker tracker;              /**< Timeline tracker for this job */
58         u32 perf_counter_per_sub_job_count;                /**< Number of values in the two arrays which is != MALI_HW_CORE_NO_COUNTER */
59         u32 perf_counter_per_sub_job_src0[_MALI_PP_MAX_SUB_JOBS]; /**< Per sub job counters src0 */
60         u32 perf_counter_per_sub_job_src1[_MALI_PP_MAX_SUB_JOBS]; /**< Per sub job counters src1 */
61 };
62
63 void mali_pp_job_initialize(void);
64 void mali_pp_job_terminate(void);
65
66 struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_uk_pp_start_job_s *uargs, u32 id);
67 void mali_pp_job_delete(struct mali_pp_job *job);
68
69 u32 mali_pp_job_get_perf_counter_src0(struct mali_pp_job *job, u32 sub_job);
70 u32 mali_pp_job_get_perf_counter_src1(struct mali_pp_job *job, u32 sub_job);
71
72 void mali_pp_job_set_pp_counter_global_src0(u32 counter);
73 void mali_pp_job_set_pp_counter_global_src1(u32 counter);
74 void mali_pp_job_set_pp_counter_sub_job_src0(u32 sub_job, u32 counter);
75 void mali_pp_job_set_pp_counter_sub_job_src1(u32 sub_job, u32 counter);
76
77 u32 mali_pp_job_get_pp_counter_global_src0(void);
78 u32 mali_pp_job_get_pp_counter_global_src1(void);
79 u32 mali_pp_job_get_pp_counter_sub_job_src0(u32 sub_job);
80 u32 mali_pp_job_get_pp_counter_sub_job_src1(u32 sub_job);
81
82 MALI_STATIC_INLINE u32 mali_pp_job_get_id(struct mali_pp_job *job)
83 {
84         return (NULL == job) ? 0 : job->id;
85 }
86
87 MALI_STATIC_INLINE u32 mali_pp_job_get_cache_order(struct mali_pp_job *job)
88 {
89         return (NULL == job) ? 0 : job->cache_order;
90 }
91
92 MALI_STATIC_INLINE u64 mali_pp_job_get_user_id(struct mali_pp_job *job)
93 {
94         return job->uargs.user_job_ptr;
95 }
96
97 MALI_STATIC_INLINE u32 mali_pp_job_get_frame_builder_id(struct mali_pp_job *job)
98 {
99         return job->uargs.frame_builder_id;
100 }
101
102 MALI_STATIC_INLINE u32 mali_pp_job_get_flush_id(struct mali_pp_job *job)
103 {
104         return job->uargs.flush_id;
105 }
106
107 MALI_STATIC_INLINE u32 mali_pp_job_get_pid(struct mali_pp_job *job)
108 {
109         return job->pid;
110 }
111
112 MALI_STATIC_INLINE u32 mali_pp_job_get_tid(struct mali_pp_job *job)
113 {
114         return job->tid;
115 }
116
117 MALI_STATIC_INLINE u32 *mali_pp_job_get_frame_registers(struct mali_pp_job *job)
118 {
119         return job->uargs.frame_registers;
120 }
121
122 MALI_STATIC_INLINE u32 *mali_pp_job_get_dlbu_registers(struct mali_pp_job *job)
123 {
124         return job->uargs.dlbu_registers;
125 }
126
127 MALI_STATIC_INLINE mali_bool mali_pp_job_is_virtual_group_job(struct mali_pp_job *job)
128 {
129         if (mali_is_mali450()) {
130                 return 1 != job->uargs.num_cores;
131         }
132
133         return MALI_FALSE;
134 }
135
136 MALI_STATIC_INLINE mali_bool mali_pp_job_is_with_dlbu(struct mali_pp_job *job)
137 {
138 #if defined(CONFIG_MALI450)
139         return 0 == job->uargs.num_cores;
140 #else
141         return MALI_FALSE;
142 #endif
143 }
144
145 MALI_STATIC_INLINE u32 mali_pp_job_get_addr_frame(struct mali_pp_job *job, u32 sub_job)
146 {
147         if (mali_pp_job_is_with_dlbu(job)) {
148                 return MALI_DLBU_VIRT_ADDR;
149         } else if (0 == sub_job) {
150                 return job->uargs.frame_registers[MALI200_REG_ADDR_FRAME / sizeof(u32)];
151         } else if (sub_job < _MALI_PP_MAX_SUB_JOBS) {
152                 return job->uargs.frame_registers_addr_frame[sub_job - 1];
153         }
154
155         return 0;
156 }
157
158 MALI_STATIC_INLINE u32 mali_pp_job_get_addr_stack(struct mali_pp_job *job, u32 sub_job)
159 {
160         if (0 == sub_job) {
161                 return job->uargs.frame_registers[MALI200_REG_ADDR_STACK / sizeof(u32)];
162         } else if (sub_job < _MALI_PP_MAX_SUB_JOBS) {
163                 return job->uargs.frame_registers_addr_stack[sub_job - 1];
164         }
165
166         return 0;
167 }
168
169 MALI_STATIC_INLINE u32 *mali_pp_job_get_wb0_registers(struct mali_pp_job *job)
170 {
171         return job->uargs.wb0_registers;
172 }
173
174 MALI_STATIC_INLINE u32 *mali_pp_job_get_wb1_registers(struct mali_pp_job *job)
175 {
176         return job->uargs.wb1_registers;
177 }
178
179 MALI_STATIC_INLINE u32 *mali_pp_job_get_wb2_registers(struct mali_pp_job *job)
180 {
181         return job->uargs.wb2_registers;
182 }
183
184 MALI_STATIC_INLINE void mali_pp_job_disable_wb0(struct mali_pp_job *job)
185 {
186         job->uargs.wb0_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0;
187 }
188
189 MALI_STATIC_INLINE void mali_pp_job_disable_wb1(struct mali_pp_job *job)
190 {
191         job->uargs.wb1_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0;
192 }
193
194 MALI_STATIC_INLINE void mali_pp_job_disable_wb2(struct mali_pp_job *job)
195 {
196         job->uargs.wb2_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0;
197 }
198
199 MALI_STATIC_INLINE mali_bool mali_pp_job_all_writeback_unit_disabled(struct mali_pp_job *job)
200 {
201         MALI_DEBUG_ASSERT_POINTER(job);
202
203         if (job->uargs.wb0_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] ||
204             job->uargs.wb1_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] ||
205             job->uargs.wb2_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT]
206            ) {
207                 /* At least one output unit active */
208                 return MALI_FALSE;
209         }
210
211         /* All outputs are disabled - we can abort the job */
212         return MALI_TRUE;
213 }
214
215 MALI_STATIC_INLINE u32 mali_pp_job_get_fb_lookup_id(struct mali_pp_job *job)
216 {
217         MALI_DEBUG_ASSERT_POINTER(job);
218
219         return MALI_PP_JOB_FB_LOOKUP_LIST_MASK & job->uargs.frame_builder_id;
220 }
221
222 MALI_STATIC_INLINE struct mali_session_data *mali_pp_job_get_session(struct mali_pp_job *job)
223 {
224         return job->session;
225 }
226
227 MALI_STATIC_INLINE mali_bool mali_pp_job_has_unstarted_sub_jobs(struct mali_pp_job *job)
228 {
229         return (job->sub_jobs_started < job->sub_jobs_num) ? MALI_TRUE : MALI_FALSE;
230 }
231
232 /* Function used when we are terminating a session with jobs. Return TRUE if it has a rendering job.
233    Makes sure that no new subjobs are started. */
234 MALI_STATIC_INLINE void mali_pp_job_mark_unstarted_failed(struct mali_pp_job *job)
235 {
236         u32 jobs_remaining = job->sub_jobs_num - job->sub_jobs_started;
237         job->sub_jobs_started   += jobs_remaining;
238         job->sub_jobs_completed += jobs_remaining;
239         job->sub_job_errors     += jobs_remaining;
240 }
241
242 MALI_STATIC_INLINE void mali_pp_job_mark_unstarted_success(struct mali_pp_job *job)
243 {
244         u32 jobs_remaining = job->sub_jobs_num - job->sub_jobs_started;
245         job->sub_jobs_started   += jobs_remaining;
246         job->sub_jobs_completed += jobs_remaining;
247 }
248
249 MALI_STATIC_INLINE mali_bool mali_pp_job_is_complete(struct mali_pp_job *job)
250 {
251         return (job->sub_jobs_num == job->sub_jobs_completed) ? MALI_TRUE : MALI_FALSE;
252 }
253
254 MALI_STATIC_INLINE u32 mali_pp_job_get_first_unstarted_sub_job(struct mali_pp_job *job)
255 {
256         return job->sub_jobs_started;
257 }
258
259 MALI_STATIC_INLINE u32 mali_pp_job_get_sub_job_count(struct mali_pp_job *job)
260 {
261         return job->sub_jobs_num;
262 }
263
264 MALI_STATIC_INLINE mali_bool mali_pp_job_needs_dma_buf_mapping(struct mali_pp_job *job)
265 {
266         MALI_DEBUG_ASSERT(job);
267
268         if (0 != job->num_memory_cookies) {
269                 return MALI_TRUE;
270         }
271
272         return MALI_FALSE;
273 }
274
275 MALI_STATIC_INLINE void mali_pp_job_mark_sub_job_started(struct mali_pp_job *job, u32 sub_job)
276 {
277         MALI_DEBUG_ASSERT_POINTER(job);
278
279         /* Assert that we are marking the "first unstarted sub job" as started */
280         MALI_DEBUG_ASSERT(job->sub_jobs_started == sub_job);
281
282         job->sub_jobs_started++;
283 }
284
285 MALI_STATIC_INLINE void mali_pp_job_mark_sub_job_completed(struct mali_pp_job *job, mali_bool success)
286 {
287         job->sub_jobs_completed++;
288         if (MALI_FALSE == success) {
289                 job->sub_job_errors++;
290         }
291 }
292
293 MALI_STATIC_INLINE mali_bool mali_pp_job_was_success(struct mali_pp_job *job)
294 {
295         if (0 == job->sub_job_errors) {
296                 return MALI_TRUE;
297         }
298         return MALI_FALSE;
299 }
300
301 MALI_STATIC_INLINE mali_bool mali_pp_job_use_no_notification(struct mali_pp_job *job)
302 {
303         return job->uargs.flags & _MALI_PP_JOB_FLAG_NO_NOTIFICATION ? MALI_TRUE : MALI_FALSE;
304 }
305
306 MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_flag(struct mali_pp_job *job)
307 {
308         return job->uargs.perf_counter_flag;
309 }
310
311
312 MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_value0(struct mali_pp_job *job, u32 sub_job)
313 {
314         return job->perf_counter_value0[sub_job];
315 }
316
317 MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_value1(struct mali_pp_job *job, u32 sub_job)
318 {
319         return job->perf_counter_value1[sub_job];
320 }
321
322 MALI_STATIC_INLINE void mali_pp_job_set_perf_counter_value0(struct mali_pp_job *job, u32 sub_job, u32 value)
323 {
324         job->perf_counter_value0[sub_job] = value;
325 }
326
327 MALI_STATIC_INLINE void mali_pp_job_set_perf_counter_value1(struct mali_pp_job *job, u32 sub_job, u32 value)
328 {
329         job->perf_counter_value1[sub_job] = value;
330 }
331
332 MALI_STATIC_INLINE _mali_osk_errcode_t mali_pp_job_check(struct mali_pp_job *job)
333 {
334         if (mali_pp_job_is_with_dlbu(job) && job->sub_jobs_num != 1) {
335                 return _MALI_OSK_ERR_FAULT;
336         }
337         return _MALI_OSK_ERR_OK;
338 }
339
340 /**
341  * Returns MALI_TRUE if first job should be started after second job.
342  *
343  * @param first First job.
344  * @param second Second job.
345  * @return MALI_TRUE if first job should be started after second job, MALI_FALSE if not.
346  */
347 MALI_STATIC_INLINE mali_bool mali_pp_job_should_start_after(struct mali_pp_job *first, struct mali_pp_job *second)
348 {
349         MALI_DEBUG_ASSERT_POINTER(first);
350         MALI_DEBUG_ASSERT_POINTER(second);
351
352         /* First job should be started after second job if second job is in progress. */
353         if (0 < second->sub_jobs_started) {
354                 return MALI_TRUE;
355         }
356
357         /* First job should be started after second job if first job has a higher job id.  A span is
358            used to handle job id wrapping. */
359         if ((mali_pp_job_get_id(first) - mali_pp_job_get_id(second)) < MALI_SCHEDULER_JOB_ID_SPAN) {
360                 return MALI_TRUE;
361         }
362
363         /* Second job should be started after first job. */
364         return MALI_FALSE;
365 }
366
367 /**
368  * Returns MALI_TRUE if this job has more than two sub jobs and all sub jobs are unstarted.
369  *
370  * @param job Job to check.
371  * @return MALI_TRUE if job has more than two sub jobs and all sub jobs are unstarted, MALI_FALSE if not.
372  */
373 MALI_STATIC_INLINE mali_bool mali_pp_job_is_large_and_unstarted(struct mali_pp_job *job)
374 {
375         MALI_DEBUG_ASSERT_POINTER(job);
376         MALI_DEBUG_ASSERT(!mali_pp_job_is_virtual_group_job(job));
377
378         return (0 == job->sub_jobs_started && 2 < job->sub_jobs_num);
379 }
380
381 /**
382  * Get PP job's Timeline tracker.
383  *
384  * @param job PP job.
385  * @return Pointer to Timeline tracker for the job.
386  */
387 MALI_STATIC_INLINE struct mali_timeline_tracker *mali_pp_job_get_tracker(struct mali_pp_job *job)
388 {
389         MALI_DEBUG_ASSERT_POINTER(job);
390         return &(job->tracker);
391 }
392
393 #endif /* __MALI_PP_JOB_H__ */