_mali_osk_errcode_t _mali_ukk_gp_start_job(void *ctx, _mali_uk_gp_start_job_s *uargs) { struct mali_session_data *session; struct mali_gp_job *job; MALI_DEBUG_ASSERT_POINTER(uargs); MALI_DEBUG_ASSERT_POINTER(ctx); session = (struct mali_session_data*)ctx; job = mali_gp_job_create(session, uargs, mali_scheduler_get_new_id()); if (NULL == job) { return _MALI_OSK_ERR_NOMEM; } #if PROFILING_SKIP_PP_AND_GP_JOBS #warning GP jobs will not be executed mali_gp_scheduler_return_job_to_user(job, MALI_TRUE); return _MALI_OSK_ERR_OK; #endif mali_pm_core_event(MALI_CORE_EVENT_GP_START); mali_gp_scheduler_lock(); _mali_osk_list_addtail(&job->list, &job_queue); mali_gp_scheduler_unlock(); MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Job %u (0x%08X) queued\n", mali_gp_job_get_id(job), job)); mali_gp_scheduler_schedule(); return _MALI_OSK_ERR_OK; }
_mali_osk_errcode_t mali_group_start_pp_job(struct mali_group *group, struct mali_pp_job *job, u32 sub_job) { struct mali_session_data *session; enum mali_group_activate_pd_status activate_status; MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->pp_state); mali_pm_core_event(MALI_CORE_EVENT_PP_START); session = mali_pp_job_get_session(job); mali_group_lock(group); mali_cluster_l2_cache_invalidate_all(group->cluster, mali_pp_job_get_id(job)); activate_status = mali_group_activate_page_directory(group, session); if (MALI_GROUP_ACTIVATE_PD_STATUS_FAILED != activate_status) { /* if session is NOT kept Zapping is done as part of session switch */ if (MALI_GROUP_ACTIVATE_PD_STATUS_OK_KEPT_PD == activate_status) { MALI_DEBUG_PRINT(3, ("PP starting job PD_Switch 0 Flush 1 Zap 1\n")); mali_mmu_zap_tlb_without_stall(group->mmu); } mali_pp_job_start(group->pp_core, job, sub_job); group->pp_running_job = job; group->pp_running_sub_job = sub_job; group->pp_state = MALI_GROUP_CORE_STATE_WORKING; mali_group_unlock(group); return _MALI_OSK_ERR_OK; } #if defined(USING_MALI200) group->pagedir_activation_failed = MALI_TRUE; #endif mali_group_unlock(group); mali_pm_core_event(MALI_CORE_EVENT_PP_STOP); /* Failed to start, so "cancel" the MALI_CORE_EVENT_PP_START */ return _MALI_OSK_ERR_FAULT; }
void mali_gp_scheduler_job_done(struct mali_group *group, struct mali_gp_job *job, mali_bool success) { MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Job %u (0x%08X) completed (%s)\n", mali_gp_job_get_id(job), job, success ? "success" : "failure")); mali_gp_scheduler_return_job_to_user(job, success); mali_gp_scheduler_lock(); /* Mark slot as idle again */ slot.state = MALI_GP_SLOT_STATE_IDLE; /* If paused, then this was the last job, so wake up sleeping workers */ if (pause_count > 0) { _mali_osk_wait_queue_wake_up(gp_scheduler_working_wait_queue); } mali_gp_scheduler_schedule_on_group(group); /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */ mali_pm_core_event(MALI_CORE_EVENT_GP_STOP); }
void mali_gp_scheduler_abort_session(struct mali_session_data *session) { struct mali_gp_job *job, *tmp; mali_gp_scheduler_lock(); MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Aborting all jobs from session 0x%08x\n", session)); /* Check queue for jobs and remove */ _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &job_queue, struct mali_gp_job, list) { if (mali_gp_job_get_session(job) == session) { MALI_DEBUG_PRINT(4, ("Mali GP scheduler: Removing GP job 0x%08x from queue\n", job)); _mali_osk_list_del(&(job->list)); mali_gp_job_delete(job); mali_pm_core_event(MALI_CORE_EVENT_GP_STOP); } } mali_gp_scheduler_unlock(); mali_group_abort_session(slot.group, session); }
/* Group lock need to be taken before calling mali_group_complete_jobs. Will release the lock here. */ static void mali_group_complete_jobs(struct mali_group *group, mali_bool complete_gp, mali_bool complete_pp, bool success) { mali_bool need_group_reset = MALI_FALSE; mali_bool gp_success = success; mali_bool pp_success = success; MALI_ASSERT_GROUP_LOCKED(group); if (complete_gp && !complete_pp) { MALI_DEBUG_ASSERT_POINTER(group->gp_core); if (_MALI_OSK_ERR_OK == mali_gp_reset(group->gp_core)) { struct mali_gp_job *gp_job_to_return = group->gp_running_job; group->gp_state = MALI_GROUP_CORE_STATE_IDLE; group->gp_running_job = NULL; MALI_DEBUG_ASSERT_POINTER(gp_job_to_return); mali_group_deactivate_page_directory(group, mali_gp_job_get_session(gp_job_to_return)); if(mali_group_other_reschedule_needed(group)) { mali_group_unlock(group); mali_pp_scheduler_do_schedule(); } else { mali_group_unlock(group); } mali_gp_scheduler_job_done(group, gp_job_to_return, gp_success); mali_pm_core_event(MALI_CORE_EVENT_GP_STOP); /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */ return; } else { need_group_reset = MALI_TRUE; MALI_DEBUG_PRINT(3, ("Mali group: Failed to reset GP, need to reset entire group\n")); pp_success = MALI_FALSE; /* This might kill PP as well, so this should fail */ } } if (complete_pp && !complete_gp) { MALI_DEBUG_ASSERT_POINTER(group->pp_core); if (_MALI_OSK_ERR_OK == mali_pp_reset(group->pp_core)) { struct mali_pp_job *pp_job_to_return = group->pp_running_job; u32 pp_sub_job_to_return = group->pp_running_sub_job; group->pp_state = MALI_GROUP_CORE_STATE_IDLE; group->pp_running_job = NULL; MALI_DEBUG_ASSERT_POINTER(pp_job_to_return); mali_group_deactivate_page_directory(group, mali_pp_job_get_session(pp_job_to_return)); if(mali_group_other_reschedule_needed(group)) { mali_group_unlock(group); mali_gp_scheduler_do_schedule(); } else { mali_group_unlock(group); } mali_pp_scheduler_job_done(group, pp_job_to_return, pp_sub_job_to_return, pp_success); mali_pm_core_event(MALI_CORE_EVENT_PP_STOP); /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */ return; } else { need_group_reset = MALI_TRUE; MALI_DEBUG_PRINT(3, ("Mali group: Failed to reset PP, need to reset entire group\n")); gp_success = MALI_FALSE; /* This might kill GP as well, so this should fail */ } } else if (complete_gp && complete_pp) { need_group_reset = MALI_TRUE; } if (MALI_TRUE == need_group_reset) { struct mali_gp_job *gp_job_to_return = group->gp_running_job; struct mali_pp_job *pp_job_to_return = group->pp_running_job; u32 pp_sub_job_to_return = group->pp_running_sub_job; mali_bool schedule_other = MALI_FALSE; MALI_DEBUG_PRINT(3, ("Mali group: Resetting entire group\n")); group->gp_state = MALI_GROUP_CORE_STATE_IDLE; group->gp_running_job = NULL; if (NULL != gp_job_to_return) { mali_group_deactivate_page_directory(group, mali_gp_job_get_session(gp_job_to_return)); } group->pp_state = MALI_GROUP_CORE_STATE_IDLE; group->pp_running_job = NULL; if (NULL != pp_job_to_return) { mali_group_deactivate_page_directory(group, mali_pp_job_get_session(pp_job_to_return)); } /* The reset has to be done after mali_group_deactivate_page_directory() */ mali_group_recovery_reset(group); if (mali_group_other_reschedule_needed(group) && (NULL == gp_job_to_return || NULL == pp_job_to_return)) { schedule_other = MALI_TRUE; } mali_group_unlock(group); if (NULL != gp_job_to_return) { mali_gp_scheduler_job_done(group, gp_job_to_return, gp_success); mali_pm_core_event(MALI_CORE_EVENT_GP_STOP); /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */ } else if (schedule_other) { mali_pp_scheduler_do_schedule(); } if (NULL != pp_job_to_return) { mali_pp_scheduler_job_done(group, pp_job_to_return, pp_sub_job_to_return, pp_success); mali_pm_core_event(MALI_CORE_EVENT_PP_STOP); /* It is ok to do this after schedule, since START/STOP is simply ++ and -- anyways */ } else if (schedule_other) { mali_gp_scheduler_do_schedule(); } return; } mali_group_unlock(group); }