/*
 * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
 *
 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
 *
 *
 * Permission to use, copy, modify, and/or distribute this software for
 * any purpose with or without fee is hereby granted, provided that the
 * above copyright notice and this permission notice appear in all
 * copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */

/*
 * This file was originally distributed by Qualcomm Atheros, Inc.
 * under proprietary terms before Copyright ownership was assigned
 * to the Linux Foundation.
 */




/*===========================================================================


                       W L A N _ Q C T _ T L . C

  OVERVIEW:

  This software unit holds the implementation of the WLAN Transport Layer.

  The functions externalized by this module are to be called ONLY by other
  WLAN modules that properly register with the Transport Layer initially.

  DEPENDENCIES:

  Are listed for each API below.


===========================================================================*/

/*===========================================================================

                      EDIT HISTORY FOR FILE


  This section contains comments describing changes made to the module.
  Notice that changes are listed in reverse chronological order.


   $Header$$DateTime$$Author$


  when        who     what, where, why
----------    ---    --------------------------------------------------------
2013-08-19    rajekuma Added RMC support
2010-07-13    c_shinde Fixed an issue where WAPI rekeying was failing because 
                      WAI frame sent out during rekeying had the protected bit
                      set to 1.
2010-05-06    rnair   Changed name of variable from usLlcType to usEtherType
                      Changed function name from GetLLCType to GetEtherType
                      Fixed 802.3 to 802.11 frame translation issue where two 
                      bytes of the LLC header was getting overwritten in the
                      non-Qos path
2010-05-06    rnair   RxAuth path fix for modifying the header before ether
                      type is retreived (Detected while testing rekeying
                      in WAPI Volans)
2010-02-19    bad     Fixed 802.11 to 802.3 ft issues with WAPI
2010-02-19    rnair   WAPI: If frame is a WAI frame in TxConn and TxAuth, TL 
                      does frame translation. 
2010-02-01    rnair   WAPI: Fixed a bug where the value of ucIsWapiSta was not       
                      being set in the TL control block in the RegisterSTA func. 
2010-01-08    lti     Added TL Data Caching 
2009-11-04    rnair   WAPI: Moving common functionality to a seperate function
                      called WLANTL_GetLLCType
2009-10-15    rnair   WAPI: Featurizing WAPI code
2009-10-09    rnair   WAPI: Modifications to authenticated state handling of Rx data
2009-10-06    rnair   Adding support for WAPI 
2009-09-22    lti     Add deregistration API for management client
2009-07-16    rnair   Temporary fix to let TL fetch packets when multiple 
                      peers exist in an IBSS
2009-06-10    lti     Fix for checking TID value of meta info on TX - prevent
                      memory overwrite 
                      Fix for properly checking the sta id for resuming trigger
                      frame generation
2009-05-14    lti     Fix for sending out trigger frames
2009-05-15    lti     Addr3 filtering 
2009-04-13    lti     Assert if packet larger then allowed
                      Drop packet that fails flatten
2009-04-02    lti     Performance fixes for TL 
2009-02-19    lti     Added fix for LLC management on Rx Connect 
2009-01-16    lti     Replaced peek data with extract data for non BD opertions
                      Extracted frame control in Tl and pass to HAL for frame 
                      type evaluation
2009-02-02    sch     Add handoff support
2008-12-09    lti     Fixes for AMSS compilation 
                      Removed assert on receive when there is no station
2008-12-02    lti     Fix fo trigger frame generation 
2008-10-31    lti     Fix fo TL tx suspend
2008-10-01    lti     Merged in fixes from reordering
                      Disabled part of UAPSD functionality in TL
                      (will be re-enabled once UAPSD is tested)
                      Fix for UAPSD multiple enable
2008-08-10    lti     Fixes following UAPSD testing
                      Fixed infinite loop on mask computation when STA no reg
2008-08-06    lti     Fixes after QOS unit testing
2008-08-06    lti     Added QOS support
2008-07-23    lti     Fix for vos packet draining
2008-07-17    lti     Fix for data type value
                      Added frame translation code in TL
                      Avoid returning failure to PE in case previous frame is
                      still pending; fail previous and cache new one for tx
                      Get frames returning boolean true if more frames are pending
2008-07-03    lti     Fixes following pre-integration testing
2008-06-26    lti     Fixes following unit testing
                      Added alloc and free for TL context
                      Using atomic set u8 instead of u32
2008-05-16    lti     Created module

===========================================================================*/

/*----------------------------------------------------------------------------
 * Include Files
 * -------------------------------------------------------------------------*/
#include "wlan_qct_tl.h" 
#include "wlan_qct_wda.h" 
#include "wlan_qct_tli.h" 
#include "wlan_qct_tli_ba.h" 
#include "wlan_qct_tl_hosupport.h"
#include "vos_types.h"
#include "vos_trace.h"
#include "wlan_qct_tl_trace.h"
#include "tlDebug.h"
#include "cfgApi.h"
#ifdef FEATURE_WLAN_WAPI
/*Included to access WDI_RxBdType */
#include "wlan_qct_wdi_bd.h"
#endif
/*Enables debugging behavior in TL*/
#define TL_DEBUG
/*Enables debugging FC control frame in TL*/
//#define TL_DEBUG_FC
//#define WLAN_SOFTAP_FLOWCTRL_EN
//#define BTAMP_TEST
#ifdef TL_DEBUG_FC
#include <wlan_qct_pal_status.h>
#include <wlan_qct_pal_device.h> // wpalReadRegister
#endif

/*----------------------------------------------------------------------------
 * Preprocessor Definitions and Constants
 * -------------------------------------------------------------------------*/
/*LLC header value*/
static v_U8_t WLANTL_LLC_HEADER[] =  {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00 };

#ifdef FEATURE_WLAN_ESE
/*Aironet SNAP header value*/
static v_U8_t WLANTL_AIRONET_SNAP_HEADER[] =  {0xAA, 0xAA, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00 };
#endif //FEATURE_WLAN_ESE

/*BT-AMP packet LLC OUI value*/
const v_U8_t WLANTL_BT_AMP_OUI[] =  {0x00, 0x19, 0x58 };

#ifdef WLAN_FEATURE_LINK_LAYER_STATS
extern const v_U8_t  WLANTL_TID_2_AC[WLAN_MAX_TID];

#endif

#define WLANTL_MAX_SNR_DATA_SAMPLES 20

#ifdef VOLANS_PERF
#define WLANTL_BD_PDU_INTERRUPT_ENABLE_THRESHOLD  120
#define WLANTL_BD_PDU_INTERRUPT_GET_THRESHOLD  120

/* TL BD/PDU threshold to enable interrupt */
int bdPduInterruptEnableThreshold = WLANTL_BD_PDU_INTERRUPT_ENABLE_THRESHOLD;
int bdPduInterruptGetThreshold = WLANTL_BD_PDU_INTERRUPT_GET_THRESHOLD;
#endif /* VOLANS_PERF */

/*-----------------------------------*
 |   Type(2b)   |     Sub-type(4b)   |
 *-----------------------------------*/
#define WLANTL_IS_DATA_FRAME(_type_sub)                               \
                     ( WLANTL_DATA_FRAME_TYPE == ( (_type_sub) & 0x30 ))

#define WLANTL_IS_QOS_DATA_FRAME(_type_sub)                                      \
                     (( WLANTL_DATA_FRAME_TYPE == ( (_type_sub) & 0x30 )) &&     \
                      ( WLANTL_80211_DATA_QOS_SUBTYPE == ( (_type_sub) & 0xF ))) 

#define WLANTL_IS_MGMT_FRAME(_type_sub)                                     \
                     ( WLANTL_MGMT_FRAME_TYPE == ( (_type_sub) & 0x30 ))

#define WLANTL_IS_MGMT_ACTION_FRAME(_type_sub)                                \
    (( WLANTL_MGMT_FRAME_TYPE == ( (_type_sub) & 0x30 )) &&    \
     ( ( WLANTL_80211_MGMT_ACTION_SUBTYPE == ( (_type_sub) & 0xF )) || \
       ( WLANTL_80211_MGMT_ACTION_NO_ACK_SUBTYPE == ( (_type_sub) & 0xF ))))

#define WLANTL_IS_PROBE_REQ(_type_sub)                                     \
                     ( WLANTL_MGMT_PROBE_REQ_FRAME_TYPE == ( (_type_sub) & 0x3F ))

#define WLANTL_IS_CTRL_FRAME(_type_sub)                                     \
                     ( WLANTL_CTRL_FRAME_TYPE == ( (_type_sub) & 0x30 ))

#ifdef FEATURE_WLAN_TDLS
#define WLANTL_IS_TDLS_FRAME(_eth_type)                                     \
                     ( WLANTL_LLC_TDLS_TYPE == ( _eth_type))
#endif

/*MAX Allowed len processed by TL - MAx MTU + 802.3 header + BD+DXE+XTL*/
#define WLANTL_MAX_ALLOWED_LEN    (1514 + 100)

#define WLANTL_DATA_FLOW_MASK 0x0F

//some flow_control define
//LWM mode will be enabled for this station if the egress/ingress falls below this ratio
#define WLANTL_LWM_EGRESS_INGRESS_THRESHOLD (0.75)

//Get enough sample to do the LWM related calculation
#define WLANTL_LWM_INGRESS_SAMPLE_THRESHOLD (64)

//Maximal on-fly packet per station in LWM mode
#define WLANTL_STA_BMU_THRESHOLD_MAX (256)

#define WLANTL_AC_MASK (0x7)
#define WLANTL_STAID_OFFSET (0x6)

/* UINT32 type endian swap */
#define SWAP_ENDIAN_UINT32(a)          ((a) = ((a) >> 0x18 ) |(((a) & 0xFF0000) >> 0x08) | \
                                            (((a) & 0xFF00) << 0x08)  | (((a) & 0xFF) << 0x18))

/* Maximum value of SNR that can be calculated by the HW */
#define WLANTL_MAX_HW_SNR 35

#define DISABLE_ARP_TOGGLE 0
#define ENABLE_ARP_TOGGLE  1
#define SEND_ARP_ON_WQ5    2

#define WLANTL_RATE_RATIO_THRESHOLD 2
#define WLANTL_PER_THRESHOLD 5
#define WLANTL_QUEUE_THRESHOLD 60
#define WLANTL_GOOD_STA_WEIGHT 1
#define WLANTL_WEIGHT_THRESHOLD 50

/*----------------------------------------------------------------------------
 * Type Declarations
 * -------------------------------------------------------------------------*/
#define TL_LITTLE_BIT_ENDIAN

typedef struct
{


   v_U8_t protVer :2;
   v_U8_t type :2;
   v_U8_t subType :4;

   v_U8_t toDS :1;
   v_U8_t fromDS :1;
   v_U8_t moreFrag :1;
   v_U8_t retry :1;
   v_U8_t powerMgmt :1;
   v_U8_t moreData :1;
   v_U8_t wep :1;
   v_U8_t order :1;


} WLANTL_MACFCType;

/* 802.11 header */
typedef struct
{
 /* Frame control field */
 WLANTL_MACFCType  wFrmCtrl;

 /* Duration ID */
 v_U16_t  usDurationId;

 /* Address 1 field  */
 v_U8_t   vA1[VOS_MAC_ADDR_SIZE];

 /* Address 2 field */
 v_U8_t   vA2[VOS_MAC_ADDR_SIZE];

 /* Address 3 field */
 v_U8_t   vA3[VOS_MAC_ADDR_SIZE];

 /* Sequence control field */
 v_U16_t  usSeqCtrl;

 // Find the size of the mandatory header size.
#define WLAN80211_MANDATORY_HEADER_SIZE \
    (sizeof(WLANTL_MACFCType) + sizeof(v_U16_t) + \
    (3 * (sizeof(v_U8_t) * VOS_MAC_ADDR_SIZE))  + \
    sizeof(v_U16_t))

 /* Optional A4 address */
 v_U8_t   optvA4[VOS_MAC_ADDR_SIZE];

 /* Optional QOS control field */
 v_U16_t  usQosCtrl;
}WLANTL_80211HeaderType;

/* 802.3 header */
typedef struct
{
 /* Destination address field */
 v_U8_t   vDA[VOS_MAC_ADDR_SIZE];

 /* Source address field */
 v_U8_t   vSA[VOS_MAC_ADDR_SIZE];

 /* Length field */
 v_U16_t  usLenType;
}WLANTL_8023HeaderType;

/*----------------------------------------------------------------------------
 * Global Data Definitions
 * -------------------------------------------------------------------------*/
#define WLAN_TL_INVALID_U_SIG 255
#define WLAN_TL_INVALID_B_SIG 255
#define ENTER() VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, "Enter:%s", __func__)

#define WLAN_TL_AC_ARRAY_2_MASK( _pSTA, _ucACMask, i ) \
  do\
  {\
    _ucACMask = 0; \
    for ( i = 0; i < WLANTL_NUM_TX_QUEUES; i++ ) \
    { \
      if ( 0 != (_pSTA)->aucACMask[i] ) \
      { \
        _ucACMask |= ( 1 << i ); \
      } \
    } \
  } while (0);


/* Following is the copy of g11bRateInfo to understand rate index at TL */
#define WLANTL_MAX_RATE_NUM               137
typedef struct
{
   uint32 phyRate;   //unit in Mega bits per sec X 10
   uint32 tputRate;  //unit in Mega bits per sec X 10
   uint32 tputBpms;  //unit in Bytes per msec = (tputRateX1024x1024)/(8x10X1000) ~= (tputRate*13)
   uint32 tputBpus;  //unit in Bytes per usec: round off to integral value
}WLANTL_RateInfo;

WLANTL_RateInfo gTLRateInfo[WLANTL_MAX_RATE_NUM]  = {
    //11b rates
    {  10,  9,  117, 0}, //index 0
    {  20,  17, 221, 0}, //index 1
    {  55,  41, 533, 0}, //index 2
    { 110,  68, 884, 0}, //index 3

    //11b short preamble
    {  10,  10,  130, 0}, //index 4
    {  20,  18,  234, 0}, //index 5
    {  55,  44,  572, 0}, //index 6
    { 110,  77, 1001, 0}, //index 7

    //11ag
    {  60,  50,  650, 1}, //index 8
    {  90,  70,  910, 1}, //index 9
    { 120, 100, 1300, 1}, //index 10
    { 180, 150, 1950, 2}, //index 11
    { 240, 190, 2470, 2}, //index 12
    { 360, 280, 3640, 4}, //index 13
    { 480, 350, 4550, 5}, //index 14
    { 540, 380, 4940, 6}, //index 15

    //11n SIMO
    {  65,  54,  702, 1}, //index 16
    { 130, 108, 1404, 1}, //index 17
    { 195, 161, 2093, 2}, //index 18
    { 260, 217, 2821, 3}, //index 19
    { 390, 326, 4238, 4}, //index 20
    { 520, 435, 5655, 6}, //index 21
    { 585, 492, 6396, 6}, //index 22
    { 650, 548, 7124, 7}, //index 23

    //11n SIMO SGI
    {  72,  59,  767, 1}, //index 24
    { 144, 118, 1534, 2}, //index 25
    { 217, 180, 2340, 2}, //index 26
    { 289, 243, 3159, 3}, //index 27
    { 434, 363, 4719, 5}, //index 28
    { 578, 486, 6318, 6}, //index 29
    { 650, 548, 7124, 7}, //index 30
    { 722, 606, 7878, 8}, //index 31

    //11n GF SIMO
    {  65,  54,  702, 1}, //index 32
    { 130, 108, 1404, 1}, //index 33
    { 195, 161, 2093, 2}, //index 34
    { 260, 217, 2821, 3}, //index 35
    { 390, 326, 4238, 4}, //index 36
    { 520, 435, 5655, 6}, //index 37
    { 585, 492, 6396, 6}, //index 38
    { 650, 548, 7124, 7}, //index 39

    //11n SIMO CB MCS 0 - 7
    { 135,   110,  1430,  1}, //index 40
    { 270,   223,  2899,  3}, //index 41
    { 405,   337,  4381,  4}, //index 42
    { 540,   454,  5902,  6}, //index 43
    { 810,   679,  8827,  9}, //index 44
    { 1080,  909, 11817, 12}, //index 45
    { 1215, 1022, 13286, 13}, //index 46
    { 1350, 1137, 14781, 15}, //index 47

    //11n SIMO CB SGI MCS 0 - 7
    { 150,   121,  1573,  2}, //index 48
    { 300,   249,  3237,  3}, //index 49
    { 450,   378,  4914,  5}, //index 50
    { 600,   503,  6539,  7}, //index 51
    { 900,   758,  9854,  10}, //index 52
    { 1200, 1010, 13130, 13}, //index 53
    { 1350, 1137, 14781, 15}, //index 54
    { 1500, 1262, 16406, 16}, //index 55

    //11n SIMO GF CB MCS 0 - 7
    { 135,   110,   1430,  1}, //index 56
    { 270,   223,   2899,  3}, //index 57
    { 405,   337,   4381,  4}, //index 58
    { 540,   454,   5902,  6}, //index 59
    { 810,   679,   8827,  9}, //index 60
    { 1080,  909,  11817, 12}, //index 61
    { 1215, 1022,  13286, 13}, //index 62
    { 1350, 1137,  14781, 15}, //index 63

    //11AC
    { 1350,  675,  8775,  9}, //reserved 64
    { 1350,  675,  8775,  9}, //reserved 65
    {   65,   45,   585,  1}, //index 66
    {  130,   91,  1183,  1}, //index 67
    {  195,  136,  1768,  2}, //index 68
    {  260,  182,  2366,  2}, //index 69
    {  390,  273,  3549,  4}, //index 70
    {  520,  364,  4732,  5}, //index 71
    {  585,  409,  5317,  5}, //index 72
    {  650,  455,  5915,  6}, //index 73
    {  780,  546,  7098,  7}, //index 74
    { 1350,  675,  8775,  9}, //reserved 75
    { 1350,  675,  8775,  9}, //reserved 76
    { 1350,  675,  8775,  9}, //reserved 77
    { 1350,  675,  8775,  9}, //index 78
    { 1350,  675,  8775,  9}, //index 79
    { 1350,  675,  8775,  9}, //index 80
    { 1350,  675,  8775,  9}, //index 81
    { 1350,  675,  8775,  9}, //index 82
    { 1350,  675,  8775,  9}, //index 83
    {  655,  458,  5954,  6}, //index 84
    {  722,  505,  6565,  7}, //index 85
    {  866,  606,  7878,  8}, //index 86
    { 1350,  675,  8775,  9}, //reserved 87
    { 1350,  675,  8775,  9}, //reserved 88
    { 1350,  675,  8775,  9}, //reserved 89
    {  135,   94,  1222,  1}, //index 90
    {  270,  189,  2457,  2}, //index 91
    {  405,  283,  3679,  4}, //index 92
    {  540,  378,  4914,  5}, //index 93
    {  810,  567,  7371,  7}, //index 94
    { 1080,  756,  9828, 10}, //index 95
    { 1215,  850, 11050, 11}, //index 96
    { 1350,  675,  8775,  9}, //index 97
    { 1350,  675,  8775,  9}, //index 98
    { 1620,  810, 10530, 11}, //index 99
    { 1800,  900, 11700, 12}, //index 100
    { 1350,  675,  8775,  9}, //reserved 101
    { 1350,  675,  8775,  9}, //index 102
    { 1350,  675,  8775,  9}, //index 103
    { 1350,  675,  8775,  9}, //index 104
    { 1350,  675,  8775,  9}, //index 105
    { 1350,  675,  8775,  9}, //index 106
    { 1200,  840, 10920, 11}, //index 107
    { 1350,  675,  8775,  9}, //index 108
    { 1500,  750,  9750, 10}, //index 109
    { 1350,  675,  8775,  9}, //index 110
    { 1800,  900, 11700, 12}, //index 111
    { 2000, 1000, 13000, 13}, //index 112
    { 1350,  675,  8775,  9}, //index 113
    {  292,  204,  2652,  3}, //index 114
    {  585,  409,  5317,  5}, //index 115
    {  877,  613,  7969,  8}, //index 116
    { 1170,  819, 10647, 11}, //index 117
    { 1755,  877, 11401, 11}, //index 118
    { 2340, 1170, 15210, 15}, //index 119
    { 2632, 1316, 17108, 17}, //index 120
    { 2925, 1462, 19006, 19}, //index 121
    { 1350,  675,  8775,  9}, //index 122
    { 3510, 1755, 22815, 23}, //index 123
    { 3900, 1950, 25350, 25}, //index 124
    { 1350,  675,  8775,  9}, //reserved 125
    { 1350,  675,  8775,  9}, //index 126
    { 1350,  675,  8775,  9}, //index 127
    { 1350,  675,  8775,  9}, //index 128
    { 1350,  675,  8775,  9}, //index 129
    { 1350,  675,  8775,  9}, //index 130
    { 1350,  675,  8775,  9}, //index 131
    { 2925, 1462, 19006, 19}, //index 132
    { 3250, 1625, 21125, 21}, //index 133
    { 1350,  675,  8775,  9}, //index 134
    { 3900, 1950, 25350, 25}, //index 135
    { 4333, 2166, 28158, 28}  //index 136
 };



/*----------------------------------------------------------------------------
 * Static Variable Definitions
 * -------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------
 * Static Function Declarations and Definitions
 * -------------------------------------------------------------------------*/

static VOS_STATUS 
WLANTL_GetEtherType
(
  v_U8_t               * aucBDHeader,
  vos_pkt_t            * vosDataBuff,
  v_U8_t                 ucMPDUHLen,
  v_U16_t              * usEtherType
);


/*----------------------------------------------------------------------------
 * Externalized Function Definitions
* -------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------
 * Function Declarations and Documentation
 * -------------------------------------------------------------------------*/
/*==========================================================================

  FUNCTION        WLANTL_FreeClientMemory

  DESCRIPTION
  It frees up the memory allocated to all the STA clients in TLCB block
  Can be called inside Close, Stop or when some FAULT occurs

  DEPENDENCIES

  PARAMETERS

  IN
  pClientSTA:    Pointer to the global client pointer array

  RETURN VALUE

  SIDE EFFECTS

============================================================================*/
void WLANTL_FreeClientMemory
(WLANTL_STAClientType* pClientSTA[WLAN_MAX_STA_COUNT])
{
    v_U32_t i = 0;
    for(i =0; i < WLAN_MAX_STA_COUNT; i++)
    {
        if( NULL != pClientSTA[i] )
        {
           vos_mem_free(pClientSTA[i]);
        }
        pClientSTA[i] = NULL;
    }
    return;
}

/*==========================================================================

  FUNCTION    WLANTL_Open

  DESCRIPTION
    Called by HDD at driver initialization. TL will initialize all its
    internal resources and will wait for the call to start to register
    with the other modules.

  DEPENDENCIES

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context
    pTLConfig:      TL Configuration

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_FAULT:  pointer to TL cb is NULL ; access would cause a page
                         fault
    VOS_STATUS_SUCCESS:  Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_Open
(
  v_PVOID_t               pvosGCtx,
  WLANTL_ConfigInfoType*  pTLConfig
)
{
  WLANTL_CbType*  pTLCb = NULL; 
  v_U8_t          ucIndex; 
  tHalHandle      smeContext;
  v_U32_t i = 0;
#if defined WLAN_FEATURE_NEIGHBOR_ROAMING
  VOS_STATUS      status = VOS_STATUS_SUCCESS;
#endif
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
    Extract TL control block
   ------------------------------------------------------------------------*/
  ENTER();
  vos_alloc_context( pvosGCtx, VOS_MODULE_ID_TL, 
                    (void*)&pTLCb, sizeof(WLANTL_CbType));

  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if (( NULL == pTLCb ) || ( NULL == pTLConfig ) )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_FATAL,
               "WLAN TL: Invalid input pointer on WLANTL_Open TL %pK Config %pK", pTLCb, pTLConfig ));
    return VOS_STATUS_E_FAULT;
  }

  /* Set the default log level to VOS_TRACE_LEVEL_ERROR */
  vos_trace_setLevel(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR);

  smeContext = vos_get_context(VOS_MODULE_ID_SME, pvosGCtx);
  if ( NULL == smeContext )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                      "%s: Invalid smeContext", __func__));
    return VOS_STATUS_E_FAULT;
  }

  /* Zero out the memory so we are OK, when CleanCB is called.*/
  vos_mem_zero((v_VOID_t *)pTLCb, sizeof(WLANTL_CbType));

  /*------------------------------------------------------------------------
    Clean up TL control block, initialize all values
   ------------------------------------------------------------------------*/
  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL:WLANTL_Open"));

  for ( i =0; i<WLAN_MAX_STA_COUNT; i++ )
  {
      if ( i < WLAN_NON32_STA_COUNT )
      {
          pTLCb->atlSTAClients[i] = vos_mem_malloc(sizeof(WLANTL_STAClientType));
          /* Allocating memory for LEGACY STA COUNT so as to avoid regression issues.  */
         if ( NULL == pTLCb->atlSTAClients[i] )
         {
             TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, "WLAN TL: StaClient allocation failed"));
             WLANTL_FreeClientMemory(pTLCb->atlSTAClients);
             vos_free_context(pvosGCtx, VOS_MODULE_ID_TL, pTLCb);
             return VOS_STATUS_E_FAULT;
         }
         vos_mem_zero((v_VOID_t *) pTLCb->atlSTAClients[i], sizeof(WLANTL_STAClientType));
      }
      else
      {
          pTLCb->atlSTAClients[i] = NULL;
      }
  }

  pTLCb->reorderBufferPool = vos_mem_vmalloc(sizeof(WLANTL_REORDER_BUFFER_T) * WLANTL_MAX_BA_SESSION);
  if (NULL == pTLCb->reorderBufferPool)
  {
    TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, "WLAN TL: Reorder buffer allocation failed"));
    WLANTL_FreeClientMemory(pTLCb->atlSTAClients);
    vos_free_context(pvosGCtx, VOS_MODULE_ID_TL, pTLCb);
    return VOS_STATUS_E_FAULT;
  }

  vos_mem_zero((v_VOID_t *)pTLCb->reorderBufferPool, sizeof(WLANTL_REORDER_BUFFER_T) * WLANTL_MAX_BA_SESSION);

  WLANTL_CleanCB(pTLCb, 0 /*do not empty*/);

  for ( ucIndex = 0; ucIndex < WLANTL_NUM_TX_QUEUES ; ucIndex++)
  {
    pTLCb->tlConfigInfo.ucAcWeights[ucIndex] = pTLConfig->ucAcWeights[ucIndex];
  }

  for ( ucIndex = 0; ucIndex < WLANTL_MAX_AC ; ucIndex++)
  {
    pTLCb->tlConfigInfo.ucReorderAgingTime[ucIndex] = pTLConfig->ucReorderAgingTime[ucIndex];
  }

  // scheduling init to be the last one of previous round
  pTLCb->uCurServedAC = WLANTL_AC_VO;
  pTLCb->ucCurLeftWeight = pTLCb->tlConfigInfo.ucAcWeights[pTLCb->uCurServedAC];
  pTLCb->ucCurrentSTA = WLAN_MAX_STA_COUNT-1;

  vos_timer_init(&pTLCb->tx_frames_timer, VOS_TIMER_TYPE_SW,
                         WLANTL_SampleTx, (void *)pTLCb);
#if 0
  //flow control field init
  vos_mem_zero(&pTLCb->tlFCInfo, sizeof(tFcTxParams_type));
  //bit 0: set (Bd/pdu count) bit 1: set (request station PS change notification)
  pTLCb->tlFCInfo.fcConfig = 0x1;
#endif

  pTLCb->vosTxFCBuf = NULL;
  pTLCb->tlConfigInfo.uMinFramesProcThres =
                pTLConfig->uMinFramesProcThres;

#ifdef FEATURE_WLAN_TDLS
  pTLCb->ucTdlsPeerCount = 0;
#endif

  pTLCb->tlConfigInfo.uDelayedTriggerFrmInt =
                pTLConfig->uDelayedTriggerFrmInt;

  pTLCb->tlConfigInfo.ucIsReplayCheck =
                pTLConfig->ucIsReplayCheck;

  /*------------------------------------------------------------------------
    Allocate internal resources
   ------------------------------------------------------------------------*/
  vos_pkt_get_packet(&pTLCb->vosDummyBuf, VOS_PKT_TYPE_RX_RAW, 1, 1,
                     1/*true*/,NULL, NULL);

  WLANTL_InitBAReorderBuffer(pvosGCtx);
#if defined WLAN_FEATURE_NEIGHBOR_ROAMING
   /* Initialize Handoff support modue
    * RSSI measure and Traffic state monitoring */
  status = WLANTL_HSInit(pvosGCtx);
  if(!VOS_IS_STATUS_SUCCESS(status))
  {
    TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "Handoff support module init fail"));
    WLANTL_FreeClientMemory(pTLCb->atlSTAClients);
    vos_mem_vfree(pTLCb->reorderBufferPool);
    vos_free_context(pvosGCtx, VOS_MODULE_ID_TL, pTLCb);
    return status;
  }
#endif

#ifdef WLAN_FEATURE_RMC
   status = WLANTL_RmcInit(pvosGCtx);
   if (!VOS_IS_STATUS_SUCCESS(status))
   {
    TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "RMC module init fail"));
    return status;
  }
#endif

  pTLCb->isBMPS = VOS_FALSE;
  pmcRegisterDeviceStateUpdateInd( smeContext,
                                   WLANTL_PowerStateChangedCB, pvosGCtx );

  return VOS_STATUS_SUCCESS;
}/* WLANTL_Open */

/*==========================================================================

  FUNCTION    WLANTL_Start

  DESCRIPTION
    Called by HDD as part of the overall start procedure. TL will use this
    call to register with BAL as a transport layer entity.

  DEPENDENCIES

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_FAULT:  pointer to TL cb is NULL ; access would cause a page
                         fault
    VOS_STATUS_SUCCESS:  Everything is good :)

    Other codes can be returned as a result of a BAL failure; see BAL API
    for more info

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_Start
(
  v_PVOID_t  pvosGCtx
)
{
  WLANTL_CbType*      pTLCb      = NULL;
  v_U32_t             uResCount = WDA_TLI_MIN_RES_DATA;
  VOS_STATUS          vosStatus;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
    Extract TL control block
   ------------------------------------------------------------------------*/
  ENTER();
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_Start"));
    return VOS_STATUS_E_FAULT;
  }

  /*------------------------------------------------------------------------
    Register with WDA as transport layer client
    Request resources for tx from bus
  ------------------------------------------------------------------------*/
  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL:WLAN TL:WLANTL_Start"));

  tlTraceInit();
  vosStatus = WDA_DS_Register( pvosGCtx, 
                          WLANTL_TxComp, 
                          WLANTL_RxFrames,
                          WLANTL_GetFrames, 
                          WLANTL_ResourceCB,
                          WDA_TLI_MIN_RES_DATA, 
                          pvosGCtx, 
                          &uResCount ); 

  if ( VOS_STATUS_SUCCESS != vosStatus )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, 
               "WLAN TL:TL failed to register with BAL/WDA, Err: %d",
               vosStatus));
    return vosStatus;
  }

  /* Enable transmission */
  vos_atomic_set_U8( &pTLCb->ucTxSuspended, 0);
  pTLCb->uResCount = uResCount;

  if (IS_FEATURE_SUPPORTED_BY_FW(SAP_BUFF_ALLOC))
    vos_timer_start(&pTLCb->tx_frames_timer, WLANTL_SAMPLE_INTERVAL);

  return VOS_STATUS_SUCCESS;
}/* WLANTL_Start */

/*==========================================================================

  FUNCTION    WLANTL_Stop

  DESCRIPTION
    Called by HDD to stop operation in TL, before close. TL will suspend all
    frame transfer operation and will wait for the close request to clean up
    its resources.

  DEPENDENCIES

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_FAULT:  pointer to TL cb is NULL ; access would cause a page
                         fault
    VOS_STATUS_SUCCESS:  Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_Stop
(
  v_PVOID_t  pvosGCtx
)
{
  WLANTL_CbType*  pTLCb = NULL;
  v_U8_t      ucIndex;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
    Extract TL control block
   ------------------------------------------------------------------------*/
  ENTER();
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
         "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_ChangeSTAState"));
    return VOS_STATUS_E_FAULT;
  }

  /*------------------------------------------------------------------------
    Stop TL and empty Station list
   ------------------------------------------------------------------------*/
  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL:WLANTL_Stop"));

  /* Disable transmission */
  vos_atomic_set_U8( &pTLCb->ucTxSuspended, 1);

  if ( NULL != pTLCb->tlMgmtFrmClient.vosPendingDataBuff )
  {
    vos_pkt_return_packet(pTLCb->tlMgmtFrmClient.vosPendingDataBuff);
    pTLCb->tlMgmtFrmClient.vosPendingDataBuff = NULL;
  }

  if ( NULL != pTLCb->tlBAPClient.vosPendingDataBuff )
  {
    vos_pkt_return_packet(pTLCb->tlBAPClient.vosPendingDataBuff);
    pTLCb->tlBAPClient.vosPendingDataBuff = NULL;
  }

#if defined WLAN_FEATURE_NEIGHBOR_ROAMING
  if(VOS_STATUS_SUCCESS != WLANTL_HSStop(pvosGCtx))
  {
    TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
               "Handoff Support module stop fail"));
  }
#endif

   if (VOS_TIMER_STATE_STOPPED !=
                  vos_timer_getCurrentState(&pTLCb->tx_frames_timer))
      vos_timer_stop(&pTLCb->tx_frames_timer);

  /*-------------------------------------------------------------------------
    Clean client stations
   -------------------------------------------------------------------------*/
  for ( ucIndex = 0; ucIndex < WLAN_MAX_STA_COUNT; ucIndex++)
  {
    if ( NULL != pTLCb->atlSTAClients[ucIndex] )
    {
        WLANTL_CleanSTA(pTLCb->atlSTAClients[ucIndex], 1 /*empty all queues*/);
    }
  }


  return VOS_STATUS_SUCCESS;
}/* WLANTL_Stop */

/*==========================================================================

  FUNCTION    WLANTL_Close

  DESCRIPTION
    Called by HDD during general driver close procedure. TL will clean up
    all the internal resources.

  DEPENDENCIES

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_FAULT:  pointer to TL cb is NULL ; access would cause a page
                         fault
    VOS_STATUS_SUCCESS:  Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_Close
(
  v_PVOID_t  pvosGCtx
)
{
  WLANTL_CbType*  pTLCb = NULL;
  tHalHandle smeContext;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
    Extract TL control block
   ------------------------------------------------------------------------*/
  ENTER();
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
         "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_ChangeSTAState"));
    return VOS_STATUS_E_FAULT;
  }
  /*------------------------------------------------------------------------
    Deregister from PMC
   ------------------------------------------------------------------------*/
  smeContext = vos_get_context(VOS_MODULE_ID_SME, pvosGCtx);
  if ( NULL == smeContext )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                      "%s: Invalid smeContext", __func__));
    // continue so that we can cleanup as much as possible
  }
  else
  {
    pmcDeregisterDeviceStateUpdateInd( smeContext, WLANTL_PowerStateChangedCB );
  }

#if defined WLAN_FEATURE_NEIGHBOR_ROAMING
  if(VOS_STATUS_SUCCESS != WLANTL_HSDeInit(pvosGCtx))
  {
    TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
               "Handoff Support module DeInit fail"));
  }
#endif

#ifdef WLAN_FEATURE_RMC
  if(VOS_STATUS_SUCCESS != WLANTL_RmcDeInit(pvosGCtx))
  {
    TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
               "RMC module DeInit fail"));
  }
#endif

   if (VOS_TIMER_STATE_RUNNING ==
                       vos_timer_getCurrentState(&pTLCb->tx_frames_timer)) {
         vos_timer_stop(&pTLCb->tx_frames_timer);
   }
   if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(&pTLCb->tx_frames_timer))) {
         TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                "%s: Cannot deallocate TX frames sample timer", __func__));
   }

  /*------------------------------------------------------------------------
    Cleanup TL control block.
   ------------------------------------------------------------------------*/
  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL: WLANTL_Close"));
  WLANTL_CleanCB(pTLCb, 1 /* empty queues/lists/pkts if any*/);

  WLANTL_FreeClientMemory(pTLCb->atlSTAClients);

  vos_mem_vfree(pTLCb->reorderBufferPool);

  /*------------------------------------------------------------------------
    Free TL context from VOSS global
   ------------------------------------------------------------------------*/
  vos_free_context(pvosGCtx, VOS_MODULE_ID_TL, pTLCb);
  return VOS_STATUS_SUCCESS;
}/* WLANTL_Close */

/*----------------------------------------------------------------------------
    INTERACTION WITH HDD
 ---------------------------------------------------------------------------*/
/*==========================================================================

  FUNCTION    WLANTL_ConfigureSwFrameTXXlationForAll

  DESCRIPTION
     Function to disable/enable frame translation for all association stations.

  DEPENDENCIES

  PARAMETERS
   IN
    pvosGCtx: VOS context 
    EnableFrameXlation TRUE means enable SW translation for all stations.
    .

  RETURN VALUE

   void.

============================================================================*/
void
WLANTL_ConfigureSwFrameTXXlationForAll
(
  v_PVOID_t pvosGCtx, 
  v_BOOL_t enableFrameXlation
)
{
  v_U8_t ucIndex;
  /*------------------------------------------------------------------------
    Extract TL control block
   ------------------------------------------------------------------------*/
  WLANTL_CbType* pTLCb = VOS_GET_TL_CB(pvosGCtx);
  WLANTL_STAClientType* pClientSTA = NULL;
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
           "WLAN TL:Invalid TL pointer from pvosGCtx on "
           "WLANTL_ConfigureSwFrameTXXlationForAll"));
    return;
  }

  TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
     "WLANTL_ConfigureSwFrameTXXlationForAll: Configure SW frameXlation %d", 
      enableFrameXlation));

  for ( ucIndex = 0; ucIndex < WLAN_MAX_TID; ucIndex++) 
  {
    pClientSTA = pTLCb->atlSTAClients[ucIndex];
    if ( NULL != pClientSTA && 0 != pClientSTA->ucExists )
    {
#ifdef WLAN_SOFTAP_VSTA_FEATURE
      // if this station was not allocated resources to perform HW-based
      // TX frame translation then force SW-based TX frame translation
      // otherwise use the frame translation supplied by the client
      if (!WDA_IsHwFrameTxTranslationCapable(pvosGCtx, ucIndex))
      {
        pClientSTA->wSTADesc.ucSwFrameTXXlation = 1;
      }
      else
#endif
        pClientSTA->wSTADesc.ucSwFrameTXXlation = enableFrameXlation;
    }
  }
}

/*===========================================================================

  FUNCTION    WLANTL_StartForwarding

  DESCRIPTION

    This function is used to ask serialization through TX thread of the   
    cached frame forwarding (if statation has been registered in the mean while) 
    or flushing (if station has not been registered by the time)

    In case of forwarding, upper layer is only required to call WLANTL_RegisterSTAClient()
    and doesn't need to call this function explicitly. TL will handle this inside 
    WLANTL_RegisterSTAClient(). 
    
    In case of flushing, upper layer is required to call this function explicitly
    
  DEPENDENCIES

    TL must have been initialized before this gets called.

   
  PARAMETERS

   ucSTAId:   station id 

  RETURN VALUE

    The result code associated with performing the operation
    Please check return values of vos_tx_mq_serialize.

  SIDE EFFECTS
    If TL was asked to perform WLANTL_CacheSTAFrame() in WLANTL_RxFrames(), 
    either WLANTL_RegisterSTAClient() or this function must be called 
    within reasonable time. Otherwise, TL will keep cached vos buffer until
    one of this function is called, and may end up with system buffer exhasution. 

    It's an upper layer's responsibility to call this function in case of
    flushing

============================================================================*/

VOS_STATUS 
WLANTL_StartForwarding
(
  v_U8_t ucSTAId,
  v_U8_t ucUcastSig, 
  v_U8_t ucBcastSig 
)
{
  vos_msg_t      sMessage;
  v_U32_t        uData;             
 /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

  /* Signal the OS to serialize our event */
  VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
             "Serializing TL Start Forwarding Cached for control STA %d", 
              ucSTAId );

  vos_mem_zero( &sMessage, sizeof(vos_msg_t) );

  uData = ucSTAId | (ucUcastSig << 8 ) | (ucBcastSig << 16); 
  sMessage.bodyval = uData;
  sMessage.type    = WLANTL_RX_FWD_CACHED;

  return vos_rx_mq_serialize(VOS_MQ_ID_TL, &sMessage);

} /* WLANTL_StartForwarding() */

/*===========================================================================

  FUNCTION    WLANTL_EnableCaching

  DESCRIPTION

    This function is used to enable caching only when assoc/reassoc req is send.
    that is cache packets only for such STA ID.


  DEPENDENCIES

    TL must have been initialized before this gets called.


  PARAMETERS

   staId:   station id

  RETURN VALUE

   none

============================================================================*/
void WLANTL_EnableCaching(v_U8_t staId)
{
  v_PVOID_t pvosGCtx= vos_get_global_context(VOS_MODULE_ID_TL,NULL);
  WLANTL_CbType* pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
           "WLAN TL:Invalid TL pointer from pvosGCtx on "
           "WLANTL_EnableCaching"));
    return;
  }
  pTLCb->atlSTAClients[staId]->enableCaching = 1;
}

/*===========================================================================

  FUNCTION    WLANTL_AssocFailed

  DESCRIPTION

    This function is used by PE to notify TL that cache needs to flushed' 
    when association is not successfully completed 

    Internally, TL post a message to TX_Thread to serialize the request to 
    keep lock-free mechanism.

   
  DEPENDENCIES

    TL must have been initialized before this gets called.

   
  PARAMETERS

   ucSTAId:   station id 

  RETURN VALUE

   none
   
  SIDE EFFECTS
   There may be race condition that PE call this API and send another association
   request immediately with same staId before TX_thread can process the message.

   To avoid this, we might need PE to wait for TX_thread process the message,
   but this is not currently implemented. 
   
============================================================================*/
void WLANTL_AssocFailed(v_U8_t staId)
{
  // flushing frames and forwarding frames uses the same message
  // the only difference is what happens when the message is processed
  // if the STA exist, the frames will be forwarded
  // and if it doesn't exist, the frames will be flushed
  // in this case we know it won't exist so the DPU index signature values don't matter
  MTRACE(vos_trace(VOS_MODULE_ID_TL, TRACE_CODE_TL_ASSOC_FAILED,
                                                staId, 0));

  if(!VOS_IS_STATUS_SUCCESS(WLANTL_StartForwarding(staId,0,0)))
  {
    VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
       " %s fails to start forwarding (staId %d)", __func__, staId);
  }
}

  /*===========================================================================

  FUNCTION  WLANTL_Finish_ULA

  DESCRIPTION
     This function is used by HDD to notify TL to finish Upper layer authentication
     incase the last EAPOL packet is pending in the TL queue. 
     To avoid the race condition between sme set key and the last EAPOL packet 
     the HDD module calls this function just before calling the sme_RoamSetKey.

  DEPENDENCIES

     TL must have been initialized before this gets called.

  PARAMETERS

   callbackRoutine:   HDD Callback function.
   callbackContext : HDD userdata context.

   RETURN VALUE

   VOS_STATUS_SUCCESS/VOS_STATUS_FAILURE

  SIDE EFFECTS

============================================================================*/

VOS_STATUS WLANTL_Finish_ULA( void (*callbackRoutine) (void *callbackContext),
                              void *callbackContext)
{
   return WDA_DS_FinishULA( callbackRoutine, callbackContext);
}


/*===========================================================================

  FUNCTION    WLANTL_RegisterSTAClient

  DESCRIPTION

    This function is used by HDD to register as a client for data services
    with TL. HDD will call this API for each new station that it adds,
    thus having the flexibility of registering different callback for each
    STA it services.

  DEPENDENCIES

    TL must have been initialized before this gets called.

    Restriction:
      Main thread will have higher priority that Tx and Rx threads thus
      guaranteeing that a station will be added before any data can be
      received for it. (This enables TL to be lock free)

  PARAMETERS

   pvosGCtx:        pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context
   pfnStARx:        function pointer to the receive packet handler from HDD
   pfnSTATxComp:    function pointer to the transmit complete confirmation
                    handler from HDD
   pfnSTAFetchPkt:  function pointer to the packet retrieval routine in HDD
   wSTADescType:    STA Descriptor, contains information related to the
                    new added STA

  RETURN VALUE

    The result code associated with performing the operation

    VOS_STATUS_E_INVAL: Input parameters are invalid
    VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer to
                        TL cb is NULL ; access would cause a page fault
    VOS_STATUS_E_EXISTS: Station was already registered
    VOS_STATUS_SUCCESS:  Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_RegisterSTAClient
(
  v_PVOID_t                 pvosGCtx,
  WLANTL_STARxCBType        pfnSTARx,
  WLANTL_TxCompCBType       pfnSTATxComp,
  WLANTL_STAFetchPktCBType  pfnSTAFetchPkt,
  WLAN_STADescType*         pwSTADescType,
  v_S7_t                    rssi
)
{
  WLANTL_CbType*  pTLCb = NULL;
  WLANTL_STAClientType* pClientSTA = NULL;
  v_U8_t    ucTid = 0;/*Local variable to clear previous replay counters of STA on all TIDs*/
  v_U32_t   istoggleArpEnb = 0;
  tpAniSirGlobal pMac;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  ENTER();
  if (( NULL == pwSTADescType ) || ( NULL == pfnSTARx ) ||
      ( NULL == pfnSTAFetchPkt ))
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid parameter sent on WLANTL_RegisterSTAClient"));
    return VOS_STATUS_E_INVAL;
  }

  if ( WLANTL_STA_ID_INVALID( pwSTADescType->ucSTAId ) )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
         "WLAN TL:Invalid station id requested on WLANTL_RegisterSTAClient"));
    return VOS_STATUS_E_FAULT;
  }

  /*------------------------------------------------------------------------
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
      "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_RegisterSTAClient"));
    return VOS_STATUS_E_FAULT;
  }

  //Code for checking and allocating memory for new STA
  if ( NULL == pTLCb->atlSTAClients[pwSTADescType->ucSTAId] ){
      pTLCb->atlSTAClients[pwSTADescType->ucSTAId] = vos_mem_malloc(sizeof(WLANTL_STAClientType));
      if ( NULL == pTLCb->atlSTAClients[pwSTADescType->ucSTAId] ){
          TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "WLAN TL: STA Client memory allocation failed in WLANTL_RegisterSTAClient"));
          return VOS_STATUS_E_FAILURE;
      }
      TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
          "WLAN TL: STA Client memory allocation in WLANTL_RegisterSTAClient"));
      vos_mem_zero((v_VOID_t *) pTLCb->atlSTAClients[pwSTADescType->ucSTAId],sizeof(WLANTL_STAClientType));
  }

  //Assigning the pointer to local variable for easy access in future
  pClientSTA = pTLCb->atlSTAClients[pwSTADescType->ucSTAId];
  if ( 0 != pClientSTA->ucExists )
  {
    pClientSTA->ucExists++;
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
      "WLAN TL:Station was already registered on WLANTL_RegisterSTAClient"));
    return VOS_STATUS_E_EXISTS;
  }

  /*------------------------------------------------------------------------
    Register station with TL
   ------------------------------------------------------------------------*/
  MTRACE(vos_trace(VOS_MODULE_ID_TL, TRACE_CODE_TL_REGISTER_STA_CLIENT,
                   pwSTADescType->ucSTAId, (unsigned )
                              (*(pwSTADescType->vSTAMACAddress.bytes+2)<<24 |
                               *(pwSTADescType->vSTAMACAddress.bytes+3)<<16 |
                               *(pwSTADescType->vSTAMACAddress.bytes+4)<<8 |
                               *(pwSTADescType->vSTAMACAddress.bytes+5))));

  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL:Registering STA Client ID: %d", pwSTADescType->ucSTAId ));

  pClientSTA->pfnSTARx       = pfnSTARx;
  pClientSTA->pfnSTAFetchPkt = pfnSTAFetchPkt;

  /* Only register if different from NULL - TL default Tx Comp Cb will
    release the vos packet */
  if ( NULL != pfnSTATxComp )
  {
    pClientSTA->pfnSTATxComp   = pfnSTATxComp;
  }

  pClientSTA->tlState  = WLANTL_STA_INIT;
  pClientSTA->tlPri    = WLANTL_STA_PRI_NORMAL;
  pClientSTA->wSTADesc.ucSTAId  = pwSTADescType->ucSTAId;
  pClientSTA->ptkInstalled = 0;
  pClientSTA->disassoc_progress = VOS_FALSE;

  pMac = vos_get_context(VOS_MODULE_ID_PE, pvosGCtx);
  if ( NULL != pMac )
  {
    wlan_cfgGetInt(pMac, WNI_CFG_TOGGLE_ARP_BDRATES, &istoggleArpEnb);
  }
  pClientSTA->arpRate = istoggleArpEnb ? ENABLE_ARP_TOGGLE : DISABLE_ARP_TOGGLE;
  pClientSTA->arpOnWQ5 = istoggleArpEnb == SEND_ARP_ON_WQ5;

  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
   "WLAN TL:Registering STA Client ID: %d with UC %d and BC %d toggleArp :%hhu",
    pwSTADescType->ucSTAId, pwSTADescType->ucUcastSig,
    pwSTADescType->ucBcastSig, pClientSTA->arpRate));

  pClientSTA->wSTADesc.wSTAType = pwSTADescType->wSTAType;

  pClientSTA->wSTADesc.ucQosEnabled = pwSTADescType->ucQosEnabled;

  pClientSTA->wSTADesc.ucAddRmvLLC = pwSTADescType->ucAddRmvLLC;

  pClientSTA->wSTADesc.ucProtectedFrame = pwSTADescType->ucProtectedFrame;

#ifdef FEATURE_WLAN_ESE
  pClientSTA->wSTADesc.ucIsEseSta = pwSTADescType->ucIsEseSta;

  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL:Registering STA Client ID: %d QoS %d Add LLC %d ProtFrame %d EseSta %d",
             pwSTADescType->ucSTAId, 
             pwSTADescType->ucQosEnabled,
             pwSTADescType->ucAddRmvLLC,
             pwSTADescType->ucProtectedFrame,
             pwSTADescType->ucIsEseSta));
#else

  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL:Registering STA Client ID: %d QoS %d Add LLC %d ProtFrame %d", 
             pwSTADescType->ucSTAId, 
             pwSTADescType->ucQosEnabled,
             pwSTADescType->ucAddRmvLLC,
             pwSTADescType->ucProtectedFrame));

#endif //FEATURE_WLAN_ESE
#ifdef WLAN_SOFTAP_VSTA_FEATURE
  // if this station was not allocated resources to perform HW-based
  // TX frame translation then force SW-based TX frame translation
  // otherwise use the frame translation supplied by the client

  if (!WDA_IsHwFrameTxTranslationCapable(pvosGCtx, pwSTADescType->ucSTAId)
      || ( WLAN_STA_BT_AMP == pwSTADescType->wSTAType))
  {
      pwSTADescType->ucSwFrameTXXlation = 1;
  }
#endif

  pClientSTA->wSTADesc.ucSwFrameTXXlation = pwSTADescType->ucSwFrameTXXlation;
  pClientSTA->wSTADesc.ucSwFrameRXXlation = pwSTADescType->ucSwFrameRXXlation;

#ifdef FEATURE_WLAN_WAPI
  pClientSTA->wSTADesc.ucIsWapiSta = pwSTADescType->ucIsWapiSta;
#endif /* FEATURE_WLAN_WAPI */

  vos_copy_macaddr( &pClientSTA->wSTADesc.vSTAMACAddress, &pwSTADescType->vSTAMACAddress);

  vos_copy_macaddr( &pClientSTA->wSTADesc.vBSSIDforIBSS, &pwSTADescType->vBSSIDforIBSS);

  vos_copy_macaddr( &pClientSTA->wSTADesc.vSelfMACAddress, &pwSTADescType->vSelfMACAddress);

  /* In volans release L replay check is done at TL */
  if (pTLCb->tlConfigInfo.ucIsReplayCheck)
     pClientSTA->ucIsReplayCheckValid = pwSTADescType->ucIsReplayCheckValid;

  pClientSTA->ulTotalReplayPacketsDetected =  0;
/*Clear replay counters of the STA on all TIDs*/
  for(ucTid = 0; ucTid < WLANTL_MAX_TID ; ucTid++)
  {
    pClientSTA->ullReplayCounter[ucTid] =  0;
  }

  /*--------------------------------------------------------------------
      Set the AC for the registered station to the highest priority AC
      Even if this AC is not supported by the station, correction will be
      made in the main TL loop after the supported mask is properly
      updated in the pending packets call
    --------------------------------------------------------------------*/
  pClientSTA->ucCurrentAC     = WLANTL_AC_HIGH_PRIO;
  pClientSTA->ucCurrentWeight = 0;
  pClientSTA->ucServicedAC    = WLANTL_AC_BK;
  pClientSTA->ucEapolPktPending = 0;

  vos_mem_zero( pClientSTA->aucACMask, sizeof(pClientSTA->aucACMask));

  vos_mem_zero( &pClientSTA->wUAPSDInfo, sizeof(pClientSTA->wUAPSDInfo));

  /*--------------------------------------------------------------------
    Reordering info and AMSDU de-aggregation
    --------------------------------------------------------------------*/
  vos_mem_zero( pClientSTA->atlBAReorderInfo,
     sizeof(pClientSTA->atlBAReorderInfo[0])*
     WLAN_MAX_TID);

  vos_mem_zero( pClientSTA->aucMPDUHeader,
                WLANTL_MPDU_HEADER_LEN);

  pClientSTA->ucMPDUHeaderLen   = 0;
  pClientSTA->vosAMSDUChain     = NULL;
  pClientSTA->vosAMSDUChainRoot = NULL;


  /* Reorder LOCK
   * During handle normal RX frame within RX thread,
   * if MC thread try to preempt, ADDBA, DELBA, TIMER
   * Context should be protected from race */
  for (ucTid = 0; ucTid < WLAN_MAX_TID ; ucTid++)
  {
    if (!VOS_IS_STATUS_SUCCESS(
        vos_lock_init(&pClientSTA->atlBAReorderInfo[ucTid].reorderLock)))
    {
       TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "Lock Init Fail"));
       return VOS_STATUS_E_FAILURE;
    }
  }
  /*--------------------------------------------------------------------
    Stats info
    --------------------------------------------------------------------*/
  vos_mem_zero( pClientSTA->auRxCount,
      sizeof(pClientSTA->auRxCount[0])*
      WLAN_MAX_TID);

  vos_mem_zero( pClientSTA->auTxCount,
      sizeof(pClientSTA->auRxCount[0])*
      WLAN_MAX_TID);
  /* Initial RSSI is always reported as zero because TL doesnt have enough
     data to calculate RSSI. So to avoid reporting zero, we are initializing
     RSSI with RSSI saved in BssDescription during scanning. */
  pClientSTA->rssiAvg = rssi;
  pClientSTA->rssiAvgBmps = rssi;
#ifdef FEATURE_WLAN_TDLS
  if(WLAN_STA_TDLS == pClientSTA->wSTADesc.wSTAType)
  {
    /* If client is TDLS, use TDLS specific alpha */
    pClientSTA->rssiAlpha = WLANTL_HO_TDLS_ALPHA;
  }
  else
  {
    pClientSTA->rssiAlpha = WLANTL_HO_DEFAULT_ALPHA;
  }
#else
    pClientSTA->rssiAlpha = WLANTL_HO_DEFAULT_ALPHA;
#endif /* FEATURE_WLAN_TDLS */
#ifdef WLAN_FEATURE_LINK_LAYER_STATS
  pClientSTA->rssiDataAlpha = WLANTL_HO_DEFAULT_ALPHA;
  pClientSTA->interfaceStats.accessCategoryStats[0].ac = WLANTL_AC_BK;
  pClientSTA->interfaceStats.accessCategoryStats[1].ac = WLANTL_AC_BE;
  pClientSTA->interfaceStats.accessCategoryStats[2].ac = WLANTL_AC_VI;
  pClientSTA->interfaceStats.accessCategoryStats[3].ac = WLANTL_AC_VO;
#endif

  /*Tx not suspended and station fully registered*/
  vos_atomic_set_U8(
        &pClientSTA->ucTxSuspended, 0);

  /* Used until multiple station support will be added*/
  pTLCb->ucRegisteredStaId = pwSTADescType->ucSTAId;

  /* Save the BAP station ID for future usage */
  if ( WLAN_STA_BT_AMP == pwSTADescType->wSTAType )
  {
    pTLCb->tlBAPClient.ucBAPSTAId = pwSTADescType->ucSTAId;
  }

  /*------------------------------------------------------------------------
    Statistics info 
    -----------------------------------------------------------------------*/
  memset(&pClientSTA->trafficStatistics,
         0, sizeof(WLANTL_TRANSFER_STA_TYPE));


  /*------------------------------------------------------------------------
    Start with the state suggested by client caller
    -----------------------------------------------------------------------*/
  pClientSTA->tlState = pwSTADescType->ucInitState;
  /*-----------------------------------------------------------------------
    After all the init is complete we can mark the existance flag 
    ----------------------------------------------------------------------*/
  pClientSTA->ucExists++;

  //flow control fields init
  pClientSTA->ucLwmModeEnabled = FALSE;
  pClientSTA->ucLwmEventReported = FALSE;
  pClientSTA->bmuMemConsumed = 0;
  pClientSTA->uIngress_length = 0;
  pClientSTA->uBuffThresholdMax = WLANTL_STA_BMU_THRESHOLD_MAX;

  pClientSTA->uLwmThreshold = WLANTL_STA_BMU_THRESHOLD_MAX / 3;

  //@@@ HDDSOFTAP does not queue unregistered packet for now
  if ( WLAN_STA_SOFTAP != pwSTADescType->wSTAType )
  { 
    /*------------------------------------------------------------------------
      Forward received frames while STA was not yet registered 
    -  ----------------------------------------------------------------------*/
    if(!VOS_IS_STATUS_SUCCESS(WLANTL_StartForwarding( pwSTADescType->ucSTAId, 
                              pwSTADescType->ucUcastSig, 
                              pwSTADescType->ucBcastSig)))
    {
      VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
         " %s fails to start forwarding", __func__);
    }
#ifdef FEATURE_WLAN_TDLS
    if( WLAN_STA_TDLS == pwSTADescType->wSTAType )
        pTLCb->ucTdlsPeerCount++;
#endif
  }
#ifdef WLAN_FEATURE_RMC
  vos_lock_init(&pClientSTA->mcLock);
#endif /* WLAN_FEATURE_RMC */

  return VOS_STATUS_SUCCESS;
}/* WLANTL_RegisterSTAClient */

/*===========================================================================

  FUNCTION    WLANTL_ClearSTAClient

  DESCRIPTION

    HDD will call this API when it no longer needs data services for the
    particular station.

  DEPENDENCIES

    A station must have been registered before the clear registration is
    called.

  PARAMETERS

   pvosGCtx:        pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context
   ucSTAId:         identifier for the STA to be cleared

  RETURN VALUE

    The result code associated with performing the operation

    VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer to
                        TL cb is NULL ; access would cause a page fault
    VOS_STATUS_E_EXISTS: Station was not registered
    VOS_STATUS_SUCCESS:  Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_ClearSTAClient
(
  v_PVOID_t         pvosGCtx,
  v_U8_t            ucSTAId
)
{
  WLANTL_CbType*  pTLCb = NULL; 
  v_U8_t  ucIndex;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  ENTER();
  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if ( WLANTL_STA_ID_INVALID( ucSTAId ) )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
           "WLAN TL:Invalid station id requested on WLANTL_ClearSTAClient"));
    return VOS_STATUS_E_FAULT;
  }
  /*------------------------------------------------------------------------
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
       "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_ClearSTAClient"));
    return VOS_STATUS_E_FAULT;
  }

  if ( NULL == pTLCb->atlSTAClients[ucSTAId] )
  {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Client Memory was not allocated on %s", __func__));
      return VOS_STATUS_E_FAILURE;
  }

  if ( 0 == pTLCb->atlSTAClients[ucSTAId]->ucExists )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
    "WLAN TL:Station was not previously registered on WLANTL_ClearSTAClient"));
    /* Clean packets cached for the STA */
    WLANTL_StartForwarding(ucSTAId,0,0);
    return VOS_STATUS_E_EXISTS;
  }

  /* Delete BA sessions on all TID's */
  for (ucIndex = 0; ucIndex < WLAN_MAX_TID ; ucIndex++)
  {
     WLANTL_BaSessionDel(pvosGCtx, ucSTAId, ucIndex);
     vos_lock_destroy(&pTLCb->atlSTAClients[ucSTAId]->atlBAReorderInfo[ucIndex].reorderLock);
  }

#ifdef FEATURE_WLAN_TDLS
  /* decrement ucTdlsPeerCount only if it is non-zero */  
  if(WLAN_STA_TDLS == pTLCb->atlSTAClients[ucSTAId]->wSTADesc.wSTAType
      && pTLCb->ucTdlsPeerCount)
      pTLCb->ucTdlsPeerCount--;
#endif

  /*------------------------------------------------------------------------
    Clear station
   ------------------------------------------------------------------------*/
  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL:Clearing STA Client ID: %d", ucSTAId ));
  WLANTL_CleanSTA(pTLCb->atlSTAClients[ucSTAId], 1 /*empty packets*/);

#ifdef WLAN_FEATURE_RMC
  /*--------------------------------------------------------------------
    Delete multicast entries for duplicate detection
    --------------------------------------------------------------------*/
  WLANTL_McastDeleteAllEntries(pTLCb->atlSTAClients[ucSTAId]);

  vos_lock_destroy(&pTLCb->atlSTAClients[ucSTAId]->mcLock);
#endif /* WLAN_FEATURE_RMC */

  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL:Clearing STA Reset History RSSI and Region number"));
  pTLCb->hoSupport.currentHOState.historyRSSI = 0;
  pTLCb->hoSupport.currentHOState.regionNumber = 0;

  return VOS_STATUS_SUCCESS;
}/* WLANTL_ClearSTAClient */

/*===========================================================================

  FUNCTION    WLANTL_ChangeSTAState

  DESCRIPTION

    HDD will make this notification whenever a change occurs in the
    connectivity state of a particular STA.

  DEPENDENCIES

    A station must have been registered before the change state can be
    called.

    RESTRICTION: A station is being notified as authenticated before the
                 keys are installed in HW. This way if a frame is received
                 before the keys are installed DPU will drop that frame.

    Main thread has higher priority that Tx and Rx threads thus guaranteeing
    the following:
        - a station will be in assoc state in TL before TL receives any data
          for it

  PARAMETERS

   pvosGCtx:        pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context
   ucSTAId:         identifier for the STA that is pending transmission
   tlSTAState:     the new state of the connection to the given station


  RETURN VALUE

    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:  Input parameters are invalid
    VOS_STATUS_E_FAULT:  Station ID is outside array boundaries or pointer to
                         TL cb is NULL ; access would cause a page fault
    VOS_STATUS_E_EXISTS: Station was not registered
    VOS_STATUS_SUCCESS:  Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_ChangeSTAState
(
  v_PVOID_t             pvosGCtx,
  v_U8_t                ucSTAId,
  WLANTL_STAStateType   tlSTAState
)
{
  WLANTL_CbType*  pTLCb = NULL;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if ( tlSTAState >= WLANTL_STA_MAX_STATE )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "WLAN TL:Invalid parameter sent on WLANTL_ChangeSTAState"));
    return VOS_STATUS_E_INVAL;
  }

  if ( WLANTL_STA_ID_INVALID( ucSTAId ) )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
             "WLAN TL:Invalid station id requested on WLANTL_ChangeSTAState"));
    return VOS_STATUS_E_FAULT;
  }

  /*------------------------------------------------------------------------
    Extract TL control block and check existance
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
         "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_ChangeSTAState"));
    return VOS_STATUS_E_FAULT;
  }

  if ( NULL == pTLCb->atlSTAClients[ucSTAId] )
  {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Client Memory was not allocated on %s", __func__));
      return VOS_STATUS_E_FAILURE;
  }

  if ( 0 == pTLCb->atlSTAClients[ucSTAId]->ucExists )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
     "WLAN TL:Station was not previously registered on WLANTL_ChangeSTAState"));
    return VOS_STATUS_E_EXISTS;
  }

  /*------------------------------------------------------------------------
    Change STA state
    No need to lock this operation, see restrictions above
   ------------------------------------------------------------------------*/
  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL:Changing state for STA Client ID: %d from %d to %d",
             ucSTAId, pTLCb->atlSTAClients[ucSTAId]->tlState, tlSTAState));

  MTRACE(vos_trace(VOS_MODULE_ID_TL,
                   TRACE_CODE_TL_STA_STATE, ucSTAId,tlSTAState ));

  pTLCb->atlSTAClients[ucSTAId]->tlState = tlSTAState;

  return VOS_STATUS_SUCCESS;
}/* WLANTL_ChangeSTAState */

/*===========================================================================

  FUNCTION    WLANTL_UpdateTdlsSTAClient

  DESCRIPTION

    HDD will call this API when ENABLE_LINK happens and  HDD want to
    register QoS or other params for TDLS peers.

  DEPENDENCIES

    A station must have been registered before the WMM/QOS registration is
    called.

  PARAMETERS

   pvosGCtx:        pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context
   wSTADescType:    STA Descriptor, contains information related to the
                    new added STA

  RETURN VALUE

    The result code associated with performing the operation

    VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer to
                        TL cb is NULL ; access would cause a page fault
    VOS_STATUS_E_EXISTS: Station was not registered
    VOS_STATUS_SUCCESS:  Everything is good :)

  SIDE EFFECTS

============================================================================*/

VOS_STATUS
WLANTL_UpdateTdlsSTAClient
(
 v_PVOID_t                 pvosGCtx,
 WLAN_STADescType*         pwSTADescType
)
{
  WLANTL_CbType* pTLCb = NULL;
  WLANTL_STAClientType* pClientSTA = NULL;
  /*------------------------------------------------------------------------
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb || ( WLAN_MAX_STA_COUNT <= pwSTADescType->ucSTAId))
  {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_UpdateTdlsSTAClient"));
      return VOS_STATUS_E_FAULT;
  }

  pClientSTA = pTLCb->atlSTAClients[pwSTADescType->ucSTAId];
  if ((NULL == pClientSTA) || 0 == pClientSTA->ucExists)
  {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                    "WLAN TL:Station not exists"));
      return VOS_STATUS_E_FAILURE;
  }

  pClientSTA->wSTADesc.ucQosEnabled = pwSTADescType->ucQosEnabled;

  TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
         "WLAN TL: %s: ucQosEnabled of pwSTADescType: %d"
          "pClientSTA->wSTADesc: %d",
          __func__, pwSTADescType->ucQosEnabled,
          pClientSTA->wSTADesc.ucQosEnabled));

  return VOS_STATUS_SUCCESS;

}

VOS_STATUS WLANTL_SetMonRxCbk(v_PVOID_t pvosGCtx, WLANTL_MonRxCBType pfnMonRx)
{
  WLANTL_CbType*  pTLCb = NULL ;
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
      "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_RegisterSTAClient"));
    return VOS_STATUS_E_FAULT;
  }
  pTLCb->pfnMonRx = pfnMonRx;
  return VOS_STATUS_SUCCESS;
}

void WLANTL_SetIsConversionReq(v_PVOID_t pvosGCtx, v_BOOL_t isConversionReq)
{
  WLANTL_CbType*  pTLCb = NULL ;
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
      "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_RegisterSTAClient"));
    return;
  }
  pTLCb->isConversionReq = isConversionReq;
  return;
}


/*===========================================================================

  FUNCTION    WLANTL_STAPtkInstalled

  DESCRIPTION

    HDD will make this notification whenever PTK is installed for the STA

  DEPENDENCIES

    A station must have been registered before the change state can be
    called.

  PARAMETERS

   pvosGCtx:        pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context
   ucSTAId:         identifier for the STA for which Pairwise key is
                    installed

  RETURN VALUE

    The result code associated with performing the operation

    VOS_STATUS_E_FAULT:  Station ID is outside array boundaries or pointer to
                         TL cb is NULL ; access would cause a page fault
    VOS_STATUS_E_EXISTS: Station was not registered
    VOS_STATUS_SUCCESS:  Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_STAPtkInstalled
(
  v_PVOID_t             pvosGCtx,
  v_U8_t                ucSTAId
)
{
  WLANTL_CbType*  pTLCb = NULL;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/

  if ( WLANTL_STA_ID_INVALID( ucSTAId ) )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
             "WLAN TL:Invalid station id requested on WLANTL_ChangeSTAState"));
    return VOS_STATUS_E_FAULT;
  }

  /*------------------------------------------------------------------------
    Extract TL control block and check existance
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
         FL("WLAN TL:Invalid TL pointer from pvosGCtx")));
    return VOS_STATUS_E_FAULT;
  }

  if ( NULL == pTLCb->atlSTAClients[ucSTAId] )
  {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          FL("WLAN TL:Client Memory was not allocated")));
      return VOS_STATUS_E_FAILURE;
  }

  if ( 0 == pTLCb->atlSTAClients[ucSTAId]->ucExists )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
     FL("WLAN TL:Station was not previously registered")));
    return VOS_STATUS_E_EXISTS;
  }

  pTLCb->atlSTAClients[ucSTAId]->ptkInstalled = 1;

  return VOS_STATUS_SUCCESS;
}/* WLANTL_STAPtkInstalled */

/*===========================================================================

  FUNCTION    WLANTL_GetSTAState

  DESCRIPTION

    Returns connectivity state of a particular STA.

  DEPENDENCIES

    A station must have been registered before its state can be retrieved.


  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context
    ucSTAId:        identifier of the station

    OUT
    ptlSTAState:    the current state of the connection to the given station


  RETURN VALUE

    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:  Input parameters are invalid
    VOS_STATUS_E_FAULT:  Station ID is outside array boundaries or pointer to
                         TL cb is NULL ; access would cause a page fault
    VOS_STATUS_E_EXISTS: Station was not registered
    VOS_STATUS_SUCCESS:  Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_GetSTAState
(
  v_PVOID_t             pvosGCtx,
  v_U8_t                ucSTAId,
  WLANTL_STAStateType   *ptlSTAState
)
{
  WLANTL_CbType*  pTLCb = NULL;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if ( NULL == ptlSTAState )
  {
     TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "WLAN TL:Invalid parameter sent on WLANTL_GetSTAState"));
    return VOS_STATUS_E_INVAL;
  }

  if ( WLANTL_STA_ID_INVALID( ucSTAId ) )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
             "WLAN TL:Invalid station id requested on WLANTL_GetSTAState"));
    return VOS_STATUS_E_FAULT;
  }

  /*------------------------------------------------------------------------
    Extract TL control block and check existance
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
         "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_GetSTAState"));
    return VOS_STATUS_E_FAULT;
  }

  if ( NULL == pTLCb->atlSTAClients[ucSTAId] )
  {
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL:Client Memory was not allocated on %s", __func__));
        return VOS_STATUS_E_FAILURE;
  }

  if ( 0 == pTLCb->atlSTAClients[ucSTAId]->ucExists )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
     "WLAN TL:Station was not previously registered on WLANTL_GetSTAState"));
    return VOS_STATUS_E_EXISTS;
  }

  /*------------------------------------------------------------------------
    Get STA state
   ------------------------------------------------------------------------*/
  *ptlSTAState = pTLCb->atlSTAClients[ucSTAId]->tlState;

  return VOS_STATUS_SUCCESS;
}/* WLANTL_GetSTAState */

/*==========================================================================
  FUNCTION   WLANTL_UpdateSTABssIdforIBSS

  DESCRIPTION
    HDD will call this API to update the BSSID for this Station.

  DEPENDENCIES
    The HDD Should registered the staID with TL before calling this function.

  PARAMETERS

    IN
    pvosGCtx:    Pointer to the global vos context; a handle to TL's
                    or WDA's control block can be extracted from its context
    IN
    ucSTAId       The Station ID for Bssid to be updated
    IN
    pBssid          BSSID to be updated

  RETURN VALUE
      The result code associated with performing the operation

      VOS_STATUS_E_INVAL:  Input parameters are invalid
      VOS_STATUS_E_FAULT:  Station ID is outside array boundaries or pointer to
                           TL cb is NULL ; access would cause a page fault
      VOS_STATUS_E_EXISTS: Station was not registered
      VOS_STATUS_SUCCESS:  Everything is good :)

    SIDE EFFECTS
============================================================================*/


VOS_STATUS
WLANTL_UpdateSTABssIdforIBSS
(
  v_PVOID_t             pvosGCtx,
  v_U8_t                ucSTAId,
  v_U8_t               *pBssid
)
{
  WLANTL_CbType*  pTLCb = NULL;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if ( WLANTL_STA_ID_INVALID( ucSTAId ) )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
             "WLAN TL:Invalid station id requested %s", __func__));
    return VOS_STATUS_E_FAULT;
  }

  /*------------------------------------------------------------------------
    Extract TL control block and check existance
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
         "WLAN TL:Invalid TL pointer from pvosGCtx %s", __func__));
    return VOS_STATUS_E_FAULT;
  }

  if ( NULL == pTLCb->atlSTAClients[ucSTAId] )
  {
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL:Client Memory was not allocated on %s", __func__));
        return VOS_STATUS_E_FAILURE;
  }

  if ( 0 == pTLCb->atlSTAClients[ucSTAId]->ucExists )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
     "WLAN TL:Station was not previously registered %s", __func__));
    return VOS_STATUS_E_EXISTS;
  }

  /*------------------------------------------------------------------------
    Update the IBSS BSSID
   ------------------------------------------------------------------------*/
  vos_mem_copy( &pTLCb->atlSTAClients[ucSTAId]->wSTADesc.vBSSIDforIBSS,
                                     pBssid, sizeof(v_MACADDR_t));

  return VOS_STATUS_SUCCESS;
}

/*===========================================================================

  FUNCTION    WLANTL_STAPktPending

  DESCRIPTION

    HDD will call this API when a packet is pending transmission in its
    queues.

  DEPENDENCIES

    A station must have been registered before the packet pending
    notification can be sent.

    RESTRICTION: TL will not count packets for pending notification.
                 HDD is expected to send the notification only when
                 non-empty event gets triggered. Worst case scenario
                 is that TL might end up making a call when Hdds
                 queues are actually empty.

  PARAMETERS

    pvosGCtx:    pointer to the global vos context; a handle to TL's
                 control block can be extracted from its context
    ucSTAId:     identifier for the STA that is pending transmission

  RETURN VALUE

    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:  Input parameters are invalid
    VOS_STATUS_E_FAULT:  Station ID is outside array boundaries or pointer
                         to TL cb is NULL ; access would cause a page fault
    VOS_STATUS_E_EXISTS: Station was not registered
    VOS_STATUS_SUCCESS:  Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_STAPktPending
(
  v_PVOID_t            pvosGCtx,
  v_U8_t               ucSTAId,
  WLANTL_ACEnumType    ucAc
)
{
  WLANTL_CbType*  pTLCb = NULL;
  WLANTL_STAClientType* pClientSTA = NULL;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
      "WLAN TL:Packet pending indication for STA: %d AC: %d", ucSTAId, ucAc);

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if ( WLANTL_STA_ID_INVALID( ucSTAId ) )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "WLAN TL:Invalid station id requested on WLANTL_STAPktPending"));
    return VOS_STATUS_E_FAULT;
  }
  /*------------------------------------------------------------------------
    Extract TL control block and check existance
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
         "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_STAPktPending"));
    return VOS_STATUS_E_FAULT;
  }

  pClientSTA = pTLCb->atlSTAClients[ucSTAId];

  if ( NULL == pClientSTA )
  {
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL:Client Memory was not allocated on %s", __func__));
        return VOS_STATUS_E_FAILURE;
  }

  if ( 0 == pClientSTA->ucExists )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
    "WLAN TL:Station was not previously registered on WLANTL_STAPktPending"));
    return VOS_STATUS_E_EXISTS;
  }

  /*---------------------------------------------------------------------
    Temporary fix to enable TL to fetch packets when multiple peers join
    an IBSS. To fix CR177301. Needs to go away when the actual fix of
    going through all STA's in round robin fashion gets merged in from
    BT AMP branch.
    --------------------------------------------------------------------*/
  pTLCb->ucRegisteredStaId = ucSTAId;

  if( WLANTL_STA_CONNECTED == pClientSTA->tlState )
  { /* EAPOL_HI_PRIORITY : need to find out whether EAPOL is pending before
       WLANTL_FetchPacket()/WLANTL_TxConn() is called.
       change STA_AUTHENTICATED != tlState to CONNECTED == tlState
       to make sure TL is indeed waiting for EAPOL.
       Just in the case when STA got disconnected shortly after connectection */
    pClientSTA->ucEapolPktPending = 1;

    MTRACE(vos_trace(VOS_MODULE_ID_TL,
           TRACE_CODE_TL_EAPOL_PKT_PENDING, ucSTAId, ucAc));

    VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
      "WLAN TL:Packet pending indication for STA: %d AC: %d State: %d", 
               ucSTAId, ucAc, pClientSTA->tlState);
  }

  /*-----------------------------------------------------------------------
    Enable this AC in the AC mask in order for TL to start servicing it
    Set packet pending flag 
    To avoid race condition, serialize the updation of AC and AC mask 
    through WLANTL_TX_STAID_AC_IND message.
  -----------------------------------------------------------------------*/

      pClientSTA->aucACMask[ucAc] = 1;

      vos_atomic_set_U8( &pClientSTA->ucPktPending, 1);

      /*------------------------------------------------------------------------
        Check if there are enough resources for transmission and tx is not
        suspended.
        ------------------------------------------------------------------------*/
       if (( pTLCb->uResCount >=  WDA_TLI_MIN_RES_DATA ) &&
          ( 0 == pTLCb->ucTxSuspended ))
      {

        TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
              "Issuing Xmit start request to BAL"));
           WDA_DS_StartXmit(pvosGCtx);
      }
      else
      {
        /*---------------------------------------------------------------------
          No error code is sent because TL will resume tx autonomously if
          resources become available or tx gets resumed
          ---------------------------------------------------------------------*/
        VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
              "WLAN TL:Request to send but condition not met. Res: %d,Suspend: %d",
              pTLCb->uResCount, pTLCb->ucTxSuspended );
      }
  return VOS_STATUS_SUCCESS;
}/* WLANTL_STAPktPending */

/*==========================================================================

  FUNCTION    WLANTL_SetSTAPriority

  DESCRIPTION

    TL exposes this API to allow upper layers a rough control over the
    priority of transmission for a given station when supporting multiple
    connections.

  DEPENDENCIES

    A station must have been registered before the change in priority can be
    called.

  PARAMETERS

    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context
    ucSTAId:        identifier for the STA that has to change priority

  RETURN VALUE

    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:  Input parameters are invalid
    VOS_STATUS_E_FAULT:  Station ID is outside array boundaries or pointer
                         to TL cb is NULL ; access would cause a page fault
    VOS_STATUS_E_EXISTS: Station was not registered
    VOS_STATUS_SUCCESS:  Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_SetSTAPriority
(
  v_PVOID_t            pvosGCtx,
  v_U8_t               ucSTAId,
  WLANTL_STAPriorityType   tlSTAPri
)
{
  WLANTL_CbType*  pTLCb = NULL;
  WLANTL_STAClientType* pClientSTA = NULL;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if ( WLANTL_STA_ID_INVALID( ucSTAId ) )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL:Invalid station id requested on WLANTL_SetSTAPriority"));
    return VOS_STATUS_E_FAULT;
  }

  /*------------------------------------------------------------------------
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
        "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_SetSTAPriority"));
    return VOS_STATUS_E_FAULT;
  }

  pClientSTA = pTLCb->atlSTAClients[ucSTAId];

  if ( NULL == pClientSTA )
  {
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL:Client Memory was not allocated on %s", __func__));
        return VOS_STATUS_E_FAILURE;
  }

  if ( 0 == pClientSTA->ucExists )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
    "WLAN TL:Station was not previously registered on WLANTL_SetSTAPriority"));
    return VOS_STATUS_E_EXISTS;
  }

  /*------------------------------------------------------------------------
    Re-analize if lock is needed when adding multiple stations
   ------------------------------------------------------------------------*/
  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL:Changing state for STA Pri ID: %d from %d to %d",
             ucSTAId, pClientSTA->tlPri, tlSTAPri));
  pClientSTA->tlPri = tlSTAPri;

  return VOS_STATUS_SUCCESS;
}/* WLANTL_SetSTAPriority */


/*----------------------------------------------------------------------------
    INTERACTION WITH BAP
 ---------------------------------------------------------------------------*/

/*==========================================================================

  FUNCTION    WLANTL_RegisterBAPClient

  DESCRIPTION
    Called by SME to register itself as client for non-data BT-AMP packets.

  DEPENDENCIES
    TL must be initialized before this function can be called.

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    or SME's control block can be extracted from its context
    pfnTlBAPRxFrm:  pointer to the receive processing routine for non-data
                    BT-AMP packets
    pfnFlushOpCompleteCb:
                    pointer to the call back function, for the Flush operation
                    completion.


  RETURN VALUE

    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:  Input parameters are invalid
    VOS_STATUS_E_FAULT:  Station ID is outside array boundaries or pointer
                         to TL cb is NULL ; access would cause a page fault
    VOS_STATUS_E_EXISTS: BAL client was already registered
    VOS_STATUS_SUCCESS:  Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_RegisterBAPClient
(
  v_PVOID_t              pvosGCtx,
  WLANTL_BAPRxCBType     pfnTlBAPRxFrm,
  WLANTL_FlushOpCompCBType  pfnFlushOpCompleteCb
)
{
  WLANTL_CbType*  pTLCb = NULL;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if ( NULL == pfnTlBAPRxFrm )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "WLAN TL:Invalid parameter sent on WLANTL_RegisterBAPClient"));
    return VOS_STATUS_E_INVAL;
  }

  if ( NULL == pfnFlushOpCompleteCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
      "Invalid Flush Complete Cb parameter sent on WLANTL_RegisterBAPClient"));
    return VOS_STATUS_E_INVAL;
  }

  /*------------------------------------------------------------------------
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
    "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_RegisterBAPClient"));
    return VOS_STATUS_E_FAULT;
  }

  /*------------------------------------------------------------------------
    Make sure this is the first registration attempt
   ------------------------------------------------------------------------*/
  if ( 0 != pTLCb->tlBAPClient.ucExists )
  {
    pTLCb->tlBAPClient.ucExists++;
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "WLAN TL:BAP client was already registered"));
    return VOS_STATUS_E_EXISTS;
  }

  /*------------------------------------------------------------------------
    Register station with TL
   ------------------------------------------------------------------------*/
  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL:Registering BAP Client" ));

  pTLCb->tlBAPClient.ucExists++;

  if ( NULL != pfnTlBAPRxFrm ) 
  {
    pTLCb->tlBAPClient.pfnTlBAPRx             = pfnTlBAPRxFrm;
  }

  pTLCb->tlBAPClient.pfnFlushOpCompleteCb   = pfnFlushOpCompleteCb;

  pTLCb->tlBAPClient.vosPendingDataBuff     = NULL;

  return VOS_STATUS_SUCCESS;
}/* WLANTL_RegisterBAPClient */


/*==========================================================================

  FUNCTION    WLANTL_TxBAPFrm

  DESCRIPTION
    BAP calls this when it wants to send a frame to the module

  DEPENDENCIES
    BAP must be registered with TL before this function can be called.

    RESTRICTION: BAP CANNOT push any packets to TL until it did not receive
                 a tx complete from the previous packet, that means BAP
                 sends one packet, wait for tx complete and then
                 sends another one

                 If BAP sends another packet before TL manages to process the
                 previously sent packet call will end in failure

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    or BAP's control block can be extracted from its context
    vosDataBuff:   pointer to the vOSS buffer containing the packet to be
                    transmitted
    pMetaInfo:      meta information about the packet
    pfnTlBAPTxComp: pointer to a transmit complete routine for notifying
                    the result of the operation over the bus

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_FAULT:  pointer to TL cb is NULL ; access would cause a
                         page fault
    VOS_STATUS_E_EXISTS: BAL client was not yet registered
    VOS_STATUS_E_BUSY:   The previous BT-AMP packet was not yet transmitted
    VOS_STATUS_SUCCESS:  Everything is good :)

    Other failure messages may be returned from the BD header handling
    routines, please check apropriate API for more info.

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_TxBAPFrm
(
  v_PVOID_t               pvosGCtx,
  vos_pkt_t*              vosDataBuff,
  WLANTL_MetaInfoType*    pMetaInfo,
  WLANTL_TxCompCBType     pfnTlBAPTxComp
)
{
  WLANTL_CbType*  pTLCb      = NULL;
  VOS_STATUS      vosStatus  = VOS_STATUS_SUCCESS;
  v_MACADDR_t     vDestMacAddr;
  v_U16_t         usPktLen;
  v_U8_t          ucStaId = 0;
  v_U8_t          extraHeadSpace = 0;
  v_U8_t          ucWDSEnabled = 0;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
     TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_TxBAPFrm"));
    return VOS_STATUS_E_FAULT;
  }

  /*------------------------------------------------------------------------
    Ensure that BAP client was registered previously
   ------------------------------------------------------------------------*/
  if (( 0 == pTLCb->tlBAPClient.ucExists ) ||
      ( WLANTL_STA_ID_INVALID(pTLCb->tlBAPClient.ucBAPSTAId) ))
  {
    pTLCb->tlBAPClient.ucExists++;
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:BAP client not register on WLANTL_TxBAPFrm"));
    return VOS_STATUS_E_EXISTS;
  }

  /*------------------------------------------------------------------------
   Check if any BT-AMP Frm is pending
  ------------------------------------------------------------------------*/
  if ( NULL != pTLCb->tlBAPClient.vosPendingDataBuff )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
        "WLAN TL:BT-AMP Frame already pending tx in TL on WLANTL_TxBAPFrm"));
    return VOS_STATUS_E_BUSY;
  }

  /*------------------------------------------------------------------------
    Save buffer and notify BAL; no lock is needed if the above restriction
    is met
    Save the tx complete fnct pointer as tl specific data in the vos buffer
   ------------------------------------------------------------------------*/

  /*------------------------------------------------------------------------
    Translate 802.3 frame to 802.11
   ------------------------------------------------------------------------*/
  ucStaId = pTLCb->tlBAPClient.ucBAPSTAId;
  if ( NULL == pTLCb->atlSTAClients[ucStaId] )
  {
       TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
           "WLAN TL:Client Memory was not allocated on %s", __func__));
       return VOS_STATUS_E_FAILURE;
  }
  if (( 0 == pMetaInfo->ucDisableFrmXtl ) && 
      ( 0 != pTLCb->atlSTAClients[ucStaId]->wSTADesc.ucSwFrameTXXlation ))
  {
    vosStatus =  WLANTL_Translate8023To80211Header( vosDataBuff, &vosStatus,
                                                    pTLCb, &ucStaId,
                                                    pMetaInfo, &ucWDSEnabled,
                                                    &extraHeadSpace);

    if ( VOS_STATUS_SUCCESS != vosStatus )
    {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                "WLAN TL:Error when translating header WLANTL_TxBAPFrm"));

      return vosStatus;
    }

    pMetaInfo->ucDisableFrmXtl = 1;
  }

  /*-------------------------------------------------------------------------
    Call HAL to fill BD header
   -------------------------------------------------------------------------*/

  /* Adding Type, SubType which was missing for EAPOL from BAP */
  pMetaInfo->ucType |= (WLANTL_80211_DATA_TYPE << 4);
  pMetaInfo->ucType |= (WLANTL_80211_DATA_QOS_SUBTYPE);

  vosStatus = WDA_DS_BuildTxPacketInfo( pvosGCtx, vosDataBuff , 
                    &vDestMacAddr, pMetaInfo->ucDisableFrmXtl, 
                    &usPktLen, pTLCb->atlSTAClients[ucStaId]->wSTADesc.ucQosEnabled,
                    ucWDSEnabled, extraHeadSpace, pMetaInfo->ucType,
                            &pTLCb->atlSTAClients[ucStaId]->wSTADesc.vSelfMACAddress,
                    pMetaInfo->ucTID, 0 /* No ACK */, pMetaInfo->usTimeStamp,
                    pMetaInfo->ucIsEapol || pMetaInfo->ucIsWai, pMetaInfo->ucIsArp,
                    pMetaInfo->ucUP, pMetaInfo->ucTxBdToken);

  if ( VOS_STATUS_SUCCESS != vosStatus )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Failed while building TX header %d", vosStatus));
    return vosStatus;
  }

  if ( NULL != pfnTlBAPTxComp )
  {
    vos_pkt_set_user_data_ptr( vosDataBuff, VOS_PKT_USER_DATA_ID_TL,
                               (v_PVOID_t)pfnTlBAPTxComp);
  }
  else
  {
    vos_pkt_set_user_data_ptr( vosDataBuff, VOS_PKT_USER_DATA_ID_TL,
                               (v_PVOID_t)WLANTL_TxCompDefaultCb);

  }

  vos_atomic_set( (uintptr_t*)&pTLCb->tlBAPClient.vosPendingDataBuff,
                      (uintptr_t)vosDataBuff);

  /*------------------------------------------------------------------------
    Check if thre are enough resources for transmission and tx is not
    suspended.
   ------------------------------------------------------------------------*/
  if (( pTLCb->uResCount >=  WDA_TLI_MIN_RES_BAP ) &&
      ( 0 == pTLCb->ucTxSuspended ))
  {
    WDA_DS_StartXmit(pvosGCtx);
  }
  else
  {
    /*---------------------------------------------------------------------
      No error code is sent because TL will resume tx autonomously if
      resources become available or tx gets resumed
     ---------------------------------------------------------------------*/
    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
          "WLAN TL:Request to send from BAP but condition not met.Res: %d,"
                 "Suspend: %d", pTLCb->uResCount, pTLCb->ucTxSuspended ));
  }

  return VOS_STATUS_SUCCESS;
}/* WLANTL_TxBAPFrm */


/*----------------------------------------------------------------------------
    INTERACTION WITH SME
 ---------------------------------------------------------------------------*/

/*==========================================================================

  FUNCTION    WLANTL_GetRssi

  DESCRIPTION
    TL will extract the RSSI information from every data packet from the
    ongoing traffic and will store it. It will provide the result to SME
    upon request.

  DEPENDENCIES

    WARNING: the read and write of this value will not be protected
             by locks, therefore the information obtained after a read
             might not always be consistent.

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    or SME's control block can be extracted from its context
    ucSTAId:        station identifier for the requested value

    OUT
    puRssi:         the average value of the RSSI


  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:  Input parameters are invalid
    VOS_STATUS_E_FAULT:  Station ID is outside array boundaries or pointer
                         to TL cb is NULL ; access would cause a page fault
    VOS_STATUS_E_EXISTS: STA was not yet registered
    VOS_STATUS_SUCCESS:  Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_GetRssi
(
  v_PVOID_t        pvosGCtx,
  v_U8_t           ucSTAId,
  v_S7_t*          pRssi
)
{
  WLANTL_CbType*  pTLCb = NULL;
  WLANTL_STAClientType* pClientSTA = NULL;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if ( NULL == pRssi )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid parameter sent on WLANTL_GetRssi"));
    return VOS_STATUS_E_INVAL;
  }

  if ( WLANTL_STA_ID_INVALID( ucSTAId ) )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid station id requested on WLANTL_GetRssi"));
    return VOS_STATUS_E_FAULT;
  }

  /*------------------------------------------------------------------------
    Extract TL control block and check existance
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_GetRssi"));
    return VOS_STATUS_E_FAULT;
  }

  pClientSTA = pTLCb->atlSTAClients[ucSTAId];

  if ( NULL == pClientSTA )
  {
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL:Client Memory was not allocated on %s", __func__));
        return VOS_STATUS_E_FAILURE;
  }

  if ( 0 == pClientSTA->ucExists )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
         "WLAN TL:Station was not previously registered on WLANTL_GetRssi"));
    return VOS_STATUS_E_EXISTS;
  }

  /*------------------------------------------------------------------------
    Copy will not be locked; please read restriction
   ------------------------------------------------------------------------*/
  if(pTLCb->isBMPS || IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE)
  {
    *pRssi = pClientSTA->rssiAvgBmps;
    /* Check If RSSI is zero because we are reading rssAvgBmps updated by HAL in 
    previous GetStatsRequest. It may be updated as zero by Hal because EnterBmps 
    might not have happend by that time. Hence reading the most recent Rssi 
    calcluated by TL*/
    if(0 == *pRssi)
    {
      *pRssi = pClientSTA->rssiAvg;
    }
  }
  else
  {
    *pRssi = pClientSTA->rssiAvg;
  }

  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                    "WLAN TL:WLANTL_GetRssi for STA: %d RSSI: %d%s",
                    ucSTAId, *pRssi,
                    pTLCb->isBMPS ? " in BMPS" : ""));

  return VOS_STATUS_SUCCESS;
}/* WLANTL_GetRssi */

/*==========================================================================

  FUNCTION    WLANTL_GetSnr

  DESCRIPTION
    TL will extract the SNR information from every data packet from the
    ongoing traffic and will store it. It will provide the result to SME
    upon request.

  DEPENDENCIES

    WARNING: the read and write of this value will not be protected
             by locks, therefore the information obtained after a read
             might not always be consistent.

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    or SME's control block can be extracted from its context
    ucSTAId:        station identifier for the requested value

    OUT
    pSnr:         the average value of the SNR


  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:  Input parameters are invalid
    VOS_STATUS_E_FAULT:  Station ID is outside array boundaries or pointer
                         to TL cb is NULL ; access would cause a page fault
    VOS_STATUS_E_EXISTS: STA was not yet registered
    VOS_STATUS_SUCCESS:  Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_GetSnr
(
  tANI_U8           ucSTAId,
  tANI_S8*          pSnr
)
{
  WLANTL_CbType*  pTLCb = NULL;
  WLANTL_STAClientType* pClientSTA = NULL;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if (NULL == pSnr)
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid parameter sent on %s", __func__));
    return VOS_STATUS_E_INVAL;
  }

  if (WLANTL_STA_ID_INVALID(ucSTAId))
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid station id requested on %s", __func__));
    return VOS_STATUS_E_FAULT;
  }

  /*------------------------------------------------------------------------
    Extract TL control block and check existance
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(vos_get_global_context(VOS_MODULE_ID_TL, NULL));
  if (NULL == pTLCb)
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "WLAN TL:Invalid TL pointer from pvosGCtx on %s", __func__));
    return VOS_STATUS_E_FAULT;
  }

  pClientSTA = pTLCb->atlSTAClients[ucSTAId];

  if (NULL == pClientSTA)
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Client Memory was not allocated on %s", __func__));
    return VOS_STATUS_E_FAILURE;
  }

  if (0 == pClientSTA->ucExists)
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
         "WLAN TL:Station was not previously registered on %s", __func__));
    return VOS_STATUS_E_EXISTS;
  }

  /*------------------------------------------------------------------------
    Copy will not be locked; please read restriction
   ------------------------------------------------------------------------*/
  if (pTLCb->isBMPS)
  {
    *pSnr = pClientSTA->snrAvgBmps;
  }
  else
  {
    /* SNR is averaged over WLANTL_MAX_SNR_DATA_SAMPLES, if there are not enough
     * data samples (snridx) to calculate the average then return the
     * average for the window of prevoius 20 packets. And if there aren't
     * enough samples and the average for previous window of 20 packets is
     * not available then return a predefined value
     *
     * NOTE: the SNR_HACK_BMPS value is defined to 127, documents from HW
     * team reveal that the SNR value has a ceiling well below 127 dBm,
     * so if SNR has value of 127 the userspace applications can know that
     * the SNR has not been computed yet because enough data was not
     * available for SNR calculation
     */
    if (pClientSTA->snrIdx > (WLANTL_MAX_SNR_DATA_SAMPLES/2)
        || !(pClientSTA->prevSnrAvg))
    {
       *pSnr = pClientSTA->snrSum / pClientSTA->snrIdx;
    }
    else if (pClientSTA->prevSnrAvg)
    {
       *pSnr = pClientSTA->prevSnrAvg;
    }
    else
    {
       *pSnr = SNR_HACK_BMPS;
    }
  }

  VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
            "WLAN TL:WLANTL_GetSnr for STA: %d SNR: %d%s",
            ucSTAId, *pSnr,
            pTLCb->isBMPS ? " in BMPS" : "");

  return VOS_STATUS_SUCCESS;
}/* WLANTL_GetSnr */
/*==========================================================================

  FUNCTION    WLANTL_GetLinkQuality

  DESCRIPTION
    TL will extract the SNR information from every data packet from the
    ongoing traffic and will store it. It will provide the result to SME
    upon request.

  DEPENDENCIES

    WARNING: the read and write of this value will not be protected
             by locks, therefore the information obtained after a read
             might not always be consistent.

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    or SME's control block can be extracted from its context
    ucSTAId:        station identifier for the requested value

    OUT
    puLinkQuality:         the average value of the SNR


  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:  Input parameters are invalid
    VOS_STATUS_E_FAULT:  Station ID is outside array boundaries or pointer
                         to TL cb is NULL ; access would cause a page fault
    VOS_STATUS_E_EXISTS: STA was not yet registered
    VOS_STATUS_SUCCESS:  Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_GetLinkQuality
(
  v_PVOID_t             pvosGCtx,
  v_U8_t                ucSTAId,
  v_U32_t*              puLinkQuality
)
{
  WLANTL_CbType*  pTLCb = NULL;
  WLANTL_STAClientType* pClientSTA = NULL;

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if ( NULL == puLinkQuality )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                 "Invalid parameter sent on WLANTL_GetLinkQuality"));
    return VOS_STATUS_E_INVAL;
  }

  if ( WLANTL_STA_ID_INVALID( ucSTAId ) )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                 "Invalid station id requested on WLANTL_GetLinkQuality"));
    return VOS_STATUS_E_FAULT;
  }

  /*------------------------------------------------------------------------
    Extract TL control block and check existance
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                 "Invalid TL pointer from pvosGCtx on WLANTL_GetLinkQuality"));
    return VOS_STATUS_E_FAULT;
  }
  pClientSTA = pTLCb->atlSTAClients[ucSTAId];

  if ( NULL == pClientSTA )
  {
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL:Client Memory was not allocated on %s", __func__));
        return VOS_STATUS_E_FAILURE;
  }

  if ( 0 == pClientSTA->ucExists )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                 "Station was not previously registered on WLANTL_GetLinkQuality"));
    return VOS_STATUS_E_EXISTS;
  }

  /*------------------------------------------------------------------------
    Copy will not be locked; please read restriction
   ------------------------------------------------------------------------*/
  *puLinkQuality = pClientSTA->uLinkQualityAvg;

  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
               "WLANTL_GetLinkQuality for STA: %d LinkQuality: %d", ucSTAId, *puLinkQuality));

  return VOS_STATUS_SUCCESS;
}/* WLANTL_GetLinkQuality */

/*==========================================================================

  FUNCTION    WLANTL_FlushStaTID

  DESCRIPTION
    TL provides this API as an interface to SME (BAP) layer. TL inturn posts a
    message to HAL. This API is called by the SME inorder to perform a flush
    operation.

  DEPENDENCIES

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    or SME's control block can be extracted from its context
    ucSTAId:        station identifier for the requested value
    ucTid:          Tspec ID for the new BA session

    OUT
    The response for this post is received in the main thread, via a response
    message from HAL to TL.

  RETURN VALUE
    VOS_STATUS_SUCCESS:  Everything is good :)

  SIDE EFFECTS
============================================================================*/
VOS_STATUS
WLANTL_FlushStaTID
(
  v_PVOID_t             pvosGCtx,
  v_U8_t                ucSTAId,
  v_U8_t                ucTid
)
{
  WLANTL_CbType*  pTLCb = NULL;
  tpFlushACReq FlushACReqPtr = NULL;
  vos_msg_t vosMessage;


  if ( WLANTL_STA_ID_INVALID( ucSTAId ) )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                 "Invalid station id requested on WLANTL_FlushStaTID"));
    return VOS_STATUS_E_FAULT;
  }

  /*------------------------------------------------------------------------
    Extract TL control block and check existance
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                 "Invalid TL pointer from pvosGCtx on WLANTL_FlushStaTID"));
    return VOS_STATUS_E_FAULT;
  }

  if ( NULL == pTLCb->atlSTAClients[ucSTAId] )
  {
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL:Client Memory was not allocated on %s", __func__));
        return VOS_STATUS_E_FAILURE;
  }

  if ( 0 == pTLCb->atlSTAClients[ucSTAId]->ucExists )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                 "Station was not previously registered on WLANTL_FlushStaTID"));
    return VOS_STATUS_E_EXISTS;
  }

  /*------------------------------------------------------------------------
  We need to post a message with the STA, TID value to HAL. HAL performs the flush
  ------------------------------------------------------------------------*/
  FlushACReqPtr = vos_mem_malloc(sizeof(tFlushACReq));

  if ( NULL == FlushACReqPtr )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
        "WLAN TL: fatal failure, cannot allocate Flush Req structure"));
    VOS_ASSERT(0);
    return VOS_STATUS_E_NOMEM;
  }

  // Start constructing the message for HAL
  FlushACReqPtr->mesgType    = SIR_TL_HAL_FLUSH_AC_REQ;
  FlushACReqPtr->mesgLen     = sizeof(tFlushACReq);
  FlushACReqPtr->mesgLen     = sizeof(tFlushACReq);
  FlushACReqPtr->ucSTAId = ucSTAId;
  FlushACReqPtr->ucTid = ucTid;

  vosMessage.type            = WDA_TL_FLUSH_AC_REQ;
  vosMessage.bodyptr = (void *)FlushACReqPtr;

  vos_mq_post_message(VOS_MQ_ID_WDA, &vosMessage);
  return VOS_STATUS_SUCCESS;
}


/*----------------------------------------------------------------------------
    INTERACTION WITH PE
 ---------------------------------------------------------------------------*/
/*==========================================================================

  FUNCTION    WLANTL_updateSpoofMacAddr

  DESCRIPTION
    Called by HDD to update macaddr

  DEPENDENCIES
    TL must be initialized before this API can be called.

  PARAMETERS

    IN
    pvosGCtx:           pointer to the global vos context; a handle to
                        TL's control block can be extracted from its context
    spoofMacAddr:     spoofed mac adderess
    selfMacAddr:        self Mac Address

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:  Input parameters are invalid
    VOS_STATUS_E_FAULT:  pointer to TL cb is NULL ; access would cause a
                         page fault
    VOS_STATUS_SUCCESS:  Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_updateSpoofMacAddr
(
  v_PVOID_t               pvosGCtx,
  v_MACADDR_t*            spoofMacAddr,
  v_MACADDR_t*            selfMacAddr
)
{
  WLANTL_CbType*  pTLCb = NULL;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_ChangeSTAState");
    return VOS_STATUS_E_FAULT;
  }

  vos_mem_copy(pTLCb->spoofMacAddr.selfMac.bytes, selfMacAddr,
                                                         VOS_MAC_ADDRESS_LEN);
  vos_mem_copy(pTLCb->spoofMacAddr.spoofMac.bytes, spoofMacAddr,
                                                         VOS_MAC_ADDRESS_LEN);

  VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,
                "TL: SelfSTA mac Addr for current Scan "MAC_ADDRESS_STR,
                        MAC_ADDR_ARRAY(pTLCb->spoofMacAddr.selfMac.bytes));

  return VOS_STATUS_SUCCESS;
}/* WLANTL_updateSpoofMacAddr */
/*==========================================================================

  FUNCTION    WLANTL_RegisterMgmtFrmClient

  DESCRIPTION
    Called by PE to register as a client for management frames delivery.

  DEPENDENCIES
    TL must be initialized before this API can be called.

  PARAMETERS

    IN
    pvosGCtx:           pointer to the global vos context; a handle to
                        TL's control block can be extracted from its context
    pfnTlMgmtFrmRx:     pointer to the receive processing routine for
                        management frames

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:  Input parameters are invalid
    VOS_STATUS_E_FAULT:  pointer to TL cb is NULL ; access would cause a
                         page fault
    VOS_STATUS_E_EXISTS: Mgmt Frame client was already registered
    VOS_STATUS_SUCCESS:  Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_RegisterMgmtFrmClient
(
  v_PVOID_t               pvosGCtx,
  WLANTL_MgmtFrmRxCBType  pfnTlMgmtFrmRx
)
{
  WLANTL_CbType*  pTLCb = NULL;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if ( NULL == pfnTlMgmtFrmRx )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
           "WLAN TL:Invalid parameter sent on WLANTL_RegisterMgmtFrmClient"));
    return VOS_STATUS_E_INVAL;
  }

  /*------------------------------------------------------------------------
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_ChangeSTAState"));
    return VOS_STATUS_E_FAULT;
  }

  /*------------------------------------------------------------------------
    Make sure this is the first registration attempt
   ------------------------------------------------------------------------*/
  if ( 0 != pTLCb->tlMgmtFrmClient.ucExists )
  {
    pTLCb->tlMgmtFrmClient.ucExists++;
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "WLAN TL:Management frame client was already registered"));
    return VOS_STATUS_E_EXISTS;
  }

  /*------------------------------------------------------------------------
    Register station with TL
   ------------------------------------------------------------------------*/
  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
            "WLAN TL:Registering Management Frame Client" ));

  pTLCb->tlMgmtFrmClient.ucExists++;

  if ( NULL != pfnTlMgmtFrmRx )
  {
    pTLCb->tlMgmtFrmClient.pfnTlMgmtFrmRx = pfnTlMgmtFrmRx;
  }

  pTLCb->tlMgmtFrmClient.vosPendingDataBuff = NULL;

  return VOS_STATUS_SUCCESS;
}/* WLANTL_RegisterMgmtFrmClient */

/*==========================================================================

  FUNCTION    WLANTL_DeRegisterMgmtFrmClient

  DESCRIPTION
    Called by PE to deregister as a client for management frames delivery.

  DEPENDENCIES
    TL must be initialized before this API can be called.

  PARAMETERS

    IN
    pvosGCtx:           pointer to the global vos context; a handle to
                        TL's control block can be extracted from its context
  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_FAULT:  pointer to TL cb is NULL ; access would cause a
                         page fault
    VOS_STATUS_E_EXISTS: Mgmt Frame client was never registered
    VOS_STATUS_SUCCESS:  Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_DeRegisterMgmtFrmClient
(
  v_PVOID_t               pvosGCtx
)
{
  WLANTL_CbType*  pTLCb = NULL;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_ChangeSTAState"));
    return VOS_STATUS_E_FAULT;
  }

  /*------------------------------------------------------------------------
    Make sure this is the first registration attempt
   ------------------------------------------------------------------------*/
  if ( 0 == pTLCb->tlMgmtFrmClient.ucExists )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "WLAN TL:Management frame client was never registered"));
    return VOS_STATUS_E_EXISTS;
  }

  /*------------------------------------------------------------------------
    Clear registration with TL
   ------------------------------------------------------------------------*/
  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
            "WLAN TL:Deregistering Management Frame Client" ));

  pTLCb->tlMgmtFrmClient.pfnTlMgmtFrmRx = WLANTL_MgmtFrmRxDefaultCb;
  if ( NULL != pTLCb->tlMgmtFrmClient.vosPendingDataBuff)
  {
    TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
              "WLAN TL:Management cache buffer not empty on deregistering"
               " - dropping packet" ));
    vos_pkt_return_packet(pTLCb->tlMgmtFrmClient.vosPendingDataBuff);

    pTLCb->tlMgmtFrmClient.vosPendingDataBuff = NULL; 
  }

  pTLCb->tlMgmtFrmClient.ucExists = 0;

  return VOS_STATUS_SUCCESS;
}/* WLANTL_RegisterMgmtFrmClient */

/*==========================================================================

  FUNCTION    WLANTL_TxMgmtFrm

  DESCRIPTION
    Called by PE when it want to send out a management frame.
    HAL will also use this API for the few frames it sends out, they are not
    management frames howevere it is accepted that an exception will be
    allowed ONLY for the usage of HAL.
    Generic data frames SHOULD NOT travel through this function.

  DEPENDENCIES
    TL must be initialized before this API can be called.

    RESTRICTION: If PE sends another packet before TL manages to process the
                 previously sent packet call will end in failure

                 Frames comming through here must be 802.11 frames, frame
                 translation in UMA will be automatically disabled.

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context;a handle to TL's
                    control block can be extracted from its context
    vosFrmBuf:      pointer to a vOSS buffer containing the management
                    frame to be transmitted
    usFrmLen:       the length of the frame to be transmitted; information
                    is already included in the vOSS buffer
    wFrmType:       the type of the frame being transmitted
    tid:            tid used to transmit this frame
    pfnCompTxFunc:  function pointer to the transmit complete routine
    pvBDHeader:     pointer to the BD header, if NULL it means it was not
                    yet constructed and it lies within TL's responsibility
                    to do so; if not NULL it is expected that it was
                    already packed inside the vos packet
    ucAckResponse:  flag notifying it an interrupt is needed for the
                    acknowledgement received when the frame is sent out
                    the air and ; the interrupt will be processed by HAL,
                    only one such frame can be pending in the system at
                    one time.


  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:  Input parameters are invalid
    VOS_STATUS_E_FAULT:  pointer to TL cb is NULL ; access would cause a
                         page fault
    VOS_STATUS_E_EXISTS: Mgmt Frame client was not yet registered
    VOS_STATUS_E_BUSY:   The previous Mgmt packet was not yet transmitted
    VOS_STATUS_SUCCESS:  Everything is good :)

    Other failure messages may be returned from the BD header handling
    routines, please check apropriate API for more info.

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_TxMgmtFrm
(
  v_PVOID_t            pvosGCtx,
  vos_pkt_t*           vosFrmBuf,
  v_U16_t              usFrmLen,
  v_U8_t               wFrmType,
  v_U8_t               ucTid,
  WLANTL_TxCompCBType  pfnCompTxFunc,
  v_PVOID_t            pvBDHeader,
  v_U32_t              ucAckResponse,
  v_U32_t               ucTxBdToken
)
{
  WLANTL_CbType*  pTLCb = NULL;
  v_MACADDR_t     vDestMacAddr;
  VOS_STATUS      vosStatus = VOS_STATUS_SUCCESS;
  v_U16_t         usPktLen;
  v_U32_t         usTimeStamp = 0;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if ( NULL == vosFrmBuf )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid parameter sent on WLANTL_TxMgmtFrm"));
    return VOS_STATUS_E_INVAL;
  }

  /*------------------------------------------------------------------------
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGP(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_FATAL,
              "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_TxMgmtFrm"));
    return VOS_STATUS_E_FAULT;
  }

  /*------------------------------------------------------------------------
    Ensure that management frame client was previously registered
   ------------------------------------------------------------------------*/
  if ( 0 == pTLCb->tlMgmtFrmClient.ucExists )
  {
    pTLCb->tlMgmtFrmClient.ucExists++;
    TLLOGP(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_FATAL,
          "WLAN TL:Management Frame client not register on WLANTL_TxMgmtFrm"));
    return VOS_STATUS_E_EXISTS;
  }

   /*------------------------------------------------------------------------
    Check if any Mgmt Frm is pending
   ------------------------------------------------------------------------*/
  //vosTempBuff = pTLCb->tlMgmtFrmClient.vosPendingDataBuff;
  if ( NULL != pTLCb->tlMgmtFrmClient.vosPendingDataBuff )
  {

    TLLOGP(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_FATAL,
        "WLAN TL:Management Frame already pending tx in TL: failing old one"));


    /*Failing the tx for the previous packet enqued by PE*/
    //vos_atomic_set( (uintptr_t*)&pTLCb->tlMgmtFrmClient.vosPendingDataBuff,
    //                    (uintptr_t)NULL);

    //vos_pkt_get_user_data_ptr( vosTempBuff, VOS_PKT_USER_DATA_ID_TL,
    //                           (v_PVOID_t)&pfnTxComp);

    /*it should never be NULL - default handler should be registered if none*/
    //if ( NULL == pfnTxComp )
    //{
    //  VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
    //            "NULL pointer to Tx Complete on WLANTL_TxMgmtFrm");
    //  VOS_ASSERT(0);
    //  return VOS_STATUS_E_FAULT;
    //}

    //pfnTxComp( pvosGCtx, vosTempBuff, VOS_STATUS_E_RESOURCES );
    //return VOS_STATUS_E_BUSY;


    //pfnCompTxFunc( pvosGCtx, vosFrmBuf, VOS_STATUS_E_RESOURCES);
    return VOS_STATUS_E_RESOURCES;
  }


  /*------------------------------------------------------------------------
    Check if BD header was build, if not construct
   ------------------------------------------------------------------------*/
  if ( NULL == pvBDHeader )
  {
     v_MACADDR_t*     pvAddr2MacAddr;
     v_U8_t   uQosHdr = VOS_FALSE;

     /* Get address 2 of Mangement Frame to give to WLANHAL_FillTxBd */
     vosStatus = vos_pkt_peek_data( vosFrmBuf, 
                                    WLANTL_MAC_ADDR_ALIGN(1) + VOS_MAC_ADDR_SIZE,
                                    (v_PVOID_t)&pvAddr2MacAddr, VOS_MAC_ADDR_SIZE);

     if ( VOS_STATUS_SUCCESS != vosStatus )
     {
       TLLOGP(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_FATAL,
                "WLAN TL:Failed while attempting to get addr2 %d", vosStatus));
       return vosStatus;
     }

    /* ESE IAPP/TDLS Frame which are data frames but technically used
     * for management functionality comes through route.
     */
    if (WLANTL_IS_QOS_DATA_FRAME(wFrmType))                                      \
    {
        uQosHdr = VOS_TRUE;
    }

    if (WLANTL_IS_PROBE_REQ(wFrmType))
    {
        if (VOS_TRUE == vos_mem_compare((v_VOID_t*) pvAddr2MacAddr,
            (v_VOID_t*) &pTLCb->spoofMacAddr.spoofMac, VOS_MAC_ADDRESS_LEN))
        {
            pvAddr2MacAddr = (v_PVOID_t)pTLCb->spoofMacAddr.selfMac.bytes;
            VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
                "TL: using self sta addr to get staidx for spoofed probe req "
                    MAC_ADDRESS_STR, MAC_ADDR_ARRAY(pvAddr2MacAddr->bytes));
        }
    }

    /*----------------------------------------------------------------------
      Call WDA to build TX header
     ----------------------------------------------------------------------*/
    vosStatus = WDA_DS_BuildTxPacketInfo( pvosGCtx, vosFrmBuf , &vDestMacAddr, 
                   1 /* always 802.11 frames*/, &usPktLen, uQosHdr /*qos not enabled !!!*/, 
                   0 /* WDS off */, 0, wFrmType, pvAddr2MacAddr, ucTid,
                   ucAckResponse, usTimeStamp, 0, 0, 0, ucTxBdToken);


    if ( !VOS_IS_STATUS_SUCCESS(vosStatus) )
    {
      TLLOGP(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_FATAL,
                "WLAN TL:Failed while attempting to build TX header %d", vosStatus));
      return vosStatus;
    }
   }/* if BD header not present */

  /*------------------------------------------------------------------------
    Save buffer and notify BAL; no lock is needed if the above restriction
    is met
    Save the tx complete fnct pointer as tl specific data in the vos buffer
   ------------------------------------------------------------------------*/
  if ( NULL != pfnCompTxFunc )
  {
    vos_pkt_set_user_data_ptr( vosFrmBuf, VOS_PKT_USER_DATA_ID_TL,
                               (v_PVOID_t)pfnCompTxFunc);
  }
  else
  {
    vos_pkt_set_user_data_ptr( vosFrmBuf, VOS_PKT_USER_DATA_ID_TL,
                               (v_PVOID_t)WLANTL_TxCompDefaultCb);

  }
  vos_atomic_set( (uintptr_t*)&pTLCb->tlMgmtFrmClient.vosPendingDataBuff,
                      (uintptr_t)vosFrmBuf);

  /*------------------------------------------------------------------------
    Check if thre are enough resources for transmission and tx is not
    suspended.
   ------------------------------------------------------------------------*/
  if ( pTLCb->uResCount >=  WDA_TLI_MIN_RES_MF )
  {
    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
              "WLAN TL:Issuing Xmit start request to BAL for MGMT"));
    vosStatus = WDA_DS_StartXmit(pvosGCtx);
    if(VOS_STATUS_SUCCESS != vosStatus)
    {
       TLLOGP(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_FATAL,
              "WLAN TL:WDA_DS_StartXmit fails. vosStatus %d", vosStatus));
       vos_atomic_set( (uintptr_t*)&pTLCb->tlMgmtFrmClient.vosPendingDataBuff,0);
    }
    return vosStatus;
    
  }
  else
  {
    /*---------------------------------------------------------------------
      No error code is sent because TL will resume tx autonomously if
      resources become available or tx gets resumed
     ---------------------------------------------------------------------*/
    TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
       "WLAN TL:Request to send for Mgmt Frm but condition not met. Res: %d",
               pTLCb->uResCount));
  }

  return VOS_STATUS_SUCCESS;
}/* WLANTL_TxMgmtFrm */

/*----------------------------------------------------------------------------
    INTERACTION WITH HAL
 ---------------------------------------------------------------------------*/

/*==========================================================================

  FUNCTION    WLANTL_ResetNotification

  DESCRIPTION
    HAL notifies TL when the module is being reset.
    Currently not used.

  DEPENDENCIES

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context


  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_FAULT:  pointer to TL cb is NULL ; access would cause a
                         page fault
    VOS_STATUS_SUCCESS:  Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_ResetNotification
(
  v_PVOID_t   pvosGCtx
)
{
  WLANTL_CbType*  pTLCb = NULL;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
   Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
      "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_ResetNotification"));
    return VOS_STATUS_E_FAULT;
  }

  WLANTL_CleanCB(pTLCb, 1 /*empty all queues and pending packets*/);
  return VOS_STATUS_SUCCESS;
}/* WLANTL_ResetNotification */

/*==========================================================================

  FUNCTION    WLANTL_SuspendDataTx

  DESCRIPTION
    HAL calls this API when it wishes to suspend transmission for a
    particular STA.

  DEPENDENCIES
    The STA for which the request is made must be first registered with
    TL by HDD.

    RESTRICTION:  In case of a suspend, the flag write and read will not be
                  locked: worst case scenario one more packet can get
                  through before the flag gets updated (we can make this
                  write atomic as well to guarantee consistency)

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context
    pucSTAId:       identifier of the station for which the request is made;
                    a value of NULL assumes suspend on all active station
    pfnSuspendTxCB: pointer to the suspend result notification in case the
                    call is asynchronous


  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_FAULT:   Station ID is outside array boundaries or pointer
                          to TL cb is NULL ; access would cause a page fault
    VOS_STATUS_E_EXISTS:  Station was not registered
    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

============================================================================*/

VOS_STATUS
WLANTL_SuspendDataTx
(
  v_PVOID_t              pvosGCtx,
  v_U8_t*                pucSTAId,
  WLANTL_SuspendCBType   pfnSuspendTx
)
{
  WLANTL_CbType*  pTLCb = NULL;
  vos_msg_t       vosMsg;

  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_SuspendDataTx"));
    return VOS_STATUS_E_FAULT;
  }

  /*------------------------------------------------------------------------
    Check the type of request: generic suspend, or per station suspend
   ------------------------------------------------------------------------*/
  if (NULL == pucSTAId)
  {
    /* General Suspend Request received */
    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
              "WLAN TL:General suspend requested"));
    vos_atomic_set_U8( &pTLCb->ucTxSuspended, 1);
    vosMsg.reserved = WLAN_MAX_STA_COUNT;
  }
  else
  {
    if ( WLANTL_STA_ID_INVALID( *pucSTAId ) )
    {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
             "WLAN TL:Invalid station id %d requested on WLANTL_SuspendDataTx", *pucSTAId));
      return VOS_STATUS_E_FAULT;
    }

    if ( NULL == pTLCb->atlSTAClients[*pucSTAId] )
    {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL:Invalid pTLCb->atlSTAClients pointer for STA Id :%d on "
            "WLANTL_SuspendDataTx", *pucSTAId));
      return VOS_STATUS_E_FAULT;
    }

    if ( 0 == pTLCb->atlSTAClients[*pucSTAId]->ucExists )
    {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
             "WLAN TL:Station %d was not previously registered on WLANTL_SuspendDataTx", *pucSTAId));
      return VOS_STATUS_E_EXISTS;
    }

    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
         "WLAN TL:Suspend request for station: %d", *pucSTAId));
    vos_atomic_set_U8( &pTLCb->atlSTAClients[*pucSTAId]->ucTxSuspended, 1);
    vosMsg.reserved = *pucSTAId;
  }

  /*------------------------------------------------------------------------
    Serialize request through TX thread
   ------------------------------------------------------------------------*/
  vosMsg.type     = WLANTL_TX_SIG_SUSPEND;
  vosMsg.bodyptr     = (v_PVOID_t)pfnSuspendTx;

  MTRACE(vos_trace(VOS_MODULE_ID_TL, TRACE_CODE_TL_SUSPEND_DATA_TX,
                    vosMsg.reserved , 0 ));

  if(!VOS_IS_STATUS_SUCCESS(vos_tx_mq_serialize( VOS_MQ_ID_TL, &vosMsg)))
  {
    VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
       " %s fails to post message", __func__);
  }

  return VOS_STATUS_SUCCESS;
}/* WLANTL_SuspendDataTx */

/*==========================================================================

  FUNCTION    WLANTL_ResumeDataTx

  DESCRIPTION
    Called by HAL to resume data transmission for a given STA.

    WARNING: If a station was individually suspended a global resume will
             not resume that station

  DEPENDENCIES

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context
    pucSTAId:       identifier of the station which is being resumed; NULL
                    translates into global resume

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_FAULT:   Station ID is outside array boundaries or pointer
                          to TL cb is NULL ; access would cause a page fault
    VOS_STATUS_E_EXISTS:  Station was not registered
    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

============================================================================*/

VOS_STATUS
WLANTL_ResumeDataTx
(
  v_PVOID_t      pvosGCtx,
  v_U8_t*        pucSTAId
)
{
  WLANTL_CbType*  pTLCb = NULL;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
           "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_ResumeDataTx"));
    return VOS_STATUS_E_FAULT;
  }

  /*------------------------------------------------------------------------
    Check to see the type of resume
   ------------------------------------------------------------------------*/
  if ( NULL == pucSTAId )
  {
    MTRACE(vos_trace(VOS_MODULE_ID_TL, TRACE_CODE_TL_RESUME_DATA_TX,
                      41 , 0 ));

    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
              "WLAN TL:General resume requested"));
    vos_atomic_set_U8( &pTLCb->ucTxSuspended, 0);
  }
  else
  {
    MTRACE(vos_trace(VOS_MODULE_ID_TL, TRACE_CODE_TL_RESUME_DATA_TX,
                      *pucSTAId , 0 ));

    if ( WLANTL_STA_ID_INVALID( *pucSTAId ))
    {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL:Invalid station id %d requested on WLANTL_ResumeDataTx", *pucSTAId));
      return VOS_STATUS_E_FAULT;
    }

    if ( NULL == pTLCb->atlSTAClients[*pucSTAId] )
    {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL:Invalid pTLCb->atlSTAClients pointer for STA Id :%d on "
            "WLANTL_ResumeDataTx", *pucSTAId));
      return VOS_STATUS_E_FAULT;
    }

    if ( 0 == pTLCb->atlSTAClients[*pucSTAId]->ucExists )
    {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
             "WLAN TL:Station %d was not previously registered on WLANTL_ResumeDataTx", *pucSTAId));
      return VOS_STATUS_E_EXISTS;
    }

    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
         "WLAN TL:Resume request for station: %d", *pucSTAId));
    vos_atomic_set_U8( &pTLCb->atlSTAClients[*pucSTAId]->ucTxSuspended, 0);
  }

  /*------------------------------------------------------------------------
    Resuming transmission
   ------------------------------------------------------------------------*/
  if (( pTLCb->uResCount >=  WDA_TLI_MIN_RES_MF ) &&
      ( 0 == pTLCb->ucTxSuspended ))
  {
    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
               "WLAN TL:Resuming transmission"));
    return WDA_DS_StartXmit(pvosGCtx);
  }

  return VOS_STATUS_SUCCESS;
}/* WLANTL_ResumeDataTx */

/*==========================================================================
  FUNCTION    WLANTL_SuspendCB

  DESCRIPTION
    Callback function for serializing Suspend signal through Tx thread

  DEPENDENCIES
    Just notify HAL that suspend in TL is complete.

  PARAMETERS

   IN
   pvosGCtx:       pointer to the global vos context; a handle to TL's
                   control block can be extracted from its context
   pUserData:      user data sent with the callback

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:   invalid input parameters
    VOS_STATUS_E_FAULT:   pointer to TL cb is NULL ; access would cause a
                          page fault
    VOS_STATUS_SUCCESS:   Everything is good :)


  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_SuspendCB
(
  v_PVOID_t             pvosGCtx,
  WLANTL_SuspendCBType  pfnSuspendCB,
  v_U16_t               usReserved
)
{
  WLANTL_CbType*  pTLCb   = NULL;
  v_U8_t          ucSTAId = (v_U8_t)usReserved;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if ( NULL == pfnSuspendCB )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
               "WLAN TL: No Call back processing requested WLANTL_SuspendCB"));
    return VOS_STATUS_SUCCESS;
  }

  /*------------------------------------------------------------------------
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_SuspendCB"));
    return VOS_STATUS_E_FAULT;
  }

  if ( WLANTL_STA_ID_INVALID( ucSTAId ) )
  {
    pfnSuspendCB(pvosGCtx, NULL, VOS_STATUS_SUCCESS);
  }
  else
  {
    pfnSuspendCB(pvosGCtx, &ucSTAId, VOS_STATUS_SUCCESS);
  }

  return VOS_STATUS_SUCCESS;
}/*WLANTL_SuspendCB*/


/*----------------------------------------------------------------------------
    CLIENT INDEPENDENT INTERFACE
 ---------------------------------------------------------------------------*/

/*==========================================================================

  FUNCTION    WLANTL_GetTxPktCount

  DESCRIPTION
    TL will provide the number of transmitted packets counted per
    STA per TID.

  DEPENDENCIES

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context
    ucSTAId:        identifier of the station
    ucTid:          identifier of the tspec

    OUT
    puTxPktCount:   the number of packets tx packet for this STA and TID

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:   Input parameters are invalid
    VOS_STATUS_E_FAULT:   Station ID is outside array boundaries or pointer
                          to TL cb is NULL ; access would cause a page fault
    VOS_STATUS_E_EXISTS:  Station was not registered
    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_GetTxPktCount
(
  v_PVOID_t      pvosGCtx,
  v_U8_t         ucSTAId,
  v_U8_t         ucTid,
  v_U32_t*       puTxPktCount
)
{
  WLANTL_CbType*  pTLCb = NULL;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if ( NULL == puTxPktCount )
  {
     TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "WLAN TL:Invalid parameter sent on WLANTL_GetTxPktCount"));
    return VOS_STATUS_E_INVAL;
  }

  if ( WLANTL_STA_ID_INVALID( ucSTAId ) || WLANTL_TID_INVALID( ucTid) )
  {
     TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
    "WLAN TL:Invalid station id %d/tid %d requested on WLANTL_GetTxPktCount",
            ucSTAId, ucTid));
    return VOS_STATUS_E_FAULT;
  }

  /*------------------------------------------------------------------------
    Extract TL control block and check if station exists
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
     TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_GetTxPktCount"));
    return VOS_STATUS_E_FAULT;
  }

  if ( NULL == pTLCb->atlSTAClients[ucSTAId] )
  {
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL:Client Memory was not allocated on %s", __func__));
        return VOS_STATUS_E_FAILURE;
  }

  if ( 0 == pTLCb->atlSTAClients[ucSTAId]->ucExists )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
    "WLAN TL:Station was not previously registered on WLANTL_GetTxPktCount %d",
     ucSTAId));
    return VOS_STATUS_E_EXISTS;
  }

  /*------------------------------------------------------------------------
    Return data
   ------------------------------------------------------------------------*/
  //VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_MED,
    //         "WLAN TL:Requested tx packet count for STA: %d, TID: %d", 
      //         ucSTAId, ucTid);

  *puTxPktCount = pTLCb->atlSTAClients[ucSTAId]->auTxCount[ucTid];

  return VOS_STATUS_SUCCESS;
}/* WLANTL_GetTxPktCount */

/*==========================================================================

  FUNCTION    WLANTL_GetRxPktCount

  DESCRIPTION
    TL will provide the number of received packets counted per
    STA per TID.

  DEPENDENCIES

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context
    ucSTAId:        identifier of the station
    ucTid:          identifier of the tspec

   OUT
    puTxPktCount:   the number of packets rx packet for this STA and TID

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:   Input parameters are invalid
    VOS_STATUS_E_FAULT:   Station ID is outside array boundaries or pointer
                          to TL cb is NULL ; access would cause a page fault
    VOS_STATUS_E_EXISTS:  Station was not registered
    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_GetRxPktCount
(
  v_PVOID_t      pvosGCtx,
  v_U8_t         ucSTAId,
  v_U8_t         ucTid,
  v_U32_t*       puRxPktCount
)
{
  WLANTL_CbType*  pTLCb = NULL;
  WLANTL_STAClientType* pClientSTA = NULL;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if ( NULL == puRxPktCount )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid parameter sent on WLANTL_GetRxPktCount"));
    return VOS_STATUS_E_INVAL;
  }

  if ( WLANTL_STA_ID_INVALID( ucSTAId ) || WLANTL_TID_INVALID( ucTid) )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
    "WLAN TL:Invalid station id %d/tid %d requested on WLANTL_GetRxPktCount",
             ucSTAId, ucTid));
    return VOS_STATUS_E_FAULT;
  }

  /*------------------------------------------------------------------------
    Extract TL control block and existance
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_GetRxPktCount"));
    return VOS_STATUS_E_FAULT;
  }
  pClientSTA = pTLCb->atlSTAClients[ucSTAId];

  if ( NULL == pClientSTA )
  {
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL:Client Memory was not allocated on %s", __func__));
        return VOS_STATUS_E_FAILURE;
  }

  if ( 0 == pClientSTA->ucExists )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
    "WLAN TL:Station was not previously registered on WLANTL_GetRxPktCount"));
    return VOS_STATUS_E_EXISTS;
  }

  /*------------------------------------------------------------------------
    Return data
   ------------------------------------------------------------------------*/
  TLLOG3(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_MED,
            "WLAN TL:Requested rx packet count for STA: %d, TID: %d",
             ucSTAId, ucTid));

  *puRxPktCount = pClientSTA->auRxCount[ucTid];

  return VOS_STATUS_SUCCESS;
}/* WLANTL_GetRxPktCount */

VOS_STATUS
WLANTL_TxFCFrame
(
  v_PVOID_t       pvosGCtx
);

/*==========================================================================

  FUNCTION    WLANTL_IsEAPOLPending

  DESCRIPTION

    HDD calls this function when hdd_tx_timeout occurs. This checks whether
    EAPOL is pending.

  DEPENDENCIES

    HDD must have registered with TL at least one STA before this function
    can be called.

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context

  RETURN VALUE

    The result code associated with performing the operation

    Success : Indicates EAPOL frame is pending and sta is in connected state

    Failure : EAPOL frame is not pending

  SIDE EFFECTS
============================================================================*/
VOS_STATUS
WLANTL_IsEAPOLPending
(
  v_PVOID_t       pvosGCtx
)
{
   WLANTL_CbType*      pTLCb = NULL;
   v_U32_t             i = 0;
  /*------------------------------------------------------------------------
    Sanity check
    Extract TL control block
   ------------------------------------------------------------------------*/
    pTLCb = VOS_GET_TL_CB(pvosGCtx);
    if (NULL == pTLCb)
    {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
           "WLAN TL:Invalid TL pointer for pvosGCtx"));
      return VOS_STATUS_E_FAILURE;
    }
    /*---------------------------------------------------------------------
     Check to see if there was any EAPOL packet is pending
     *--------------------------------------------------------------------*/
    for ( i = 0; i < WLAN_MAX_STA_COUNT; i++)
    {
       if ((NULL != pTLCb->atlSTAClients[i]) &&
           (pTLCb->atlSTAClients[i]->ucExists) &&
           (0 == pTLCb->atlSTAClients[i]->ucTxSuspended) &&
           (WLANTL_STA_CONNECTED == pTLCb->atlSTAClients[i]->tlState) &&
           (pTLCb->atlSTAClients[i]->ucPktPending)
           )
           return VOS_STATUS_SUCCESS;
    }
    return VOS_STATUS_E_FAILURE;
}

/*============================================================================
                      TL INTERNAL API DEFINITION
============================================================================*/

/*==========================================================================

  FUNCTION    WLANTL_GetFrames

  DESCRIPTION

    BAL calls this function at the request of the lower bus interface.
    When this request is being received TL will retrieve packets from HDD
    in accordance with the priority rules and the count supplied by BAL.

  DEPENDENCIES

    HDD must have registered with TL at least one STA before this function
    can be called.

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    or BAL's control block can be extracted from its context
    uSize:          maximum size accepted by the lower layer
    uFlowMask       TX flow control mask for Prima. Each bit is defined as 
                    WDA_TXFlowEnumType

    OUT
    vosDataBuff:   it will contain a pointer to the first buffer supplied
                    by TL, if there is more than one packet supplied, TL
                    will chain them through vOSS buffers

  RETURN VALUE

    The result code associated with performing the operation

    1 or more: number of required resources if there are still frames to fetch
    0 : error or HDD queues are drained

  SIDE EFFECTS

  NOTE
    
    Featurized uFlowMask. If we want to remove featurization, we need to change
    BAL on Volans.

============================================================================*/
v_U32_t
WLANTL_GetFrames
(
  v_PVOID_t       pvosGCtx,
  vos_pkt_t     **ppFrameDataBuff,
  v_U32_t         uSize,
  v_U8_t          uFlowMask,
  v_BOOL_t*       pbUrgent
)
{
   vos_pkt_t**         pvosDataBuff = (vos_pkt_t**)ppFrameDataBuff;
   WLANTL_CbType*      pTLCb = NULL;
   WLANTL_STAClientType* pClientSTA = NULL;
   v_U32_t             uRemaining = uSize;
   vos_pkt_t*          vosRoot;
   vos_pkt_t*          vosTempBuf;
   WLANTL_STAFuncType  pfnSTAFsm;
   v_U16_t             usPktLen;
   v_U32_t             uResLen;
   v_U8_t              ucSTAId;
   v_U8_t              ucAC;
   vos_pkt_t*          vosDataBuff;
   v_U32_t             uTotalPktLen;
   v_U32_t             i=0;
   v_U32_t             j=0;
   v_U32_t             ucResult = 0;
   VOS_STATUS          vosStatus;
   WLANTL_STAEventType   wSTAEvent;
   tBssSystemRole       systemRole;
   tpAniSirGlobal pMac;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if (( NULL == pTLCb ) || ( NULL == pvosDataBuff ))
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
         "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_ChangeSTAState"));
    return ucResult;
  }

  pMac = vos_get_context(VOS_MODULE_ID_PE, pvosGCtx);
  if ( NULL == pMac )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                      "%s: Invalid pMac", __func__));
    return ucResult;
  }

  vosDataBuff = pTLCb->vosDummyBuf; /* Just to avoid checking for NULL at
                                         each iteration */

  pTLCb->uResCount = uSize;

  /*-----------------------------------------------------------------------
    Save the root as we will walk this chain as we fill it
   -----------------------------------------------------------------------*/
  vosRoot = vosDataBuff;
 
  /*-----------------------------------------------------------------------
    There is still data - until FSM function says otherwise
   -----------------------------------------------------------------------*/
  pTLCb->bUrgent      = FALSE;

  while (( pTLCb->tlConfigInfo.uMinFramesProcThres < pTLCb->uResCount ) &&
         ( 0 < uRemaining ))
  {
    systemRole = wdaGetGlobalSystemRole(pMac);
#ifdef WLAN_SOFTAP_FLOWCTRL_EN
/* FIXME: The code has been disabled since it is creating issues in power save */
    if (eSYSTEM_AP_ROLE == systemRole)
    {
       if (pTLCb->done_once == 0 && NULL == pTLCb->vosTxFCBuf)
       {
          WLANTL_TxFCFrame (pvosGCtx);
          pTLCb->done_once ++;
       }
    } 
    if ( NULL != pTLCb->vosTxFCBuf )
    {
       //there is flow control packet waiting to be sent
       WDA_TLI_PROCESS_FRAME_LEN( pTLCb->vosTxFCBuf, usPktLen, uResLen, uTotalPktLen);
    
       if ( ( pTLCb->uResCount > uResLen ) &&
            ( uRemaining > uTotalPktLen ) &&
            ( uFlowMask & ( 1 << WDA_TXFLOW_FC ) ) )
       {
          TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                   "WLAN TL:Chaining FC frame first on GetFrame"));

          vos_pkt_chain_packet( vosDataBuff, pTLCb->vosTxFCBuf, 1 /*true*/ );

          vos_atomic_set( (uintptr_t*)&pTLCb->vosTxFCBuf, (uintptr_t) NULL);

          /*FC frames cannot be delayed*/
          pTLCb->bUrgent      = TRUE;

          /*Update remaining len from SSC */
          uRemaining        -= (usPktLen + WDA_DXE_HEADER_SIZE);

          /*Update resource count */
          pTLCb->uResCount -= uResLen;
       }
       else
       {
          TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
                "WLAN TL:send fc out of source %s", __func__));
          ucResult = ( pTLCb->uResCount > uResLen )?VOS_TRUE:VOS_FALSE;
          break; /* Out of resources or reached max len */
       }
   }
   else 
#endif //WLAN_SOFTAP_FLOWCTRL_EN

    if (( NULL != pTLCb->tlMgmtFrmClient.vosPendingDataBuff ) &&
        ( uFlowMask & ( 1 << WDA_TXFLOW_MGMT ) ) )
    {
      WDA_TLI_PROCESS_FRAME_LEN( pTLCb->tlMgmtFrmClient.vosPendingDataBuff,
                          usPktLen, uResLen, uTotalPktLen);

      if (usPktLen > WLANTL_MAX_ALLOWED_LEN)
      {
          usPktLen = WLANTL_MAX_ALLOWED_LEN;
          VOS_ASSERT(0);
      }

      if ( ( pTLCb->uResCount > uResLen ) &&
           ( uRemaining > uTotalPktLen ) &&
           ( uFlowMask & ( 1 << WDA_TXFLOW_MGMT ) ) )
      {
        TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                   "WLAN TL:Chaining management frame on GetFrame"));

        vos_pkt_chain_packet( vosDataBuff,
                              pTLCb->tlMgmtFrmClient.vosPendingDataBuff,
                              1 /*true*/ );

        vos_atomic_set( (uintptr_t*)&pTLCb->tlMgmtFrmClient.
                                  vosPendingDataBuff, (uintptr_t)NULL);

        /*management frames cannot be delayed*/
        pTLCb->bUrgent      = TRUE;

        /*Update remaining len from SSC */
        uRemaining        -= (usPktLen + WDA_DXE_HEADER_SIZE);

        /*Update resource count */
        pTLCb->uResCount -= uResLen;
      }
      else
      {
        ucResult = ( pTLCb->uResCount > uResLen )?VOS_TRUE:VOS_FALSE;
        break; /* Out of resources or reached max len */
      }
    }
    else if (( pTLCb->tlBAPClient.vosPendingDataBuff ) &&
             ( WDA_TLI_MIN_RES_BAP <= pTLCb->uResCount ) &&
             ( 0 == pTLCb->ucTxSuspended )          )
    {
      WDA_TLI_PROCESS_FRAME_LEN( pTLCb->tlBAPClient.vosPendingDataBuff,
                          usPktLen, uResLen, uTotalPktLen);

      if (usPktLen > WLANTL_MAX_ALLOWED_LEN)
      {
          usPktLen = WLANTL_MAX_ALLOWED_LEN;
          VOS_ASSERT(0);
      }

      if ( ( pTLCb->uResCount > (uResLen + WDA_TLI_MIN_RES_MF ) ) &&
           ( uRemaining > uTotalPktLen ))
      {
        TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                   "WLAN TL:Chaining BT-AMP frame on GetFrame"));

        vos_pkt_chain_packet( vosDataBuff,
                              pTLCb->tlBAPClient.vosPendingDataBuff,
                              1 /*true*/ );

        /*BAP frames cannot be delayed*/
        pTLCb->bUrgent      = TRUE;

        vos_atomic_set( (uintptr_t*)&pTLCb->tlBAPClient.vosPendingDataBuff,
                        (uintptr_t) NULL);

        /*Update remaining len from SSC */
        uRemaining        -=  (usPktLen + WDA_DXE_HEADER_SIZE);

        /*Update resource count */
        pTLCb->uResCount  -= uResLen;
      }
      else
      {
        ucResult = uResLen + WDA_TLI_MIN_RES_MF;
        break; /* Out of resources or reached max len */
      }
    }
    /* note: this feature implemented only after WLAN_INGETRATED_SOC */
    /* search 'EAPOL_HI_PRIORITY' will show EAPOL HI_PRIORITY change in TL and WDI
       by default, EAPOL will be treated as higher priority, which means
       use mgmt_pool and DXE_TX_HI prority channel.
       this is introduced to address EAPOL failure under high background traffic
       with multi-channel concurrent mode. But this change works in SCC or standalone, too.
       see CR#387009 and WCNSOS-8
     */
    else if (( WDA_TLI_MIN_RES_MF <= pTLCb->uResCount )&&
             ( 0 == pTLCb->ucTxSuspended ) &&
             ( uFlowMask & ( 1 << WDA_TXFLOW_MGMT ) )
            )
    {
        vosTempBuf = NULL;
        /*---------------------------------------------------------------------
         Check to see if there was any EAPOL packet is pending
         *--------------------------------------------------------------------*/
        for ( i = 0; i < WLAN_MAX_STA_COUNT; i++)
        {
           if ((NULL != pTLCb->atlSTAClients[i]) &&
               (pTLCb->atlSTAClients[i]->ucExists) &&
               (0 == pTLCb->atlSTAClients[i]->ucTxSuspended) &&
               (WLANTL_STA_CONNECTED == pTLCb->atlSTAClients[i]->tlState) &&
               (pTLCb->atlSTAClients[i]->ucPktPending)
               )
               break;
        }

        if (i >= WLAN_MAX_STA_COUNT)
        {
           /* No More to Serve Exit Get Frames */
           break;
        }
        /* Serve EAPOL frame with HI_FLOW_MASK */
        ucSTAId = i;

        pClientSTA = pTLCb->atlSTAClients[ucSTAId];

        MTRACE(vos_trace(VOS_MODULE_ID_TL,
               TRACE_CODE_TL_GET_FRAMES_EAPOL, ucSTAId, pClientSTA->tlState));

        if (pClientSTA->wSTADesc.wSTAType == WLAN_STA_INFRA)
        {
            if(0 != pClientSTA->aucACMask[WLANTL_AC_HIGH_PRIO])
            {
              pClientSTA->ucCurrentAC = WLANTL_AC_HIGH_PRIO;
              pTLCb->uCurServedAC = WLANTL_AC_HIGH_PRIO;
            }
            else
                break;
        }
        else
        {
            for (j = WLANTL_MAX_AC ; j > 0; j--)
            {
              if (0 != pClientSTA->aucACMask[j-1])
              {
                pClientSTA->ucCurrentAC = j-1;
                pTLCb->uCurServedAC = j-1;
                break;
              }
            }
        }

        wSTAEvent = WLANTL_TX_EVENT;

        pfnSTAFsm = tlSTAFsm[pClientSTA->tlState].
                        pfnSTATbl[wSTAEvent];

        if ( NULL != pfnSTAFsm )
        {
          pClientSTA->ucNoMoreData = 0;
          vosStatus  = pfnSTAFsm( pvosGCtx, ucSTAId, &vosTempBuf, VOS_FALSE);

          if (( VOS_STATUS_SUCCESS != vosStatus ) &&
              ( NULL != vosTempBuf ))
          {
               pClientSTA->pfnSTATxComp( pvosGCtx, vosTempBuf, vosStatus );
               vosTempBuf = NULL;
               break;
          }/* status success*/
        }

        if (NULL != vosTempBuf)
        {
            WDA_TLI_PROCESS_FRAME_LEN( vosTempBuf, usPktLen, uResLen, uTotalPktLen);

            if (usPktLen > WLANTL_MAX_ALLOWED_LEN)
            {
                usPktLen = WLANTL_MAX_ALLOWED_LEN;
                VOS_ASSERT(0);
            }

            TLLOG4(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,
                      "WLAN TL:Resources needed by frame: %d", uResLen));

            if ( ( pTLCb->uResCount >= (uResLen + WDA_TLI_MIN_RES_MF ) ) &&
               ( uRemaining > uTotalPktLen )
               )
            {
              TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                        "WLAN TL:Chaining data frame on GetFrame"));

              vos_pkt_chain_packet( vosDataBuff, vosTempBuf, 1 /*true*/ );

              /*EAPOL frame cannot be delayed*/
              pTLCb->bUrgent      = TRUE;

              vosTempBuf =  NULL;

              /*Update remaining len from SSC */
              uRemaining  -= (usPktLen + WDA_DXE_HEADER_SIZE);

               /*Update resource count */
              pTLCb->uResCount  -= uResLen;

              //fow control update
              pClientSTA->uIngress_length += uResLen;
              pClientSTA->uBuffThresholdMax = (pClientSTA->uBuffThresholdMax >= uResLen) ?
                (pClientSTA->uBuffThresholdMax - uResLen) : 0;
              pClientSTA->ucEapolPktPending = 0;
              VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                "WLAN TL:GetFrames STA: %d EAPOLPktPending %d",
                         ucSTAId, pClientSTA->ucEapolPktPending);
            }
         }
         else
         {  // no EAPOL frames exit Get frames
            TLLOG2(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                   "WLAN TL:GetFrames STA: %d, no EAPOL frame, continue.",
                   ucSTAId));
            continue;
         }
    }

    else if (( WDA_TLI_MIN_RES_DATA <= pTLCb->uResCount ) &&
             ( 0 == pTLCb->ucTxSuspended ) &&
             ( uFlowMask & WLANTL_DATA_FLOW_MASK))
    {
      /*---------------------------------------------------------------------
        Check to see if there was any packet left behind previously due to
        size constraints
       ---------------------------------------------------------------------*/
      vosTempBuf = NULL;

      if ( NULL != pTLCb->vosTempBuf ) 
      {
        vosTempBuf          = pTLCb->vosTempBuf;
        pTLCb->vosTempBuf   = NULL;
        ucSTAId             = pTLCb->ucCachedSTAId; 
        ucAC                = pTLCb->ucCachedAC;

        if ( NULL == pTLCb->atlSTAClients[ucSTAId] )
        {
            TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                "WLAN TL:Client Memory was not allocated on %s", __func__));
            continue;
        }

        pTLCb->atlSTAClients[ucSTAId]->ucNoMoreData = 0;
        pClientSTA = pTLCb->atlSTAClients[ucSTAId];

        TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                   "WLAN TL:Chaining cached data frame on GetFrame"));
      }
      else
      {
        WLAN_TLGetNextTxIds( pvosGCtx, &ucSTAId);
        if (ucSTAId >= WLAN_MAX_STA_COUNT)
        {
         /* Packets start coming in even after insmod Without *
            starting Hostapd or Interface being up            *
            During which cases STAID is invaled and hence 
            the check. HalMsg_ScnaComplete Triggers */

            break;
        }
        /* ucCurrentAC should have correct AC to be served by calling
           WLAN_TLGetNextTxIds */
        pClientSTA = pTLCb->atlSTAClients[ucSTAId];
        if ( NULL == pClientSTA )
        {
            TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                "WLAN TL:Client Memory was not allocated on %s", __func__));
            continue;
        }

        ucAC = pClientSTA->ucCurrentAC;

        pClientSTA->ucNoMoreData = 1;
        TLLOG4(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,
                   "WLAN TL: %s get one data frame, station ID %d ", __func__, ucSTAId));
        /*-------------------------------------------------------------------
        Check to see that STA is valid and tx is not suspended
         -------------------------------------------------------------------*/
        if ( ( ! WLANTL_STA_ID_INVALID( ucSTAId ) ) &&
           ( 0 == pClientSTA->ucTxSuspended ) &&
           ( 0 == pClientSTA->fcStaTxDisabled) )
        {
          TLLOG4(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,
                   "WLAN TL: %s sta id valid and not suspended ",__func__));
          wSTAEvent = WLANTL_TX_EVENT;

          pfnSTAFsm = tlSTAFsm[pClientSTA->tlState].
                        pfnSTATbl[wSTAEvent];

          if ( NULL != pfnSTAFsm )
          {
            pClientSTA->ucNoMoreData = 0;
            vosStatus  = pfnSTAFsm( pvosGCtx, ucSTAId, &vosTempBuf, VOS_FALSE);

            if (( VOS_STATUS_SUCCESS != vosStatus ) &&
                ( NULL != vosTempBuf ))
            {
                 pClientSTA->pfnSTATxComp( pvosGCtx,
                                                             vosTempBuf,
                                                             vosStatus );
                 vosTempBuf = NULL;
            }/* status success*/
          }/*NULL function state*/
        }/* valid STA id and ! suspended*/
        else
        {
           if ( ! WLANTL_STA_ID_INVALID( ucSTAId ) ) 
           {
                TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_DEBUG,
                  "WLAN TL:Not fetching frame because suspended for sta ID %d", 
                   ucSTAId));
           }
        }
      }/* data */

      if ( NULL != vosTempBuf )
      {
        WDA_TLI_PROCESS_FRAME_LEN( vosTempBuf, usPktLen, uResLen, uTotalPktLen);

        if (usPktLen > WLANTL_MAX_ALLOWED_LEN)
        {
            usPktLen = WLANTL_MAX_ALLOWED_LEN;
            VOS_ASSERT(0);
        }

        TLLOG4(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,
                  "WLAN TL:Resources needed by frame: %d", uResLen));

        if ( ( pTLCb->uResCount >= (uResLen + WDA_TLI_MIN_RES_BAP ) ) &&
             ( uRemaining > uTotalPktLen ) &&
             ( uFlowMask & WLANTL_DATA_FLOW_MASK ) )
        {
          TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                    "WLAN TL:Chaining data frame on GetFrame"));

          vos_pkt_chain_packet( vosDataBuff, vosTempBuf, 1 /*true*/ );
          vosTempBuf =  NULL;

          /*Update remaining len from SSC */
          uRemaining        -= (usPktLen + WDA_DXE_HEADER_SIZE);

           /*Update resource count */
          pTLCb->uResCount  -= uResLen;

          //fow control update
          pClientSTA->uIngress_length += uResLen;
          pClientSTA->uBuffThresholdMax = (pClientSTA->uBuffThresholdMax >= uResLen) ?
            (pClientSTA->uBuffThresholdMax - uResLen) : 0;

          pClientSTA->tx_frames ++;

        }
        else
        {
          /* Store this for later tx - already fetched from HDD */
          pTLCb->vosTempBuf = vosTempBuf;
          pTLCb->ucCachedSTAId = ucSTAId;
          pTLCb->ucCachedAC    = ucAC;
          ucResult = uResLen + WDA_TLI_MIN_RES_BAP;
          TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
               "min %d res required by TL.", ucResult ));
          break; /* Out of resources or reached max len */
        }
      }
      else
      {
           for ( i = 0; i < WLAN_MAX_STA_COUNT; i++)
           {
              if (NULL != pTLCb->atlSTAClients[i] && (pTLCb->atlSTAClients[i]->ucExists) &&
                  (pTLCb->atlSTAClients[i]->ucPktPending) &&
                  (pTLCb->atlSTAClients[i]->disassoc_progress == VOS_FALSE))
              {
                  /* There is station to be Served */
                  break;
              }
           }
           if (i >= WLAN_MAX_STA_COUNT)
           {
              /* No More to Serve Exit Get Frames */
              break;
           }
           else
           {
              /* More to be Served */
              continue;
           }
        } 
      }
    else
    {
      TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL:Returning from GetFrame: resources = %d suspended = %d",
                 pTLCb->uResCount, pTLCb->ucTxSuspended));
      /* TL is starving even when DXE is not in low resource condition 
         Return min resource number required and Let DXE deceide what to do */
      if(( 0 == pTLCb->ucTxSuspended ) && 
         ( uFlowMask & WLANTL_DATA_FLOW_MASK ) )
      {
         TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
             "WLAN TL:Returning from GetFrame: resources = %d",
                 pTLCb->uResCount));
         ucResult = WDA_TLI_MIN_RES_DATA;
      }
       break; /*out of min data resources*/
    }

    pTLCb->usPendingTxCompleteCount++;
    /* Move data buffer up one packet */
    vos_pkt_walk_packet_chain( vosDataBuff, &vosDataBuff, 0/*false*/ );
  }

  /*----------------------------------------------------------------------
    Packet chain starts at root + 1
   ----------------------------------------------------------------------*/
  vos_pkt_walk_packet_chain( vosRoot, &vosDataBuff, 1/*true*/ );

  *pvosDataBuff = vosDataBuff;
  if (pbUrgent)
  {
      *pbUrgent     = pTLCb->bUrgent;
  }
  else
  {
      VOS_ASSERT( pbUrgent );
  }
  return ucResult;
}/* WLANTL_GetFrames */


/*==========================================================================

  FUNCTION    WLANTL_TxComp

  DESCRIPTION
    It is being called by BAL upon asynchronous notification of the packet
    or packets  being sent over the bus.

  DEPENDENCIES
    Tx complete cannot be called without a previous transmit.

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    or BAL's control block can be extracted from its context
    vosDataBuff:   it will contain a pointer to the first buffer for which
                    the BAL report is being made, if there is more then one
                    packet they will be chained using vOSS buffers.
    wTxStatus:      the status of the transmitted packet, see above chapter
                    on HDD interaction for a list of possible values

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:   Input parameters are invalid
    VOS_STATUS_E_FAULT:   pointer to TL cb is NULL ; access would cause a
                          page fault
    VOS_STATUS_E_EXISTS:  Station was not registered
    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_TxComp
(
  v_PVOID_t       pvosGCtx,
  vos_pkt_t      *pFrameDataBuff,
  VOS_STATUS      wTxStatus
)
{
  vos_pkt_t*           vosDataBuff = (vos_pkt_t*)pFrameDataBuff;
  WLANTL_CbType*       pTLCb     = NULL;
  WLANTL_TxCompCBType  pfnTxComp = NULL;
  VOS_STATUS           vosStatus = VOS_STATUS_SUCCESS;
  vos_pkt_t*           vosTempTx = NULL;

  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if ( NULL == vosDataBuff )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Extraneous NULL data pointer on WLANTL_TxComp"));
    return VOS_STATUS_E_INVAL;
  }

  /*------------------------------------------------------------------------
   Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_TxComp"));
    return VOS_STATUS_E_FAULT;
  }

  while ((0 < pTLCb->usPendingTxCompleteCount) &&
         ( VOS_STATUS_SUCCESS == vosStatus ) &&
         ( NULL !=  vosDataBuff))
  {
    vos_pkt_get_user_data_ptr(  vosDataBuff, VOS_PKT_USER_DATA_ID_TL,
                               (v_PVOID_t)&pfnTxComp);

    /*it should never be NULL - default handler should be registered if none*/
    if ( NULL == pfnTxComp )
    {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                "WLAN TL:NULL pointer to Tx Complete on WLANTL_TxComp"));
      VOS_ASSERT(0);
      return VOS_STATUS_E_FAULT;
    }

    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
               "WLAN TL:Calling Tx complete for pkt %pK in function %pK",
               vosDataBuff, pfnTxComp));

    vosTempTx = vosDataBuff;
    vosStatus = vos_pkt_walk_packet_chain( vosDataBuff,
                                           &vosDataBuff, 1/*true*/);

    pfnTxComp( pvosGCtx, vosTempTx, wTxStatus );

    pTLCb->usPendingTxCompleteCount--;
  }

 
  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
            "WLAN TL: current TL values are: resources = %d "
            "pTLCb->usPendingTxCompleteCount = %d",
              pTLCb->uResCount, pTLCb->usPendingTxCompleteCount));

  return VOS_STATUS_SUCCESS;
}/* WLANTL_TxComp */

/*==========================================================================

  FUNCTION    WLANTL_CacheSTAFrame

  DESCRIPTION
    Internal utility function for for caching incoming data frames that do 
    not have a registered station yet. 

  DEPENDENCIES
    TL must be initiailized before this function gets called.
    In order to benefit from thsi caching, the components must ensure that
    they will only register with TL at the moment when they are fully setup
    and ready to receive incoming data 
   
  PARAMETERS

    IN
    
    pTLCb:                  TL control block
    ucSTAId:                station id
    vosTempBuff:            the data packet
    uDPUSig:                DPU signature of the incoming packet
    bBcast:                 true if packet had the MC/BC bit set 

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_FAULT:   pointer to TL cb is NULL or STA Id invalid ; access
                          would cause a page fault
    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

============================================================================*/
static VOS_STATUS
WLANTL_CacheSTAFrame
(
  WLANTL_CbType*    pTLCb,
  v_U8_t            ucSTAId,
  vos_pkt_t*        vosTempBuff,
  v_U32_t           uDPUSig,
  v_U8_t            bBcast,
  v_U8_t            ucFrmType
)
{
  v_U8_t    ucUcastSig;
  v_U8_t    ucBcastSig;
  v_BOOL_t  bOldSTAPkt;
  WLANTL_STAClientType* pClientSTA = NULL;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

  /*-------------------------------------------------------------------------  
     Sanity check 
   -------------------------------------------------------------------------*/ 
  if (( NULL == pTLCb ) || ( NULL == vosTempBuff ) )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL: Invalid input pointer on WLANTL_CacheSTAFrame TL %pK"
               " Packet %pK", pTLCb, vosTempBuff ));
    return VOS_STATUS_E_FAULT;
  }

  if ( WLANTL_STA_ID_INVALID( ucSTAId ) )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
         "WLAN TL:Invalid station id requested on WLANTL_CacheSTAFrame"));
    return VOS_STATUS_E_FAULT;
  }
  pClientSTA = pTLCb->atlSTAClients[ucSTAId];

  if ( NULL == pClientSTA )
  {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Client Memory was not allocated on %s", __func__));
      return VOS_STATUS_E_FAILURE;
  }

  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL:Attempting to cache pkt for STA %d, BD DPU Sig: %d with sig UC: %d, BC: %d", 
             ucSTAId, uDPUSig,
             pClientSTA->wSTADesc.ucUcastSig,
             pClientSTA->wSTADesc.ucBcastSig));

  if(WLANTL_IS_CTRL_FRAME(ucFrmType))
  {
      TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                 "WLAN TL: No need to cache CTRL frame. Dropping"));
      vos_pkt_return_packet(vosTempBuff); 
      return VOS_STATUS_SUCCESS;
  }

  /*-------------------------------------------------------------------------
    Check if the packet that we are trying to cache belongs to the old
    registered station (if any) or the new (potentially)upcoming station
    
    - If the STA with this Id was never registered with TL - the signature
    will be invalid;
    - If the STA was previously registered TL will have cached the former
    set of DPU signatures
  -------------------------------------------------------------------------*/
  if ( bBcast )
  {
    ucBcastSig = (v_U8_t)uDPUSig;
    bOldSTAPkt = (( WLAN_TL_INVALID_B_SIG != 
                  pClientSTA->wSTADesc.ucBcastSig ) &&
      ( ucBcastSig == pClientSTA->wSTADesc.ucBcastSig ));
  }
  else
  {
    ucUcastSig = (v_U8_t)uDPUSig;
    bOldSTAPkt = (( WLAN_TL_INVALID_U_SIG != 
                    pClientSTA->wSTADesc.ucUcastSig ) &&
        ( ucUcastSig == pClientSTA->wSTADesc.ucUcastSig ));
  }

  /*------------------------------------------------------------------------
    If the value of the DPU SIG matches the old, this packet will not
    be cached as it belonged to the former association
    In case the SIG does not match - this is a packet for a potentially new
    associated station 
  -------------------------------------------------------------------------*/
  if ( bOldSTAPkt || bBcast )
  {
    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
               "WLAN TL:Data packet matches old sig for sig DPU: %d UC: %d, "
               "BC: %d - dropping", 
               uDPUSig, 
               pClientSTA->wSTADesc.ucUcastSig,
               pClientSTA->wSTADesc.ucBcastSig));
    vos_pkt_return_packet(vosTempBuff); 
  }
  else
  {
    if ( NULL == pClientSTA->vosBegCachedFrame )
    {
      /*this is the first frame that we are caching */
      pClientSTA->vosBegCachedFrame = vosTempBuff;

      pClientSTA->tlCacheInfo.cacheInitTime = vos_timer_get_system_time();
      pClientSTA->tlCacheInfo.cacheDoneTime =
              pClientSTA->tlCacheInfo.cacheInitTime;
      pClientSTA->tlCacheInfo.cacheSize = 1;

      MTRACE(vos_trace(VOS_MODULE_ID_TL, TRACE_CODE_TL_CACHE_FRAME,
                       ucSTAId, pClientSTA->tlCacheInfo.cacheSize));

    }
    else
    {
      /*this is a subsequent frame that we are caching: chain to the end */
      vos_pkt_chain_packet(pClientSTA->vosEndCachedFrame,
                           vosTempBuff, VOS_TRUE);

      pClientSTA->tlCacheInfo.cacheDoneTime = vos_timer_get_system_time();
      pClientSTA->tlCacheInfo.cacheSize ++;

      if (pClientSTA->tlCacheInfo.cacheSize % WLANTL_CACHE_TRACE_WATERMARK == 0)
      {
        VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                  "%s: Cache High watermark for staid:%d (%d)",
                  __func__,ucSTAId, pClientSTA->tlCacheInfo.cacheSize);
        MTRACE(vos_trace(VOS_MODULE_ID_TL, TRACE_CODE_TL_CACHE_FRAME,
                         ucSTAId, pClientSTA->tlCacheInfo.cacheSize));
      }
    }
    pClientSTA->vosEndCachedFrame = vosTempBuff;
  }/*else new packet*/

  return VOS_STATUS_SUCCESS; 
}/*WLANTL_CacheSTAFrame*/

/*==========================================================================

  FUNCTION    WLANTL_FlushCachedFrames

  DESCRIPTION
    Internal utility function used by TL to flush the station cache

  DEPENDENCIES
    TL must be initiailized before this function gets called.
    
  PARAMETERS

    IN

    vosDataBuff:   it will contain a pointer to the first cached buffer
                   received,

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

  NOTE
    This function doesn't re-initialize vosDataBuff to NULL. It's caller's 
    responsibility to do so, if required, after this function call.
    Because of this restriction, we decide to make this function to static
    so that upper layer doesn't need to be aware of this restriction. 
    
============================================================================*/
static VOS_STATUS
WLANTL_FlushCachedFrames
(
  vos_pkt_t*      vosDataBuff
)
{
  /*----------------------------------------------------------------------
    Return the entire chain to vos if there are indeed cache frames 
  ----------------------------------------------------------------------*/
  if ( NULL != vosDataBuff )
  {
    vos_pkt_return_packet(vosDataBuff);
  }

  return VOS_STATUS_SUCCESS;  
}/*WLANTL_FlushCachedFrames*/

/*==========================================================================

  FUNCTION    WLANTL_ForwardSTAFrames

  DESCRIPTION
    Internal utility function for either forwarding cached data to the station after
    the station has been registered, or flushing cached data if the station has not 
    been registered. 
     

  DEPENDENCIES
    TL must be initiailized before this function gets called.
   
  PARAMETERS

    IN
    
    pTLCb:                  TL control block
    ucSTAId:                station id

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_FAULT:   pointer to TL cb is NULL ; access would cause a
                          page fault
    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS
    This function doesn't re-initialize vosDataBuff to NULL. It's caller's 
    responsibility to do so, if required, after this function call.
    Because of this restriction, we decide to make this function to static
    so that upper layer doesn't need to be aware of this restriction. 

============================================================================*/
static VOS_STATUS
WLANTL_ForwardSTAFrames
(
  void*             pvosGCtx,
  v_U8_t            ucSTAId,
  v_U8_t            ucUcastSig,
  v_U8_t            ucBcastSig
)
{
  WLANTL_CbType*  pTLCb = NULL;
  WLANTL_STAClientType* pClientSTA = NULL;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

  /*-------------------------------------------------------------------------  
     Sanity check 
   -------------------------------------------------------------------------*/ 
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
        "WLAN TL: Invalid input pointer on WLANTL_ForwardSTAFrames TL %pK",
         pTLCb ));
    return VOS_STATUS_E_FAULT;
  }

  if ( WLANTL_STA_ID_INVALID( ucSTAId ) )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
         "WLAN TL:Invalid station id requested on WLANTL_ForwardSTAFrames"));
    return VOS_STATUS_E_FAULT;
  }

  //WLAN_TL_LOCK_STA_CACHE(pTLCb->atlSTAClients[ucSTAId]); 

  /*------------------------------------------------------------------------
     Check if station has not been registered in the mean while
     if not registered, flush cached frames.
   ------------------------------------------------------------------------*/ 
  pClientSTA = pTLCb->atlSTAClients[ucSTAId];

  if ( NULL == pClientSTA )
  {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Client Memory was not allocated on %s", __func__));
      return VOS_STATUS_E_FAILURE;
  }

  if ( 0 == pClientSTA->ucExists )
  {
    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
       "WLAN TL:Station has been deleted for STA %d - flushing cache", ucSTAId));
    MTRACE(vos_trace(VOS_MODULE_ID_TL, TRACE_CODE_TL_FLUSH_CACHED_FRAMES,
                     ucSTAId, pClientSTA->tlCacheInfo.cacheSize));
    WLANTL_FlushCachedFrames(pClientSTA->vosBegCachedFrame);
    goto done; 
  }

  /*------------------------------------------------------------------------
    Forwarding cache frames received while the station was in the process   
    of being registered with the rest of the SW components   

    Access to the cache must be locked; similarly updating the signature and   
    the existence flag must be synchronized because these values are checked   
    during cached  
  ------------------------------------------------------------------------*/
  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
       "WLAN TL:Preparing to fwd packets for STA %d", ucSTAId));

  /*-----------------------------------------------------------------------
    Save the new signature values
  ------------------------------------------------------------------------*/
  pClientSTA->wSTADesc.ucUcastSig  = ucUcastSig;
  pClientSTA->wSTADesc.ucBcastSig  = ucBcastSig;

  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
       "WLAN TL:Fwd-ing packets for STA %d UC %d BC %d",
       ucSTAId, ucUcastSig, ucBcastSig));

  /*-------------------------------------------------------------------------  
     Check to see if we have any cached data to forward 
   -------------------------------------------------------------------------*/ 
  if ( NULL != pClientSTA->vosBegCachedFrame )
  {
    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
               "WLAN TL: Fwd-ing Cached packets for station %d", ucSTAId ));

    WLANTL_RxCachedFrames( pTLCb, 
                           ucSTAId, 
                           pClientSTA->vosBegCachedFrame);
  }
  else
  {
     TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
               "WLAN TL: NO cached packets for station %d", ucSTAId ));
  }

done:
  /*-------------------------------------------------------------------------  
   Clear the station cache 
   -------------------------------------------------------------------------*/
  pClientSTA->vosBegCachedFrame = NULL;
  pClientSTA->vosEndCachedFrame = NULL;
  pClientSTA->tlCacheInfo.cacheSize = 0;
  pClientSTA->tlCacheInfo.cacheClearTime = vos_timer_get_system_time();

    /*-----------------------------------------------------------------------
    After all the init is complete we can mark the existance flag 
    ----------------------------------------------------------------------*/
  pClientSTA->enableCaching = 0;

  //WLAN_TL_UNLOCK_STA_CACHE(pTLCb->atlSTAClients[ucSTAId]); 
  return VOS_STATUS_SUCCESS; 

}/*WLANTL_ForwardSTAFrames*/


#if defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_ESE_UPLOAD)
/*==========================================================================

  FUNCTION    WLANTL_IsIAPPFrame

  DESCRIPTION
    Internal utility function for detecting incoming ESE IAPP frames

  DEPENDENCIES

  PARAMETERS

    IN
    
    pvBDHeader:             pointer to the BD header
    vosTempBuff:            the data packet

    IN/OUT
    pFirstDataPktArrived:   static from caller function; used for rssi 
                            computation
  RETURN VALUE
    The result code associated with performing the operation

    VOS_TRUE:   It is a IAPP frame
    VOS_FALSE:  It is NOT IAPP frame

  SIDE EFFECTS

============================================================================*/
v_BOOL_t
WLANTL_IsIAPPFrame
(
  v_PVOID_t         pvBDHeader,
  vos_pkt_t*        vosTempBuff
)
{
  v_U16_t             usMPDUDOffset;
  v_U8_t              ucOffset;
  v_U8_t              ucSnapHdr[WLANTL_LLC_SNAP_SIZE];
  v_SIZE_t            usSnapHdrSize = WLANTL_LLC_SNAP_SIZE;
  VOS_STATUS          vosStatus;

  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Check if OUI field is present.
  -------------------------------------------------------------------------*/
  if ( VOS_FALSE == WDA_IS_RX_LLC_PRESENT(pvBDHeader) )
  {
      TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
                  "WLAN TL:LLC header removed, cannot determine BT-AMP type -"
                  "dropping pkt"));
      /* Drop packet */
      vos_pkt_return_packet(vosTempBuff);
      return VOS_TRUE;
  }
  usMPDUDOffset = (v_U8_t)WDA_GET_RX_MPDU_DATA_OFFSET(pvBDHeader);
  ucOffset      = (v_U8_t)usMPDUDOffset + WLANTL_LLC_SNAP_OFFSET;

  vosStatus = vos_pkt_extract_data( vosTempBuff, ucOffset,
                                (v_PVOID_t)ucSnapHdr, &usSnapHdrSize);

  if (( VOS_STATUS_SUCCESS != vosStatus)) 
  {
    TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
                "Unable to extract Snap Hdr of data  packet -"
                "dropping pkt"));
    return VOS_FALSE;
  }

 /*------------------------------------------------------------------------
    Check if this is IAPP frame by matching Aironet Snap hdr.
  -------------------------------------------------------------------------*/
  // Compare returns 1 if values are same and 0
  // if not the same.
  if (( WLANTL_LLC_SNAP_SIZE != usSnapHdrSize ) ||
     ( 0 == vos_mem_compare(ucSnapHdr, (v_PVOID_t)WLANTL_AIRONET_SNAP_HEADER,
                            WLANTL_LLC_SNAP_SIZE ) ))
  {
    return VOS_FALSE;
  }

  return VOS_TRUE;

}
#endif //FEATURE_WLAN_ESE

/*==========================================================================

  FUNCTION    WLANTL_ProcessBAPFrame

  DESCRIPTION
    Internal utility function for processing incoming BT-AMP frames

  DEPENDENCIES
    TL must be initiailized before this function gets called.
    Bothe the BT-AMP station and the BAP Ctrl path must have been previously 
    registered with TL.

  PARAMETERS

    IN
    
    pvBDHeader:             pointer to the BD header
    vosTempBuff:            the data packet
    pTLCb:                  TL control block
    ucSTAId:                station id

    IN/OUT
    pFirstDataPktArrived:   static from caller function; used for rssi 
                            computation
  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:   Input parameters are invalid
    VOS_STATUS_E_FAULT:   pointer to TL cb is NULL ; access would cause a
                          page fault
    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

============================================================================*/
v_BOOL_t
WLANTL_ProcessBAPFrame
(
  v_PVOID_t         pvBDHeader,
  vos_pkt_t*        vosTempBuff,
  WLANTL_CbType*    pTLCb,
  v_U8_t*           pFirstDataPktArrived,
  v_U8_t            ucSTAId
)
{
  v_U16_t             usMPDUDOffset;
  v_U8_t              ucOffset;
  v_U8_t              ucOUI[WLANTL_LLC_OUI_SIZE];
  v_SIZE_t            usOUISize = WLANTL_LLC_OUI_SIZE;
  VOS_STATUS          vosStatus;
  v_U16_t             usType;
  v_SIZE_t            usTypeLen = sizeof(usType);
  v_U8_t              ucMPDUHOffset;
  v_U8_t              ucMPDUHLen = 0;
  v_U16_t             usActualHLen = 0;

  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Extract OUI and type from LLC and validate; if non-data send to BAP
  -------------------------------------------------------------------------*/
  if ( VOS_FALSE == WDA_IS_RX_LLC_PRESENT(pvBDHeader) )
  {
    TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
          "WLAN TL:LLC header removed, cannot determine BT-AMP type -"
              "dropping pkt"));
    /* Drop packet */
    vos_pkt_return_packet(vosTempBuff);
    return VOS_TRUE; 
  }

  usMPDUDOffset = (v_U8_t)WDA_GET_RX_MPDU_DATA_OFFSET(pvBDHeader);
  ucMPDUHOffset = (v_U8_t)WDA_GET_RX_MPDU_HEADER_OFFSET(pvBDHeader);
  ucMPDUHLen    = (v_U8_t)WDA_GET_RX_MPDU_HEADER_LEN(pvBDHeader);
  ucOffset      = (v_U8_t)usMPDUDOffset + WLANTL_LLC_OUI_OFFSET;

  vosStatus = vos_pkt_extract_data( vosTempBuff, ucOffset,
                                (v_PVOID_t)ucOUI, &usOUISize);

#if 0
  // Compare returns 1 if values are same and 0
  // if not the same.
  if (( WLANTL_LLC_OUI_SIZE != usOUISize ) ||
     ( 0 == vos_mem_compare(ucOUI, (v_PVOID_t)WLANTL_BT_AMP_OUI,
                            WLANTL_LLC_OUI_SIZE ) ))
  {
    TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
                "LLC header points to diff OUI in BT-AMP station -"
                "dropping pkt"));
    /* Drop packet */
    vos_pkt_return_packet(vosTempBuff);
    return VOS_TRUE;
  }
#endif
  /*------------------------------------------------------------------------
    Extract LLC OUI and ensure that this is indeed a BT-AMP frame
   ------------------------------------------------------------------------*/
  vosStatus = vos_pkt_extract_data( vosTempBuff,
                                 ucOffset + WLANTL_LLC_OUI_SIZE,
                                (v_PVOID_t)&usType, &usTypeLen);

  if (( VOS_STATUS_SUCCESS != vosStatus) ||
      ( sizeof(usType) != usTypeLen ))
  {
    TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
                "Unable to extract type on incoming BAP packet -"
                "dropping pkt"));
    /* Drop packet */
    vos_pkt_return_packet(vosTempBuff);
    return VOS_TRUE;
  }

  /*------------------------------------------------------------------------
    Check if this is BT-AMP data or ctrl packet(RSN, LinkSvision, ActivityR)
   ------------------------------------------------------------------------*/
  usType = vos_be16_to_cpu(usType);

  if (WLANTL_BAP_IS_NON_DATA_PKT_TYPE(usType))
  {
    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
      "WLAN TL:Non-data packet received over BT-AMP link: %d, => BAP",
               usType));

    /*Flatten packet as BAP expects to be able to peek*/
    if ( VOS_STATUS_SUCCESS != vos_pkt_flatten_rx_pkt(&vosTempBuff))
    {
      TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
                 "WLAN TL:Cannot flatten BT-AMP packet - dropping"));
      /* Drop packet */
      vos_pkt_return_packet(vosTempBuff);
      return VOS_TRUE;
    }

    /* Send packet to BAP client*/
    if ( VOS_STATUS_SUCCESS != WDA_DS_TrimRxPacketInfo( vosTempBuff ) )
    {
      TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
        "WLAN TL:BD header corrupted - dropping packet"));
      /* Drop packet */
      vos_pkt_return_packet(vosTempBuff);
      return VOS_TRUE;
    }

    if ( 0 == WDA_GET_RX_FT_DONE(pvBDHeader) )
    {
      TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
          "Non-data packet received over BT-AMP link: Sending it for "
          "frame Translation"));

      if (usMPDUDOffset > ucMPDUHOffset)
      {
        usActualHLen = usMPDUDOffset - ucMPDUHOffset;
      }

      /* software frame translation for BTAMP WDS.*/
      WLANTL_Translate80211To8023Header( vosTempBuff, &vosStatus, usActualHLen,
                                         ucMPDUHLen, pTLCb,ucSTAId, VOS_FALSE);
      
    }
    if (pTLCb->tlBAPClient.pfnTlBAPRx)
        pTLCb->tlBAPClient.pfnTlBAPRx( vos_get_global_context(VOS_MODULE_ID_TL,pTLCb),
                                       vosTempBuff,
                                       (WLANTL_BAPFrameEnumType)usType );
    else
    {
        VOS_ASSERT(0);
    }

    return VOS_TRUE;
  }
  else
  {
    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
      "WLAN TL: BAP DATA packet received over BT-AMP link: %d, => BAP",
               usType));
   /*!!!FIX ME!!*/
 #if 0
    /*--------------------------------------------------------------------
     For data packet collect phy stats RSSI and Link Quality
     Calculate the RSSI average and save it. Continuous average is done.
    --------------------------------------------------------------------*/
    if ( *pFirstDataPktArrived == 0)
    {
      pTLCb->atlSTAClients[ucSTAId].rssiAvg =
         WLANHAL_GET_RSSI_AVERAGE( pvBDHeader );
      pTLCb->atlSTAClients[ucSTAId].uLinkQualityAvg = 
        WLANHAL_RX_BD_GET_SNR( pvBDHeader );

      // Rcvd 1st pkt, start average from next time
      *pFirstDataPktArrived = 1;
    }
    else
    {
      pTLCb->atlSTAClients[ucSTAId].rssiAvg =
          (WLANHAL_GET_RSSI_AVERAGE( pvBDHeader ) + 
           pTLCb->atlSTAClients[ucSTAId].rssiAvg)/2;
      pTLCb->atlSTAClients[ucSTAId].uLinkQualityAvg =
          (WLANHAL_RX_BD_GET_SNR( pvBDHeader ) +  
           pTLCb->atlSTAClients[ucSTAId].uLinkQualityAvg)/2;
    }/*Else, first data packet*/
 #endif
  }/*BT-AMP data packet*/

  return VOS_FALSE; 
}/*WLANTL_ProcessBAPFrame*/


/*==========================================================================

  FUNCTION    WLANTL_ProcessFCFrame

  DESCRIPTION
    Internal utility function for processing incoming Flow Control frames. Enable
    or disable LWM mode based on the information.

  DEPENDENCIES
    TL must be initiailized before this function gets called.
    FW sends up special flow control frame.

  PARAMETERS

    IN
    pvosGCtx                pointer to vos global context
    pvBDHeader:             pointer to the BD header
    pTLCb:                  TL control block
    pvBDHeader              pointer to BD header.

    IN/OUT
    pFirstDataPktArrived:   static from caller function; used for rssi 
                            computation
  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:   Input frame are invalid
    VOS_STATUS_E_FAULT:   pointer to TL cb is NULL ; access would cause a
                          page fault
    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS
    The ingress and egress of each station will be updated. If needed, LWM mode will
    be enabled or disabled based on the flow control algorithm.

============================================================================*/
v_BOOL_t
WLANTL_ProcessFCFrame
(
  v_PVOID_t         pvosGCtx,
  vos_pkt_t*        pvosDataBuff,
  v_PVOID_t         pvBDHeader
)
{
#if 1 //enable processing of only fcStaTxDisabled bitmap for now. the else part is old better qos code.
      // need to revisit the old code for full implementation.
  v_U8_t            ucSTAId;
  v_U16_t           ucStaValidBitmap;
  v_U16_t           ucStaTxDisabledBitmap;
  WLANTL_CbType*    pTLCb = NULL;
  #ifdef TL_DEBUG_FC
  v_U32_t           rxTimeStamp;
  v_U32_t           curTick;
  #endif
  /*------------------------------------------------------------------------
   Extract TL control block
  ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_SuspendDataTx"));
    return VOS_STATUS_E_FAULT;
  }
  ucStaValidBitmap = WDA_GET_RX_FC_VALID_STA_MASK(pvBDHeader);
  ucStaTxDisabledBitmap = WDA_GET_RX_FC_STA_TX_DISABLED_BITMAP(pvBDHeader);
#ifdef TL_DEBUG_FC
  rxTimeStamp = WDA_GET_RX_TIMESTAMP(pvBDHeader);
  /* hard code of MTU_GLOBAL_TIMER_ADDR to calculate the time between generated and processed */
  wpalReadRegister(0x03081400+0x1D4, &curTick);

  TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
    "%ld (%ld-%ld): Disabled %x Valid %x", curTick > rxTimeStamp ? curTick - rxTimeStamp : rxTimeStamp - (0xFFFFFFFF - curTick),
    curTick, rxTimeStamp,  ucStaTxDisabledBitmap, ucStaValidBitmap));
#endif
  for(ucSTAId = 0; ucStaValidBitmap != 0; ucStaValidBitmap >>=1, ucStaTxDisabledBitmap >>= 1, ucSTAId ++)
  {
    if ( (0 == (ucStaValidBitmap & 0x1)) || (pTLCb->atlSTAClients[ucSTAId] && (0 == pTLCb->atlSTAClients[ucSTAId]->ucExists)) )
        continue;

    if (ucStaTxDisabledBitmap & 0x1)
    {
      WLANTL_SuspendDataTx(pvosGCtx, &ucSTAId, NULL);
    }
    else
    {
      WLANTL_ResumeDataTx(pvosGCtx, &ucSTAId);
    }
  }

#else
  VOS_STATUS          vosStatus;
  tpHalFcRxBd         pvFcRxBd = NULL;
  v_U8_t              ucBitCheck = 0x1;
  v_U8_t              ucStaValid = 0;
  v_U8_t              ucSTAId = 0;

      VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
                 "Received FC Response");
  if ( (NULL == pTLCb) || (NULL == pvosDataBuff))
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
        "WLAN TL:Invalid pointer in %s", __func__));
    return VOS_STATUS_E_FAULT;
  }
  vosStatus = vos_pkt_peek_data( pvosDataBuff, 0, (v_PVOID_t)&pvFcRxBd,
                                   sizeof(tHalFcRxBd));

  if ( (VOS_STATUS_SUCCESS != vosStatus) || (NULL == pvFcRxBd) )
  {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                 "WLAN TL:wrong FC Rx packet"));
      return VOS_STATUS_E_INVAL;
  }
  
  // need to swap bytes in the FC contents.  
  WLANHAL_SwapFcRxBd(&pvFcRxBd->fcSTATxQLen[0]);

  //logic to enable/disable LWM mode for each station
  for( ucStaValid = (v_U8_t)pvFcRxBd->fcSTAValidMask; ucStaValid; ucStaValid >>= 1, ucBitCheck <<= 1, ucSTAId ++)
  {
    if ( (0 == (ucStaValid & 0x1)) || (0 == pTLCb->atlSTAClients[ucSTAId].ucExists) )
    {
      continue;
    }

    if ( pvFcRxBd->fcSTAThreshIndMask & ucBitCheck )
    {
      //LWM event is reported by FW. Able to fetch more packet
      if( pTLCb->atlSTAClients[ucSTAId].ucLwmModeEnabled )
      {
        //Now memory usage is below LWM. Station can send more packets.
        pTLCb->atlSTAClients[ucSTAId].ucLwmEventReported = TRUE;
      }
      else
      {
        TLLOG4(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,
                 "WLAN TL: FW report LWM event but the station %d is not in LWM mode", ucSTAId));
      }
    }

    //calculate uEgress_length/uIngress_length only after receiving enough packets
    if (WLANTL_LWM_INGRESS_SAMPLE_THRESHOLD <= pTLCb->atlSTAClients[ucSTAId].uIngress_length)
    {
      //check memory usage info to see whether LWM mode should be enabled for the station
      v_U32_t uEgress_length = pTLCb->atlSTAClients[ucSTAId].uIngress_length + 
        pTLCb->atlSTAClients[ucSTAId].bmuMemConsumed - pvFcRxBd->fcSTATxQLen[ucSTAId];

      //if ((float)uEgress_length/(float)pTLCb->atlSTAClients[ucSTAId].uIngress_length 
      //      <= WLANTL_LWM_EGRESS_INGRESS_THRESHOLD)
      if ( (pTLCb->atlSTAClients[ucSTAId].uIngress_length > uEgress_length) &&
           ((pTLCb->atlSTAClients[ucSTAId].uIngress_length - uEgress_length ) >= 
            (pTLCb->atlSTAClients[ucSTAId].uIngress_length >> 2))
         )
      {   
         TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                    "WLAN TL:Enable LWM mode for station %d", ucSTAId));
         pTLCb->atlSTAClients[ucSTAId].ucLwmModeEnabled = TRUE;
      }
      else
      {
        if( pTLCb->atlSTAClients[ucSTAId].ucLwmModeEnabled )
        {
          TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                    "WLAN TL:Disable LWM mode for station %d", ucSTAId));
          pTLCb->atlSTAClients[ucSTAId].ucLwmModeEnabled = FALSE;
        }

      }

      //remember memory usage in FW starting from this round
      pTLCb->atlSTAClients[ucSTAId].bmuMemConsumed = pvFcRxBd->fcSTATxQLen[ucSTAId];
      pTLCb->atlSTAClients[ucSTAId].uIngress_length = 0;
    } //(WLANTL_LWM_INGRESS_SAMPLE_THRESHOLD <= pTLCb->atlSTAClients[ucSTAId].uIngress_length)

    if( pTLCb->atlSTAClients[ucSTAId].ucLwmModeEnabled )
    {
      //always update current maximum allowed memeory usage
      pTLCb->atlSTAClients[ucSTAId].uBuffThresholdMax =  WLANTL_STA_BMU_THRESHOLD_MAX -
        pvFcRxBd->fcSTATxQLen[ucSTAId];
    }

  }
#endif

  return VOS_STATUS_SUCCESS;
}

/**
 * WLANTL_FlowControl() - TX Flow control
 * @pTLCb: TL context pointer
 * @pvosDataBuff: Firmware indication data buffer
 *
 * This function implenets the algorithm to flow control TX traffic in  case
 * of SAP and SAP + STA concurrency.
 *
 * Algorithm goal is to fetch more packets from good peer than bad peer by
 * introducing weights for each station connected. Weight of each station is
 * calcutated by taking ratio of max RA rate of the peers to its rate. If the
 * ratio is less than two based on number of queued frames in the station BTQM
 * weight is modified. If the queued frames reaches the defined threshold weight
 * is assigned as four. Here weight is inversely proportional to the number of
 * packets fetch.
 *
 * Return true if flow controlled or false otherwise.
 */
static bool WLANTL_FlowControl(WLANTL_CbType* pTLCb, vos_pkt_t* pvosDataBuff)
{
   WLANTL_FlowControlInfo *fc_data = NULL;
   WLANTL_PerStaFlowControlParam *sta_fc_params = NULL;
   uint8_t num_stas;
   struct sk_buff *skb = NULL;
   uint16_t data_len;
   uint8_t *staid;
   uint16_t max_rate = 0;
   uint8_t i;

   vos_pkt_get_packet_length(pvosDataBuff, &data_len);
   if (!data_len) {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "%s: Null fw indication data", __func__));
      return false;
   }

   vos_pkt_get_os_packet(pvosDataBuff, (v_VOID_t **)&skb, 0);
   fc_data = (WLANTL_FlowControlInfo *)skb->data;
   num_stas = fc_data->num_stas;
   if (!num_stas) {
      TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
          "%s: No connected stations", __func__));
      return true;
   }

   /* Skip flow control for one connected station */
   if (1 == num_stas)
      return true;

   staid = (uint8_t *)vos_mem_malloc(WLAN_MAX_STA_COUNT);
   if (!staid) {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "%s: mem allocation failure", __func__));
      return false;
   }
   vos_mem_set((uint8_t *)staid, WLAN_MAX_STA_COUNT, 0);

   sta_fc_params = (WLANTL_PerStaFlowControlParam *)(&fc_data->num_stas + 1);

   for(i = 0; i < num_stas; i ++, sta_fc_params ++) {
      staid[i] = sta_fc_params->sta_id;

      if (!pTLCb->atlSTAClients[staid[i]])
         continue;

      pTLCb->atlSTAClients[staid[i]]->per = sta_fc_params->avg_per;
      pTLCb->atlSTAClients[staid[i]]->queue = sta_fc_params->queue_len;
      pTLCb->atlSTAClients[staid[i]]->trate = sta_fc_params->rate;
      max_rate = max_rate > pTLCb->atlSTAClients[staid[i]]->trate ?
                            max_rate : pTLCb->atlSTAClients[staid[i]]->trate;

      TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
          "%s: sta_id:%d in:%d queue:%d avg_per:%d rate:%d", __func__,
          staid[i], pTLCb->atlSTAClients[staid[i]]->tx_samples_sum,
          pTLCb->atlSTAClients[staid[i]]->queue,
          pTLCb->atlSTAClients[staid[i]]->per,
          pTLCb->atlSTAClients[staid[i]]->trate));
   }

   for (i = 0; i < num_stas; i++) {
      pTLCb->atlSTAClients[staid[i]]->weight =
                             max_rate/pTLCb->atlSTAClients[staid[i]]->trate;
      if (pTLCb->atlSTAClients[staid[i]]->weight >=
          WLANTL_RATE_RATIO_THRESHOLD) {
         if (!pTLCb->atlSTAClients[staid[i]]->set_flag) {
            vos_set_hdd_bad_sta(staid[i]);
            pTLCb->atlSTAClients[staid[i]]->set_flag = true;
         }
         /**
          * If station's link becomes very bad rssi below -90dbm then because
          * of high PER rate high number of packets are stuck in BTQM which is
          * affecting the good peers throughput. So throttle further the bad
          * link traffic.
          */
         if ((pTLCb->atlSTAClients[staid[i]]->weight >
              WLANTL_WEIGHT_THRESHOLD) &&
             (pTLCb->atlSTAClients[staid[i]]->queue >
              WLANTL_QUEUE_THRESHOLD))
            pTLCb->atlSTAClients[staid[i]]->weight *= 2;
      }
      if (pTLCb->atlSTAClients[staid[i]]->weight <
          WLANTL_RATE_RATIO_THRESHOLD) {
         if (pTLCb->atlSTAClients[staid[i]]->per >= WLANTL_PER_THRESHOLD &&
             pTLCb->atlSTAClients[staid[i]]->queue > WLANTL_QUEUE_THRESHOLD
             && !pTLCb->atlSTAClients[staid[i]]->set_flag) {
            pTLCb->atlSTAClients[staid[i]]->weight *= 2;
            vos_set_hdd_bad_sta(staid[i]);
            pTLCb->atlSTAClients[staid[i]]->set_flag = true;
         }
         else if (pTLCb->atlSTAClients[staid[i]]->set_flag) {
            vos_reset_hdd_bad_sta(staid[i]);
            pTLCb->atlSTAClients[staid[i]]->set_flag = false;
         }
      }
   }
   vos_mem_free(staid);
   return true;
}

/**
 * WLANTL_CacheEapol() - cache eapol frames
 * @pTLCb : pointer to TL context
 * @vosTempBuff: pointer to vos packet buff
 *
 * Return: None
 *
 */
static void WLANTL_CacheEapol(WLANTL_CbType* pTLCb, vos_pkt_t* vosTempBuff)
{
   if ((NULL == pTLCb) || (NULL == vosTempBuff))
   {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "%s: Invalid input pointer", __func__));
      return;
   }

   if (NULL == pTLCb->vosEapolCachedFrame) {
      TLLOG1(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
               "%s: Cache Eapol frame", __func__));
      pTLCb->vosEapolCachedFrame = vosTempBuff;
   }
   else {
      TLLOG1(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
               "%s: Drop duplicate EAPOL frame", __func__));
      vos_pkt_return_packet(vosTempBuff);
   }
}

/**
 * WLANTL_SampleRxRSSI() - Collect RX rssi samples
 * @pTLCb: TL context pointer
 * @pBDHeader: RX Meta data pointer
 * @sta_id: Station ID
 *
 * This function records the last twenty RX RSSI samples
 *
 * Return: void
 */
static void WLANTL_SampleRxRSSI(WLANTL_CbType* pTLCb, void * pBDHeader,
                                uint8_t sta_id)
{
   uint8_t count;
   uint8_t old_idx;
   s8 curr_RSSI, curr_RSSI0, curr_RSSI1;
   WLANTL_STAClientType *pClientSTA = pTLCb->atlSTAClients[sta_id];

   if(pClientSTA == NULL) {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
      " %s: pClientSTA is NULL", __func__));
      return;
   }
   count = pClientSTA->rssi_sample_cnt;
   old_idx = pClientSTA->rssi_stale_idx;

   curr_RSSI0 = WLANTL_GETRSSI0(pBDHeader);
   curr_RSSI1 = WLANTL_GETRSSI1(pBDHeader);

   curr_RSSI  = (curr_RSSI0 > curr_RSSI1) ? curr_RSSI0 : curr_RSSI1;

   if (count >= WLANTL_RSSI_SAMPLE_CNT) {
      pClientSTA->rssi_sample_sum -= pClientSTA->rssi_sample[old_idx];
      pClientSTA->rssi_sample[old_idx] = curr_RSSI;
      pClientSTA->rssi_sample_sum += pClientSTA->rssi_sample[old_idx];
      old_idx >= (WLANTL_RSSI_SAMPLE_CNT - 1) ? old_idx = 0 : old_idx++;
      pClientSTA->rssi_stale_idx = old_idx;
   } else {
      pClientSTA->rssi_sample[count] = curr_RSSI;
      pClientSTA->rssi_sample_sum += pClientSTA->rssi_sample[count];
      pClientSTA->rssi_sample_cnt++;
   }
}

/**
 * WLANTL_StaMonRX - Send packets to monitor mode
 * @pTLCb: TL context pointer
 * @pFrame: Rx buffer pointer
 * @pBDHeader: RX Meta data pointer
 * @sta_id: Station ID
 *
 * Return: true if RX monitor mode or false otherwise
 */
static bool WLANTL_StaMonRX(WLANTL_CbType* pTLCb, vos_pkt_t *pFrame,
                            WDI_DS_RxMetaInfoType *pRxMetadata,
                            uint8_t sta_id)
{
   WLANTL_STAClientType *pClientSTA = NULL;
   tpSirMacMgmtHdr pHdr = NULL;
   v_MACADDR_t *peerMacAddr = NULL;
   uint8_t i = 0;
   uint8_t addr1_index = WDA_GET_RX_ADDR1_IDX(pRxMetadata);
   bool tp_data = false;

   pHdr = (tpSirMacMgmtHdr)pRxMetadata->mpduHeaderPtr;
   peerMacAddr = (v_MACADDR_t *)pHdr->da;

   if (vos_check_monitor_state() == false)
       return false;

   if ((addr1_index == 254) &&
       WLANTL_IS_DATA_FRAME(WDA_GET_RX_TYPE_SUBTYPE(pRxMetadata)) &&
       !pRxMetadata->bcast) {
       tp_data = true;
   } else if (WLANTL_STA_ID_MONIFACE(sta_id) == 0) {
       return false;
   }

   if (WLANTL_IS_MGMT_FRAME(WDA_GET_RX_TYPE_SUBTYPE(pRxMetadata)) || tp_data) {

      if (pRxMetadata->bcast)
         return false;

      for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
         if (NULL == pTLCb->atlSTAClients[i])
            continue;
         if (0 == pTLCb->atlSTAClients[i]->ucExists)
            continue;
         if (WLANTL_STA_AUTHENTICATED == pTLCb->atlSTAClients[i]->tlState)
            break;
      }

      if (i == WLAN_MAX_STA_COUNT) {
          if (tp_data)
              return true;

         return false;
      }

      pClientSTA = pTLCb->atlSTAClients[i];

      if (vos_is_macaddr_equal(peerMacAddr,
          &pClientSTA->wSTADesc.vSelfMACAddress))
         return false;

      if (vos_is_macaddr_equal(peerMacAddr, &pTLCb->spoofMacAddr.spoofMac) &&
          !tp_data)
          return false;
   }

   return true;
}

/*==========================================================================

  FUNCTION    WLANTL_RxFrames

  DESCRIPTION
    Callback registered by TL and called by BAL when a packet is received
    over the bus. Upon the call of this function TL will make the necessary
    decision with regards to the forwarding or queuing of this packet and
    the layer it needs to be delivered to.

  DEPENDENCIES
    TL must be initiailized before this function gets called.
    If the frame carried is a data frame then the station for which it is
    destined to must have been previously registered with TL.

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    or BAL's control block can be extracted from its context

    vosDataBuff:   it will contain a pointer to the first buffer received,
                    if there is more then one packet they will be chained
                    using vOSS buffers.

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:   Input parameters are invalid
    VOS_STATUS_E_FAULT:   pointer to TL cb is NULL ; access would cause a
                          page fault
    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_RxFrames
(
  v_PVOID_t      pvosGCtx,
  vos_pkt_t     *pFrameDataBuff
)
{
  vos_pkt_t*          vosDataBuff = (vos_pkt_t*)pFrameDataBuff;
  WLANTL_CbType*      pTLCb = NULL;
  WLANTL_STAClientType* pClientSTA = NULL;
  WLANTL_STAFuncType  pfnSTAFsm;
  vos_pkt_t*          vosTempBuff;
  v_U8_t              ucSTAId;
  VOS_STATUS          vosStatus;
  v_U8_t              ucFrmType;
  v_PVOID_t           pvBDHeader = NULL;
  WLANTL_STAEventType wSTAEvent  = WLANTL_RX_EVENT;
  v_U8_t              ucTid      = 0;
  v_BOOL_t            broadcast  = VOS_FALSE;
  v_BOOL_t            selfBcastLoopback = VOS_FALSE;
  static v_U8_t       first_data_pkt_arrived;
  v_U32_t             uDPUSig; 
  v_U16_t             usPktLen;
  v_BOOL_t            bForwardIAPPwithLLC = VOS_FALSE;
#ifdef WLAN_FEATURE_LINK_LAYER_STATS
  v_S7_t              currentAvgRSSI = 0;
  v_U8_t              ac;
#endif
  uint8_t            ucMPDUHLen;
  uint16_t           seq_no;
  u64                pn_num;
  uint16_t           usEtherType = 0;
  bool               sta_mon_data = false;

  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL:TL Receive Frames called"));

  /*------------------------------------------------------------------------
    Sanity check
    ------------------------------------------------------------------------*/
  if ( NULL == vosDataBuff )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid parameter sent on WLANTL_RxFrames"));
    return VOS_STATUS_E_INVAL;
  }

 /*------------------------------------------------------------------------
   Popolaute timestamp as the time when packet arrives
   ---------------------------------------------------------------------- */
   vosDataBuff->timestamp = vos_timer_get_system_ticks();

  /*------------------------------------------------------------------------
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
        "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_ChangeSTAState"));
    return VOS_STATUS_E_FAULT;
  }

  /*---------------------------------------------------------------------
    Save the initial buffer - this is the first received buffer
   ---------------------------------------------------------------------*/
  vosTempBuff = vosDataBuff;

  while (NULL != vosDataBuff)
  {
    broadcast = VOS_FALSE;
    selfBcastLoopback = VOS_FALSE; 

    vos_pkt_walk_packet_chain( vosDataBuff, &vosDataBuff, 1/*true*/ );

    /*---------------------------------------------------------------------
      Peek at BD header - do not remove
      !!! Optimize me: only part of header is needed; not entire one
     ---------------------------------------------------------------------*/
    vosStatus = WDA_DS_PeekRxPacketInfo( vosTempBuff, (v_PVOID_t)&pvBDHeader, 1/*Swap BD*/ );

    if ( NULL == pvBDHeader )
    {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                 "WLAN TL:Cannot extract BD header"));
      /* Drop packet */
      vos_pkt_return_packet(vosTempBuff);
      vosTempBuff = vosDataBuff;
      continue;
    }

    /*---------------------------------------------------------------------
         Check if frame is for monitor interface
       ---------------------------------------------------------------------*/
    ucSTAId = (v_U8_t)WDA_GET_RX_STAID(pvBDHeader);

    sta_mon_data = WLANTL_StaMonRX(pTLCb, vosTempBuff, pvBDHeader, ucSTAId);

    if (vos_get_conparam() == VOS_MONITOR_MODE || sta_mon_data)
    {
        sta_mon_data = false;

        if( pTLCb->isConversionReq )
            WLANTL_MonTranslate80211To8023Header(vosTempBuff, pTLCb);

        pTLCb->pfnMonRx(pvosGCtx, vosTempBuff, pTLCb->isConversionReq);
        vosTempBuff = vosDataBuff;
        continue;
    }

    /*---------------------------------------------------------------------
      Check if FC frame reported from FW
    ---------------------------------------------------------------------*/
    if(WDA_IS_RX_FC(pvBDHeader))
    {
      TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                 "WLAN TL:receive one FC frame"));

      WLANTL_FlowControl(pTLCb, vosTempBuff);

      /* Drop packet */
      vos_pkt_return_packet(vosTempBuff);
      vosTempBuff = vosDataBuff;
      continue;
    }

    /* AMSDU HW bug fix
     * After 2nd AMSDU subframe HW could not handle BD correctly
     * HAL workaround is needed */
    if(WDA_GET_RX_ASF(pvBDHeader))
    {
      WDA_DS_RxAmsduBdFix(pvosGCtx, pvBDHeader);
    }

    /*---------------------------------------------------------------------
      Extract frame control field from 802.11 header if present 
      (frame translation not done) 
    ---------------------------------------------------------------------*/

    vosStatus = WDA_DS_GetFrameTypeSubType( pvosGCtx, vosTempBuff,
                         pvBDHeader, &ucFrmType );
    if ( VOS_STATUS_SUCCESS != vosStatus )
    {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                   "WLAN TL:Cannot extract Frame Control Field"));
      /* Drop packet */
      vos_pkt_return_packet(vosTempBuff);
      vosTempBuff = vosDataBuff;
      continue;
    }

    vos_pkt_get_packet_length(vosTempBuff, &usPktLen);

    /*---------------------------------------------------------------------
      Check if management and send to PE
    ---------------------------------------------------------------------*/

    if ( WLANTL_IS_MGMT_FRAME(ucFrmType))
    {
      TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                 "WLAN TL:Sending packet to management client"));
      if ( VOS_STATUS_SUCCESS != vos_pkt_flatten_rx_pkt(&vosTempBuff))
      {
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                   "WLAN TL:Cannot flatten packet - dropping"));
        /* Drop packet */
        vos_pkt_return_packet(vosTempBuff);
        vosTempBuff = vosDataBuff;
        continue;
      }
      ucSTAId = (v_U8_t)WDA_GET_RX_STAID( pvBDHeader );
      /* Read RSSI and update */
      if(!WLANTL_STA_ID_INVALID(ucSTAId))
      {
#if defined WLAN_FEATURE_NEIGHBOR_ROAMING
        /* Read RSSI and update */
        vosStatus = WLANTL_HSHandleRXFrame(pvosGCtx,
                                           WLANTL_MGMT_FRAME_TYPE,
                                           pvBDHeader,
                                           ucSTAId,
                                           VOS_FALSE,
                                           NULL);
#else
        vosStatus = WLANTL_ReadRSSI(pvosGCtx, pvBDHeader, ucSTAId);
#endif
        if (!VOS_IS_STATUS_SUCCESS(vosStatus))
        {
          TLLOGW(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
                           "Handle RX Management Frame fail within Handoff "
                           "support module"));
          /* Do Not Drop packet at here
           * Revisit why HO module return fail
           *   vos_pkt_return_packet(vosTempBuff);
           *   vosTempBuff = vosDataBuff;
           *   continue;
           */
        }
        vosStatus = WLANTL_ReadSNR(pvosGCtx, pvBDHeader, ucSTAId);

        if (!VOS_IS_STATUS_SUCCESS(vosStatus))
        {
          TLLOGW(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
                            FL("Failed to Read SNR")));
        }
#ifdef WLAN_FEATURE_LINK_LAYER_STATS
        pClientSTA = pTLCb->atlSTAClients[ucSTAId];
        if ( NULL != pClientSTA)
        {
            pClientSTA->interfaceStats.mgmtRx++;
        }
#endif

        WLANTL_SampleRxRSSI(pTLCb, pvBDHeader, ucSTAId);

      }

      pTLCb->tlMgmtFrmClient.pfnTlMgmtFrmRx( pvosGCtx, vosTempBuff); 
    }
    else /* Data Frame */
    {
      ucSTAId = (v_U8_t)WDA_GET_RX_STAID( pvBDHeader );
      ucTid   = (v_U8_t)WDA_GET_RX_TID( pvBDHeader );
      uDPUSig = WDA_GET_RX_DPUSIG(pvBDHeader);
      ucMPDUHLen = (uint8_t)WDA_GET_RX_MPDU_HEADER_LEN(pvBDHeader);
      seq_no = (uint16_t)WDA_GET_RX_REORDER_CUR_PKT_SEQ_NO(pvBDHeader);
      pn_num = WDA_GET_RX_REPLAY_COUNT(pvBDHeader);

      vosTempBuff->pn_replay_skip = 0;
      vosTempBuff->pn_num = pn_num;

      TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                 "WLAN TL:Data packet received for STA %d", ucSTAId));

      /*------------------------------------------------------------------
        This should be corrected when multipe sta support is added !!!
        for now bcast frames will be sent to the last registered STA
       ------------------------------------------------------------------*/
      if ( WDA_IS_RX_BCAST(pvBDHeader))
      {
        TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
        "WLAN TL:TL rx Bcast frame - sending to last registered station"));
        broadcast = VOS_TRUE;
        /*-------------------------------------------------------------------
          If Addr1 is b/mcast, but Addr3 is our own self MAC, it is a b/mcast
          pkt we sent  looping back to us. To be dropped if we are non BTAMP  
         -------------------------------------------------------------------*/ 
        if( WLANHAL_RX_BD_ADDR3_SELF_IDX == 
            (v_U8_t)WDA_GET_RX_ADDR3_IDX( pvBDHeader )) 
        {
          selfBcastLoopback = VOS_TRUE; 
        }
      }/*if bcast*/

      /* Pre assoc cache eapol */
      if (pTLCb->preassoc_caching)
      {
         WLANTL_GetEtherType(pvBDHeader,vosTempBuff, ucMPDUHLen, &usEtherType);
         if (WLANTL_LLC_8021X_TYPE != usEtherType)
         {
            VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
                      "%s: RX Frame not EAPOL EtherType %d",
                      __func__, usEtherType);
            vos_pkt_return_packet(vosTempBuff);
         }
         else
         {
            WLANTL_CacheEapol(pTLCb, vosTempBuff);
            TLLOG1(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
                "WLAN TL:TL preassoc_caching is enabled seq No: %d", seq_no));
         }

         vosTempBuff = vosDataBuff;
         continue;
      }

      if (WLANTL_STA_ID_INVALID(ucSTAId))
      {
        TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
                   "WLAN TL:STAId %d. Invalid STA ID dropping pkt",
                   ucSTAId));
        /* Drop packet */
        vos_pkt_return_packet(vosTempBuff);
        vosTempBuff = vosDataBuff;
        continue;
      }

      if (WLANTL_TID_INVALID( ucTid)) {
         /* There is a possibility AP uses wrong TID. In that case to avoid
            dropping EAPOL packet in the driver use TID to zero.*/
         VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
             "WLAN TL:Invalid Tid: %d Frame type: %d", ucTid, ucFrmType);
         WDA_GET_RX_TID( pvBDHeader ) = 0;
         ucTid = 0;
      }

#ifdef WLAN_FEATURE_LINK_LAYER_STATS
      ac = WLANTL_TID_2_AC[ucTid];
#endif

      /*----------------------------------------------------------------------
        No need to lock cache access because cache manipulation only happens
        in the transport thread/task context
        - These frames are to be forwarded to the station upon registration
          which happens in the main thread context
          The caching here can happen in either Tx or Rx thread depending
          on the current SSC scheduling
        - also we need to make sure that the frames in the cache are fwd-ed to
          the station before the new incoming ones 
      -----------------------------------------------------------------------*/
      pClientSTA = pTLCb->atlSTAClients[ucSTAId];
      if (NULL == pClientSTA)
      {
          TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
                   "WLAN TL:STA not allocated memory. Dropping packet"));
          vos_pkt_return_packet(vosTempBuff);
          vosTempBuff = vosDataBuff;
          continue;
      }

#ifdef FEATURE_WLAN_TDLS
      if (( pClientSTA->ucExists ) &&
           (WLAN_STA_TDLS == pClientSTA->wSTADesc.wSTAType) &&
           (pClientSTA->ucTxSuspended))
          vos_atomic_set_U8( &pClientSTA->ucTxSuspended, 0 );
      else if ( !broadcast && (pClientSTA->ucExists == 0 ) )
      {
          tpSirMacMgmtHdr pMacHeader = WDA_GET_RX_MAC_HEADER( pvBDHeader );

          /* from the direct peer while it is not registered to TL yet */
          if ( (pMacHeader->fc.fromDS == 0) &&
               (pMacHeader->fc.toDS == 0) )
          {
              v_U8_t ucAddr3STAId;

              ucAddr3STAId = WDA_GET_RX_ADDR3_IDX(pvBDHeader);

              if ( WLANTL_STA_ID_INVALID(ucAddr3STAId) )
              {
                TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
                           "WLAN TL:STA ID %d invalid - dropping pkt", ucAddr3STAId));
                /* Drop packet */
                vos_pkt_return_packet(vosTempBuff);
                vosTempBuff = vosDataBuff;
                continue;
              }

              if (!(pTLCb->atlSTAClients[ucAddr3STAId] && pTLCb->atlSTAClients[ucAddr3STAId]->ucExists &&
                  (WLAN_STA_INFRA == pTLCb->atlSTAClients[ucAddr3STAId]->wSTADesc.wSTAType) &&
                  (WLANTL_STA_AUTHENTICATED == pTLCb->atlSTAClients[ucAddr3STAId]->tlState)))
              {
                  TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
                           "%s: staId %d addr3Id %d tlState %d. Unkown Receiver/Transmitter Dropping packet", __func__,
                           ucSTAId, ucAddr3STAId, pTLCb->atlSTAClients[ucAddr3STAId]->tlState));
                  vos_pkt_return_packet(vosTempBuff);
                  vosTempBuff = vosDataBuff;
                  continue;
              }
              else
              {
                  VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_DEBUG,
                            "staId %d doesn't exist"
                            " but mapped to AP staId %d PN:[0x%llX]",
                            ucSTAId, ucAddr3STAId, pn_num);
                  ucSTAId = ucAddr3STAId;
                  pClientSTA = pTLCb->atlSTAClients[ucAddr3STAId];
                  vosTempBuff->pn_replay_skip = 1;
              }
          }
      }
#endif

      if (( pClientSTA->enableCaching == 1 ) &&
            /*Dont buffer Broadcast/Multicast frames. If AP transmits bursts of Broadcast/Multicast data frames, 
             * libra buffers all Broadcast/Multicast packets after authentication with AP, 
             * So it will lead to low resource condition in Rx Data Path.*/
          ( WDA_IS_RX_BCAST(pvBDHeader) == 0 ))
      {
        if( WDA_IsSelfSTA(pvosGCtx,ucSTAId))
        {
           //drop packet for Self STA index
           TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
                  "%s: Packet dropped for Self STA with staId %d ", __func__, ucSTAId ));

           vos_pkt_return_packet(vosTempBuff);
           vosTempBuff = vosDataBuff;
           continue;
        }
        /* Station has not yet been registered with TL - cache the frame */
        TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
                 "%s: staId %d exist %d tlState %d cache rx frame", __func__, ucSTAId,
                 pClientSTA->ucExists, pClientSTA->tlState));
        WLANTL_CacheSTAFrame( pTLCb, ucSTAId, vosTempBuff, uDPUSig, broadcast, ucFrmType);
        vosTempBuff = vosDataBuff;
        continue;
      }

#ifdef FEATURE_WLAN_ESE_UPLOAD
      if ((pClientSTA->wSTADesc.ucIsEseSta)|| broadcast)
      {
        /*--------------------------------------------------------------------
          Filter the IAPP frames for ESE connection;
          if data it will return false and it
          will be routed through the regular data path
        --------------------------------------------------------------------*/
        if ( WLANTL_IsIAPPFrame(pvBDHeader,
                                vosTempBuff))
        {
            bForwardIAPPwithLLC = VOS_TRUE;
        }
      }
#endif

#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD)
      if ((pClientSTA->wSTADesc.ucIsEseSta)|| broadcast)
      {
        /*--------------------------------------------------------------------
          Filter the IAPP frames for ESE connection;
          if data it will return false and it 
          will be routed through the regular data path
        --------------------------------------------------------------------*/
        if ( WLANTL_IsIAPPFrame(pvBDHeader,
                                vosTempBuff))
        {
            if ( VOS_STATUS_SUCCESS != vos_pkt_flatten_rx_pkt(&vosTempBuff))
            {
               TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                        "WLAN TL:Cannot flatten packet - dropping"));
               /* Drop packet */
               vos_pkt_return_packet(vosTempBuff);
            } else {

               TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
                        "WLAN TL: Received ESE IAPP Frame"));

               pTLCb->tlMgmtFrmClient.pfnTlMgmtFrmRx( pvosGCtx, vosTempBuff); 
            }
            vosTempBuff = vosDataBuff;
            continue;
        }
      }
#endif  /* defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) */

      if ( WLAN_STA_BT_AMP == pClientSTA->wSTADesc.wSTAType )
      {
        /*--------------------------------------------------------------------
          Process the ctrl BAP frame; if data it will return false and it 
          will be routed through the regular data path
        --------------------------------------------------------------------*/
        if ( WLANTL_ProcessBAPFrame( pvBDHeader,
                                     vosTempBuff,
                                     pTLCb,
                                    &first_data_pkt_arrived,
                                     ucSTAId))
        {
          vosTempBuff = vosDataBuff;
          continue;
        }
      }/*if BT-AMP station*/
      else if(selfBcastLoopback == VOS_TRUE)
      { 
        /* Drop packet */ 
        vos_pkt_return_packet(vosTempBuff); 
        vosTempBuff = vosDataBuff; 
        continue; 
      } 
      
      /*---------------------------------------------------------------------
        Data packet received, send to state machine
      ---------------------------------------------------------------------*/
      wSTAEvent = WLANTL_RX_EVENT;

      pfnSTAFsm = tlSTAFsm[pClientSTA->tlState].
                      pfnSTATbl[wSTAEvent];

      if ( NULL != pfnSTAFsm )
      {
#if defined WLAN_FEATURE_NEIGHBOR_ROAMING
        /* Read RSSI and update */
        vosStatus = WLANTL_HSHandleRXFrame(pvosGCtx,
                                           WLANTL_DATA_FRAME_TYPE,
                                           pvBDHeader,
                                           ucSTAId,
                                           broadcast,
                                           vosTempBuff);
        broadcast = VOS_FALSE;
#else
        vosStatus = WLANTL_ReadRSSI(pvosGCtx, pvBDHeader, ucSTAId);
#endif
        if (!VOS_IS_STATUS_SUCCESS(vosStatus))
        {
          TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
            "Handle RX Data Frame fail within Handoff support module"));
          /* Do Not Drop packet at here 
           * Revisit why HO module return fail
           * vos_pkt_return_packet(vosTempBuff);
           * vosTempBuff = vosDataBuff;
           * continue;
           */
        }
#ifdef WLAN_FEATURE_LINK_LAYER_STATS
        pClientSTA = pTLCb->atlSTAClients[ucSTAId];
        if ( NULL != pClientSTA)
        {
            tpSirMacMgmtHdr pMacHeader = WDA_GET_RX_MAC_HEADER( pvBDHeader );
            if (!IS_BROADCAST_ADD(pMacHeader->da) && IS_MULTICAST_ADD(pMacHeader->da))
            {
                pClientSTA->interfaceStats.accessCategoryStats[ac].rxMcast++;
            }

            WLANTL_HSGetDataRSSI(pvosGCtx, pvBDHeader, ucSTAId,
                    &currentAvgRSSI);
            pClientSTA->interfaceStats.rssiData = currentAvgRSSI;

            pClientSTA->interfaceStats.accessCategoryStats[ac].rxMpdu++;
            if (WDA_IS_RX_AN_AMPDU (pvBDHeader))
            {
                pClientSTA->interfaceStats.accessCategoryStats[ac].rxAmpdu++;
            }
        }


#endif
        vosStatus = WLANTL_ReadSNR(pvosGCtx, pvBDHeader, ucSTAId);

        if (!VOS_IS_STATUS_SUCCESS(vosStatus))
        {
          TLLOGW(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
                           FL("Failed to Read SNR")));
        }

        WLANTL_SampleRxRSSI(pTLCb, pvBDHeader, ucSTAId);

        pfnSTAFsm( pvosGCtx, ucSTAId, &vosTempBuff, bForwardIAPPwithLLC);
      }
      else
        {
          TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
            "WLAN TL:NULL state function, STA:%d, State: %d- dropping packet",
                   ucSTAId, pClientSTA->tlState));
          /* Drop packet */
          vos_pkt_return_packet(vosTempBuff);
          vosTempBuff = vosDataBuff;
          continue;
        }
    }/* else data frame*/

    vosTempBuff = vosDataBuff;
  }/*while chain*/

  return VOS_STATUS_SUCCESS;
}/* WLANTL_RxFrames */

#ifdef WLAN_FEATURE_LINK_LAYER_STATS
/*==========================================================================

  FUNCTION    WLANTL_CollectInterfaceStats

  DESCRIPTION
    Utility function used by TL to send the statitics

  DEPENDENCIES


  PARAMETERS

    IN

    ucSTAId:    station for which the statistics need to collected

    vosDataBuff: it will contain the pointer to the corresponding
                structure

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:   Input parameters are invalid
    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_CollectInterfaceStats
(
  v_PVOID_t       pvosGCtx,
  v_U8_t          ucSTAId,
  WLANTL_InterfaceStatsType    *vosDataBuff
)
{
  WLANTL_CbType*  pTLCb = NULL;
  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if ( WLANTL_STA_ID_INVALID( ucSTAId ) )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
           "WLAN TL:Invalid station id requested on WLANTL_CollectStats"));
    return VOS_STATUS_E_FAULT;
  }
  /*------------------------------------------------------------------------
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
       "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_CollectStats"));
    return VOS_STATUS_E_FAULT;
  }

  if ( NULL == pTLCb->atlSTAClients[ucSTAId] )
  {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Client Memory was not allocated on %s", __func__));
      return VOS_STATUS_E_FAILURE;
  }
  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
              "WLAN TL: collect WIFI_STATS_IFACE results"));

  vos_mem_copy(vosDataBuff, &pTLCb->atlSTAClients[ucSTAId]->interfaceStats,
          sizeof(WLANTL_InterfaceStatsType));
  return VOS_STATUS_SUCCESS;
}

/*==========================================================================

  FUNCTION    WLANTL_ClearInterfaceStats

  DESCRIPTION
    Utility function used by TL to clear the statitics

  DEPENDENCIES


  PARAMETERS

    IN

    ucSTAId:    station for which the statistics need to collected

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:   Input parameters are invalid
    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_ClearInterfaceStats
(
  v_PVOID_t       pvosGCtx,
  v_U8_t          ucSTAId,
  v_U8_t          statsClearReqMask
)
{
    WLANTL_CbType*  pTLCb = NULL;
    WLANTL_STAClientType* pClientSTA = NULL;
    /*------------------------------------------------------------------------
      Sanity check
      ------------------------------------------------------------------------*/
    if ( WLANTL_STA_ID_INVALID( ucSTAId ) )
    {
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid station id requested on WLANTL_CollectStats"));
        return VOS_STATUS_E_FAULT;
    }
    /*------------------------------------------------------------------------
      Extract TL control block
      ------------------------------------------------------------------------*/
    pTLCb = VOS_GET_TL_CB(pvosGCtx);
    if ( NULL == pTLCb )
    {
        TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
            "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_CollectStats"));
        return VOS_STATUS_E_FAULT;
    }

    pClientSTA = pTLCb->atlSTAClients[ucSTAId];
    if ( NULL == pClientSTA )
    {
        TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                    "WLAN TL:Client Memory was not allocated on %s", __func__));
        return VOS_STATUS_E_FAILURE;
    }

    if ((statsClearReqMask & WIFI_STATS_IFACE_AC) ||
            (statsClearReqMask & WIFI_STATS_IFACE)) {
        TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                    "WLAN TL:cleared WIFI_STATS_IFACE_AC results"));
        pClientSTA->interfaceStats.accessCategoryStats[0].rxMcast = 0;
        pClientSTA->interfaceStats.accessCategoryStats[1].rxMcast = 0;
        pClientSTA->interfaceStats.accessCategoryStats[2].rxMcast = 0;
        pClientSTA->interfaceStats.accessCategoryStats[3].rxMcast = 0;

        pClientSTA->interfaceStats.accessCategoryStats[0].rxMpdu = 0;
        pClientSTA->interfaceStats.accessCategoryStats[1].rxMpdu = 0;
        pClientSTA->interfaceStats.accessCategoryStats[2].rxMpdu = 0;
        pClientSTA->interfaceStats.accessCategoryStats[3].rxMpdu = 0;

        pClientSTA->interfaceStats.accessCategoryStats[0].rxAmpdu = 0;
        pClientSTA->interfaceStats.accessCategoryStats[1].rxAmpdu = 0;
        pClientSTA->interfaceStats.accessCategoryStats[2].rxAmpdu = 0;
        pClientSTA->interfaceStats.accessCategoryStats[3].rxAmpdu = 0;
    }

    if (statsClearReqMask & WIFI_STATS_IFACE) {
        TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                    "WLAN TL:cleared WIFI_STATS_IFACE results"));
        pClientSTA->interfaceStats.mgmtRx = 0;
        pClientSTA->interfaceStats.rssiData = 0;
        return VOS_STATUS_SUCCESS;
    }

    return VOS_STATUS_SUCCESS;
}

#endif /* WLAN_FEATURE_LINK_LAYER_STATS */

/*==========================================================================

  FUNCTION    WLANTL_RxCachedFrames

  DESCRIPTION
    Utility function used by TL to forward the cached frames to a particular
    station; 

  DEPENDENCIES
    TL must be initiailized before this function gets called.
    If the frame carried is a data frame then the station for which it is
    destined to must have been previously registered with TL.

  PARAMETERS

    IN
    pTLCb:   pointer to TL handle 
   
    ucSTAId:    station for which we need to forward the packets

    vosDataBuff:   it will contain a pointer to the first cached buffer
                   received, if there is more then one packet they will be
                   chained using vOSS buffers.

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:   Input parameters are invalid
    VOS_STATUS_E_FAULT:   pointer to TL cb is NULL ; access would cause a
                          page fault
    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_RxCachedFrames
(
  WLANTL_CbType*  pTLCb,
  v_U8_t          ucSTAId,
  vos_pkt_t*      vosDataBuff
)
{
  WLANTL_STAClientType* pClientSTA = NULL;
  WLANTL_STAFuncType  pfnSTAFsm;
  vos_pkt_t*          vosTempBuff;
  VOS_STATUS          vosStatus;
  v_PVOID_t           pvBDHeader = NULL;
  WLANTL_STAEventType wSTAEvent  = WLANTL_RX_EVENT;
  v_U8_t              ucTid      = 0;
  v_BOOL_t            broadcast  = VOS_FALSE;
  v_BOOL_t            bSigMatch  = VOS_FALSE; 
  v_BOOL_t            selfBcastLoopback = VOS_FALSE;
  static v_U8_t       first_data_pkt_arrived;
  v_U32_t             uDPUSig; 
  v_U8_t              ucUcastSig; 
  v_U8_t              ucBcastSig; 
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL:TL Receive Cached Frames called"));

  /*------------------------------------------------------------------------
    Sanity check
    ------------------------------------------------------------------------*/
  if ( NULL == vosDataBuff )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid parameter sent on WLANTL_RxFrames"));
    return VOS_STATUS_E_INVAL;
  }

  pClientSTA = pTLCb->atlSTAClients[ucSTAId];

  if ( NULL == pClientSTA )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
        "WLAN TL:Client Memory was not allocated on %s", __func__));
    return VOS_STATUS_E_FAILURE;
  }

  MTRACE(vos_trace(VOS_MODULE_ID_TL, TRACE_CODE_TL_FORWARD_CACHED_FRAMES,
                   ucSTAId, 1<<16 | pClientSTA->tlCacheInfo.cacheSize));

  /*---------------------------------------------------------------------
    Save the initial buffer - this is the first received buffer
   ---------------------------------------------------------------------*/
  vosTempBuff = vosDataBuff;

  while ( NULL != vosTempBuff )
  {
    broadcast = VOS_FALSE;
    selfBcastLoopback = VOS_FALSE; 

    vos_pkt_walk_packet_chain( vosDataBuff, &vosDataBuff, 1/*true*/ );

          TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
               "WLAN TL:Sending new cached packet to station %d", ucSTAId));
    /*---------------------------------------------------------------------
      Peek at BD header - do not remove
      !!! Optimize me: only part of header is needed; not entire one
     ---------------------------------------------------------------------*/
    vosStatus = WDA_DS_PeekRxPacketInfo( vosTempBuff, (v_PVOID_t)&pvBDHeader, 0 );

    if ( NULL == pvBDHeader )
          {
            TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                 "WLAN TL:Cannot extract BD header"));
          /* Drop packet */
          vos_pkt_return_packet(vosTempBuff);
          vosTempBuff = vosDataBuff;
          continue;
        }

    uDPUSig = WDA_GET_RX_DPUSIG( pvBDHeader );

    /* AMSDU HW bug fix
     * After 2nd AMSDU subframe HW could not handle BD correctly
     * HAL workaround is needed */
    if(WDA_GET_RX_ASF(pvBDHeader))
    {
      WDA_DS_RxAmsduBdFix(vos_get_global_context(VOS_MODULE_ID_TL,pTLCb), 
                           pvBDHeader);
    }

    ucTid   = (v_U8_t)WDA_GET_RX_TID( pvBDHeader );

    VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
               "WLAN TL:Data packet cached for STA %d", ucSTAId);

    /*------------------------------------------------------------------
      This should be corrected when multipe sta support is added !!!
      for now bcast frames will be sent to the last registered STA
     ------------------------------------------------------------------*/
    if ( WDA_IS_RX_BCAST(pvBDHeader))
    {
          TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                 "WLAN TL:TL rx Bcast frame "));
      broadcast = VOS_TRUE;

      /* If Addr1 is b/mcast, but Addr3 is our own self MAC, it is a b/mcast 
       * pkt we sent looping back to us. To be dropped if we are non BTAMP  
       */ 
      if( WLANHAL_RX_BD_ADDR3_SELF_IDX == 
          (v_U8_t)WDA_GET_RX_ADDR3_IDX( pvBDHeader )) 
      {
        selfBcastLoopback = VOS_TRUE; 
      }
    }/*if bcast*/

     /*-------------------------------------------------------------------------
      Check if the packet that we cached matches the DPU signature of the
      newly added station 
    -------------------------------------------------------------------------*/
    pClientSTA = pTLCb->atlSTAClients[ucSTAId];

    if ( NULL == pClientSTA )
    {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Client Memory was not allocated on %s", __func__));
      return VOS_STATUS_E_FAILURE;
    }

    if ( broadcast )
    {
      ucBcastSig = (v_U8_t)uDPUSig;
      bSigMatch = (( WLAN_TL_INVALID_B_SIG != 
                    pClientSTA->wSTADesc.ucBcastSig ) &&
        ( ucBcastSig == pClientSTA->wSTADesc.ucBcastSig ));
    }
    else
    {
      ucUcastSig = (v_U8_t)uDPUSig;
      bSigMatch = (( WLAN_TL_INVALID_U_SIG != 
                      pClientSTA->wSTADesc.ucUcastSig ) &&
          ( ucUcastSig == pClientSTA->wSTADesc.ucUcastSig ));
    }

    /*-------------------------------------------------------------------------
      If the packet doesn't match - drop it 
    -------------------------------------------------------------------------*/
    if ( !bSigMatch )
    {
            TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_MED,
        "WLAN TL: Cached packet does not match DPU Sig of the new STA - drop "
        " DPU Sig %d  UC %d BC %d B %d",
        uDPUSig,
        pClientSTA->wSTADesc.ucUcastSig,
        pClientSTA->wSTADesc.ucBcastSig,
        broadcast));

      /* Drop packet */ 
      vos_pkt_return_packet(vosTempBuff); 
      vosTempBuff = vosDataBuff; 
      continue; 

    }/*if signature mismatch*/

    /*------------------------------------------------------------------------
      Check if BT-AMP frame:
      - additional processing needed in this case to separate BT-AMP date
        from BT-AMP Ctrl path 
    ------------------------------------------------------------------------*/
    if ( WLAN_STA_BT_AMP == pClientSTA->wSTADesc.wSTAType )
    {
      /*--------------------------------------------------------------------
        Process the ctrl BAP frame; if data it will return false and it 
        will be routed through the regular data path
      --------------------------------------------------------------------*/
      if ( WLANTL_ProcessBAPFrame( pvBDHeader,
                                   vosTempBuff,
                                   pTLCb,
                                  &first_data_pkt_arrived,
                                   ucSTAId))
      {
          vosTempBuff = vosDataBuff;
          continue;
        }
      }/*if BT-AMP station*/
      else if(selfBcastLoopback == VOS_TRUE)
      { 
        /* Drop packet */ 
        vos_pkt_return_packet(vosTempBuff); 
        vosTempBuff = vosDataBuff; 
        continue; 
      } 
      
      /*---------------------------------------------------------------------
        Data packet received, send to state machine
      ---------------------------------------------------------------------*/
      wSTAEvent = WLANTL_RX_EVENT;

      pfnSTAFsm = tlSTAFsm[pClientSTA->tlState].
                      pfnSTATbl[wSTAEvent];

      if ( NULL != pfnSTAFsm )
      {
#if defined WLAN_FEATURE_NEIGHBOR_ROAMING
        /* Read RSSI and update */
        vosStatus = WLANTL_HSHandleRXFrame(vos_get_global_context(
                                         VOS_MODULE_ID_TL,pTLCb),
                                           WLANTL_DATA_FRAME_TYPE,
                                           pvBDHeader,
                                           ucSTAId,
                                           broadcast,
                                           vosTempBuff);
        broadcast = VOS_FALSE;
#else
        vosStatus = WLANTL_ReadRSSI(vos_get_global_context(VOS_MODULE_ID_TL,pTLCb), pvBDHeader, ucSTAId);
#endif
        if(!VOS_IS_STATUS_SUCCESS(vosStatus))
        {
          TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "Handle RX Data Frame fail within Handoff support module"));
          /* Do Not Drop packet at here 
           * Revisit why HO module return fail
          vos_pkt_return_packet(vosTempBuff);
          vosTempBuff = vosDataBuff;
          continue;
           */
        }
        pfnSTAFsm( vos_get_global_context(VOS_MODULE_ID_TL,pTLCb), ucSTAId, 
                 &vosTempBuff, VOS_FALSE);
      }
      else
      {
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL:NULL state function, STA:%d, State: %d- dropping packet",
                   ucSTAId, pClientSTA->tlState));
        /* Drop packet */
        vos_pkt_return_packet(vosTempBuff);
        vosTempBuff = vosDataBuff;
        continue;
      }

    vosTempBuff = vosDataBuff;
  }/*while chain*/

  return VOS_STATUS_SUCCESS;
}/* WLANTL_RxCachedFrames */

/**
 * WLANTL_ForwardPkts() - forward cached eapol frames
 * @pvosGCtx: pointer to vos global context
 * @data: value to indicate either forward or flush
 *
 * Return: None
 *
 */
static VOS_STATUS WLANTL_ForwardPkts(void* pvosGCtx, uint32_t data)
{
   WLANTL_CbType*  pTLCb = NULL;

   pTLCb = VOS_GET_TL_CB(pvosGCtx);
   if (NULL == pTLCb) {
      TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
             "%s: Invalid input pointer", __func__));
      return VOS_STATUS_E_FAULT;
   }

   if (!data) {
      TLLOG2(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "%s: Pre assoc fail flush cache", __func__));
      WLANTL_FlushCachedFrames(pTLCb->vosEapolCachedFrame);
      goto done;
   }

   /* forward packets to HDD */
   if (NULL != pTLCb->vosEapolCachedFrame) {
      TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "%s: forward pre assoc cached frames", __func__));
      WLANTL_MonTranslate80211To8023Header(pTLCb->vosEapolCachedFrame, pTLCb);
      pTLCb->pfnEapolFwd(pvosGCtx, pTLCb->vosEapolCachedFrame);
   }

done:
  pTLCb->vosEapolCachedFrame = NULL;
  pTLCb->preassoc_caching = false;

  return VOS_STATUS_SUCCESS;
}

/*==========================================================================
  FUNCTION    WLANTL_RxProcessMsg

  DESCRIPTION
    Called by VOSS when a message was serialized for TL through the
    rx thread/task.

  DEPENDENCIES
    The TL must be initialized before this function can be called.

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context
    message:        type and content of the message


  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:   invalid input parameters
    VOS_STATUS_E_FAULT:   pointer to TL cb is NULL ; access would cause a
                          page fault
    VOS_STATUS_SUCCESS:   Everything is good :)

  Other values can be returned as a result of a function call, please check
  corresponding API for more info.
  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_RxProcessMsg
(
  v_PVOID_t        pvosGCtx,
  vos_msg_t*       message
)
{
   VOS_STATUS      vosStatus = VOS_STATUS_SUCCESS;
   v_U32_t         uData;
   v_U8_t          ucSTAId;
   v_U8_t          ucUcastSig;
   v_U8_t          ucBcastSig;

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if ( NULL == message )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid parameter sent on WLANTL_RxProcessMessage"));
    return VOS_STATUS_E_INVAL;
  }

  /*------------------------------------------------------------------------
    Process message
   ------------------------------------------------------------------------*/
  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL:Received message: %d through rx flow", message->type));

  switch( message->type )
  {

  case WLANTL_RX_FWD_CACHED:
    /*---------------------------------------------------------------------
     The data sent with the message has the following structure:
       | 00 | ucBcastSignature | ucUcastSignature | ucSTAID |
       each field above is one byte
    ---------------------------------------------------------------------*/
    uData       = message->bodyval;
    ucSTAId     = ( uData & 0x000000FF);
    ucUcastSig  = ( uData & 0x0000FF00)>>8;
    ucBcastSig  = (v_U8_t)(( uData & 0x00FF0000)>>16);
    vosStatus   = WLANTL_ForwardSTAFrames( pvosGCtx, ucSTAId,
                                           ucUcastSig, ucBcastSig);
    break;

  case WLANTL_RX_FWD_PRE_ASSOC_CACHED:
    uData = message->bodyval;
    vosStatus = WLANTL_ForwardPkts(pvosGCtx, uData);
    break;

  default:
    /*no processing for now*/
    break;
  }

  return VOS_STATUS_SUCCESS;
}


/*==========================================================================
  FUNCTION    WLANTL_ResourceCB

  DESCRIPTION
    Called by the TL when it has packets available for transmission.

  DEPENDENCIES
    The TL must be registered with BAL before this function can be called.

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    or BAL's control block can be extracted from its context

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_FAULT:   pointer to TL cb is NULL ; access would cause a
                          page fault
    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_ResourceCB
(
  v_PVOID_t       pvosGCtx,
  v_U32_t         uCount
)
{
   WLANTL_CbType*  pTLCb = NULL;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
        "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_ChangeSTAState"));
    return VOS_STATUS_E_FAULT;
  }

  pTLCb->uResCount = uCount;


  /*-----------------------------------------------------------------------
    Resume Tx if enough res and not suspended
   -----------------------------------------------------------------------*/
  if (( pTLCb->uResCount >=  WDA_TLI_MIN_RES_MF ) &&
      ( 0 == pTLCb->ucTxSuspended ))
  {
    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
         "WLAN TL:Issuing Xmit start request to BAL for avail res ASYNC"));
    return WDA_DS_StartXmit(pvosGCtx);
  }

  return VOS_STATUS_SUCCESS;
}/* WLANTL_ResourceCB */


/*==========================================================================
  FUNCTION   WLANTL_IsTxXmitPending

  DESCRIPTION
    Called by the WDA when it wants to know whether WDA_DS_TX_START_XMIT msg
    is pending in TL msg queue 

  DEPENDENCIES
    The TL must be registered with WDA before this function can be called.

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    or WDA's control block can be extracted from its context

  RETURN VALUE
    The result code associated with performing the operation

    0:   No WDA_DS_TX_START_XMIT msg pending 
    1:   Msg WDA_DS_TX_START_XMIT already pending in TL msg queue 

  SIDE EFFECTS

============================================================================*/
v_BOOL_t
WLANTL_IsTxXmitPending
(
  v_PVOID_t       pvosGCtx
)
{

   WLANTL_CbType*  pTLCb = NULL;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_FATAL,
        "WLAN TL:Invalid TL pointer from pvosGCtx in WLANTL_IsTxXmitPending "));
    return FALSE;
  }

  return pTLCb->isTxTranmitMsgPending;

}/*WLANTL_IsTxXmitPending */

/*==========================================================================
  FUNCTION   WLANTL_SetTxXmitPending

  DESCRIPTION
    Called by the WDA when it wants to indicate that WDA_DS_TX_START_XMIT msg
    is pending in TL msg queue 

  DEPENDENCIES
    The TL must be registered with WDA before this function can be called.

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    or WDA's control block can be extracted from its context

  RETURN VALUE      None

  SIDE EFFECTS

============================================================================*/

v_VOID_t
WLANTL_SetTxXmitPending
(
  v_PVOID_t       pvosGCtx
)
{

   WLANTL_CbType*  pTLCb = NULL;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_FATAL,
        "WLAN TL:Invalid TL pointer from pvosGCtx in WLANTL_SetTxXmitPending"));
    return;
  }

  pTLCb->isTxTranmitMsgPending = 1;
  return;

}/*WLANTL_SetTxXmitPending  */

/*==========================================================================
  FUNCTION   WLANTL_ClearTxXmitPending

  DESCRIPTION
    Called by the WDA when it wants to indicate that no WDA_DS_TX_START_XMIT msg
    is pending in TL msg queue 

  DEPENDENCIES
    The TL must be registered with WDA before this function can be called.

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    or WDA's control block can be extracted from its context

  RETURN VALUE     None

  SIDE EFFECTS

============================================================================*/

v_VOID_t
WLANTL_ClearTxXmitPending
(
  v_PVOID_t       pvosGCtx
)
{

   WLANTL_CbType*  pTLCb = NULL;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_FATAL,
        "WLAN TL:Invalid TL pointer from pvosGCtx in WLANTL_ClearTxXmitPending "));
    return;
  }

  pTLCb->isTxTranmitMsgPending = 0;
  return;
}/*WLANTL_ClearTxXmitPending */

/*==========================================================================
  FUNCTION   WLANTL_TxThreadDebugHandler

  DESCRIPTION
    Printing TL Snapshot dump, processed under TxThread context, currently
    information regarding the global TlCb struture. Dumps information related
    to per active STA connection currently in use by TL.

  DEPENDENCIES
    The TL must be initialized before this gets called.

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    or WDA's control block can be extracted from its context

  RETURN VALUE      None

  SIDE EFFECTS

============================================================================*/

v_VOID_t
WLANTL_TxThreadDebugHandler
(
 v_PVOID_t *pVosContext
)
{
   WLANTL_CbType* pTLCb = NULL;
   WLANTL_STAClientType* pClientSTA = NULL;
   int i = 0;
   v_U8_t uFlowMask; // TX FlowMask from WDA

   TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_FATAL,
        "WLAN TL: %s Enter ", __func__));

   pTLCb = VOS_GET_TL_CB(pVosContext);

   if ( NULL == pVosContext || NULL == pTLCb )
   {
        TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                        "Global VoS Context or TL Context are NULL"));
        return;
   }

   if (VOS_STATUS_SUCCESS == WDA_DS_GetTxFlowMask(pVosContext, &uFlowMask))
   {
        TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "WDA uTxFlowMask: 0x%x", uFlowMask));
   }

   TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "************************TL DUMP INFORMATION**************"));

   TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "uDelayedTriggerFrmInt:%d\tuMinFramesProcThres:%d",
          pTLCb->tlConfigInfo.uDelayedTriggerFrmInt,
          pTLCb->tlConfigInfo.uMinFramesProcThres));

   TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "Management Frame Client exists: %d",
          pTLCb->tlMgmtFrmClient.ucExists));
   TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "usPendingTxCompleteCount: %d\tucTxSuspended: %d",
          pTLCb->usPendingTxCompleteCount,
          pTLCb->ucTxSuspended));

   TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "uResCount: %d", pTLCb->uResCount));

   TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "ucRegisteredStaId: %d\tucCurrentSTA: %d",
          pTLCb->ucRegisteredStaId, pTLCb->ucCurrentSTA));

   TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "UrgentFrameProcessing: %s\tuFramesProcThres: %d",
          (pTLCb->bUrgent?"True":"False"), pTLCb->uFramesProcThres));

   TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "isTxTranmitMsgPending: %d\t isBMPS: %s",
          pTLCb->isTxTranmitMsgPending, pTLCb->isBMPS?"True":"False"));

#ifdef FEATURE_WLAN_TDLS
   TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "TDLS Peer Count: %d", pTLCb->ucTdlsPeerCount));
#endif

   TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
          "++++++++++++++++++++Registerd Client Information++++++++++"));

   for ( i =0; i<WLAN_MAX_STA_COUNT; i++ )
   {
        pClientSTA = pTLCb->atlSTAClients[i];
        if( NULL == pClientSTA || 0 == pClientSTA->ucExists)
        {
                continue;
        }

        TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
              "######################STA Index: %d ############################",i));
        TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, "WLAN_STADescType:"));
        TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
              "STAId: %d\t STA MAC Address: %pM", pClientSTA->wSTADesc.ucSTAId,
              pClientSTA->wSTADesc.vSTAMACAddress.bytes));
        TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
              "STA Type: %d\tProtectedFrame: %d",
              pClientSTA->wSTADesc.wSTAType, pClientSTA->wSTADesc.ucProtectedFrame));
        TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
               "QoS: %d\tRxFrameTrans: %d\tTxFrameTrans: %d",
               pClientSTA->wSTADesc.ucQosEnabled, pClientSTA->wSTADesc.ucSwFrameRXXlation,
               pClientSTA->wSTADesc.ucSwFrameTXXlation));
        TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
              "ucUcastSig: %d\tucBcastSig: %d", pClientSTA->wSTADesc.ucUcastSig,
              pClientSTA->wSTADesc.ucBcastSig));

        TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
              "ClientIndex: %d\t Exists: %d", i, pClientSTA->ucExists));
        TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
              "TL State: %d\t TL Priority: %d", pClientSTA->tlState,
              pClientSTA->tlPri));
        TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
              "ucTxSuspended: %d\tucPktPending: %d", pClientSTA->ucTxSuspended,
              pClientSTA->ucPktPending));
        TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
              "ucEAPOLPktPending: %d\tucNoMoreData: %d",
              pClientSTA->ucEapolPktPending, pClientSTA->ucNoMoreData));
        TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
               "enableCaching: %d\t fcStaTxDisabled: %d", pClientSTA->enableCaching,
               pClientSTA->fcStaTxDisabled));
        TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
               "ucCurrentAC: %d\tucServicedAC: %d", pClientSTA->ucCurrentAC,
               pClientSTA->ucServicedAC));
        TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
              "TID: %d\tautTxCount[0]: %d\tauRxCount[0]: %d",0, pClientSTA->auTxCount[0],
              pClientSTA->auRxCount[0]));
        TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
              "aucAcMask[0]: %d\taucAcMask[1]: %d\taucAcMask[2]: %d\taucAcMask[3]: %d\t",
              pClientSTA->aucACMask[0], pClientSTA->aucACMask[1],
              pClientSTA->aucACMask[2], pClientSTA->aucACMask[3]));
        TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,

               "ucCurrentWeight: %d", pClientSTA->ucCurrentWeight));

        if( WLAN_STA_SOFTAP == pClientSTA->wSTADesc.wSTAType)
        {
            TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
                  "TrafficStatistics for SOFTAP Station:"));
            TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
                  "RUF=%d\tRMF=%d\tRBF=%d", pClientSTA->trafficStatistics.rxUCFcnt,
                                            pClientSTA->trafficStatistics.rxMCFcnt,
                                            pClientSTA->trafficStatistics.rxBCFcnt));
            TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
                  "RUB=%d\tRMB=%d\tRBB=%d", pClientSTA->trafficStatistics.rxUCBcnt,
                                            pClientSTA->trafficStatistics.rxMCBcnt,
                                            pClientSTA->trafficStatistics.rxBCBcnt));
            TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
                  "TUF=%d\tTMF=%d\tTBF=%d", pClientSTA->trafficStatistics.txUCFcnt,
                                            pClientSTA->trafficStatistics.txMCFcnt,
                                            pClientSTA->trafficStatistics.txBCFcnt));
            TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
                  "TUB=%d\tTMB=%d\tTBB=%d", pClientSTA->trafficStatistics.txUCBcnt,
                                            pClientSTA->trafficStatistics.txMCBcnt,
                                            pClientSTA->trafficStatistics.txBCBcnt));
        }

    }
   return;
}

/*==========================================================================
  FUNCTION   WLANTL_FatalErrorHandler

  DESCRIPTION
    Handle Fatal errors detected on the TX path.
    Currently issues SSR to recover from the error.

  DEPENDENCIES
    The TL must be initialized before this gets called.

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    or WDA's control block can be extracted from its context

  RETURN VALUE      None

  SIDE EFFECTS

============================================================================*/
v_VOID_t
WLANTL_FatalErrorHandler
(
 v_PVOID_t *pVosContext
)
{

   TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_FATAL,
        "WLAN TL: %s Enter ", __func__));

   if ( NULL == pVosContext )
   {
        TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                        "%s: Global VoS Context or TL Context are NULL",
                        __func__));
        return;
   }

   /*
    * Issue SSR. vos_wlanRestart has tight checks to make sure that
    * we do not send an FIQ if previous FIQ is not processed
    */
   vos_wlanRestart(VOS_REASON_UNSPECIFIED);
}

/*==========================================================================
  FUNCTION   WLANTL_TLDebugMessage

  DESCRIPTION
    Post a TL Snapshot request, posts message in TxThread.

  DEPENDENCIES
    The TL must be initialized before this gets called.

  PARAMETERS

    IN
    displaySnapshot Boolean showing whether to dump the snapshot or not.

  RETURN VALUE      None

  SIDE EFFECTS

============================================================================*/

v_VOID_t
WLANTL_TLDebugMessage
(
 v_U32_t debugFlags
)
{
   vos_msg_t vosMsg;
   VOS_STATUS status;

   if(debugFlags & WLANTL_DEBUG_TX_SNAPSHOT)
   {
        vosMsg.reserved = 0;
        vosMsg.bodyptr  = NULL;
        vosMsg.type     = WLANTL_TX_SNAPSHOT;

        status = vos_tx_mq_serialize( VOS_MODULE_ID_TL, &vosMsg);
        if(status != VOS_STATUS_SUCCESS)
        {
            TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, "TX Msg Posting Failed with status: %d",status));
            return;
        }
   }
   if (debugFlags & WLANTL_DEBUG_FW_CLEANUP)
   {
        vosMsg.reserved = 0;
        vosMsg.bodyptr  = NULL;
        vosMsg.type     = WLANTL_TX_FW_DEBUG;

        status = vos_tx_mq_serialize( VOS_MODULE_ID_TL, &vosMsg);
        if(status != VOS_STATUS_SUCCESS)
        {
            TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, "TX Msg Posting Failed with status: %d",status));
            return;
        }
   }
   if(debugFlags & WLANTL_DEBUG_KICKDXE)
   {
        vosMsg.reserved = 0;
        vosMsg.bodyptr  = NULL;
        vosMsg.type     = WLANTL_TX_KICKDXE;

        status = vos_tx_mq_serialize( VOS_MODULE_ID_TL, &vosMsg);
        if(status != VOS_STATUS_SUCCESS)
        {
            TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, "TX Msg Posting Failed with status: %d",status));
            return;
        }
   }
   return;
}

/*==========================================================================
  FUNCTION   WLANTL_FatalError

  DESCRIPTION
    Fatal error reported in TX path, post an event to TX Thread for further
    handling

  DEPENDENCIES
    The TL must be initialized before this gets called.

  PARAMETERS

    VOID

  RETURN VALUE      None

  SIDE EFFECTS

============================================================================*/

v_VOID_t
WLANTL_FatalError
(
 v_VOID_t
)
{
   vos_msg_t vosMsg;
   VOS_STATUS status;

   vosMsg.reserved = 0;
   vosMsg.bodyptr  = NULL;
   vosMsg.type     = WLANTL_TX_FATAL_ERROR;

   status = vos_tx_mq_serialize( VOS_MODULE_ID_TL, &vosMsg);
   if(status != VOS_STATUS_SUCCESS)
   {
       TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                        "%s: TX Msg Posting Failed with status: %d",
                        __func__,status));
   }
   return;
}
/*============================================================================
                           TL STATE MACHINE
============================================================================*/

/*==========================================================================
  FUNCTION    WLANTL_STATxConn

  DESCRIPTION
    Transmit in connected state - only EAPOL and WAI packets allowed

  DEPENDENCIES
    The STA must be registered with TL before this function can be called.

  PARAMETERS

   IN
   pvosGCtx:       pointer to the global vos context; a handle to TL's
                   control block can be extracted from its context
   ucSTAId:        identifier of the station being processed
   vosDataBuff:   pointer to the tx vos buffer

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_FAULT:   pointer to TL cb is NULL ; access would cause a
                          page fault
    VOS_STATUS_SUCCESS:   Everything is good :)

   Other return values are possible coming from the called functions.
   Please check API for additional info.

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_STATxConn
(
  v_PVOID_t     pvosGCtx,
  v_U8_t        ucSTAId,
  vos_pkt_t**   pvosDataBuff,
  v_BOOL_t      bForwardIAPPwithLLC
)
{
   v_U16_t              usPktLen;
   VOS_STATUS           vosStatus;
   v_MACADDR_t          vDestMacAddr;
   vos_pkt_t*           vosDataBuff = NULL;
   WLANTL_CbType*       pTLCb       = NULL;
   WLANTL_STAClientType* pClientSTA = NULL;
   WLANTL_MetaInfoType  tlMetaInfo;
   v_U8_t               ucTypeSubtype = 0;
   v_U8_t               ucTid;
   v_U8_t               extraHeadSpace = 0;
   v_U8_t               ucWDSEnabled = 0;
   v_U8_t               ucAC, ucACMask, i; 
   v_U32_t              txFlag = HAL_TX_NO_ENCRYPTION_MASK;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
   VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
             "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_STATxConn");
   *pvosDataBuff = NULL;
    return VOS_STATUS_E_FAULT;
  }
  pClientSTA = pTLCb->atlSTAClients[ucSTAId];

  if ( NULL == pClientSTA )
  {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Client Memory was not allocated on %s", __func__));
      return VOS_STATUS_E_FAILURE;
  }

  /*-------------------------------------------------------------------
      Disable AC temporary - if successfull retrieve re-enable
      The order is justified because of the possible scenario
       - TL tryes to fetch packet for AC and it returns NULL
       - TL analyzes the data it has received to see if there are
       any more pkts available for AC -> if not TL will disable AC
       - however it is possible that while analyzing results TL got
       preempted by a pending indication where the mask was again set
       TL will not check again and as a result when it resumes
       execution it will disable AC
       To prevent this the AC will be disabled here and if retrieve
       is successfull it will be re-enabled
  -------------------------------------------------------------------*/


  //LTI:pTLCb->atlSTAClients[ucSTAId].
  //LTI:   aucACMask[pTLCb->atlSTAClients[ucSTAId].ucCurrentAC] = 0; 

  /*------------------------------------------------------------------------
    Fetch packet from HDD
   ------------------------------------------------------------------------*/
#ifdef FEATURE_WLAN_TDLS
  if ((WLAN_STA_SOFTAP != pClientSTA->wSTADesc.wSTAType) &&
      !(vos_concurrent_open_sessions_running()) &&
      !pTLCb->ucTdlsPeerCount)
  {
#else
  if ((WLAN_STA_SOFTAP != pClientSTA->wSTADesc.wSTAType) &&
      !(vos_concurrent_open_sessions_running()))
  {
#endif
      ucAC = pClientSTA->ucCurrentAC;

  /*-------------------------------------------------------------------
      Disable AC temporary - if successfull retrieve re-enable
      The order is justified because of the possible scenario
       - TL tryes to fetch packet for AC and it returns NULL
       - TL analyzes the data it has received to see if there are
       any more pkts available for AC -> if not TL will disable AC
       - however it is possible that while analyzing results TL got
       preempted by a pending indication where the mask was again set
       TL will not check again and as a result when it resumes
       execution it will disable AC
       To prevent this the AC will be disabled here and if retrieve
       is successfull it will be re-enabled
  -------------------------------------------------------------------*/
      pClientSTA->aucACMask[ucAC] = 0;
  }
  else
  {
      //softap case
      ucAC = pTLCb->uCurServedAC;
      pClientSTA->aucACMask[ucAC] = 0;
  }

    /*You make an initial assumption that HDD has no more data and if the
      assumption was wrong you reset the flags to their original state
     This will prevent from exposing a race condition between checking with HDD
     for packets and setting the flags to false*/
  //LTI: vos_atomic_set_U8( &pTLCb->atlSTAClients[ucSTAId].ucPktPending, 0);
  //LTI: pTLCb->atlSTAClients[ucSTAId].ucNoMoreData = 1;
  vos_atomic_set_U8( &pClientSTA->ucPktPending, 0);
  WLAN_TL_AC_ARRAY_2_MASK( pClientSTA, ucACMask, i);
    /*You make an initial assumption that HDD has no more data and if the
           assumption was wrong you reset the flags to their original state
           This will prevent from exposing a race condition between checking with HDD
           for packets and setting the flags to false*/
  if ( 0 == ucACMask )
  {
      pClientSTA->ucNoMoreData = 1;
  }
  else
  {
      vos_atomic_set_U8( &pClientSTA->ucPktPending, 1);
  }


  VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
            "WLAN TL: WLANTL_STATxConn fetching packet from HDD for AC: %d AC Mask: %d Pkt Pending: %d", 
             ucAC, ucACMask, pClientSTA->ucPktPending);

  /*------------------------------------------------------------------------
    Fetch tx packet from HDD
   ------------------------------------------------------------------------*/

  vosStatus = pClientSTA->pfnSTAFetchPkt( pvosGCtx,
                               &ucSTAId,
                               ucAC,
                               &vosDataBuff, &tlMetaInfo );

  if (( VOS_STATUS_SUCCESS != vosStatus ) || ( NULL == vosDataBuff ))
  {
    TLLOG1(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
               "WLAN TL:No more data at HDD status %d", vosStatus));
    *pvosDataBuff = NULL;

    /*--------------------------------------------------------------------
    Reset AC for the serviced station to the highest priority AC
    -> due to no more data at the station
    Even if this AC is not supported by the station, correction will be
    made in the main TL loop
    --------------------------------------------------------------------*/
    pClientSTA->ucCurrentAC     = WLANTL_AC_HIGH_PRIO;
    pClientSTA->ucCurrentWeight = 0;

    VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
              "WLAN TL: WLANTL_STATxConn no more packets in HDD for AC: %d AC Mask: %d", 
               ucAC, ucACMask);

    return vosStatus;
  }

  /*There are still packets in HDD - set back the pending packets and 
   the no more data assumption*/
  vos_atomic_set_U8( &pClientSTA->ucPktPending, 1);
  pClientSTA->ucNoMoreData = 0;
  pClientSTA->aucACMask[ucAC] = 1;

#ifdef WLAN_PERF 
  vos_pkt_set_user_data_ptr( vosDataBuff, VOS_PKT_USER_DATA_ID_BAL, 
                             (v_PVOID_t)0);

#endif /*WLAN_PERF*/


#ifdef FEATURE_WLAN_WAPI
   /*------------------------------------------------------------------------
    If the packet is neither an Eapol packet nor a WAI packet then drop it
   ------------------------------------------------------------------------*/
   if ( 0 == tlMetaInfo.ucIsEapol && 0 == tlMetaInfo.ucIsWai )
   {
     TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
                "WLAN TL:Only EAPOL or WAI packets allowed before authentication"));

     /* Fail tx for packet */
     pClientSTA->pfnSTATxComp( pvosGCtx, vosDataBuff,
                                                VOS_STATUS_E_BADMSG);
     vosDataBuff = NULL;
     *pvosDataBuff = NULL;
     return VOS_STATUS_SUCCESS;
  }
#else
   if ( 0 == tlMetaInfo.ucIsEapol )
  {
     TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                "WLAN TL:Received non EAPOL packet before authentication"));

    /* Fail tx for packet */
    pClientSTA->pfnSTATxComp( pvosGCtx, vosDataBuff,
                                                VOS_STATUS_E_BADMSG);
    vosDataBuff = NULL;
    *pvosDataBuff = NULL;
    return VOS_STATUS_SUCCESS;
  }
#endif /* FEATURE_WLAN_WAPI */

  /*-------------------------------------------------------------------------
   Check TID
  -------------------------------------------------------------------------*/
  ucTid     = tlMetaInfo.ucTID;

  /*Make sure TID is valid*/
  if ( WLANTL_TID_INVALID(ucTid)) 
  {
     TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
            "WLAN TL:Invalid TID sent in meta info %d - defaulting to 0 (BE)", 
             ucTid));
     ucTid = 0; 
  }

  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL:Attaching BD header to pkt on WLANTL_STATxConn"));

#ifdef FEATURE_WLAN_WAPI
  /*------------------------------------------------------------------------
    Translate 802.3 frame to 802.11 if Frame translation is enabled or if 
    frame is a WAI frame.
   ------------------------------------------------------------------------*/
  if ( ( 1 == tlMetaInfo.ucIsWai ) ||
       ( 0 == tlMetaInfo.ucDisableFrmXtl ) )
#else
  /*------------------------------------------------------------------------
    Translate 802.3 frame to 802.11 if Frame translation is enabled 
   ------------------------------------------------------------------------*/
  if ( ( 0 == tlMetaInfo.ucDisableFrmXtl ) &&
      ( 0 != pClientSTA->wSTADesc.ucSwFrameTXXlation) )
#endif //#ifdef FEATURE_WLAN_WAPI
  {
    vosStatus =  WLANTL_Translate8023To80211Header( vosDataBuff, &vosStatus,
                                                    pTLCb, &ucSTAId,
                                                    &tlMetaInfo, &ucWDSEnabled,
                                                    &extraHeadSpace);
    if ( VOS_STATUS_SUCCESS != vosStatus )
    {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                "WLAN TL:Error when translating header WLANTL_STATxConn"));

      return vosStatus;
    }

    tlMetaInfo.ucDisableFrmXtl = 1;
  }

  /*-------------------------------------------------------------------------
    Call HAL to fill BD header
   -------------------------------------------------------------------------*/
  ucTypeSubtype |= (WLANTL_80211_DATA_TYPE << 4);

  if ( pClientSTA->wSTADesc.ucQosEnabled )
  {
    ucTypeSubtype |= (WLANTL_80211_DATA_QOS_SUBTYPE);
  }

#ifdef FEATURE_WLAN_WAPI
  /* TL State does not transition to AUTHENTICATED till GTK is installed, So in
   * case of WPA where GTK handshake is done after the 4 way handshake, the
   * unicast 2/2 EAPOL packet from the STA->AP has to be encrypted even before
   * the TL is in authenticated state. Since the PTK has been installed
   * already (after the 4 way handshake) we make sure that all traffic
   * is encrypted henceforth.(Note: TL is still not in AUTHENTICATED state so
   * we will only allow EAPOL data or WAI in case of WAPI)
   */
  if (tlMetaInfo.ucIsEapol && pClientSTA->ptkInstalled)
  {
    txFlag = 0;
  }
#else
  if (pClientSTA->ptkInstalled)
  {
    txFlag = 0;
  }
#endif

  vosStatus = (VOS_STATUS)WDA_DS_BuildTxPacketInfo( pvosGCtx, vosDataBuff , &vDestMacAddr,
                          tlMetaInfo.ucDisableFrmXtl, &usPktLen,
                          pClientSTA->wSTADesc.ucQosEnabled, ucWDSEnabled,
                          extraHeadSpace,
                          ucTypeSubtype, &pClientSTA->wSTADesc.vSelfMACAddress,
                          ucTid, txFlag,
                          tlMetaInfo.usTimeStamp, tlMetaInfo.ucIsEapol || tlMetaInfo.ucIsWai,
                          tlMetaInfo.ucIsArp, tlMetaInfo.ucUP, tlMetaInfo.ucTxBdToken);

  if ( VOS_STATUS_SUCCESS != vosStatus )
  {
     TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                "WLAN TL:Failed while attempting to fill BD %d", vosStatus));
    *pvosDataBuff = NULL;
    return vosStatus;
  }

  /*-----------------------------------------------------------------------
    Update tx counter for BA session query for tx side
    !1 - should this be done for EAPOL frames?
    -----------------------------------------------------------------------*/
  pClientSTA->auTxCount[ucTid]++;

  vos_pkt_set_user_data_ptr( vosDataBuff, VOS_PKT_USER_DATA_ID_TL,
               (v_PVOID_t)pClientSTA->pfnSTATxComp );

  /*------------------------------------------------------------------------
    Save data to input pointer for TL core
  ------------------------------------------------------------------------*/
  *pvosDataBuff = vosDataBuff;
  /*security frames cannot be delayed*/
  pTLCb->bUrgent      = TRUE;

  /* TX Statistics */
  if (!(tlMetaInfo.ucBcast || tlMetaInfo.ucMcast))
  {
    /* This is TX UC frame */
    pClientSTA->trafficStatistics.txUCFcnt++;
    pClientSTA->trafficStatistics.txUCBcnt += usPktLen;
  }

  return VOS_STATUS_SUCCESS;
}/* WLANTL_STATxConn */


/*==========================================================================
  FUNCTION    WLANTL_STATxAuth

  DESCRIPTION
    Transmit in authenticated state - all data allowed

  DEPENDENCIES
    The STA must be registered with TL before this function can be called.

  PARAMETERS

   IN
   pvosGCtx:       pointer to the global vos context; a handle to TL's
                   control block can be extracted from its context
   ucSTAId:        identifier of the station being processed
   vosDataBuff:   pointer to the tx vos buffer

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_FAULT:   pointer to TL cb is NULL ; access would cause a
                          page fault
    VOS_STATUS_SUCCESS:   Everything is good :)

   Other return values are possible coming from the called functions.
   Please check API for additional info.

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_STATxAuth
(
  v_PVOID_t     pvosGCtx,
  v_U8_t        ucSTAId,
  vos_pkt_t**   pvosDataBuff,
  v_BOOL_t      bForwardIAPPwithLLC
)
{
   v_U16_t               usPktLen;
   VOS_STATUS            vosStatus;
   v_MACADDR_t           vDestMacAddr;
   vos_pkt_t*            vosDataBuff = NULL;
   WLANTL_CbType*        pTLCb       = NULL;
   WLANTL_MetaInfoType   tlMetaInfo;
   v_U8_t                ucTypeSubtype = 0;
   WLANTL_ACEnumType     ucAC;
   WLANTL_ACEnumType     ucNextAC;
   v_U8_t                ucTid;
   v_U8_t                ucSwFrmXtl = 0;
   v_U8_t                extraHeadSpace = 0;
   WLANTL_STAClientType *pStaClient = NULL;
   v_U8_t                ucWDSEnabled = 0;
   v_U32_t               ucTxFlag   = 0;
   v_U8_t                ucACMask, i;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
   Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if (( NULL == pTLCb ) || ( NULL == pvosDataBuff ))
  {
     TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL:Invalid input params on WLANTL_STATxAuth TL %pK DB %pK",
             pTLCb, pvosDataBuff));
    if (NULL != pvosDataBuff)
    {
        *pvosDataBuff = NULL;
    }
    if(NULL != pTLCb)
    {
        if ( NULL == pTLCb->atlSTAClients[ucSTAId] )
        {
            TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                "WLAN TL:Client Memory was not allocated on %s", __func__));
            return VOS_STATUS_E_FAILURE;
        }
        pTLCb->atlSTAClients[ucSTAId]->ucNoMoreData = 1;
    }
    return VOS_STATUS_E_FAULT;
  }
  pStaClient = pTLCb->atlSTAClients[ucSTAId];

  if ( NULL == pStaClient )
  {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Client Memory was not allocated on %s", __func__));
      return VOS_STATUS_E_FAILURE;
  }

  vos_mem_zero(&tlMetaInfo, sizeof(tlMetaInfo));
  /*------------------------------------------------------------------------
    Fetch packet from HDD
   ------------------------------------------------------------------------*/
#ifdef FEATURE_WLAN_TDLS
  if ((WLAN_STA_SOFTAP != pStaClient->wSTADesc.wSTAType) &&
      (!vos_concurrent_open_sessions_running()) &&
      !pTLCb->ucTdlsPeerCount)
  {
#else
  if ((WLAN_STA_SOFTAP != pStaClient->wSTADesc.wSTAType) &&
      (!vos_concurrent_open_sessions_running()))
  {
#endif
  ucAC = pStaClient->ucCurrentAC;

  /*-------------------------------------------------------------------
      Disable AC temporary - if successfull retrieve re-enable
      The order is justified because of the possible scenario
       - TL tryes to fetch packet for AC and it returns NULL
       - TL analyzes the data it has received to see if there are
       any more pkts available for AC -> if not TL will disable AC
       - however it is possible that while analyzing results TL got
       preempted by a pending indication where the mask was again set
       TL will not check again and as a result when it resumes
       execution it will disable AC
       To prevent this the AC will be disabled here and if retrieve
       is successfull it will be re-enabled
  -------------------------------------------------------------------*/
  pStaClient->aucACMask[pStaClient->ucCurrentAC] = 0; 

  // don't reset it, as other AC queues in HDD may have packets
  //vos_atomic_set_U8( &pStaClient->ucPktPending, 0);
  }
  else
  {
    //softap case
    ucAC = pTLCb->uCurServedAC;
    pStaClient->aucACMask[ucAC] = 0; 

    //vos_atomic_set_U8( &pStaClient->ucPktPending, 0);
  }

  WLAN_TL_AC_ARRAY_2_MASK( pStaClient, ucACMask, i); 
    /*You make an initial assumption that HDD has no more data and if the 
      assumption was wrong you reset the flags to their original state
     This will prevent from exposing a race condition between checking with HDD 
     for packets and setting the flags to false*/
  if ( 0 == ucACMask )
  {
    vos_atomic_set_U8( &pStaClient->ucPktPending, 0);
    pStaClient->ucNoMoreData = 1;
  }

  vosStatus = pStaClient->pfnSTAFetchPkt( pvosGCtx, 
                               &ucSTAId,
                               ucAC,
                               &vosDataBuff, &tlMetaInfo );


  if (( VOS_STATUS_SUCCESS != vosStatus ) || ( NULL == vosDataBuff ))
  {

    VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
               "WLAN TL:Failed while attempting to fetch pkt from HDD QId:%d status:%d",
               ucAC, vosStatus);
    *pvosDataBuff = NULL;
    /*--------------------------------------------------------------------
      Reset AC for the serviced station to the highest priority AC
      -> due to no more data at the station
      Even if this AC is not supported by the station, correction will be
      made in the main TL loop
    --------------------------------------------------------------------*/
    pStaClient->ucCurrentAC     = WLANTL_AC_HIGH_PRIO;
    pStaClient->ucCurrentWeight = 0;

    return vosStatus;
  }

  WLANTL_StatHandleTXFrame(pvosGCtx, ucSTAId, vosDataBuff, NULL, &tlMetaInfo);

  /*There are still packets in HDD - set back the pending packets and 
   the no more data assumption*/
  vos_atomic_set_U8( &pStaClient->ucPktPending, 1);
  pStaClient->ucNoMoreData = 0;

  if (WLAN_STA_SOFTAP != pStaClient->wSTADesc.wSTAType)
  {
  // don't need to set it, as we don't reset it in this function.
  //vos_atomic_set_U8( &pTLCb->atlSTAClients[ucSTAId].ucPktPending, 1);
  }

#ifdef WLAN_PERF 
   vos_pkt_set_user_data_ptr( vosDataBuff, VOS_PKT_USER_DATA_ID_BAL, 
                       (v_PVOID_t)0);
#endif /*WLAN_PERF*/

   /*-------------------------------------------------------------------------
    Check TID
   -------------------------------------------------------------------------*/
   ucTid     = tlMetaInfo.ucTID;

  /*Make sure TID is valid*/
  if ( WLANTL_TID_INVALID(ucTid)) 
  {
     TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
            "WLAN TL:Invalid TID sent in meta info %d - defaulting to 0 (BE)", 
             ucTid));
     ucTid = 0; 
  }

  /*Save for UAPSD timer consideration*/
  pStaClient->ucServicedAC = ucAC; 

  if ( ucAC == pStaClient->ucCurrentAC ) 
  {
    pStaClient->aucACMask[pStaClient->ucCurrentAC] = 1;
    pStaClient->ucCurrentWeight--;
  }
  else
  {
    pStaClient->ucCurrentAC     = ucAC;
    pStaClient->ucCurrentWeight = pTLCb->tlConfigInfo.ucAcWeights[ucAC] - 1;

    pStaClient->aucACMask[pStaClient->ucCurrentAC] = 1;

  }

  if (WLAN_STA_SOFTAP != pStaClient->wSTADesc.wSTAType)
  {
  if ( 0 == pStaClient->ucCurrentWeight ) 
  {
    WLANTL_ACEnumType tempAC = ucAC;
    /*-----------------------------------------------------------------------
       Choose next AC - !!! optimize me
    -----------------------------------------------------------------------*/
    while ( 0 != ucACMask ) 
    {
      if(tempAC == WLANTL_AC_BK)
         ucNextAC = WLANTL_AC_HIGH_PRIO;
      else
         ucNextAC = (tempAC - 1);

      if ( 0 != pStaClient->aucACMask[ucNextAC] )
      {
         pStaClient->ucCurrentAC     = ucNextAC;
         pStaClient->ucCurrentWeight = pTLCb->tlConfigInfo.ucAcWeights[ucNextAC];

         TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                    "WLAN TL: Changing serviced AC to: %d with Weight: %d",
                    pStaClient->ucCurrentAC , 
                    pStaClient->ucCurrentWeight));
         break;
      }
      tempAC = ucNextAC;
    }
  }
  }

  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL:Attaching BD header to pkt on WLANTL_STATxAuth"));

  /*------------------------------------------------------------------------
    Translate 802.3 frame to 802.11
   ------------------------------------------------------------------------*/
  if ( 0 == tlMetaInfo.ucDisableFrmXtl )
  {
     /* Needs frame translation */
     // if the client has not enabled SW-only frame translation
     // and if the frame is a unicast frame
     //   (HW frame translation does not support multiple broadcast domains
     //    so we use SW frame translation for broadcast/multicast frames)
#ifdef FEATURE_WLAN_WAPI
     // and if the frame is not a WAPI frame
#endif
     // then use HW_based frame translation

     if ( ( 0 == pStaClient->wSTADesc.ucSwFrameTXXlation ) &&
          ( 0 == tlMetaInfo.ucBcast ) &&
          ( 0 == tlMetaInfo.ucMcast )
#ifdef FEATURE_WLAN_WAPI
          && ( tlMetaInfo.ucIsWai != 1 )
#endif
        )
     {
#ifdef WLAN_PERF 
        v_U32_t uFastFwdOK = 0;

        /* HW based translation. See if the frame could be fast forwarded */
        WDA_TLI_FastHwFwdDataFrame( pvosGCtx, vosDataBuff , &vosStatus, 
                                   &uFastFwdOK, &tlMetaInfo, &pStaClient->wSTADesc);

        if( VOS_STATUS_SUCCESS == vosStatus )
        {
            if(uFastFwdOK)
            {
                /* Packet could be fast forwarded now */
                vos_pkt_set_user_data_ptr( vosDataBuff, VOS_PKT_USER_DATA_ID_TL, 
                               (v_PVOID_t)pStaClient->pfnSTATxComp );

                *pvosDataBuff = vosDataBuff;

                /* TODO: Do we really need to update WLANTL_HSHandleTXFrame() 
                   stats for every pkt? */
                pStaClient->auTxCount[tlMetaInfo.ucTID]++;
                return vosStatus;
             }
             /* can't be fast forwarded, fall through normal (slow) path. */
        }
        else
        {

            TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                       "WLAN TL:Failed while attempting to fastFwd BD %d", vosStatus));
            *pvosDataBuff = NULL;
            return vosStatus;
        }
#endif /*WLAN_PERF*/
     }
     else
     {
        /* SW based translation */

       vosStatus =  WLANTL_Translate8023To80211Header( vosDataBuff, &vosStatus,
                                                    pTLCb, &ucSTAId,
                                                    &tlMetaInfo, &ucWDSEnabled,
                                                    &extraHeadSpace);
       if ( VOS_STATUS_SUCCESS != vosStatus )
       {
          TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                    "WLAN TL:Error when translating header WLANTL_STATxAuth"));
          return vosStatus;
       }

       TLLOG4(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,
                    "WLAN TL software translation success"));
       ucSwFrmXtl = 1;
       tlMetaInfo.ucDisableFrmXtl = 1;
    }
  }
#ifdef FEATURE_WLAN_TDLS
    /*In case of TDLS, if the packet is destined to TDLS STA ucSTAId may
      change. so update the pStaClient accordingly */
    pStaClient = pTLCb->atlSTAClients[ucSTAId];

    if ( NULL == pStaClient )
    {
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
        "pStaClient is NULL %s", __func__));
        return VOS_STATUS_E_FAILURE;
    }
#endif
  /*-------------------------------------------------------------------------
    Call HAL to fill BD header
   -------------------------------------------------------------------------*/
  ucTypeSubtype |= (WLANTL_80211_DATA_TYPE << 4);

  if ( pStaClient->wSTADesc.ucQosEnabled ) 
  {
    ucTypeSubtype |= (WLANTL_80211_DATA_QOS_SUBTYPE);
  }

  /* ucAC now points to TL Q ID with a new queue added in TL,
   * hence look for the uapsd info for the correct AC that
   * this packet belongs to.
   */
  ucTxFlag  = (0 != pStaClient->wUAPSDInfo[tlMetaInfo.ac].ucSet)?
              HAL_TRIGGER_ENABLED_AC_MASK:0;

#ifdef FEATURE_WLAN_WAPI
  if ( pStaClient->wSTADesc.ucIsWapiSta == 1 )
  {
#ifdef LIBRA_WAPI_SUPPORT
    ucTxFlag = ucTxFlag | HAL_WAPI_STA_MASK;
#endif //LIBRA_WAPI_SUPPORT
    if ( tlMetaInfo.ucIsWai == 1 ) 
    {
      ucTxFlag = ucTxFlag | HAL_TX_NO_ENCRYPTION_MASK;
    }
  }
#endif /* FEATURE_WLAN_WAPI */
#ifdef FEATURE_WLAN_TDLS
  if ( pStaClient->wSTADesc.wSTAType == WLAN_STA_TDLS )
  {
    ucTxFlag = ucTxFlag | HAL_TDLS_PEER_STA_MASK;
  }
#endif /* FEATURE_WLAN_TDLS */
  if( tlMetaInfo.ucIsArp )
  {
    if (pTLCb->track_arp)
    {
       if (vos_check_arp_target_ip(vosDataBuff))
       {
          ucTxFlag |= HAL_USE_FW_IN_TX_PATH;
          ucTxFlag |= HAL_TXCOMP_REQUESTED_MASK;
          tlMetaInfo.ucTxBdToken = ++ pTLCb->txbd_token;
       }
    }

    if (pStaClient->arpOnWQ5)
    {
        ucTxFlag |= HAL_USE_FW_IN_TX_PATH;
    }
    if (pStaClient->arpRate == 0)
    {
        ucTxFlag |= HAL_USE_BD_RATE_1_MASK;
    }
    else if (pStaClient->arpRate == 1 || pStaClient->arpRate == 3)
    {
        pStaClient->arpRate ^= 0x2;
        ucTxFlag |= HAL_USE_BD_RATE_1_MASK<<(pStaClient->arpRate-1);
    }
    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
           "arp pkt sending on BD rate: %hhu", pStaClient->arpRate));
  }

  vosStatus = (VOS_STATUS)WDA_DS_BuildTxPacketInfo( pvosGCtx, 
                     vosDataBuff , &vDestMacAddr,
                     tlMetaInfo.ucDisableFrmXtl, &usPktLen,
                     pStaClient->wSTADesc.ucQosEnabled, ucWDSEnabled, 
                     extraHeadSpace,
                     ucTypeSubtype, &pStaClient->wSTADesc.vSelfMACAddress,
                     ucTid, ucTxFlag, tlMetaInfo.usTimeStamp, 
                     tlMetaInfo.ucIsEapol, tlMetaInfo.ucIsArp, tlMetaInfo.ucUP,
                     tlMetaInfo.ucTxBdToken);

  if(!VOS_IS_STATUS_SUCCESS(vosStatus))
  {
    TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "Fill TX BD Error status %d", vosStatus));

    return vosStatus;
  }

  /* TX Statistics */
  if (!(tlMetaInfo.ucBcast || tlMetaInfo.ucMcast))
  {
    /* This is TX UC frame */
    pStaClient->trafficStatistics.txUCFcnt++;
    pStaClient->trafficStatistics.txUCBcnt += usPktLen;
  }

#ifndef FEATURE_WLAN_TDLS
  /*-----------------------------------------------------------------------
    Update tx counter for BA session query for tx side
    -----------------------------------------------------------------------*/
  pStaClient->auTxCount[ucTid]++;
#else
  pTLCb->atlSTAClients[ucSTAId]->auTxCount[ucTid]++;
#endif

  /* This code is to send traffic with lower priority AC when we does not 
     get admitted to send it. Today HAL does not downgrade AC so this code 
     does not get executed.(In other words, HAL doesn’t change tid. The if 
     statement is always false.)
     NOTE: In the case of LA downgrade occurs in HDD (that was the change 
     Phani made during WMM-AC plugfest). If WM & BMP also took this approach, 
     then there will be no need for any AC downgrade logic in TL/WDI.   */
#if 0
  if (( ucTid != tlMetaInfo.ucTID ) &&
      ( 0 != pStaClient->wSTADesc.ucQosEnabled ) && 
      ( 0 != ucSwFrmXtl ))
  {
    /*---------------------------------------------------------------------
      !! FIX me: Once downgrading is clear put in the proper change
    ---------------------------------------------------------------------*/
    ucQCOffset = WLANHAL_TX_BD_HEADER_SIZE + WLANTL_802_11_HEADER_LEN;

    //!!!Fix this replace peek with extract 
    vos_pkt_peek_data( vosDataBuff, ucQCOffset,(v_PVOID_t)&pucQosCtrl,
                       sizeof(*pucQosCtrl));
    *pucQosCtrl = ucTid; //? proper byte order
  }
#endif

  if ( VOS_STATUS_SUCCESS != vosStatus )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Failed while attempting to fill BD %d", vosStatus));
    *pvosDataBuff = NULL;
    return vosStatus;
  }

  vos_pkt_set_user_data_ptr( vosDataBuff, VOS_PKT_USER_DATA_ID_TL,
                   (v_PVOID_t)pStaClient->pfnSTATxComp );

  *pvosDataBuff = vosDataBuff;

  /*BE & BK can be delayed, VO and VI not frames cannot be delayed*/
  if ( pStaClient->ucServicedAC > WLANTL_AC_BE ) 
  {
    pTLCb->bUrgent= TRUE;
  }

  return VOS_STATUS_SUCCESS;
}/* WLANTL_STATxAuth */

/*==========================================================================
  FUNCTION    WLANTL_STATxDisc

  DESCRIPTION
    Transmit in disconnected state - no data allowed

  DEPENDENCIES
    The STA must be registered with TL before this function can be called.

  PARAMETERS

   IN
   pvosGCtx:       pointer to the global vos context; a handle to TL's
                   control block can be extracted from its context
   ucSTAId:        identifier of the station being processed
   vosDataBuff:   pointer to the tx vos buffer

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_STATxDisc
(
  v_PVOID_t     pvosGCtx,
  v_U8_t        ucSTAId,
  vos_pkt_t**   pvosDataBuff,
  v_BOOL_t      bForwardIAPPwithLLC
)
{
   WLANTL_CbType*        pTLCb       = NULL;
   WLANTL_STAClientType* pClientSTA = NULL;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
     TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_STATxAuth"));
    *pvosDataBuff = NULL;
    return VOS_STATUS_E_FAULT;
  }

  pClientSTA = pTLCb->atlSTAClients[ucSTAId];

  if ( NULL == pClientSTA )
  {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Client Memory was not allocated on %s", __func__));
      return VOS_STATUS_E_FAILURE;
  }

  /*------------------------------------------------------------------------
    Error
   ------------------------------------------------------------------------*/
  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
    "WLAN TL:Packet should not be transmitted in state disconnected ignoring"
            " request"));

  *pvosDataBuff = NULL;
   pClientSTA->ucNoMoreData = 1;
   
   //Should not be anything pending in disconnect state
   vos_atomic_set_U8( &pClientSTA->ucPktPending, 0);

  return VOS_STATUS_SUCCESS;
}/* WLANTL_STATxDisc */

/*==========================================================================
  FUNCTION    WLANTL_STARxConn

  DESCRIPTION
    Receive in connected state - only EAPOL

  DEPENDENCIES
    The STA must be registered with TL before this function can be called.

  PARAMETERS

   IN
   pvosGCtx:       pointer to the global vos context; a handle to TL's
                   control block can be extracted from its context
   ucSTAId:        identifier of the station being processed
   vosDataBuff:   pointer to the tx/rx vos buffer

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:   invalid input parameters
    VOS_STATUS_E_FAULT:   pointer to TL cb is NULL ; access would cause a
                          page fault
    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_STARxConn
(
  v_PVOID_t     pvosGCtx,
  v_U8_t        ucSTAId,
  vos_pkt_t**   pvosDataBuff,
  v_BOOL_t      bForwardIAPPwithLLC
)
{
   WLANTL_CbType*           pTLCb = NULL;
   WLANTL_STAClientType*    pClientSTA = NULL;
   v_U16_t                  usEtherType = 0;
   v_U16_t                  usPktLen;
   v_U8_t                   ucMPDUHOffset;
   v_U16_t                  usMPDUDOffset;
   v_U16_t                  usMPDULen;
   v_U8_t                   ucMPDUHLen;
   v_U16_t                  usActualHLen = 0;
   VOS_STATUS               vosStatus  = VOS_STATUS_SUCCESS;
   vos_pkt_t*               vosDataBuff;
   v_PVOID_t                aucBDHeader;
   v_U8_t                   ucTid;
   WLANTL_RxMetaInfoType    wRxMetaInfo;
   v_U8_t                   ucAsf; /* AMSDU sub frame */
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if (( NULL == pvosDataBuff ) || ( NULL == ( vosDataBuff = *pvosDataBuff )))
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid parameter sent on WLANTL_STARxConn"));
    return VOS_STATUS_E_INVAL;
  }

  /*------------------------------------------------------------------------
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
        "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_ChangeSTAState"));
    return VOS_STATUS_E_FAULT;
  }
  pClientSTA = pTLCb->atlSTAClients[ucSTAId];

  if ( NULL == pClientSTA )
  {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Client Memory was not allocated on %s", __func__));
      return VOS_STATUS_E_FAILURE;
  }

  /*------------------------------------------------------------------------
    Extract BD header and check if valid
   ------------------------------------------------------------------------*/
  vosStatus = WDA_DS_PeekRxPacketInfo( vosDataBuff, (v_PVOID_t)&aucBDHeader, 0/*Swap BD*/ );

  if ( NULL == aucBDHeader )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Cannot extract BD header"));
    VOS_ASSERT( 0 );
    return VOS_STATUS_E_FAULT;
  }


  ucMPDUHOffset = (v_U8_t)WDA_GET_RX_MPDU_HEADER_OFFSET(aucBDHeader);
  usMPDUDOffset = (v_U16_t)WDA_GET_RX_MPDU_DATA_OFFSET(aucBDHeader);
  usMPDULen     = (v_U16_t)WDA_GET_RX_MPDU_LEN(aucBDHeader);
  ucMPDUHLen    = (v_U8_t)WDA_GET_RX_MPDU_HEADER_LEN(aucBDHeader);
  ucTid         = (v_U8_t)WDA_GET_RX_TID(aucBDHeader);
  ucAsf         = (v_U8_t)WDA_GET_RX_ASF(aucBDHeader);

  vos_pkt_get_packet_length( vosDataBuff, &usPktLen);

  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL:BD header processing data: HO %d DO %d Len %d HLen %d",
             ucMPDUHOffset, usMPDUDOffset, usMPDULen, ucMPDUHLen));

    /*It will cut out the 802.11 header if not used*/
  if ( VOS_STATUS_SUCCESS != WDA_DS_TrimRxPacketInfo( vosDataBuff ) )
  {
    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
               "WLAN TL:BD header corrupted - dropping packet"));
    /* Drop packet */
    vos_pkt_return_packet(vosDataBuff);
    return VOS_STATUS_SUCCESS;
  }

  if (ucAsf) {
    vos_pkt_return_packet(vosDataBuff);
    *pvosDataBuff = NULL;
    VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "WLAN TL: AMSDU frames are not allowed while authentication - dropping");
    return VOS_STATUS_SUCCESS;
  }

  vosStatus = WLANTL_GetEtherType(aucBDHeader,vosDataBuff,ucMPDUHLen,&usEtherType);
  
  if( VOS_IS_STATUS_SUCCESS(vosStatus) )
  {
#ifdef FEATURE_WLAN_WAPI
    /* If frame is neither an EAPOL frame nor a WAI frame then we drop the frame*/
    /* TODO: Do we need a check to see if we are in WAPI mode? If not is it possible */
    /* that we get an EAPOL packet in WAPI mode or vice versa? */
    if ( WLANTL_LLC_8021X_TYPE  != usEtherType && WLANTL_LLC_WAI_TYPE  != usEtherType )
    {
      VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
                 "WLAN TL:RX Frame not EAPOL or WAI EtherType %d - dropping", usEtherType );
      /* Drop packet */
      vos_pkt_return_packet(vosDataBuff);
    }
#else
    if ( WLANTL_LLC_8021X_TYPE  != usEtherType )
    {
      VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                 "WLAN TL:RX Frame not EAPOL EtherType %d - dropping", usEtherType);
      /* Drop packet */
      vos_pkt_return_packet(vosDataBuff);
    }
#endif /* FEATURE_WLAN_WAPI */
    else /* Frame is an EAPOL frame or a WAI frame*/  
    {
      MTRACE(vos_trace(VOS_MODULE_ID_TL,
                   TRACE_CODE_TL_RX_CONN_EAPOL, ucSTAId, usEtherType ));

      VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
                 "WLAN TL:RX Frame  EAPOL EtherType %d - processing", usEtherType);

      if (( 0 == WDA_GET_RX_FT_DONE(aucBDHeader) ) &&
         ( 0 != pClientSTA->wSTADesc.ucSwFrameRXXlation))
      {
      if (usMPDUDOffset > ucMPDUHOffset)
      {
         usActualHLen = usMPDUDOffset - ucMPDUHOffset;
      }

      vosStatus = WLANTL_Translate80211To8023Header( vosDataBuff, &vosStatus, usActualHLen, 
                      ucMPDUHLen, pTLCb, ucSTAId, bForwardIAPPwithLLC);

        if ( VOS_STATUS_SUCCESS != vosStatus ) 
        {
          TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
            "WLAN TL:Failed to translate from 802.11 to 802.3 - dropping"));
          /* Drop packet */
          vos_pkt_return_packet(vosDataBuff);
          return vosStatus;
        }
      }
      /*-------------------------------------------------------------------
      Increment receive counter
      -------------------------------------------------------------------*/
      if ( !WLANTL_TID_INVALID( ucTid) ) 
      {
        pClientSTA->auRxCount[ucTid]++;
      }
      else
      {
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid tid  %d (Station ID %d) on %s",
               ucTid, ucSTAId, __func__));
        vos_pkt_return_packet(vosDataBuff);
        return VOS_STATUS_E_FAILURE;
      }

      TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
               "WLAN TL:Sending EAPoL frame to station %d AC %d", ucSTAId, ucTid));

      /*-------------------------------------------------------------------
      !!!Assuming TID = UP mapping 
      -------------------------------------------------------------------*/
      wRxMetaInfo.ucUP = ucTid;

      TLLOG4(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,
               "WLAN TL %s:Sending data chain to station", __func__));
      if ( WLAN_STA_SOFTAP == pClientSTA->wSTADesc.wSTAType )
      {
        wRxMetaInfo.ucDesSTAId = WLAN_RX_SAP_SELF_STA_ID;
        pClientSTA->pfnSTARx( pvosGCtx, vosDataBuff, ucSTAId,
                                            &wRxMetaInfo );
      }
      else
      pClientSTA->pfnSTARx( pvosGCtx, vosDataBuff, ucSTAId,
                                            &wRxMetaInfo );
    }/*EAPOL frame or WAI frame*/
  }/*vos status success*/

  return VOS_STATUS_SUCCESS;
}/* WLANTL_STARxConn */

/*==========================================================================
  FUNCTION    WLANTL_FwdPktToHDD

  DESCRIPTION
    Determine the Destation Station ID and route the Frame to Upper Layer

  DEPENDENCIES

  PARAMETERS

   IN
   pvosGCtx:       pointer to the global vos context; a handle to TL's
                   control block can be extracted from its context
   ucSTAId:        identifier of the station being processed
   vosDataBuff:   pointer to the rx vos buffer

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:   invalid input parameters
    VOS_STATUS_E_FAULT:   pointer to TL cb is NULL ; access would cause a
                          page fault
    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

============================================================================*/

VOS_STATUS
WLANTL_FwdPktToHDD
(
  v_PVOID_t       pvosGCtx,
  vos_pkt_t*     pvosDataBuff,
  v_U8_t          ucSTAId
)
{
   v_MACADDR_t              DestMacAddress;
   v_MACADDR_t              *pDestMacAddress = &DestMacAddress;
   v_SIZE_t                 usMacAddSize = VOS_MAC_ADDR_SIZE;
   WLANTL_CbType*           pTLCb = NULL;
   WLANTL_STAClientType*    pClientSTA = NULL;
   vos_pkt_t*               vosDataBuff ;
   VOS_STATUS               vosStatus = VOS_STATUS_SUCCESS;
   v_U32_t*                 STAMetaInfoPtr;
   vos_pkt_t*               vosNextDataBuff ;
   v_U8_t                   ucDesSTAId;
   WLANTL_RxMetaInfoType    wRxMetaInfo;

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if (( NULL == pvosDataBuff ) || ( NULL == ( vosDataBuff = pvosDataBuff )))
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "WLAN TL:Invalid parameter sent on WLANTL_FwdPktToHdd"));
    return VOS_STATUS_E_INVAL;
  }

  /*------------------------------------------------------------------------
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_FwdPktToHdd"));
    return VOS_STATUS_E_FAULT;
  }

  if(WLANTL_STA_ID_INVALID(ucSTAId))
  {
     TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"ucSTAId %d is not valid",
                 ucSTAId));
     return VOS_STATUS_E_INVAL;
  }

  pClientSTA = pTLCb->atlSTAClients[ucSTAId];

  if ( NULL == pClientSTA )
  {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Client Memory was not allocated on %s", __func__));
      return VOS_STATUS_E_FAILURE;
  }

   /* This the change required for SoftAp to handle Reordered Buffer. Since a STA
      may have packets destined to multiple destinations we have to process each packet
      at a time and determine its Destination. So the Voschain provided by Reorder code
      is unchain and forwarded to Upper Layer after Determining the Destination */

   vosDataBuff = pvosDataBuff;
   while (vosDataBuff != NULL)
   {
      vos_pkt_walk_packet_chain( vosDataBuff, &vosNextDataBuff, 1/*true*/ );
      vos_pkt_get_user_data_ptr( vosDataBuff, VOS_PKT_USER_DATA_ID_TL,
                                 (v_PVOID_t *)&STAMetaInfoPtr );
      wRxMetaInfo.ucUP = (v_U8_t)((uintptr_t)STAMetaInfoPtr & WLANTL_AC_MASK);
      ucDesSTAId = (v_U8_t)(((uintptr_t)STAMetaInfoPtr) >> WLANTL_STAID_OFFSET);
       
      vosStatus = vos_pkt_extract_data( vosDataBuff, 0, (v_VOID_t *)pDestMacAddress, &usMacAddSize);
      if ( VOS_STATUS_SUCCESS != vosStatus )
      {
         TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                "WLAN TL: recv corrupted data packet"));
         vos_pkt_return_packet(vosDataBuff);
         return vosStatus;
      }

      TLLOG4(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,
                        "station mac "MAC_ADDRESS_STR,
                        MAC_ADDR_ARRAY(pDestMacAddress->bytes)));

      if (vos_is_macaddr_broadcast( pDestMacAddress ) || vos_is_macaddr_group(pDestMacAddress))
      {
          // destination is mc/bc station
          ucDesSTAId = WLAN_RX_BCMC_STA_ID;
          TLLOG4(VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO_LOW,
                    "%s: BC/MC packet, id %d", __func__, WLAN_RX_BCMC_STA_ID));
      }
      else
      {
         if (vos_is_macaddr_equal(pDestMacAddress, &pClientSTA->wSTADesc.vSelfMACAddress))
         {
            // destination is AP itself
            ucDesSTAId = WLAN_RX_SAP_SELF_STA_ID;
            TLLOG4(VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO_LOW,
                     "%s: packet to AP itself, id %d", __func__, WLAN_RX_SAP_SELF_STA_ID));
         }
         else if (( WLAN_MAX_STA_COUNT <= ucDesSTAId ) || (NULL != pTLCb->atlSTAClients[ucDesSTAId] && pTLCb->atlSTAClients[ucDesSTAId]->ucExists == 0))
         {
            // destination station is something else
            TLLOG4(VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO_LOW,
                 "%s: get an station index larger than WLAN_MAX_STA_COUNT %d", __func__, ucDesSTAId));
            ucDesSTAId = WLAN_RX_SAP_SELF_STA_ID;
         }

         
         //loopback unicast station comes here
      }

      wRxMetaInfo.ucUP = (v_U8_t)((uintptr_t)STAMetaInfoPtr & WLANTL_AC_MASK);
      wRxMetaInfo.ucDesSTAId = ucDesSTAId;
     
      vosStatus = pClientSTA->pfnSTARx( pvosGCtx, vosDataBuff, ucDesSTAId,
                                            &wRxMetaInfo );
      if ( VOS_STATUS_SUCCESS != vosStatus )
      {
          TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                "WLAN TL: failed to send pkt to HDD"));
          vos_pkt_return_packet(vosDataBuff);

          return vosStatus;
      }
      vosDataBuff = vosNextDataBuff;
   }
   return VOS_STATUS_SUCCESS;
}

#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
void WLANTL_StopRxRateMonitor(v_PVOID_t pvosGCtx)
{
   WLANTL_CbType *pTLCb = VOS_GET_TL_CB(pvosGCtx);
   if (!pTLCb)
     return;
   pTLCb->gDsRxRoamStats.running = eWLAN_PAL_FALSE;
}

void WLANTL_StartRxRateMonitor(v_PVOID_t pvosGCtx, v_U8_t staId,
                  v_U16_t minRate,
                  v_U16_t maxRate, v_U8_t minPercentage,
                  v_U16_t minPktRequired, void *hHal,
                  v_U64_t timeToWait,
                  void (*triggerRoamScanfn) (void *, v_U8_t))
{

   WLANTL_CbType *pTLCb = VOS_GET_TL_CB(pvosGCtx);
   if (!pTLCb)
     return;

   pTLCb->gDsRxRoamStats.running = eWLAN_PAL_TRUE;
   pTLCb->gDsRxRoamStats.index = 0;
   pTLCb->gDsRxRoamStats.lastTriggerTime = jiffies_to_msecs(jiffies);
   pTLCb->gDsRxRoamStats.maxRate = maxRate;
   pTLCb->gDsRxRoamStats.minRate = minRate;
   pTLCb->gDsRxRoamStats.staId = staId;
   pTLCb->gDsRxRoamStats.minPercentage = minPercentage;
   pTLCb->gDsRxRoamStats.timeToWait = timeToWait * 1000;
   pTLCb->gDsRxRoamStats.intialPktToStart = 0;
   pTLCb->gDsRxRoamStats.minPktRequired = minPktRequired;
   pTLCb->gDsRxRoamStats.triggerRoamScanfn = triggerRoamScanfn;
   pTLCb->gDsRxRoamStats.hHal = hHal;
   vos_mem_zero(pTLCb->gDsRxRoamStats.rxRoamStats, ROAM_MAX_INDEX_NUM *
                                sizeof(WLANTL_RoamTrafficStatsType));
   VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_DEBUG,
       "staId=%d, minRate=%d maxRate=%d minPercentage=%d minPktRequired=%d",
       staId, minRate, maxRate, minPercentage, minPktRequired);
}

void static WLANTL_ClearAllRoamStats(WLANTL_CbType *pTLCb)
{
   pTLCb->gDsRxRoamStats.index = 0;
   pTLCb->gDsRxRoamStats.totalPkt = 0;
   pTLCb->gDsRxRoamStats.lowRatePkt = 0;
   pTLCb->gDsRxRoamStats.intialPktToStart = 0;
   vos_mem_zero(pTLCb->gDsRxRoamStats.rxRoamStats, ROAM_MAX_INDEX_NUM *
                                sizeof(WLANTL_RoamTrafficStatsType));
}

/*
 * WLANTL_ClearRoamStatsTillIndex : This API will clear older data
 * at the indexes.
 *
 * Since its a circular buffer we don't know if we are filling
 * data first time or some older data was already present at
 * the index. In that case we should clear the older data from
 * current index to new index and subtract this data from
 * global count as well before filling new one.
 */
static inline void WLANTL_ClearRoamStatsTillIndex(WLANTL_CbType *pTLCb,
                                           v_U8_t newIndex)
{
   while (pTLCb->gDsRxRoamStats.index < newIndex)
   {
     pTLCb->gDsRxRoamStats.index++;
     pTLCb->gDsRxRoamStats.totalPkt -=
         pTLCb->gDsRxRoamStats.
             rxRoamStats[pTLCb->gDsRxRoamStats.index].totalPktRcvd;
     pTLCb->gDsRxRoamStats.lowRatePkt -=
         pTLCb->gDsRxRoamStats.
             rxRoamStats[pTLCb->gDsRxRoamStats.index].lowRateRxPacketsRcvd;
     pTLCb->gDsRxRoamStats.
         rxRoamStats[pTLCb->gDsRxRoamStats.index].totalPktRcvd = 0;
     pTLCb->gDsRxRoamStats.
         rxRoamStats[pTLCb->gDsRxRoamStats.index].lowRateRxPacketsRcvd = 0;
   }
}


static void WLANTL_ClearOldPERStats(WLANTL_CbType *pTLCb, v_U8_t incrementCnt)
{
   v_U8_t newIndex;

   newIndex = (pTLCb->gDsRxRoamStats.index + incrementCnt) %
                                             ROAM_MAX_INDEX_NUM;

   /* We have crossed the max limit of buffer, clear the stats
    * till ROAM_MAX_INDEX_NUM and set index as 0 */
   if ((pTLCb->gDsRxRoamStats.index + incrementCnt) >=
                                             ROAM_MAX_INDEX_NUM)
   {
       WLANTL_ClearRoamStatsTillIndex(pTLCb, ROAM_MAX_INDEX_NUM - 1);
       pTLCb->gDsRxRoamStats.index = -1;
   }
   /* Clear the stats from current index till new index */
   WLANTL_ClearRoamStatsTillIndex(pTLCb, newIndex);
}

/*
 * This API implements a circular buffer to store rate stats for a station to
 * trigger PER based roam scan.
 * API will start monitoring only if DUT gets continues packets which are below
 * configured rate. In the upper rates, this should have minimal effect on data
 * throughput.
 *
 * This API will store stats in a circular buffer of size ROAM_MAX_INDEX_NUM
 * where each index will have time duration of ROAM_PER_INDEX_TIME.
 * Using a buffer instead of counter will help to maintain stats of time
 * duration ROAM_PER_INDEX_TIME * ROAM_MAX_INDEX_NUM. Whenever host gets a new
 * packet, it will remove last ROAM_PER_INDEX_TIME duration of packets from
 * global entry and index entry and fill new data.
 *
 * Global stats of data also be maintained so that host need not to parse whole
 * buffer while checking the trigger condition
 * Each of the index will be having the packets stats at duration of
 * ROAM_PER_INDEX_TIME from the first packet which arrived in that.
 * Global index will be used to calculate new index position to fill once host
 * gets a packet.
 */
static void WLANTL_updatePERStats(WLANTL_CbType *pTLCb,
                                  v_U8_t rateIndex)
{
   v_U8_t incrementCnt = 0;
   v_U64_t currentTime, timeDifference;

   /*
    * Host will start monitoring Rx rates only if it gets
    * MIN_PKTS_TO_START_MONTIOR number of pkts continuously below min rate
    * This will make sure we never do this much processing in high
    * rates/throughput cases
    */

   if(pTLCb->gDsRxRoamStats.intialPktToStart < MIN_PKTS_TO_START_MONTIOR)
   {
       if (gTLRateInfo[rateIndex].phyRate < pTLCb->gDsRxRoamStats.minRate)
          pTLCb->gDsRxRoamStats.intialPktToStart++;
       else
          pTLCb->gDsRxRoamStats.intialPktToStart = 0;
       return;
   }

   currentTime = jiffies_to_msecs(jiffies);
   /*
    * scan was triggered in last timeToWait time duration
    * Wait for timeToWait before monitoring again.
    */
   if((currentTime - pTLCb->gDsRxRoamStats.lastTriggerTime) <
       pTLCb->gDsRxRoamStats.timeToWait)
       return;

   /* paket above max rate, clear current stats and montior again */
   if (gTLRateInfo[rateIndex].phyRate >=
           pTLCb->gDsRxRoamStats.maxRate)
   {
       WLANTL_ClearAllRoamStats(pTLCb);
       /* Stop any PER based scan if going on */
       pTLCb->gDsRxRoamStats.
                  triggerRoamScanfn(pTLCb->gDsRxRoamStats.hHal, 0);
       return;
   }

   timeDifference = currentTime -
       pTLCb->gDsRxRoamStats.rxRoamStats[pTLCb->gDsRxRoamStats.index].time;

   if (timeDifference)
       incrementCnt = do_div(timeDifference, ROAM_PER_INDEX_TIME);

   /* More that ROAM_PER_INDEX_TIME has esclapsed,
    * fill data at new index */
   if (incrementCnt)
   {
       if (incrementCnt > ROAM_MAX_INDEX_NUM)
       {
           /*
            * Clear all stats, these are older than
            * ROAM_MAX_INDEX_NUM * ROAM_PER_INDEX_TIME (Max buffer time)
            */
           WLANTL_ClearAllRoamStats(pTLCb);
           pTLCb->gDsRxRoamStats.index = 0;
       }
       else
           WLANTL_ClearOldPERStats(pTLCb, incrementCnt);

       pTLCb->gDsRxRoamStats.rxRoamStats
                    [pTLCb->gDsRxRoamStats.index].time = currentTime;
   }

   /* If pkt rate below minRate, increment low pkts counts */
   if (gTLRateInfo[rateIndex].phyRate <
           pTLCb->gDsRxRoamStats.minRate)
   {
       pTLCb->gDsRxRoamStats.
           rxRoamStats[pTLCb->gDsRxRoamStats.index].
               lowRateRxPacketsRcvd++;
       pTLCb->gDsRxRoamStats.lowRatePkt++;
   }
   /* Increment total pkts counts */
   pTLCb->gDsRxRoamStats.
           rxRoamStats[pTLCb->gDsRxRoamStats.index].totalPktRcvd++;
   pTLCb->gDsRxRoamStats.totalPkt++;

   /* Check if we have reached threshold value to trigger a roam scan */
   if ((pTLCb->gDsRxRoamStats.totalPkt != 0) &&
       (pTLCb->gDsRxRoamStats.totalPkt >
                pTLCb->gDsRxRoamStats.minPktRequired)&&
       ((pTLCb->gDsRxRoamStats.lowRatePkt * 100) >
                (pTLCb->gDsRxRoamStats.totalPkt *
       pTLCb->gDsRxRoamStats.minPercentage)))
   {
       /* callback handler to trigger a roam scan */
       if (pTLCb->gDsRxRoamStats.triggerRoamScanfn)
           pTLCb->gDsRxRoamStats.
                   triggerRoamScanfn(pTLCb->gDsRxRoamStats.hHal, 1);

       VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_DEBUG,
           "PER Roam: triggerring roam scan totalPkt =%lu lowRatePkt %lu minPktRequired %u minPercentage %d",
           (long unsigned int) pTLCb->gDsRxRoamStats.totalPkt,
           (long unsigned int) pTLCb->gDsRxRoamStats.lowRatePkt,
           (unsigned int) pTLCb->gDsRxRoamStats.minPktRequired,
           pTLCb->gDsRxRoamStats.minPercentage);

       WLANTL_ClearAllRoamStats(pTLCb);
       /*  save current time as last trigger time */
       pTLCb->gDsRxRoamStats.lastTriggerTime = currentTime;
   }
}
#endif

/*==========================================================================
  FUNCTION    WLANTL_STARxAuth

  DESCRIPTION
    Receive in authenticated state - all data allowed

  DEPENDENCIES
    The STA must be registered with TL before this function can be called.

  PARAMETERS

   IN
   pvosGCtx:       pointer to the global vos context; a handle to TL's
                   control block can be extracted from its context
   ucSTAId:        identifier of the station being processed
   vosDataBuff:   pointer to the rx vos buffer

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:   invalid input parameters
    VOS_STATUS_E_FAULT:   pointer to TL cb is NULL ; access would cause a
                          page fault
    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_STARxAuth
(
  v_PVOID_t     pvosGCtx,
  v_U8_t        ucSTAId,
  vos_pkt_t**   pvosDataBuff,
  v_BOOL_t      bForwardIAPPwithLLC
)
{
   WLANTL_CbType*           pTLCb = NULL;
   WLANTL_STAClientType*    pClientSTA = NULL;
   v_U8_t                   ucAsf; /* AMSDU sub frame */
   v_U16_t                  usMPDUDOffset;
   v_U8_t                   ucMPDUHOffset;
   v_U16_t                  usMPDULen;
   v_U8_t                   ucMPDUHLen;
   v_U16_t                  usActualHLen = 0;   
   v_U8_t                   ucTid;
#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
   v_U8_t                   rxRate;
   v_U8_t                   type;
#endif
#ifdef FEATURE_WLAN_WAPI
   v_U16_t                  usEtherType = 0;
   tSirMacMgmtHdr           *hdr;
#endif
   v_U16_t                  usPktLen;
   vos_pkt_t*               vosDataBuff ;
   v_PVOID_t                aucBDHeader;
   VOS_STATUS               vosStatus;
   WLANTL_RxMetaInfoType    wRxMetaInfo;
   static v_U8_t            ucPMPDUHLen;
   v_U32_t*                 STAMetaInfoPtr;
   v_U8_t                   ucEsf=0; /* first subframe of AMSDU flag */
   v_U64_t                  ullcurrentReplayCounter=0; /*current replay counter*/
   v_U64_t                  ullpreviousReplayCounter=0; /*previous replay counter*/
   v_U16_t                  ucUnicastBroadcastType=0; /*It denotes whether received frame is UC or BC*/
   struct _BARFrmStruct     *pBarFrame = NULL;

  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if (( NULL == pvosDataBuff ) || ( NULL == ( vosDataBuff = *pvosDataBuff )))
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "WLAN TL:Invalid parameter sent on WLANTL_STARxAuth"));
    return VOS_STATUS_E_INVAL;
  }

  /*------------------------------------------------------------------------
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_STARxAuth"));
    return VOS_STATUS_E_FAULT;
  }
  pClientSTA = pTLCb->atlSTAClients[ucSTAId];

  if ( NULL == pClientSTA )
  {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Client Memory was not allocated on %s", __func__));
      return VOS_STATUS_E_FAILURE;
  }

  /*------------------------------------------------------------------------
    Extract BD header and check if valid
   ------------------------------------------------------------------------*/
  WDA_DS_PeekRxPacketInfo( vosDataBuff, (v_PVOID_t)&aucBDHeader, 0 );

  ucMPDUHOffset = (v_U8_t)WDA_GET_RX_MPDU_HEADER_OFFSET(aucBDHeader);
  usMPDUDOffset = (v_U16_t)WDA_GET_RX_MPDU_DATA_OFFSET(aucBDHeader);
  usMPDULen     = (v_U16_t)WDA_GET_RX_MPDU_LEN(aucBDHeader);
  ucMPDUHLen    = (v_U8_t)WDA_GET_RX_MPDU_HEADER_LEN(aucBDHeader);
  ucTid         = (v_U8_t)WDA_GET_RX_TID(aucBDHeader);
#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
  rxRate        = (v_U8_t)WDA_GET_RX_MAC_RATE_IDX(aucBDHeader);
  type          = (v_U8_t)WDA_GET_RX_TYPE(aucBDHeader);
#endif
  pClientSTA->rate_idx = (v_U8_t)WDA_GET_RX_MAC_RATE_IDX(aucBDHeader);

  /* Fix for a hardware bug. 
   * H/W does not update the tid field in BD header for BAR frames.
   * Fix is to read the tid field from MAC header of BAR frame */
  if( (WDA_GET_RX_TYPE(aucBDHeader) == SIR_MAC_CTRL_FRAME) &&
      (WDA_GET_RX_SUBTYPE(aucBDHeader) == SIR_MAC_CTRL_BAR))
  {
      pBarFrame = (struct _BARFrmStruct *)(WDA_GET_RX_MAC_HEADER(aucBDHeader));
      ucTid = pBarFrame->barControl.numTID;
  }

  /*Host based replay check is needed for unicast data frames*/
  ucUnicastBroadcastType  = (v_U16_t)WDA_IS_RX_BCAST(aucBDHeader);
  if(0 != ucMPDUHLen)
  {
    ucPMPDUHLen = ucMPDUHLen;
  }

  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL:BD header processing data: HO %d DO %d Len %d HLen %d"
             " Tid %d BD %d",
             ucMPDUHOffset, usMPDUDOffset, usMPDULen, ucMPDUHLen, ucTid,
             WLANHAL_RX_BD_HEADER_SIZE));

  vos_pkt_get_packet_length( vosDataBuff, &usPktLen);

  if ( VOS_STATUS_SUCCESS != WDA_DS_TrimRxPacketInfo( vosDataBuff ) )
  {
    if((WDA_GET_RX_ASF(aucBDHeader) && !WDA_GET_RX_ESF(aucBDHeader)))
  {
    /* AMSDU case, ucMPDUHOffset = 0
     * it should be hancdled seperatly */
    if(( usMPDUDOffset >  ucMPDUHOffset ) &&
       ( usMPDULen     >= ucMPDUHLen ) && ( usPktLen >= usMPDULen ) &&
       ( !WLANTL_TID_INVALID(ucTid) ))
    {
        ucMPDUHOffset = usMPDUDOffset - WLANTL_MPDU_HEADER_LEN; 
    }
    else
    {
      TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                "WLAN TL:BD header corrupted - dropping packet"));
      /* Drop packet */
      vos_pkt_return_packet(vosDataBuff);
      return VOS_STATUS_SUCCESS;
    }
  }
  else
  {
    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
              "WLAN TL:BD header corrupted - dropping packet"));
    /* Drop packet */
    vos_pkt_return_packet(vosDataBuff);
    return VOS_STATUS_SUCCESS;
  }
  }

#ifdef WLAN_FEATURE_RMC
  if (pTLCb->multicastDuplicateDetectionEnabled &&
      (WLAN_STA_IBSS == pClientSTA->wSTADesc.wSTAType) &&
       WLANTL_IS_DATA_FRAME(WDA_GET_RX_TYPE_SUBTYPE(aucBDHeader)))
  {
    /*
     * Multicast duplicate detection is only for frames received in
     * IBSS mode.
     */
    if (VOS_TRUE == WLANTL_IsDuplicateMcastFrm(pClientSTA, vosDataBuff))
    {
         pTLCb->mcastDupCnt++;
         /* Duplicate multicast data packet, drop the packet */
         vos_pkt_return_packet(vosDataBuff);
         return VOS_STATUS_SUCCESS;
    }
  }
#endif /* WLAN_FEATURE_RMC */

#ifdef FEATURE_WLAN_WAPI
  if ( pClientSTA->wSTADesc.ucIsWapiSta )
  {
    vosStatus = WLANTL_GetEtherType(aucBDHeader, vosDataBuff, ucMPDUHLen, &usEtherType);
    if( VOS_IS_STATUS_SUCCESS(vosStatus) )
    {
      if ( WLANTL_LLC_WAI_TYPE  == usEtherType )
      {
        hdr = WDA_GET_RX_MAC_HEADER(aucBDHeader);
        if ( hdr->fc.wep )
        {
          TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                     "WLAN TL:WAI frame was received encrypted - dropping"));
          /* Drop packet */
          /*Temporary fix added to fix wapi rekey issue*/
          vos_pkt_return_packet(vosDataBuff);
          return vosStatus; //returning success
        }
      }
      else
      {
        if (  WLANHAL_RX_IS_UNPROTECTED_WPI_FRAME(aucBDHeader) ) 
        {
          TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                     "WLAN TL:Non-WAI frame was received unencrypted - dropping"));
          /* Drop packet */
          vos_pkt_return_packet(vosDataBuff); 
          return vosStatus; //returning success
        }
      }
    }
    else //could not extract EtherType - this should not happen
    {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                 "WLAN TL:Could not extract EtherType"));
      //Packet is already freed
      return vosStatus; //returning failure
    }
  }
#endif /* FEATURE_WLAN_WAPI */

  /*----------------------------------------------------------------------
    Increment receive counter
    !! not sure this is the best place to increase this - pkt might be
    dropped below or delayed in TL's queues
    - will leave it here for now
   ------------------------------------------------------------------------*/
  if ( !WLANTL_TID_INVALID( ucTid) ) 
  {
    pClientSTA->auRxCount[ucTid]++;
  }
  else
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
           "WLAN TL:Invalid tid  %d (Station ID %d) on %s",
           ucTid, ucSTAId, __func__));
    vos_pkt_return_packet(vosDataBuff);
    return VOS_STATUS_E_FAILURE;
  }

#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
  if (pTLCb->gDsRxRoamStats.running &&
     (ucSTAId == pTLCb->gDsRxRoamStats.staId) &&
     (rxRate < WLANTL_MAX_RATE_NUM) && (type == SIR_MAC_DATA_FRAME))
  {
      WLANTL_updatePERStats(pTLCb, rxRate);
  }
#endif
  /*------------------------------------------------------------------------
    Check if AMSDU and send for processing if so
   ------------------------------------------------------------------------*/
  ucAsf = (v_U8_t)WDA_GET_RX_ASF(aucBDHeader);

  if ( 0 != ucAsf )
  {
    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
               "WLAN TL:Packet is AMSDU sub frame - sending for completion"));
    vosStatus = WLANTL_AMSDUProcess( pvosGCtx, &vosDataBuff, aucBDHeader, ucSTAId,
                         ucMPDUHLen, usMPDULen );
    if(NULL == vosDataBuff)
    {
       //Packet is already freed
       return VOS_STATUS_SUCCESS;
    }
  }
  /* After AMSDU header handled
   * AMSDU frame just same with normal frames */
    /*-------------------------------------------------------------------
      Translating header if necesary
       !! Fix me: rmv comments below
    ----------------------------------------------------------------------*/
  if (( 0 == WDA_GET_RX_FT_DONE(aucBDHeader) ) &&
      ( 0 != pClientSTA->wSTADesc.ucSwFrameRXXlation) &&
      ( WLANTL_IS_DATA_FRAME(WDA_GET_RX_TYPE_SUBTYPE(aucBDHeader)) ))
  {
    if(0 == ucMPDUHLen)
    {
      ucMPDUHLen = ucPMPDUHLen;
    }
    if (usMPDUDOffset > ucMPDUHOffset)
    {
      usActualHLen = usMPDUDOffset - ucMPDUHOffset;
    }
    vosStatus = WLANTL_Translate80211To8023Header( vosDataBuff, &vosStatus, usActualHLen, 
                        ucMPDUHLen, pTLCb, ucSTAId, bForwardIAPPwithLLC);

      if ( VOS_STATUS_SUCCESS != vosStatus )
      {
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
               "WLAN TL:Failed to translate from 802.11 to 802.3 - dropping"));
        /* Drop packet */
        vos_pkt_return_packet(vosDataBuff);
        return vosStatus;
      }
    }
    /* Softap requires additional Info such as Destination STAID and Access
       Category. Voschain or Buffer returned by BA would be unchain and this
       Meta Data would help in routing the packets to appropriate Destination */
    if( WLAN_STA_SOFTAP == pClientSTA->wSTADesc.wSTAType)
    {
       STAMetaInfoPtr = (v_U32_t *)(uintptr_t)(ucTid | (WDA_GET_RX_ADDR3_IDX(aucBDHeader) << WLANTL_STAID_OFFSET));
       vos_pkt_set_user_data_ptr( vosDataBuff, VOS_PKT_USER_DATA_ID_TL,
                                 (v_PVOID_t)STAMetaInfoPtr);
    }

  /* Check to see if re-ordering session is in place.
     Skip add to reorder list for TDLS packet on AP staid*/
  if (0 != pClientSTA->atlBAReorderInfo[ucTid].ucExists  &&
      !vosDataBuff->pn_replay_skip)
  {
    WLANTL_MSDUReorder( pTLCb, &vosDataBuff, aucBDHeader, ucSTAId, ucTid );
  }

if(WLANTL_IS_DATA_FRAME(WDA_GET_RX_TYPE_SUBTYPE(aucBDHeader)) &&
   (0 == ucUnicastBroadcastType)
#ifdef FEATURE_ON_CHIP_REORDERING
   && (WLANHAL_IsOnChipReorderingEnabledForTID(pvosGCtx, ucSTAId, ucTid) != TRUE)
#endif
)
{
  /* replay check code : check whether replay check is needed or not
     Skip replay check for TDLS traffic with AP sta id */
  if(VOS_TRUE == pClientSTA->ucIsReplayCheckValid)
  {
      /* replay check is needed for the station */

      /* check whether frame is AMSDU frame */
      if ( 0 != ucAsf )
      {
          /* Since virgo can't send AMSDU frames this leg of the code 
             was not tested properly, it needs to be tested properly*/
          /* Frame is AMSDU frame. As per 802.11n only first
             subframe will have replay counter */
          ucEsf =  WDA_GET_RX_ESF( aucBDHeader );
          if( 0 != ucEsf )
          {
              v_BOOL_t status;
              /* Getting 48-bit replay counter from the RX BD */
              ullcurrentReplayCounter = WDA_DS_GetReplayCounter(aucBDHeader);
 
              VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
               "WLAN TL: AMSDU currentReplayCounter [0x%llX]",ullcurrentReplayCounter);
              
              /* Getting 48-bit previous replay counter from TL control  block */
              ullpreviousReplayCounter = pClientSTA->ullReplayCounter[ucTid];

              VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
               "WLAN TL: AMSDU previousReplayCounter [0x%llX]",ullpreviousReplayCounter);

              /* It is first subframe of AMSDU thus it
                 conatains replay counter perform the
                 replay check for this first subframe*/
              status =  WLANTL_IsReplayPacket( ullcurrentReplayCounter, ullpreviousReplayCounter);
              if(VOS_FALSE == status)
              {
                   /* Not a replay paket, update previous replay counter in TL CB */    
                   pClientSTA->ullReplayCounter[ucTid] = ullcurrentReplayCounter;
              }
              else
              {
                  VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                  "WLAN TL: AMSDU Drop the replay packet with PN : [0x%llX]",ullcurrentReplayCounter);

                  pClientSTA->ulTotalReplayPacketsDetected++;
                  VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                  "WLAN TL: AMSDU total dropped replay packets on STA ID %X is [0x%X]",
                  ucSTAId,  pClientSTA->ulTotalReplayPacketsDetected);

                  /* Drop the packet */
                  vos_pkt_return_packet(vosDataBuff);
                  return VOS_STATUS_SUCCESS;
              }
          }
      }
      else
      {
           v_BOOL_t status;
           uint16_t seq_no = (uint16_t)WDA_GET_RX_REORDER_CUR_PKT_SEQ_NO(aucBDHeader);

           /* Getting 48-bit replay counter from the RX BD */
           ullcurrentReplayCounter = WDA_DS_GetReplayCounter(aucBDHeader);

           VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
             "WLAN TL: Non-AMSDU currentReplayCounter [0x%llX]",ullcurrentReplayCounter);

           /* Getting 48-bit previous replay counter from TL control  block */
           ullpreviousReplayCounter = pClientSTA->ullReplayCounter[ucTid];

           VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
               "WLAN TL: Non-AMSDU previousReplayCounter [0x%llX]",ullpreviousReplayCounter);

           /* It is not AMSDU frame so perform 
              reaply check for each packet, as
              each packet contains valid replay counter*/
           if (vosDataBuff != NULL && !vosDataBuff->pn_replay_skip) {
              if (vos_is_pkt_chain(vosDataBuff)) {
                 WLANTL_ReorderReplayCheck(pClientSTA, &vosDataBuff, ucTid);
              } else {
                 status =  WLANTL_IsReplayPacket(ullcurrentReplayCounter,
                                                 ullpreviousReplayCounter);
                 if(VOS_FALSE == status) {
                    /* Not a replay paket, update previous replay counter in TL CB */
                    pClientSTA->ullReplayCounter[ucTid] = ullcurrentReplayCounter;
                    pClientSTA->last_seq_no[ucTid] = seq_no;
                 } else {
                    VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                    "Non AMSDU Drop replay with PN: [0x%llX], prevPN: [0x%llx]"
                    " seq_no:%d last_seq_no:%d",
                    ullcurrentReplayCounter, ullpreviousReplayCounter, seq_no,
                    pClientSTA->last_seq_no[ucTid]);

                    pClientSTA->ulTotalReplayPacketsDetected++;
                    VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                    "WLAN TL: Non AMSDU total dropped replay packets on STA ID %X is [0x%X]",
                    ucSTAId,  pClientSTA->ulTotalReplayPacketsDetected);

                    /* Repaly packet, drop the packet */
                    vos_pkt_return_packet(vosDataBuff);
                    return VOS_STATUS_SUCCESS;
                 }
              }
          }
      }
   }
}

/*It is a broadast packet DPU has already done replay check for 
  broadcast packets no need to do replay check of these packets*/

  if ( NULL != vosDataBuff )
  {
    if( WLAN_STA_SOFTAP == pClientSTA->wSTADesc.wSTAType)
    {
      WLANTL_FwdPktToHDD( pvosGCtx, vosDataBuff, ucSTAId );
    }
    else
    {
      wRxMetaInfo.ucUP = ucTid;
      wRxMetaInfo.rssiAvg = pClientSTA->rssiAvg;
#ifdef FEATURE_WLAN_TDLS
      if (WLAN_STA_TDLS == pClientSTA->wSTADesc.wSTAType)
      {
          wRxMetaInfo.isStaTdls = TRUE;
      }
      else
      {
          wRxMetaInfo.isStaTdls = FALSE;
      }
#endif
      pClientSTA->pfnSTARx( pvosGCtx, vosDataBuff, ucSTAId,
                                            &wRxMetaInfo );
    }
  }/* if not NULL */

  return VOS_STATUS_SUCCESS;
}/* WLANTL_STARxAuth */


/*==========================================================================
  FUNCTION    WLANTL_STARxDisc

  DESCRIPTION
    Receive in disconnected state - no data allowed

  DEPENDENCIES
    The STA must be registered with TL before this function can be called.

  PARAMETERS

   IN
   pvosGCtx:       pointer to the global vos context; a handle to TL's
                   control block can be extracted from its context
   ucSTAId:        identifier of the station being processed
   vosDataBuff:   pointer to the rx vos buffer

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_STARxDisc
(
  v_PVOID_t     pvosGCtx,
  v_U8_t        ucSTAId,
  vos_pkt_t**   pvosDataBuff,
  v_BOOL_t      bForwardIAPPwithLLC
)
{
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if (( NULL == pvosDataBuff ) || ( NULL ==  *pvosDataBuff ))
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "WLAN TL:Invalid parameter sent on WLANTL_STARxDisc"));
    return VOS_STATUS_E_INVAL;
  }

  /*------------------------------------------------------------------------
    Error - drop packet
   ------------------------------------------------------------------------*/
  TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
             "WLAN TL:Packet should not be received in state disconnected"
             " - dropping"));
  vos_pkt_return_packet(*pvosDataBuff);
  *pvosDataBuff = NULL;

  return VOS_STATUS_SUCCESS;
}/* WLANTL_STARxDisc */

/*==========================================================================
      Processing main loops for MAIN and TX threads
  ==========================================================================*/

/*==========================================================================
  FUNCTION    WLANTL_McProcessMsg

  DESCRIPTION
    Called by VOSS when a message was serialized for TL through the
    main thread/task.

  DEPENDENCIES
    The TL must be initialized before this function can be called.

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context
    message:        type and content of the message


  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:   invalid input parameters
    VOS_STATUS_E_FAULT:   pointer to TL cb is NULL ; access would cause a
                          page fault
    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_McProcessMsg
(
  v_PVOID_t        pvosGCtx,
  vos_msg_t*       message
)
{
   WLANTL_CbType*  pTLCb = NULL;
   tAddBAInd*      ptAddBaInd = NULL;
   tDelBAInd*      ptDelBaInd = NULL;
   tAddBARsp*      ptAddBaRsp = NULL;
   vos_msg_t       vosMessage;
   VOS_STATUS      vosStatus;
   tpFlushACRsp FlushACRspPtr;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if ( NULL == message )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid parameter sent on WLANTL_ProcessMainMessage"));
    return VOS_STATUS_E_INVAL;
  }

  /*------------------------------------------------------------------------
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
     "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_ProcessMainMessage"));
    return VOS_STATUS_E_FAULT;
  }

  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
        "WLAN TL:Received message: %d through main flow", message->type));

  switch( message->type )
  {
  case WDA_TL_FLUSH_AC_RSP:
    // Extract the message from the message body
    FlushACRspPtr = (tpFlushACRsp)(message->bodyptr);
    // Make sure the call back function is not null.
    if ( NULL == pTLCb->tlBAPClient.pfnFlushOpCompleteCb )
    {
      VOS_ASSERT(0);
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
       "WLAN TL:Invalid TL pointer pfnFlushOpCompleteCb"));
      return VOS_STATUS_E_FAULT;
    }

    TLLOG2(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
            "Received message:  Flush complete received by TL"));

    // Since we have the response back from HAL, just call the BAP client
    // registered call back from TL. There is only 1 possible
    // BAP client. So directly reference tlBAPClient
    pTLCb->tlBAPClient.pfnFlushOpCompleteCb( pvosGCtx,
            FlushACRspPtr->ucSTAId,
            FlushACRspPtr->ucTid, FlushACRspPtr->status );

    // Free the PAL memory, we are done with it.
    TLLOG2(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
        "Flush complete received by TL: Freeing %pK", FlushACRspPtr));
    vos_mem_free((v_VOID_t *)FlushACRspPtr);
    break;

  case WDA_HDD_ADDBA_REQ:
   ptAddBaInd = (tAddBAInd*)(message->bodyptr);
    vosStatus = WLANTL_BaSessionAdd( pvosGCtx,
                                 ptAddBaInd->baSession.baSessionID,
                                     ptAddBaInd->baSession.STAID,
                                     ptAddBaInd->baSession.baTID,
                                 (v_U32_t)ptAddBaInd->baSession.baBufferSize,
                                 ptAddBaInd->baSession.winSize,
                                 ptAddBaInd->baSession.SSN);
    ptAddBaRsp = vos_mem_malloc(sizeof(*ptAddBaRsp));

    if ( NULL == ptAddBaRsp )
    {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                "WLAN TL: fatal failure, cannot allocate BA Rsp structure"));
      VOS_ASSERT(0);
      return VOS_STATUS_E_NOMEM;
    }

    if ( VOS_STATUS_SUCCESS == vosStatus )
    {
      TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                "WLAN TL: Sending success indication to HAL for ADD BA"));
      /*Send success*/
      ptAddBaRsp->mesgType    = WDA_HDD_ADDBA_RSP;
      vosMessage.type         = WDA_HDD_ADDBA_RSP;
    }
    else
    {
      TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                 "WLAN TL: Sending failure indication to HAL for ADD BA"));

      /*Send failure*/
      ptAddBaRsp->mesgType    = WDA_BA_FAIL_IND;
      vosMessage.type         = WDA_BA_FAIL_IND;
    }

    ptAddBaRsp->mesgLen     = sizeof(tAddBARsp);
    ptAddBaRsp->baSessionID = ptAddBaInd->baSession.baSessionID;
      /* This is default, reply win size has to be handled BA module, FIX THIS */
      ptAddBaRsp->replyWinSize = WLANTL_MAX_WINSIZE;
    vosMessage.bodyptr = ptAddBaRsp;

    vos_mq_post_message( VOS_MQ_ID_WDA, &vosMessage );
    WLANTL_McFreeMsg (pvosGCtx, message);
  break;
  case WDA_DELETEBA_IND:
    ptDelBaInd = (tDelBAInd*)(message->bodyptr);
    vosStatus  = WLANTL_BaSessionDel(pvosGCtx,
                                 ptDelBaInd->staIdx,
                                 ptDelBaInd->baTID);

    if ( VOS_STATUS_SUCCESS != vosStatus )
    {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "WLAN TL: Failed to del BA session STA:%d TID:%d Status :%d",
               ptDelBaInd->staIdx,
               ptDelBaInd->baTID,
               vosStatus));
    }
    WLANTL_McFreeMsg (pvosGCtx, message);
    break;
  default:
    /*no processing for now*/
    break;
  }

  return VOS_STATUS_SUCCESS;
}/* WLANTL_ProcessMainMessage */

/*==========================================================================
  FUNCTION    WLANTL_McFreeMsg

  DESCRIPTION
    Called by VOSS to free a given TL message on the Main thread when there
    are messages pending in the queue when the whole system is been reset.
    For now, TL does not allocate any body so this function shout translate
    into a NOOP

  DEPENDENCIES
    The TL must be initialized before this function can be called.

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context
    message:        type and content of the message


  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_McFreeMsg
(
  v_PVOID_t        pvosGCtx,
  vos_msg_t*       message
)
{
  WLANTL_CbType*  pTLCb = NULL;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

   /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if ( NULL == message )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid parameter sent on WLANTL_McFreeMsg"));
    return VOS_STATUS_E_INVAL;
  }

  /*------------------------------------------------------------------------
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
     "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_McFreeMsg"));
    return VOS_STATUS_E_FAULT;
  }

  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
        "WLAN TL:Received message: %d through main free", message->type));

  switch( message->type )
  {
  case WDA_HDD_ADDBA_REQ:
  case WDA_DELETEBA_IND:
    /*vos free body pointer*/
    vos_mem_free(message->bodyptr);
    message->bodyptr = NULL;
    break;
  default:
    /*no processing for now*/
    break;
  }

  return VOS_STATUS_SUCCESS;
}/*WLANTL_McFreeMsg*/

/*==========================================================================
  FUNCTION    WLANTL_TxProcessMsg

  DESCRIPTION
    Called by VOSS when a message was serialized for TL through the
    tx thread/task.

  DEPENDENCIES
    The TL must be initialized before this function can be called.

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context
    message:        type and content of the message


  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:   invalid input parameters
    VOS_STATUS_E_FAULT:   pointer to TL cb is NULL ; access would cause a
                          page fault
    VOS_STATUS_SUCCESS:   Everything is good :)

  Other values can be returned as a result of a function call, please check
  corresponding API for more info.
  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_TxProcessMsg
(
  v_PVOID_t        pvosGCtx,
  vos_msg_t*       message
)
{
   VOS_STATUS      vosStatus = VOS_STATUS_SUCCESS;
   void (*callbackRoutine) (void *callbackContext);
   void *callbackContext;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if ( NULL == message )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid parameter sent on WLANTL_ProcessTxMessage"));
    return VOS_STATUS_E_INVAL;
  }

  /*------------------------------------------------------------------------
    Process message
   ------------------------------------------------------------------------*/
  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL:Received message: %d through tx flow", message->type));

  switch( message->type )
  {
  case WLANTL_TX_SIG_SUSPEND:
    vosStatus = WLANTL_SuspendCB( pvosGCtx,
                                 (WLANTL_SuspendCBType)message->bodyptr,
                                 message->reserved);
    break;
  case WLANTL_TX_RES_NEEDED:
    vosStatus = WLANTL_GetTxResourcesCB( pvosGCtx );
     break;

  case WDA_DS_TX_START_XMIT:
      WLANTL_ClearTxXmitPending(pvosGCtx);
      vosStatus = WDA_DS_TxFrames( pvosGCtx );
      break;

  case WDA_DS_FINISH_ULA:
    callbackContext = message->bodyptr;
    callbackRoutine = message->callback;
    if ( NULL != callbackRoutine )
    {
      callbackRoutine(callbackContext);
    }
    break;

  case WLANTL_TX_SNAPSHOT:
    /*Dumping TL State and then continuing to print
      the DXE Dump*/
    WLANTL_TxThreadDebugHandler(pvosGCtx);
    WDA_TransportChannelDebug(NULL, VOS_TRUE, VOS_FALSE);
    break;

  case WLANTL_TX_FATAL_ERROR:
    WLANTL_FatalErrorHandler(pvosGCtx);
    break;

  case WLANTL_TX_FW_DEBUG:
    vos_fwDumpReq(274, 0, 0, 0, 0, 1); //Async event
    break;

  case WLANTL_TX_KICKDXE:
    WDA_TransportKickDxe();
    break;

  default:
    /*no processing for now*/
    break;
  }

  return vosStatus;
}/* WLANTL_TxProcessMsg */

/*==========================================================================
  FUNCTION    WLANTL_McFreeMsg

  DESCRIPTION
    Called by VOSS to free a given TL message on the Main thread when there
    are messages pending in the queue when the whole system is been reset.
    For now, TL does not allocate any body so this function shout translate
    into a NOOP

  DEPENDENCIES
    The TL must be initialized before this function can be called.

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context
    message:        type and content of the message


  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_TxFreeMsg
(
  v_PVOID_t        pvosGCtx,
  vos_msg_t*       message
)
{
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*Nothing to do for now!!!*/
  return VOS_STATUS_SUCCESS;
}/*WLANTL_TxFreeMsg*/

/*==========================================================================

  FUNCTION    WLANTL_TxFCFrame

  DESCRIPTION
    Internal utility function to send FC frame. Enable
    or disable LWM mode based on the information.

  DEPENDENCIES
    TL must be initiailized before this function gets called.
    FW sends up special flow control frame.

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:   Input pointers are NULL.
    VOS_STATUS_E_FAULT:   Something is wrong.
    VOS_STATUS_SUCCESS:   Everything is good.

  SIDE EFFECTS
    Newly formed FC frame is generated and waits to be transmitted. Previously unsent frame will
    be released.

============================================================================*/
VOS_STATUS
WLANTL_TxFCFrame
(
  v_PVOID_t       pvosGCtx
)
{
#if 0
  WLANTL_CbType*      pTLCb = NULL;
  VOS_STATUS          vosStatus;
  tpHalFcTxBd         pvFcTxBd = NULL;
  vos_pkt_t *         pPacket = NULL;
  v_U8_t              ucSTAId = 0;
  v_U8_t              ucBitCheck = 1;

  VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
               "WLAN TL: Send FC frame %s", __func__);

  /*------------------------------------------------------------------------
    Sanity check
    ------------------------------------------------------------------------*/
  if ( NULL == pvosGCtx )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid parameter %s", __func__));
    return VOS_STATUS_E_INVAL;
  }
  /*------------------------------------------------------------------------
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);

  if (NULL == pTLCb)
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
        "WLAN TL:Invalid pointer in %s \n", __func__));
    return VOS_STATUS_E_INVAL;
  }
  
  //Get one voss packet
  vosStatus = vos_pkt_get_packet( &pPacket, VOS_PKT_TYPE_TX_802_11_MGMT, sizeof(tHalFcTxBd), 1, 
                                    VOS_FALSE, NULL, NULL );

  if ( VOS_STATUS_SUCCESS != vosStatus )
  {
    return VOS_STATUS_E_INVAL;
  }

  vosStatus = vos_pkt_reserve_head( pPacket, (void *)&pvFcTxBd, sizeof(tHalFcTxBd));

  if( VOS_STATUS_SUCCESS != vosStatus )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                 "%s: failed to reserve FC TX BD %d\n",__func__, sizeof(tHalFcTxBd)));
    vos_pkt_return_packet( pPacket );
    return VOS_STATUS_E_FAULT;
  }

  //Generate most recent tlFCInfo. Most fields are correct.
  pTLCb->tlFCInfo.fcSTAThreshEnabledMask = 0;
  pTLCb->tlFCInfo.fcSTATxMoreDataMask = 0;
  for( ucSTAId = 0, ucBitCheck = 1 ; ucSTAId < WLAN_MAX_STA_COUNT; ucBitCheck <<= 1, ucSTAId ++)
  {
    if (0 == pTLCb->atlSTAClients[ucSTAId].ucExists)
    {
      continue;
    }

    if (pTLCb->atlSTAClients[ucSTAId].ucPktPending)
    {
      pTLCb->tlFCInfo.fcSTATxMoreDataMask |= ucBitCheck;
    }

    if ( (pTLCb->atlSTAClients[ucSTAId].ucLwmModeEnabled) &&
         (pTLCb->atlSTAClients[ucSTAId].bmuMemConsumed > pTLCb->atlSTAClients[ucSTAId].uLwmThreshold))
    {
      pTLCb->tlFCInfo.fcSTAThreshEnabledMask |= ucBitCheck;

      pTLCb->tlFCInfo.fcSTAThresh[ucSTAId] = (tANI_U8)pTLCb->atlSTAClients[ucSTAId].uLwmThreshold;

      pTLCb->atlSTAClients[ucSTAId].ucLwmEventReported = FALSE;
    }

  }
  
  //request immediate feedback
  pTLCb->tlFCInfo.fcConfig |= 0x4;                               

  //fill in BD to sent
  vosStatus = WLANHAL_FillFcTxBd(pvosGCtx, &pTLCb->tlFCInfo, (void *)pvFcTxBd);

  if( VOS_STATUS_SUCCESS != vosStatus )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                 "%s: Fill FC TX BD unsuccessful\n", __func__));
    vos_pkt_return_packet( pPacket );
    return VOS_STATUS_E_FAULT;
  }

  if (NULL != pTLCb->vosTxFCBuf)
  {
    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                 "%s: Previous FC TX BD not sent\n", __func__));
    vos_pkt_return_packet(pTLCb->vosTxFCBuf);
  }

  pTLCb->vosTxFCBuf = pPacket;

  vos_pkt_set_user_data_ptr( pPacket, VOS_PKT_USER_DATA_ID_TL,
                               (v_PVOID_t)WLANTL_TxCompDefaultCb);
  vosStatus = WDA_DS_StartXmit(pvosGCtx);

  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
               "WLAN TL: send FC frame leave %s", __func__));
#endif
  return VOS_STATUS_SUCCESS;
}


/*==========================================================================
  FUNCTION    WLANTL_GetTxResourcesCB

  DESCRIPTION
    Processing function for Resource needed signal. A request will be issued
    to BAL to get more tx resources.

  DEPENDENCIES
    The TL must be initialized before this function can be called.

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context


  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_FAULT:   pointer to TL cb is NULL ; access would cause a
                          page fault
    VOS_STATUS_SUCCESS:   Everything is good :)

  Other values can be returned as a result of a function call, please check
  corresponding API for more info.
  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_GetTxResourcesCB
(
  v_PVOID_t        pvosGCtx
)
{
  WLANTL_CbType*  pTLCb      = NULL;
  v_U32_t         uResCount  = WDA_TLI_MIN_RES_DATA;
  VOS_STATUS      vosStatus  = VOS_STATUS_SUCCESS;
  v_U8_t          ucMgmt     = 0;
  v_U8_t          ucBAP      = 0;
  v_U8_t          ucData     = 0;
#ifdef WLAN_SOFTAP_FLOWCTRL_EN
  tBssSystemRole systemRole;
  tpAniSirGlobal pMac;
#endif
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  /*------------------------------------------------------------------------
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid TL pointer from pvosGCtx on"
               " WLANTL_ProcessTxMessage"));
    return VOS_STATUS_E_FAULT;
  }

  /*------------------------------------------------------------------------
    Get tx resources from BAL
   ------------------------------------------------------------------------*/
  vosStatus = WDA_DS_GetTxResources( pvosGCtx, &uResCount );

  if ( (VOS_STATUS_SUCCESS != vosStatus) && (VOS_STATUS_E_RESOURCES != vosStatus))
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:TL failed to get resources from BAL, Err: %d",
               vosStatus));
    return vosStatus;
  }

  /* Currently only Linux BAL returns the E_RESOURCES error code when it is running 
     out of BD/PDUs. To make use of this interrupt for throughput enhancement, similar
     changes should be done in BAL code of AMSS and WM */
  if (VOS_STATUS_E_RESOURCES == vosStatus)
  {
#ifdef VOLANS_PERF
     WLANHAL_EnableIdleBdPduInterrupt(pvosGCtx, (tANI_U8)bdPduInterruptGetThreshold);
     VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
               "WLAN TL: Enabling Idle BD/PDU interrupt, Current resources = %d", uResCount);
#else
    return VOS_STATUS_E_FAILURE;
#endif
  }

  pTLCb->uResCount = uResCount;
  

#ifdef WLAN_SOFTAP_FLOWCTRL_EN
  /* FIXME: disabled since creating issues in power-save, needs to be addressed */ 
  pTLCb->sendFCFrame ++;
  pMac = vos_get_context(VOS_MODULE_ID_WDA, pvosGCtx);
  systemRole = wdaGetGlobalSystemRole(pMac);
  if (eSYSTEM_AP_ROLE == systemRole)
  {
     if (pTLCb->sendFCFrame % 16 == 0)
     {
         TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                "Transmit FC"));
         WLANTL_TxFCFrame (pvosGCtx);
     } 
  }
#endif //WLAN_SOFTAP_FLOWCTRL_EN 

  ucData = ( pTLCb->uResCount >=  WDA_TLI_MIN_RES_DATA );
  ucBAP  = ( pTLCb->uResCount >=  WDA_TLI_MIN_RES_BAP ) &&
           ( NULL != pTLCb->tlBAPClient.vosPendingDataBuff );
  ucMgmt = ( pTLCb->uResCount >=  WDA_TLI_MIN_RES_MF ) &&
           ( NULL != pTLCb->tlMgmtFrmClient.vosPendingDataBuff );

  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL: Eval Resume tx Res: %d DATA: %d BAP: %d MGMT: %d",
             pTLCb->uResCount, ucData, ucBAP, ucMgmt));

  if (( 0 == pTLCb->ucTxSuspended ) &&
      (( 0 != ucData ) || ( 0 != ucMgmt ) || ( 0 != ucBAP ) ) )
  {
    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                 "Issuing Xmit start request to BAL for avail res SYNC"));
    vosStatus =WDA_DS_StartXmit(pvosGCtx);
  }
  return vosStatus;
}/*WLANTL_GetTxResourcesCB*/

/*==========================================================================
      Utility functions
  ==========================================================================*/

/*==========================================================================
  FUNCTION    WLANTL_Translate8023To80211Header

  DESCRIPTION
    Inline function for translating and 802.11 header into an 802.3 header.

  DEPENDENCIES


  PARAMETERS

   IN
    pTLCb:            TL control block
   IN/OUT 
    ucStaId:          station ID. Incase of TDLS, this returns actual TDLS
                      station ID used

   IN/OUT
    vosDataBuff:      vos data buffer, will contain the new header on output

   OUT
    pvosStatus:       status of the operation

  RETURN VALUE

    VOS_STATUS_SUCCESS:  Everything is good :)

    Other error codes might be returned from the vos api used in the function
    please check those return values.

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_Translate8023To80211Header
(
  vos_pkt_t*      vosDataBuff,
  VOS_STATUS*     pvosStatus,
  WLANTL_CbType*  pTLCb,
  v_U8_t          *pucStaId,
  WLANTL_MetaInfoType *tlMetaInfo,
  v_U8_t          *ucWDSEnabled,
  v_U8_t          *extraHeadSpace
)
{
  WLANTL_8023HeaderType  w8023Header;
  WLANTL_80211HeaderType *pw80211Header; // Allocate an aligned BD and then fill it. 
  VOS_STATUS             vosStatus;
  v_U8_t                 MandatoryucHeaderSize = WLAN80211_MANDATORY_HEADER_SIZE;
  v_U8_t                 ucHeaderSize = 0;
  v_VOID_t               *ppvBDHeader = NULL;
  WLANTL_STAClientType*  pClientSTA = NULL;
  v_U8_t                 ucQoSOffset = WLAN80211_MANDATORY_HEADER_SIZE;
  v_U8_t                 ucStaId;
#ifdef FEATURE_WLAN_ESE_UPLOAD
  v_BOOL_t               bIAPPTxwithLLC = VOS_FALSE;
  v_SIZE_t               wIAPPSnapSize = WLANTL_LLC_HEADER_LEN;
  v_U8_t                 wIAPPSnap[WLANTL_LLC_HEADER_LEN] = {0};
#endif
  *ucWDSEnabled = 0; // default WDS off.
  vosStatus = vos_pkt_pop_head( vosDataBuff, &w8023Header,
                                sizeof(w8023Header));

  if ( VOS_STATUS_SUCCESS != vosStatus )
  {
     TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
     "WLAN TL: Packet pop header fails on WLANTL_Translate8023To80211Header"));
     return vosStatus;
  }

  if( NULL == pucStaId )
  {
     TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
     "WLAN TL: Invalid pointer for StaId"));
     return VOS_STATUS_E_INVAL;
  }
  ucStaId = *pucStaId;
  pClientSTA = pTLCb->atlSTAClients[ucStaId];

  if ( NULL == pClientSTA )
  {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Client Memory was not allocated on %s", __func__));
      return VOS_STATUS_E_FAILURE;
  }

#ifdef FEATURE_WLAN_TDLS

  if ( WLAN_STA_INFRA == pTLCb->atlSTAClients[ucStaId]->wSTADesc.wSTAType
      && pTLCb->ucTdlsPeerCount )
  {
    v_U8_t ucIndex = 0;
    for ( ucIndex = 0; ucIndex < WLAN_MAX_STA_COUNT ; ucIndex++)
    {
      if ( ucIndex != ucStaId && pTLCb->atlSTAClients[ucIndex] && pTLCb->atlSTAClients[ucIndex]->ucExists &&
          (pTLCb->atlSTAClients[ucIndex]->tlState == WLANTL_STA_AUTHENTICATED) &&
          (!pTLCb->atlSTAClients[ucIndex]->ucTxSuspended) &&
          vos_mem_compare( (void*)pTLCb->atlSTAClients[ucIndex]->wSTADesc.vSTAMACAddress.bytes,
            (void*)w8023Header.vDA, 6) )
      {
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,
              "WLAN TL: Got a TDLS station. Using that index"));
        ucStaId = ucIndex;
        *pucStaId = ucStaId;
        pClientSTA = pTLCb->atlSTAClients[ucStaId];
        if ( NULL == pClientSTA )
        {
            TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                "WLAN TL:Client Memory was not allocated on %s", __func__));
            return VOS_STATUS_E_FAILURE;
        }
        break;
      }
    }
  }
#endif

#ifdef FEATURE_WLAN_ESE_UPLOAD
if ((0 == w8023Header.usLenType) && (pClientSTA->wSTADesc.ucIsEseSta))
{
    vos_pkt_extract_data(vosDataBuff,0,&wIAPPSnap[0],&wIAPPSnapSize);
    if (vos_mem_compare(wIAPPSnap,WLANTL_AIRONET_SNAP_HEADER,WLANTL_LLC_HEADER_LEN))
    {
        /*The SNAP and the protocol type are already in the data buffer.
         They are filled by the application (wpa_supplicant). So, Skip Adding LLC below.*/
         bIAPPTxwithLLC = VOS_TRUE;
    }
    else
    {
        bIAPPTxwithLLC = VOS_FALSE;
    }
}
#endif /* FEATURE_WLAN_ESE_UPLOAD */

  if ((0 != pClientSTA->wSTADesc.ucAddRmvLLC)
#ifdef FEATURE_WLAN_ESE_UPLOAD
      && (!bIAPPTxwithLLC)
#endif /* FEATURE_WLAN_ESE_UPLOAD */
     )
  {
    /* Push the length */
    vosStatus = vos_pkt_push_head(vosDataBuff,
                    &w8023Header.usLenType, sizeof(w8023Header.usLenType));

    if ( VOS_STATUS_SUCCESS != vosStatus )
    {
       TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                  "WLAN TL: Packet push ether type fails on"
                  " WLANTL_Translate8023To80211Header"));
       return vosStatus;
    }

#ifdef BTAMP_TEST
    // The STA side will execute this, a hack to test BTAMP by using the
    // infra setup. On real BTAMP this will come from BAP itself.
    {
    static v_U8_t WLANTL_BT_AMP_LLC_HEADER[] =  {0xAA, 0xAA, 0x03, 0x00, 0x19, 0x58 };
    vosStatus = vos_pkt_push_head(vosDataBuff, WLANTL_BT_AMP_LLC_HEADER,
                       sizeof(WLANTL_BT_AMP_LLC_HEADER));

    if ( VOS_STATUS_SUCCESS != vosStatus )
    {
       TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                 "WLAN TL: Packet push LLC header fails on"
                  " WLANTL_Translate8023To80211Header"));
       return vosStatus;
    }
    }
#else
    vosStatus = vos_pkt_push_head(vosDataBuff, WLANTL_LLC_HEADER,
                       sizeof(WLANTL_LLC_HEADER));

    if ( VOS_STATUS_SUCCESS != vosStatus )
    {
       TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                 "WLAN TL: Packet push LLC header fails on"
                  " WLANTL_Translate8023To80211Header"));
       return vosStatus;
    }
#endif
  }/*If add LLC is enabled*/
  else
  {
#ifdef FEATURE_WLAN_ESE_UPLOAD
      bIAPPTxwithLLC = VOS_FALSE; /*Reset the Flag here to start afresh with the next TX pkt*/
#endif /* FEATURE_WLAN_ESE_UPLOAD */
       TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                 "WLAN TL: STA Client registered to not remove LLC"
                  " WLANTL_Translate8023To80211Header"));
  }

#ifdef BTAMP_TEST
  pClientSTA->wSTADesc.wSTAType = WLAN_STA_BT_AMP;
#endif

  // Find the space required for the 802.11 header format
  // based on the frame control fields.
  ucHeaderSize = MandatoryucHeaderSize;
  if (pClientSTA->wSTADesc.ucQosEnabled)
  {  
    ucHeaderSize += sizeof(pw80211Header->usQosCtrl);
  }
  if (pClientSTA->wSTADesc.wSTAType == WLAN_STA_BT_AMP)
  {  
    ucHeaderSize += sizeof(pw80211Header->optvA4);
    ucQoSOffset += sizeof(pw80211Header->optvA4);
  }

  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
      " WLANTL_Translate8023To80211Header : Header size = %d ", ucHeaderSize));

  vos_pkt_reserve_head( vosDataBuff, &ppvBDHeader, ucHeaderSize );
  if ( NULL == ppvBDHeader )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                "WLAN TL:VOSS packet corrupted "));
    *pvosStatus = VOS_STATUS_E_INVAL;
    return *pvosStatus;
  }


  // OK now we have the space. Fill the 80211 header
  /* Fill A2 */
  pw80211Header = (WLANTL_80211HeaderType *)(ppvBDHeader);
  // only clear the required space.
  vos_mem_set( pw80211Header, ucHeaderSize, 0 );
  vos_mem_copy( pw80211Header->vA2, w8023Header.vSA,  VOS_MAC_ADDR_SIZE);


#ifdef FEATURE_WLAN_WAPI
  if (( WLANTL_STA_AUTHENTICATED == pClientSTA->tlState ||
        pClientSTA->ptkInstalled ) && (tlMetaInfo->ucIsWai != 1))
#else
  if ( WLANTL_STA_AUTHENTICATED == pClientSTA->tlState ||
       pClientSTA->ptkInstalled )
#endif
  {
    pw80211Header->wFrmCtrl.wep =
                 pClientSTA->wSTADesc.ucProtectedFrame;
  }

  pw80211Header->usDurationId = 0;
  pw80211Header->usSeqCtrl    = 0;

  pw80211Header->wFrmCtrl.type     = WLANTL_80211_DATA_TYPE;



  if(pClientSTA->wSTADesc.ucQosEnabled)
  {
      pw80211Header->wFrmCtrl.subType  = WLANTL_80211_DATA_QOS_SUBTYPE;

      *((v_U16_t *)((v_U8_t *)ppvBDHeader + ucQoSOffset)) = tlMetaInfo->ucUP;

  }
  else
  {
      pw80211Header->wFrmCtrl.subType  = 0;
      tlMetaInfo->ucUP = 0;
      tlMetaInfo->ucTID = 0;

  // NO NO NO - there is not enough memory allocated to write the QOS ctrl  
  // field, it will overwrite the first 2 bytes of the data packet(LLC header)
  // pw80211Header->usQosCtrl         = 0;
  }


  switch( pClientSTA->wSTADesc.wSTAType )
  {
     case WLAN_STA_IBSS:
        pw80211Header->wFrmCtrl.toDS          = 0;
        pw80211Header->wFrmCtrl.fromDS        = 0;

        vos_copy_macaddr( (v_MACADDR_t*)&pw80211Header->vA1,
                             (v_MACADDR_t*)&w8023Header.vDA);
        vos_mem_copy( pw80211Header->vA3,
              &pClientSTA->wSTADesc.vBSSIDforIBSS ,
              VOS_MAC_ADDR_SIZE);
        break;

     case WLAN_STA_BT_AMP:
        *ucWDSEnabled = 1; // WDS on.
        pw80211Header->wFrmCtrl.toDS          = 1;
        pw80211Header->wFrmCtrl.fromDS        = 1;
        vos_copy_macaddr( (v_MACADDR_t*)&pw80211Header->vA1,
              &pClientSTA->wSTADesc.vSTAMACAddress);
        vos_mem_copy( pw80211Header->vA2,
              w8023Header.vSA, VOS_MAC_ADDR_SIZE);
        vos_copy_macaddr( (v_MACADDR_t*)&pw80211Header->vA3,
              &pClientSTA->wSTADesc.vSTAMACAddress);
        /* fill the optional A4 header */
        vos_mem_copy( pw80211Header->optvA4,
              w8023Header.vSA, VOS_MAC_ADDR_SIZE);
        TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                 "BTAMP CASE NOW ---------staid=%d",
                 ucStaId));
        break;

     case WLAN_STA_SOFTAP:
        *ucWDSEnabled = 0; // WDS off.
        pw80211Header->wFrmCtrl.toDS          = 0;
        pw80211Header->wFrmCtrl.fromDS        = 1;
        /*Copy the DA to A1*/
        vos_mem_copy( pw80211Header->vA1, w8023Header.vDA , VOS_MAC_ADDR_SIZE);   
        vos_copy_macaddr( (v_MACADDR_t*)&pw80211Header->vA2,
              &pClientSTA->wSTADesc.vSelfMACAddress);
        vos_mem_copy( pw80211Header->vA3,
              w8023Header.vSA, VOS_MAC_ADDR_SIZE);
        TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                 "sw 802 to 80211 softap case  ---------staid=%d",
                 ucStaId));
        break;
#ifdef FEATURE_WLAN_TDLS
     case WLAN_STA_TDLS:
        pw80211Header->wFrmCtrl.toDS          = 0;
        pw80211Header->wFrmCtrl.fromDS        = 0;
        /*Fix me*/
        vos_copy_macaddr( (v_MACADDR_t*)&pw80211Header->vA1,
              &pClientSTA->wSTADesc.vSTAMACAddress);
        vos_mem_copy( pw80211Header->vA3,
              &pClientSTA->wSTADesc.vBSSIDforIBSS ,
              VOS_MAC_ADDR_SIZE);
        VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
              ("TL:TDLS CASE NOW ---------staid=%d"), ucStaId);
        break;
#endif
     case WLAN_STA_INFRA:
     default:
        pw80211Header->wFrmCtrl.toDS          = 1;
        pw80211Header->wFrmCtrl.fromDS        = 0;
        vos_copy_macaddr( (v_MACADDR_t*)&pw80211Header->vA1,
              &pClientSTA->wSTADesc.vSTAMACAddress);
        vos_mem_copy( pw80211Header->vA3, w8023Header.vDA , VOS_MAC_ADDR_SIZE);
        TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                 "REGULAR INFRA LINK CASE---------staid=%d",
                 ucStaId));
        break;
  }
  // OK now we have the space. Fill the 80211 header
  /* Fill A2 */
  pw80211Header = (WLANTL_80211HeaderType *)(ppvBDHeader);
  return VOS_STATUS_SUCCESS;
}/*WLANTL_Translate8023To80211Header*/


/*=============================================================================
   BEGIN LOG FUNCTION    !!! Remove me or clean me
=============================================================================*/
#if 0 //def WLANTL_DEBUG

#define WLANTL_DEBUG_FRAME_BYTE_PER_LINE    16
#define WLANTL_DEBUG_FRAME_BYTE_PER_BYTE    4

static v_VOID_t WLANTL_DebugFrame
(
   v_PVOID_t   dataPointer,
   v_U32_t     dataSize
)
{
   v_U8_t   lineBuffer[WLANTL_DEBUG_FRAME_BYTE_PER_LINE];
   v_U32_t  numLines;
   v_U32_t  numBytes;
   v_U32_t  idx;
   v_U8_t   *linePointer;

   numLines = dataSize / WLANTL_DEBUG_FRAME_BYTE_PER_LINE;
   numBytes = dataSize % WLANTL_DEBUG_FRAME_BYTE_PER_LINE;
   linePointer = (v_U8_t *)dataPointer;

   TLLOGE(VOS_TRACE(VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_ERROR, "WLAN TL:Frame Debug Frame Size %d, Pointer 0x%pK", dataSize, dataPointer));
   for(idx = 0; idx < numLines; idx++)
   {
      memset(lineBuffer, 0, WLANTL_DEBUG_FRAME_BYTE_PER_LINE);
      memcpy(lineBuffer, linePointer, WLANTL_DEBUG_FRAME_BYTE_PER_LINE);
      TLLOGE(VOS_TRACE(VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_ERROR,
                "WLAN TL:0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x 0x%2x",
                 lineBuffer[0], lineBuffer[1], lineBuffer[2], lineBuffer[3], lineBuffer[4], lineBuffer[5], lineBuffer[6], lineBuffer[7],
                 lineBuffer[8], lineBuffer[9], lineBuffer[10], lineBuffer[11], lineBuffer[12], lineBuffer[13], lineBuffer[14], lineBuffer[15]));
      linePointer += WLANTL_DEBUG_FRAME_BYTE_PER_LINE;
   }

   if(0 == numBytes)
      return;

   memset(lineBuffer, 0, WLANTL_DEBUG_FRAME_BYTE_PER_LINE);
   memcpy(lineBuffer, linePointer, numBytes);
   for(idx = 0; idx < WLANTL_DEBUG_FRAME_BYTE_PER_LINE / WLANTL_DEBUG_FRAME_BYTE_PER_BYTE; idx++)
   {
      TLLOGE(VOS_TRACE(VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_ERROR, "WLAN TL:0x%2x 0x%2x 0x%2x 0x%2x",
                lineBuffer[idx * WLANTL_DEBUG_FRAME_BYTE_PER_BYTE], lineBuffer[1 + idx * WLANTL_DEBUG_FRAME_BYTE_PER_BYTE],
                lineBuffer[2 + idx * WLANTL_DEBUG_FRAME_BYTE_PER_BYTE], lineBuffer[3 + idx * WLANTL_DEBUG_FRAME_BYTE_PER_BYTE]));
      if(((idx + 1) * WLANTL_DEBUG_FRAME_BYTE_PER_BYTE) >= numBytes)
         break;
   }

   return;
}
#endif

/*=============================================================================
   END LOG FUNCTION
=============================================================================*/

/*==========================================================================
  FUNCTION    WLANTL_Translate80211To8023Header

  DESCRIPTION
    Inline function for translating and 802.11 header into an 802.3 header.

  DEPENDENCIES


  PARAMETERS

   IN
    pTLCb:            TL control block
    ucStaId:          station ID
    ucHeaderLen:      Length of the header from BD
    ucActualHLen:     Length of header including padding or any other trailers

   IN/OUT
    vosDataBuff:      vos data buffer, will contain the new header on output

   OUT
    pvosStatus:       status of the operation

   RETURN VALUE

    The result code associated with performing the operation
    VOS_STATUS_SUCCESS:  Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_Translate80211To8023Header
(
  vos_pkt_t*      vosDataBuff,
  VOS_STATUS*     pvosStatus,
  v_U16_t         usActualHLen,
  v_U8_t          ucHeaderLen,
  WLANTL_CbType*  pTLCb,
  v_U8_t          ucSTAId,
  v_BOOL_t        bForwardIAPPwithLLC
)
{
  WLANTL_8023HeaderType  w8023Header;
  WLANTL_80211HeaderType w80211Header;
  v_U8_t                 aucLLCHeader[WLANTL_LLC_HEADER_LEN];
  VOS_STATUS             vosStatus;
  v_U16_t                usDataStartOffset = 0;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  if ( sizeof(w80211Header) < ucHeaderLen )
  {
     TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
       "Warning !: Check the header size for the Rx frame structure=%d received=%dn",
       sizeof(w80211Header), ucHeaderLen));
     ucHeaderLen = sizeof(w80211Header);
  }

  // This will take care of headers of all sizes, 3 address, 3 addr QOS,
  // WDS non-QOS and WDS QoS etc. We have space for all in the 802.11 header structure.
  vosStatus = vos_pkt_pop_head( vosDataBuff, &w80211Header, ucHeaderLen);

  if ( VOS_STATUS_SUCCESS != vosStatus )
  {
     TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                "WLAN TL: Failed to pop 80211 header from packet %d",
                vosStatus));

     return vosStatus;
  }

  switch ( w80211Header.wFrmCtrl.fromDS )
  {
  case 0:
    if ( w80211Header.wFrmCtrl.toDS )
    {
      //SoftAP AP mode
      vos_mem_copy( w8023Header.vDA, w80211Header.vA3, VOS_MAC_ADDR_SIZE);
      vos_mem_copy( w8023Header.vSA, w80211Header.vA2, VOS_MAC_ADDR_SIZE);
      TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                  "WLAN TL SoftAP: 802 3 DA %08x SA %08x",
                  w8023Header.vDA, w8023Header.vSA));
    }
    else 
    {
      /* IBSS */
      vos_mem_copy( w8023Header.vDA, w80211Header.vA1, VOS_MAC_ADDR_SIZE);
      vos_mem_copy( w8023Header.vSA, w80211Header.vA2, VOS_MAC_ADDR_SIZE);
    }
    break;
  case 1:
    if ( w80211Header.wFrmCtrl.toDS )
    {
      /* BT-AMP case */
      vos_mem_copy( w8023Header.vDA, w80211Header.vA1, VOS_MAC_ADDR_SIZE);
      vos_mem_copy( w8023Header.vSA, w80211Header.vA2, VOS_MAC_ADDR_SIZE);
    }
    else
    { /* Infra */
      vos_mem_copy( w8023Header.vDA, w80211Header.vA1, VOS_MAC_ADDR_SIZE);
      vos_mem_copy( w8023Header.vSA, w80211Header.vA3, VOS_MAC_ADDR_SIZE);
    }
    break;
  }

  if( usActualHLen > ucHeaderLen )
  {
     usDataStartOffset = usActualHLen - ucHeaderLen;
  }

  if ( 0 < usDataStartOffset )
  {
    vosStatus = vos_pkt_trim_head( vosDataBuff, usDataStartOffset );

    if ( VOS_STATUS_SUCCESS != vosStatus )
    {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                  "WLAN TL: Failed to trim header from packet %d",
                  vosStatus));
      return vosStatus;
    }
  }

  if ( NULL == pTLCb->atlSTAClients[ucSTAId] )
  {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Client Memory was not allocated on %s", __func__));
      return VOS_STATUS_E_FAILURE;
  }

  if ( 0 != pTLCb->atlSTAClients[ucSTAId]->wSTADesc.ucAddRmvLLC
#ifdef FEATURE_WLAN_ESE_UPLOAD
    && (!bForwardIAPPwithLLC)
#endif /*  FEATURE_WLAN_ESE_UPLOAD */
     )
  {
    // Extract the LLC header
    vosStatus = vos_pkt_pop_head( vosDataBuff, aucLLCHeader,
                                  WLANTL_LLC_HEADER_LEN);

    if ( VOS_STATUS_SUCCESS != vosStatus )
    {
       TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
                  "WLAN TL: Failed to pop LLC header from packet %d",
                  vosStatus));

       return vosStatus;
    }

    //Extract the length
    vos_mem_copy(&w8023Header.usLenType,
      &aucLLCHeader[WLANTL_LLC_HEADER_LEN - sizeof(w8023Header.usLenType)],
      sizeof(w8023Header.usLenType) );
  }
  else
  {
    vosStatus = vos_pkt_get_packet_length(vosDataBuff,
                                        &w8023Header.usLenType);

    if ( VOS_STATUS_SUCCESS != vosStatus )
    {
       TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                  "WLAN TL: Failed to get packet length %d",
                  vosStatus));

       return vosStatus;
    }

    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
        "WLAN TL: BTAMP len (ethertype) fld = %d",
        w8023Header.usLenType));
    w8023Header.usLenType = vos_cpu_to_be16(w8023Header.usLenType);
  }

  vos_pkt_push_head(vosDataBuff, &w8023Header, sizeof(w8023Header));

#ifdef BTAMP_TEST
  {
  // AP side will execute this.
  v_U8_t *temp_w8023Header = NULL;
  vosStatus = vos_pkt_peek_data( vosDataBuff, 0,
    &temp_w8023Header, sizeof(w8023Header) );
  }
#endif
#if 0 /*TL_DEBUG*/
  vos_pkt_get_packet_length(vosDataBuff, &usLen);
  vos_pkt_pop_head( vosDataBuff, aucData, usLen);

  WLANTL_DebugFrame(aucData, usLen);

  vos_pkt_push_head(vosDataBuff, aucData, usLen);

#endif

  *pvosStatus = VOS_STATUS_SUCCESS;

  return VOS_STATUS_SUCCESS;
}/*WLANTL_Translate80211To8023Header*/

VOS_STATUS
WLANTL_MonTranslate80211To8023Header
(
  vos_pkt_t*      vosDataBuff,
  WLANTL_CbType*  pTLCb
)
{
   v_U16_t                  usMPDUDOffset;
   v_U8_t                   ucMPDUHOffset;
   v_U8_t                   ucMPDUHLen;
   v_U16_t                  usActualHLen = 0;
   v_U16_t                  usDataStartOffset = 0;
   v_PVOID_t                aucBDHeader;
   WLANTL_8023HeaderType    w8023Header;
   WLANTL_80211HeaderType   w80211Header;
   VOS_STATUS               vosStatus;
   v_U8_t                   aucLLCHeader[WLANTL_LLC_HEADER_LEN];

   WDA_DS_PeekRxPacketInfo( vosDataBuff, (v_PVOID_t)&aucBDHeader, 0 );
   ucMPDUHOffset = (v_U8_t)WDA_GET_RX_MPDU_HEADER_OFFSET(aucBDHeader);
   usMPDUDOffset = (v_U16_t)WDA_GET_RX_MPDU_DATA_OFFSET(aucBDHeader);
   ucMPDUHLen    = (v_U8_t)WDA_GET_RX_MPDU_HEADER_LEN(aucBDHeader);
   if (usMPDUDOffset > ucMPDUHOffset)
   {
      usActualHLen = usMPDUDOffset - ucMPDUHOffset;
   }

  if ( sizeof(w80211Header) < ucMPDUHLen )
  {
     TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
       "Warning !: Check the header size for the Rx frame structure=%d received=%dn",
       sizeof(w80211Header), ucMPDUHLen));
     ucMPDUHLen = sizeof(w80211Header);
  }

  vosStatus = vos_pkt_pop_head( vosDataBuff, &w80211Header, ucMPDUHLen);
  if ( VOS_STATUS_SUCCESS != vosStatus )
  {
     TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                "WLAN TL: Failed to pop 80211 header from packet %d",
                vosStatus));

     return vosStatus;
  }
  switch ( w80211Header.wFrmCtrl.fromDS )
  {
  case 0:
    if ( w80211Header.wFrmCtrl.toDS )
    {
      vos_mem_copy( w8023Header.vDA, w80211Header.vA3, VOS_MAC_ADDR_SIZE);
      vos_mem_copy( w8023Header.vSA, w80211Header.vA2, VOS_MAC_ADDR_SIZE);
      TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                  "WLAN TL SoftAP: 802 3 DA %08x SA %08x",
                  w8023Header.vDA, w8023Header.vSA));
    }
    else
    {
      vos_mem_copy( w8023Header.vDA, w80211Header.vA1, VOS_MAC_ADDR_SIZE);
      vos_mem_copy( w8023Header.vSA, w80211Header.vA2, VOS_MAC_ADDR_SIZE);
    }
    break;
  case 1:
    if ( w80211Header.wFrmCtrl.toDS )
    {
      vos_mem_copy( w8023Header.vDA, w80211Header.vA1, VOS_MAC_ADDR_SIZE);
      vos_mem_copy( w8023Header.vSA, w80211Header.vA2, VOS_MAC_ADDR_SIZE);
    }
    else
    {
      vos_mem_copy( w8023Header.vDA, w80211Header.vA1, VOS_MAC_ADDR_SIZE);
      vos_mem_copy( w8023Header.vSA, w80211Header.vA3, VOS_MAC_ADDR_SIZE);
    }
    break;
  }
  if( usActualHLen > ucMPDUHLen )
  {
     usDataStartOffset = usActualHLen - ucMPDUHLen;
  }

  if ( 0 < usDataStartOffset )
  {
    vosStatus = vos_pkt_trim_head( vosDataBuff, usDataStartOffset );

    if ( VOS_STATUS_SUCCESS != vosStatus )
    {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                  "WLAN TL: Failed to trim header from packet %d",
                  vosStatus));
      return vosStatus;
    }
  }
   // Extract the LLC header
   vosStatus = vos_pkt_pop_head( vosDataBuff, aucLLCHeader,
                                 WLANTL_LLC_HEADER_LEN);

   if ( VOS_STATUS_SUCCESS != vosStatus )
   {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
                 "WLAN TL: Failed to pop LLC header from packet %d",
                 vosStatus));

      return vosStatus;
   }

   //Extract the length
   vos_mem_copy(&w8023Header.usLenType,
     &aucLLCHeader[WLANTL_LLC_HEADER_LEN - sizeof(w8023Header.usLenType)],
     sizeof(w8023Header.usLenType) );

   vos_pkt_push_head(vosDataBuff, &w8023Header, sizeof(w8023Header));
   return VOS_STATUS_SUCCESS;
}

/*==========================================================================
  FUNCTION    WLANTL_FindFrameTypeBcMcUc

  DESCRIPTION
    Utility function to find whether received frame is broadcast, multicast
    or unicast.

  DEPENDENCIES
    The STA must be registered with TL before this function can be called.

  PARAMETERS

   IN
   pTLCb:          pointer to the TL's control block
   ucSTAId:        identifier of the station being processed
   vosDataBuff:    pointer to the vos buffer

   IN/OUT
    pucBcMcUc:       pointer to buffer, will contain frame type on return

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:   invalid input parameters
    VOS_STATUS_E_BADMSG:  failed to extract info from data buffer
    VOS_STATUS_SUCCESS:   success

  SIDE EFFECTS
    None.
============================================================================*/
VOS_STATUS
WLANTL_FindFrameTypeBcMcUc
(
  WLANTL_CbType *pTLCb,
  v_U8_t        ucSTAId,
  vos_pkt_t     *vosDataBuff,
  v_U8_t        *pucBcMcUc
)
{
   VOS_STATUS    vosStatus = VOS_STATUS_SUCCESS;
   v_PVOID_t     aucBDHeader;
   v_PVOID_t     pvPeekData;
   /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

   /*------------------------------------------------------------------------
     Sanity check
    ------------------------------------------------------------------------*/
   if ((NULL == pTLCb) || 
       (NULL == vosDataBuff) || 
       (NULL == pucBcMcUc))
   {
      TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
             "WLAN TL:Invalid parameter in WLANTL_FindFrameTypeBcMcUc"));
      return VOS_STATUS_E_INVAL;
   }

   if ( NULL == pTLCb->atlSTAClients[ucSTAId] )
   {
       TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
           "WLAN TL:Client Memory was not allocated on %s", __func__));
       return VOS_STATUS_E_FAILURE;
   }

   /*------------------------------------------------------------------------
     Extract BD header and check if valid
    ------------------------------------------------------------------------*/
   vosStatus = WDA_DS_PeekRxPacketInfo(vosDataBuff, (v_PVOID_t)&aucBDHeader, 0/*Swap BD*/ );

   if (NULL == aucBDHeader)
   {
      TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
             "WLAN TL:WLANTL_FindFrameTypeBcMcUc - Cannot extract BD header"));
      VOS_ASSERT(0);
      return VOS_STATUS_E_BADMSG;
   }

   if ((0 == WDA_GET_RX_FT_DONE(aucBDHeader)) &&
       (0 != pTLCb->atlSTAClients[ucSTAId]->wSTADesc.ucSwFrameRXXlation))
   {
      /* Its an 802.11 frame, extract MAC address 1 */
      TLLOG2(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL:WLANTL_FindFrameTypeBcMcUc - 802.11 frame, peeking Addr1"));
      vosStatus = vos_pkt_peek_data(vosDataBuff, WLANTL_MAC_ADDR_ALIGN(1), 
                                    (v_PVOID_t)&pvPeekData, VOS_MAC_ADDR_SIZE);
   }
   else
   {
      /* Its an 802.3 frame, extract Destination MAC address */
      TLLOG2(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL:WLANTL_FindFrameTypeBcMcUc - 802.3 frame, peeking DA"));
      vosStatus = vos_pkt_peek_data(vosDataBuff, WLANTL_MAC_ADDR_ALIGN(0),
                                    (v_PVOID_t)&pvPeekData, VOS_MAC_ADDR_SIZE);
   }

   if (VOS_STATUS_SUCCESS != vosStatus) 
   {
      TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
             "WLAN TL:WLANTL_FindFrameTypeBcMcUc - Failed to peek MAC address"));
      return vosStatus;
   }

   if (((tANI_U8 *)pvPeekData)[0] == 0xff)
   {
      *pucBcMcUc = WLANTL_FRAME_TYPE_BCAST;
   }
   else
   {
      if ((((tANI_U8 *)pvPeekData)[0] & 0x01) == 0x01)
         *pucBcMcUc = WLANTL_FRAME_TYPE_MCAST;
      else
         *pucBcMcUc = WLANTL_FRAME_TYPE_UCAST;
   }

   TLLOG2(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
          "WLAN TL:WLANTL_FindFrameTypeBcMcUc - Addr1Byte1 is: %x", 
          ((tANI_U8 *)pvPeekData)[0]));

  return VOS_STATUS_SUCCESS;
}

#if 0
#ifdef WLAN_PERF 
/*==========================================================================
  FUNCTION    WLANTL_FastHwFwdDataFrame

  DESCRIPTION 
    Fast path function to quickly forward a data frame if HAL determines BD 
    signature computed here matches the signature inside current VOSS packet. 
    If there is a match, HAL and TL fills in the swapped packet length into 
    BD header and DxE header, respectively. Otherwise, packet goes back to 
    normal (slow) path and a new BD signature would be tagged into BD in this
    VOSS packet later by the WLANHAL_FillTxBd() function.

  DEPENDENCIES 
     
  PARAMETERS 

   IN
        pvosGCtx    VOS context
        vosDataBuff Ptr to VOSS packet
        pMetaInfo   For getting frame's TID
        pStaInfo    For checking STA type
    
   OUT
        pvosStatus  returned status
        puFastFwdOK Flag to indicate whether frame could be fast forwarded
   
  RETURN VALUE
    No return.   

  SIDE EFFECTS 
  
============================================================================*/
static void
WLANTL_FastHwFwdDataFrame
( 
  v_PVOID_t     pvosGCtx,
  vos_pkt_t*    vosDataBuff,
  VOS_STATUS*   pvosStatus,
  v_U32_t*       puFastFwdOK,
  WLANTL_MetaInfoType*  pMetaInfo,
  WLAN_STADescType*  pStaInfo
 
)
{
    v_PVOID_t   pvPeekData;
    v_U8_t      ucDxEBDWLANHeaderLen = WLANTL_BD_HEADER_LEN(0) + sizeof(WLANBAL_sDXEHeaderType); 
    v_U8_t      ucIsUnicast;
    WLANBAL_sDXEHeaderType  *pDxEHeader;
    v_PVOID_t   pvBDHeader;
    v_PVOID_t   pucBuffPtr;
    v_U16_t      usPktLen;

   /*-----------------------------------------------------------------------
    Extract packet length
    -----------------------------------------------------------------------*/

    vos_pkt_get_packet_length( vosDataBuff, &usPktLen);

   /*-----------------------------------------------------------------------
    Extract MAC address
    -----------------------------------------------------------------------*/
    *pvosStatus = vos_pkt_peek_data( vosDataBuff, 
                                 WLANTL_MAC_ADDR_ALIGN(0), 
                                 (v_PVOID_t)&pvPeekData, 
                                 VOS_MAC_ADDR_SIZE );

    if ( VOS_STATUS_SUCCESS != *pvosStatus ) 
    {
       TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                  "WLAN TL:Failed while attempting to extract MAC Addr %d", 
                  *pvosStatus));
       *pvosStatus = VOS_STATUS_E_INVAL;
       return;
    }

   /*-----------------------------------------------------------------------
    Reserve head room for DxE header, BD, and WLAN header
    -----------------------------------------------------------------------*/

    vos_pkt_reserve_head( vosDataBuff, &pucBuffPtr, 
                        ucDxEBDWLANHeaderLen );
    if ( NULL == pucBuffPtr )
    {
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                    "WLAN TL:No enough space in VOSS packet %pK for DxE/BD/WLAN header", vosDataBuff));
       *pvosStatus = VOS_STATUS_E_INVAL;
        return;
    }
    pDxEHeader = (WLANBAL_sDXEHeaderType  *)pucBuffPtr;
    pvBDHeader = (v_PVOID_t) &pDxEHeader[1];

    /* UMA Tx acceleration is enabled. 
     * UMA would help convert frames to 802.11, fill partial BD fields and 
     * construct LLC header. To further accelerate this kind of frames,
     * HAL would attempt to reuse the BD descriptor if the BD signature 
     * matches to the saved BD descriptor.
     */
     if(pStaInfo->wSTAType == WLAN_STA_IBSS)
        ucIsUnicast = !(((tANI_U8 *)pvPeekData)[0] & 0x01);
     else
        ucIsUnicast = 1;
 
     *puFastFwdOK = (v_U32_t) WLANHAL_TxBdFastFwd(pvosGCtx, pvPeekData, pMetaInfo->ucTID, ucIsUnicast, pvBDHeader, usPktLen );
    
      /* Can't be fast forwarded. Trim the VOS head back to original location. */
      if(! *puFastFwdOK){
          vos_pkt_trim_head(vosDataBuff, ucDxEBDWLANHeaderLen);
      }else{
        /* could be fast forwarded. Now notify BAL DxE header filling could be completely skipped
         */
        v_U32_t uPacketSize = WLANTL_BD_HEADER_LEN(0) + usPktLen;
        vos_pkt_set_user_data_ptr( vosDataBuff, VOS_PKT_USER_DATA_ID_BAL, 
                       (v_PVOID_t)uPacketSize);
        pDxEHeader->size  = SWAP_ENDIAN_UINT32(uPacketSize);
      }
     *pvosStatus = VOS_STATUS_SUCCESS;
      return;
}
#endif /*WLAN_PERF*/
#endif

#if 0
/*==========================================================================
   FUNCTION    WLANTL_PrepareBDHeader

  DESCRIPTION
    Inline function for preparing BD header before HAL processing.

  DEPENDENCIES
    Just notify HAL that suspend in TL is complete.

  PARAMETERS

   IN
    vosDataBuff:      vos data buffer
    ucDisableFrmXtl:  is frame xtl disabled

   OUT
    ppvBDHeader:      it will contain the BD header
    pvDestMacAdddr:   it will contain the destination MAC address
    pvosStatus:       status of the combined processing
    pusPktLen:        packet len.

  RETURN VALUE
    No return.

  SIDE EFFECTS

============================================================================*/
void
WLANTL_PrepareBDHeader
(
  vos_pkt_t*      vosDataBuff,
  v_PVOID_t*      ppvBDHeader,
  v_MACADDR_t*    pvDestMacAdddr,
  v_U8_t          ucDisableFrmXtl,
  VOS_STATUS*     pvosStatus,
  v_U16_t*        pusPktLen,
  v_U8_t          ucQosEnabled,
  v_U8_t          ucWDSEnabled,
  v_U8_t          extraHeadSpace
)
{
  v_U8_t      ucHeaderOffset;
  v_U8_t      ucHeaderLen;
  v_U8_t      ucBDHeaderLen = WLANTL_BD_HEADER_LEN(ucDisableFrmXtl);

  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  /*-------------------------------------------------------------------------
    Get header pointer from VOSS
    !!! make sure reserve head zeros out the memory
   -------------------------------------------------------------------------*/
  vos_pkt_get_packet_length( vosDataBuff, pusPktLen);

  if ( WLANTL_MAC_HEADER_LEN(ucDisableFrmXtl) > *pusPktLen )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL: Length of the packet smaller than expected network"
               " header %d", *pusPktLen ));

    *pvosStatus = VOS_STATUS_E_INVAL;
    return;
  }

  vos_pkt_reserve_head( vosDataBuff, ppvBDHeader,
                        ucBDHeaderLen );
  if ( NULL == *ppvBDHeader )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                "WLAN TL:VOSS packet corrupted on Attach BD header"));
    *pvosStatus = VOS_STATUS_E_INVAL;
    return;
  }

  /*-----------------------------------------------------------------------
    Extract MAC address
   -----------------------------------------------------------------------*/
  {
   v_SIZE_t usMacAddrSize = VOS_MAC_ADDR_SIZE;
   *pvosStatus = vos_pkt_extract_data( vosDataBuff,
                                     ucBDHeaderLen +
                                     WLANTL_MAC_ADDR_ALIGN(ucDisableFrmXtl),
                                     (v_PVOID_t)pvDestMacAdddr,
                                     &usMacAddrSize );
  }
  if ( VOS_STATUS_SUCCESS != *pvosStatus )
  {
     TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                "WLAN TL:Failed while attempting to extract MAC Addr %d",
                *pvosStatus));
  }
  else
  {
    /*---------------------------------------------------------------------
        Fill MPDU info fields:
          - MPDU data start offset
          - MPDU header start offset
          - MPDU header length
          - MPDU length - this is a 16b field - needs swapping
    --------------------------------------------------------------------*/
    ucHeaderOffset = ucBDHeaderLen;
    ucHeaderLen    = WLANTL_MAC_HEADER_LEN(ucDisableFrmXtl);

    if ( 0 != ucDisableFrmXtl )
    {
      if ( 0 != ucQosEnabled )
      {
        ucHeaderLen += WLANTL_802_11_HEADER_QOS_CTL;
      }

      // Similar to Qos we need something for WDS format !
      if ( ucWDSEnabled != 0 )
      {
        // If we have frame translation enabled
        ucHeaderLen    += WLANTL_802_11_HEADER_ADDR4_LEN;
      }
      if ( extraHeadSpace != 0 )
      {
        // Decrease the packet length with the extra padding after the header
        *pusPktLen = *pusPktLen - extraHeadSpace;
      }
    }

    WLANHAL_TX_BD_SET_MPDU_HEADER_LEN( *ppvBDHeader, ucHeaderLen);
    WLANHAL_TX_BD_SET_MPDU_HEADER_OFFSET( *ppvBDHeader, ucHeaderOffset);
    WLANHAL_TX_BD_SET_MPDU_DATA_OFFSET( *ppvBDHeader,
                                          ucHeaderOffset + ucHeaderLen + extraHeadSpace);
    WLANHAL_TX_BD_SET_MPDU_LEN( *ppvBDHeader, *pusPktLen);

    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                "WLAN TL: VALUES ARE HLen=%x Hoff=%x doff=%x len=%x ex=%d",
                ucHeaderLen, ucHeaderOffset, 
                (ucHeaderOffset + ucHeaderLen + extraHeadSpace), 
                *pusPktLen, extraHeadSpace));
  }/* if peek MAC success*/

}/* WLANTL_PrepareBDHeader */
#endif

//THIS IS A HACK AND NEEDS TO BE FIXED FOR CONCURRENCY
/*==========================================================================
  FUNCTION    WLAN_TLGetNextTxIds

  DESCRIPTION
    Gets the next station and next AC in the list that should be served by the TL.

    Multiple Station Scheduling and TL queue management. 

    4 HDD BC/MC data packet queue status is specified as Station 0's status. Weights used
    in WFQ algorith are initialized in WLANTL_OPEN and contained in tlConfigInfo field.
    Each station has fields of ucPktPending and AC mask to tell whether a AC has traffic
    or not.
      
    Stations are served in a round-robin fashion from highest priority to lowest priority.
    The number of round-robin times of each prioirty equals to the WFQ weights and differetiates
    the traffic of different prioirty. As such, stations can not provide low priority packets if
    high priority packets are all served.

  DEPENDENCIES

  PARAMETERS

   IN
   pvosGCtx:     pointer to the global vos context; a handle to TL's
                 control block can be extracted from its context

   OUT
   pucSTAId:    Station ID

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_SUCCESS:   Everything is good

  SIDE EFFECTS
   
   TL context contains currently served station ID in ucCurrentSTA field, currently served AC
   in uCurServedAC field, and unserved weights of current AC in uCurLeftWeight.
   When existing from the function, these three fields are changed accordingly.

============================================================================*/
VOS_STATUS
WLAN_TLAPGetNextTxIds
(
  v_PVOID_t    pvosGCtx,
  v_U8_t*      pucSTAId
)
{
  WLANTL_CbType*  pTLCb;
  v_U8_t          ucACFilter = 1;
  v_U8_t          ucNextSTA, ucTempSTA;
  v_BOOL_t        isServed = TRUE;  //current round has find a packet or not
  v_U8_t          ucACLoopNum = WLANTL_AC_HIGH_PRIO + 1; //number of loop to go
  v_U8_t          uFlowMask; // TX FlowMask from WDA
  uint8           ucACMask; 
  uint8           i = 0;
  uint8           j;
  uint8           minWeightSta;
  uint32_t        sta_bitmask = 0;
  /*------------------------------------------------------------------------
    Extract TL control block
  ------------------------------------------------------------------------*/
  //ENTER();

  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
      "WLAN TL:Invalid TL pointer from pvosGCtx on WLAN_TLAPGetNextTxIds"));
    return VOS_STATUS_E_FAULT;
  }

  if ( VOS_STATUS_SUCCESS != WDA_DS_GetTxFlowMask( pvosGCtx, &uFlowMask ) )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
      "WLAN TL:Failed to retrieve Flow control mask from WDA"));
    return VOS_STATUS_E_FAULT;
  }

  /* The flow mask does not differentiate between different ACs/Qs
   * since we use a single dxe channel for all ACs/Qs, hence it is
   * enough to check that there are dxe resources on data channel
   */
  uFlowMask &= WLANTL_DATA_FLOW_MASK;

  if (0 == uFlowMask)
  {
    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
           "WLAN TL: No resources to send packets"));

    // Setting STA Id to invalid if mask is 0
    *pucSTAId = WLAN_MAX_STA_COUNT;
    return VOS_STATUS_E_FAULT;
  }

  ucNextSTA = pTLCb->ucCurrentSTA;

  ++ucNextSTA;

  if ( WLAN_MAX_STA_COUNT <= ucNextSTA )
    ucNextSTA = 0;

    isServed = FALSE;
    if ( 0 == pTLCb->ucCurLeftWeight )
    {
      //current prioirty is done
      if ( WLANTL_AC_BK == (WLANTL_ACEnumType)pTLCb->uCurServedAC )
      {
        //end of current VO, VI, BE, BK loop. Reset priority.
        pTLCb->uCurServedAC = WLANTL_AC_HIGH_PRIO;
      }
      else 
      {
        pTLCb->uCurServedAC --;
      }

      pTLCb->ucCurLeftWeight =  pTLCb->tlConfigInfo.ucAcWeights[pTLCb->uCurServedAC];
 
    } // (0 == pTLCb->ucCurLeftWeight)

  ucTempSTA = ucNextSTA;
  minWeightSta = ucNextSTA;

  //decide how many loops to go. if current loop is partial, do one extra to make sure
  //we cover every station
  if ((1 == pTLCb->ucCurLeftWeight) && (ucNextSTA != 0))
  {
    ucACLoopNum ++; // now is 5 loops
  }

  /* Start with highest priority. ucNextSTA, pTLCb->uCurServedAC, pTLCb->ucCurLeftWeight
     all have previous values.*/
  for (; ucACLoopNum > 0;  ucACLoopNum--)
  {

    ucACFilter = 1 << pTLCb->uCurServedAC;

    // pTLCb->ucCurLeftWeight keeps previous results.
    for (; (pTLCb->ucCurLeftWeight > 0) ; pTLCb->ucCurLeftWeight-- )
    {

      for ( ; ucNextSTA < WLAN_MAX_STA_COUNT; ucNextSTA ++ )
      {
        if(NULL == pTLCb->atlSTAClients[ucNextSTA])
        {
            continue;
        }
        WLAN_TL_AC_ARRAY_2_MASK (pTLCb->atlSTAClients[ucNextSTA], ucACMask, i);

        if ( (0 == pTLCb->atlSTAClients[ucNextSTA]->ucExists) ||
             ((0 == pTLCb->atlSTAClients[ucNextSTA]->ucPktPending) && !(ucACMask)) ||
             (0 == (ucACMask & ucACFilter)) )

        {
          //current station does not exist or have any packet to serve.
          continue;
        }

        if ((WLANTL_STA_AUTHENTICATED != pTLCb->atlSTAClients[ucNextSTA]->tlState)
           || (pTLCb->atlSTAClients[ucNextSTA]->disassoc_progress == VOS_TRUE ))
        {
          TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                 "%s Sta %d not in auth state so skipping it.",
                 __func__, ucNextSTA));
          continue;
        }

        //go to next station if current station can't send due to flow control
        //Station is allowed to send when it is not in LWM mode. When station is in LWM mode,
        //station is allowed to send only after FW reports FW memory is below threshold and on-fly
        //packets are less then allowed value
        if ( (TRUE == pTLCb->atlSTAClients[ucNextSTA]->ucLwmModeEnabled) &&
             ((FALSE == pTLCb->atlSTAClients[ucNextSTA]->ucLwmEventReported) ||
                 (0 < pTLCb->atlSTAClients[ucNextSTA]->uBuffThresholdMax))
           )
        {
          continue;
        }

        /*
         * Initial weight is 0 is for all the stations. As part of FW TX stats
         * indication to host, good peer weight is updated to one and the
         * remaining peers weight is updated based on their RA rates and BTQM
         * queued frames length. TL skips fetching the packet until the station
         * has got chances equal to its weight.
         */
        if (pTLCb->atlSTAClients[ucNextSTA]->weight > WLANTL_GOOD_STA_WEIGHT) {
           if (pTLCb->atlSTAClients[ucNextSTA]->weight_count <=
               pTLCb->atlSTAClients[ucNextSTA]->weight)
           {
              if (pTLCb->atlSTAClients[minWeightSta]->weight <= 1)
                  minWeightSta = ucNextSTA;
              else if (pTLCb->atlSTAClients[ucNextSTA]->weight <
                  pTLCb->atlSTAClients[minWeightSta]->weight) {
                 minWeightSta = ucNextSTA;
              }
              sta_bitmask |= (1 << ucNextSTA);
              pTLCb->atlSTAClients[ucNextSTA]->weight_count++;
              continue;
           }
           else
              pTLCb->atlSTAClients[ucNextSTA]->weight_count = 0;
        }

        // Find a station. Weight is updated already.
        *pucSTAId = ucNextSTA;
        pTLCb->ucCurrentSTA = ucNextSTA;
        pTLCb->atlSTAClients[*pucSTAId]->ucCurrentAC = pTLCb->uCurServedAC;
  
        TLLOG4(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,
                   " TL serve one station AC: %d  W: %d StaId: %d",
                   pTLCb->uCurServedAC, pTLCb->ucCurLeftWeight, pTLCb->ucCurrentSTA ));
      
        pTLCb->ucCurLeftWeight--;
        return VOS_STATUS_SUCCESS;
      } //STA loop

      for (j = 0; j < ucTempSTA; j++) {
         if (NULL == pTLCb->atlSTAClients[j])
            continue;

         WLAN_TL_AC_ARRAY_2_MASK (pTLCb->atlSTAClients[j], ucACMask, i);

         if ((0 == pTLCb->atlSTAClients[j]->ucExists) ||
             ((0 == pTLCb->atlSTAClients[j]->ucPktPending) && !(ucACMask)) ||
             (0 == (ucACMask & ucACFilter)))
            continue;

         if ((WLANTL_STA_AUTHENTICATED != pTLCb->atlSTAClients[j]->tlState) ||
             (pTLCb->atlSTAClients[j]->disassoc_progress == VOS_TRUE)) {
            TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                  "%s Sta %d not in auth state so skipping it.",
                  __func__, ucNextSTA));
            continue;
         }

         if ((TRUE == pTLCb->atlSTAClients[j]->ucLwmModeEnabled) &&
            ((FALSE == pTLCb->atlSTAClients[j]->ucLwmEventReported) ||
             (0 < pTLCb->atlSTAClients[j]->uBuffThresholdMax)))
            continue;

         if (pTLCb->atlSTAClients[j]->weight > WLANTL_GOOD_STA_WEIGHT) {
            if (pTLCb->atlSTAClients[j]->weight_count <=
                pTLCb->atlSTAClients[j]->weight)
            {
               if (pTLCb->atlSTAClients[minWeightSta]->weight <= 1)
                  minWeightSta = j;
               else if (pTLCb->atlSTAClients[j]->weight <
                   pTLCb->atlSTAClients[minWeightSta]->weight) {
                  minWeightSta = j;
               }
               sta_bitmask |= (1 << j);
               pTLCb->atlSTAClients[j]->weight_count++;
               continue;
            }
            else
               pTLCb->atlSTAClients[j]->weight_count = 0;
         }

         *pucSTAId = j;
         pTLCb->ucCurrentSTA = j;
         pTLCb->atlSTAClients[*pucSTAId]->ucCurrentAC = pTLCb->uCurServedAC;

         TLLOG4(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,
                    " TL serve one station AC: %d  W: %d StaId: %d",
                   pTLCb->uCurServedAC, pTLCb->ucCurLeftWeight, pTLCb->ucCurrentSTA ));
         pTLCb->ucCurLeftWeight--;
         return VOS_STATUS_SUCCESS;
      }

      /* Fecth packet from the stations with minimum weight among them */
      if (pTLCb->atlSTAClients[minWeightSta] &&
          pTLCb->atlSTAClients[minWeightSta]->ucPktPending)
      {
         *pucSTAId = minWeightSta;
         pTLCb->ucCurrentSTA = minWeightSta;
         pTLCb->atlSTAClients[*pucSTAId]->ucCurrentAC = pTLCb->uCurServedAC;

         for (j = 0; sta_bitmask != 0; sta_bitmask >>= 1, j++)
         {
            if (0 == (sta_bitmask & 0x1))
               continue;

            if (minWeightSta == j)
               continue;
            /* To ensure fairness between stations */
            pTLCb->atlSTAClients[j]->weight_count +=
                             pTLCb->atlSTAClients[minWeightSta]->weight -
                             pTLCb->atlSTAClients[minWeightSta]->weight_count;
         }
         pTLCb->atlSTAClients[minWeightSta]->weight_count = 0;

         TLLOG4(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,
                    " TL serve one station AC: %d  W: %d StaId: %d",
                   pTLCb->uCurServedAC, pTLCb->ucCurLeftWeight, pTLCb->ucCurrentSTA ));
         pTLCb->ucCurLeftWeight--;
         return VOS_STATUS_SUCCESS;
      }

      ucNextSTA = 0;
      if ( FALSE == isServed )
      {
        //current loop finds no packet.no need to repeat for the same priority
        break;
      }
      //current loop is partial loop. go for one more loop.
      isServed = FALSE;

    } //Weight loop

    if (WLANTL_AC_BK == pTLCb->uCurServedAC)
    {
      pTLCb->uCurServedAC = WLANTL_AC_HIGH_PRIO;
    }
    else
    {
      pTLCb->uCurServedAC--;
    }
    pTLCb->ucCurLeftWeight =  pTLCb->tlConfigInfo.ucAcWeights[pTLCb->uCurServedAC];

  }// AC loop

  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                   " TL can't find one station to serve" ));

  pTLCb->uCurServedAC = WLANTL_AC_BK;
  pTLCb->ucCurLeftWeight = 1;
  //invalid number will be captured by caller
  pTLCb->ucCurrentSTA = WLAN_MAX_STA_COUNT; 

  *pucSTAId = pTLCb->ucCurrentSTA;
  return VOS_STATUS_E_FAULT;
}


/*==========================================================================
  FUNCTION    WLAN_TLGetNextTxIds

  DESCRIPTION
    Gets the next station and next AC in the list

  DEPENDENCIES

  PARAMETERS

   IN
   pvosGCtx:     pointer to the global vos context; a handle to TL's
                 control block can be extracted from its context

   OUT
   pucSTAId:    Station ID


  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLAN_TLGetNextTxIds
(
  v_PVOID_t    pvosGCtx,
  v_U8_t*      pucSTAId
)
{
  WLANTL_CbType*  pTLCb;
  v_U8_t          ucNextAC;
  v_U8_t          ucNextSTA; 
  v_U8_t          ucCount; 
  v_U8_t          uFlowMask; // TX FlowMask from WDA
  v_U8_t          ucACMask = 0;
  v_U8_t          i = 0; 

  tBssSystemRole systemRole; //RG HACK to be removed
  tpAniSirGlobal pMac;

  pMac = vos_get_context(VOS_MODULE_ID_PE, pvosGCtx);
  if ( NULL == pMac )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                      "%s: Invalid pMac", __func__));
    return VOS_STATUS_E_FAULT;
  }

  systemRole = wdaGetGlobalSystemRole(pMac);

  /*------------------------------------------------------------------------
    Extract TL control block
  ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
      "WLAN TL:Invalid TL pointer from pvosGCtx on WLAN_TLGetNextTxIds"));
    return VOS_STATUS_E_FAULT;
  }

#ifdef FEATURE_WLAN_TDLS
  if ((eSYSTEM_AP_ROLE == systemRole) ||
      (eSYSTEM_STA_IN_IBSS_ROLE == systemRole) ||
      (vos_concurrent_open_sessions_running()) || pTLCb->ucTdlsPeerCount)
#else
  if ((eSYSTEM_AP_ROLE == systemRole) ||
      (eSYSTEM_STA_IN_IBSS_ROLE == systemRole) ||
      (vos_concurrent_open_sessions_running()))
#endif
  {
    return WLAN_TLAPGetNextTxIds(pvosGCtx,pucSTAId);
  }


  if ( VOS_STATUS_SUCCESS != WDA_DS_GetTxFlowMask( pvosGCtx, &uFlowMask ) )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
      "WLAN TL:Failed to retrieve Flow control mask from WDA"));
    return VOS_STATUS_E_FAULT;
  }

  /* The flow mask does not differentiate between different ACs/Qs
   * since we use a single dxe channel for all ACs/Qs, hence it is
   * enough to check that there are dxe resources on data channel
   */
  uFlowMask &= WLANTL_DATA_FLOW_MASK;

  if (0 == uFlowMask)
  {
    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
      "WLAN TL: No resources to send packets"));

    // Setting STA id to invalid if mask is 0
    *pucSTAId = WLAN_MAX_STA_COUNT;
    return VOS_STATUS_E_FAULT;
  }

  /*STA id - no priority yet implemented */
  /*-----------------------------------------------------------------------
    Choose the next STA for tx - for now go in a round robin fashion
    through all the stations that have pending packets     
  -------------------------------------------------------------------------*/
  ucNextSTA = pTLCb->ucCurrentSTA;
  
  pTLCb->ucCurrentSTA = WLAN_MAX_STA_COUNT; 
  for ( ucCount = 0; 
        ucCount < WLAN_MAX_STA_COUNT;
        ucCount++ )
  {
    ucNextSTA = ( (ucNextSTA+1) >= WLAN_MAX_STA_COUNT )?0:(ucNextSTA+1);
    if(NULL == pTLCb->atlSTAClients[ucNextSTA])
    {
        continue;
    }

    if ((pTLCb->atlSTAClients[ucNextSTA]->weight > WLANTL_GOOD_STA_WEIGHT) &&
        (pTLCb->atlSTAClients[ucNextSTA]->ucPktPending)) {
       if (pTLCb->atlSTAClients[ucNextSTA]->weight_count <=
           pTLCb->atlSTAClients[ucNextSTA]->weight) {
          pTLCb->atlSTAClients[ucNextSTA]->weight_count++;
          continue;
       }
       else
          pTLCb->atlSTAClients[ucNextSTA]->weight_count = 0;
    }

    if (( pTLCb->atlSTAClients[ucNextSTA]->ucExists ) &&
        ( pTLCb->atlSTAClients[ucNextSTA]->ucPktPending ))
    {
      if (WLANTL_STA_AUTHENTICATED == pTLCb->atlSTAClients[ucNextSTA]->tlState)
      {
        TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
               "STA ID: %d on WLAN_TLGetNextTxIds", *pucSTAId));
        pTLCb->ucCurrentSTA = ucNextSTA;
        break;
      }
      else
      {
        TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
               "%s Sta %d is not in auth state, skipping this sta.",
               __func__, ucNextSTA));
      }
    }
  }

  *pucSTAId = pTLCb->ucCurrentSTA;

  if ( WLANTL_STA_ID_INVALID( *pucSTAId ) )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
      "WLAN TL:No station registered with TL at this point"));

    return VOS_STATUS_E_FAULT;

  }

  /*Convert the array to a mask for easier operation*/
  WLAN_TL_AC_ARRAY_2_MASK( pTLCb->atlSTAClients[*pucSTAId], ucACMask, i);
  
  if ( 0 == ucACMask )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
      "WLAN TL: Mask 0 "
      "STA ID: %d on WLAN_TLGetNextTxIds", *pucSTAId));

     /*setting STA id to invalid if mask is 0*/
     *pucSTAId = WLAN_MAX_STA_COUNT;

     return VOS_STATUS_E_FAULT;
  }

  /*-----------------------------------------------------------------------
    AC is updated whenever a packet is fetched from HDD -> the current
    weight of such an AC cannot be 0 -> in this case TL is expected to
    exit this function at this point during the main Tx loop
  -----------------------------------------------------------------------*/
  if ( 0 < pTLCb->atlSTAClients[*pucSTAId]->ucCurrentWeight  )
  {
    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                  "WLAN TL: Maintaining serviced AC to: %d for Weight: %d",
                  pTLCb->atlSTAClients[*pucSTAId]->ucCurrentAC ,
                  pTLCb->atlSTAClients[*pucSTAId]->ucCurrentWeight));
    return VOS_STATUS_SUCCESS;
  }

  /*-----------------------------------------------------------------------
     Choose highest priority AC - !!! optimize me
  -----------------------------------------------------------------------*/
  ucNextAC = pTLCb->atlSTAClients[*pucSTAId]->ucCurrentAC;
    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "Next AC: %d", ucNextAC));

  while ( 0 != ucACMask )
  {
    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             " AC Mask: %d Next: %d Res : %d",
               ucACMask, ( 1 << ucNextAC ), ( ucACMask & ( 1 << ucNextAC ))));

    if ( 0 != ( ucACMask & ( 1 << ucNextAC )))
    {
       pTLCb->atlSTAClients[*pucSTAId]->ucCurrentAC     =
                                   (WLANTL_ACEnumType)ucNextAC;
       pTLCb->atlSTAClients[*pucSTAId]->ucCurrentWeight =
                       pTLCb->tlConfigInfo.ucAcWeights[ucNextAC];

        TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                  "WLAN TL: Switching serviced AC to: %d with Weight: %d",
                  pTLCb->atlSTAClients[*pucSTAId]->ucCurrentAC ,
                  pTLCb->atlSTAClients[*pucSTAId]->ucCurrentWeight));
       break;
    }

    if (ucNextAC == WLANTL_AC_BK)
        ucNextAC = WLANTL_AC_HIGH_PRIO;
    else
        ucNextAC--;

    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
               "Next AC %d", ucNextAC));
  }

  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             " C AC: %d C W: %d",
             pTLCb->atlSTAClients[*pucSTAId]->ucCurrentAC,
             pTLCb->atlSTAClients[*pucSTAId]->ucCurrentWeight));

  return VOS_STATUS_SUCCESS;
}/* WLAN_TLGetNextTxIds */



/*==========================================================================
      DEFAULT HANDLERS: Registered at initialization with TL
  ==========================================================================*/

/*==========================================================================

  FUNCTION    WLANTL_MgmtFrmRxDefaultCb

  DESCRIPTION
    Default Mgmt Frm rx callback: asserts all the time. If this function gets
    called  it means there is no registered rx cb pointer for Mgmt Frm.

  DEPENDENCIES

  PARAMETERS
    Not used.

  RETURN VALUE

   VOS_STATUS_E_FAILURE: Always FAILURE.

============================================================================*/
VOS_STATUS
WLANTL_MgmtFrmRxDefaultCb
(
  v_PVOID_t  pvosGCtx,
  v_PVOID_t  vosBuff
)
{
  if ( NULL != vosBuff )
  {
    TLLOGP(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_FATAL,
             "WLAN TL:Fatal failure: No registered Mgmt Frm client on pkt RX"));
    /* Drop packet */
    vos_pkt_return_packet((vos_pkt_t *)vosBuff);
  }

      TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                 "WLAN TL: No registered Mgmt Frm client on pkt RX. Load/Unload in progress, Ignore"));

  return VOS_STATUS_E_FAILURE;
}/*WLANTL_MgmtFrmRxDefaultCb*/

/*==========================================================================

  FUNCTION   WLANTL_BAPRxDefaultCb

  DESCRIPTION
    Default BAP rx callback: asserts all the time. If this function gets
    called  it means there is no registered rx cb pointer for BAP.

  DEPENDENCIES

  PARAMETERS
    Not used.

  RETURN VALUE

   VOS_STATUS_E_FAILURE: Always FAILURE.

============================================================================*/
VOS_STATUS
WLANTL_BAPRxDefaultCb
(
  v_PVOID_t  pvosGCtx,
  vos_pkt_t*       vosDataBuff,
  WLANTL_BAPFrameEnumType frameType
)
{
  TLLOGP(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_FATAL,
             "WLAN TL:Fatal failure: No registered BAP client on BAP pkt RX"));
#ifndef BTAMP_TEST
  VOS_ASSERT(0);
#endif
  return VOS_STATUS_E_FAILURE;
}/*WLANTL_MgmtFrmRxDefaultCb*/

/*==========================================================================

  FUNCTION    WLANTL_STARxDefaultCb

  DESCRIPTION
    Default STA rx callback: asserts all the time. If this function gets
    called  it means there is no registered rx cb pointer for station.
    (Mem corruption most likely, it should never happen)

  DEPENDENCIES

  PARAMETERS
    Not used.

  RETURN VALUE

    VOS_STATUS_E_FAILURE: Always FAILURE.

============================================================================*/
VOS_STATUS
WLANTL_STARxDefaultCb
(
  v_PVOID_t               pvosGCtx,
  vos_pkt_t*              vosDataBuff,
  v_U8_t                  ucSTAId,
  WLANTL_RxMetaInfoType*  pRxMetaInfo
)
{
  TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
       "WLAN TL: No registered STA client rx cb for STAID: %d dropping pkt",
               ucSTAId));
  vos_pkt_return_packet(vosDataBuff);
  return VOS_STATUS_SUCCESS;
}/*WLANTL_MgmtFrmRxDefaultCb*/


/*==========================================================================

  FUNCTION    WLANTL_STAFetchPktDefaultCb

  DESCRIPTION
    Default fetch callback: asserts all the time. If this function gets
    called  it means there is no registered fetch cb pointer for station.
    (Mem corruption most likely, it should never happen)

  DEPENDENCIES

  PARAMETERS
    Not used.

  RETURN VALUE

    VOS_STATUS_E_FAILURE: Always FAILURE.

============================================================================*/
VOS_STATUS
WLANTL_STAFetchPktDefaultCb
(
  v_PVOID_t              pvosGCtx,
  v_U8_t*                pucSTAId,
  WLANTL_ACEnumType      ucAC,
  vos_pkt_t**            vosDataBuff,
  WLANTL_MetaInfoType*   tlMetaInfo
)
{
  TLLOGP(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_FATAL,
             "WLAN TL:Fatal failure: No registered STA client on data pkt RX"));
  VOS_ASSERT(0);
  return VOS_STATUS_E_FAILURE;
}/*WLANTL_MgmtFrmRxDefaultCb*/

/*==========================================================================

  FUNCTION    WLANTL_TxCompDefaultCb

  DESCRIPTION
    Default tx complete handler. It will release the completed pkt to
    prevent memory leaks.

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to
                    TL/HAL/PE/BAP/HDD control block can be extracted from
                    its context
    vosDataBuff:   pointer to the VOSS data buffer that was transmitted
    wTxSTAtus:      status of the transmission


  RETURN VALUE
    The result code associated with performing the operation; please
    check vos_pkt_return_packet for possible error codes.

    Please check  vos_pkt_return_packet API for possible return values.

============================================================================*/
VOS_STATUS
WLANTL_TxCompDefaultCb
(
 v_PVOID_t      pvosGCtx,
 vos_pkt_t*     vosDataBuff,
 VOS_STATUS     wTxSTAtus
)
{
  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
         "WLAN TL:TXComp not registered, releasing pkt to prevent mem leak"));
  return vos_pkt_return_packet(vosDataBuff);
}/*WLANTL_TxCompDefaultCb*/


/*==========================================================================
      Cleanup functions
  ==========================================================================*/

/*==========================================================================

  FUNCTION    WLANTL_CleanCB

  DESCRIPTION
    Cleans TL control block

  DEPENDENCIES

  PARAMETERS

    IN
    pTLCb:       pointer to TL's control block
    ucEmpty:     set if TL has to clean up the queues and release pedning pkts

  RETURN VALUE
    The result code associated with performing the operation

     VOS_STATUS_E_INVAL:   invalid input parameters
     VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_CleanCB
(
  WLANTL_CbType*  pTLCb,
  v_U8_t      ucEmpty
)
{
  v_U8_t ucIndex;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*-------------------------------------------------------------------------
    Sanity check
   -------------------------------------------------------------------------*/
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid parameter sent on WLANTL_CleanCB"));
    return VOS_STATUS_E_INVAL;
  }

  /* number of packets sent to BAL waiting for tx complete confirmation */
  pTLCb->usPendingTxCompleteCount = 0;

  /* global suspend flag */
   vos_atomic_set_U8( &pTLCb->ucTxSuspended, 1);

  /* resource flag */
  pTLCb->uResCount = 0;


  /*-------------------------------------------------------------------------
    Client stations
   -------------------------------------------------------------------------*/
  for ( ucIndex = 0; ucIndex < WLAN_MAX_STA_COUNT ; ucIndex++)
  {
    if(NULL != pTLCb->atlSTAClients[ucIndex])
    {
        WLANTL_CleanSTA( pTLCb->atlSTAClients[ucIndex], ucEmpty);
    }
  }

  /*-------------------------------------------------------------------------
    Management Frame client
   -------------------------------------------------------------------------*/
  pTLCb->tlMgmtFrmClient.ucExists = 0;

  if ( ( 0 != ucEmpty) &&
       ( NULL != pTLCb->tlMgmtFrmClient.vosPendingDataBuff ))
  {
    vos_pkt_return_packet(pTLCb->tlMgmtFrmClient.vosPendingDataBuff);
  }

  pTLCb->tlMgmtFrmClient.vosPendingDataBuff  = NULL;

  /* set to a default cb in order to prevent constant checking for NULL */
  pTLCb->tlMgmtFrmClient.pfnTlMgmtFrmRx = WLANTL_MgmtFrmRxDefaultCb;

  /*-------------------------------------------------------------------------
    BT AMP client
   -------------------------------------------------------------------------*/
  pTLCb->tlBAPClient.ucExists = 0;

  if (( 0 != ucEmpty) &&
      ( NULL != pTLCb->tlBAPClient.vosPendingDataBuff ))
  {
    vos_pkt_return_packet(pTLCb->tlBAPClient.vosPendingDataBuff);
  }
  
  if (( 0 != ucEmpty) &&
      ( NULL != pTLCb->vosDummyBuf ))
  {
    vos_pkt_return_packet(pTLCb->vosDummyBuf);
  }

  pTLCb->tlBAPClient.vosPendingDataBuff  = NULL;

  pTLCb->vosDummyBuf = NULL;
  pTLCb->vosTempBuf  = NULL;
  pTLCb->ucCachedSTAId = WLAN_MAX_STA_COUNT;

  /* set to a default cb in order to prevent constant checking for NULL */
  pTLCb->tlBAPClient.pfnTlBAPRx = WLANTL_BAPRxDefaultCb;

  pTLCb->ucRegisteredStaId = WLAN_MAX_STA_COUNT;

  return VOS_STATUS_SUCCESS;

}/* WLANTL_CleanCB*/

/*==========================================================================

  FUNCTION    WLANTL_CleanSTA

  DESCRIPTION
    Cleans a station control block.

  DEPENDENCIES

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context
    ucEmpty:        if set the queues and pending pkts will be emptyed

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:   invalid input parameters
    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_CleanSTA
(
  WLANTL_STAClientType*  ptlSTAClient,
  v_U8_t             ucEmpty
)
{
  v_U8_t  ucIndex;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*-------------------------------------------------------------------------
    Sanity check
   -------------------------------------------------------------------------*/
  if ( NULL == ptlSTAClient )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid parameter sent on WLANTL_CleanSTA"));
    return VOS_STATUS_E_INVAL;
  }

  /*------------------------------------------------------------------------
    Clear station from TL
   ------------------------------------------------------------------------*/
  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL: Clearing STA Client ID: %d, Empty flag: %d",
             ptlSTAClient->wSTADesc.ucSTAId, ucEmpty ));

  ptlSTAClient->pfnSTARx          = WLANTL_STARxDefaultCb;
  ptlSTAClient->pfnSTATxComp      = WLANTL_TxCompDefaultCb;
  ptlSTAClient->pfnSTAFetchPkt    = WLANTL_STAFetchPktDefaultCb;

  ptlSTAClient->tlState           = WLANTL_STA_INIT;
  ptlSTAClient->tlPri             = WLANTL_STA_PRI_NORMAL;

  vos_zero_macaddr( &ptlSTAClient->wSTADesc.vSTAMACAddress );
  vos_zero_macaddr( &ptlSTAClient->wSTADesc.vBSSIDforIBSS );
  vos_zero_macaddr( &ptlSTAClient->wSTADesc.vSelfMACAddress );

  ptlSTAClient->wSTADesc.ucSTAId  = 0;
  ptlSTAClient->wSTADesc.wSTAType = WLAN_STA_MAX;

  ptlSTAClient->wSTADesc.ucQosEnabled     = 0;
  ptlSTAClient->wSTADesc.ucAddRmvLLC      = 0;
  ptlSTAClient->wSTADesc.ucSwFrameTXXlation = 0;
  ptlSTAClient->wSTADesc.ucSwFrameRXXlation = 0;
  ptlSTAClient->wSTADesc.ucProtectedFrame = 0;
  ptlSTAClient->disassoc_progress = VOS_FALSE;
  /*-------------------------------------------------------------------------
    AMSDU information for the STA
   -------------------------------------------------------------------------*/
  if ( ( 0 != ucEmpty ) &&
       ( NULL != ptlSTAClient->vosAMSDUChainRoot ))
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_FATAL,
               "WLAN TL:Non NULL vosAMSDUChainRoot on WLANTL_CleanSTA, "
               "suspecting a memory corruption"));

  }

  ptlSTAClient->vosAMSDUChain     = NULL;
  ptlSTAClient->vosAMSDUChainRoot = NULL;

  vos_mem_zero( (v_PVOID_t)ptlSTAClient->aucMPDUHeader,
                 WLANTL_MPDU_HEADER_LEN);
  ptlSTAClient->ucMPDUHeaderLen    = 0;

  /*-------------------------------------------------------------------------
    Reordering information for the STA
   -------------------------------------------------------------------------*/
  for ( ucIndex = 0; ucIndex < WLAN_MAX_TID ; ucIndex++)
  {
    if(0 == ptlSTAClient->atlBAReorderInfo[ucIndex].ucExists)
    {
      continue;
    }
    if(NULL != ptlSTAClient->atlBAReorderInfo[ucIndex].reorderBuffer)
    {
      ptlSTAClient->atlBAReorderInfo[ucIndex].reorderBuffer->isAvailable = VOS_TRUE;
      memset(&ptlSTAClient->atlBAReorderInfo[ucIndex].reorderBuffer->arrayBuffer[0], 0, WLANTL_MAX_WINSIZE * sizeof(v_PVOID_t));
    }
    vos_timer_destroy(&ptlSTAClient->atlBAReorderInfo[ucIndex].agingTimer);
    memset(&ptlSTAClient->atlBAReorderInfo[ucIndex], 0, sizeof(WLANTL_BAReorderType));
  }

  /*-------------------------------------------------------------------------
     QOS information for the STA
    -------------------------------------------------------------------------*/
   ptlSTAClient->ucCurrentAC     = WLANTL_AC_HIGH_PRIO;
   ptlSTAClient->ucCurrentWeight = 0;
   ptlSTAClient->ucServicedAC    = WLANTL_AC_BK;

   vos_mem_zero( ptlSTAClient->aucACMask, sizeof(ptlSTAClient->aucACMask));
   vos_mem_zero( &ptlSTAClient->wUAPSDInfo, sizeof(ptlSTAClient->wUAPSDInfo));


  /*--------------------------------------------------------------------
    Stats info
    --------------------------------------------------------------------*/
   vos_mem_zero( ptlSTAClient->auRxCount,
                 sizeof(ptlSTAClient->auRxCount[0])* WLAN_MAX_TID);
   vos_mem_zero( ptlSTAClient->auTxCount,
                 sizeof(ptlSTAClient->auTxCount[0])* WLAN_MAX_TID);
   ptlSTAClient->rssiAvg = 0;

   /*Tx not suspended and station fully registered*/
   vos_atomic_set_U8( &ptlSTAClient->ucTxSuspended, 0);
   vos_atomic_set_U8( &ptlSTAClient->ucNoMoreData, 1);

  if ( 0 == ucEmpty )
  {
    ptlSTAClient->wSTADesc.ucUcastSig       = WLAN_TL_INVALID_U_SIG;
    ptlSTAClient->wSTADesc.ucBcastSig       = WLAN_TL_INVALID_B_SIG;
  }

  ptlSTAClient->ucExists       = 0;

  /*--------------------------------------------------------------------
    Statistics info 
    --------------------------------------------------------------------*/
  memset(&ptlSTAClient->trafficStatistics,
         0,
         sizeof(WLANTL_TRANSFER_STA_TYPE));

  /*fix me!!: add new values from the TL Cb for cleanup */
  return VOS_STATUS_SUCCESS;
}/* WLANTL_CleanSTA */


/*==========================================================================
  FUNCTION    WLANTL_EnableUAPSDForAC

  DESCRIPTION
   Called by HDD to enable UAPSD. TL in turn calls WDA API to enable the
   logic in FW/SLM to start sending trigger frames. Previously TL had the
   trigger frame logic which later moved down to FW. Hence
   HDD -> TL -> WDA -> FW call flow.

  DEPENDENCIES
    The TL must be initialized before this function can be called.

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context
    ucSTAId:        station Id
    ucAC:           AC for which U-APSD is being enabled
    ucTid:          TID for which U-APSD is setup
    ucUP:           used to place in the trigger frame generation
    ucServiceInt:   service interval used by TL to send trigger frames
    ucSuspendInt:   suspend interval used by TL to determine that an
                    app is idle and should start sending trigg frms less often
    wTSDir:         direction of TSpec

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_EnableUAPSDForAC
(
  v_PVOID_t          pvosGCtx,
  v_U8_t             ucSTAId,
  WLANTL_ACEnumType  ucAC,
  v_U8_t             ucTid,
  v_U8_t             ucUP,
  v_U32_t            uServiceInt,
  v_U32_t            uSuspendInt,
  WLANTL_TSDirType   wTSDir
)
{

  WLANTL_CbType*      pTLCb      = NULL;
  VOS_STATUS          vosStatus   = VOS_STATUS_SUCCESS;
  tUapsdInfo          halUAPSDInfo; 
 /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if (( NULL == pTLCb ) || WLANTL_STA_ID_INVALID( ucSTAId )
      ||   WLANTL_AC_INVALID(ucAC))
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid input params on WLANTL_EnableUAPSDForAC"
               " TL: %pK  STA: %d  AC: %d",
               pTLCb, ucSTAId, ucAC));
    return VOS_STATUS_E_FAULT;
  }

  if ( NULL == pTLCb->atlSTAClients[ucSTAId] )
  {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Client Memory was not allocated on %s", __func__));
      return VOS_STATUS_E_FAILURE;
  }

  /*Set this flag in order to remember that this is a trigger enabled AC*/
  pTLCb->atlSTAClients[ucSTAId]->wUAPSDInfo[ucAC].ucSet = 1;

#ifdef FEATURE_WLAN_TDLS
  if(pTLCb->atlSTAClients[ucSTAId]->wSTADesc.wSTAType != WLAN_STA_TDLS)
#endif
  {
    if( 0 == uServiceInt )
    {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Input params on WLANTL_EnableUAPSDForAC"
               " SI: %d", uServiceInt ));
    }

    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
               "WLAN TL:Enabling U-APSD in FW for STA: %d AC: %d SI: %d SPI: %d "
               "DI: %d",
               ucSTAId, ucAC, uServiceInt, uSuspendInt,
               pTLCb->tlConfigInfo.uDelayedTriggerFrmInt));

    /*Save all info for HAL*/
    halUAPSDInfo.staidx         = ucSTAId;
    halUAPSDInfo.ac             = ucAC;
    halUAPSDInfo.up             = ucUP;
    halUAPSDInfo.srvInterval    = uServiceInt;
    halUAPSDInfo.susInterval    = uSuspendInt;
    halUAPSDInfo.delayInterval  = pTLCb->tlConfigInfo.uDelayedTriggerFrmInt;

    /*Notify HAL*/
    vosStatus = WDA_EnableUapsdAcParams(pvosGCtx, ucSTAId, &halUAPSDInfo);
  }
  return vosStatus;

}/*WLANTL_EnableUAPSDForAC*/


/*==========================================================================
  FUNCTION    WLANTL_DisableUAPSDForAC

  DESCRIPTION
   Called by HDD to disable UAPSD. TL in turn calls WDA API to disable the
   logic in FW/SLM to stop sending trigger frames. Previously TL had the
   trigger frame logic which later moved down to FW. Hence
   HDD -> TL -> WDA -> FW call flow.

  DEPENDENCIES
    The TL must be initialized before this function can be called.

  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context
    ucSTAId:        station Id
    ucAC:         AC for which U-APSD is being enabled


  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_SUCCESS:   Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_DisableUAPSDForAC
(
  v_PVOID_t          pvosGCtx,
  v_U8_t             ucSTAId,
  WLANTL_ACEnumType  ucAC
)
{
  WLANTL_CbType* pTLCb;
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
    Extract TL control block
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if (( NULL == pTLCb ) || WLANTL_STA_ID_INVALID( ucSTAId )
      ||   WLANTL_AC_INVALID(ucAC) )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid input params on WLANTL_DisableUAPSDForAC"
               " TL: %pK  STA: %d  AC: %d", pTLCb, ucSTAId, ucAC ));
    return VOS_STATUS_E_FAULT;
  }

  if ( NULL == pTLCb->atlSTAClients[ucSTAId] )
  {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Client Memory was not allocated on %s", __func__));
      return VOS_STATUS_E_FAILURE;
  }

  /*Reset this flag as this is no longer a trigger enabled AC*/
  pTLCb->atlSTAClients[ucSTAId]->wUAPSDInfo[ucAC].ucSet = 1;

  TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
             "WLAN TL:Disabling U-APSD in FW for STA: %d AC: %d ",
             ucSTAId, ucAC));

  /*Notify HAL*/
  WDA_DisableUapsdAcParams(pvosGCtx, ucSTAId, ucAC);

  return VOS_STATUS_SUCCESS;
}/* WLANTL_DisableUAPSDForAC */

#if defined WLAN_FEATURE_NEIGHBOR_ROAMING
/*==========================================================================
  FUNCTION     WLANTL_RegRSSIIndicationCB

  DESCRIPTION  Registration function to get notification if RSSI cross
               threshold.
               Client should register threshold, direction, and notification
               callback function pointer

  DEPENDENCIES NONE
    
  PARAMETERS   in pAdapter - Global handle
               in rssiValue - RSSI threshold value
               in triggerEvent - Cross direction should be notified
                                 UP, DOWN, and CROSS
               in crossCBFunction - Notification CB Function
               in usrCtxt - user context

  RETURN VALUE VOS_STATUS

  SIDE EFFECTS NONE
  
============================================================================*/
VOS_STATUS WLANTL_RegRSSIIndicationCB
(
   v_PVOID_t                       pAdapter,
   v_S7_t                          rssiValue,
   v_U8_t                          triggerEvent,
   WLANTL_RSSICrossThresholdCBType crossCBFunction,
   VOS_MODULE_ID                   moduleID,
   v_PVOID_t                       usrCtxt
)
{
   VOS_STATUS                     status = VOS_STATUS_SUCCESS;

   status = WLANTL_HSRegRSSIIndicationCB(pAdapter,
                                         rssiValue,
                                         triggerEvent,
                                         crossCBFunction,
                                         moduleID,
                                         usrCtxt);

   return status;
}

/*==========================================================================
  FUNCTION     WLANTL_DeregRSSIIndicationCB

  DESCRIPTION  Remove specific threshold from list

  DEPENDENCIES NONE
    
  PARAMETERS   in pAdapter - Global handle
               in rssiValue - RSSI threshold value
               in triggerEvent - Cross direction should be notified
                                 UP, DOWN, and CROSS
   
  RETURN VALUE VOS_STATUS

  SIDE EFFECTS NONE
  
============================================================================*/
VOS_STATUS WLANTL_DeregRSSIIndicationCB
(
   v_PVOID_t                       pAdapter,
   v_S7_t                          rssiValue,
   v_U8_t                          triggerEvent,
   WLANTL_RSSICrossThresholdCBType crossCBFunction,
   VOS_MODULE_ID                   moduleID
)
{
   VOS_STATUS                     status = VOS_STATUS_SUCCESS;

   status = WLANTL_HSDeregRSSIIndicationCB(pAdapter,
                                           rssiValue,
                                           triggerEvent,
                                           crossCBFunction,
                                           moduleID);
   return status;
}

/*==========================================================================
  FUNCTION     WLANTL_SetAlpha

  DESCRIPTION  ALPLA is weight value to calculate AVG RSSI
               avgRSSI = (ALPHA * historyRSSI) + ((10 - ALPHA) * newRSSI)
               avgRSSI has (ALPHA * 10)% of history RSSI weight and
               (10 - ALPHA)% of newRSSI weight
               This portion is dynamically configurable.
               Default is ?

  DEPENDENCIES NONE
    
  PARAMETERS   in pAdapter - Global handle
               in valueAlpah - ALPHA
   
  RETURN VALUE VOS_STATUS

  SIDE EFFECTS NONE
  
============================================================================*/
VOS_STATUS WLANTL_SetAlpha
(
   v_PVOID_t pAdapter,
   v_U8_t    valueAlpha
)
{
   VOS_STATUS                     status = VOS_STATUS_SUCCESS;

   status = WLANTL_HSSetAlpha(pAdapter, valueAlpha);
   return status;
}

/*==========================================================================

   FUNCTION

   DESCRIPTION 
    
   PARAMETERS 

   RETURN VALUE

============================================================================*/
VOS_STATUS WLANTL_BMPSRSSIRegionChangedNotification
(
   v_PVOID_t             pAdapter,
   tpSirRSSINotification pRSSINotification
)
{
   VOS_STATUS                     status = VOS_STATUS_SUCCESS;

   status = WLANTL_HSBMPSRSSIRegionChangedNotification(pAdapter, pRSSINotification);
   return status;
}

/*==========================================================================
  FUNCTION     WLANTL_RegGetTrafficStatus

  DESCRIPTION  Registration function for traffic status monitoring
               During measure period count data frames.
               If frame count is larger then IDLE threshold set as traffic ON
               or OFF.
               And traffic status is changed send report to client with
               registered callback function

  DEPENDENCIES NONE
    
  PARAMETERS   in pAdapter - Global handle
               in idleThreshold - Traffic on or off threshold
               in measurePeriod - Traffic state check period
               in trfficStatusCB - traffic status changed notification
                                   CB function
               in usrCtxt - user context
   
  RETURN VALUE VOS_STATUS

  SIDE EFFECTS NONE
  
============================================================================*/
VOS_STATUS WLANTL_RegGetTrafficStatus
(
   v_PVOID_t                          pAdapter,
   v_U32_t                            idleThreshold,
   v_U32_t                            measurePeriod,
   WLANTL_TrafficStatusChangedCBType  trfficStatusCB,
   v_PVOID_t                          usrCtxt
)
{
   VOS_STATUS                     status = VOS_STATUS_SUCCESS;

   status = WLANTL_HSRegGetTrafficStatus(pAdapter,
                                idleThreshold,
                                measurePeriod,
                                trfficStatusCB,
                                usrCtxt);
   return status;
}
#endif
/*==========================================================================
  FUNCTION      WLANTL_GetStatistics

  DESCRIPTION   Get traffic statistics for identified station 

  DEPENDENCIES  NONE
    
  PARAMETERS    in pAdapter - Global handle
                in statType - specific statistics field to reset
                out statBuffer - traffic statistics buffer
   
  RETURN VALUE  VOS_STATUS

  SIDE EFFECTS  NONE
  
============================================================================*/
VOS_STATUS WLANTL_GetStatistics
(
   v_PVOID_t                  pAdapter,
   WLANTL_TRANSFER_STA_TYPE  *statBuffer,
   v_U8_t                     STAid
)
{
  WLANTL_CbType            *pTLCb  = VOS_GET_TL_CB(pAdapter);
  WLANTL_STAClientType*     pClientSTA = NULL;
  VOS_STATUS                status = VOS_STATUS_SUCCESS;
  WLANTL_TRANSFER_STA_TYPE *statistics = NULL;

  /*------------------------------------------------------------------------
    Sanity check
    Extract TL control block 
   ------------------------------------------------------------------------*/
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL:Invalid TL pointer on WLANTL_GetStatistics"));
    return VOS_STATUS_E_FAULT;
  }

  pClientSTA = pTLCb->atlSTAClients[STAid];

  if ( NULL == pClientSTA )
  {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Client Memory was not allocated on %s", __func__));
      return VOS_STATUS_E_FAILURE;
  }

  if(0 == pClientSTA->ucExists)
  {
    TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
    "WLAN TL: %d STA ID does not exist", STAid));
    return VOS_STATUS_E_INVAL;
  }

  if(NULL == statBuffer)
  {
    TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
    "WLAN TL:Invalid TL statistics buffer pointer on WLANTL_GetStatistics"));
    return VOS_STATUS_E_INVAL;
  }

  statistics = &pClientSTA->trafficStatistics;
  vos_mem_copy(statBuffer, statistics, sizeof(WLANTL_TRANSFER_STA_TYPE));

  return status;
}

/*==========================================================================
  FUNCTION      WLANTL_ResetStatistics

  DESCRIPTION   Reset statistics structure for identified station ID
                Reset means set values as 0

  DEPENDENCIES  NONE
    
  PARAMETERS    in pAdapter - Global handle
                in statType - specific statistics field to reset
   
  RETURN VALUE  VOS_STATUS

  SIDE EFFECTS  NONE
  
============================================================================*/
VOS_STATUS WLANTL_ResetStatistics
(
   v_PVOID_t                  pAdapter,
   v_U8_t                     STAid
)
{
  WLANTL_CbType            *pTLCb  = VOS_GET_TL_CB(pAdapter);
  WLANTL_STAClientType*     pClientSTA = NULL;
  VOS_STATUS                status = VOS_STATUS_SUCCESS;
  WLANTL_TRANSFER_STA_TYPE *statistics = NULL;

  /*------------------------------------------------------------------------
    Sanity check
    Extract TL control block 
   ------------------------------------------------------------------------*/
  if (NULL == pTLCb) 
  {
    TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL:Invalid TL pointer on WLANTL_GetStatistics"));
    return VOS_STATUS_E_FAULT;
  }

  pClientSTA = pTLCb->atlSTAClients[STAid];

  if ( NULL == pClientSTA )
  {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Client Memory was not allocated on %s", __func__));
      return VOS_STATUS_E_FAILURE;
  }

  if(0 == pClientSTA->ucExists)
  {
    TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
    "WLAN TL: %d STA ID does not exist", STAid));
    return VOS_STATUS_E_INVAL;
  }

  statistics = &pClientSTA->trafficStatistics;
  vos_mem_zero((v_VOID_t *)statistics, sizeof(WLANTL_TRANSFER_STA_TYPE));

  return status;
}

/*==========================================================================
  FUNCTION      WLANTL_GetSpecStatistic

  DESCRIPTION   Get specific field within statistics structure for
                identified station ID 

  DEPENDENCIES  NONE

  PARAMETERS    in pAdapter - Global handle
                in statType - specific statistics field to reset
                in STAid    - Station ID
                out buffer  - Statistic value
   
  RETURN VALUE  VOS_STATUS

  SIDE EFFECTS  NONE
  
============================================================================*/
VOS_STATUS WLANTL_GetSpecStatistic
(
   v_PVOID_t                    pAdapter,
   WLANTL_TRANSFER_STATIC_TYPE  statType,
   v_U32_t                     *buffer,
   v_U8_t                       STAid
)
{
  WLANTL_CbType            *pTLCb  = VOS_GET_TL_CB(pAdapter);
  WLANTL_STAClientType*     pClientSTA = NULL;
  VOS_STATUS                status = VOS_STATUS_SUCCESS;
  WLANTL_TRANSFER_STA_TYPE *statistics = NULL;

  /*------------------------------------------------------------------------
    Sanity check
    Extract TL control block 
   ------------------------------------------------------------------------*/
  if (NULL == pTLCb) 
  {
    TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL:Invalid TL pointer on WLANTL_GetStatistics"));
    return VOS_STATUS_E_FAULT;
  }
  pClientSTA = pTLCb->atlSTAClients[STAid];

  if ( NULL == pClientSTA )
  {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Client Memory was not allocated on %s", __func__));
      return VOS_STATUS_E_FAILURE;
  }

  if(0 == pClientSTA->ucExists)
  {
    TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
    "WLAN TL: %d STA ID does not exist", STAid));
    return VOS_STATUS_E_INVAL;
  }

  if(NULL == buffer)
  {
    TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
    "WLAN TL:Invalid TL statistic buffer pointer on WLANTL_GetStatistics"));
    return VOS_STATUS_E_INVAL;
  }

  statistics = &pClientSTA->trafficStatistics;
  switch(statType)
  {
    case WLANTL_STATIC_TX_UC_FCNT:
      *buffer = statistics->txUCFcnt;
      break;

    case WLANTL_STATIC_TX_MC_FCNT:
      *buffer = statistics->txMCFcnt;
      break;

    case WLANTL_STATIC_TX_BC_FCNT:
      *buffer = statistics->txBCFcnt;
      break;

    case WLANTL_STATIC_TX_UC_BCNT:
      *buffer = statistics->txUCBcnt;
      break;

    case WLANTL_STATIC_TX_MC_BCNT:
      *buffer = statistics->txMCBcnt;
      break;

    case WLANTL_STATIC_TX_BC_BCNT:
      *buffer = statistics->txBCBcnt;
      break;

    case WLANTL_STATIC_RX_UC_FCNT:
      *buffer = statistics->rxUCFcnt;
      break;

    case WLANTL_STATIC_RX_MC_FCNT:
      *buffer = statistics->rxMCFcnt;
      break;

    case WLANTL_STATIC_RX_BC_FCNT:
      *buffer = statistics->rxBCFcnt;
      break;

    case WLANTL_STATIC_RX_UC_BCNT:
      *buffer = statistics->rxUCBcnt;
      break;

    case WLANTL_STATIC_RX_MC_BCNT:
      *buffer = statistics->rxMCBcnt;
      break;

    case WLANTL_STATIC_RX_BC_BCNT:
      *buffer = statistics->rxBCBcnt;
      break;

    case WLANTL_STATIC_RX_BCNT:
      *buffer = statistics->rxBcnt;
      break;

    case WLANTL_STATIC_RX_BCNT_CRC_OK:
      *buffer = statistics->rxBcntCRCok;
      break;

    case WLANTL_STATIC_RX_RATE:
      *buffer = statistics->rxRate;
      break;

    default:
      *buffer = 0;
      status = VOS_STATUS_E_INVAL;
      break;
  }


  return status;
}

/*==========================================================================
  FUNCTION      WLANTL_ResetSpecStatistic

  DESCRIPTION   Reset specific field within statistics structure for
                identified station ID
                Reset means set as 0

  DEPENDENCIES  NONE
    
  PARAMETERS    in pAdapter - Global handle
                in statType - specific statistics field to reset
                in STAid    - Station ID

  RETURN VALUE  VOS_STATUS

  SIDE EFFECTS  NONE
  
============================================================================*/
VOS_STATUS WLANTL_ResetSpecStatistic
(
   v_PVOID_t                    pAdapter,
   WLANTL_TRANSFER_STATIC_TYPE  statType,
   v_U8_t                       STAid
)
{
  WLANTL_CbType            *pTLCb  = VOS_GET_TL_CB(pAdapter);
  WLANTL_STAClientType*     pClientSTA = NULL;
  VOS_STATUS                status = VOS_STATUS_SUCCESS;
  WLANTL_TRANSFER_STA_TYPE *statistics = NULL;

  /*------------------------------------------------------------------------
    Sanity check
    Extract TL control block 
   ------------------------------------------------------------------------*/
  if (NULL == pTLCb) 
  {
    TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL:Invalid TL pointer on WLANTL_GetStatistics"));
    return VOS_STATUS_E_FAULT;
  }

  pClientSTA = pTLCb->atlSTAClients[STAid];

  if ( NULL == pClientSTA )
  {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
          "WLAN TL:Client Memory was not allocated on %s", __func__));
      return VOS_STATUS_E_FAILURE;
  }

  if(0 == pClientSTA->ucExists)
  {
    TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
    "WLAN TL: %d STA ID does not exist", STAid));
    return VOS_STATUS_E_INVAL;
  }

  statistics = &pClientSTA->trafficStatistics;
  switch(statType)
  {
    case WLANTL_STATIC_TX_UC_FCNT:
      statistics->txUCFcnt = 0;
      break;

    case WLANTL_STATIC_TX_MC_FCNT:
      statistics->txMCFcnt = 0;
      break;

    case WLANTL_STATIC_TX_BC_FCNT:
      statistics->txBCFcnt = 0;
      break;

    case WLANTL_STATIC_TX_UC_BCNT:
      statistics->txUCBcnt = 0;
      break;

    case WLANTL_STATIC_TX_MC_BCNT:
      statistics->txMCBcnt = 0;
      break;

    case WLANTL_STATIC_TX_BC_BCNT:
      statistics->txBCBcnt = 0;
      break;

    case WLANTL_STATIC_RX_UC_FCNT:
      statistics->rxUCFcnt = 0;
      break;

    case WLANTL_STATIC_RX_MC_FCNT:
      statistics->rxMCFcnt = 0;
      break;

    case WLANTL_STATIC_RX_BC_FCNT:
      statistics->rxBCFcnt = 0;
      break;

    case WLANTL_STATIC_RX_UC_BCNT:
      statistics->rxUCBcnt = 0;
      break;

    case WLANTL_STATIC_RX_MC_BCNT:
      statistics->rxMCBcnt = 0;
      break;

    case WLANTL_STATIC_RX_BC_BCNT:
      statistics->rxBCBcnt = 0;
      break;

    case WLANTL_STATIC_RX_BCNT:
      statistics->rxBcnt = 0;
      break;

    case WLANTL_STATIC_RX_BCNT_CRC_OK:
      statistics->rxBcntCRCok = 0;
      break;

    case WLANTL_STATIC_RX_RATE:
      statistics->rxRate = 0;
      break;

    default:
      status = VOS_STATUS_E_INVAL;
      break;
  }

  return status;
}


/*==========================================================================

   FUNCTION

   DESCRIPTION   Read RSSI value out of a RX BD
    
   PARAMETERS:  Caller must validate all parameters 

   RETURN VALUE

============================================================================*/
VOS_STATUS WLANTL_ReadRSSI
(
   v_PVOID_t        pAdapter,
   v_PVOID_t        pBDHeader,
   v_U8_t           STAid
)
{
   WLANTL_CbType   *tlCtxt = VOS_GET_TL_CB(pAdapter);
   v_S7_t           currentRSSI, currentRSSI0, currentRSSI1;


   if(NULL == tlCtxt)
   {
      TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, "%s Invalid TL handle", __func__));
      return VOS_STATUS_E_INVAL;
   }

   if ( NULL == tlCtxt->atlSTAClients[STAid] )
   {
       TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
           "WLAN TL:Client Memory was not allocated on %s", __func__));
       return VOS_STATUS_E_FAILURE;
   }

   currentRSSI0 = WLANTL_GETRSSI0(pBDHeader);
   currentRSSI1 = WLANTL_GETRSSI1(pBDHeader);
   currentRSSI  = (currentRSSI0 > currentRSSI1) ? currentRSSI0 : currentRSSI1;

   tlCtxt->atlSTAClients[STAid]->rssiAvg = currentRSSI;

   return VOS_STATUS_SUCCESS;
}

/*==========================================================================

   FUNCTION

   DESCRIPTION   Read SNR value out of a RX BD

   PARAMETERS:  Caller must validate all parameters

   RETURN VALUE

============================================================================*/
VOS_STATUS WLANTL_ReadSNR
(
   v_PVOID_t        pAdapter,
   v_PVOID_t        pBDHeader,
   v_U8_t           STAid
)
{
   WLANTL_CbType   *tlCtxt = VOS_GET_TL_CB(pAdapter);
   v_S7_t           currentSNR;


   if (NULL == tlCtxt)
   {
      TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                       "%s Invalid TL handle", __func__));
      return VOS_STATUS_E_INVAL;
   }

   if (NULL == tlCtxt->atlSTAClients[STAid])
   {
       TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
           "WLAN TL:Client Memory was not allocated on %s", __func__));
       return VOS_STATUS_E_FAILURE;
   }

   currentSNR = WLANTL_GETSNR(pBDHeader);

   /* SNR reported in the Buffer Descriptor is scaled up by 2(SNR*2),
    * Get the correct SNR value
    */
   currentSNR = currentSNR >> 1;

   /* SNR reported by HW cannot be more than 35dB due to HW limitations */
   currentSNR = (WLANTL_MAX_HW_SNR > currentSNR ? currentSNR :
                                                  WLANTL_MAX_HW_SNR);

   TLLOG2(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
          "%s: snrsum: %d snridx: %d prevsnravg: %d",
           __func__,
           tlCtxt->atlSTAClients[STAid]->snrSum,
           tlCtxt->atlSTAClients[STAid]->snrIdx,
           tlCtxt->atlSTAClients[STAid]->prevSnrAvg));

   /* The SNR returned for all purposes is the average SNR over
    * WLANTL_MAX_SNR_DATA_SMAPLES.When data samples
    * > WLANTL_MAX_SNR_DATA_SAMPLES are obtained,
    * store the average of the samples in prevSnrAvg
    * and start a new averaging window. The prevSnrAvg is used when
    * enough data samples are not available when applications
    * actually query for SNR.
    *
    * SEE: WLANTL_GetSnr()
    */
   if (tlCtxt->atlSTAClients[STAid]->snrIdx >= WLANTL_MAX_SNR_DATA_SAMPLES)
   {
       tlCtxt->atlSTAClients[STAid]->prevSnrAvg =
               tlCtxt->atlSTAClients[STAid]->snrSum /
               tlCtxt->atlSTAClients[STAid]->snrIdx;
       tlCtxt->atlSTAClients[STAid]->snrSum = 0;
       tlCtxt->atlSTAClients[STAid]->snrIdx = 0;
   }
   tlCtxt->atlSTAClients[STAid]->snrSum += currentSNR;
   tlCtxt->atlSTAClients[STAid]->snrIdx += 1;

   return VOS_STATUS_SUCCESS;
}

/*
 DESCRIPTION 
    TL returns the weight currently maintained in TL.
 IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's 
                    or SME's control block can be extracted from its context 

 OUT
    pACWeights:     Caller allocated memory for filling in weights

 RETURN VALUE  VOS_STATUS
*/
VOS_STATUS  
WLANTL_GetACWeights 
( 
  v_PVOID_t             pvosGCtx,
  v_U8_t*               pACWeights
)
{
   WLANTL_CbType*  pTLCb = NULL;
   v_U8_t          ucIndex; 
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if ( NULL == pACWeights )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid parameter sent on WLANTL_GetACWeights"));
    return VOS_STATUS_E_INVAL;
  }

  /*------------------------------------------------------------------------
    Extract TL control block and check existance
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_GetACWeights"));
    return VOS_STATUS_E_FAULT;
  }
  for ( ucIndex = 0; ucIndex < WLANTL_MAX_AC ; ucIndex++)
  {
    pACWeights[ucIndex] = pTLCb->tlConfigInfo.ucAcWeights[ucIndex];
  }

  return VOS_STATUS_SUCCESS;
}



/*
 DESCRIPTION 
    Change the weight currently maintained by TL.
 IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's 
                    or SME's control block can be extracted from its context 
    pACWeights:     Caller allocated memory contain the weights to use


 RETURN VALUE  VOS_STATUS
*/
VOS_STATUS  
WLANTL_SetACWeights 
( 
  v_PVOID_t             pvosGCtx,
  v_U8_t*               pACWeights
)
{
   WLANTL_CbType*  pTLCb = NULL;
   v_U8_t          ucIndex; 
  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  /*------------------------------------------------------------------------
    Sanity check
   ------------------------------------------------------------------------*/
  if ( NULL == pACWeights )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Invalid parameter sent on WLANTL_GetACWeights"));
    return VOS_STATUS_E_INVAL;
  }

  /*------------------------------------------------------------------------
    Extract TL control block and check existance
   ------------------------------------------------------------------------*/
  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if ( NULL == pTLCb )
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
              "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_GetACWeights"));
    return VOS_STATUS_E_FAULT;
  }
  for ( ucIndex = 0; ucIndex < WLANTL_MAX_AC ; ucIndex++)
  {
    pTLCb->tlConfigInfo.ucAcWeights[ucIndex] = pACWeights[ucIndex];
  }

  pTLCb->tlConfigInfo.ucAcWeights[WLANTL_AC_HIGH_PRIO] = pACWeights[WLANTL_AC_VO];
  return VOS_STATUS_SUCCESS;
}


/*==========================================================================

   FUNCTION

   DESCRIPTION 
    
   PARAMETERS 

   RETURN VALUE

============================================================================*/
void WLANTL_PowerStateChangedCB
(
   v_PVOID_t pAdapter,
   tPmcState newState
)
{
   WLANTL_CbType                *tlCtxt = VOS_GET_TL_CB(pAdapter);

   if (NULL == tlCtxt)
   {
     VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                "%s: Invalid TL Control Block", __func__ );
     return;
   }

   VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, "Power state changed, new state is %d", newState );
   switch(newState)
   {
      case FULL_POWER:
         tlCtxt->isBMPS = VOS_FALSE;
         break;

      case BMPS:
#if defined WLAN_FEATURE_NEIGHBOR_ROAMING
         WLANTL_SetFWRSSIThresholds(pAdapter);
#endif

         tlCtxt->isBMPS = VOS_TRUE;
         break;

      case IMPS:
      case LOW_POWER:
      case REQUEST_BMPS:
      case REQUEST_FULL_POWER:
      case REQUEST_IMPS:
      case STOPPED:
      case REQUEST_START_UAPSD:
      case REQUEST_STOP_UAPSD:
      case UAPSD:
      case REQUEST_STANDBY:
      case STANDBY:
      case REQUEST_ENTER_WOWL:
      case REQUEST_EXIT_WOWL:
      case WOWL:
         TLLOGW(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN, "Not handle this events %d", newState ));
         break;

      default:
         TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, "Not a valid event %d", newState ));
         break;
   }

   return;
}
/*==========================================================================
  FUNCTION      WLANTL_GetEtherType

  DESCRIPTION   Extract Ether type information from the BD

  DEPENDENCIES  NONE
    
  PARAMETERS    in aucBDHeader - BD header
                in vosDataBuff - data buffer
                in ucMPDUHLen  - MPDU header length
                out pUsEtherType - pointer to Ethertype

  RETURN VALUE  VOS_STATUS_SUCCESS : if the EtherType is successfully extracted
                VOS_STATUS_FAILURE : if the EtherType extraction failed and
                                     the packet was dropped

  SIDE EFFECTS  NONE
  
============================================================================*/
static VOS_STATUS WLANTL_GetEtherType
(
   v_U8_t               * aucBDHeader,
   vos_pkt_t            * vosDataBuff,
   v_U8_t                 ucMPDUHLen,
   v_U16_t              * pUsEtherType
)
{
  v_U8_t                   ucOffset;
  v_U16_t                  usEtherType = *pUsEtherType;
  v_SIZE_t                 usLLCSize = sizeof(usEtherType);
  VOS_STATUS               vosStatus  = VOS_STATUS_SUCCESS;
  
  /*------------------------------------------------------------------------
    Check if LLC is present - if not, TL is unable to determine type
   ------------------------------------------------------------------------*/
  if ( VOS_FALSE == WDA_IS_RX_LLC_PRESENT( aucBDHeader ) )
  {
    ucOffset = WLANTL_802_3_HEADER_LEN - sizeof(usEtherType); 
  }
  else
  {
    ucOffset = ucMPDUHLen + WLANTL_LLC_PROTO_TYPE_OFFSET;
  }

  /*------------------------------------------------------------------------
    Extract LLC type 
  ------------------------------------------------------------------------*/
  vosStatus = vos_pkt_extract_data( vosDataBuff, ucOffset, 
                                    (v_PVOID_t)&usEtherType, &usLLCSize); 

  if (( VOS_STATUS_SUCCESS != vosStatus ) || 
      ( sizeof(usEtherType) != usLLCSize ))
      
  {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
               "WLAN TL:Error extracting Ether type from data packet"));
    /* Drop packet */
    vos_pkt_return_packet(vosDataBuff);
    vosStatus = VOS_STATUS_E_FAILURE;
  }
  else
  {
    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
               "WLAN TL:Ether type retrieved before endianess conv: %d", 
               usEtherType));

    usEtherType = vos_be16_to_cpu(usEtherType);
    *pUsEtherType = usEtherType;

    TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
               "WLAN TL:Ether type retrieved: %d", usEtherType));
  }
  
  return vosStatus;
}

/*==========================================================================
  FUNCTION      WLANTL_GetSoftAPStatistics

  DESCRIPTION   Collect the cumulative statistics for all Softap stations

  DEPENDENCIES  NONE
    
  PARAMETERS    in pvosGCtx  - Pointer to the global vos context
                   bReset    - If set TL statistics will be cleared after reading
                out statsSum - pointer to collected statistics

  RETURN VALUE  VOS_STATUS_SUCCESS : if the Statistics are successfully extracted

  SIDE EFFECTS  NONE

============================================================================*/
VOS_STATUS WLANTL_GetSoftAPStatistics(v_PVOID_t pAdapter, WLANTL_TRANSFER_STA_TYPE *statsSum, v_BOOL_t bReset)
{
    v_U8_t i = 0;
    VOS_STATUS  vosStatus = VOS_STATUS_SUCCESS;
    WLANTL_CbType *pTLCb  = VOS_GET_TL_CB(pAdapter);
    WLANTL_TRANSFER_STA_TYPE statBufferTemp;
    vos_mem_zero((v_VOID_t *)&statBufferTemp, sizeof(WLANTL_TRANSFER_STA_TYPE));
    vos_mem_zero((v_VOID_t *)statsSum, sizeof(WLANTL_TRANSFER_STA_TYPE));


    if ( NULL == pTLCb )
    {
       return VOS_STATUS_E_FAULT;
    } 

    // Sum up all the statistics for stations of Soft AP from TL
    for (i = 0; i < WLAN_MAX_STA_COUNT; i++)
    {
        if ( NULL == pTLCb->atlSTAClients[i])
        {
            continue;
        }
        if (pTLCb->atlSTAClients[i]->wSTADesc.wSTAType == WLAN_STA_SOFTAP)
        {
           vosStatus = WLANTL_GetStatistics(pAdapter, &statBufferTemp, i);// Can include staId 1 because statistics not collected for it

           if (!VOS_IS_STATUS_SUCCESS(vosStatus))
                return VOS_STATUS_E_FAULT;

            // Add to the counters
           statsSum->txUCFcnt += statBufferTemp.txUCFcnt;
           statsSum->txMCFcnt += statBufferTemp.txMCFcnt;
           statsSum->txBCFcnt += statBufferTemp.txBCFcnt;
           statsSum->txUCBcnt += statBufferTemp.txUCBcnt;
           statsSum->txMCBcnt += statBufferTemp.txMCBcnt;
           statsSum->txBCBcnt += statBufferTemp.txBCBcnt;
           statsSum->rxUCFcnt += statBufferTemp.rxUCFcnt;
           statsSum->rxMCFcnt += statBufferTemp.rxMCFcnt;
           statsSum->rxBCFcnt += statBufferTemp.rxBCFcnt;
           statsSum->rxUCBcnt += statBufferTemp.rxUCBcnt;
           statsSum->rxMCBcnt += statBufferTemp.rxMCBcnt;
           statsSum->rxBCBcnt += statBufferTemp.rxBCBcnt;

           if (bReset)
           {
              vosStatus = WLANTL_ResetStatistics(pAdapter, i);
              if (!VOS_IS_STATUS_SUCCESS(vosStatus))
                return VOS_STATUS_E_FAULT;               
          }
        }
    }

    return vosStatus;
}

/*===============================================================================
  FUNCTION      WLANTL_IsReplayPacket
     
  DESCRIPTION   This function does replay check for valid stations
 
  DEPENDENCIES  Validity of replay check must be done before the function 
                is called
                          
  PARAMETERS    currentReplayCounter    current replay counter taken from RX BD 
                previousReplayCounter   previous replay counter taken from TL CB
                                       
  RETRUN        VOS_TRUE    packet is a replay packet
                VOS_FALSE   packet is not a replay packet

  SIDE EFFECTS   none
 ===============================================================================*/
v_BOOL_t
WLANTL_IsReplayPacket
(
  v_U64_t    ullcurrentReplayCounter,
  v_U64_t    ullpreviousReplayCounter
)
{
   /* Do the replay check by comparing previous received replay counter with
      current received replay counter*/
    if(ullpreviousReplayCounter < ullcurrentReplayCounter)
    {
        /* Valid packet not replay */
        return VOS_FALSE;
    }
    else
    {

        /* Current packet number is less than or equal to previuos received 
           packet no, this means current packet is replay packet */
        VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
        "WLAN TL: Replay packet found with replay counter :[0x%llX]",ullcurrentReplayCounter);
           
        return VOS_TRUE;
    }
}

#if 0
/*===============================================================================
  FUNCTION      WLANTL_GetReplayCounterFromRxBD
     
  DESCRIPTION   This function extracts 48-bit replay packet number from RX BD 
 
  DEPENDENCIES  Validity of replay check must be done before the function 
                is called
                          
  PARAMETERS    pucRxHeader pointer to RX BD header
                                       
  RETRUN        v_U64_t    Packet number extarcted from RX BD

  SIDE EFFECTS   none
 ===============================================================================*/
v_U64_t
WLANTL_GetReplayCounterFromRxBD
(
   v_U8_t *pucRxBDHeader
)
{
/* 48-bit replay counter is created as follows
   from RX BD 6 byte PMI command:
   Addr : AES/TKIP
   0x38 : pn3/tsc3
   0x39 : pn2/tsc2
   0x3a : pn1/tsc1
   0x3b : pn0/tsc0

   0x3c : pn5/tsc5
   0x3d : pn4/tsc4 */

#ifdef ANI_BIG_BYTE_ENDIAN
    v_U64_t ullcurrentReplayCounter = 0;
    /* Getting 48-bit replay counter from the RX BD */
    ullcurrentReplayCounter = WLANHAL_RX_BD_GET_PMICMD_20TO23(pucRxBDHeader); 
    ullcurrentReplayCounter <<= 16;
    ullcurrentReplayCounter |= (( WLANHAL_RX_BD_GET_PMICMD_24TO25(pucRxBDHeader) & 0xFFFF0000) >> 16);
    return ullcurrentReplayCounter;
#else
    v_U64_t ullcurrentReplayCounter = 0;
    /* Getting 48-bit replay counter from the RX BD */
    ullcurrentReplayCounter = (WLANHAL_RX_BD_GET_PMICMD_24TO25(pucRxBDHeader) & 0x0000FFFF); 
    ullcurrentReplayCounter <<= 32; 
    ullcurrentReplayCounter |= WLANHAL_RX_BD_GET_PMICMD_20TO23(pucRxBDHeader); 
    return ullcurrentReplayCounter;
#endif
}
#endif

/*===============================================================================
  FUNCTION      WLANTL_PostResNeeded
     
  DESCRIPTION   This function posts message to TL to reserve BD/PDU memory
 
  DEPENDENCIES  None
                          
  PARAMETERS    pvosGCtx
                                       
  RETURN        None

  SIDE EFFECTS   none
 ===============================================================================*/

void WLANTL_PostResNeeded(v_PVOID_t pvosGCtx)
{
  vos_msg_t            vosMsg;

  vosMsg.reserved = 0;
  vosMsg.bodyptr  = NULL;
  vosMsg.type     = WLANTL_TX_RES_NEEDED;
  VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
        "WLAN TL: BD/PDU available interrupt received, Posting message to TL");
  if(!VOS_IS_STATUS_SUCCESS(vos_tx_mq_serialize( VOS_MQ_ID_TL, &vosMsg)))
  {
    VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
       " %s fails to post message", __func__);
  }
}

/*===============================================================================
  FUNCTION       WLANTL_UpdateRssiBmps

  DESCRIPTION    This function updates the TL's RSSI (in BMPS mode)

  DEPENDENCIES   None

  PARAMETERS

    pvosGCtx         VOS context          VOS Global context
    staId            Station ID           Station ID
    rssi             RSSI (BMPS mode)     RSSI in BMPS mode

  RETURN         None

  SIDE EFFECTS   none
 ===============================================================================*/

void WLANTL_UpdateRssiBmps(v_PVOID_t pvosGCtx, v_U8_t staId, v_S7_t rssi)
{
  WLANTL_CbType* pTLCb = VOS_GET_TL_CB(pvosGCtx);

  if (NULL != pTLCb && NULL != pTLCb->atlSTAClients[staId])
  {
    pTLCb->atlSTAClients[staId]->rssiAvgBmps = rssi;
  }
}

/*===============================================================================
  FUNCTION       WLANTL_UpdateSnrBmps

  DESCRIPTION    This function updates the TL's SNR (in BMPS mode)

  DEPENDENCIES   None

  PARAMETERS

    pvosGCtx         VOS context          VOS Global context
    staId            Station ID           Station ID
    snr             SNR (BMPS mode)     SNR in BMPS mode

  RETURN         None

  SIDE EFFECTS   none
 ===============================================================================*/

void WLANTL_UpdateSnrBmps(v_PVOID_t pvosGCtx, v_U8_t staId, v_S7_t snr)
{
  WLANTL_CbType* pTLCb = VOS_GET_TL_CB(pvosGCtx);

  if (NULL != pTLCb && NULL != pTLCb->atlSTAClients[staId])
  {
    pTLCb->atlSTAClients[staId]->snrAvgBmps = snr;
  }
}

/*===============================================================================
  FUNCTION       WLANTL_UpdateLinkCapacity

  DESCRIPTION    This function updates the STA's Link Capacity in TL

  DEPENDENCIES   None

  PARAMETERS

    pvosGCtx         VOS context          VOS Global context
    staId            Station ID           Station ID
    linkCapacity     linkCapacity         Link Capacity

  RETURN         None

  SIDE EFFECTS   none
 ===============================================================================*/

void WLANTL_UpdateLinkCapacity(v_PVOID_t pvosGCtx, v_U8_t staId, v_U32_t linkCapacity)
{
    WLANTL_CbType* pTLCb = VOS_GET_TL_CB(pvosGCtx);

    if (NULL != pTLCb && NULL != pTLCb->atlSTAClients[staId])
    {
        pTLCb->atlSTAClients[staId]->linkCapacity = linkCapacity;
    }
}


/*===========================================================================

  FUNCTION    WLANTL_GetSTALinkCapacity

  DESCRIPTION

    Returns Link Capacity of a particular STA.

  DEPENDENCIES

    A station must have been registered before its state can be retrieved.


  PARAMETERS

    IN
    pvosGCtx:       pointer to the global vos context; a handle to TL's
                    control block can be extracted from its context
    ucSTAId:        identifier of the station

    OUT
    plinkCapacity:  the current link capacity the connection to
                    the given station


  RETURN VALUE

    The result code associated with performing the operation

    VOS_STATUS_E_INVAL:  Input parameters are invalid
    VOS_STATUS_E_FAULT:  Station ID is outside array boundaries or pointer to
                         TL cb is NULL ; access would cause a page fault
    VOS_STATUS_E_EXISTS: Station was not registered
    VOS_STATUS_SUCCESS:  Everything is good :)

  SIDE EFFECTS

============================================================================*/
VOS_STATUS
WLANTL_GetSTALinkCapacity
(
    v_PVOID_t             pvosGCtx,
    v_U8_t                ucSTAId,
    v_U32_t               *plinkCapacity
)
{
    WLANTL_CbType*  pTLCb = NULL;
    /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

    /*------------------------------------------------------------------------
      Sanity check
     ------------------------------------------------------------------------*/
    if ( NULL == plinkCapacity )
    {
        TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                         FL("WLAN TL:Invalid parameter")));
        return VOS_STATUS_E_INVAL;
    }

    if ( WLANTL_STA_ID_INVALID( ucSTAId ) )
    {
        TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                         FL("WLAN TL:Invalid station id")));
        return VOS_STATUS_E_FAULT;
    }

    /*------------------------------------------------------------------------
      Extract TL control block and check existance
     ------------------------------------------------------------------------*/
    pTLCb = VOS_GET_TL_CB(pvosGCtx);
    if ( NULL == pTLCb )
    {
         TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                          FL("WLAN TL:Invalid TL pointer from pvosGCtx")));
         return VOS_STATUS_E_FAULT;
    }

    if ( NULL == pTLCb->atlSTAClients[ucSTAId] )
    {
        TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                         FL("WLAN TL:Client Memory was not allocated")));
        return VOS_STATUS_E_FAILURE;
    }

    if ( 0 == pTLCb->atlSTAClients[ucSTAId]->ucExists )
    {
        TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
                         FL("WLAN TL:Station was not previously registered")));
        return VOS_STATUS_E_EXISTS;
    }

    /*------------------------------------------------------------------------
      Get STA state
     ------------------------------------------------------------------------*/
    *plinkCapacity = pTLCb->atlSTAClients[ucSTAId]->linkCapacity;

    return VOS_STATUS_SUCCESS;
}/* WLANTL_GetSTALinkCapacity */

/*
 * WLANTL_ResetRxSSN - reset last rx ssn
 * @pvosGCtx: global vos context
 * @ucSTAId: station id
 *
 * This function resets the last ssn of all tids of the station
 * for whom BA reorder session exists.
 *
 * Return: none
 */
void WLANTL_ResetRxSSN(v_PVOID_t pvosGCtx, uint8_t ucSTAId)
{
   WLANTL_CbType*  pTLCb = NULL;
   WLANTL_STAClientType* pClientSTA = NULL;
   uint8_t i;

  if (WLANTL_STA_ID_INVALID(ucSTAId)) {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
             "WLAN TL:Invalid station id requested WLANTL_ResetRxSSN"));
    return;
  }

  pTLCb = VOS_GET_TL_CB(pvosGCtx);
  if (NULL == pTLCb) {
    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
         "WLAN TL:Invalid TL pointer from pvosGCtx WLANTL_ResetRxSSN"));
    return;
  }

  pClientSTA = pTLCb->atlSTAClients[ucSTAId];

  for (i = 0; i < WLAN_MAX_TID ; i++) {
     if (0 == pClientSTA->atlBAReorderInfo[i].ucExists) {
        continue;
     }
     TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
           "WLAN TL: Last RxSSN reset to zero for tid %d", i));
     pClientSTA->atlBAReorderInfo[i].LastSN = 0;
  }
}

void WLANTL_SetDataPktFilter(v_PVOID_t pvosGCtx, uint8_t ucSTAId, bool flag)
{
   WLANTL_CbType*  pTLCb = NULL;
   WLANTL_STAClientType* pClientSTA = NULL;
   uint8_t i;

   if (WLANTL_STA_ID_INVALID(ucSTAId)) {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "%s: Invalid station id requested", __func__));
      return;
   }

   pTLCb = VOS_GET_TL_CB(pvosGCtx);
   if (NULL == pTLCb) {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
             "%s: Invalid TL pointer from pvosGCtx", __func__));
   return;
   }

   pClientSTA = pTLCb->atlSTAClients[ucSTAId];

   for (i = 0; i < WLAN_MAX_TID ; i++) {
      if (0 == pClientSTA->atlBAReorderInfo[i].ucExists)
         continue;

      TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
            "WLAN TL: Last RxSSN reset to zero for tid %d", i));
      pClientSTA->atlBAReorderInfo[i].set_data_filter = flag;
   }
}

/**
 * WLANTL_ShiftArrByOne() - utility function to shift array by one
 * @arr: pointer to array
 * @len: length of the array
 *
 * Caller responsibility to provide the correct length of the array
 * other may leads to bugs.
 *
 * Return: void
 */
static void WLANTL_ShiftArrByOne(uint32_t *arr, uint8_t len)
{
   int i;
   for (i = 0; i < len - 1; i ++)
      arr[i] = arr[i + 1];
   arr[i] = 0;
}

/**
 * WLANTL_SampleTx() - collect tx samples
 * @data: TL context pointer
 *
 * This function records the last five tx bytes sent samples
 * collected after tx_bytes_timer expire.
 *
 * Return: void
 */
void WLANTL_SampleTx(void *data)
{
   WLANTL_CbType* pTLCb = (WLANTL_CbType *)data;
   WLANTL_STAClientType* pClientSTA = NULL;
   uint8_t count = pTLCb->sample_count;
   uint8_t i;

   for ( i = 0; i < WLAN_MAX_STA_COUNT; i++) {
       if (NULL != pTLCb->atlSTAClients[i] &&
           pTLCb->atlSTAClients[i]->ucExists) {
          pClientSTA = pTLCb->atlSTAClients[i];

          if (count > (WLANTL_SAMPLE_COUNT - 1)) {
              count = WLANTL_SAMPLE_COUNT - 1;
              pClientSTA->tx_samples_sum -= pClientSTA->tx_sample[0];
              WLANTL_ShiftArrByOne(pClientSTA->tx_sample, WLANTL_SAMPLE_COUNT);
          }

          pClientSTA->tx_sample[count] = pClientSTA->tx_frames;
          pClientSTA->tx_samples_sum += pClientSTA->tx_sample[count];
          pClientSTA->tx_frames = 0;
          count++;
          pTLCb->sample_count = count;
       }
   }

   vos_timer_start(&pTLCb->tx_frames_timer, WLANTL_SAMPLE_INTERVAL);
}

/**
 * WLANTL_EnablePreAssocCaching() - Enable caching EAPOL frames
 *
 * Return: None
 *
 */
void WLANTL_EnablePreAssocCaching(void)
{
   v_PVOID_t pvosGCtx= vos_get_global_context(VOS_MODULE_ID_TL,NULL);
   WLANTL_CbType* pTLCb = VOS_GET_TL_CB(pvosGCtx);
   if (NULL == pTLCb ) {
      TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "%s: Invalid TL pointer for global context", __func__));
      return;
   }

   pTLCb->vosEapolCachedFrame = NULL;
   pTLCb->preassoc_caching = true;
}

/**
 * WLANTL_ForwardPreAssoc() - forward cached eapol frames
 * @flag: Value to forward or flush
 *
 * Return: vos status
 *
 */
static VOS_STATUS WLANTL_ForwardPreAssoc(bool flag)
{
  vos_msg_t sMessage;

  VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            " ---- Serializing TL for forwarding pre assoc cache frames");

  vos_mem_zero( &sMessage, sizeof(vos_msg_t));
  sMessage.type    = WLANTL_RX_FWD_PRE_ASSOC_CACHED;
  sMessage.bodyval = flag;

  return vos_rx_mq_serialize(VOS_MQ_ID_TL, &sMessage);
}

/**
 * WLANTL_PreAssocForward() - forward cached eapol frames
 * @flag: Value to forward or flush
 *
 * Return: None
 *
 */
void WLANTL_PreAssocForward(bool flag)
{
  if(!VOS_IS_STATUS_SUCCESS(WLANTL_ForwardPreAssoc(flag)))
  {
    VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
       " %s fails to forward packets", __func__);
  }
}

/**
 * WLANTL_RegisterFwdEapol() - register call back to forward cached eapol frame
 * @pvosGCtx : pointer to vos global context
 * @pfnFwdEapol: call back function pointer
 *
 * Return: None
 *
 */
void WLANTL_RegisterFwdEapol(v_PVOID_t pvosGCtx,
                             WLANTL_FwdEapolCBType pfnFwdEapol)
{
   WLANTL_CbType* pTLCb = NULL;
   pTLCb = VOS_GET_TL_CB(pvosGCtx);

   if (pTLCb)
      pTLCb->pfnEapolFwd = pfnFwdEapol;
}

 /**
 * WLANTL_SetARPFWDatapath() - keep or remove FW in data path for ARP
 *
 * @flag: value to keep or remove FW from data path
 *
 * Return: void
 */
void WLANTL_SetARPFWDatapath(void * pvosGCtx, bool flag)
{

   WLANTL_CbType*  pTLCb = NULL;

   pTLCb = VOS_GET_TL_CB(pvosGCtx);
   if (NULL == pTLCb) {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
             "%s: Invalid TL pointer from pvosGCtx", __func__));
      return;
   }

   pTLCb->track_arp = flag;

}

v_U16_t wlan_tl_get_sta_rx_rate(void *pvosGCtx, uint8_t ucSTAId)
{
	WLANTL_CbType*  pTLCb = NULL;
	v_U16_t rate = 0;

	pTLCb = VOS_GET_TL_CB(pvosGCtx);
	if (NULL == pTLCb) {
		TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
			"%s: Invalid TL pointer from pvosGCtx", __func__));
		return rate;
	}

	if (pTLCb->atlSTAClients[ucSTAId]->ucExists)
	    rate = vos_get_rate_from_rateidx(
		pTLCb->atlSTAClients[ucSTAId]->rate_idx);

	return rate;
}

void WLANTL_GetSAPStaRSSi(void *pvosGCtx, uint8_t ucSTAId, s8 *rssi)
{
   WLANTL_CbType*  pTLCb = NULL;
   uint8_t count;

   pTLCb = VOS_GET_TL_CB(pvosGCtx);
   if (NULL == pTLCb) {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
             "%s: Invalid TL pointer from pvosGCtx", __func__));
      return;
   }

   count = pTLCb->atlSTAClients[ucSTAId]->rssi_sample_cnt;
   count < WLANTL_RSSI_SAMPLE_CNT ? count++ : count;

   *rssi = pTLCb->atlSTAClients[ucSTAId]->rssi_sample_sum / count;
}

void WLANTL_SetKeySeqCounter(void *pvosGCtx, u64 counter, uint8_t staid)
{
   WLANTL_CbType*  pTLCb = NULL;
   uint8_t i;

   pTLCb = VOS_GET_TL_CB(pvosGCtx);
   if (NULL == pTLCb) {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
             "%s: Invalid TL pointer from pvosGCtx", __func__));
      return;
   }

   if (WLANTL_STA_ID_INVALID(staid)) {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
             "%s: Invalid Sta id passed", __func__));
      return;
   }

   if (NULL == pTLCb->atlSTAClients[staid]) {
      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
             "%s: Station context is NULL", __func__));
      return;
   }

   for(i = 0; i < WLANTL_MAX_TID; i++)
      pTLCb->atlSTAClients[staid]->ullReplayCounter[i] = counter;
}

#ifdef WLAN_FEATURE_RMC
VOS_STATUS WLANTL_RmcInit
(
    v_PVOID_t   pAdapter
)
{
    WLANTL_CbType   *pTLCb = VOS_GET_TL_CB(pAdapter);
    VOS_STATUS       status = VOS_STATUS_SUCCESS;
    tANI_U8          count;

    /*sanity check*/
    if (NULL == pTLCb)
    {
        TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "Invalid TL handle"));
        return VOS_STATUS_E_INVAL;
    }

    for ( count = 0; count < WLANTL_RMC_HASH_TABLE_SIZE; count++ )
    {
        pTLCb->rmcSession[count] = NULL;
    }

    vos_lock_init(&pTLCb->rmcLock);

    pTLCb->multicastDuplicateDetectionEnabled = 1;
    pTLCb->rmcDataPathEnabled = 0;

    return status;
}


VOS_STATUS WLANTL_RmcDeInit
(
    v_PVOID_t   pAdapter
)
{
    WLANTL_CbType   *pTLCb = VOS_GET_TL_CB(pAdapter);
    VOS_STATUS       status = VOS_STATUS_SUCCESS;
    tANI_U8          count;
    WLANTL_RMC_SESSION *pNode;
    WLANTL_RMC_SESSION *pPrev;

    /*sanity check*/
    if (NULL == pTLCb)
    {
        TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "Invalid TL handle"));
        return VOS_STATUS_E_INVAL;
    }

    for ( count = 0; count < WLANTL_RMC_HASH_TABLE_SIZE; count++ )
    {
        pNode = pTLCb->rmcSession[count];
        while (pNode)
        {
            pPrev = pNode;
            pNode = pNode->next;
            vos_mem_free((v_VOID_t * )pPrev);
        }
    }

    vos_lock_destroy(&pTLCb->rmcLock);

    return status;
}


tANI_U8 WLANTL_RmcHashRmcSession ( v_MACADDR_t   *pMcastAddr )
{
    tANI_U32 sum;
    tANI_U8  hash;

    sum = (pMcastAddr->bytes[0] + pMcastAddr->bytes[1] + pMcastAddr->bytes[2] +
           pMcastAddr->bytes[3] + pMcastAddr->bytes[4] + pMcastAddr->bytes[5]);

    hash = (tANI_U8)(sum & ((WLANTL_RMC_HASH_TABLE_SIZE - 1)));

    return hash;
}


WLANTL_RMC_SESSION* WLANTL_RmcLookUpRmcSession
(
    WLANTL_RMC_SESSION *rmcSession[],
    v_MACADDR_t     *pMcastAddr
)
{
    WLANTL_RMC_SESSION *pNode;
    tANI_U8               index;

    /*sanity check*/
    if (NULL == pMcastAddr)
    {
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "Sanity check failed pMcastAddr %pK", pMcastAddr));
        return NULL;
    }

    index = WLANTL_RmcHashRmcSession(pMcastAddr);
    pNode = rmcSession[index];
    while ( pNode )
    {
        if (vos_is_macaddr_equal( &(pNode->rmcAddr), pMcastAddr))
        {
            return pNode;
        }
        pNode = pNode->next;
    }

    return NULL;
}

WLANTL_RMC_SESSION *WLANTL_RmcAddRmcSession
(
  WLANTL_RMC_SESSION *rmcSession[],
  v_MACADDR_t   *pMcastAddr
)
{
    WLANTL_RMC_SESSION *pNode;
    tANI_U8               index;

    index = WLANTL_RmcHashRmcSession(pMcastAddr);
    pNode = WLANTL_RmcLookUpRmcSession(rmcSession, pMcastAddr);
    if ( NULL != pNode )
    {
        /*already exists*/
        return NULL;
    }
    else
    {
        pNode = (WLANTL_RMC_SESSION *)vos_mem_malloc(sizeof(*pNode));
        if (pNode)
        {
            vos_mem_copy( &(pNode->rmcAddr), pMcastAddr,
                sizeof(pNode->rmcAddr) );
            pNode->next = rmcSession[index];
            rmcSession[index] = pNode;
            return pNode;
        }
        else
        {
            VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                "%s: vos_mem_malloc failed can't enable RMC session",
                __func__);
            return NULL;
        }
    }
}

tANI_U8
WLANTL_RmcDeleteRmcSession
(
  WLANTL_RMC_SESSION *rmcSession[],
  v_MACADDR_t   *pMcastAddr
)
{
    WLANTL_RMC_SESSION *pHead;
    WLANTL_RMC_SESSION *pNode;
    WLANTL_RMC_SESSION *pPrev;
    tANI_U8               index;

    index = WLANTL_RmcHashRmcSession(pMcastAddr);
    pHead = pNode = rmcSession[index];
    while (pNode)
    {
        if (vos_is_macaddr_equal( &(pNode->rmcAddr), pMcastAddr))
        {
            if (pHead == pNode)
            {
                rmcSession[index] = pNode->next;
            }
            else
            {
                pPrev->next = pNode->next;
            }
            vos_mem_free((v_VOID_t * )pNode);
            return 1;
        }
        pPrev = pNode;
        pNode = pNode->next;
    }

    return 0;
}

VOS_STATUS
WLANTL_ProcessRmcCommand
(
    WLANTL_CbType*  pTLCb,
    v_MACADDR_t    *pMcastAddr,
    tANI_U32        command
)
{
    VOS_STATUS status;
    tANI_U32 count;
    tANI_U32 rmcActive;

    if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire( &(pTLCb->rmcLock))))
    {
        TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "%s Get Lock Fail", __func__));
        return VOS_STATUS_E_FAILURE;
    }

    /*add or delete node from active rmc hash table*/
    if (command)
    {
        /*add requested rmc session in active rmc session list*/
        if (WLANTL_RmcAddRmcSession(pTLCb->rmcSession, pMcastAddr))
        {
            TLLOGE( VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                "RMC session " MAC_ADDRESS_STR " added in TL hash table",
                MAC_ADDR_ARRAY(pMcastAddr->bytes) ) );
            pTLCb->rmcDataPathEnabled = TRUE;
            status = VOS_STATUS_SUCCESS;
        }
        else
        {
            TLLOGE( VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                "RMC session " MAC_ADDRESS_STR " already exists in TL hash"
                " table", MAC_ADDR_ARRAY(pMcastAddr->bytes) ) );
            status = VOS_STATUS_E_FAILURE;
        }
    }
    else
    {
        /*delete requested rmc session from active rmc session list*/
        if (WLANTL_RmcDeleteRmcSession(pTLCb->rmcSession, pMcastAddr))
        {
            TLLOGE( VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
                "RMC session " MAC_ADDRESS_STR " deleted from TL hash table",
                MAC_ADDR_ARRAY(pMcastAddr->bytes)) );
            status = VOS_STATUS_SUCCESS;
            rmcActive = FALSE;
            for ( count = 0; count < WLANTL_RMC_HASH_TABLE_SIZE; count++ )
            {
                if (pTLCb->rmcSession[count])
                {
                    rmcActive = TRUE;
                    break;
                }
            }
            if (TRUE == rmcActive)
            {
                pTLCb->rmcDataPathEnabled = TRUE;
            }
            else
            {
                pTLCb->rmcDataPathEnabled = FALSE;
            }
        }
        else
        {
            TLLOGE( VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                "RMC session " MAC_ADDRESS_STR " doesn't exist in TL hash"
                " table", MAC_ADDR_ARRAY(pMcastAddr->bytes) ) );
            status = VOS_STATUS_E_FAILURE;
        }
    }

    if (!VOS_IS_STATUS_SUCCESS(vos_lock_release(&(pTLCb->rmcLock))))
    {
         TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
             "%s Release Lock Fail", __func__));
         return VOS_STATUS_E_FAILURE;
    }

    return status;
}/* End of WLANTL_ProcessRmcCommand */

VOS_STATUS
WLANTL_EnableRMC
(
    v_PVOID_t     pvosGCtx,
    v_MACADDR_t   *pMcastTransmitterAddr
)
{
    WLANTL_CbType*  pTLCb;
    VOS_STATUS status;

    /*sanity check*/
    if ( (NULL == pvosGCtx) || (NULL == pMcastTransmitterAddr) )
    {
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL %s: Sanity check failed pvosGCtx %pK aMcastAddr %pK",
            __func__, pvosGCtx, pMcastTransmitterAddr));
        return VOS_STATUS_E_FAILURE;
    }

    /*sanity check*/
    pTLCb = VOS_GET_TL_CB(pvosGCtx);
    if ( NULL == pTLCb )
    {
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL %s: pTLCb is NULL", __func__));
        return VOS_STATUS_E_FAILURE;
    }

    status = WLANTL_ProcessRmcCommand(pTLCb, pMcastTransmitterAddr , 1);

    return status;
} /* End of WLANTL_EnableRMC */


VOS_STATUS
WLANTL_DisableRMC
(
    v_PVOID_t     pvosGCtx,
    v_MACADDR_t   *pMcastTransmitterAddr
)
{
    WLANTL_CbType* pTLCb;
    VOS_STATUS status;

    /*Sanity check*/
    if ((NULL == pvosGCtx) || (NULL == pMcastTransmitterAddr))
    {
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL %s: Sanity check failed pvosGCtx %pK aMcastAddr %pK",
             __func__, pvosGCtx, pMcastTransmitterAddr));
        return VOS_STATUS_E_FAILURE;
    }

    /*Sanity check*/
    pTLCb = VOS_GET_TL_CB(pvosGCtx);
    if (NULL == pTLCb)
    {
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL %s: pTLCb is NULL", __func__));
        return VOS_STATUS_E_FAILURE;
    }

    status = WLANTL_ProcessRmcCommand(pTLCb, pMcastTransmitterAddr, 0);

    return status;
} /* End of WLANTL_DisableRMC */


/*=============================================================================
        Duplicate Multicast Detection Functions
==============================================================================*/

/*=============================================================================
  FUNCTION    WLANTL_IsDuplicateMcastFrm

  DESCRIPTION
    This function checks for duplicast multicast frames and drops them.

  DEPENDENCIES

  PARAMETERS

   IN

   pClientSTA  : Pointer to WLANTL_STAClientType
   aucBDHeader : Pointer to BD header

  RETURN VALUE

    VOS_FALSE:  This frame is not a duplicate

    VOS_TRUE:   This frame is a duplicate

==============================================================================*/
v_U8_t
WLANTL_IsDuplicateMcastFrm
(
    WLANTL_STAClientType *pClientSTA,
    vos_pkt_t *vosDataBuff
)
{
    v_U8_t duplicate = VOS_FALSE;
    WLANTL_RMC_SESSION *pNode;
    v_U16_t     usSeqCtrl;
    v_MACADDR_t mcastAddr;
    VOS_STATUS  vosStatus;
    v_PVOID_t   pvPeekData;

    /* Get address 1 of Data Frame */
    vosStatus = vos_pkt_peek_data(vosDataBuff, WLANTL_MAC_ADDR_ALIGN(1),
                                  (v_PVOID_t)&pvPeekData, VOS_MAC_ADDR_SIZE);

    if ( VOS_STATUS_SUCCESS != vosStatus )
    {
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                "WLAN TL: Failed to get Addr 1 of 80211 header from packet %d",
                vosStatus));
        return VOS_FALSE;
    }

    /* Copy address 1 of Data Frame */
    vos_mem_copy(&mcastAddr.bytes, pvPeekData, VOS_MAC_ADDR_SIZE);

    /*
     * We perform duplicate detection for only multicast data frames
     */
    if (vos_is_macaddr_group(&mcastAddr) &&
         !vos_is_macaddr_broadcast(&mcastAddr))
    {
        /* Get sequence control of Data Frame */
        vosStatus = vos_pkt_peek_data(vosDataBuff,
                    (WLANTL_MAC_ADDR_ALIGN(1) + (3 * VOS_MAC_ADDR_SIZE)),
                      (v_PVOID_t)&pvPeekData, sizeof(v_U16_t));

        if ( VOS_STATUS_SUCCESS != vosStatus )
        {
            TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                    "WLAN TL: Failed to get Sequence Control from packet %d",
                    vosStatus));
            return VOS_FALSE;
        }

        /* Copy sequence control from the Data Frame */
        usSeqCtrl = *(v_U16_t *)pvPeekData;

        if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&(pClientSTA->mcLock))))
        {
            TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                    "%s Get Lock Fail", __func__));
            return VOS_FALSE;
        }

        pNode = WLANTL_RmcLookUpRmcSession(pClientSTA->mcastSession,
                                                      &mcastAddr);
        if (NULL == pNode)
        {
            /* If the session does not exist, add it. */
            pNode = WLANTL_RmcAddRmcSession(pClientSTA->mcastSession,
                                              &mcastAddr);
            /* If we could not add a entry, skip duplicate detection */
            if (NULL == pNode)
            {
                TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                    "%s Failed to add multicast session", __func__));
                if (!VOS_IS_STATUS_SUCCESS
                     (vos_lock_release(&(pClientSTA->mcLock))))
                {
                    TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                        "%s Release Lock Fail", __func__));
                }
                return VOS_FALSE;
            }
            /* Initialize the sequence control value. */
            pNode->mcSeqCtl = usSeqCtrl;
        }
        else
        {
            /*
             * Check if the sequence number of this frame matches the last
             * we have seen.
             */
            if (pNode->mcSeqCtl == usSeqCtrl)
            {
                pNode->rxMCDupcnt++;
                TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
                     "%s Rx Multicast Duplicate %d " MAC_ADDRESS_STR
                     " (Seq %x)", __func__,
                     pNode->rxMCDupcnt, MAC_ADDR_ARRAY(mcastAddr.bytes),
                     usSeqCtrl));
                duplicate = VOS_TRUE;
            }
            else
            {
                /* Update the last seen sequence number */
                pNode->mcSeqCtl = usSeqCtrl;
            }
        }

        if (!VOS_IS_STATUS_SUCCESS (vos_lock_release(&(pClientSTA->mcLock))))
        {
            TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                    "%s Release Lock Fail", __func__));
        }
    }

    return duplicate;
}

/*=============================================================================
  FUNCTION    WLANTL_McastDeleteAllEntries

  DESCRIPTION
    This function removes all multicast entries used for duplicate detection

  DEPENDENCIES

  PARAMETERS

   IN

   pClientSTA  : Pointer to WLANTL_STAClientType

  RETURN VALUE

    None

==============================================================================*/
void
WLANTL_McastDeleteAllEntries(WLANTL_STAClientType * pClientSTA)
{
    WLANTL_RMC_SESSION *pNode, **head;
    int index;

    TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
                        "%s Deleting all multicast entries", __func__));

    if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&(pClientSTA->mcLock))))
    {
        TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                "%s Get Lock Fail", __func__));
        return;
    }

    for (index = 0; index < WLANTL_RMC_HASH_TABLE_SIZE; index++)
    {
        head = &pClientSTA->mcastSession[index];

        pNode = *head;

        while (pNode)
        {
            *head = pNode->next;
            /* free the group entry */
            vos_mem_free(pNode);
            pNode = *head;
        }
    }

    if (!VOS_IS_STATUS_SUCCESS (vos_lock_release(&(pClientSTA->mcLock))))
    {
        TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
                "%s Release Lock Fail", __func__));
    }
}

/*=============================================================================
  FUNCTION    WLANTL_SetMcastDuplicateDetection

  DESCRIPTION
    This function sets multicate duplicate detection operation.
    If enable is 1, the detection is enabled, else it is disabled.

  DEPENDENCIES

  PARAMETERS

   IN

   pvosGCtx   : Pointer to VOS global context
   enable : Boolean to enable or disable

  RETURN VALUE
    The result code associated with performing the operation

    VOS_STATUS_E_FAULT:   Sanity check on input failed

    VOS_STATUS_SUCCESS:   Everything is good :)

   Other return values are possible coming from the called functions.
   Please check API for additional info.

  SIDE EFFECTS

==============================================================================*/
VOS_STATUS
WLANTL_SetMcastDuplicateDetection
(
    v_PVOID_t     pvosGCtx,
    v_U8_t        enable
)
{
    WLANTL_CbType* pTLCb;

    /*Sanity check*/
    if (NULL == pvosGCtx)
    {
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL %s: Sanity check failed pvosGCtx %pK",
             __func__, pvosGCtx));
        return VOS_STATUS_E_FAILURE;
    }

    /*Sanity check*/
    pTLCb = VOS_GET_TL_CB(pvosGCtx);
    if (NULL == pTLCb)
    {
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL %s: pTLCb is NULL", __func__));
        return VOS_STATUS_E_FAILURE;
    }

    switch (enable)
    {
    default:
        /*
         * Any value other than 0 or 1 is used to dump the
         * duplicate count.
         */
        TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
            "WLAN TL %s: Multicast Duplicate Count %d",
             __func__, pTLCb->mcastDupCnt));
        break;
    case 0:
    case 1:
        pTLCb->multicastDuplicateDetectionEnabled = enable;
        break;
    }

    return VOS_STATUS_SUCCESS;
}

#endif /* WLAN_FEATURE_RMC */
