_mali_osk_errcode_t mali_soft_job_system_signal_job(struct mali_soft_job_system *system, u32 job_id) { struct mali_soft_job *job; struct mali_timeline_system *timeline_system; mali_scheduler_mask schedule_mask; MALI_DEBUG_ASSERT_POINTER(system); mali_soft_job_system_lock(system); job = mali_soft_job_system_lookup_job(system, job_id); if ((NULL == job) || (MALI_SOFT_JOB_TYPE_USER_SIGNALED != job->type) || !(MALI_SOFT_JOB_STATE_STARTED == job->state || MALI_SOFT_JOB_STATE_TIMED_OUT == job->state)) { mali_soft_job_system_unlock(system); MALI_PRINT_ERROR(("Mali Soft Job: invalid soft job id %u", job_id)); return _MALI_OSK_ERR_ITEM_NOT_FOUND; } if (MALI_SOFT_JOB_STATE_TIMED_OUT == job->state) { job->state = MALI_SOFT_JOB_STATE_SIGNALED; mali_soft_job_system_unlock(system); MALI_DEBUG_ASSERT(MALI_TRUE == job->activated); MALI_DEBUG_PRINT(4, ("Mali Soft Job: soft job %u (0x%08X) was timed out\n", job->id, job)); mali_soft_job_destroy(job); return _MALI_OSK_ERR_TIMEOUT; } MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_STARTED == job->state); job->state = MALI_SOFT_JOB_STATE_SIGNALED; mali_soft_job_system_unlock(system); /* Since the job now is in signaled state, timeouts from the timeline system will be * ignored, and it is not possible to signal this job again. */ timeline_system = system->session->timeline_system; MALI_DEBUG_ASSERT_POINTER(timeline_system); /* Wait until activated. */ _mali_osk_wait_queue_wait_event(timeline_system->wait_queue, mali_soft_job_is_activated, (void *) job); MALI_DEBUG_PRINT(4, ("Mali Soft Job: signaling soft job %u (0x%08X)\n", job->id, job)); schedule_mask = mali_timeline_tracker_release(&job->tracker); mali_scheduler_schedule_from_mask(schedule_mask, MALI_FALSE); mali_soft_job_destroy(job); return _MALI_OSK_ERR_OK; }
mali_scheduler_mask mali_soft_job_system_activate_job(struct mali_soft_job *job) { mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY; MALI_DEBUG_ASSERT_POINTER(job); MALI_DEBUG_ASSERT_POINTER(job->system); MALI_DEBUG_ASSERT_POINTER(job->system->session); MALI_DEBUG_PRINT(4, ("Mali Soft Job: Timeline activation for soft job %u (0x%08X).\n", job->id, job)); mali_soft_job_system_lock(job->system); if (unlikely(job->system->session->is_aborting)) { MALI_DEBUG_PRINT(3, ("Mali Soft Job: Soft job %u (0x%08X) activated while session is aborting.\n", job->id, job)); mali_soft_job_system_unlock(job->system); /* Since we are in shutdown, we can ignore the scheduling bitmask. */ mali_timeline_tracker_release(&job->tracker); mali_soft_job_destroy(job); return schedule_mask; } /* Send activated notification. */ mali_soft_job_send_activated_notification(job); /* Wake up sleeping signaler. */ job->activated = MALI_TRUE; /* If job type is self signaled, release tracker, move soft job to free list, and scheduler at once */ if (MALI_SOFT_JOB_TYPE_SELF_SIGNALED == job->type) { MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_STARTED == job->state); job->state = MALI_SOFT_JOB_STATE_SIGNALED; mali_soft_job_system_unlock(job->system); schedule_mask |= mali_timeline_tracker_release(&job->tracker); mali_soft_job_destroy(job); } else { _mali_osk_wait_queue_wake_up(job->tracker.system->wait_queue); mali_soft_job_system_unlock(job->system); } return schedule_mask; }
int soft_job_start_wrapper(struct mali_session_data *session, _mali_uk_soft_job_start_s __user *uargs) { _mali_uk_soft_job_start_s kargs; u32 type, point; u64 user_job; struct mali_timeline_fence fence; struct mali_soft_job *job = NULL; u32 __user *job_id_ptr = NULL; /* If the job was started successfully, 0 is returned. If there was an error, but the job * was started, we return -ENOENT. For anything else returned, the job was not started. */ MALI_CHECK_NON_NULL(uargs, -EINVAL); MALI_CHECK_NON_NULL(session, -EINVAL); MALI_DEBUG_ASSERT_POINTER(session->soft_job_system); if (0 != copy_from_user(&kargs, uargs, sizeof(kargs))) { return -EFAULT; } type = kargs.type; user_job = kargs.user_job; job_id_ptr = (u32 __user *)(uintptr_t)kargs.job_id_ptr; mali_timeline_fence_copy_uk_fence(&fence, &kargs.fence); if ((MALI_SOFT_JOB_TYPE_USER_SIGNALED != type) && (MALI_SOFT_JOB_TYPE_SELF_SIGNALED != type)) { MALI_DEBUG_PRINT_ERROR(("Invalid soft job type specified\n")); return -EINVAL; } /* Create soft job. */ job = mali_soft_job_create(session->soft_job_system, (enum mali_soft_job_type)type, user_job); if (unlikely(NULL == job)) { return map_errcode(_MALI_OSK_ERR_NOMEM); } /* Write job id back to user space. */ if (0 != put_user(job->id, job_id_ptr)) { MALI_PRINT_ERROR(("Mali Soft Job: failed to put job id")); mali_soft_job_destroy(job); return map_errcode(_MALI_OSK_ERR_NOMEM); } /* Start soft job. */ point = mali_soft_job_start(job, &fence); if (0 != put_user(point, &uargs->point)) { /* Let user space know that something failed after the job was started. */ return -ENOENT; } return 0; }
void mali_soft_job_system_abort(struct mali_soft_job_system *system) { struct mali_soft_job *job, *tmp; _MALI_OSK_LIST_HEAD_STATIC_INIT(jobs); MALI_DEBUG_ASSERT_POINTER(system); MALI_DEBUG_ASSERT_POINTER(system->session); MALI_DEBUG_ASSERT(system->session->is_aborting); MALI_DEBUG_PRINT(3, ("Mali Soft Job: Aborting soft job system for session 0x%08X.\n", system->session)); mali_soft_job_system_lock(system); _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &system->jobs_used, struct mali_soft_job, system_list) { MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_STARTED == job->state || MALI_SOFT_JOB_STATE_TIMED_OUT == job->state); if (MALI_SOFT_JOB_STATE_STARTED == job->state) { /* If the job has been activated, we have to release the tracker and destroy * the job. If not, the tracker will be released and the job destroyed when * it is activated. */ if (MALI_TRUE == job->activated) { MALI_DEBUG_PRINT(3, ("Mali Soft Job: Aborting unsignaled soft job %u (0x%08X).\n", job->id, job)); job->state = MALI_SOFT_JOB_STATE_SIGNALED; _mali_osk_list_move(&job->system_list, &jobs); } } else if (MALI_SOFT_JOB_STATE_TIMED_OUT == job->state) { MALI_DEBUG_PRINT(3, ("Mali Soft Job: Aborting timed out soft job %u (0x%08X).\n", job->id, job)); /* We need to destroy this soft job. */ _mali_osk_list_move(&job->system_list, &jobs); } } mali_soft_job_system_unlock(system); /* Release and destroy jobs. */ _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &jobs, struct mali_soft_job, system_list) { MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_SIGNALED == job->state || MALI_SOFT_JOB_STATE_TIMED_OUT == job->state); if (MALI_SOFT_JOB_STATE_SIGNALED == job->state) { mali_timeline_tracker_release(&job->tracker); } /* Move job back to used list before destroying. */ _mali_osk_list_move(&job->system_list, &system->jobs_used); mali_soft_job_destroy(job); } }
mali_scheduler_mask mali_soft_job_system_timeout_job(struct mali_soft_job *job) { mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY; MALI_DEBUG_ASSERT_POINTER(job); MALI_DEBUG_ASSERT_POINTER(job->system); MALI_DEBUG_ASSERT_POINTER(job->system->session); MALI_DEBUG_ASSERT(MALI_TRUE == job->activated); MALI_DEBUG_PRINT(4, ("Mali Soft Job: Timeline timeout for soft job %u (0x%08X).\n", job->id, job)); mali_soft_job_system_lock(job->system); MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_STARTED == job->state || MALI_SOFT_JOB_STATE_SIGNALED == job->state); if (unlikely(job->system->session->is_aborting)) { /* The session is aborting. This job will be released and destroyed by @ref * mali_soft_job_system_abort(). */ mali_soft_job_system_unlock(job->system); return MALI_SCHEDULER_MASK_EMPTY; } if (MALI_SOFT_JOB_STATE_STARTED != job->state) { MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_SIGNALED == job->state); /* The job is about to be signaled, ignore timeout. */ MALI_DEBUG_PRINT(4, ("Mali Soft Job: Timeout on soft job %u (0x%08X) in signaled state.\n", job->id, job)); mali_soft_job_system_unlock(job->system); return schedule_mask; } MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_STARTED == job->state); job->state = MALI_SOFT_JOB_STATE_TIMED_OUT; _mali_osk_atomic_inc(&job->refcount); mali_soft_job_system_unlock(job->system); schedule_mask = mali_timeline_tracker_release(&job->tracker); mali_soft_job_destroy(job); return schedule_mask; }