static void mali_gp_scheduler_schedule_on_group(struct mali_group *group)
{
	struct mali_gp_job *job;

	MALI_DEBUG_ASSERT_LOCK_HELD(group->lock);
	MALI_DEBUG_ASSERT_LOCK_HELD(gp_scheduler_lock);

	if (0 < pause_count || MALI_GP_SLOT_STATE_IDLE != slot.state || _mali_osk_list_empty(&job_queue))
	{
		mali_gp_scheduler_unlock();
		MALI_DEBUG_PRINT(4, ("Mali GP scheduler: Nothing to schedule (paused=%u, idle slots=%u)\n",
		                     pause_count, MALI_GP_SLOT_STATE_IDLE == slot.state ? 1 : 0));
		return; /* Nothing to do, so early out */
	}

	/* Get (and remove) next job in queue */
	job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_gp_job, list);
	_mali_osk_list_del(&job->list);

	/* Mark slot as busy */
	slot.state = MALI_GP_SLOT_STATE_WORKING;

	mali_gp_scheduler_unlock();

	MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Starting job %u (0x%08X)\n", mali_gp_job_get_id(job), job));

	if (_MALI_OSK_ERR_OK != mali_group_start_gp_job(slot.group, job))
	{
		MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Failed to start GP job\n"));
		MALI_DEBUG_ASSERT(0); /* this cant fail on Mali-300+, no need to implement put back of job */
	}
}
예제 #2
0
_mali_osk_errcode_t _mali_ukk_gp_suspend_response(_mali_uk_gp_suspend_response_s *args)
{
	struct mali_session_data *session;
	_mali_osk_errcode_t ret = _MALI_OSK_ERR_FAULT;

	MALI_DEBUG_ASSERT_POINTER(args);

	if (NULL == args->ctx)
	{
		return _MALI_OSK_ERR_INVALID_ARGS;
	}

	session = (struct mali_session_data*)args->ctx;
	if (NULL == session)
	{
		return _MALI_OSK_ERR_FAULT;
	}

	mali_gp_scheduler_lock();

	/* Make sure that the cookie returned by user space is the same as we provided in the first place */
	if (args->cookie != slot.returned_cookie)
	{
		MALI_DEBUG_PRINT(2, ("Mali GP scheduler: Got an illegal cookie from user space, expected %u but got %u (job id)\n", slot.returned_cookie, args->cookie)) ;
		mali_gp_scheduler_unlock();
		return _MALI_OSK_ERR_FAULT;
	}

	mali_gp_scheduler_unlock();

	switch (args->code)
	{
		case _MALIGP_JOB_RESUME_WITH_NEW_HEAP:
			MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Resuming job %u with new heap; 0x%08X - 0x%08X\n", args->cookie, args->arguments[0], args->arguments[1]));
			mali_group_resume_gp_with_new_heap(slot.group, args->cookie, args->arguments[0], args->arguments[1]);
			ret = _MALI_OSK_ERR_OK;
			break;

		case _MALIGP_JOB_ABORT:
			MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Aborting job %u, no new heap provided\n", args->cookie));
			mali_group_abort_gp_job(slot.group, args->cookie);
			ret = _MALI_OSK_ERR_OK;
			break;

		default:
			MALI_PRINT_ERROR(("Mali GP scheduler: Wrong suspend response from user space\n"));
			ret = _MALI_OSK_ERR_FAULT;
			break;
	}

    return ret;

}
예제 #3
0
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();
	}

}
_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;
}
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.
	*/
}
예제 #6
0
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);
}
예제 #7
0
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.
	*/
}
예제 #8
0
void mali_gp_scheduler_do_schedule(void)
{
	mali_gp_scheduler_lock();

	mali_gp_scheduler_schedule();

	mali_gp_scheduler_unlock();
}
void mali_gp_scheduler_suspend(void)
{
	mali_gp_scheduler_lock();
	pause_count++; /* Increment the pause_count so that no more jobs will be scheduled */
	mali_gp_scheduler_unlock();

	_mali_osk_wait_queue_wait_event(gp_scheduler_working_wait_queue, mali_gp_scheduler_is_suspended);
}
예제 #10
0
void mali_gp_scheduler_suspend(void)
{
	mali_gp_scheduler_lock();
	pause_count++; 
	mali_gp_scheduler_unlock();

	_mali_osk_wait_queue_wait_event(gp_scheduler_working_wait_queue, mali_gp_scheduler_is_suspended);
}
예제 #11
0
void mali_gp_scheduler_resume(void)
{
	mali_gp_scheduler_lock();
	pause_count--; 
	if (0 == pause_count)
	{
		mali_gp_scheduler_schedule();
	}
	mali_gp_scheduler_unlock();
}
void mali_gp_scheduler_resume(void)
{
	mali_gp_scheduler_lock();
	pause_count--; /* Decrement pause_count to allow scheduling again (if it reaches 0) */
	mali_gp_scheduler_unlock();
	if (0 == pause_count)
	{
		mali_gp_scheduler_schedule();
	}
}
static mali_bool mali_gp_scheduler_is_suspended(void)
{
	mali_bool ret;

	mali_gp_scheduler_lock();
	ret = pause_count > 0 && slot.state == MALI_GP_SLOT_STATE_IDLE;
	mali_gp_scheduler_unlock();

	return ret;
}
예제 #14
0
_mali_osk_errcode_t _mali_ukk_gp_start_job(_mali_uk_gp_start_job_s *args)
{
	struct mali_session_data *session;
	struct mali_gp_job *job;

	MALI_DEBUG_ASSERT_POINTER(args);

	if (NULL == args->ctx)
	{
		return _MALI_OSK_ERR_INVALID_ARGS;
	}

	session = (struct mali_session_data*)args->ctx;
	if (NULL == session)
	{
		return _MALI_OSK_ERR_FAULT;
	}

	job = mali_gp_job_create(session, args, 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_gp_scheduler_lock();

	_mali_osk_list_addtail(&job->list, &job_queue);

	MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Job %u (0x%08X) queued\n", mali_gp_job_get_id(job), job));

	mali_gp_scheduler_schedule();

	mali_gp_scheduler_unlock();

	return _MALI_OSK_ERR_OK;
}
예제 #15
0
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);
}
예제 #16
0
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_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);
	}
	else
	{
		mali_gp_scheduler_schedule();
	}

	mali_gp_scheduler_unlock();

	mali_gp_scheduler_return_job_to_user(job, success);
}
예제 #17
0
/* Group and scheduler must be locked when entering this function.  Both will be unlocked before
 * exiting. */
static void mali_gp_scheduler_schedule_internal_and_unlock(void)
{
    struct mali_gp_job *job = NULL;

    MALI_DEBUG_ASSERT_LOCK_HELD(slot.group->lock);
    MALI_DEBUG_ASSERT_LOCK_HELD(gp_scheduler_lock);

    if (0 < pause_count || MALI_GP_SLOT_STATE_IDLE != slot.state ||
            (_mali_osk_list_empty(&job_queue) && _mali_osk_list_empty(&job_queue_high))) {
        mali_gp_scheduler_unlock();
        mali_group_unlock(slot.group);
        MALI_DEBUG_PRINT(4, ("Mali GP scheduler: Nothing to schedule (paused=%u, idle slots=%u)\n",
                             pause_count, MALI_GP_SLOT_STATE_IDLE == slot.state ? 1 : 0));
#if defined(CONFIG_GPU_TRACEPOINTS) && defined(CONFIG_TRACEPOINTS)
        trace_gpu_sched_switch(mali_gp_get_hw_core_desc(group->gp_core), sched_clock(), 0, 0, 0);
#endif
        return; /* Nothing to do, so early out */
    }

    /* Get next job in queue */
    if (!_mali_osk_list_empty(&job_queue_high)) {
        job = _MALI_OSK_LIST_ENTRY(job_queue_high.next, struct mali_gp_job, list);
    } else {
예제 #18
0
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_lock();

	
	slot.state = MALI_GP_SLOT_STATE_IDLE;

	
	if (pause_count > 0)
	{
		_mali_osk_wait_queue_wake_up(gp_scheduler_working_wait_queue);
	}
	else
	{
		mali_gp_scheduler_schedule();
	}

	mali_gp_scheduler_unlock();

	mali_gp_scheduler_return_job_to_user(job, success);
}
예제 #19
0
_mali_osk_errcode_t _mali_ukk_gp_start_job(_mali_uk_gp_start_job_s *args)
{
	struct mali_session_data *session;
	struct mali_gp_job *job;

	MALI_DEBUG_ASSERT_POINTER(args);

	if (NULL == args->ctx)
	{
		return _MALI_OSK_ERR_INVALID_ARGS;
	}

	session = (struct mali_session_data*)args->ctx;
	if (NULL == session)
	{
		return _MALI_OSK_ERR_FAULT;
	}

	job = mali_gp_job_create(session, args, mali_scheduler_get_new_id());
	if (NULL == job)
	{
		return _MALI_OSK_ERR_NOMEM;
	}

	mali_gp_scheduler_lock();

	_mali_osk_list_addtail(&job->list, &job_queue);

	MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Job %u (0x%08X) queued\n", mali_gp_job_get_id(job), job));

	mali_gp_scheduler_schedule();

	mali_gp_scheduler_unlock();

	return _MALI_OSK_ERR_OK;
}