2 * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
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.
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.
11 #include "mali_kernel_common.h"
12 #include "mali_group.h"
14 #include "mali_l2_cache.h"
18 #include "mali_dlbu.h"
19 #include "mali_broadcast.h"
20 #include "mali_gp_scheduler.h"
21 #include "mali_pp_scheduler.h"
22 #include "mali_kernel_core.h"
23 #include "mali_osk_profiling.h"
25 static void mali_group_bottom_half_mmu(void *data);
26 static void mali_group_bottom_half_gp(void *data);
27 static void mali_group_bottom_half_pp(void *data);
29 static void mali_group_timeout(void *data);
30 static void mali_group_reset_pp(struct mali_group *group);
32 #if defined(CONFIG_MALI400_PROFILING)
33 static void mali_group_report_l2_cache_counters_per_core(struct mali_group *group, u32 core_num);
34 #endif /* #if defined(CONFIG_MALI400_PROFILING) */
37 * The group object is the most important object in the device driver,
38 * and acts as the center of many HW operations.
39 * The reason for this is that operations on the MMU will affect all
40 * cores connected to this MMU (a group is defined by the MMU and the
41 * cores which are connected to this).
42 * The group lock is thus the most important lock, followed by the
43 * GP and PP scheduler locks. They must be taken in the following
45 * GP/PP lock first, then group lock(s).
48 static struct mali_group *mali_global_groups[MALI_MAX_NUMBER_OF_GROUPS];
49 static u32 mali_global_num_groups = 0;
51 enum mali_group_activate_pd_status
53 MALI_GROUP_ACTIVATE_PD_STATUS_FAILED,
54 MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD,
55 MALI_GROUP_ACTIVATE_PD_STATUS_OK_SWITCHED_PD,
58 /* local helper functions */
59 static enum mali_group_activate_pd_status mali_group_activate_page_directory(struct mali_group *group, struct mali_session_data *session);
60 static void mali_group_deactivate_page_directory(struct mali_group *group, struct mali_session_data *session);
61 static void mali_group_remove_session_if_unused(struct mali_group *group, struct mali_session_data *session);
62 static void mali_group_recovery_reset(struct mali_group *group);
63 static void mali_group_mmu_page_fault(struct mali_group *group);
65 static void mali_group_post_process_job_pp(struct mali_group *group);
66 static void mali_group_post_process_job_gp(struct mali_group *group, mali_bool suspend);
68 void mali_group_lock(struct mali_group *group)
70 if(_MALI_OSK_ERR_OK != _mali_osk_lock_wait(group->lock, _MALI_OSK_LOCKMODE_RW))
72 /* Non-interruptable lock failed: this should never happen. */
75 MALI_DEBUG_PRINT(5, ("Mali group: Group lock taken 0x%08X\n", group));
78 void mali_group_unlock(struct mali_group *group)
80 MALI_DEBUG_PRINT(5, ("Mali group: Releasing group lock 0x%08X\n", group));
81 _mali_osk_lock_signal(group->lock, _MALI_OSK_LOCKMODE_RW);
85 void mali_group_assert_locked(struct mali_group *group)
87 MALI_DEBUG_ASSERT_LOCK_HELD(group->lock);
92 struct mali_group *mali_group_create(struct mali_l2_cache_core *core, struct mali_dlbu_core *dlbu, struct mali_bcast_unit *bcast)
94 struct mali_group *group = NULL;
95 _mali_osk_lock_flags_t lock_flags;
97 #if defined(MALI_UPPER_HALF_SCHEDULING)
98 lock_flags = _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE;
100 lock_flags = _MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE;
103 if (mali_global_num_groups >= MALI_MAX_NUMBER_OF_GROUPS)
105 MALI_PRINT_ERROR(("Mali group: Too many group objects created\n"));
109 group = _mali_osk_calloc(1, sizeof(struct mali_group));
112 group->timeout_timer = _mali_osk_timer_init();
114 if (NULL != group->timeout_timer)
116 _mali_osk_lock_order_t order;
117 _mali_osk_timer_setcallback(group->timeout_timer, mali_group_timeout, (void *)group);
121 order = _MALI_OSK_LOCK_ORDER_GROUP_VIRTUAL;
125 order = _MALI_OSK_LOCK_ORDER_GROUP;
128 group->lock = _mali_osk_lock_init(lock_flags, 0, order);
129 if (NULL != group->lock)
131 group->l2_cache_core[0] = core;
132 group->session = NULL;
133 group->page_dir_ref_count = 0;
134 group->power_is_on = MALI_TRUE;
135 group->state = MALI_GROUP_STATE_IDLE;
136 _mali_osk_list_init(&group->group_list);
137 _mali_osk_list_init(&group->pp_scheduler_list);
138 group->parent_group = NULL;
139 group->l2_cache_core_ref_count[0] = 0;
140 group->l2_cache_core_ref_count[1] = 0;
141 group->bcast_core = bcast;
142 group->dlbu_core = dlbu;
144 mali_global_groups[mali_global_num_groups] = group;
145 mali_global_num_groups++;
149 _mali_osk_timer_term(group->timeout_timer);
151 _mali_osk_free(group);
157 _mali_osk_errcode_t mali_group_add_mmu_core(struct mali_group *group, struct mali_mmu_core* mmu_core)
159 /* This group object now owns the MMU core object */
160 group->mmu= mmu_core;
161 group->bottom_half_work_mmu = _mali_osk_wq_create_work(mali_group_bottom_half_mmu, group);
162 if (NULL == group->bottom_half_work_mmu)
164 return _MALI_OSK_ERR_FAULT;
166 return _MALI_OSK_ERR_OK;
169 void mali_group_remove_mmu_core(struct mali_group *group)
171 /* This group object no longer owns the MMU core object */
173 if (NULL != group->bottom_half_work_mmu)
175 _mali_osk_wq_delete_work(group->bottom_half_work_mmu);
179 _mali_osk_errcode_t mali_group_add_gp_core(struct mali_group *group, struct mali_gp_core* gp_core)
181 /* This group object now owns the GP core object */
182 group->gp_core = gp_core;
183 group->bottom_half_work_gp = _mali_osk_wq_create_work(mali_group_bottom_half_gp, group);
184 if (NULL == group->bottom_half_work_gp)
186 return _MALI_OSK_ERR_FAULT;
188 return _MALI_OSK_ERR_OK;
191 void mali_group_remove_gp_core(struct mali_group *group)
193 /* This group object no longer owns the GP core object */
194 group->gp_core = NULL;
195 if (NULL != group->bottom_half_work_gp)
197 _mali_osk_wq_delete_work(group->bottom_half_work_gp);
201 _mali_osk_errcode_t mali_group_add_pp_core(struct mali_group *group, struct mali_pp_core* pp_core)
203 /* This group object now owns the PP core object */
204 group->pp_core = pp_core;
205 group->bottom_half_work_pp = _mali_osk_wq_create_work(mali_group_bottom_half_pp, group);
206 if (NULL == group->bottom_half_work_pp)
208 return _MALI_OSK_ERR_FAULT;
210 return _MALI_OSK_ERR_OK;
213 void mali_group_remove_pp_core(struct mali_group *group)
215 /* This group object no longer owns the PP core object */
216 group->pp_core = NULL;
217 if (NULL != group->bottom_half_work_pp)
219 _mali_osk_wq_delete_work(group->bottom_half_work_pp);
223 void mali_group_delete(struct mali_group *group)
227 MALI_DEBUG_PRINT(4, ("Deleting group %p\n", group));
229 MALI_DEBUG_ASSERT(NULL == group->parent_group);
231 /* Delete the resources that this group owns */
232 if (NULL != group->gp_core)
234 mali_gp_delete(group->gp_core);
237 if (NULL != group->pp_core)
239 mali_pp_delete(group->pp_core);
242 if (NULL != group->mmu)
244 mali_mmu_delete(group->mmu);
247 if (mali_group_is_virtual(group))
249 /* Remove all groups from virtual group */
250 struct mali_group *child;
251 struct mali_group *temp;
253 _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list)
255 child->parent_group = NULL;
256 mali_group_delete(child);
259 mali_dlbu_delete(group->dlbu_core);
261 if (NULL != group->bcast_core)
263 mali_bcast_unit_delete(group->bcast_core);
267 for (i = 0; i < MALI_MAX_NUMBER_OF_GROUPS; i++)
269 if (mali_global_groups[i] == group)
271 mali_global_groups[i] = NULL;
272 mali_global_num_groups--;
274 if (i != mali_global_num_groups)
276 /* We removed a group from the middle of the array -- move the last
277 * group to the current position to close the gap */
278 mali_global_groups[i] = mali_global_groups[mali_global_num_groups];
279 mali_global_groups[mali_global_num_groups] = NULL;
286 if (NULL != group->timeout_timer)
288 _mali_osk_timer_del(group->timeout_timer);
289 _mali_osk_timer_term(group->timeout_timer);
292 if (NULL != group->bottom_half_work_mmu)
294 _mali_osk_wq_delete_work(group->bottom_half_work_mmu);
297 if (NULL != group->bottom_half_work_gp)
299 _mali_osk_wq_delete_work(group->bottom_half_work_gp);
302 if (NULL != group->bottom_half_work_pp)
304 _mali_osk_wq_delete_work(group->bottom_half_work_pp);
307 _mali_osk_lock_term(group->lock);
309 _mali_osk_free(group);
312 MALI_DEBUG_CODE(static void mali_group_print_virtual(struct mali_group *vgroup)
315 struct mali_group *group;
316 struct mali_group *temp;
318 MALI_DEBUG_PRINT(4, ("Virtual group %p\n", vgroup));
319 MALI_DEBUG_PRINT(4, ("l2_cache_core[0] = %p, ref = %d\n", vgroup->l2_cache_core[0], vgroup->l2_cache_core_ref_count[0]));
320 MALI_DEBUG_PRINT(4, ("l2_cache_core[1] = %p, ref = %d\n", vgroup->l2_cache_core[1], vgroup->l2_cache_core_ref_count[1]));
323 _MALI_OSK_LIST_FOREACHENTRY(group, temp, &vgroup->group_list, struct mali_group, group_list)
325 MALI_DEBUG_PRINT(4, ("[%d] %p, l2_cache_core[0] = %p\n", i, group, group->l2_cache_core[0]));
331 * @brief Add child group to virtual group parent
333 * Before calling this function, child must have it's state set to JOINING_VIRTUAL
334 * to ensure it's not touched during the transition period. When this function returns,
335 * child's state will be IN_VIRTUAL.
337 void mali_group_add_group(struct mali_group *parent, struct mali_group *child)
342 MALI_DEBUG_PRINT(3, ("Adding group %p to virtual group %p\n", child, parent));
344 MALI_ASSERT_GROUP_LOCKED(parent);
346 MALI_DEBUG_ASSERT(mali_group_is_virtual(parent));
347 MALI_DEBUG_ASSERT(!mali_group_is_virtual(child));
348 MALI_DEBUG_ASSERT(NULL == child->parent_group);
349 MALI_DEBUG_ASSERT(MALI_GROUP_STATE_JOINING_VIRTUAL == child->state);
351 _mali_osk_list_addtail(&child->group_list, &parent->group_list);
353 child->state = MALI_GROUP_STATE_IN_VIRTUAL;
354 child->parent_group = parent;
356 MALI_DEBUG_ASSERT_POINTER(child->l2_cache_core[0]);
358 MALI_DEBUG_PRINT(4, ("parent->l2_cache_core: [0] = %p, [1] = %p\n", parent->l2_cache_core[0], parent->l2_cache_core[1]));
359 MALI_DEBUG_PRINT(4, ("child->l2_cache_core: [0] = %p, [1] = %p\n", child->l2_cache_core[0], child->l2_cache_core[1]));
361 /* Keep track of the L2 cache cores of child groups */
363 for (i = 0; i < 2; i++)
365 if (parent->l2_cache_core[i] == child->l2_cache_core[0])
367 MALI_DEBUG_ASSERT(parent->l2_cache_core_ref_count[i] > 0);
368 parent->l2_cache_core_ref_count[i]++;
375 /* First time we see this L2 cache, add it to our list */
376 i = (NULL == parent->l2_cache_core[0]) ? 0 : 1;
378 MALI_DEBUG_PRINT(4, ("First time we see l2_cache %p. Adding to [%d] = %p\n", child->l2_cache_core[0], i, parent->l2_cache_core[i]));
380 MALI_DEBUG_ASSERT(NULL == parent->l2_cache_core[i]);
382 parent->l2_cache_core[i] = child->l2_cache_core[0];
383 parent->l2_cache_core_ref_count[i]++;
386 /* Update Broadcast Unit and DLBU */
387 mali_bcast_add_group(parent->bcast_core, child);
388 mali_dlbu_add_group(parent->dlbu_core, child);
391 MALI_DEBUG_ASSERT(0 == child->page_dir_ref_count);
392 if (parent->session == child->session)
394 mali_mmu_zap_tlb(child->mmu);
398 child->session = NULL;
400 if (NULL == parent->session)
402 mali_mmu_activate_empty_page_directory(child->mmu);
407 mali_bool activate_success = mali_mmu_activate_page_directory(child->mmu,
408 mali_session_get_page_directory(parent->session));
409 MALI_DEBUG_ASSERT(activate_success);
410 MALI_IGNORE(activate_success);
413 child->session = NULL;
415 /* Start job on child when parent is active */
416 if (NULL != parent->pp_running_job)
418 struct mali_pp_job *job = parent->pp_running_job;
419 MALI_DEBUG_PRINT(3, ("Group %x joining running job %d on virtual group %x\n",
420 child, mali_pp_job_get_id(job), parent));
421 MALI_DEBUG_ASSERT(MALI_GROUP_STATE_WORKING == parent->state);
422 mali_pp_job_start(child->pp_core, job, mali_pp_core_get_id(child->pp_core), MALI_TRUE);
424 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|
425 MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(child->pp_core))|
426 MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH,
427 mali_pp_job_get_frame_builder_id(job), mali_pp_job_get_flush_id(job), 0, 0, 0);
429 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|
430 MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(child->pp_core))|
431 MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL,
432 mali_pp_job_get_pid(job), mali_pp_job_get_tid(job), 0, 0, 0);
435 MALI_DEBUG_CODE(mali_group_print_virtual(parent);)
439 * @brief Remove child group from virtual group parent
441 * After the child is removed, it's state will be LEAVING_VIRTUAL and must be set
442 * to IDLE before it can be used.
444 void mali_group_remove_group(struct mali_group *parent, struct mali_group *child)
448 MALI_ASSERT_GROUP_LOCKED(parent);
450 MALI_DEBUG_PRINT(3, ("Removing group %p from virtual group %p\n", child, parent));
452 MALI_DEBUG_ASSERT(mali_group_is_virtual(parent));
453 MALI_DEBUG_ASSERT(!mali_group_is_virtual(child));
454 MALI_DEBUG_ASSERT(parent == child->parent_group);
455 MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IN_VIRTUAL == child->state);
456 /* Removing groups while running is not yet supported. */
457 MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IDLE == parent->state);
459 mali_group_lock(child);
461 /* Update Broadcast Unit and DLBU */
462 mali_bcast_remove_group(parent->bcast_core, child);
463 mali_dlbu_remove_group(parent->dlbu_core, child);
465 _mali_osk_list_delinit(&child->group_list);
467 child->session = parent->session;
468 child->parent_group = NULL;
469 child->state = MALI_GROUP_STATE_LEAVING_VIRTUAL;
471 /* Keep track of the L2 cache cores of child groups */
472 i = (child->l2_cache_core[0] == parent->l2_cache_core[0]) ? 0 : 1;
474 MALI_DEBUG_ASSERT(child->l2_cache_core[0] == parent->l2_cache_core[i]);
476 parent->l2_cache_core_ref_count[i]--;
478 if (parent->l2_cache_core_ref_count[i] == 0)
480 parent->l2_cache_core[i] = NULL;
483 MALI_DEBUG_CODE(mali_group_print_virtual(parent));
485 mali_group_unlock(child);
488 struct mali_group *mali_group_acquire_group(struct mali_group *parent)
490 struct mali_group *child;
492 MALI_ASSERT_GROUP_LOCKED(parent);
494 MALI_DEBUG_ASSERT(mali_group_is_virtual(parent));
495 MALI_DEBUG_ASSERT(!_mali_osk_list_empty(&parent->group_list));
497 child = _MALI_OSK_LIST_ENTRY(parent->group_list.prev, struct mali_group, group_list);
499 mali_group_remove_group(parent, child);
504 void mali_group_reset(struct mali_group *group)
507 * This function should not be used to abort jobs,
508 * currently only called during insmod and PM resume
510 MALI_DEBUG_ASSERT(NULL == group->gp_running_job);
511 MALI_DEBUG_ASSERT(NULL == group->pp_running_job);
513 mali_group_lock(group);
515 group->session = NULL;
517 if (NULL != group->mmu)
519 mali_mmu_reset(group->mmu);
522 if (NULL != group->gp_core)
524 mali_gp_reset(group->gp_core);
527 if (NULL != group->pp_core)
529 mali_group_reset_pp(group);
532 mali_group_unlock(group);
535 struct mali_gp_core* mali_group_get_gp_core(struct mali_group *group)
537 return group->gp_core;
540 struct mali_pp_core* mali_group_get_pp_core(struct mali_group *group)
542 return group->pp_core;
545 _mali_osk_errcode_t mali_group_start_gp_job(struct mali_group *group, struct mali_gp_job *job)
547 struct mali_session_data *session;
548 enum mali_group_activate_pd_status activate_status;
550 MALI_ASSERT_GROUP_LOCKED(group);
551 MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IDLE == group->state);
553 session = mali_gp_job_get_session(job);
555 if (NULL != group->l2_cache_core[0])
557 mali_l2_cache_invalidate_all_conditional(group->l2_cache_core[0], mali_gp_job_get_id(job));
560 activate_status = mali_group_activate_page_directory(group, session);
561 if (MALI_GROUP_ACTIVATE_PD_STATUS_FAILED != activate_status)
563 /* if session is NOT kept Zapping is done as part of session switch */
564 if (MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD == activate_status)
566 mali_mmu_zap_tlb_without_stall(group->mmu);
568 mali_gp_job_start(group->gp_core, job);
570 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
571 MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0) |
572 MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH,
573 mali_gp_job_get_frame_builder_id(job), mali_gp_job_get_flush_id(job), 0, 0, 0);
574 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START |
575 MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0),
576 mali_gp_job_get_pid(job), mali_gp_job_get_tid(job), 0, 0, 0);
577 #if defined(CONFIG_MALI400_PROFILING)
578 if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[0])) &&
579 (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[0])))
580 mali_group_report_l2_cache_counters_per_core(group, 0);
581 #endif /* #if defined(CONFIG_MALI400_PROFILING) */
583 group->gp_running_job = job;
584 group->state = MALI_GROUP_STATE_WORKING;
586 /* Setup the timeout timer value and save the job id for the job running on the gp core */
587 _mali_osk_timer_mod(group->timeout_timer, _mali_osk_time_mstoticks(mali_max_job_runtime));
589 return _MALI_OSK_ERR_OK;
592 return _MALI_OSK_ERR_FAULT;
595 _mali_osk_errcode_t mali_group_start_pp_job(struct mali_group *group, struct mali_pp_job *job, u32 sub_job)
597 struct mali_session_data *session;
598 enum mali_group_activate_pd_status activate_status;
600 MALI_ASSERT_GROUP_LOCKED(group);
601 MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IDLE == group->state);
603 session = mali_pp_job_get_session(job);
605 if (NULL != group->l2_cache_core[0])
607 mali_l2_cache_invalidate_all_conditional(group->l2_cache_core[0], mali_pp_job_get_id(job));
610 if (NULL != group->l2_cache_core[1])
612 mali_l2_cache_invalidate_all_conditional(group->l2_cache_core[1], mali_pp_job_get_id(job));
615 activate_status = mali_group_activate_page_directory(group, session);
616 if (MALI_GROUP_ACTIVATE_PD_STATUS_FAILED != activate_status)
618 /* if session is NOT kept Zapping is done as part of session switch */
619 if (MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD == activate_status)
621 MALI_DEBUG_PRINT(3, ("PP starting job PD_Switch 0 Flush 1 Zap 1\n"));
622 mali_mmu_zap_tlb_without_stall(group->mmu);
625 if (mali_group_is_virtual(group))
627 struct mali_group *child;
628 struct mali_group *temp;
631 /* Configure DLBU for the job */
632 mali_dlbu_config_job(group->dlbu_core, job);
634 /* Write stack address for each child group */
635 _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list)
637 mali_pp_write_addr_stack(child->pp_core, job);
642 mali_pp_job_start(group->pp_core, job, sub_job, MALI_FALSE);
644 /* if the group is virtual, loop through physical groups which belong to this group
645 * and call profiling events for its cores as virtual */
646 if (MALI_TRUE == mali_group_is_virtual(group))
648 struct mali_group *child;
649 struct mali_group *temp;
651 _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list)
653 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|
654 MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(child->pp_core))|
655 MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH,
656 mali_pp_job_get_frame_builder_id(job), mali_pp_job_get_flush_id(job), 0, 0, 0);
658 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|
659 MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(child->pp_core))|
660 MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL,
661 mali_pp_job_get_pid(job), mali_pp_job_get_tid(job), 0, 0, 0);
663 #if defined(CONFIG_MALI400_PROFILING)
664 if (0 != group->l2_cache_core_ref_count[0])
666 if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[0])) &&
667 (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[0])))
669 mali_group_report_l2_cache_counters_per_core(group, mali_l2_cache_get_id(group->l2_cache_core[0]));
672 if (0 != group->l2_cache_core_ref_count[1])
674 if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[1])) &&
675 (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[1])))
677 mali_group_report_l2_cache_counters_per_core(group, mali_l2_cache_get_id(group->l2_cache_core[1]));
680 #endif /* #if defined(CONFIG_MALI400_PROFILING) */
682 else /* group is physical - call profiling events for physical cores */
684 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|
685 MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(group->pp_core))|
686 MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH,
687 mali_pp_job_get_frame_builder_id(job), mali_pp_job_get_flush_id(job), 0, 0, 0);
689 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|
690 MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(group->pp_core))|
691 MALI_PROFILING_EVENT_REASON_START_STOP_HW_PHYSICAL,
692 mali_pp_job_get_pid(job), mali_pp_job_get_tid(job), 0, 0, 0);
693 #if defined(CONFIG_MALI400_PROFILING)
694 if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[0])) &&
695 (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[0])))
697 mali_group_report_l2_cache_counters_per_core(group, mali_l2_cache_get_id(group->l2_cache_core[0]));
699 #endif /* #if defined(CONFIG_MALI400_PROFILING) */
701 group->pp_running_job = job;
702 group->pp_running_sub_job = sub_job;
703 group->state = MALI_GROUP_STATE_WORKING;
705 /* Setup the timeout timer value and save the job id for the job running on the pp core */
706 _mali_osk_timer_mod(group->timeout_timer, _mali_osk_time_mstoticks(mali_max_job_runtime));
708 return _MALI_OSK_ERR_OK;
711 return _MALI_OSK_ERR_FAULT;
714 struct mali_gp_job *mali_group_resume_gp_with_new_heap(struct mali_group *group, u32 job_id, u32 start_addr, u32 end_addr)
716 MALI_ASSERT_GROUP_LOCKED(group);
718 if (group->state != MALI_GROUP_STATE_OOM ||
719 mali_gp_job_get_id(group->gp_running_job) != job_id)
721 return NULL; /* Illegal request or job has already been aborted */
724 if (NULL != group->l2_cache_core[0])
726 mali_l2_cache_invalidate_all_force(group->l2_cache_core[0]);
729 mali_mmu_zap_tlb_without_stall(group->mmu);
731 mali_gp_resume_with_new_heap(group->gp_core, start_addr, end_addr);
733 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_RESUME|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), 0, 0, 0, 0, 0);
735 group->state = MALI_GROUP_STATE_WORKING;
737 return group->gp_running_job;
740 static void mali_group_reset_pp(struct mali_group *group)
742 struct mali_group *child;
743 struct mali_group *temp;
745 /* TODO: If we *know* that the group is idle, this could be faster. */
747 mali_pp_reset_async(group->pp_core);
749 // if (!mali_group_is_virtual(group) || NULL == group->pp_running_job) //LWJ
751 if (!mali_group_is_virtual(group) || NULL != group->pp_running_job)
753 /* This is a physical group or an idle virtual group -- simply wait for
754 * the reset to complete. */
755 mali_pp_reset_wait(group->pp_core);
757 else /* virtual group */
759 /* Loop through all members of this virtual group and wait until they
760 * are done resetting.
762 _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list)
764 mali_pp_reset_wait(child->pp_core);
769 static void mali_group_complete_pp(struct mali_group *group, mali_bool success)
771 struct mali_pp_job *pp_job_to_return;
772 u32 pp_sub_job_to_return;
774 MALI_DEBUG_ASSERT_POINTER(group->pp_core);
775 MALI_DEBUG_ASSERT_POINTER(group->pp_running_job);
776 MALI_ASSERT_GROUP_LOCKED(group);
778 mali_group_post_process_job_pp(group);
780 mali_pp_reset_async(group->pp_core);
782 pp_job_to_return = group->pp_running_job;
783 pp_sub_job_to_return = group->pp_running_sub_job;
784 group->state = MALI_GROUP_STATE_IDLE;
785 group->pp_running_job = NULL;
787 mali_group_deactivate_page_directory(group, group->session);
789 if (_MALI_OSK_ERR_OK != mali_pp_reset_wait(group->pp_core))
791 MALI_DEBUG_PRINT(3, ("Mali group: Failed to reset PP, need to reset entire group\n"));
793 mali_group_recovery_reset(group);
796 mali_pp_scheduler_job_done(group, pp_job_to_return, pp_sub_job_to_return, success);
799 static void mali_group_complete_gp(struct mali_group *group, mali_bool success)
801 struct mali_gp_job *gp_job_to_return;
803 MALI_DEBUG_ASSERT_POINTER(group->gp_core);
804 MALI_DEBUG_ASSERT_POINTER(group->gp_running_job);
805 MALI_ASSERT_GROUP_LOCKED(group);
807 mali_group_post_process_job_gp(group, MALI_FALSE);
809 mali_gp_reset_async(group->gp_core);
811 gp_job_to_return = group->gp_running_job;
812 group->state = MALI_GROUP_STATE_IDLE;
813 group->gp_running_job = NULL;
815 mali_group_deactivate_page_directory(group, group->session);
817 if (_MALI_OSK_ERR_OK != mali_gp_reset_wait(group->gp_core))
819 MALI_DEBUG_PRINT(3, ("Mali group: Failed to reset GP, need to reset entire group\n"));
821 mali_group_recovery_reset(group);
824 mali_gp_scheduler_job_done(group, gp_job_to_return, success);
827 void mali_group_abort_gp_job(struct mali_group *group, u32 job_id)
829 MALI_ASSERT_GROUP_LOCKED(group);
831 if (group->state == MALI_GROUP_STATE_IDLE ||
832 mali_gp_job_get_id(group->gp_running_job) != job_id)
834 return; /* No need to cancel or job has already been aborted or completed */
837 mali_group_complete_gp(group, MALI_FALSE);
840 static void mali_group_abort_pp_job(struct mali_group *group, u32 job_id)
842 MALI_ASSERT_GROUP_LOCKED(group);
844 if (group->state == MALI_GROUP_STATE_IDLE ||
845 mali_pp_job_get_id(group->pp_running_job) != job_id)
847 return; /* No need to cancel or job has already been aborted or completed */
850 mali_group_complete_pp(group, MALI_FALSE);
853 void mali_group_abort_session(struct mali_group *group, struct mali_session_data *session)
855 struct mali_gp_job *gp_job;
856 struct mali_pp_job *pp_job;
859 mali_bool abort_pp = MALI_FALSE;
860 mali_bool abort_gp = MALI_FALSE;
862 mali_group_lock(group);
864 if (mali_group_is_in_virtual(group))
866 /* Group is member of a virtual group, don't touch it! */
867 mali_group_unlock(group);
871 gp_job = group->gp_running_job;
872 pp_job = group->pp_running_job;
874 if ((NULL != gp_job) && (mali_gp_job_get_session(gp_job) == session))
876 MALI_DEBUG_PRINT(4, ("Aborting GP job 0x%08x from session 0x%08x\n", gp_job, session));
878 gp_job_id = mali_gp_job_get_id(gp_job);
879 abort_gp = MALI_TRUE;
882 if ((NULL != pp_job) && (mali_pp_job_get_session(pp_job) == session))
884 MALI_DEBUG_PRINT(4, ("Mali group: Aborting PP job 0x%08x from session 0x%08x\n", pp_job, session));
886 pp_job_id = mali_pp_job_get_id(pp_job);
887 abort_pp = MALI_TRUE;
890 // if (0 != abort_gp) //LWJ ORG
893 mali_group_abort_gp_job(group, gp_job_id);
895 // if (0 != abort_pp) //LWJ ORG
898 mali_group_abort_pp_job(group, pp_job_id);
901 mali_group_remove_session_if_unused(group, session);
903 mali_group_unlock(group);
906 struct mali_group *mali_group_get_glob_group(u32 index)
908 if(mali_global_num_groups > index)
910 return mali_global_groups[index];
916 u32 mali_group_get_glob_num_groups(void)
918 return mali_global_num_groups;
921 static enum mali_group_activate_pd_status mali_group_activate_page_directory(struct mali_group *group, struct mali_session_data *session)
923 enum mali_group_activate_pd_status retval;
924 MALI_ASSERT_GROUP_LOCKED(group);
926 MALI_DEBUG_PRINT(5, ("Mali group: Activating page directory 0x%08X from session 0x%08X on group 0x%08X\n", mali_session_get_page_directory(session), session, group));
927 MALI_DEBUG_ASSERT(0 <= group->page_dir_ref_count);
929 if (0 != group->page_dir_ref_count)
931 if (group->session != session)
933 MALI_DEBUG_PRINT(4, ("Mali group: Activating session FAILED: 0x%08x on group 0x%08X. Existing session: 0x%08x\n", session, group, group->session));
934 return MALI_GROUP_ACTIVATE_PD_STATUS_FAILED;
938 MALI_DEBUG_PRINT(4, ("Mali group: Activating session already activated: 0x%08x on group 0x%08X. New Ref: %d\n", session, group, 1+group->page_dir_ref_count));
939 retval = MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD;
945 /* There might be another session here, but it is ok to overwrite it since group->page_dir_ref_count==0 */
946 if (group->session != session)
948 mali_bool activate_success;
949 MALI_DEBUG_PRINT(5, ("Mali group: Activate session: %08x previous: %08x on group 0x%08X. Ref: %d\n", session, group->session, group, 1+group->page_dir_ref_count));
951 activate_success = mali_mmu_activate_page_directory(group->mmu, mali_session_get_page_directory(session));
952 MALI_DEBUG_ASSERT(activate_success);
953 if ( MALI_FALSE== activate_success ) return MALI_GROUP_ACTIVATE_PD_STATUS_FAILED;
954 group->session = session;
955 retval = MALI_GROUP_ACTIVATE_PD_STATUS_OK_SWITCHED_PD;
959 MALI_DEBUG_PRINT(4, ("Mali group: Activate existing session 0x%08X on group 0x%08X. Ref: %d\n", session->page_directory, group, 1+group->page_dir_ref_count));
960 retval = MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD;
964 group->page_dir_ref_count++;
968 static void mali_group_deactivate_page_directory(struct mali_group *group, struct mali_session_data *session)
970 MALI_ASSERT_GROUP_LOCKED(group);
972 MALI_DEBUG_ASSERT(0 < group->page_dir_ref_count);
973 MALI_DEBUG_ASSERT(session == group->session);
975 group->page_dir_ref_count--;
977 /* As an optimization, the MMU still points to the group->session even if (0 == group->page_dir_ref_count),
978 and we do not call mali_mmu_activate_empty_page_directory(group->mmu); */
979 MALI_DEBUG_ASSERT(0 <= group->page_dir_ref_count);
982 static void mali_group_remove_session_if_unused(struct mali_group *group, struct mali_session_data *session)
984 MALI_ASSERT_GROUP_LOCKED(group);
986 if (0 == group->page_dir_ref_count)
988 MALI_DEBUG_ASSERT(MALI_GROUP_STATE_WORKING != group->state);
990 if (group->session == session)
992 MALI_DEBUG_ASSERT(MALI_TRUE == group->power_is_on);
993 MALI_DEBUG_PRINT(3, ("Mali group: Deactivating unused session 0x%08X on group %08X\n", session, group));
994 mali_mmu_activate_empty_page_directory(group->mmu);
995 group->session = NULL;
1000 void mali_group_power_on(void)
1003 for (i = 0; i < mali_global_num_groups; i++)
1005 struct mali_group *group = mali_global_groups[i];
1006 mali_group_lock(group);
1007 MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IDLE == group->state);
1008 group->power_is_on = MALI_TRUE;
1010 if (NULL != group->l2_cache_core[0])
1012 mali_l2_cache_power_is_enabled_set(group->l2_cache_core[0], MALI_TRUE);
1015 if (NULL != group->l2_cache_core[1])
1017 mali_l2_cache_power_is_enabled_set(group->l2_cache_core[1], MALI_TRUE);
1020 mali_group_unlock(group);
1022 MALI_DEBUG_PRINT(4,("group: POWER ON\n"));
1025 mali_bool mali_group_power_is_on(struct mali_group *group)
1027 MALI_ASSERT_GROUP_LOCKED(group);
1028 return group->power_is_on;
1031 void mali_group_power_off(void)
1034 /* It is necessary to set group->session = NULL; so that the powered off MMU is not written to on map /unmap */
1035 /* It is necessary to set group->power_is_on=MALI_FALSE so that pending bottom_halves does not access powered off cores. */
1036 for (i = 0; i < mali_global_num_groups; i++)
1038 struct mali_group *group = mali_global_groups[i];
1039 mali_group_lock(group);
1040 MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IDLE == group->state);
1041 group->session = NULL;
1042 group->power_is_on = MALI_FALSE;
1044 if (NULL != group->l2_cache_core[0])
1046 mali_l2_cache_power_is_enabled_set(group->l2_cache_core[0], MALI_FALSE);
1049 if (NULL != group->l2_cache_core[1])
1051 mali_l2_cache_power_is_enabled_set(group->l2_cache_core[1], MALI_FALSE);
1054 mali_group_unlock(group);
1056 MALI_DEBUG_PRINT(4,("group: POWER OFF\n"));
1060 static void mali_group_recovery_reset(struct mali_group *group)
1062 MALI_ASSERT_GROUP_LOCKED(group);
1064 /* Stop cores, bus stop */
1065 if (NULL != group->pp_core)
1067 mali_pp_stop_bus(group->pp_core);
1071 mali_gp_stop_bus(group->gp_core);
1074 /* Flush MMU and clear page fault (if any) */
1075 mali_mmu_activate_fault_flush_page_directory(group->mmu);
1076 mali_mmu_page_fault_done(group->mmu);
1078 /* Wait for cores to stop bus, then do a hard reset on them */
1079 if (NULL != group->pp_core)
1081 if (mali_group_is_virtual(group))
1083 struct mali_group *child, *temp;
1085 _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list)
1087 mali_pp_stop_bus_wait(child->pp_core);
1088 mali_pp_hard_reset(child->pp_core);
1093 mali_pp_stop_bus_wait(group->pp_core);
1094 mali_pp_hard_reset(group->pp_core);
1099 mali_gp_stop_bus_wait(group->gp_core);
1100 mali_gp_hard_reset(group->gp_core);
1104 mali_mmu_reset(group->mmu);
1105 group->session = NULL;
1108 #if MALI_STATE_TRACKING
1109 u32 mali_group_dump_state(struct mali_group *group, char *buf, u32 size)
1113 n += _mali_osk_snprintf(buf + n, size - n, "Group: %p\n", group);
1114 n += _mali_osk_snprintf(buf + n, size - n, "\tstate: %d\n", group->state);
1117 n += mali_gp_dump_state(group->gp_core, buf + n, size - n);
1118 n += _mali_osk_snprintf(buf + n, size - n, "\tGP job: %p\n", group->gp_running_job);
1122 n += mali_pp_dump_state(group->pp_core, buf + n, size - n);
1123 n += _mali_osk_snprintf(buf + n, size - n, "\tPP job: %p, subjob %d \n",
1124 group->pp_running_job, group->pp_running_sub_job);
1131 static void mali_group_mmu_page_fault(struct mali_group *group)
1133 MALI_ASSERT_GROUP_LOCKED(group);
1135 if (NULL != group->pp_core)
1137 struct mali_pp_job *pp_job_to_return;
1138 u32 pp_sub_job_to_return;
1140 MALI_DEBUG_ASSERT_POINTER(group->pp_running_job);
1142 mali_group_post_process_job_pp(group);
1144 pp_job_to_return = group->pp_running_job;
1145 pp_sub_job_to_return = group->pp_running_sub_job;
1146 group->state = MALI_GROUP_STATE_IDLE;
1147 group->pp_running_job = NULL;
1149 mali_group_deactivate_page_directory(group, group->session);
1151 mali_group_recovery_reset(group); /* This will also clear the page fault itself */
1153 mali_pp_scheduler_job_done(group, pp_job_to_return, pp_sub_job_to_return, MALI_FALSE);
1157 struct mali_gp_job *gp_job_to_return;
1159 MALI_DEBUG_ASSERT_POINTER(group->gp_running_job);
1161 mali_group_post_process_job_gp(group, MALI_FALSE);
1163 gp_job_to_return = group->gp_running_job;
1164 group->state = MALI_GROUP_STATE_IDLE;
1165 group->gp_running_job = NULL;
1167 mali_group_deactivate_page_directory(group, group->session);
1169 mali_group_recovery_reset(group); /* This will also clear the page fault itself */
1171 mali_gp_scheduler_job_done(group, gp_job_to_return, MALI_FALSE);
1175 _mali_osk_errcode_t mali_group_upper_half_mmu(void * data)
1177 struct mali_group *group = (struct mali_group *)data;
1178 struct mali_mmu_core *mmu = group->mmu;
1181 MALI_DEBUG_ASSERT_POINTER(mmu);
1183 /* Check if it was our device which caused the interrupt (we could be sharing the IRQ line) */
1184 int_stat = mali_mmu_get_int_status(mmu);
1187 struct mali_group *parent = group->parent_group;
1189 /* page fault or bus error, we thread them both in the same way */
1190 mali_mmu_mask_all_interrupts(mmu);
1193 _mali_osk_wq_schedule_work(group->bottom_half_work_mmu);
1197 _mali_osk_wq_schedule_work(parent->bottom_half_work_mmu);
1199 return _MALI_OSK_ERR_OK;
1202 return _MALI_OSK_ERR_FAULT;
1205 static void mali_group_bottom_half_mmu(void * data)
1207 struct mali_group *group = (struct mali_group *)data;
1208 struct mali_mmu_core *mmu = group->mmu;
1212 MALI_DEBUG_ASSERT_POINTER(mmu);
1214 mali_group_lock(group);
1216 /* TODO: Remove some of these asserts? Will we ever end up in
1217 * "physical" bottom half for a member of the virtual group? */
1218 MALI_DEBUG_ASSERT(NULL == group->parent_group);
1219 MALI_DEBUG_ASSERT(!mali_group_is_in_virtual(group));
1221 if ( MALI_FALSE == mali_group_power_is_on(group) )
1223 MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.", mmu->hw_core.description));
1224 mali_group_unlock(group);
1228 rawstat = mali_mmu_get_rawstat(mmu);
1229 status = mali_mmu_get_status(mmu);
1231 MALI_DEBUG_PRINT(4, ("Mali MMU: Bottom half, interrupt 0x%08X, status 0x%08X\n", rawstat, status));
1233 if (rawstat & (MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR))
1235 /* An actual page fault has occurred. */
1236 u32 fault_address = mali_mmu_get_page_fault_addr(mmu);
1237 MALI_DEBUG_PRINT(2,("Mali MMU: Page fault detected at 0x%x from bus id %d of type %s on %s\n",
1238 (void*)fault_address,
1239 (status >> 6) & 0x1F,
1240 (status & 32) ? "write" : "read",
1241 mmu->hw_core.description));
1242 MALI_IGNORE(fault_address);
1244 mali_group_mmu_page_fault(group);
1247 mali_group_unlock(group);
1250 _mali_osk_errcode_t mali_group_upper_half_gp(void *data)
1252 struct mali_group *group = (struct mali_group *)data;
1253 struct mali_gp_core *core = group->gp_core;
1256 irq_readout = mali_gp_get_int_stat(core);
1258 if (MALIGP2_REG_VAL_IRQ_MASK_NONE != irq_readout)
1260 /* Mask out all IRQs from this core until IRQ is handled */
1261 mali_gp_mask_all_interrupts(core);
1263 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0)|MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, irq_readout, 0, 0, 0, 0);
1265 /* We do need to handle this in a bottom half */
1266 _mali_osk_wq_schedule_work(group->bottom_half_work_gp);
1267 return _MALI_OSK_ERR_OK;
1270 return _MALI_OSK_ERR_FAULT;
1273 static void mali_group_bottom_half_gp(void *data)
1275 struct mali_group *group = (struct mali_group *)data;
1279 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, 0, _mali_osk_get_tid(), MALI_PROFILING_MAKE_EVENT_DATA_CORE_GP(0), 0, 0);
1281 mali_group_lock(group);
1283 if ( MALI_FALSE == mali_group_power_is_on(group) )
1285 MALI_PRINT_ERROR(("Mali group: Interrupt bottom half of %s when core is OFF.", mali_gp_get_hw_core_desc(group->gp_core)));
1286 mali_group_unlock(group);
1287 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
1291 irq_readout = mali_gp_read_rawstat(group->gp_core);
1293 MALI_DEBUG_PRINT(4, ("Mali group: GP bottom half IRQ 0x%08X from core %s\n", irq_readout, mali_gp_get_hw_core_desc(group->gp_core)));
1295 if (irq_readout & (MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST|MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST))
1297 u32 core_status = mali_gp_read_core_status(group->gp_core);
1298 if (0 == (core_status & MALIGP2_REG_VAL_STATUS_MASK_ACTIVE))
1300 MALI_DEBUG_PRINT(4, ("Mali group: GP job completed, calling group handler\n"));
1301 group->core_timed_out = MALI_FALSE;
1302 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
1303 MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
1304 MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
1305 0, _mali_osk_get_tid(), 0, 0, 0);
1306 mali_group_complete_gp(group, MALI_TRUE);
1307 mali_group_unlock(group);
1313 * Now lets look at the possible error cases (IRQ indicating error or timeout)
1314 * END_CMD_LST, HANG and PLBU_OOM interrupts are not considered error.
1316 irq_errors = irq_readout & ~(MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST|MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST|MALIGP2_REG_VAL_IRQ_HANG|MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM);
1317 if (0 != irq_errors)
1319 MALI_PRINT_ERROR(("Mali group: Unknown interrupt 0x%08X from core %s, aborting job\n", irq_readout, mali_gp_get_hw_core_desc(group->gp_core)));
1320 group->core_timed_out = MALI_FALSE;
1321 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
1322 MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
1323 MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
1324 0, _mali_osk_get_tid(), 0, 0, 0);
1325 mali_group_complete_gp(group, MALI_FALSE);
1326 mali_group_unlock(group);
1329 else if (group->core_timed_out) /* SW timeout */
1331 group->core_timed_out = MALI_FALSE;
1332 if (!_mali_osk_timer_pending(group->timeout_timer) && NULL != group->gp_running_job)
1334 MALI_PRINT(("Mali group: Job %d timed out\n", mali_gp_job_get_id(group->gp_running_job)));
1335 mali_group_complete_gp(group, MALI_FALSE);
1336 mali_group_unlock(group);
1340 else if (irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM)
1342 /* GP wants more memory in order to continue. */
1343 MALI_DEBUG_PRINT(3, ("Mali group: PLBU needs more heap memory\n"));
1345 group->state = MALI_GROUP_STATE_OOM;
1346 mali_group_unlock(group); /* Nothing to do on the HW side, so just release group lock right away */
1347 mali_gp_scheduler_oom(group, group->gp_running_job);
1348 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
1353 * The only way to get here is if we only got one of two needed END_CMD_LST
1354 * interrupts. Enable all but not the complete interrupt that has been
1355 * received and continue to run.
1357 mali_gp_enable_interrupts(group->gp_core, irq_readout & (MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST|MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST));
1358 mali_group_unlock(group);
1360 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0);
1363 static void mali_group_post_process_job_gp(struct mali_group *group, mali_bool suspend)
1365 /* Stop the timeout timer. */
1366 _mali_osk_timer_del_async(group->timeout_timer);
1368 if (NULL == group->gp_running_job)
1374 mali_gp_update_performance_counters(group->gp_core, group->gp_running_job, suspend);
1376 #if defined(CONFIG_MALI400_PROFILING)
1379 /* @@@@ todo: test this case and see if it is still working*/
1380 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SUSPEND|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0),
1381 mali_gp_job_get_perf_counter_value0(group->gp_running_job),
1382 mali_gp_job_get_perf_counter_value1(group->gp_running_job),
1383 mali_gp_job_get_perf_counter_src0(group->gp_running_job) | (mali_gp_job_get_perf_counter_src1(group->gp_running_job) << 8),
1388 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0),
1389 mali_gp_job_get_perf_counter_value0(group->gp_running_job),
1390 mali_gp_job_get_perf_counter_value1(group->gp_running_job),
1391 mali_gp_job_get_perf_counter_src0(group->gp_running_job) | (mali_gp_job_get_perf_counter_src1(group->gp_running_job) << 8),
1394 if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[0])) &&
1395 (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[0])))
1396 mali_group_report_l2_cache_counters_per_core(group, 0);
1400 mali_gp_job_set_current_heap_addr(group->gp_running_job,
1401 mali_gp_read_plbu_alloc_start_addr(group->gp_core));
1404 _mali_osk_errcode_t mali_group_upper_half_pp(void *data)
1406 struct mali_group *group = (struct mali_group *)data;
1407 struct mali_pp_core *core = group->pp_core;
1411 * For Mali-450 there is one particular case we need to watch out for:
1413 * Criteria 1) this function call can be due to a shared interrupt,
1414 * and not necessary because this core signaled an interrupt.
1415 * Criteria 2) this core is a part of a virtual group, and thus it should
1416 * not do any post processing.
1417 * Criteria 3) this core has actually indicated that is has completed by
1418 * having set raw_stat/int_stat registers to != 0
1420 * If all this criteria is meet, then we could incorrectly start post
1421 * processing on the wrong group object (this should only happen on the
1424 #if !defined(MALI_UPPER_HALF_SCHEDULING)
1425 if (mali_group_is_in_virtual(group))
1428 * This check is done without the group lock held, which could lead to
1429 * a potential race. This is however ok, since we will safely re-check
1430 * this with the group lock held at a later stage. This is just an
1431 * early out which will strongly benefit shared IRQ systems.
1433 return _MALI_OSK_ERR_OK;
1437 irq_readout = mali_pp_get_int_stat(core);
1438 if (MALI200_REG_VAL_IRQ_MASK_NONE != irq_readout)
1440 /* Mask out all IRQs from this core until IRQ is handled */
1441 mali_pp_mask_all_interrupts(core);
1443 #if defined(CONFIG_MALI400_PROFILING)
1444 /* Currently no support for this interrupt event for the virtual PP core */
1445 if (!mali_group_is_virtual(group))
1447 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE |
1448 MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id) |
1449 MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT,
1450 irq_readout, 0, 0, 0, 0);
1454 #if defined(MALI_UPPER_HALF_SCHEDULING)
1455 if (irq_readout & MALI200_REG_VAL_IRQ_END_OF_FRAME)
1457 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START |
1458 MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
1459 MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF,
1460 0, 0, MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0);
1462 MALI_DEBUG_PRINT(3, ("Mali PP: Job completed, calling group handler from upper half\n"));
1464 mali_group_lock(group);
1466 /* Read int stat again */
1467 irq_readout = mali_pp_read_rawstat(core);
1468 if (!(irq_readout & MALI200_REG_VAL_IRQ_END_OF_FRAME))
1470 /* There was nothing to do */
1471 mali_pp_enable_interrupts(core);
1472 mali_group_unlock(group);
1473 return _MALI_OSK_ERR_OK;
1476 if (mali_group_is_in_virtual(group))
1478 /* We're member of a virtual group, so interrupt should be handled by the virtual group */
1479 mali_pp_enable_interrupts(core);
1480 mali_group_unlock(group);
1481 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
1482 MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
1483 MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF,
1484 0, 0, MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0);
1485 return _MALI_OSK_ERR_FAULT;
1488 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
1489 MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
1490 MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF,
1491 0, 0, MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0);
1493 mali_group_complete_pp(group, MALI_TRUE);
1494 /* No need to enable interrupts again, since the core will be reset while completing the job */
1496 mali_group_unlock(group);
1498 return _MALI_OSK_ERR_OK;
1502 /* We do need to handle this in a bottom half */
1503 _mali_osk_wq_schedule_work(group->bottom_half_work_pp);
1504 return _MALI_OSK_ERR_OK;
1507 return _MALI_OSK_ERR_FAULT;
1510 static void mali_group_bottom_half_pp(void *data)
1512 struct mali_group *group = (struct mali_group *)data;
1513 struct mali_pp_core *core = group->pp_core;
1517 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START |
1518 MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
1519 MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
1520 0, _mali_osk_get_tid(), MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0);
1522 mali_group_lock(group);
1524 if (mali_group_is_in_virtual(group))
1526 /* We're member of a virtual group, so interrupt should be handled by the virtual group */
1527 mali_pp_enable_interrupts(core);
1528 mali_group_unlock(group);
1529 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
1530 MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
1531 MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
1532 0, _mali_osk_get_tid(), 0, 0, 0);
1536 if ( MALI_FALSE == mali_group_power_is_on(group) )
1538 MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.", mali_pp_get_hw_core_desc(core)));
1539 mali_group_unlock(group);
1540 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
1541 MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
1542 MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
1543 0, _mali_osk_get_tid(), 0, 0, 0);
1547 irq_readout = mali_pp_read_rawstat(group->pp_core);
1549 MALI_DEBUG_PRINT(4, ("Mali PP: Bottom half IRQ 0x%08X from core %s\n", irq_readout, mali_pp_get_hw_core_desc(group->pp_core)));
1551 if (irq_readout & MALI200_REG_VAL_IRQ_END_OF_FRAME)
1553 MALI_DEBUG_PRINT(3, ("Mali PP: Job completed, calling group handler\n"));
1554 group->core_timed_out = MALI_FALSE;
1555 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
1556 MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
1557 MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
1558 0, _mali_osk_get_tid(), 0, 0, 0);
1559 mali_group_complete_pp(group, MALI_TRUE);
1560 mali_group_unlock(group);
1565 * Now lets look at the possible error cases (IRQ indicating error or timeout)
1566 * END_OF_FRAME and HANG interrupts are not considered error.
1568 irq_errors = irq_readout & ~(MALI200_REG_VAL_IRQ_END_OF_FRAME|MALI200_REG_VAL_IRQ_HANG);
1569 if (0 != irq_errors)
1571 MALI_PRINT_ERROR(("Mali PP: Unknown interrupt 0x%08X from core %s, aborting job\n",
1572 irq_readout, mali_pp_get_hw_core_desc(group->pp_core)));
1573 group->core_timed_out = MALI_FALSE;
1574 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
1575 MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
1576 MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
1577 0, _mali_osk_get_tid(), 0, 0, 0);
1578 mali_group_complete_pp(group, MALI_FALSE);
1579 mali_group_unlock(group);
1582 else if (group->core_timed_out) /* SW timeout */
1584 group->core_timed_out = MALI_FALSE;
1585 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
1586 MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
1587 MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
1588 0, _mali_osk_get_tid(), 0, 0, 0);
1589 if (!_mali_osk_timer_pending(group->timeout_timer) && NULL != group->pp_running_job)
1591 MALI_PRINT(("Mali PP: Job %d timed out on core %s\n",
1592 mali_pp_job_get_id(group->pp_running_job), mali_pp_get_hw_core_desc(core)));
1593 mali_group_complete_pp(group, MALI_FALSE);
1594 mali_group_unlock(group);
1598 mali_group_unlock(group);
1604 * We should never get here, re-enable interrupts and continue
1606 if (0 == irq_readout)
1608 MALI_DEBUG_PRINT(3, ("Mali group: No interrupt found on core %s\n",
1609 mali_pp_get_hw_core_desc(group->pp_core)));
1613 MALI_PRINT_ERROR(("Mali group: Unhandled PP interrupt 0x%08X on %s\n", irq_readout,
1614 mali_pp_get_hw_core_desc(group->pp_core)));
1616 mali_pp_enable_interrupts(core);
1617 mali_group_unlock(group);
1619 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
1620 MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
1621 MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
1622 0, _mali_osk_get_tid(), 0, 0, 0);
1625 static void mali_group_post_process_job_pp(struct mali_group *group)
1627 MALI_ASSERT_GROUP_LOCKED(group);
1629 /* Stop the timeout timer. */
1630 _mali_osk_timer_del_async(group->timeout_timer);
1632 /*todo add stop SW counters profiling*/
1634 if (NULL != group->pp_running_job)
1636 if (MALI_TRUE == mali_group_is_virtual(group))
1638 struct mali_group *child;
1639 struct mali_group *temp;
1641 /* update performance counters from each physical pp core within this virtual group */
1642 _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list)
1644 mali_pp_update_performance_counters(child->pp_core, group->pp_running_job, group->pp_running_sub_job);
1647 #if defined(CONFIG_MALI400_PROFILING)
1648 /* send profiling data per physical core */
1649 _MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list)
1651 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|
1652 MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(child->pp_core))|
1653 MALI_PROFILING_EVENT_REASON_START_STOP_HW_VIRTUAL,
1654 mali_pp_job_get_perf_counter_value0(group->pp_running_job, mali_pp_core_get_id(child->pp_core)),
1655 mali_pp_job_get_perf_counter_value1(group->pp_running_job, mali_pp_core_get_id(child->pp_core)),
1656 mali_pp_job_get_perf_counter_src0(group->pp_running_job) | (mali_pp_job_get_perf_counter_src1(group->pp_running_job) << 8),
1659 if (0 != group->l2_cache_core_ref_count[0])
1661 if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[0])) &&
1662 (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[0])))
1664 mali_group_report_l2_cache_counters_per_core(group, mali_l2_cache_get_id(group->l2_cache_core[0]));
1667 if (0 != group->l2_cache_core_ref_count[1])
1669 if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[1])) &&
1670 (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[1])))
1672 mali_group_report_l2_cache_counters_per_core(group, mali_l2_cache_get_id(group->l2_cache_core[1]));
1680 /* update performance counters for a physical group's pp core */
1681 mali_pp_update_performance_counters(group->pp_core, group->pp_running_job, group->pp_running_sub_job);
1683 #if defined(CONFIG_MALI400_PROFILING)
1684 _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|
1685 MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(mali_pp_core_get_id(group->pp_core))|
1686 MALI_PROFILING_EVENT_REASON_START_STOP_HW_PHYSICAL,
1687 mali_pp_job_get_perf_counter_value0(group->pp_running_job, group->pp_running_sub_job),
1688 mali_pp_job_get_perf_counter_value1(group->pp_running_job, group->pp_running_sub_job),
1689 mali_pp_job_get_perf_counter_src0(group->pp_running_job) | (mali_pp_job_get_perf_counter_src1(group->pp_running_job) << 8),
1691 if ((MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src0(group->l2_cache_core[0])) &&
1692 (MALI_HW_CORE_NO_COUNTER != mali_l2_cache_core_get_counter_src1(group->l2_cache_core[0])))
1694 mali_group_report_l2_cache_counters_per_core(group, mali_l2_cache_get_id(group->l2_cache_core[0]));
1701 static void mali_group_timeout(void *data)
1703 struct mali_group *group = (struct mali_group *)data;
1705 group->core_timed_out = MALI_TRUE;
1707 if (NULL != group->gp_core)
1709 MALI_DEBUG_PRINT(2, ("Mali group: TIMEOUT on %s\n", mali_gp_get_hw_core_desc(group->gp_core)));
1710 _mali_osk_wq_schedule_work(group->bottom_half_work_gp);
1714 MALI_DEBUG_PRINT(2, ("Mali group: TIMEOUT on %s\n", mali_pp_get_hw_core_desc(group->pp_core)));
1715 _mali_osk_wq_schedule_work(group->bottom_half_work_pp);
1719 void mali_group_zap_session(struct mali_group *group, struct mali_session_data *session)
1721 MALI_DEBUG_ASSERT_POINTER(group);
1722 MALI_DEBUG_ASSERT_POINTER(session);
1724 /* Early out - safe even if mutex is not held */
1725 if (group->session != session) return;
1727 mali_group_lock(group);
1729 mali_group_remove_session_if_unused(group, session);
1731 if (group->session == session)
1733 /* The Zap also does the stall and disable_stall */
1734 mali_bool zap_success = mali_mmu_zap_tlb(group->mmu);
1735 if (MALI_TRUE != zap_success)
1737 MALI_DEBUG_PRINT(2, ("Mali memory unmap failed. Doing pagefault handling.\n"));
1738 mali_group_mmu_page_fault(group);
1742 mali_group_unlock(group);
1745 #if defined(CONFIG_MALI400_PROFILING)
1746 static void mali_group_report_l2_cache_counters_per_core(struct mali_group *group, u32 core_num)
1752 u32 profiling_channel = 0;
1756 case 0: profiling_channel = MALI_PROFILING_EVENT_TYPE_SINGLE |
1757 MALI_PROFILING_EVENT_CHANNEL_GPU |
1758 MALI_PROFILING_EVENT_REASON_SINGLE_GPU_L20_COUNTERS;
1760 case 1: profiling_channel = MALI_PROFILING_EVENT_TYPE_SINGLE |
1761 MALI_PROFILING_EVENT_CHANNEL_GPU |
1762 MALI_PROFILING_EVENT_REASON_SINGLE_GPU_L21_COUNTERS;
1764 case 2: profiling_channel = MALI_PROFILING_EVENT_TYPE_SINGLE |
1765 MALI_PROFILING_EVENT_CHANNEL_GPU |
1766 MALI_PROFILING_EVENT_REASON_SINGLE_GPU_L22_COUNTERS;
1768 default: profiling_channel = MALI_PROFILING_EVENT_TYPE_SINGLE |
1769 MALI_PROFILING_EVENT_CHANNEL_GPU |
1770 MALI_PROFILING_EVENT_REASON_SINGLE_GPU_L20_COUNTERS;
1776 mali_l2_cache_core_get_counter_values(group->l2_cache_core[0], &source0, &value0, &source1, &value1);
1780 if (1 == mali_l2_cache_get_id(group->l2_cache_core[0]))
1782 mali_l2_cache_core_get_counter_values(group->l2_cache_core[0], &source0, &value0, &source1, &value1);
1784 else if (1 == mali_l2_cache_get_id(group->l2_cache_core[1]))
1786 mali_l2_cache_core_get_counter_values(group->l2_cache_core[1], &source0, &value0, &source1, &value1);
1791 if (2 == mali_l2_cache_get_id(group->l2_cache_core[0]))
1793 mali_l2_cache_core_get_counter_values(group->l2_cache_core[0], &source0, &value0, &source1, &value1);
1795 else if (2 == mali_l2_cache_get_id(group->l2_cache_core[1]))
1797 mali_l2_cache_core_get_counter_values(group->l2_cache_core[1], &source0, &value0, &source1, &value1);
1801 _mali_osk_profiling_add_event(profiling_channel, source1 << 8 | source0, value0, value1, 0, 0);
1803 #endif /* #if defined(CONFIG_MALI400_PROFILING) */