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 */
}
示例#3
0
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 );
	}
}
示例#4
0
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);
}