--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/wlan_bearer/wlanldd/wlan_common/umac_common/src/UmacTxRateAdaptation.cpp Tue Feb 02 02:03:13 2010 +0200
@@ -0,0 +1,788 @@
+/*
+* Copyright (c) 2002-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 WlanTxRateAdaptation class
+*
+*/
+
+/*
+* %version: 21 %
+*/
+
+#include "config.h"
+#include "UmacTxRateAdaptation.h"
+#include "UmacContextImpl.h"
+#include "wha_mibDefaultvalues.h"
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+WlanTxRateAdaptation::WlanTxRateAdaptation()
+ {
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::WlanTxRateAdaptation()"));
+
+ // default values for the rate adaptation algorithm parameters
+ //
+ const TUint8 KDefaultMinStepUpCheckpoint = 10;
+ const TUint8 KDefaultMaxStepUpCheckpoint = 60;
+ const TUint8 KDefaultStepUpCheckpointFactor = 2;
+ const TUint8 KDefaultStepDownCheckpoint = 3;
+ const TUint8 KDefaultMinStepUpThreshold = 70;
+ const TUint8 KDefaultMaxStepUpThreshold = 90;
+ const TUint8 KDefaultStepUpThresholdIncrement = 10;
+ const TUint8 KDefaultStepDownThreshold = 50;
+
+ iAlgorithmParam.iMinStepUpCheckpoint =
+ KDefaultMinStepUpCheckpoint;
+
+ iAlgorithmParam.iMaxStepUpCheckpoint =
+ KDefaultMaxStepUpCheckpoint;
+
+ iAlgorithmParam.iStepUpCheckpointFactor =
+ KDefaultStepUpCheckpointFactor;
+
+ iAlgorithmParam.iStepDownCheckpoint =
+ KDefaultStepDownCheckpoint;
+
+ iAlgorithmParam.iMinStepUpThreshold =
+ KDefaultMinStepUpThreshold;
+
+ iAlgorithmParam.iMaxStepUpThreshold =
+ KDefaultMaxStepUpThreshold;
+
+ iAlgorithmParam.iStepUpThresholdIncrement =
+ KDefaultStepUpThresholdIncrement;
+
+ iAlgorithmParam.iStepDownThreshold =
+ KDefaultStepDownThreshold;
+
+ iAlgorithmParam.iDisableProbeHandling = EFalse;
+
+ for ( TUint32 j = 0; j != WHA::EQueueIdMax; ++j )
+ {
+ // initially every Tx queue is mapped to the same (general) Tx
+ // policy
+ iQueue2Policy[j] = WHA::KDefaultTxRatePolicyId;
+ }
+
+ for ( TUint32 i = 0; i != KMaxRatePolicyCount; ++i )
+ {
+ iPolicy[i].iCurrentTxRate = NULL;
+ iPolicy[i].iHead = NULL;
+ iPolicy[i].iTail = NULL;
+ iPolicy[i].iNumOfRates = 0;
+
+ iPolicy[i].iProbe = EFalse;
+ iPolicy[i].iTxCount = 0;
+ iPolicy[i].iTxFailCount = 0;
+ iPolicy[i].iStepUpCheckpoint = KDefaultMinStepUpCheckpoint;
+ iPolicy[i].iStepUpThreshold = KDefaultMinStepUpThreshold;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void WlanTxRateAdaptation::RateStepDown( SPolicy& aPolicy ) const
+ {
+ OsTracePrint( KTxRateAdapt,
+ (TUint8*)("UMAC: WlanTxRateAdaptation::RateStepDown(): old rate: 0x%08x"),
+ aPolicy.iCurrentTxRate->iBitRate);
+
+ if ( aPolicy.iCurrentTxRate->iPrev )
+ {
+ // descent rate
+ aPolicy.iCurrentTxRate = aPolicy.iCurrentTxRate->iPrev;
+
+ OsTracePrint( KTxRateAdapt,
+ (TUint8*)("UMAC: WlanTxRateAdaptation::RateStepDown(): new rate: 0x%08x"),
+ aPolicy.iCurrentTxRate->iBitRate);
+ }
+ else
+ {
+ // we are already using the lowest rate
+ // nothing to do
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::RateStepDown(): already using the lowest rate") );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TBool WlanTxRateAdaptation::RateStepUp( SPolicy& aPolicy ) const
+ {
+ OsTracePrint( KTxRateAdapt,
+ (TUint8*)("UMAC: WlanTxRateAdaptation::RateStepUp(): old rate: 0x%08x"),
+ aPolicy.iCurrentTxRate->iBitRate);
+
+ TBool status( ETrue );
+
+ if ( aPolicy.iCurrentTxRate->iNext )
+ {
+ // ascend rate
+ aPolicy.iCurrentTxRate = aPolicy.iCurrentTxRate->iNext;
+
+ OsTracePrint( KTxRateAdapt,
+ (TUint8*)("UMAC: WlanTxRateAdaptation::RateStepUp(): new rate: 0x%08x"),
+ aPolicy.iCurrentTxRate->iBitRate);
+ }
+ else
+ {
+ // we are already using the highest rate.
+ // Indicate that to the caller
+ status = EFalse;
+
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::RateStepUp(): already using the highest rate") );
+ }
+
+ return status;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void WlanTxRateAdaptation::InsertRate(
+ TUint8 aPolicyIndex, SBitRate* aBlock ) const
+ {
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::InsertRate(): aPolicyIndex: %d"),
+ aPolicyIndex);
+ OsTracePrint( KTxRateAdapt,
+ (TUint8*)("UMAC: WlanTxRateAdaptation::InsertRate(): rate: 0x%08x"),
+ aBlock->iBitRate);
+
+ // traverse our single linked list of rate entrys
+ // and locate the correct place for the new rate
+ SBitRate* ptr = iPolicy[aPolicyIndex].iHead;
+ SBitRate* prev = ptr;
+
+ do
+ {
+ if ( aBlock->iBitRate < ptr->iBitRate )
+ {
+ // rate to be inserted is smaller than
+ // the "current" rate
+ break;
+ }
+
+ prev = ptr;
+ ptr = ptr->iNext;
+ }
+ while ( ptr );
+
+ if ( ptr )
+ {
+ // correct slot found
+ // link the new rate
+ prev->iNext = aBlock;
+ aBlock->iPrev = prev;
+ aBlock->iNext = ptr;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TBool WlanTxRateAdaptation::AppendRate(
+ TUint8 aPolicyIndex,
+ WHA::TRate aRate )
+ {
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::AppendRate(): aPolicyIndex: %d"),
+ aPolicyIndex);
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::AppendRate(): rate: 0x%08x"), aRate);
+
+ // allocate a new block for the rate
+ SBitRate* block
+ = static_cast<SBitRate*>(os_alloc( sizeof(SBitRate) ));
+
+ if ( !block )
+ {
+ // alloc failure; we cannot continue
+ OsTracePrint( KErrorLevel,
+ (TUint8*)("UMAC: WlanTxRateAdaptation::AppendRate(): alloc failure"));
+
+ return EFalse;
+ }
+
+ block->iBitRate = aRate;
+ block->iNext = NULL;
+ block->iPrev = NULL;
+
+ if ( !iPolicy[aPolicyIndex].iHead )
+ {
+ // this is the first append
+
+ iPolicy[aPolicyIndex].iHead = block;
+ iPolicy[aPolicyIndex].iTail = iPolicy[aPolicyIndex].iHead;
+ iPolicy[aPolicyIndex].iCurrentTxRate = block;
+ ++iPolicy[aPolicyIndex].iNumOfRates;
+ }
+ else
+ {
+ // not the first rate to append
+
+ if ( block->iBitRate > iPolicy[aPolicyIndex].iTail->iBitRate )
+ {
+ // new rate bigger than the last one
+ // append to rear
+ iPolicy[aPolicyIndex].iTail->iNext = block;
+ block->iPrev = iPolicy[aPolicyIndex].iTail;
+ // new tail
+ iPolicy[aPolicyIndex].iTail = block;
+ ++iPolicy[aPolicyIndex].iNumOfRates;
+ }
+ else if( block->iBitRate < iPolicy[aPolicyIndex].iTail->iBitRate )
+ {
+ // new rate smaller than the last one
+ // insert the rate to the correct slot
+ InsertRate( aPolicyIndex, block );
+ ++iPolicy[aPolicyIndex].iNumOfRates;
+ }
+ else
+ {
+ // new rate equal to the last one
+ // this cannot happen as we are setting the rates only once
+ // and from a rate bitmask
+ }
+ }
+
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::AppendRate(): num of existing rates: %d"),
+ iPolicy[aPolicyIndex].iNumOfRates);
+
+ return ETrue;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void WlanTxRateAdaptation::Reset( SPolicy& aPolicy ) const
+ {
+ OsTracePrint( KTxRateAdapt,
+ (TUint8*)("UMAC: WlanTxRateAdaptation::Reset() a policy"));
+
+ // dealloc all rates
+ SBitRate* ptr = aPolicy.iHead;
+ SBitRate* cache = ptr;
+
+ while ( ptr )
+ {
+ cache = ptr;
+ ptr = ptr->iNext;
+
+ // free the previous one
+ os_free( cache );
+ }
+
+ aPolicy.iCurrentTxRate = NULL;
+ aPolicy.iHead = NULL;
+ aPolicy.iTail = NULL;
+ aPolicy.iNumOfRates = 0;
+
+ aPolicy.iProbe = EFalse;
+ aPolicy.iTxCount = 0;
+ aPolicy.iTxFailCount = 0;
+ aPolicy.iStepUpCheckpoint = iAlgorithmParam.iMinStepUpCheckpoint;
+ aPolicy.iStepUpThreshold = iAlgorithmParam.iMinStepUpThreshold;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TBool WlanTxRateAdaptation::SetRates(
+ TUint8 aPolicyId,
+ WHA::TRate aRateBitmask )
+ {
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::SetRates(): aPolicyId: 0x%08x"), aPolicyId);
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::SetRates(): aRateBitmask: 0x%08x"), aRateBitmask);
+
+ // make the list of rates; but 1st clear the list
+ Reset( iPolicy[aPolicyId - 1] );
+
+ // make rates from bitmask
+ const TUint32 cntr_end( 32 );
+ TUint32 cntr( 0 );
+
+ for ( TUint32 bit = 1 ; cntr != cntr_end ; (bit <<= 1) )
+ {
+ if ( aRateBitmask & bit )
+ {
+ // rate is to be set
+ if ( !AppendRate( aPolicyId - 1, aRateBitmask & bit ) )
+ {
+ return EFalse;
+ }
+ }
+
+ ++cntr;
+ }
+
+ // if we got this far, the rates are now in the list
+
+ return ETrue;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void WlanTxRateAdaptation::SetPolicy(
+ WHA::TQueueId aQueueId,
+ TUint8 aPolicyId )
+ {
+ OsTracePrint( KTxRateAdapt,
+ (TUint8*)("UMAC: WlanTxRateAdaptation::SetPolicy(): aQueueId: %d"),
+ aQueueId);
+ OsTracePrint( KTxRateAdapt,
+ (TUint8*)("UMAC: WlanTxRateAdaptation::SetPolicy(): aPolicyId: %d"),
+ aPolicyId);
+
+ iQueue2Policy[aQueueId] = aPolicyId;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void WlanTxRateAdaptation::SetCurrentMaxTxRate(
+ TUint8 aPolicyId,
+ WHA::TRate aRate )
+ {
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::SetCurrentMaxTxRate(): aPolicyId: %d"),
+ aPolicyId );
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::SetCurrentMaxTxRate(): aRate: 0x%08x"),
+ aRate );
+
+ if ( !iPolicy[aPolicyId - 1].iNumOfRates )
+ {
+ // catch implementation error
+ OsAssert( (TUint8*)("UMAC: panic: no rates defined"),
+ (TUint8*)(WLAN_FILE), __LINE__ );
+ }
+
+ // traverse our single linked list of rate entrys from rear (i.e. from
+ // the highest) to front (i.e. to the lowest) and try to locate the
+ // provided rate entry, or the next lower one, so that it can be set as
+ // the current max tx rate
+
+ SBitRate* ptr = iPolicy[aPolicyId - 1].iTail;
+
+ do
+ {
+ if ( ptr->iBitRate <= aRate )
+ {
+ // found
+ break;
+ }
+ else
+ {
+ ptr = ptr->iPrev;
+ }
+ }
+ while ( ptr );
+
+ if ( ptr )
+ {
+ // usable rate was found. Set it as the current rate
+ iPolicy[aPolicyId - 1].iCurrentTxRate = ptr;
+ }
+ else
+ {
+ // the provided max Tx rate is lower than any of the
+ // rates in this rate policy. In this case we have to set the
+ // lowest rate in the policy as the current rate (even
+ // though it is higher than what was requested)
+ iPolicy[aPolicyId - 1].iCurrentTxRate = iPolicy[aPolicyId - 1].iHead;
+ }
+
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::SetCurrentMaxTxRate(): current rate now set to: 0x%08x"),
+ iPolicy[aPolicyId - 1].iCurrentTxRate->iBitRate );
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void WlanTxRateAdaptation::SetAlgorithmParameters(
+ TUint8 aMinStepUpCheckpoint,
+ TUint8 aMaxStepUpCheckpoint,
+ TUint8 aStepUpCheckpointFactor,
+ TUint8 aStepDownCheckpoint,
+ TUint8 aMinStepUpThreshold,
+ TUint8 aMaxStepUpThreshold,
+ TUint8 aStepUpThresholdIncrement,
+ TUint8 aStepDownThreshold,
+ TBool aDisableProbeHandling )
+ {
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::SetAlgorithmParameters") );
+
+ iAlgorithmParam.iMinStepUpCheckpoint = aMinStepUpCheckpoint;
+ iAlgorithmParam.iMaxStepUpCheckpoint = aMaxStepUpCheckpoint;
+ iAlgorithmParam.iStepUpCheckpointFactor = aStepUpCheckpointFactor;
+ iAlgorithmParam.iStepDownCheckpoint = aStepDownCheckpoint;
+ iAlgorithmParam.iMinStepUpThreshold = aMinStepUpThreshold;
+ iAlgorithmParam.iMaxStepUpThreshold = aMaxStepUpThreshold;
+ iAlgorithmParam.iStepUpThresholdIncrement = aStepUpThresholdIncrement;
+ iAlgorithmParam.iStepDownThreshold = aStepDownThreshold;
+ iAlgorithmParam.iDisableProbeHandling = aDisableProbeHandling;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void WlanTxRateAdaptation::RatePolicy(
+ const WlanContextImpl& aCtxImpl,
+ WHA::TQueueId aQueueId,
+ TBool aUseSpecialRatePolicy,
+ WHA::TRate& aRate,
+ TUint8& aPolicyId ) const
+ {
+ aPolicyId = iQueue2Policy[aQueueId];
+
+ if ( aCtxImpl.WHASettings().iCapability &
+ WHA::SSettings::KAutonomousRateAdapt )
+ {
+ // autonomous rate adaptation is being used, i.e. rate adaptation is
+ // handled by lower layers. In this case it's not relevant to specify
+ // a Max Tx Rate and the whole value is not applicable. So we return
+ // zero
+ const WHA::TRate notRelevant( 0 );
+ aRate = notRelevant;
+
+ const TUint8 KSpecialTxAutoRatePolicy =
+ aCtxImpl.SpecialTxAutoRatePolicy();
+
+ if ( aUseSpecialRatePolicy && KSpecialTxAutoRatePolicy )
+ {
+ aPolicyId = KSpecialTxAutoRatePolicy;
+ }
+ }
+ else
+ {
+ // rate adaptation is handled by this object
+
+ if ( !iPolicy[aPolicyId - 1].iNumOfRates )
+ {
+ OsAssert( (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::RatePolicy(): panic: no rates defined"),
+ (TUint8*)(WLAN_FILE), __LINE__ );
+ }
+
+ if ( !iPolicy[aPolicyId - 1].iCurrentTxRate )
+ {
+ // catch implementation error
+
+ OsTracePrint( KErrorLevel,
+ (TUint8*)("UMAC: no current rate specified for policy id: %d"),
+ aPolicyId );
+ OsAssert( (TUint8*)("UMAC: panic"), (TUint8*)(WLAN_FILE), __LINE__ );
+ }
+
+ // return the current Max Tx Rate
+ aRate = iPolicy[aPolicyId - 1].iCurrentTxRate->iBitRate;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void WlanTxRateAdaptation::OnTxCompleted(
+ WHA::TRate aRate,
+ TBool aSuccess,
+ WHA::TQueueId aQueueId,
+ WHA::TRate aRequestedRate )
+ {
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::OnTxCompleted(): aRate: 0x%08x"),
+ aRate);
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::OnTxCompleted(): aSuccess: %d"),
+ aSuccess);
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::OnTxCompleted(): aQueueId: %d"),
+ aQueueId);
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::OnTxCompleted(): aRequestedRate: 0x%08x"),
+ aRequestedRate);
+
+ TBool success( aSuccess );
+
+ TUint8 policyId = iQueue2Policy[aQueueId];
+ OsTracePrint( KTxRateAdapt,
+ (TUint8*)("UMAC: WlanTxRateAdaptation::OnTxCompleted(): policyId: %d"),
+ policyId);
+
+ if ( iPolicy[policyId - 1].iCurrentTxRate )
+ {
+ // as Current Tx Rate is defined for this policy, it means that
+ // this rate adaptation object is configured and we can handle this
+ // event
+
+ if ( aSuccess )
+ {
+ // the frame was successfully delivered to nw
+
+ // from rate adaptation point of view we are interested in the
+ // actual Tx rate of the frame only if the current rate for the Tx
+ // policy in question is still the same as the originally requested Tx
+ // rate for this frame.
+ // (After we have switched the curent rate to something else, we may
+ // still receive Tx completions for frames which we have requested to
+ // be sent with the previous rate. We are not interested in their
+ // actual Tx rate any more.)
+ if ( aRequestedRate == iPolicy[policyId - 1].iCurrentTxRate->iBitRate )
+ {
+ if ( aRate != aRequestedRate )
+ {
+ // actual Tx rate was different than the originally requested
+ // rate. This is a Tx "failure" from Tx rate adaptation point
+ // of view
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::OnTxCompleted(): succeeded with a different rate than requested"));
+ success = EFalse;
+ }
+ }
+ else
+ {
+ // curent rate of the Tx policy in question not the same any more
+ // as the originally requested rate for this frame. The frame is
+ // ignored from Tx rate adaptation considerations
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::OnTxCompleted(): current rate for this Tx policy not same any more as originally requested rate for this frame"));
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::OnTxCompleted(): frame ignored from Tx rate adaptation considerations"));
+ return;
+ }
+ }
+
+ TRateStep rateStep = OnTxCompleted( success, iPolicy[policyId - 1] );
+
+ switch ( rateStep )
+ {
+ case EStepUp:
+ if ( RateStepUp( iPolicy[policyId - 1] ) )
+ {
+ // step up succeeded (i.e. there was a higher rate to switch to)
+
+ // if probe frame handling hasn't been disabled, the next
+ // transmitted frame will be handled as a probe frame
+ if ( !iAlgorithmParam.iDisableProbeHandling )
+ {
+ iPolicy[policyId - 1].iProbe = ETrue;
+ }
+ }
+ break;
+ case EStepDown:
+ RateStepDown( iPolicy[policyId - 1] );
+ break;
+ case EKeepCurrent:
+ // nothing to do here
+ break;
+ default:
+ OsTracePrint( KErrorLevel,
+ (TUint8*)("UMAC: unkown rate step: %d"),
+ rateStep );
+ OsAssert( (TUint8*)("UMAC: panic"), (TUint8*)(WLAN_FILE), __LINE__ );
+ }
+ }
+ else
+ {
+ // Current Tx Rate is not defined for this policy, which means that
+ // this rate adaptation object is not configured (it has been
+ // reset) and cannot handle the event. So we just discard it
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::OnTxCompleted(): Rate adaptation not configured. Tx complete event discarded"));
+ }
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void WlanTxRateAdaptation::Reset()
+ {
+ OsTracePrint( KTxRateAdapt,
+ (TUint8*)("UMAC: WlanTxRateAdaptation::Reset() the whole object"));
+
+ for ( TUint32 j = 0; j != WHA::EQueueIdMax; ++j )
+ {
+ // every Tx queue is mapped to the same (general) Tx policy
+ iQueue2Policy[j] = WHA::KDefaultTxRatePolicyId;
+ }
+
+ for ( TUint32 i = 0; i != KMaxRatePolicyCount; ++i )
+ {
+ // reset the state of every individual Tx policy
+ Reset( iPolicy[i] );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// Note: The rate adaptation algorithm requires that:
+// iStepDownCheckpoint <= iStepUpCheckpoint and
+// iStepDownCheckpoint > 1 (or it can also be == 1 if iDisableProbeHandling
+// is ETrue)
+// ---------------------------------------------------------------------------
+//
+WlanTxRateAdaptation::TRateStep WlanTxRateAdaptation::OnTxCompleted(
+ TBool aSuccess,
+ SPolicy& aPolicy ) const
+ {
+ TRateStep rateStep( EKeepCurrent );
+
+ ++aPolicy.iTxCount;
+
+ if ( !aSuccess )
+ {
+ ++aPolicy.iTxFailCount;
+ }
+
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::OnTxCompleted(): iProbe (0 no/1 yes): %d"),
+ aPolicy.iProbe );
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::OnTxCompleted(): iTxCount after counting this frame: %d"),
+ aPolicy.iTxCount );
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::OnTxCompleted(): iTxFailCount after counting this frame: %d"),
+ aPolicy.iTxFailCount );
+ OsTracePrint( KTxRateAdapt,
+ (TUint8*)("UMAC: WlanTxRateAdaptation::OnTxCompleted(): iCurrentTxRate: 0x%08x"),
+ aPolicy.iCurrentTxRate->iBitRate);
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::OnTxCompleted(): iStepUpCheckpoint: %d"),
+ aPolicy.iStepUpCheckpoint );
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::OnTxCompleted(): iStepUpThreshold: %d"),
+ aPolicy.iStepUpThreshold );
+
+ if ( aPolicy.iProbe )
+ {
+ // this was a probe frame; check if a rate change is needed
+
+ if ( !aSuccess )
+ {
+ // either the Tx failed completely or it succeeded at a lower
+ // rate than requested
+
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::OnTxCompleted(): probe failure"));
+
+ // decrement the rate
+ rateStep = EStepDown;
+
+ aPolicy.iStepUpCheckpoint =
+ ( aPolicy.iStepUpCheckpoint *
+ iAlgorithmParam.iStepUpCheckpointFactor
+ > iAlgorithmParam.iMaxStepUpCheckpoint ) ?
+ iAlgorithmParam.iMaxStepUpCheckpoint :
+ aPolicy.iStepUpCheckpoint *
+ iAlgorithmParam.iStepUpCheckpointFactor;
+
+ aPolicy.iStepUpThreshold =
+ ( aPolicy.iStepUpThreshold +
+ iAlgorithmParam.iStepUpThresholdIncrement
+ > iAlgorithmParam.iMaxStepUpThreshold ) ?
+ iAlgorithmParam.iMaxStepUpThreshold :
+ aPolicy.iStepUpThreshold +
+ iAlgorithmParam.iStepUpThresholdIncrement;
+
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::OnTxCompleted(): new iStepUpCheckpoint: %d"),
+ aPolicy.iStepUpCheckpoint );
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::OnTxCompleted(): new iStepUpThreshold: %d"),
+ aPolicy.iStepUpThreshold );
+
+ aPolicy.iTxCount = 0;
+ aPolicy.iTxFailCount = 0;
+ }
+ else
+ {
+ // Tx success with requested rate; nothing more to do
+ }
+
+ // in any case clear the probe flag
+ aPolicy.iProbe = EFalse;
+ }
+ else
+ {
+ if ( aPolicy.iTxCount % iAlgorithmParam.iStepDownCheckpoint == 0 )
+ {
+ // check if the rate should be decremented
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::OnTxCompleted(): check for decrement need"));
+
+ if ( aPolicy.iTxFailCount * 100
+ >= iAlgorithmParam.iStepDownThreshold * aPolicy.iTxCount )
+ {
+ // at least iStepDownThreshold % of iTxCount frames have
+ // "failed" => decrement rate
+ //
+ rateStep = EStepDown;
+ aPolicy.iStepUpCheckpoint =
+ iAlgorithmParam.iMinStepUpCheckpoint;
+ aPolicy.iStepUpThreshold =
+ iAlgorithmParam.iMinStepUpThreshold;
+
+ aPolicy.iTxCount = 0;
+ aPolicy.iTxFailCount = 0;
+ }
+ }
+
+ if ( rateStep != EStepDown &&
+ aPolicy.iTxCount >= aPolicy.iStepUpCheckpoint )
+ {
+ // check if the rate should be incremented
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::OnTxCompleted(): check for increment need"));
+
+ if ( ( aPolicy.iTxCount - aPolicy.iTxFailCount ) * 100
+ >= aPolicy.iStepUpThreshold * aPolicy.iTxCount )
+ {
+ // at least iStepUpThreshold % of iTxCount frames have
+ // "succeeded" => increment rate
+ //
+ rateStep = EStepUp;
+ }
+
+ aPolicy.iTxCount = 0;
+ aPolicy.iTxFailCount = 0;
+ }
+ }
+
+ OsTracePrint( KTxRateAdapt, (TUint8*)
+ ("UMAC: WlanTxRateAdaptation::OnTxCompleted(): rateStep: %d (keep = 0, down, up)"),
+ rateStep );
+
+ return rateStep;
+ }