1 /*
2 * Copyright (C) 2011-2017 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_dump_status(struct mali_group *group);
100
101 void mali_group_delete(struct mali_group *group);
102
103 _mali_osk_errcode_t mali_group_add_mmu_core(struct mali_group *group,
104 struct mali_mmu_core *mmu_core);
105 void mali_group_remove_mmu_core(struct mali_group *group);
106
107 _mali_osk_errcode_t mali_group_add_gp_core(struct mali_group *group,
108 struct mali_gp_core *gp_core);
109 void mali_group_remove_gp_core(struct mali_group *group);
110
111 _mali_osk_errcode_t mali_group_add_pp_core(struct mali_group *group,
112 struct mali_pp_core *pp_core);
113 void mali_group_remove_pp_core(struct mali_group *group);
114
mali_group_core_description(struct mali_group * group)115 MALI_STATIC_INLINE const char *mali_group_core_description(
116 struct mali_group *group)
117 {
118 MALI_DEBUG_ASSERT_POINTER(group);
119 if (NULL != group->pp_core) {
120 return mali_pp_core_description(group->pp_core);
121 } else {
122 MALI_DEBUG_ASSERT_POINTER(group->gp_core);
123 return mali_gp_core_description(group->gp_core);
124 }
125 }
126
mali_group_is_virtual(struct mali_group * group)127 MALI_STATIC_INLINE mali_bool mali_group_is_virtual(struct mali_group *group)
128 {
129 MALI_DEBUG_ASSERT_POINTER(group);
130
131 #if (defined(CONFIG_MALI450) || defined(CONFIG_MALI470))
132 return (NULL != group->dlbu_core);
133 #else
134 return MALI_FALSE;
135 #endif
136 }
137
138 /** @brief Check if a group is a part of a virtual group or not
139 */
mali_group_is_in_virtual(struct mali_group * group)140 MALI_STATIC_INLINE mali_bool mali_group_is_in_virtual(struct mali_group *group)
141 {
142 MALI_DEBUG_ASSERT_POINTER(group);
143 MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
144
145 #if (defined(CONFIG_MALI450) || defined(CONFIG_MALI470))
146 return (NULL != group->parent_group) ? MALI_TRUE : MALI_FALSE;
147 #else
148 return MALI_FALSE;
149 #endif
150 }
151
152 /** @brief Reset group
153 *
154 * This function will reset the entire group,
155 * including all the cores present in the group.
156 *
157 * @param group Pointer to the group to reset
158 */
159 void mali_group_reset(struct mali_group *group);
160
mali_group_get_session(struct mali_group * group)161 MALI_STATIC_INLINE struct mali_session_data *mali_group_get_session(
162 struct mali_group *group)
163 {
164 MALI_DEBUG_ASSERT_POINTER(group);
165 MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
166
167 return group->session;
168 }
169
mali_group_clear_session(struct mali_group * group)170 MALI_STATIC_INLINE void mali_group_clear_session(struct mali_group *group)
171 {
172 MALI_DEBUG_ASSERT_POINTER(group);
173 MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
174
175 if (NULL != group->session) {
176 mali_mmu_activate_empty_page_directory(group->mmu);
177 group->session = NULL;
178 }
179 }
180
181 enum mali_group_state mali_group_activate(struct mali_group *group);
182
183 /*
184 * Change state from ACTIVATION_PENDING to ACTIVE
185 * For virtual group, all childs need to be ACTIVE first
186 */
187 mali_bool mali_group_set_active(struct mali_group *group);
188
189 /*
190 * @return MALI_TRUE means one or more domains can now be powered off,
191 * and caller should call either mali_pm_update_async() or
192 * mali_pm_update_sync() in order to do so.
193 */
194 mali_bool mali_group_deactivate(struct mali_group *group);
195
mali_group_get_state(struct mali_group * group)196 MALI_STATIC_INLINE enum mali_group_state mali_group_get_state(struct mali_group *group)
197 {
198 MALI_DEBUG_ASSERT_POINTER(group);
199 MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
200 return group->state;
201 }
202
mali_group_power_is_on(struct mali_group * group)203 MALI_STATIC_INLINE mali_bool mali_group_power_is_on(struct mali_group *group)
204 {
205 MALI_DEBUG_ASSERT_POINTER(group);
206 return group->power_is_on;
207 }
208
209 void mali_group_power_up(struct mali_group *group);
210 void mali_group_power_down(struct mali_group *group);
211
mali_group_set_disable_request(struct mali_group * group,mali_bool disable)212 MALI_STATIC_INLINE void mali_group_set_disable_request(
213 struct mali_group *group, mali_bool disable)
214 {
215 MALI_DEBUG_ASSERT_POINTER(group);
216 MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
217 group->disable_requested = disable;
218
219 /**
220 * When one of child group's disable_requeset is set TRUE, then
221 * the disable_request of parent group should also be set to TRUE.
222 * While, the disable_request of parent group should only be set to FALSE
223 * only when all of its child group's disable_request are set to FALSE.
224 */
225 if (NULL != group->parent_group && MALI_TRUE == disable) {
226 group->parent_group->disable_requested = disable;
227 }
228 }
229
mali_group_disable_requested(struct mali_group * group)230 MALI_STATIC_INLINE mali_bool mali_group_disable_requested(
231 struct mali_group *group)
232 {
233 MALI_DEBUG_ASSERT_POINTER(group);
234 MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
235 return group->disable_requested;
236 }
237
238 /** @brief Virtual groups */
239 void mali_group_add_group(struct mali_group *parent, struct mali_group *child);
240 struct mali_group *mali_group_acquire_group(struct mali_group *parent);
241 void mali_group_remove_group(struct mali_group *parent, struct mali_group *child);
242
243 /** @brief Checks if the group is working.
244 */
mali_group_is_working(struct mali_group * group)245 MALI_STATIC_INLINE mali_bool mali_group_is_working(struct mali_group *group)
246 {
247 MALI_DEBUG_ASSERT_POINTER(group);
248 MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
249 if (mali_group_is_in_virtual(group)) {
250 struct mali_group *tmp_group = mali_executor_get_virtual_group();
251 return tmp_group->is_working;
252 }
253 return group->is_working;
254 }
255
mali_group_get_running_gp_job(struct mali_group * group)256 MALI_STATIC_INLINE struct mali_gp_job *mali_group_get_running_gp_job(struct mali_group *group)
257 {
258 MALI_DEBUG_ASSERT_POINTER(group);
259 MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
260 return group->gp_running_job;
261 }
262
263 /** @brief Zap MMU TLB on all groups
264 *
265 * Zap TLB on group if \a session is active.
266 */
267 mali_bool mali_group_zap_session(struct mali_group *group,
268 struct mali_session_data *session);
269
270 /** @brief Get pointer to GP core object
271 */
mali_group_get_gp_core(struct mali_group * group)272 MALI_STATIC_INLINE struct mali_gp_core *mali_group_get_gp_core(struct mali_group *group)
273 {
274 MALI_DEBUG_ASSERT_POINTER(group);
275 return group->gp_core;
276 }
277
278 /** @brief Get pointer to PP core object
279 */
mali_group_get_pp_core(struct mali_group * group)280 MALI_STATIC_INLINE struct mali_pp_core *mali_group_get_pp_core(struct mali_group *group)
281 {
282 MALI_DEBUG_ASSERT_POINTER(group);
283 return group->pp_core;
284 }
285
286 /** @brief Start GP job
287 */
288 void mali_group_start_gp_job(struct mali_group *group, struct mali_gp_job *job, mali_bool gpu_secure_mode_pre_enabled);
289
290 void mali_group_start_pp_job(struct mali_group *group, struct mali_pp_job *job, u32 sub_job, mali_bool gpu_secure_mode_pre_enabled);
291
292 /** @brief Start virtual group Job on a virtual group
293 */
294 void mali_group_start_job_on_virtual(struct mali_group *group, struct mali_pp_job *job, u32 first_subjob, u32 last_subjob);
295
296
297 /** @brief Start a subjob from a particular on a specific PP group
298 */
299 void mali_group_start_job_on_group(struct mali_group *group, struct mali_pp_job *job, u32 subjob);
300
301
302 /** @brief remove all the unused groups in tmp_unused group list, so that the group is in consistent status.
303 */
304 void mali_group_non_dlbu_job_done_virtual(struct mali_group *group);
305
306
307 /** @brief Resume GP job that suspended waiting for more heap memory
308 */
309 void mali_group_resume_gp_with_new_heap(struct mali_group *group, u32 job_id, u32 start_addr, u32 end_addr);
310
mali_group_get_interrupt_result_gp(struct mali_group * group)311 MALI_STATIC_INLINE enum mali_interrupt_result mali_group_get_interrupt_result_gp(struct mali_group *group)
312 {
313 MALI_DEBUG_ASSERT_POINTER(group);
314 MALI_DEBUG_ASSERT_POINTER(group->gp_core);
315 MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
316 return mali_gp_get_interrupt_result(group->gp_core);
317 }
318
mali_group_get_interrupt_result_pp(struct mali_group * group)319 MALI_STATIC_INLINE enum mali_interrupt_result mali_group_get_interrupt_result_pp(struct mali_group *group)
320 {
321 MALI_DEBUG_ASSERT_POINTER(group);
322 MALI_DEBUG_ASSERT_POINTER(group->pp_core);
323 MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
324 return mali_pp_get_interrupt_result(group->pp_core);
325 }
326
mali_group_get_interrupt_result_mmu(struct mali_group * group)327 MALI_STATIC_INLINE enum mali_interrupt_result mali_group_get_interrupt_result_mmu(struct mali_group *group)
328 {
329 MALI_DEBUG_ASSERT_POINTER(group);
330 MALI_DEBUG_ASSERT_POINTER(group->mmu);
331 MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
332 return mali_mmu_get_interrupt_result(group->mmu);
333 }
334
mali_group_gp_is_active(struct mali_group * group)335 MALI_STATIC_INLINE mali_bool mali_group_gp_is_active(struct mali_group *group)
336 {
337 MALI_DEBUG_ASSERT_POINTER(group);
338 MALI_DEBUG_ASSERT_POINTER(group->gp_core);
339 MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
340 return mali_gp_is_active(group->gp_core);
341 }
342
mali_group_pp_is_active(struct mali_group * group)343 MALI_STATIC_INLINE mali_bool mali_group_pp_is_active(struct mali_group *group)
344 {
345 MALI_DEBUG_ASSERT_POINTER(group);
346 MALI_DEBUG_ASSERT_POINTER(group->pp_core);
347 MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
348 return mali_pp_is_active(group->pp_core);
349 }
350
mali_group_has_timed_out(struct mali_group * group)351 MALI_STATIC_INLINE mali_bool mali_group_has_timed_out(struct mali_group *group)
352 {
353 unsigned long time_cost;
354 struct mali_group *tmp_group = group;
355
356 MALI_DEBUG_ASSERT_POINTER(group);
357 MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
358
359 /* if the group is in virtual need to use virtual_group's start time */
360 if (mali_group_is_in_virtual(group)) {
361 tmp_group = mali_executor_get_virtual_group();
362 }
363
364 time_cost = _mali_osk_time_tickcount() - tmp_group->start_time;
365 if (_mali_osk_time_mstoticks(mali_max_job_runtime) <= time_cost) {
366 /*
367 * current tick is at or after timeout end time,
368 * so this is a valid timeout
369 */
370 return MALI_TRUE;
371 } else {
372 /*
373 * Not a valid timeout. A HW interrupt probably beat
374 * us to it, and the timer wasn't properly deleted
375 * (async deletion used due to atomic context).
376 */
377 return MALI_FALSE;
378 }
379 }
380
mali_group_mask_all_interrupts_gp(struct mali_group * group)381 MALI_STATIC_INLINE void mali_group_mask_all_interrupts_gp(struct mali_group *group)
382 {
383 MALI_DEBUG_ASSERT_POINTER(group);
384 MALI_DEBUG_ASSERT_POINTER(group->gp_core);
385 MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
386 return mali_gp_mask_all_interrupts(group->gp_core);
387 }
388
mali_group_mask_all_interrupts_pp(struct mali_group * group)389 MALI_STATIC_INLINE void mali_group_mask_all_interrupts_pp(struct mali_group *group)
390 {
391 MALI_DEBUG_ASSERT_POINTER(group);
392 MALI_DEBUG_ASSERT_POINTER(group->pp_core);
393 MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
394 return mali_pp_mask_all_interrupts(group->pp_core);
395 }
396
mali_group_enable_interrupts_gp(struct mali_group * group,enum mali_interrupt_result exceptions)397 MALI_STATIC_INLINE void mali_group_enable_interrupts_gp(
398 struct mali_group *group,
399 enum mali_interrupt_result exceptions)
400 {
401 MALI_DEBUG_ASSERT_POINTER(group);
402 MALI_DEBUG_ASSERT_POINTER(group->gp_core);
403 MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
404 mali_gp_enable_interrupts(group->gp_core, exceptions);
405 }
406
mali_group_schedule_bottom_half_gp(struct mali_group * group)407 MALI_STATIC_INLINE void mali_group_schedule_bottom_half_gp(struct mali_group *group)
408 {
409 MALI_DEBUG_ASSERT_POINTER(group);
410 MALI_DEBUG_ASSERT_POINTER(group->gp_core);
411 _mali_osk_wq_schedule_work(group->bottom_half_work_gp);
412 }
413
414
mali_group_schedule_bottom_half_pp(struct mali_group * group)415 MALI_STATIC_INLINE void mali_group_schedule_bottom_half_pp(struct mali_group *group)
416 {
417 MALI_DEBUG_ASSERT_POINTER(group);
418 MALI_DEBUG_ASSERT_POINTER(group->pp_core);
419 _mali_osk_wq_schedule_work(group->bottom_half_work_pp);
420 }
421
mali_group_schedule_bottom_half_mmu(struct mali_group * group)422 MALI_STATIC_INLINE void mali_group_schedule_bottom_half_mmu(struct mali_group *group)
423 {
424 MALI_DEBUG_ASSERT_POINTER(group);
425 MALI_DEBUG_ASSERT_POINTER(group->mmu);
426 _mali_osk_wq_schedule_work(group->bottom_half_work_mmu);
427 }
428
429 struct mali_pp_job *mali_group_complete_pp(struct mali_group *group, mali_bool success, u32 *sub_job);
430
431 struct mali_gp_job *mali_group_complete_gp(struct mali_group *group, mali_bool success);
432
433 #if defined(CONFIG_MALI400_PROFILING)
mali_group_oom(struct mali_group * group)434 MALI_STATIC_INLINE void mali_group_oom(struct mali_group *group)
435 {
436 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SUSPEND |
437 MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0),
438 0, 0, 0, 0, 0);
439 }
440 #endif
441
442 struct mali_group *mali_group_get_glob_group(u32 index);
443 u32 mali_group_get_glob_num_groups(void);
444
445 u32 mali_group_dump_state(struct mali_group *group, char *buf, u32 size);
446
447
448 _mali_osk_errcode_t mali_group_upper_half_mmu(void *data);
449 _mali_osk_errcode_t mali_group_upper_half_gp(void *data);
450 _mali_osk_errcode_t mali_group_upper_half_pp(void *data);
451
mali_group_is_empty(struct mali_group * group)452 MALI_STATIC_INLINE mali_bool mali_group_is_empty(struct mali_group *group)
453 {
454 MALI_DEBUG_ASSERT_POINTER(group);
455 MALI_DEBUG_ASSERT(mali_group_is_virtual(group));
456 MALI_DEBUG_ASSERT_EXECUTOR_LOCK_HELD();
457 return _mali_osk_list_empty(&group->group_list);
458 }
459
460 #endif /* __MALI_GROUP_H__ */
461