diff -r 000000000000 -r c40eb8fe8501 wlan_bearer/wlanldd/wlan_common/umac_common/src/umacdynamicpowermodemgmtcntx.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wlan_bearer/wlanldd/wlan_common/umac_common/src/umacdynamicpowermodemgmtcntx.cpp Tue Feb 02 02:03:13 2010 +0200 @@ -0,0 +1,660 @@ +/* +* Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Implementation of the WlanDynamicPowerModeMgmtCntx class +* +*/ + +/* +* %version: 14 % +*/ + +#include "config.h" +#include "umacdynamicpowermodemgmtcntx.h" +#include "UmacContextImpl.h" + +// default time interval in microseconds after which transition from Active +// mode to Light PS mode is considered. +// This value is used if another value hasn't been provided +const TUint32 KDefaultToLightPsTimeout = 100000; // 100ms + +// default time interval in microseconds after which the frame counter +// used when considering transition from Light PS to Active mode is reset. +// This value is used if another value hasn't been provided +const TUint32 KDefaultToActiveTimeout = 300000; // 300ms + +// default time interval in microseconds after which transition from Light PS +// mode to Deep PS mode is considered. +// This value is used if another value hasn't been provided +const TUint32 KDefaultToDeepPsTimeout = 1000000; // 1s + + +// ================= MEMBER FUNCTIONS ======================= + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +WlanDynamicPowerModeMgmtCntx::WlanDynamicPowerModeMgmtCntx( + WlanContextImpl& aWlanCtxImpl ) : + iStateChange( EFalse ), + iFlags( 0 | KStayInPsDespiteUapsdVoiceTraffic ), + iToLightPsTimeout( KDefaultToLightPsTimeout ), + iToActiveTimeout( KDefaultToActiveTimeout ), + iToDeepPsTimeout( KDefaultToDeepPsTimeout ), + iActiveCntx( NULL ), + iWlanContextImpl( aWlanCtxImpl ) + { + os_memset( iIgnoreTraffic, 0, sizeof( iIgnoreTraffic ) ); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +WlanDynamicPowerModeMgmtCntx::~WlanDynamicPowerModeMgmtCntx() + { + CancelTimeouts(); + iActiveCntx = NULL; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void WlanDynamicPowerModeMgmtCntx::StartPowerModeManagement() + { + if ( !iActiveCntx ) + { + const TPowerMgmtMode KCurrentPwrMgmtMode ( + iWlanContextImpl.CurrentPwrMgmtMode() ); + + switch ( KCurrentPwrMgmtMode ) + { + case EActive: + OsTracePrint( KPwrStateTransition, (TUint8*) + ("UMAC: WlanDynamicPowerModeMgmtCntx::StartPowerModeManagement: Activating Active mode context") ); + + iActiveCntx = &iActiveModeCntx; + RegisterToLightPsTimeout(); + break; + case ELightPs: + OsTracePrint( KPwrStateTransition, (TUint8*) + ("UMAC: WlanDynamicPowerModeMgmtCntx::StartPowerModeManagement: Activating Light PS mode context") ); + + iActiveCntx = &iLightPsModeCntx; + + if ( // we have roamed to the current AP + iWlanContextImpl.Reassociate() && + // we have not yet indicated to WLAN Mgmt Client the + // opportunity to perform tests on the current AP + !iWlanContextImpl.ApTestOpportunityIndicated() ) + { + // start to seek for the test opportunity + iWlanContextImpl.ApTestOpportunitySeekStarted( ETrue ); + + OsTracePrint( KUmacDetails, (TUint8*) + ("UMAC: WlanDynamicPowerModeMgmtCntx::StartPowerModeManagement: Start AP test opportunity seek") ); + } + + RegisterToActiveTimeout(); + RegisterToDeepPsTimeout(); + break; + case EDeepPs: + OsTracePrint( KPwrStateTransition, (TUint8*) + ("UMAC: WlanDynamicPowerModeMgmtCntx::StartPowerModeManagement: Activating Deep PS mode context") ); + + iActiveCntx = &iDeepPsModeCntx; + break; + default: + // implementation error + OsAssert( + (TUint8*)("UMAC: panic"), + (TUint8*)(WLAN_FILE), + __LINE__ ); + } + + // reset active context prior use + iActiveCntx->Reset(); + // and also reset the state change flag + iStateChange = EFalse; + } + else + { + // we already have an active context, so no action needed + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void WlanDynamicPowerModeMgmtCntx::StopPowerModeManagement() + { + if ( iActiveCntx ) + { + OsTracePrint( KPwrStateTransition, (TUint8*) + ("UMAC: WlanDynamicPowerModeMgmtCntx::StopPowerModeManagement: dynamic power mode mgmt stopped") ); + + CancelTimeouts(); + iStateChange = EFalse; + iActiveCntx = NULL; // no active context any more + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TPowerMgmtModeChange WlanDynamicPowerModeMgmtCntx::OnFrameTx( + WHA::TQueueId aQueueId, + TUint16 aEtherType ) + { + TPowerMgmtModeChange powerMgmtModeChange( ENoChange ); + + if ( iActiveCntx ) + { + // we have an active context, i.e. we are doing power mode mgmt + + if ( !iStateChange ) + { + powerMgmtModeChange = iActiveCntx->OnFrameTx( + iWlanContextImpl, + aQueueId, + aEtherType, + iIgnoreTraffic[aQueueId] ); + + if ( powerMgmtModeChange != ENoChange ) + { + // as we will do a mode change, cancel any possibly running + // power mode management timers + CancelTimeouts(); + } + } + else + { + // state change already signalled from this power mode context, + // don't do it more than once. No action needed + OsTracePrint( KPwrStateTransition, (TUint8*) + ("UMAC: WlanDynamicPowerModeMgmtCntx::OnFrameTx: statechange already signalled") ); + } + } + else + { + // dynamic power mode mgmt is not active => "No change" will be + // returned. No action needed + } + + OsTracePrint( KPwrStateTransition, (TUint8*) + ("UMAC: WlanDynamicPowerModeMgmtCntx::OnFrameTx: statechange: %d"), + powerMgmtModeChange ); + + return powerMgmtModeChange; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TPowerMgmtModeChange WlanDynamicPowerModeMgmtCntx::OnFrameRx( + WHA::TQueueId aAccessCategory, + TUint16 aEtherType, + TUint aPayloadLength, + TDaType aDaType ) + { + TPowerMgmtModeChange powerMgmtModeChange( ENoChange ); + + if ( iActiveCntx ) + { + // we have an active context, i.e. we are doing power mode mgmt + + if ( !iStateChange ) + { + powerMgmtModeChange = iActiveCntx->OnFrameRx( + iWlanContextImpl, + aAccessCategory, + aEtherType, + iIgnoreTraffic[aAccessCategory], + aPayloadLength, + aDaType ); + + if ( powerMgmtModeChange != ENoChange ) + { + // as we will do a mode change, cancel any possibly running + // power mode management timers + CancelTimeouts(); + } + } + else + { + // state change already signalled from this power mode context, + // don't do it more than once. No action needed + OsTracePrint( KPwrStateTransition, (TUint8*) + ("UMAC: WlanDynamicPowerModeMgmtCntx::OnFrameRx: statechange already signalled") ); + } + } + else + { + // dynamic power mode mgmt is not active => "No change" will be + // returned. No action needed + } + + OsTracePrint( KPwrStateTransition, (TUint8*) + ("UMAC: WlanDynamicPowerModeMgmtCntx::OnFrameRx: statechange: %d"), + powerMgmtModeChange ); + + return powerMgmtModeChange; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TBool WlanDynamicPowerModeMgmtCntx::OnActiveToLightPsTimerTimeout() + { + if ( ( iActiveCntx == &iActiveModeCntx ) && + ( iFlags & KToLightPsTimerStarted ) && + ( !iStateChange ) ) + { + iFlags &= ~KToLightPsTimerStarted; + + iStateChange = iActiveCntx->OnActiveToLightPsTimerTimeout(); + + OsTracePrint( KPwrStateTransition, (TUint8*) + ("UMAC: WlanDynamicPowerModeMgmtCntx::OnActiveToLightPsTimerTimeout: change state: %d"), + iStateChange ); + + if ( !iStateChange ) + { + RegisterToLightPsTimeout(); + } + } + else + { + // either + // the timeout occurred in a wrong context or totally without an active + // context (i.e. when we are not doing dynamic power mode mgmt) OR + // the timer is not started, i.e. the timeout occurred when we weren't + // expecting it (which means that the timeout callback had already been + // registered when we tried to cancel this timer the previous time) OR + // a state change has already been signalled from this power mode + // context. + // In all these cases the timeout is not relevant and we take no action + OsTracePrint( KPwrStateTransition, (TUint8*) + ("UMAC: WlanDynamicPowerModeMgmtCntx::OnActiveToLightPsTimerTimeout: not relevant timeout") ); + } + + return iStateChange; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TBool WlanDynamicPowerModeMgmtCntx::OnLightPsToActiveTimerTimeout() + { + if ( ( iActiveCntx == &iLightPsModeCntx ) && + ( iFlags & KToActiveTimerStarted ) && + ( !iStateChange ) ) + { + iFlags &= ~KToActiveTimerStarted; + + iStateChange = iActiveCntx->OnLightPsToActiveTimerTimeout( + iWlanContextImpl ); + + OsTracePrint( KPwrStateTransition, (TUint8*) + ("UMAC: WlanDynamicPowerModeMgmtCntx::OnLightPsToActiveTimerTimeout: change state: %d"), + iStateChange ); + + // as we currently never do a mode change when this timeout occurs, + // we arm the timer again + RegisterToActiveTimeout(); + } + else + { + // either + // the timeout occurred in a wrong context or totally without an active + // context (i.e. when we are not doing dynamic power mode mgmt) OR + // the timer is not started, i.e. the timeout occurred when we weren't + // expecting it (which means that the timeout callback had already been + // registered when we tried to cancel this timer the previous time) OR + // a state change has already been signalled from this power mode + // context. + // In all these cases the timeout is not relevant and we take no action + OsTracePrint( KPwrStateTransition, (TUint8*) + ("UMAC: WlanDynamicPowerModeMgmtCntx::OnLightPsToActiveTimerTimeout: not relevant timeout") ); + } + + return iStateChange; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TBool WlanDynamicPowerModeMgmtCntx::OnLightPsToDeepPsTimerTimeout() + { + if ( ( iActiveCntx == &iLightPsModeCntx ) && + ( iFlags & KToDeepPsTimerStarted ) && + ( !iStateChange ) ) + { + iFlags &= ~KToDeepPsTimerStarted; + + iStateChange = iActiveCntx->OnLightPsToDeepPsTimerTimeout(); + + OsTracePrint( KPwrStateTransition, (TUint8*) + ("UMAC: WlanDynamicPowerModeMgmtCntx::OnLightPsToDeepPsTimerTimeout: change state: %d"), + iStateChange ); + + if ( !iStateChange ) + { + RegisterToDeepPsTimeout(); + } + } + else + { + // either + // the timeout occurred in a wrong context or totally without an active + // context (i.e. when we are not doing dynamic power mode mgmt) OR + // the timer is not started, i.e. the timeout occurred when we weren't + // expecting it (which means that the timeout callback had already been + // registered when we tried to cancel this timer the previous time) OR + // a state change has already been signalled from this power mode + // context. + // In all these cases the timeout is not relevant and we take no action + OsTracePrint( KPwrStateTransition, (TUint8*) + ("UMAC: WlanDynamicPowerModeMgmtCntx::OnLightPsToDeepPsTimerTimeout: not relevant timeout") ); + } + + return iStateChange; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void WlanDynamicPowerModeMgmtCntx::SetParameters( + TUint32 aToLightPsTimeout, + TUint16 aToLightPsFrameThreshold, + TUint32 aToActiveTimeout, + TUint16 aToActiveFrameThreshold, + TUint32 aToDeepPsTimeout, + TUint16 aToDeepPsFrameThreshold, + TUint16 aUapsdRxFrameLengthThreshold ) + { + OsTracePrint( KPwrStateTransition, (TUint8*) + ("UMAC: WlanDynamicPowerModeMgmtCntx::SetParameters") ); + + iToLightPsTimeout = aToLightPsTimeout; + iActiveModeCntx.SetParameters( + aToLightPsFrameThreshold, + aUapsdRxFrameLengthThreshold ); + + iToActiveTimeout = aToActiveTimeout; + iToDeepPsTimeout = aToDeepPsTimeout; + iLightPsModeCntx.SetParameters( + aToActiveFrameThreshold, + aToDeepPsFrameThreshold, + aUapsdRxFrameLengthThreshold ); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void WlanDynamicPowerModeMgmtCntx::ConfigureTrafficOverride( + TBool aStayInPsDespiteUapsdVoiceTraffic, + TBool aStayInPsDespiteUapsdVideoTraffic, + TBool aStayInPsDespiteUapsdBestEffortTraffic, + TBool aStayInPsDespiteUapsdBackgroundTraffic, + TBool aStayInPsDespiteLegacyVoiceTraffic, + TBool aStayInPsDespiteLegacyVideoTraffic, + TBool aStayInPsDespiteLegacyBestEffortTraffic, + TBool aStayInPsDespiteLegacyBackgroundTraffic ) + { + if ( aStayInPsDespiteUapsdVoiceTraffic ) + { + iFlags |= KStayInPsDespiteUapsdVoiceTraffic; + } + else + { + iFlags &= ~KStayInPsDespiteUapsdVoiceTraffic; + } + + if ( aStayInPsDespiteUapsdVideoTraffic ) + { + iFlags |= KStayInPsDespiteUapsdVideoTraffic; + } + else + { + iFlags &= ~KStayInPsDespiteUapsdVideoTraffic; + } + + if ( aStayInPsDespiteUapsdBestEffortTraffic ) + { + iFlags |= KStayInPsDespiteUapsdBestEffortTraffic; + } + else + { + iFlags &= ~KStayInPsDespiteUapsdBestEffortTraffic; + } + + if ( aStayInPsDespiteUapsdBackgroundTraffic ) + { + iFlags |= KStayInPsDespiteUapsdBackgroundTraffic; + } + else + { + iFlags &= ~KStayInPsDespiteUapsdBackgroundTraffic; + } + + if ( aStayInPsDespiteLegacyVoiceTraffic ) + { + iFlags |= KStayInPsDespiteLegacyVoiceTraffic; + } + else + { + iFlags &= ~KStayInPsDespiteLegacyVoiceTraffic; + } + + if ( aStayInPsDespiteLegacyVideoTraffic ) + { + iFlags |= KStayInPsDespiteLegacyVideoTraffic; + } + else + { + iFlags &= ~KStayInPsDespiteLegacyVideoTraffic; + } + + if ( aStayInPsDespiteLegacyBestEffortTraffic ) + { + iFlags |= KStayInPsDespiteLegacyBestEffortTraffic; + } + else + { + iFlags &= ~KStayInPsDespiteLegacyBestEffortTraffic; + } + + if ( aStayInPsDespiteLegacyBackgroundTraffic ) + { + iFlags |= KStayInPsDespiteLegacyBackgroundTraffic; + } + else + { + iFlags &= ~KStayInPsDespiteLegacyBackgroundTraffic; + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void WlanDynamicPowerModeMgmtCntx::FreezeTrafficOverride() + { + if ( iWlanContextImpl.UapsdUsedForBestEffort() ) + { + iIgnoreTraffic[WHA::ELegacy] = StayInPsDespiteUapsdBestEffortTraffic() ? + ETrue : EFalse; + } + else + { + iIgnoreTraffic[WHA::ELegacy] = StayInPsDespiteLegacyBestEffortTraffic() ? + ETrue : EFalse; + } + + if ( iWlanContextImpl.UapsdUsedForBackground() ) + { + iIgnoreTraffic[WHA::EBackGround] = StayInPsDespiteUapsdBackgroundTraffic() ? + ETrue : EFalse; + } + else + { + iIgnoreTraffic[WHA::EBackGround] = StayInPsDespiteLegacyBackgroundTraffic() ? + ETrue : EFalse; + } + + if ( iWlanContextImpl.UapsdUsedForVideo() ) + { + iIgnoreTraffic[WHA::EVideo] = StayInPsDespiteUapsdVideoTraffic() ? + ETrue : EFalse; + } + else + { + iIgnoreTraffic[WHA::EVideo] = StayInPsDespiteLegacyVideoTraffic() ? + ETrue : EFalse; + } + + if ( iWlanContextImpl.UapsdUsedForVoice() ) + { + iIgnoreTraffic[WHA::EVoice] = StayInPsDespiteUapsdVoiceTraffic() ? + ETrue : EFalse; + } + else + { + iIgnoreTraffic[WHA::EVoice] = StayInPsDespiteLegacyVoiceTraffic() ? + ETrue : EFalse; + } + +#ifndef NDEBUG + OsTracePrint( KPwrStateTransition | KQos, (TUint8*) + ("UMAC: WlanDynamicPowerModeMgmtCntx::FreezeTrafficOverride: traffic ignoration for BE, BG, VI, VO, HCCA frozen to:") ); + + for ( TUint accessCategory = WHA::ELegacy; + accessCategory < WHA::EQueueIdMax; + ++accessCategory ) + { + OsTracePrint( KPwrStateTransition | KQos, (TUint8*) + ("UMAC: WlanDynamicPowerModeMgmtCntx::FreezeTrafficOverride: ignore traffic: %d"), + iIgnoreTraffic[accessCategory] ); + } +#endif // !NDEBUG + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void WlanDynamicPowerModeMgmtCntx::RegisterToLightPsTimeout() + { + if ( !( iFlags & KToLightPsTimerStarted ) ) + { + iFlags |= KToLightPsTimerStarted; + + iWlanContextImpl.iUmac.RegisterTimeout( + iToLightPsTimeout, + EWlanActiveToLightPsTimer ); + } + else + { + // timer already running; no action needed + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void WlanDynamicPowerModeMgmtCntx::RegisterToActiveTimeout() + { + if ( !( iFlags & KToActiveTimerStarted ) ) + { + iFlags |= KToActiveTimerStarted; + + iWlanContextImpl.iUmac.RegisterTimeout( + iToActiveTimeout, + EWlanLightPsToActiveTimer ); + } + else + { + // timer already running; no action needed + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void WlanDynamicPowerModeMgmtCntx::RegisterToDeepPsTimeout() + { + if ( !( iFlags & KToDeepPsTimerStarted ) ) + { + iFlags |= KToDeepPsTimerStarted; + + iWlanContextImpl.iUmac.RegisterTimeout( + iToDeepPsTimeout, + EWlanLightPsToDeepPsTimer ); + } + else + { + // timer already running; no action needed + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void WlanDynamicPowerModeMgmtCntx::CancelToLightPsTimeout() + { + if ( iFlags & KToLightPsTimerStarted ) + { + iFlags &= ~KToLightPsTimerStarted; + iWlanContextImpl.iUmac.CancelTimeout( EWlanActiveToLightPsTimer ); + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void WlanDynamicPowerModeMgmtCntx::CancelToActiveTimeout() + { + if ( iFlags & KToActiveTimerStarted ) + { + iFlags &= ~KToActiveTimerStarted; + iWlanContextImpl.iUmac.CancelTimeout( EWlanLightPsToActiveTimer ); + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void WlanDynamicPowerModeMgmtCntx::CancelToDeepPsTimeout() + { + if ( iFlags & KToDeepPsTimerStarted ) + { + iFlags &= ~KToDeepPsTimerStarted; + iWlanContextImpl.iUmac.CancelTimeout( EWlanLightPsToDeepPsTimer ); + } + }