wlan_bearer/wlanldd/wlan_common/umac_common/src/umacpacketscheduler.cpp
changeset 0 c40eb8fe8501
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wlan_bearer/wlanldd/wlan_common/umac_common/src/umacpacketscheduler.cpp	Tue Feb 02 02:03:13 2010 +0200
@@ -0,0 +1,851 @@
+/*
+* Copyright (c) 2005-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:   The one and only packet scheduler
+*
+*/
+
+/*
+* %version: 28 %
+*/
+
+#include "config.h"
+#include "umacpacketscheduler.h"
+#include "umacpacketschedulerclient.h"
+#include "UmacContextImpl.h"
+
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+WlanPacketScheduler::WlanPacketScheduler( 
+    MWlanPacketSchedulerClient& aWlanPacketSchedulerClient ) 
+    : iPacketSchedulerClient(aWlanPacketSchedulerClient), 
+    iCurrent( NULL ), 
+    iTxPipelineActive( ETrue ), 
+    iNumOfPackets( 0 ), 
+    iNumOfNotCompletedPackets( 0 ),
+    iFlags( 0 )
+    {
+    // initially mark all as free
+    for ( TPacketIdCntxs::iterator pos = iPacketIdCntxs.begin()
+        ; pos != iPacketIdCntxs.end() ; ++pos )
+        {
+        pos->iFree = ETrue;
+        }
+    // initially mark all as free
+    for ( TPacketElements::iterator pos = iPacketElements.begin()
+        ; pos != iPacketElements.end() ; ++pos )
+        {
+        pos->iFree = ETrue;
+        }
+    // initially mark all as free
+    fill( iQueueStates.begin(), iQueueStates.end(), EQueueNotFull );
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+TBool WlanPacketScheduler::Push(
+    WlanContextImpl& aCtxImpl,                               
+    const TAny* aPacket, 
+    TUint32 aLength, 
+    WHA::TQueueId aQueueId,
+    TUint32 aPacketId,
+    const TDataBuffer* aMetaHeader,
+    TBool aMore,
+    TBool aMulticastData,
+    TBool aUseSpecialRatePolicy )
+    {
+    OsTracePrint( KPacketScheduler, (TUint8*)
+        ("UMAC: WlanPacketScheduler::Push: aMulticastData: %d"), 
+        aMulticastData );
+   
+    SElement* free_slot = FreeElementSlot();
+    if ( !free_slot )
+        {
+        // no free element slot was found,
+        // which means that all slots are in use 
+        // we do nothing else than silently fail the operation
+        OsTracePrint( KPacketScheduler | KWarningLevel, (TUint8*)
+            ("UMAC: packetscheduler Push: no free slot found -> fail") );
+
+        // packet push failure we must signal
+        // set up a flag to signal client at later time to retry 
+        // this operation
+        iFlags |= KSignalPushPacket;
+
+        return EFalse;
+        }
+
+    // one more packet to schedule
+    ++iNumOfPackets;
+
+    // store packet send context
+    free_slot->iFree = EFalse;  // context is no longer free
+    free_slot->iPacket = aPacket;
+    free_slot->iLength = aLength;
+
+    // extract a free packet ID context
+    SPacketIdCntx* packet_id_cnxt = FreePacketIdCntx();
+    if ( !packet_id_cnxt )
+        {
+        // no free element was found
+        // we should allways enough of elements available
+        // so this issue means that we have either:
+        // 1) programming error
+        // 2) too small element storage
+        // in any case the issue must be solved at compile time not runtime
+        OsAssert( (TUint8*)("UMAC: panic"), (TUint8*)(WLAN_FILE), __LINE__ );
+        return EFalse;
+        }
+
+    ++iNumOfNotCompletedPackets;
+    OsTracePrint( KPacketScheduler, (TUint8*)
+        ("UMAC: WlanPacketScheduler::Push: the nbr of packets not yet completed by WHA layer is now: %d"),
+        iNumOfNotCompletedPackets );
+
+    // store packet ID context
+    packet_id_cnxt->iQueueId = aQueueId;
+    packet_id_cnxt->iFrameId = aPacketId;
+    packet_id_cnxt->iMetaHeader = aMetaHeader;
+    packet_id_cnxt->iFree = EFalse; // this id is no longer free
+    packet_id_cnxt->iMulticastData = aMulticastData;
+    packet_id_cnxt->iUseSpecialRatePolicy = aUseSpecialRatePolicy;
+    
+    // link packet element to packet id context
+    free_slot->iPacketIdCntx = packet_id_cnxt;
+    
+    if ( iCurrent )
+        {
+        if ( iTxPipelineActive )
+            {
+            // it is not logical to have a valid current pointer 
+            // when the tx pipeline is active
+            OsAssert( (TUint8*)("UMAC * panic"), 
+                (TUint8*)(WLAN_FILE), __LINE__ );
+            }
+
+        // we have a existing current pointer 
+        // it means that the tx pipeline is stopped
+        // lets see if the pushed packet has a 
+        // queue full status and proceed from that
+
+        if ( iQueueStates[packet_id_cnxt->iQueueId] == EQueueNotFull )
+            {
+            // as the pushed packet goes to non full queue let's 
+            // set the one with highest priority as the current packet to send
+            if ( Priority( packet_id_cnxt->iQueueId ) > 
+                 Priority( iCurrent->iPacketIdCntx->iQueueId ) )
+                {
+                iCurrent = free_slot;
+                }
+            else   
+                {
+                // no action 
+                }
+            }
+        else   // --- != EQueueNotFull ---
+            {
+            // pushed packet queue is full -> no action
+            OsTracePrint( 
+                KPacketScheduler, (TUint8*)
+                ("UMAC: WlanPacketScheduler::Push: queue for the pushed packet is full, queue id: %d"),
+                packet_id_cnxt->iQueueId );
+            }
+        }
+    else    // --- iCurrent ---
+        {
+        // we do not have a valid current pointer, which means that all
+        // the packets pending inside the scheduler have a queue full status
+        // tough luck, but we can live with it...
+        if ( iQueueStates[packet_id_cnxt->iQueueId] == EQueueNotFull )
+            {
+            // the pushed packet queue is not full queue
+            // so we shall mark it as the current one
+            iCurrent = free_slot;
+            }
+        }
+
+    if ( iTxPipelineActive && iCurrent )
+        {
+        // packet scheduling feasible
+        // as tx pipeline is active and we have a current packet to be send
+        iPacketSchedulerClient.CallPacketSchedule( aCtxImpl, aMore );
+        } 
+
+    if (
+        // push packet signalling to client flagged
+        iFlags & KSignalPushPacket 
+        // AND
+        && 
+        // packet scheduler is not full
+        !Full() )
+        {
+        iFlags &= ~KSignalPushPacket;
+        iPacketSchedulerClient.OnPacketPushPossible( aCtxImpl );
+        }
+
+    return ETrue;
+    }
+
+// ---------------------------------------------------------------------------
+// make internal state as empty
+// ---------------------------------------------------------------------------
+//
+void WlanPacketScheduler::Flush( WlanContextImpl& aCtxImpl )
+    {
+    // remove all pending packet transmission entrys
+    // and call correct completion method for user plane packets
+    OsTracePrint( 
+        KPacketScheduler, 
+        (TUint8*)("UMAC: WlanPacketScheduler::Flush") );
+
+    for ( TPacketElements::iterator pos = iPacketElements.begin(); 
+          pos != iPacketElements.end(); 
+          ++pos )
+        {
+        if ( pos->iFree == EFalse )
+            // slot in use -> complete the packet and release the slot
+            {
+            pos->iFree = ETrue;
+            iPacketSchedulerClient.OnPacketFlushEvent( 
+                aCtxImpl, 
+                pos->iPacketIdCntx->iFrameId,
+                const_cast<TDataBuffer*>(pos->iPacketIdCntx->iMetaHeader) );
+
+            // as we won't be getting a packet tx completion for this packet
+            // mark also the corresponding packet context free
+            pos->iPacketIdCntx->iFree = ETrue;
+            --iNumOfNotCompletedPackets;
+            }
+        }
+
+    // NOTE: we do not clear other packet ID contexts as there can be pending
+    // packet transmissions, which means we should get packet transmission  
+    // callbacks and we must map the context then
+
+    iCurrent = NULL;
+    iNumOfPackets = 0;
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void WlanPacketScheduler::SchedulePackets( 
+    WlanContextImpl& aCtxImpl,
+    TBool aMore )
+    {
+    if ( !(iTxPipelineActive && iCurrent) )
+        {
+        // nothing to do
+        return;
+        }
+
+    typedef 
+        Carray<
+        SPacketIdCntx*, 
+        KNumOfElements, 
+        EFalse,                 // no delete pointees
+        NoCopy<SPacketIdCntx*>  // disallow copying
+        > TPacketIdCntxsPtrs;
+
+    // this critter stores the xferred packet id contexes in case of
+    // synchronous xfer occurs and we must manullay call
+    // completion method for the frame ids
+    TPacketIdCntxsPtrs packetid_cntxs;
+    TPacketIdCntxsPtrs::iterator pos(  packetid_cntxs.begin() );
+    
+    WHA::TStatus status ( WHA::KSuccess );
+
+    // send all packets that are feasible for sending
+    // as long as the adpatation layer does not stop
+    // the tx pipeline
+    do 
+        {
+        // store current packet id context
+        *pos = iCurrent->iPacketIdCntx;
+
+
+        // trace the frame critter
+        OsTracePrint( KPacketScheduler, 
+            (TUint8*)("UMAC: scheduling dot11 packet for tx"),
+            *(reinterpret_cast<const Sdot11MacHeader*>(iCurrent->iPacket)) );
+        OsTracePrint( KPacketScheduler, (TUint8*)
+            ("UMAC: WlanPacketScheduler::SchedulePackets: queue ID: %d"), 
+            (*pos)->iQueueId );
+        OsTracePrint( KPacketScheduler, (TUint8*)
+            ("UMAC: WlanPacketScheduler::SchedulePackets: frame ID: %d"), 
+            (*pos)->iFrameId );
+        OsTracePrint( KPacketScheduler, 
+            (TUint8*)("UMAC: WlanPacketScheduler::SchedulePackets: packet id: 0x%08x"),
+            reinterpret_cast<WHA::TPacketId>(*pos) );
+
+        // are multiple packets ready for sending in the same context
+        TBool morePackets ( aMore || MultipleReadyPacketsPending() );
+        
+        OsTracePrint( KPacketScheduler, (TUint8*)
+            ("UMAC: WlanPacketScheduler::SchedulePackets: more: %d"), 
+            morePackets );
+    
+        // determine and store the current Tx rate & rate policy to be used 
+        // with the Tx queue in question
+        //
+        TUint8 txPolicyId ( 0 );
+        aCtxImpl.TxRatePolicy( 
+            iCurrent->iPacketIdCntx->iQueueId,
+            iCurrent->iPacketIdCntx->iUseSpecialRatePolicy,
+            iCurrent->iPacketIdCntx->iRequestedTxRate, 
+            txPolicyId );
+
+        OsTracePrint( KPacketScheduler, (TUint8*)
+            ("UMAC: WlanPacketScheduler::SchedulePackets: txRate: 0x%08x"), 
+            iCurrent->iPacketIdCntx->iRequestedTxRate );
+        OsTracePrint( KPacketScheduler, (TUint8*)
+            ("UMAC: WlanPacketScheduler::SchedulePackets: txPolicyId: %d"), 
+            txPolicyId );
+        
+        const TUint8 KSizeOfTuint32 ( sizeof( TUint32 ) );
+        const TUint8 KOffBy ( 
+            reinterpret_cast<TUint32>(iCurrent->iPacket) % KSizeOfTuint32 );
+            
+        if ( KOffBy )
+            {
+            // The frame start address is not 32 bit aligned. This can
+            // happen e.g. if the frame was left pending during
+            // roaming, and we roamed from a non-QoS nw to a QoS nw, or vice
+            // versa. That makes the alignment to be off by 2 bytes. The only
+            // way to get the start address correctly aligned is to copy the 
+            // whole frame. Note, that we always leave enough empty space at 
+            // the end of the frame buffer to enable this
+            OsTracePrint( KWsaTxDetails, (TUint8*)
+                ("UMAC: WlanPacketScheduler::SchedulePackets: Frame start address 0x%08x not aligned; fixing it"), 
+                reinterpret_cast<TUint32>(iCurrent->iPacket) );
+            os_memcpy( 
+                reinterpret_cast<TUint8*>(
+                    const_cast<TAny*>(iCurrent->iPacket)) + 
+                        ( KSizeOfTuint32 - KOffBy ),
+                reinterpret_cast<const TUint8*>(iCurrent->iPacket),
+                iCurrent->iLength );
+
+            iCurrent->iPacket = 
+                reinterpret_cast<const TUint8*>(iCurrent->iPacket) + 
+                ( KSizeOfTuint32 - KOffBy );
+
+            OsTracePrint( KWsaTxDetails, (TUint8*)
+                ("UMAC: WlanPacketScheduler::SchedulePackets: New frame start address: 0x%08x"), 
+                reinterpret_cast<TUint32>(iCurrent->iPacket) );
+            }
+
+        status = aCtxImpl.Wha().SendPacket( 
+            iCurrent->iPacket, 
+            iCurrent->iLength,
+            iCurrent->iPacketIdCntx->iQueueId,
+            txPolicyId,
+            // note that this value is not relevant when autonomous rate
+            // adaptation is being used
+            iCurrent->iPacketIdCntx->iRequestedTxRate,
+            morePackets,
+            // packet id passed is used as an act to a complex type
+            reinterpret_cast<WHA::TPacketId>(*pos),            
+            aCtxImpl.iWlanMib.dot11CurrentTxPowerLevel,
+            aCtxImpl.iWlanMib.dot11MaxTransmitMSDULifetime[
+                iCurrent->iPacketIdCntx->iQueueId],
+            NULL );
+
+        // store current time in packet context
+        iCurrent->iPacketIdCntx->iSendReqTimeStamp = os_systemTime();
+            
+        ++pos;  // next free slot
+        // for the possible following frame submissions within this Tx loop we
+        // cannot use this indication of more frames in UMAC adaptation any more
+        // as it is valid only for the first submission
+        aMore = EFalse;
+
+        OsTracePrint( 
+            KPacketScheduler, 
+            (TUint8*)("UMAC: WlanPacketScheduler::SchedulePackets: SendPacket status: %d"),
+            status);
+        
+        if ( status == WHA::KPending )
+            {
+            // stop the tx pipeline
+            StopTxPipeLine();
+            // packet was accepted for delivery
+            --iNumOfPackets;
+            iCurrent->iFree = ETrue;    // mark as free
+            }
+        else if ( status == WHA::KQueueFull )
+            {
+            OsTracePrint( 
+                KPacketScheduler, (TUint8*)
+                ("UMAC: WlanPacketScheduler::SchedulePackets: queue for the current packet is full, queue id: %d"),
+                iCurrent->iPacketIdCntx->iQueueId );
+
+            // packet was discarded
+            // we may schedule from another queue
+            // this is done automatically as we are executing a loop
+            TranmsitQueueFull( iCurrent->iPacketIdCntx->iQueueId );
+
+            // do not clear context as this packet needs to be resend
+            // at some point
+            }
+        else if ( status == WHA::KSuccessXfer )
+            {
+            // synchronous xfer occurred and no packet transfer
+            // method gets called for the packets send in this context,
+            // which means that we must manually call completion method
+            // for all of those packets
+            --iNumOfPackets;    // packet was accepted for delivery
+            iCurrent->iFree = ETrue;    // mark as free
+
+            // call completion method for all stacked packet id contexes
+            // as they are part of a synchronous xfer
+            for ( TPacketIdCntxsPtrs::iterator beg 
+                = packetid_cntxs.begin() 
+                ; beg != pos 
+                ; ++beg )
+                {
+                iPacketSchedulerClient.OnPacketTransferComplete(
+                    aCtxImpl, 
+                    (*beg)->iFrameId,
+                    const_cast<TDataBuffer*>((*beg)->iMetaHeader) );
+                }
+
+            // now as all have been handled
+            // clear the stack by resetting the position 
+            // to begin of the buffer 
+            pos = packetid_cntxs.begin();
+            }
+        else if ( status == WHA::KSuccess )
+            {
+            // this is the success scenario
+            --iNumOfPackets; // packet was accepted for delivery
+            iCurrent->iFree = ETrue;    // mark as free
+            }
+        else if ( status == WHA::KSuccessQueueFull )
+            {
+            // packet was accepted 
+            --iNumOfPackets;
+            // ... but the destination queue is now full
+            TranmsitQueueFull( iCurrent->iPacketIdCntx->iQueueId );
+            // we may schedule from another queue
+            // this is done automatically as we are executing a loop
+
+            iCurrent->iFree = ETrue;    // mark as free
+            }
+        else
+            {
+            // adaptation programming error
+            OsAssert( (TUint8*)("UMAC: panic"), (TUint8*)(WLAN_FILE), __LINE__ );
+            }
+
+        // select new current packet that is to be transferred,
+        // if such exists
+        SetNextCurrent();
+
+        // stop packet sending if tx pipeleline is stopped or there 
+        // is no current packet to be xferred
+        } while ( iCurrent && iTxPipelineActive );
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void WlanPacketScheduler::SendPacketTransfer( 
+    WlanContextImpl& aCtxImpl, 
+    WHA::TPacketId aPacketId )
+    {
+    OsTracePrint( 
+        KPacketScheduler, (TUint8*)
+        ("UMAC: WlanPacketScheduler::SendPacketTransfer: packet id: 0x%08x"),
+         aPacketId);
+
+    // tx pipeline is always activated by this method
+    StartTxPipeLine();
+
+    if ( iCurrent )
+        {
+        // current packet to be xferred exists
+        // notify the client code of this
+        iPacketSchedulerClient.CallPacketSchedule( aCtxImpl, EFalse );
+        }
+
+    // call packet transfer completion method,
+    // with client supplied frame id
+    const SPacketIdCntx* packet_id_cnxt 
+        = reinterpret_cast<const SPacketIdCntx*>(aPacketId);
+    iPacketSchedulerClient.OnPacketTransferComplete( 
+        aCtxImpl, 
+        packet_id_cnxt->iFrameId,
+        const_cast<TDataBuffer*>(packet_id_cnxt->iMetaHeader) );
+
+    if ( // push packet signaling to client flagged
+         iFlags & KSignalPushPacket
+         // AND
+         && 
+         // packet scheduler is not full
+         !Full() )
+        {
+        iFlags &= ~KSignalPushPacket;
+        iPacketSchedulerClient.OnPacketPushPossible( aCtxImpl );
+        }
+
+    if ( // someone is waiting for internal Tx buffer to become available
+         aCtxImpl.InternalTxBufBeingWaited() 
+         // AND
+         && 
+         // packet scheduler still is not full
+         !Full() )
+        {
+        aCtxImpl.ClearInternalTxBufBeingWaitedFlag();
+        iPacketSchedulerClient.OnPacketPushPossible( aCtxImpl );
+        }
+    }
+ 
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void WlanPacketScheduler::SendPacketComplete(
+    WlanContextImpl& aCtxImpl, 
+    WHA::TStatus aStatus,
+    WHA::TPacketId aPacketId,
+    WHA::TRate aRate,
+    TUint32 aPacketQueueDelay,
+    TUint32 aMediaDelay,
+    TUint8 aAckFailures )
+    {
+    OsTracePrint( KPacketScheduler, (TUint8*)
+        ("UMAC: WlanPacketScheduler::SendPacketComplete: packet id: 0x%08x"),
+        aPacketId);
+
+    // determine the packet context related to this frame
+    SPacketIdCntx* packet_id_cnxt 
+        = reinterpret_cast<SPacketIdCntx*>(aPacketId);
+
+    // calculate Total Tx Delay for this frame. 
+    // Using the TUint type for the result is safe
+    const TUint totalTxDelay = 
+        os_systemTime() - 
+        packet_id_cnxt->iSendReqTimeStamp;
+
+    // as packet has been processed from device transmit queue
+    // mark that queue as not full
+    iQueueStates[packet_id_cnxt->iQueueId] = EQueueNotFull;
+    
+    // note the queue via which the packet was transmitted
+    const WHA::TQueueId queueId ( packet_id_cnxt->iQueueId );
+
+    // note the originally requested Tx rate 
+    const WHA::TRate requestedTxRate( packet_id_cnxt->iRequestedTxRate );
+    
+    // this context can now be reused
+    packet_id_cnxt->iFree = ETrue;
+    --iNumOfNotCompletedPackets;
+    
+    OsTracePrint( KPacketScheduler, (TUint8*)
+        ("UMAC: WlanPacketScheduler::SendPacketComplete: the nbr of packets not yet completed by WHA layer is now: %d"),
+        iNumOfNotCompletedPackets );
+    
+    // adjust current packet pointer if needed
+    SetCurrentPacket( *packet_id_cnxt );
+
+    if ( iTxPipelineActive && iCurrent )
+        {
+        // packet scheduling feasible
+        // as tx pipeline is active and we have a current packet to be sent
+        iPacketSchedulerClient.CallPacketSchedule( aCtxImpl, EFalse );
+        } 
+
+    // notify client of event
+    iPacketSchedulerClient.OnPacketSendComplete( 
+        aCtxImpl,
+        aStatus,
+        packet_id_cnxt->iFrameId,
+        aRate,
+        aPacketQueueDelay,
+        aMediaDelay,
+        totalTxDelay,
+        aAckFailures,
+        queueId,
+        requestedTxRate,
+        packet_id_cnxt->iMulticastData );
+
+    if (
+        // push packet signalling to client flagged
+        iFlags & KSignalPushPacket 
+        // AND
+        && 
+        // packet scheduler is not full
+        !Full() )
+        {
+        iFlags &= ~KSignalPushPacket;
+        iPacketSchedulerClient.OnPacketPushPossible( aCtxImpl );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+TBool WlanPacketScheduler::GetWhaTxStatus( 
+    const WlanContextImpl& aCtxImpl,
+    TWhaTxQueueState& aTxQueueState ) const
+    {
+    if ( aCtxImpl.QosEnabled() )
+        {
+        for ( TUint queueId = 0; queueId < EQueueIdMax; ++queueId )
+            {
+            aTxQueueState[queueId] = 
+                static_cast<TTxQueueState>(iQueueStates[queueId]);
+            }
+        }
+    else
+        {
+        for ( TUint queueId = 0; queueId < EQueueIdMax; ++queueId )
+            {
+            aTxQueueState[queueId] = 
+                static_cast<TTxQueueState>(iQueueStates[ELegacy]);
+            }        
+        }
+    
+    return iTxPipelineActive;
+    }
+
+// ---------------------------------------------------------------------------
+// check do we have more than the current packet ready for transmit
+// ---------------------------------------------------------------------------
+//
+TBool WlanPacketScheduler::MultipleReadyPacketsPending()
+    {    
+    TUint32 cntr( 0 );
+
+    for ( TPacketElements::iterator pos = iPacketElements.begin() 
+        ; pos != iPacketElements.end() 
+        ; ++pos )
+        {
+        if ( pos->iFree == EFalse )
+            // element in use
+            {
+            if ( iQueueStates[pos->iPacketIdCntx->iQueueId] == EQueueNotFull )
+                // and in non empty queue
+                {
+                if ( ++cntr > 1 )
+                    // multiple entries found
+                    {
+                    OsTracePrint( KPacketScheduler, (TUint8*)
+                        ("UMAC: WlanPacketScheduler::MultipleReadyPacketsPending: multiple pending entries exist for non-full queue(s)") );
+                        
+                    // terminate the loop
+                    break;
+                    }
+                }
+            }
+        }
+
+    return (cntr > 1);
+    }
+
+// ---------------------------------------------------------------------------
+// select new current packet to be transmitted if one exists
+// ---------------------------------------------------------------------------
+//
+void WlanPacketScheduler::SetNextCurrent()
+    {
+    // no current exist as we setting a new one
+    iCurrent = NULL;
+
+    if ( !iNumOfPackets  )
+        {
+        // as no packets exist there can not be a current one
+        return;
+        }
+
+    TPacketElements::iterator pos( iPacketElements.begin() );    
+    TUint cntr( iNumOfPackets );
+    while ( cntr )
+        {
+        // process max amount of packets 
+        // we have pending inside the scheduler
+        if ( pos->iFree == EFalse )
+            {
+            // element in use -> process it
+
+            if ( iCurrent )
+                {
+                // a current packet exists
+                if (
+                    // packet is in non full queue 
+                    iQueueStates[pos->iPacketIdCntx->iQueueId] 
+                    == EQueueNotFull
+                    // AND 
+                    && 
+                    // has higher prioty than the current packet
+                    ( Priority( pos->iPacketIdCntx->iQueueId ) 
+                    > Priority( iCurrent->iPacketIdCntx->iQueueId ) ) )
+                    {
+                    // which means it is the new current packet
+                    iCurrent = pos;
+                    }
+                }
+            else    // --- iCurrent ---
+                {
+                // there is no current packet
+
+                if (
+                    // packet is in non full queue 
+                    iQueueStates[pos->iPacketIdCntx->iQueueId] 
+                    == EQueueNotFull )
+                    {
+                    // which means it is the new current packet
+                    iCurrent = pos;
+                    }
+                }
+            
+            --cntr;
+            }
+        ++pos;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+WlanPacketScheduler::SPacketIdCntx* WlanPacketScheduler::FreePacketIdCntx()
+    {
+    const TPacketIdCntxsPredicate unary_predicate;
+
+    // find first free element
+    SPacketIdCntx* pos 
+        = find_if( 
+        iPacketIdCntxs.begin(), 
+        iPacketIdCntxs.end(), 
+        unary_predicate );
+
+    return (pos != iPacketIdCntxs.end() ? pos : NULL);
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+WlanPacketScheduler::SElement* WlanPacketScheduler::FreeElementSlot()
+    {
+    const TElementPredicate unary_predicate;
+
+    // find first free element
+    SElement* pos 
+        = find_if( 
+        iPacketElements.begin(), 
+        iPacketElements.end(), 
+        unary_predicate );
+
+    return (pos != iPacketElements.end() ? pos : NULL);
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void WlanPacketScheduler::SetCurrentPacket( 
+    const SPacketIdCntx& aCompletedCntx )
+    {
+    TBool skip_current( EFalse );
+
+    if ( iCurrent )
+        {
+        // current packet to be scheduled exists
+        
+        if ( Priority( iCurrent->iPacketIdCntx->iQueueId ) >= 
+             Priority( aCompletedCntx.iQueueId ) )
+            {
+            // the current packet has at least equal priority as the
+            // processed one, which means that there is no need
+            // to adjust the current pointer
+
+            // skip setting current
+            skip_current = ETrue;
+            }
+        else
+            {
+            // processed packet has a higher priority as the current one,
+            // which means that we have to check do we have packets in that
+            // queue as the new current packet have to be set from those
+            // packets (as they have higher priority)
+            }
+        }
+    else    // --- iCurrent ---
+        {
+        // there is no current packet, which means that we have to check do we
+        // have packets in the same queue as the processed one
+        // as the current packet have to be set from those
+        // packets (if any exists)        
+        }
+
+    // check and adjust if needed the current packet pointer
+    // to point to the highest prioriy packet in non full transmit queue
+
+    if ( skip_current == EFalse )
+        {
+        TPacketElements::iterator pos( iPacketElements.begin() );    
+        TUint cntr( iNumOfPackets );
+        while ( cntr )
+            {
+            // process max amount of packets 
+            // we have pending inside the scheduler
+            if ( pos->iFree == EFalse )
+                {
+                // element in use -> process it
+                if ( iCurrent )
+                    {
+                    // a current packet exists
+
+                    if ( // packet is in non full queue 
+                         iQueueStates[pos->iPacketIdCntx->iQueueId] 
+                         == EQueueNotFull
+                         // AND 
+                         && 
+                         // has higher prioty than the current packet
+                         ( Priority( pos->iPacketIdCntx->iQueueId ) 
+                         > Priority( iCurrent->iPacketIdCntx->iQueueId ) ) )
+                        {
+                        // which means it is the new current packet
+                        iCurrent = pos;
+                        }
+                    }
+                else    // --- iCurrent ---
+                    {
+                    // there is no current packet
+                    if ( // packet is in non full queue 
+                         iQueueStates[pos->iPacketIdCntx->iQueueId] 
+                         == EQueueNotFull )
+                        {
+                        // which means it is the new current packet
+                        iCurrent = pos;
+                        }
+                    }
+            
+                --cntr;
+                }
+            ++pos;
+            }
+        }
+    }