void mali_gp_scheduler_oom(struct mali_group *group, struct mali_gp_job *job) { _mali_uk_gp_job_suspended_s * jobres; _mali_osk_notification_t * notification; mali_gp_scheduler_lock(); notification = job->oom_notification; job->oom_notification = NULL; slot.returned_cookie = mali_gp_job_get_id(job); jobres = (_mali_uk_gp_job_suspended_s *)notification->result_buffer; jobres->user_job_ptr = mali_gp_job_get_user_id(job); jobres->cookie = mali_gp_job_get_id(job); mali_gp_scheduler_unlock(); jobres->reason = _MALIGP_JOB_SUSPENDED_OUT_OF_MEMORY; mali_session_send_notification(mali_gp_job_get_session(job), notification); /* * If this function failed, then we could return the job to user space right away, * but there is a job timer anyway that will do that eventually. * This is not exactly a common case anyway. */ }
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_gp_scheduler_unlock(); /* Abort running jobs from this session. It is safe to do this outside * the scheduler lock as there is only one GP core, and the queue has * already been emptied, as long as there are no new jobs coming in * from user space. */ mali_group_abort_session(slot.group, session); }
static void mali_gp_scheduler_return_job_to_user(struct mali_gp_job *job, mali_bool success) { _mali_osk_notification_t *notobj = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_FINISHED, sizeof(_mali_uk_gp_job_finished_s)); if (NULL != notobj) { _mali_uk_gp_job_finished_s *jobres = notobj->result_buffer; _mali_osk_memset(jobres, 0, sizeof(_mali_uk_gp_job_finished_s)); /* @@@@ can be removed once we initialize all members in this struct */ jobres->user_job_ptr = mali_gp_job_get_user_id(job); if (MALI_TRUE == success) { jobres->status = _MALI_UK_JOB_STATUS_END_SUCCESS; } else { jobres->status = _MALI_UK_JOB_STATUS_END_UNKNOWN_ERR; } jobres->heap_current_addr = mali_gp_job_get_current_heap_addr(job); jobres->perf_counter0 = mali_gp_job_get_perf_counter_value0(job); jobres->perf_counter1 = mali_gp_job_get_perf_counter_value1(job); mali_session_send_notification(mali_gp_job_get_session(job), notobj); } else { MALI_PRINT_ERROR(("Mali GP scheduler: Unable to allocate notification object\n")); } mali_gp_job_delete(job); }
void mali_gp_scheduler_oom(struct mali_group *group, struct mali_gp_job *job) { _mali_osk_notification_t *notobj; notobj = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_STALLED, sizeof(_mali_uk_gp_job_suspended_s)); if (NULL != notobj) { _mali_uk_gp_job_suspended_s * jobres; mali_gp_scheduler_lock(); jobres = (_mali_uk_gp_job_suspended_s *)notobj->result_buffer; jobres->user_job_ptr = mali_gp_job_get_user_id(job); jobres->reason = _MALIGP_JOB_SUSPENDED_OUT_OF_MEMORY; jobres->cookie = mali_gp_job_get_id(job); slot.returned_cookie = jobres->cookie; mali_session_send_notification(mali_gp_job_get_session(job), notobj); mali_gp_scheduler_unlock(); } /* * If this function failed, then we could return the job to user space right away, * but there is a job timer anyway that will do that eventually. * This is not exactly a common case anyway. */ }
void mali_gp_scheduler_oom(struct mali_group *group, struct mali_gp_job *job) { _mali_osk_notification_t *notobj; notobj = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_STALLED, sizeof(_mali_uk_gp_job_suspended_s)); if (NULL != notobj) { _mali_uk_gp_job_suspended_s * jobres; mali_gp_scheduler_lock(); jobres = (_mali_uk_gp_job_suspended_s *)notobj->result_buffer; jobres->user_job_ptr = mali_gp_job_get_user_id(job); jobres->reason = _MALIGP_JOB_SUSPENDED_OUT_OF_MEMORY; jobres->cookie = mali_gp_job_get_id(job); slot.returned_cookie = jobres->cookie; mali_session_send_notification(mali_gp_job_get_session(job), notobj); mali_gp_scheduler_unlock(); } }
void mali_group_abort_session(struct mali_group *group, struct mali_session_data *session) { struct mali_gp_job *gp_job; struct mali_pp_job *pp_job; u32 gp_job_id = 0; u32 pp_job_id = 0; mali_bool abort_pp = MALI_FALSE; mali_bool abort_gp = MALI_FALSE; mali_group_lock(group); gp_job = group->gp_running_job; pp_job = group->pp_running_job; if (gp_job && mali_gp_job_get_session(gp_job) == session) { MALI_DEBUG_PRINT(4, ("Aborting GP job 0x%08x from session 0x%08x\n", gp_job, session)); gp_job_id = mali_gp_job_get_id(gp_job); abort_gp = MALI_TRUE; } if (pp_job && mali_pp_job_get_session(pp_job) == session) { MALI_DEBUG_PRINT(4, ("Mali group: Aborting PP job 0x%08x from session 0x%08x\n", pp_job, session)); pp_job_id = mali_pp_job_get_id(pp_job); abort_pp = MALI_TRUE; } mali_group_unlock(group); /* These functions takes and releases the group lock */ if (0 != abort_gp) { mali_group_abort_gp_job(group, gp_job_id); } if (0 != abort_pp) { mali_group_abort_pp_job(group, pp_job_id); } mali_group_lock(group); mali_group_remove_session_if_unused(group, session); mali_group_unlock(group); }
_mali_osk_errcode_t mali_group_start_gp_job(struct mali_group *group, struct mali_gp_job *job) { struct mali_session_data *session; enum mali_group_activate_pd_status activate_status; MALI_DEBUG_ASSERT(MALI_GROUP_CORE_STATE_IDLE == group->gp_state); mali_pm_core_event(MALI_CORE_EVENT_GP_START); session = mali_gp_job_get_session(job); mali_group_lock(group); mali_cluster_l2_cache_invalidate_all(group->cluster, mali_gp_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_mmu_zap_tlb_without_stall(group->mmu); } mali_gp_job_start(group->gp_core, job); group->gp_running_job = job; group->gp_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_GP_STOP); /* Failed to start, so "cancel" the MALI_CORE_EVENT_GP_START */ return _MALI_OSK_ERR_FAULT; }
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)); _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_gp_scheduler_unlock(); mali_group_abort_session(slot.group, session); }
static void mali_gp_scheduler_return_job_to_user(struct mali_gp_job *job, mali_bool success) { _mali_uk_gp_job_finished_s *jobres = job->finished_notification->result_buffer; _mali_osk_memset(jobres, 0, sizeof(_mali_uk_gp_job_finished_s)); /* @@@@ can be removed once we initialize all members in this struct */ jobres->user_job_ptr = mali_gp_job_get_user_id(job); if (MALI_TRUE == success) { jobres->status = _MALI_UK_JOB_STATUS_END_SUCCESS; } else { jobres->status = _MALI_UK_JOB_STATUS_END_UNKNOWN_ERR; } jobres->heap_current_addr = mali_gp_job_get_current_heap_addr(job); jobres->perf_counter0 = mali_gp_job_get_perf_counter_value0(job); jobres->perf_counter1 = mali_gp_job_get_perf_counter_value1(job); mali_session_send_notification(mali_gp_job_get_session(job), job->finished_notification); job->finished_notification = NULL; mali_gp_job_delete(job); }
/* 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); }