struct mali_gp_job *mali_gp_job_create(struct mali_session_data *session, _mali_uk_gp_start_job_s *uargs, u32 id) { struct mali_gp_job *job; u32 perf_counter_flag; job = _mali_osk_malloc(sizeof(struct mali_gp_job)); if (NULL != job) { job->finished_notification = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_FINISHED, sizeof(_mali_uk_gp_job_finished_s)); if (NULL == job->finished_notification) { _mali_osk_free(job); return NULL; } job->oom_notification = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_STALLED, sizeof(_mali_uk_gp_job_suspended_s)); if (NULL == job->oom_notification) { _mali_osk_notification_delete(job->finished_notification); _mali_osk_free(job); return NULL; } if (0 != copy_from_user(&job->uargs, uargs, sizeof(_mali_uk_gp_start_job_s))) { _mali_osk_notification_delete(job->finished_notification); _mali_osk_notification_delete(job->oom_notification); _mali_osk_free(job); return NULL; } perf_counter_flag = mali_gp_job_get_perf_counter_flag(job); /* case when no counters came from user space * so pass the debugfs / DS-5 provided global ones to the job object */ if (!((perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE) || (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE))) { mali_gp_job_set_perf_counter_src0(job, mali_gp_job_get_gp_counter_src0()); mali_gp_job_set_perf_counter_src1(job, mali_gp_job_get_gp_counter_src1()); } _mali_osk_list_init(&job->list); job->session = session; job->id = id; job->heap_current_addr = job->uargs.frame_registers[4]; job->perf_counter_value0 = 0; job->perf_counter_value1 = 0; job->pid = _mali_osk_get_pid(); job->tid = _mali_osk_get_tid(); return job; } return NULL; }
void mali_pp_job_delete(struct mali_pp_job *job) { #ifdef CONFIG_SYNC /* It is safe to delete the work without flushing. */ if (NULL != job->sync_work) _mali_osk_wq_delete_work_nonflush(job->sync_work); if (NULL != job->pre_fence) sync_fence_put(job->pre_fence); if (NULL != job->sync_point) sync_fence_put(job->sync_point->fence); #endif if (NULL != job->finished_notification) { _mali_osk_notification_delete(job->finished_notification); } _mali_osk_free(job->memory_cookies); #if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH) /* Unmap buffers attached to job */ if (0 < job->num_dma_bufs) { mali_dma_buf_unmap_job(job); } _mali_osk_free(job->dma_bufs); #endif /* CONFIG_DMA_SHARED_BUFFER */ _mali_osk_free(job); }
int mali_dump_memory_notify(_mali_uk_memory_usage_dumped_s __user *arg) { struct mali_session_data *session, *tmp; _mali_osk_notification_t * notification; mali_session_lock(); MALI_SESSION_FOREACH(session, tmp, link) { notification = _mali_osk_notification_create(_MALI_NOTIFCATION_MEMORY_USAGE_DUMP, sizeof(_mali_uk_memory_usage_dumped_s)); if (NULL == notification) { MALI_PRINT_ERROR( ("Failed to create notification object\n")); mali_session_unlock(); return -ENOMEM; } if (0 != copy_from_user(notification->result_buffer, arg, sizeof(_mali_uk_memory_usage_dumped_s))) { _mali_osk_notification_delete(notification); mali_session_unlock(); return -EFAULT; } mali_session_send_notification(session, notification); }
_mali_osk_errcode_t _mali_ukk_gp_suspend_response(_mali_uk_gp_suspend_response_s *args) { struct mali_session_data *session; struct mali_gp_job *resumed_job; _mali_osk_notification_t *new_notification = 0; 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; } if (_MALIGP_JOB_RESUME_WITH_NEW_HEAP == args->code) { new_notification = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_STALLED, sizeof(_mali_uk_gp_job_suspended_s)); if (NULL == new_notification) { MALI_PRINT_ERROR(("Mali GP scheduler: Failed to allocate notification object. Will abort GP job.\n")); mali_group_lock(slot.group); mali_group_abort_gp_job(slot.group, args->cookie); mali_group_unlock(slot.group); return _MALI_OSK_ERR_FAULT; } } mali_group_lock(slot.group); if (_MALIGP_JOB_RESUME_WITH_NEW_HEAP == args->code) { 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])); resumed_job = mali_group_resume_gp_with_new_heap(slot.group, args->cookie, args->arguments[0], args->arguments[1]); if (NULL != resumed_job) { resumed_job->oom_notification = new_notification; mali_group_unlock(slot.group); return _MALI_OSK_ERR_OK; } else { mali_group_unlock(slot.group); _mali_osk_notification_delete(new_notification); return _MALI_OSK_ERR_FAULT; } } 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); mali_group_unlock(slot.group); return _MALI_OSK_ERR_OK; }
void mali_gp_job_delete(struct mali_gp_job *job) { /* de-allocate the pre-allocated oom notifications */ if (NULL != job->oom_notification) { _mali_osk_notification_delete(job->oom_notification); job->oom_notification = NULL; } if (NULL != job->finished_notification) { _mali_osk_notification_delete(job->finished_notification); job->finished_notification = NULL; } _mali_osk_free(job); }
void mali_gp_job_delete(struct mali_gp_job *job) { MALI_DEBUG_ASSERT_POINTER(job); MALI_DEBUG_ASSERT(NULL == job->pp_tracker); MALI_DEBUG_ASSERT(_mali_osk_list_empty(&job->list)); /* de-allocate the pre-allocated oom notifications */ if (NULL != job->oom_notification) { _mali_osk_notification_delete(job->oom_notification); job->oom_notification = NULL; } if (NULL != job->finished_notification) { _mali_osk_notification_delete(job->finished_notification); job->finished_notification = NULL; } _mali_osk_free(job); }
void _mali_osk_notification_queue_term( _mali_osk_notification_queue_t *queue ) { _mali_osk_notification_t *result; MALI_DEBUG_ASSERT_POINTER( queue ); while (_MALI_OSK_ERR_OK == _mali_osk_notification_queue_dequeue(queue, &result)) { _mali_osk_notification_delete( result ); } /* not much to do, just free the memory */ kfree(queue); }
void mali_pp_job_delete(struct mali_pp_job *job) { #ifdef MTK_CONFIG_SYNC /* It is safe to delete the work without flushing. */ if (NULL != job->sync_work) _mali_osk_wq_delete_work_nonflush(job->sync_work); if (NULL != job->pre_fence) sync_fence_put(job->pre_fence); if (NULL != job->sync_point) sync_fence_put(job->sync_point->fence); #endif if (NULL != job->finished_notification) { _mali_osk_notification_delete(job->finished_notification); } _mali_osk_free(job); }
void mali_soft_job_destroy(struct mali_soft_job *job) { MALI_DEBUG_ASSERT_POINTER(job); MALI_DEBUG_ASSERT_POINTER(job->system); MALI_DEBUG_PRINT(4, ("Mali Soft Job: destroying soft job %u (0x%08X)\n", job->id, job)); if (NULL != job) { if (0 < _mali_osk_atomic_dec_return(&job->refcount)) return; _mali_osk_atomic_term(&job->refcount); if (NULL != job->activated_notification) { _mali_osk_notification_delete(job->activated_notification); job->activated_notification = NULL; } mali_soft_job_system_free_job(job->system, job); } }
void mali_pp_job_delete(struct mali_pp_job *job) { mali_dma_put_cmd_buf(&job->dma_cmd_buf); if (NULL != job->finished_notification) { _mali_osk_notification_delete(job->finished_notification); } _mali_osk_free(job->memory_cookies); #if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH) /* Unmap buffers attached to job */ if (0 < job->num_dma_bufs) { mali_dma_buf_unmap_job(job); } _mali_osk_free(job->dma_bufs); #endif /* CONFIG_DMA_SHARED_BUFFER */ _mali_osk_free(job); }
_mali_osk_errcode_t _mali_ukk_wait_for_notification( _mali_uk_wait_for_notification_s *args ) { _mali_osk_errcode_t err; _mali_osk_notification_t * notification; _mali_osk_notification_queue_t *queue; /* check input */ MALI_DEBUG_ASSERT_POINTER(args); MALI_CHECK_NON_NULL(args->ctx, _MALI_OSK_ERR_INVALID_ARGS); queue = (_mali_osk_notification_queue_t *)mali_kernel_session_manager_slot_get(args->ctx, mali_subsystem_core_id); /* if the queue does not exist we're currently shutting down */ if (NULL == queue) { MALI_DEBUG_PRINT(1, ("No notification queue registered with the session. Asking userspace to stop querying\n")); args->type = _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS; MALI_SUCCESS; } /* receive a notification, might sleep */ err = _mali_osk_notification_queue_receive(queue, ¬ification); if (_MALI_OSK_ERR_OK != err) { MALI_ERROR(err); /* errcode returned, pass on to caller */ } /* copy the buffer to the user */ args->type = (_mali_uk_notification_type)notification->notification_type; _mali_osk_memcpy(&args->data, notification->result_buffer, notification->result_buffer_size); /* finished with the notification */ _mali_osk_notification_delete( notification ); MALI_SUCCESS; /* all ok */ }
struct mali_gp_job *mali_gp_job_create(struct mali_session_data *session, _mali_uk_gp_start_job_s *uargs, u32 id, struct mali_timeline_tracker *pp_tracker) { struct mali_gp_job *job; u32 perf_counter_flag; job = _mali_osk_malloc(sizeof(struct mali_gp_job)); if (NULL != job) { job->finished_notification = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_FINISHED, sizeof(_mali_uk_gp_job_finished_s)); if (NULL == job->finished_notification) { _mali_osk_free(job); return NULL; } job->oom_notification = _mali_osk_notification_create(_MALI_NOTIFICATION_GP_STALLED, sizeof(_mali_uk_gp_job_suspended_s)); if (NULL == job->oom_notification) { _mali_osk_notification_delete(job->finished_notification); _mali_osk_free(job); return NULL; } if (0 != _mali_osk_copy_from_user(&job->uargs, uargs, sizeof(_mali_uk_gp_start_job_s))) { _mali_osk_notification_delete(job->finished_notification); _mali_osk_notification_delete(job->oom_notification); _mali_osk_free(job); return NULL; } perf_counter_flag = mali_gp_job_get_perf_counter_flag(job); /* case when no counters came from user space * so pass the debugfs / DS-5 provided global ones to the job object */ if (!((perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE) || (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE))) { mali_gp_job_set_perf_counter_src0(job, mali_gp_job_get_gp_counter_src0()); mali_gp_job_set_perf_counter_src1(job, mali_gp_job_get_gp_counter_src1()); } _mali_osk_list_init(&job->list); job->session = session; job->id = id; job->heap_current_addr = job->uargs.frame_registers[4]; job->perf_counter_value0 = 0; job->perf_counter_value1 = 0; job->pid = _mali_osk_get_pid(); job->tid = _mali_osk_get_tid(); job->pp_tracker = pp_tracker; if (NULL != job->pp_tracker) { /* Take a reference on PP job's tracker that will be released when the GP job is done. */ mali_timeline_system_tracker_get(session->timeline_system, pp_tracker); } mali_timeline_tracker_init(&job->tracker, MALI_TIMELINE_TRACKER_GP, NULL, job); mali_timeline_fence_copy_uk_fence(&(job->tracker.fence), &(job->uargs.fence)); return job; } return NULL; }
static void pmm_event_process( void ) { _mali_osk_errcode_t err = _MALI_OSK_ERR_OK; _mali_osk_notification_t *msg = NULL; _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR; mali_pmm_message_t *event; u32 process_messages; MALI_DEBUG_ASSERT_POINTER(pmm); /* Max number of messages to process before exiting - as we shouldn't stay * processing the messages for a long time */ process_messages = _mali_osk_atomic_read( &(pmm->messages_queued) ); while( process_messages > 0 ) { /* Check internal message queue first */ err = _mali_osk_notification_queue_dequeue( pmm->iqueue, &msg ); if( err != _MALI_OSK_ERR_OK ) { if( pmm->status == MALI_PMM_STATUS_IDLE || pmm->status == MALI_PMM_STATUS_OS_WAITING || pmm->status == MALI_PMM_STATUS_DVFS_PAUSE) { if( pmm->waiting > 0 ) pmm->waiting--; /* We aren't busy changing state, so look at real events */ err = _mali_osk_notification_queue_dequeue( pmm->queue, &msg ); if( err != _MALI_OSK_ERR_OK ) { pmm->no_events++; MALIPMM_DEBUG_PRINT( ("PMM: event_process - No message to process\n") ); /* Nothing to do - so return */ return; } else { #if MALI_PMM_TRACE pmm->messages_received++; #endif } } else { /* Waiting for an internal message */ pmm->waiting++; MALIPMM_DEBUG_PRINT( ("PMM: event_process - Waiting for internal message, messages queued=%d\n", pmm->waiting) ); return; } } else { #if MALI_PMM_TRACE pmm->imessages_received++; #endif } MALI_DEBUG_ASSERT_POINTER( msg ); /* Check the message type matches */ MALI_DEBUG_ASSERT( msg->notification_type == MALI_PMM_NOTIFICATION_TYPE ); event = msg->result_buffer; _mali_osk_atomic_dec( &(pmm->messages_queued) ); process_messages--; #if MALI_PMM_TRACE /* Trace before we process the event in case we have an error */ _mali_pmm_trace_event_message( event, MALI_TRUE ); #endif err = pmm_policy_process( pmm, event ); if( err != _MALI_OSK_ERR_OK ) { MALI_PRINT_ERROR( ("PMM: Error(%d) in policy %d when processing event message with id: %d", err, pmm->policy, event->id) ); } /* Delete notification */ _mali_osk_notification_delete ( msg ); if( pmm->fatal_power_err ) { /* Nothing good has happened - exit */ return; } #if MALI_PMM_TRACE MALI_PRINT( ("PMM Trace: Event processed, msgs (sent/read) = %d/%d, int msgs (sent/read) = %d/%d, no events = %d, waiting = %d\n", pmm->messages_sent, pmm->messages_received, pmm->imessages_sent, pmm->imessages_received, pmm->no_events, pmm->waiting) ); #endif } if( pmm->status == MALI_PMM_STATUS_IDLE && pmm->waiting > 0 ) { /* For events we ignored whilst we were busy, add a new * scheduled time to look at them */ _mali_osk_irq_schedulework( pmm->irq ); } }
void pmm_fatal_reset( _mali_pmm_internal_state_t *pmm ) { _mali_osk_errcode_t err = _MALI_OSK_ERR_OK; _mali_osk_notification_t *msg = NULL; mali_pmm_status status; MALI_DEBUG_ASSERT_POINTER(pmm); MALIPMM_DEBUG_PRINT( ("PMM: Fatal Reset called") ); MALI_DEBUG_ASSERT( pmm->status != MALI_PMM_STATUS_OFF ); /* Reset the common status */ pmm->waiting = 0; pmm->missed = 0; pmm->fatal_power_err = MALI_FALSE; pmm->no_events = 0; pmm->check_policy = MALI_FALSE; pmm->cores_pend_down = 0; pmm->cores_pend_up = 0; pmm->cores_ack_down = 0; pmm->cores_ack_up = 0; pmm->is_dvfs_active = 0; #if MALI_PMM_TRACE pmm->messages_sent = 0; pmm->messages_received = 0; pmm->imessages_sent = 0; pmm->imessages_received = 0; MALI_PRINT( ("PMM Trace: *** Fatal reset occurred ***") ); #endif /* Set that we are unavailable whilst resetting */ pmm->state = MALI_PMM_STATE_UNAVAILABLE; status = pmm->status; pmm->status = MALI_PMM_STATUS_OFF; /* We want all cores powered */ pmm->cores_powered = pmm->cores_registered; /* The cores may not be idle, but this state will be rectified later */ pmm->cores_idle = pmm->cores_registered; /* So power on any cores that are registered */ if( pmm->cores_registered != 0 ) { int n; volatile mali_pmm_core_mask *pregistered = &(pmm->cores_registered); #if !MALI_PMM_NO_PMU err = mali_platform_powerup( pmm->cores_registered ); #endif if( err != _MALI_OSK_ERR_OK ) { /* This is very bad as we can't even be certain the cores are now * powered up */ MALI_PRINT_ERROR( ("PMM: Failed to perform PMM reset!\n") ); /* TBD driver exit? */ } for( n = SIZEOF_CORES_LIST-1; n >= 0; n-- ) { if( (cores_list[n] & (*pregistered)) != 0 ) { MALI_PMM_UNLOCK(pmm); /* Core is now active - so try putting it in the idle queue */ err = mali_core_signal_power_up( cores_list[n], MALI_FALSE ); MALI_PMM_LOCK(pmm); /* We either succeeded, or we were not off anyway, or we have * just be deregistered */ MALI_DEBUG_ASSERT( (err == _MALI_OSK_ERR_OK) || (err == _MALI_OSK_ERR_BUSY) || (err == _MALI_OSK_ERR_FAULT && (*pregistered & cores_list[n]) == 0) ); } } } /* Unblock any pending OS event */ if( status == MALI_PMM_STATUS_OS_POWER_UP ) { /* Get the OS data and respond to the power up */ _mali_osk_pmm_power_up_done( pmm_retrieve_os_event_data( pmm ) ); } if( status == MALI_PMM_STATUS_OS_POWER_DOWN ) { /* Get the OS data and respond to the power down * NOTE: We are not powered down at this point due to power problems, * so we are lying to the system, but something bad has already * happened and we are trying unstick things * TBD - Add busy loop to power down cores? */ _mali_osk_pmm_power_down_done( pmm_retrieve_os_event_data( pmm ) ); } /* Purge the event queues */ do { if( _mali_osk_notification_queue_dequeue( pmm->iqueue, &msg ) == _MALI_OSK_ERR_OK ) { _mali_osk_notification_delete ( msg ); break; } } while (MALI_TRUE); do { if( _mali_osk_notification_queue_dequeue( pmm->queue, &msg ) == _MALI_OSK_ERR_OK ) { _mali_osk_notification_delete ( msg ); break; } } while (MALI_TRUE); /* Return status/state to normal */ pmm->status = MALI_PMM_STATUS_IDLE; pmm_update_system_state(pmm); }
static void mali_user_settings_notify(_mali_uk_user_setting_t setting, u32 value) { mali_bool done = MALI_FALSE; /* * This function gets a bit complicated because we can't hold the session lock while * allocating notification objects. */ while (!done) { u32 i; u32 num_sessions_alloc; u32 num_sessions_with_lock; u32 used_notification_objects = 0; _mali_osk_notification_t **notobjs; /* Pre allocate the number of notifications objects we need right now (might change after lock has been taken) */ num_sessions_alloc = mali_session_get_count(); if (0 == num_sessions_alloc) { /* No sessions to report to */ return; } notobjs = (_mali_osk_notification_t **)_mali_osk_malloc(sizeof(_mali_osk_notification_t *) * num_sessions_alloc); if (NULL == notobjs) { MALI_PRINT_ERROR(("Failed to notify user space session about num PP core change (alloc failure)\n")); return; } for (i = 0; i < num_sessions_alloc; i++) { notobjs[i] = _mali_osk_notification_create(_MALI_NOTIFICATION_SETTINGS_CHANGED, sizeof(_mali_uk_settings_changed_s)); if (NULL != notobjs[i]) { _mali_uk_settings_changed_s *data; data = notobjs[i]->result_buffer; data->setting = setting; data->value = value; } else { MALI_PRINT_ERROR(("Failed to notify user space session about setting change (alloc failure %u)\n", i)); } } mali_session_lock(); /* number of sessions will not change while we hold the lock */ num_sessions_with_lock = mali_session_get_count(); if (num_sessions_alloc >= num_sessions_with_lock) { /* We have allocated enough notification objects for all the sessions atm */ struct mali_session_data *session, *tmp; MALI_SESSION_FOREACH(session, tmp, link) { MALI_DEBUG_ASSERT(used_notification_objects < num_sessions_alloc); if (NULL != notobjs[used_notification_objects]) { mali_session_send_notification(session, notobjs[used_notification_objects]); notobjs[used_notification_objects] = NULL; /* Don't track this notification object any more */ } used_notification_objects++; } done = MALI_TRUE; } mali_session_unlock(); /* Delete any remaining/unused notification objects */ for (; used_notification_objects < num_sessions_alloc; used_notification_objects++) { if (NULL != notobjs[used_notification_objects]) { _mali_osk_notification_delete(notobjs[used_notification_objects]); } } _mali_osk_free(notobjs); }