xref: /OK3568_Linux_fs/kernel/drivers/gpu/arm/mali400/mali/common/mali_group.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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