wlan_bearer/wlanldd/wlan_common/umac_common/src/umacdynamicpowermodemgmtcntx.cpp
changeset 0 c40eb8fe8501
child 25 a0fdcd0e4c56
--- /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 );
+        }
+    }