Merge tag 'v4.4-rc8'
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / mali400 / mali / common / mali_group.h
1 /*
2  * Copyright (C) 2011-2014 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 #ifndef __MALI_GROUP_H__
12 #define __MALI_GROUP_H__
13
14 #include "mali_osk.h"
15 #include "mali_l2_cache.h"
16 #include "mali_mmu.h"
17 #include "mali_gp.h"
18 #include "mali_pp.h"
19 #include "mali_session.h"
20 #include "mali_osk_profiling.h"
21
22 /**
23  * @brief Default max runtime [ms] for a core job - used by timeout timers
24  */
25 #define MALI_MAX_JOB_RUNTIME_DEFAULT 5000
26
27 extern int mali_max_job_runtime;
28
29 #define MALI_MAX_NUMBER_OF_GROUPS 10
30 #define MALI_MAX_NUMBER_OF_PHYSICAL_PP_GROUPS 8
31
32 enum mali_group_state {
33         MALI_GROUP_STATE_INACTIVE,
34         MALI_GROUP_STATE_ACTIVATION_PENDING,
35         MALI_GROUP_STATE_ACTIVE,
36 };
37
38 /**
39  * The structure represents a render group
40  * A render group is defined by all the cores that share the same Mali MMU
41  */
42
43 struct mali_group {
44         struct mali_mmu_core        *mmu;
45         struct mali_session_data    *session;
46
47         enum mali_group_state        state;
48         mali_bool                    power_is_on;
49
50         mali_bool                    is_working;
51         unsigned long                start_time; /* in ticks */
52
53         struct mali_gp_core         *gp_core;
54         struct mali_gp_job          *gp_running_job;
55
56         struct mali_pp_core         *pp_core;
57         struct mali_pp_job          *pp_running_job;
58         u32                         pp_running_sub_job;
59
60         struct mali_pm_domain       *pm_domain;
61
62         struct mali_l2_cache_core   *l2_cache_core[2];
63         u32                         l2_cache_core_ref_count[2];
64
65         /* Parent virtual group (if any) */
66         struct mali_group           *parent_group;
67
68         struct mali_dlbu_core       *dlbu_core;
69         struct mali_bcast_unit      *bcast_core;
70
71         /* Used for working groups which needs to be disabled */
72         mali_bool                    disable_requested;
73
74         /* Used by group to link child groups (for virtual group) */
75         _mali_osk_list_t            group_list;
76
77         /* Used by executor module in order to link groups of same state */
78         _mali_osk_list_t            executor_list;
79
80         /* Used by PM domains to link groups of same domain */
81         _mali_osk_list_t             pm_domain_list;
82
83         _mali_osk_wq_work_t         *bottom_half_work_mmu;
84         _mali_osk_wq_work_t         *bottom_half_work_gp;
85         _mali_osk_wq_work_t         *bottom_half_work_pp;
86
87         _mali_osk_timer_t           *timeout_timer;
88 };
89
90 /** @brief Create a new Mali group object
91  *
92  * @return A pointer to a new group object
93  */
94 struct mali_group *mali_group_create(struct mali_l2_cache_core *core,
95                                      struct mali_dlbu_core *dlbu,
96                                      struct mali_bcast_unit *bcast,
97                                      u32 domain_index);
98
99 void mali_group_delete(struct mali_group *group);
100
101 _mali_osk_errcode_t mali_group_add_mmu_core(struct mali_group *group,
102                 struct mali_mmu_core *mmu_core);
103 void mali_group_remove_mmu_core(struct mali_group *group);
104
105 _mali_osk_errcode_t mali_group_add_gp_core(struct mali_group *group,
106                 struct mali_gp_core *gp_core);
107 void mali_group_remove_gp_core(struct mali_group *group);
108
109 _mali_osk_errcode_t mali_group_add_pp_core(struct mali_group *group,
110                 struct mali_pp_core *pp_core);
111 void mali_group_remove_pp_core(struct mali_group *group);
112
113 MALI_STATIC_INLINE const char *mali_group_core_description(
114         struct mali_group *group)
115 {
116         MALI_DEBUG_ASSERT_POINTER(group);
117         if (NULL != group->pp_core) {
118                 return mali_pp_core_description(group->pp_core);
119         } else {
120                 MALI_DEBUG_ASSERT_POINTER(group->gp_core);
121                 return mali_gp_core_description(group->gp_core);
122         }
123 }
124
125 MALI_STATIC_INLINE mali_bool mali_group_is_virtual(struct mali_group *group)
126 {
127         MALI_DEBUG_ASSERT_POINTER(group);
128
129 #if defined(CONFIG_MALI450)
130         return (NULL != group->dlbu_core);
131 #else
132         return MALI_FALSE;
133 #endif
134 }
135
136 /** @brief Check if a group is a part of a virtual group or not
137  */
138 MALI_STATIC_INLINE mali_bool mali_group_is_in_virtual(struct mali_group *group)
139 {
140         MALI_DEBUG_ASSERT_POINTER(group);
141         MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
142
143 #if defined(CONFIG_MALI450)
144         return (NULL != group->parent_group) ? MALI_TRUE : MALI_FALSE;
145 #else
146         return MALI_FALSE;
147 #endif
148 }
149
150 /** @brief Reset group
151  *
152  * This function will reset the entire group,
153  * including all the cores present in the group.
154  *
155  * @param group Pointer to the group to reset
156  */
157 void mali_group_reset(struct mali_group *group);
158
159 MALI_STATIC_INLINE struct mali_session_data *mali_group_get_session(
160         struct mali_group *group)
161 {
162         MALI_DEBUG_ASSERT_POINTER(group);
163         MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
164
165         return group->session;
166 }
167
168 MALI_STATIC_INLINE void mali_group_clear_session(struct mali_group *group)
169 {
170         MALI_DEBUG_ASSERT_POINTER(group);
171         MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
172
173         if (NULL != group->session) {
174                 mali_mmu_activate_empty_page_directory(group->mmu);
175                 group->session = NULL;
176         }
177 }
178
179 enum mali_group_state mali_group_activate(struct mali_group *group);
180
181 /*
182  * Change state from ACTIVATION_PENDING to ACTIVE
183  * For virtual group, all childs need to be ACTIVE first
184  */
185 mali_bool mali_group_set_active(struct mali_group *group);
186
187 /*
188  * @return MALI_TRUE means one or more domains can now be powered off,
189  * and caller should call either mali_pm_update_async() or
190  * mali_pm_update_sync() in order to do so.
191  */
192 mali_bool mali_group_deactivate(struct mali_group *group);
193
194 MALI_STATIC_INLINE enum mali_group_state mali_group_get_state(struct mali_group *group)
195 {
196         MALI_DEBUG_ASSERT_POINTER(group);
197         MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
198         return group->state;
199 }
200
201 MALI_STATIC_INLINE mali_bool mali_group_power_is_on(struct mali_group *group)
202 {
203         MALI_DEBUG_ASSERT_POINTER(group);
204         return group->power_is_on;
205 }
206
207 void mali_group_power_up(struct mali_group *group);
208 void mali_group_power_down(struct mali_group *group);
209
210 MALI_STATIC_INLINE void mali_group_set_disable_request(
211         struct mali_group *group, mali_bool disable)
212 {
213         MALI_DEBUG_ASSERT_POINTER(group);
214         MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
215         group->disable_requested = disable;
216
217         /**
218          * When one of child group's disable_requeset is set TRUE, then
219          * the disable_request of parent group should also be set to TRUE.
220          * While, the disable_request of parent group should only be set to FALSE
221          * only when all of its child group's disable_request are set to FALSE.
222          */
223         if (NULL != group->parent_group && MALI_TRUE == disable) {
224                 group->parent_group->disable_requested = disable;
225         }
226 }
227
228 MALI_STATIC_INLINE mali_bool mali_group_disable_requested(
229         struct mali_group *group)
230 {
231         MALI_DEBUG_ASSERT_POINTER(group);
232         MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
233         return group->disable_requested;
234 }
235
236 /** @brief Virtual groups */
237 void mali_group_add_group(struct mali_group *parent, struct mali_group *child);
238 struct mali_group *mali_group_acquire_group(struct mali_group *parent);
239 void mali_group_remove_group(struct mali_group *parent, struct mali_group *child);
240
241 /** @brief Checks if the group is working.
242  */
243 MALI_STATIC_INLINE mali_bool mali_group_is_working(struct mali_group *group)
244 {
245         MALI_DEBUG_ASSERT_POINTER(group);
246         MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
247         if (mali_group_is_in_virtual(group)) {
248                 struct mali_group *tmp_group = mali_executor_get_virtual_group();
249                 return tmp_group->is_working;
250         }
251         return group->is_working;
252 }
253
254 MALI_STATIC_INLINE struct mali_gp_job *mali_group_get_running_gp_job(struct mali_group *group)
255 {
256         MALI_DEBUG_ASSERT_POINTER(group);
257         MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
258         return group->gp_running_job;
259 }
260
261 /** @brief Zap MMU TLB on all groups
262  *
263  * Zap TLB on group if \a session is active.
264  */
265 mali_bool mali_group_zap_session(struct mali_group *group,
266                                  struct mali_session_data *session);
267
268 /** @brief Get pointer to GP core object
269  */
270 MALI_STATIC_INLINE struct mali_gp_core *mali_group_get_gp_core(struct mali_group *group)
271 {
272         MALI_DEBUG_ASSERT_POINTER(group);
273         return group->gp_core;
274 }
275
276 /** @brief Get pointer to PP core object
277  */
278 MALI_STATIC_INLINE struct mali_pp_core *mali_group_get_pp_core(struct mali_group *group)
279 {
280         MALI_DEBUG_ASSERT_POINTER(group);
281         return group->pp_core;
282 }
283
284 /** @brief Start GP job
285  */
286 void mali_group_start_gp_job(struct mali_group *group, struct mali_gp_job *job);
287
288 void mali_group_start_pp_job(struct mali_group *group, struct mali_pp_job *job, u32 sub_job);
289
290 /** @brief Start virtual group Job on a virtual group
291 */
292 void mali_group_start_job_on_virtual(struct mali_group *group, struct mali_pp_job *job, u32 first_subjob, u32 last_subjob);
293
294
295 /** @brief Start a subjob from a particular on a specific PP group
296 */
297 void mali_group_start_job_on_group(struct mali_group *group, struct mali_pp_job *job, u32 subjob);
298
299
300 /** @brief remove all the unused groups in tmp_unused group  list, so that the group is in consistent status.
301  */
302 void mali_group_non_dlbu_job_done_virtual(struct mali_group *group);
303
304
305 /** @brief Resume GP job that suspended waiting for more heap memory
306  */
307 void mali_group_resume_gp_with_new_heap(struct mali_group *group, u32 job_id, u32 start_addr, u32 end_addr);
308
309 MALI_STATIC_INLINE enum mali_interrupt_result mali_group_get_interrupt_result_gp(struct mali_group *group)
310 {
311         MALI_DEBUG_ASSERT_POINTER(group);
312         MALI_DEBUG_ASSERT_POINTER(group->gp_core);
313         MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
314         return mali_gp_get_interrupt_result(group->gp_core);
315 }
316
317 MALI_STATIC_INLINE enum mali_interrupt_result mali_group_get_interrupt_result_pp(struct mali_group *group)
318 {
319         MALI_DEBUG_ASSERT_POINTER(group);
320         MALI_DEBUG_ASSERT_POINTER(group->pp_core);
321         MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
322         return mali_pp_get_interrupt_result(group->pp_core);
323 }
324
325 MALI_STATIC_INLINE enum mali_interrupt_result mali_group_get_interrupt_result_mmu(struct mali_group *group)
326 {
327         MALI_DEBUG_ASSERT_POINTER(group);
328         MALI_DEBUG_ASSERT_POINTER(group->mmu);
329         MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
330         return mali_mmu_get_interrupt_result(group->mmu);
331 }
332
333 MALI_STATIC_INLINE mali_bool mali_group_gp_is_active(struct mali_group *group)
334 {
335         MALI_DEBUG_ASSERT_POINTER(group);
336         MALI_DEBUG_ASSERT_POINTER(group->gp_core);
337         MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
338         return mali_gp_is_active(group->gp_core);
339 }
340
341 MALI_STATIC_INLINE mali_bool mali_group_pp_is_active(struct mali_group *group)
342 {
343         MALI_DEBUG_ASSERT_POINTER(group);
344         MALI_DEBUG_ASSERT_POINTER(group->pp_core);
345         MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
346         return mali_pp_is_active(group->pp_core);
347 }
348
349 MALI_STATIC_INLINE mali_bool mali_group_has_timed_out(struct mali_group *group)
350 {
351         unsigned long time_cost;
352         struct mali_group *tmp_group = group;
353
354         MALI_DEBUG_ASSERT_POINTER(group);
355         MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
356
357         /* if the group is in virtual need to use virtual_group's start time */
358         if (mali_group_is_in_virtual(group)) {
359                 tmp_group = mali_executor_get_virtual_group();
360         }
361
362         time_cost = _mali_osk_time_tickcount() - tmp_group->start_time;
363         if (_mali_osk_time_mstoticks(mali_max_job_runtime) <= time_cost) {
364                 /*
365                  * current tick is at or after timeout end time,
366                  * so this is a valid timeout
367                  */
368                 return MALI_TRUE;
369         } else {
370                 /*
371                  * Not a valid timeout. A HW interrupt probably beat
372                  * us to it, and the timer wasn't properly deleted
373                  * (async deletion used due to atomic context).
374                  */
375                 return MALI_FALSE;
376         }
377 }
378
379 MALI_STATIC_INLINE void mali_group_mask_all_interrupts_gp(struct mali_group *group)
380 {
381         MALI_DEBUG_ASSERT_POINTER(group);
382         MALI_DEBUG_ASSERT_POINTER(group->gp_core);
383         MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
384         return mali_gp_mask_all_interrupts(group->gp_core);
385 }
386
387 MALI_STATIC_INLINE void mali_group_mask_all_interrupts_pp(struct mali_group *group)
388 {
389         MALI_DEBUG_ASSERT_POINTER(group);
390         MALI_DEBUG_ASSERT_POINTER(group->pp_core);
391         MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
392         return mali_pp_mask_all_interrupts(group->pp_core);
393 }
394
395 MALI_STATIC_INLINE void mali_group_enable_interrupts_gp(
396         struct mali_group *group,
397         enum mali_interrupt_result exceptions)
398 {
399         MALI_DEBUG_ASSERT_POINTER(group);
400         MALI_DEBUG_ASSERT_POINTER(group->gp_core);
401         MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
402         mali_gp_enable_interrupts(group->gp_core, exceptions);
403 }
404
405 MALI_STATIC_INLINE void mali_group_schedule_bottom_half_gp(struct mali_group *group)
406 {
407         MALI_DEBUG_ASSERT_POINTER(group);
408         MALI_DEBUG_ASSERT_POINTER(group->gp_core);
409         _mali_osk_wq_schedule_work(group->bottom_half_work_gp);
410 }
411
412 MALI_STATIC_INLINE void mali_group_schedule_bottom_half_pp(struct mali_group *group)
413 {
414         MALI_DEBUG_ASSERT_POINTER(group);
415         MALI_DEBUG_ASSERT_POINTER(group->pp_core);
416         _mali_osk_wq_schedule_work(group->bottom_half_work_pp);
417 }
418
419 MALI_STATIC_INLINE void mali_group_schedule_bottom_half_mmu(struct mali_group *group)
420 {
421         MALI_DEBUG_ASSERT_POINTER(group);
422         MALI_DEBUG_ASSERT_POINTER(group->mmu);
423         _mali_osk_wq_schedule_work(group->bottom_half_work_mmu);
424 }
425
426 struct mali_pp_job *mali_group_complete_pp(struct mali_group *group, mali_bool success, u32 *sub_job);
427
428 struct mali_gp_job *mali_group_complete_gp(struct mali_group *group, mali_bool success);
429
430 #if defined(CONFIG_MALI400_PROFILING)
431 MALI_STATIC_INLINE void mali_group_oom(struct mali_group *group)
432 {
433         _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SUSPEND |
434                                       MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0),
435                                       0, 0, 0, 0, 0);
436 }
437 #endif
438
439 struct mali_group *mali_group_get_glob_group(u32 index);
440 u32 mali_group_get_glob_num_groups(void);
441
442 u32 mali_group_dump_state(struct mali_group *group, char *buf, u32 size);
443
444
445 _mali_osk_errcode_t mali_group_upper_half_mmu(void *data);
446 _mali_osk_errcode_t mali_group_upper_half_gp(void *data);
447 _mali_osk_errcode_t mali_group_upper_half_pp(void *data);
448
449 MALI_STATIC_INLINE mali_bool mali_group_is_empty(struct mali_group *group)
450 {
451         MALI_DEBUG_ASSERT_POINTER(group);
452         MALI_DEBUG_ASSERT(mali_group_is_virtual(group));
453         MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
454         return _mali_osk_list_empty(&group->group_list);
455 }
456
457 #endif /* __MALI_GROUP_H__ */