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); }
_mali_osk_errcode_t _mali_osk_notification_queue_receive(_mali_osk_notification_queue_t *queue, _mali_osk_notification_t **result) { /* check input */ MALI_DEBUG_ASSERT_POINTER(queue); MALI_DEBUG_ASSERT_POINTER(result); /* default result */ *result = NULL; if (wait_event_interruptible(queue->receive_queue, _MALI_OSK_ERR_OK == _mali_osk_notification_queue_dequeue(queue, result))) { return _MALI_OSK_ERR_RESTARTSYSCALL; } return _MALI_OSK_ERR_OK; /* all ok */ }
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); }