diff options
Diffstat (limited to 'drivers/media/video/samsung/mali/common/mali_pp_scheduler.c')
-rw-r--r-- | drivers/media/video/samsung/mali/common/mali_pp_scheduler.c | 248 |
1 files changed, 124 insertions, 124 deletions
diff --git a/drivers/media/video/samsung/mali/common/mali_pp_scheduler.c b/drivers/media/video/samsung/mali/common/mali_pp_scheduler.c index eedf661..a944055 100644 --- a/drivers/media/video/samsung/mali/common/mali_pp_scheduler.c +++ b/drivers/media/video/samsung/mali/common/mali_pp_scheduler.c @@ -17,8 +17,6 @@ #include "mali_pp_job.h" #include "mali_group.h" #include "mali_cluster.h" -#include "mali_osk_profiling.h" - /* Maximum of 8 PP cores (a group can only have maximum of 1 PP core) */ #define MALI_MAX_NUMBER_OF_PP_GROUPS 8 @@ -41,14 +39,10 @@ struct mali_pp_slot */ enum mali_pp_slot_state state; struct mali_session_data *session; - struct mali_pp_job *job; - u32 subjob; }; static u32 pp_version = 0; static _MALI_OSK_LIST_HEAD(job_queue); /* List of jobs with some unscheduled work */ -static u32 job_queue_depth; - static struct mali_pp_slot slots[MALI_MAX_NUMBER_OF_PP_GROUPS]; static u32 num_slots = 0; static u32 num_slots_idle = 0; @@ -67,7 +61,7 @@ _mali_osk_errcode_t mali_pp_scheduler_initialize(void) _MALI_OSK_INIT_LIST_HEAD(&job_queue); - pp_scheduler_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_SCHEDULER); + pp_scheduler_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_SCHEDULER); if (NULL == pp_scheduler_lock) { return _MALI_OSK_ERR_NOMEM; @@ -160,7 +154,7 @@ static mali_bool mali_pp_scheduler_session_has_running_jobs(struct mali_session_ for (i = 0; i < num_slots; i++) { if (MALI_PP_SLOT_STATE_WORKING == slots[i].state) - { + { if (slots[i].session == session) { return MALI_TRUE; @@ -171,123 +165,131 @@ static mali_bool mali_pp_scheduler_session_has_running_jobs(struct mali_session_ return MALI_FALSE; } -static mali_bool slots_available(void) -{ - return num_slots_idle > 0; -} - static void mali_pp_scheduler_schedule(void) { + u32 i; struct mali_pp_job *job; +#if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS + struct mali_session_data * session; +#endif + + MALI_ASSERT_PP_SCHEDULER_LOCKED(); - if (0 < pause_count || 0 == num_slots_idle || 0 == job_queue_depth) + if (0 < pause_count || 0 == num_slots_idle || _mali_osk_list_empty(&job_queue)) { MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Nothing to schedule (paused=%u, idle slots=%u)\n", pause_count, num_slots_idle)); return; /* Nothing to do, so early out */ } - while(slots_available() && 0 < job_queue_depth) + +#if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP + if ( num_slots_idle < num_slots ) + { + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job not started, since only %d/%d cores are available\n", num_slots_idle,num_slots)); + return; + } +#endif + +#if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS + /* Finding initial session for the PP cores */ + job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_pp_job, list); + session = job->session; + if ( num_slots != num_slots_idle ) + { + for (i = 0; (i < num_slots) ; i++) + { + if ( slots[i].state == MALI_PP_SLOT_STATE_IDLE ) + { + continue; + } + session = mali_group_get_session(slots[i].group); + break; + } + } +#endif + + for (i = 0; (i < num_slots) && (0 < num_slots_idle); i++) { - u32 i, slot_count; - struct mali_pp_slot *reserved_slots[num_slots]; - struct mali_session_data *session; + u32 sub_job; - mali_pp_scheduler_lock(); - /* Get job */ - if (_mali_osk_list_empty(&job_queue) || !slots_available()) + if (_mali_osk_list_empty(&job_queue)) /* move this check down to where we know we have started all sub jobs for this job??? */ { - mali_pp_scheduler_unlock(); break; /* No more jobs to schedule, so early out */ } + + if (MALI_PP_SLOT_STATE_IDLE != slots[i].state) + { + continue; + } + job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_pp_job, list); MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(job)); /* All jobs on the job_queue should have unstarted sub jobs */ - session = mali_pp_job_get_session(job); if (MALI_TRUE == mali_pp_job_has_active_barrier(job)) { if (MALI_TRUE == mali_pp_scheduler_session_has_running_jobs(mali_pp_job_get_session(job))) { - /* There is already a running job from this - * session, so we need to enforce the barrier */ - mali_pp_scheduler_unlock(); + /* There is already a running job from this session, so we need to enforce the barrier */ return; } else { - /* Barrier is now enforced, update job object - * so we don't delay execution of sub-jobs */ + /* Barrier is now enforced, update job object so we don't delay execution of sub-jobs */ mali_pp_job_barrier_enforced(job); } } - /* Reserve slots */ - for (i = 0, slot_count = 0; i < num_slots; i++) + #if MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED + if ( (0==job->sub_jobs_started) && (num_slots_idle < num_slots) && (job->sub_job_count > num_slots_idle)) { - struct mali_pp_slot *slot = &slots[i]; - - if (MALI_PP_SLOT_STATE_IDLE != slot->state) continue; - - slot->state = MALI_PP_SLOT_STATE_WORKING; - slot->session = session; - slot->job = job; - slot->subjob = mali_pp_job_get_first_unstarted_sub_job(job); - mali_pp_job_mark_sub_job_started(job, slot->subjob); - --job_queue_depth; - - --num_slots_idle; - reserved_slots[slot_count++] = slot; - - if (!mali_pp_job_has_unstarted_sub_jobs(job)) - { - _mali_osk_list_del(&job->list); - break; - } + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job with %d subjobs not started, since only %d/%d cores are available\n", job->sub_job_count, num_slots_idle,num_slots)); + return; } + #endif - MALI_DEBUG_ASSERT(0 < slot_count); + #if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS + if ( job->session != session ) + { + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job not started since existing job is from another application\n")); + return; + } + #endif - mali_pp_scheduler_unlock(); + sub_job = mali_pp_job_get_first_unstarted_sub_job(job); - /* Start (sub)job(s) on core(s) */ - for(i = 0; i < slot_count; i++) + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Starting job %u (0x%08X) part %u/%u\n", mali_pp_job_get_id(job), job, sub_job + 1, mali_pp_job_get_sub_job_count(job))); + if (_MALI_OSK_ERR_OK == mali_group_start_pp_job(slots[i].group, job, sub_job)) { - struct mali_pp_slot *slot = reserved_slots[i]; - struct mali_pp_job *job; - u32 subjob; + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job %u (0x%08X) part %u/%u started\n", mali_pp_job_get_id(job), job, sub_job + 1, mali_pp_job_get_sub_job_count(job))); - MALI_DEBUG_ASSERT_POINTER(slot); - MALI_DEBUG_ASSERT(MALI_PP_SLOT_STATE_WORKING == slot->state); - MALI_DEBUG_ASSERT_POINTER(slot->job); + /* Mark this sub job as started */ + mali_pp_job_mark_sub_job_started(job, sub_job); - job = slot->job; - subjob = slot->subjob; + /* Mark slot as busy */ + slots[i].state = MALI_PP_SLOT_STATE_WORKING; + slots[i].session = mali_pp_job_get_session(job); + num_slots_idle--; - if (_MALI_OSK_ERR_OK == mali_group_start_pp_job(slot->group, slot->job, slot->subjob)) - { - MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job %u (0x%08X) part %u/%u started\n", - mali_pp_job_get_id(job), job, subjob + 1, - mali_pp_job_get_sub_job_count(job))); - } - else + if (!mali_pp_job_has_unstarted_sub_jobs(job)) { - MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Failed to start PP job\n")); - /* This can only happen on Mali-200 */ -#if !defined(USING_MALI200) - MALI_DEBUG_ASSERT(0); + /* + * All sub jobs have now started for this job, remove this job from the job queue. + * The job will now only be referred to by the slots which are running it. + * The last slot to complete will make sure it is returned to user space. + */ + _mali_osk_list_del(&job->list); +#if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP + MALI_DEBUG_PRINT(6, ("Mali PP scheduler: Skip scheduling more jobs when MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP is set.\n")); + return; #endif - mali_pp_scheduler_lock(); - /* Put job back on queue */ - mali_pp_job_mark_sub_job_not_stated(job, subjob); - _mali_osk_list_add(&job->list, &job_queue); - /* Set slot idle */ - slot->state = MALI_PP_SLOT_STATE_IDLE; - slot->session = NULL; - slot->job = NULL; - slot->subjob = 0; - mali_pp_scheduler_unlock(); } } + else + { + MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Failed to start PP job\n")); + return; + } } } @@ -333,42 +335,35 @@ static void mali_pp_scheduler_return_job_to_user(struct mali_pp_job *job) void mali_pp_scheduler_do_schedule(void) { + mali_pp_scheduler_lock(); + mali_pp_scheduler_schedule(); + + mali_pp_scheduler_unlock(); } void mali_pp_scheduler_job_done(struct mali_group *group, struct mali_pp_job *job, u32 sub_job, mali_bool success) { u32 i; - struct mali_pp_slot *slot = NULL; mali_bool job_is_done; - MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Job %u (0x%08X) part %u/%u completed (%s)\n", - mali_pp_job_get_id(job), - job, sub_job + 1, - mali_pp_job_get_sub_job_count(job), - success ? "success" : "failure")); + MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Job %u (0x%08X) part %u/%u completed (%s)\n", mali_pp_job_get_id(job), job, sub_job + 1, mali_pp_job_get_sub_job_count(job), success ? "success" : "failure")); mali_pp_scheduler_lock(); - mali_pp_job_mark_sub_job_completed(job, success); - /* Find slot which was running this job */ for (i = 0; i < num_slots; i++) { - slot = &slots[i]; - if (slot->group == group) - break; + if (slots[i].group == group) + { + MALI_DEBUG_ASSERT(MALI_PP_SLOT_STATE_WORKING == slots[i].state); + slots[i].state = MALI_PP_SLOT_STATE_IDLE; + slots[i].session = NULL; + num_slots_idle++; + mali_pp_job_mark_sub_job_completed(job, success); + } } - MALI_DEBUG_ASSERT_POINTER(slot); - - slot->state = MALI_PP_SLOT_STATE_IDLE; - slot->session = NULL; - slot->job = NULL; - slot->subjob = 0; - - num_slots_idle++; - /* If paused, then this was the last job, so wake up sleeping workers */ if (pause_count > 0) { @@ -378,6 +373,10 @@ void mali_pp_scheduler_job_done(struct mali_group *group, struct mali_pp_job *jo */ _mali_osk_wait_queue_wake_up(pp_scheduler_working_wait_queue); } + else + { + mali_pp_scheduler_schedule(); + } job_is_done = mali_pp_job_is_complete(job); @@ -389,8 +388,6 @@ void mali_pp_scheduler_job_done(struct mali_group *group, struct mali_pp_job *jo MALI_DEBUG_PRINT(4, ("Mali PP scheduler: All parts completed for job %u (0x%08X)\n", mali_pp_job_get_id(job), job)); mali_pp_scheduler_return_job_to_user(job); } - - mali_pp_scheduler_schedule(); } void mali_pp_scheduler_suspend(void) @@ -399,7 +396,11 @@ void mali_pp_scheduler_suspend(void) pause_count++; /* Increment the pause_count so that no more jobs will be scheduled */ mali_pp_scheduler_unlock(); - /* Go to sleep. When woken up again (in mali_pp_scheduler_job_done), the + /*mali_pp_scheduler_working_lock();*/ + /* We have now aquired the working lock, which means that we have successfully paused the scheduler */ + /*mali_pp_scheduler_working_unlock();*/ + + /* go to sleep. When woken up again (in mali_pp_scheduler_job_done), the * mali_pp_scheduler_suspended() function will be called. This will return true * iff state is idle and pause_count > 0, so if the core is active this * will not do anything. @@ -418,17 +419,17 @@ void mali_pp_scheduler_resume(void) mali_pp_scheduler_unlock(); } -_mali_osk_errcode_t _mali_ukk_pp_start_job(void *ctx, _mali_uk_pp_start_job_s *uargs) +_mali_osk_errcode_t _mali_ukk_pp_start_job(_mali_uk_pp_start_job_s *args) { struct mali_session_data *session; struct mali_pp_job *job; - MALI_DEBUG_ASSERT_POINTER(uargs); - MALI_DEBUG_ASSERT_POINTER(ctx); + MALI_DEBUG_ASSERT_POINTER(args); + MALI_DEBUG_ASSERT_POINTER(args->ctx); - session = (struct mali_session_data*)ctx; + session = (struct mali_session_data*)args->ctx; - job = mali_pp_job_create(session, uargs, mali_scheduler_get_new_id()); + job = mali_pp_job_create(session, args, mali_scheduler_get_new_id()); if (NULL == job) { return _MALI_OSK_ERR_NOMEM; @@ -450,15 +451,13 @@ _mali_osk_errcode_t _mali_ukk_pp_start_job(void *ctx, _mali_uk_pp_start_job_s *u mali_pp_scheduler_lock(); - job_queue_depth += mali_pp_job_get_sub_job_count(job); _mali_osk_list_addtail(&job->list, &job_queue); - MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Job %u (0x%08X) with %u parts queued\n", - mali_pp_job_get_id(job), job, mali_pp_job_get_sub_job_count(job))); + MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Job %u (0x%08X) with %u parts queued\n", mali_pp_job_get_id(job), job, mali_pp_job_get_sub_job_count(job))); - mali_pp_scheduler_unlock(); + mali_pp_scheduler_schedule(); - if (slots_available()) mali_pp_scheduler_schedule(); + mali_pp_scheduler_unlock(); return _MALI_OSK_ERR_OK; } @@ -490,8 +489,9 @@ void _mali_ukk_pp_job_disable_wb(_mali_uk_pp_disable_wb_s *args) session = (struct mali_session_data*)args->ctx; - /* Check queue for jobs that match */ mali_pp_scheduler_lock(); + + /* Check queue for jobs that match */ _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &job_queue, struct mali_pp_job, list) { if (mali_pp_job_get_session(job) == session && @@ -513,6 +513,7 @@ void _mali_ukk_pp_job_disable_wb(_mali_uk_pp_disable_wb_s *args) break; } } + mali_pp_scheduler_unlock(); } @@ -530,7 +531,6 @@ void mali_pp_scheduler_abort_session(struct mali_session_data *session) if (mali_pp_job_get_session(job) == session) { _mali_osk_list_del(&(job->list)); - job_queue_depth -= mali_pp_job_get_sub_job_count(job) - mali_pp_job_get_first_unstarted_sub_job(job); if ( mali_pp_job_is_currently_rendering_and_if_so_abort_new_starts(job) ) { @@ -551,9 +551,14 @@ void mali_pp_scheduler_abort_session(struct mali_session_data *session) { struct mali_group *group = slots[i].group; - MALI_DEBUG_PRINT(5, ("PP sched abort: Attempting abort for session 0x%08x on group 0x%08x\n", session, group)); + MALI_DEBUG_PRINT(5, ("PP sched abort: Looking at group 0x%08x\n", group)); + + if (MALI_PP_SLOT_STATE_WORKING == slots[i].state) + { + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Aborting session 0x%08x from group 0x%08x\n", session, group)); - mali_group_abort_session(group, session); + mali_group_abort_session(group, session); + } } } @@ -568,11 +573,6 @@ static mali_bool mali_pp_scheduler_is_suspended(void) return ret; } -int mali_pp_scheduler_get_queue_depth(void) -{ - return job_queue_depth; -} - #if MALI_STATE_TRACKING u32 mali_pp_scheduler_dump_state(char *buf, u32 size) { |