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); }