wlan: MCC- EAPOL frame to use TX_HIGH_PRIO DXE channel and mgmt pool

EAPOL frames cannot be delayed even if DATA pool is full
MCC second session EAPOL failure under high data traffic in first
session

Change-Id: I702224d3873826aa3954bcb2a76868f1e25d08bd
CR-Fixed: 387009, 412052
diff --git a/CORE/TL/src/wlan_qct_tl.c b/CORE/TL/src/wlan_qct_tl.c
index 8aa0a5a..d70f1dd 100644
--- a/CORE/TL/src/wlan_qct_tl.c
+++ b/CORE/TL/src/wlan_qct_tl.c
@@ -1222,7 +1222,8 @@
   pTLCb->atlSTAClients[pwSTADescType->ucSTAId].ucCurrentAC     = WLANTL_AC_VO;
   pTLCb->atlSTAClients[pwSTADescType->ucSTAId].ucCurrentWeight = 0;
   pTLCb->atlSTAClients[pwSTADescType->ucSTAId].ucServicedAC    = WLANTL_AC_BK;
-  
+  pTLCb->atlSTAClients[pwSTADescType->ucSTAId].ucEapolPktPending = 0;
+
   vos_mem_zero( pTLCb->atlSTAClients[pwSTADescType->ucSTAId].aucACMask,
                 sizeof(pTLCb->atlSTAClients[pwSTADescType->ucSTAId].aucACMask)); 
 
@@ -1699,9 +1700,15 @@
     --------------------------------------------------------------------*/
   pTLCb->ucRegisteredStaId = ucSTAId;
 
-  if( WLANTL_STA_AUTHENTICATED != pTLCb->atlSTAClients[ucSTAId].tlState )
-  {
-    VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+  if( WLANTL_STA_CONNECTED == pTLCb->atlSTAClients[ucSTAId].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 */
+    pTLCb->atlSTAClients[ucSTAId].ucEapolPktPending = 1;
+
+    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, pTLCb->atlSTAClients[ucSTAId].tlState);
   }
@@ -1713,7 +1720,8 @@
     through WLANTL_TX_STAID_AC_IND message.
   -----------------------------------------------------------------------*/
 #ifdef WLAN_SOFTAP_FEATURE
-    if (WLAN_STA_SOFTAP != pTLCb->atlSTAClients[ucSTAId].wSTADesc.wSTAType)
+    if ((WLAN_STA_SOFTAP != pTLCb->atlSTAClients[ucSTAId].wSTADesc.wSTAType) &&
+        !(vos_concurrent_sessions_running()))
     {
 #endif
 
@@ -2089,7 +2097,7 @@
                     ucWDSEnabled, extraHeadSpace, pMetaInfo->ucType,
                             &pTLCb->atlSTAClients[ucStaId].wSTADesc.vSelfMACAddress,
                     pMetaInfo->ucTID, 0 /* No ACK */, pMetaInfo->usTimeStamp,
-                    pMetaInfo->ucIsEapol, pMetaInfo->ucUP );
+                    pMetaInfo->ucIsEapol || pMetaInfo->ucIsWai, pMetaInfo->ucUP );
 
   if ( VOS_STATUS_SUCCESS != vosStatus )
   {
@@ -3702,6 +3710,112 @@
         break; /* Out of resources or reached max len */
       }
     }
+#if defined( FEATURE_WLAN_INTEGRATED_SOC )
+    /* 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 ((pTLCb->atlSTAClients[i].ucExists) &&
+               (0 == pTLCb->atlSTAClients[i].ucTxSuspended) &&
+               (pTLCb->atlSTAClients[i].ucEapolPktPending)
+               )
+               break;
+        }
+
+        if (i >= WLAN_MAX_STA_COUNT)
+        {
+           /* No More to Serve Exit Get Frames */
+           break;
+        }
+        /* Serve EAPOL frame with HI_FLOW_MASK */
+        ucSTAId = i;
+
+        wSTAEvent = WLANTL_TX_EVENT;
+
+        pfnSTAFsm = tlSTAFsm[pTLCb->atlSTAClients[ucSTAId].tlState].
+                        pfnSTATbl[wSTAEvent];
+
+        if ( NULL != pfnSTAFsm )
+        {
+          pTLCb->atlSTAClients[ucSTAId].ucNoMoreData = 0;
+          vosStatus  = pfnSTAFsm( pvosGCtx, ucSTAId, &vosTempBuf);
+
+          if (( VOS_STATUS_SUCCESS != vosStatus ) &&
+              ( NULL != vosTempBuf ))
+          {
+               pTLCb->atlSTAClients[ucSTAId].pfnSTATxComp( pvosGCtx,
+                                                           vosTempBuf,
+                                                           vosStatus );
+               vosTempBuf = NULL;
+               break;
+          }/* status success*/
+        }
+
+        if (NULL != vosTempBuf)
+        {
+            WDA_TLI_PROCESS_FRAME_LEN( vosTempBuf, usPktLen, uResLen, uTotalPktLen);
+
+            VOS_ASSERT( usPktLen <= WLANTL_MAX_ALLOWED_LEN);
+
+            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*/ );
+
+              pTLCb->atlSTAClients[i].ucEapolPktPending = 0;
+
+              VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
+                "WLAN TL:GetFrames STA: %d EAPOLPktPending %d",
+                         ucSTAId, pTLCb->atlSTAClients[ucSTAId].ucEapolPktPending);
+
+              /*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;
+
+#ifdef WLAN_SOFTAP_FEATURE
+              //fow control update
+              pTLCb->atlSTAClients[ucSTAId].uIngress_length += uResLen;
+              pTLCb->atlSTAClients[ucSTAId].uBuffThresholdMax = (pTLCb->atlSTAClients[ucSTAId].uBuffThresholdMax >= uResLen) ?
+                (pTLCb->atlSTAClients[ucSTAId].uBuffThresholdMax - uResLen) : 0;
+#endif
+            }
+         }
+         else
+         {  // no EAPOL frames exit Get frames
+            break;
+         }
+    }
+#endif /* FEATURE_WLAN_INTEGRATED_SOC */
+
     else if (( WDA_TLI_MIN_RES_DATA <= pTLCb->uResCount )&&
              ( 0 == pTLCb->ucTxSuspended )
 #if defined( FEATURE_WLAN_INTEGRATED_SOC )
@@ -5852,7 +5966,7 @@
                           extraHeadSpace,
                           ucTypeSubtype, &pTLCb->atlSTAClients[ucSTAId].wSTADesc.vSelfMACAddress,
                           ucTid, HAL_TX_NO_ENCRYPTION_MASK,
-                          tlMetaInfo.usTimeStamp, tlMetaInfo.ucIsEapol, tlMetaInfo.ucUP );
+                          tlMetaInfo.usTimeStamp, tlMetaInfo.ucIsEapol || tlMetaInfo.ucIsWai, tlMetaInfo.ucUP );
 
   if ( VOS_STATUS_SUCCESS != vosStatus )
   {
diff --git a/CORE/TL/src/wlan_qct_tli.h b/CORE/TL/src/wlan_qct_tli.h
index 3089d95..3e953de 100644
--- a/CORE/TL/src/wlan_qct_tli.h
+++ b/CORE/TL/src/wlan_qct_tli.h
@@ -523,6 +523,9 @@
   /*Packet pending flag - set if tx is pending for the station*/
   v_U8_t                        ucPktPending;
   
+  /*EAPOL Packet pending flag - set if EAPOL packet is pending for the station*/
+  v_U8_t                        ucEapolPktPending;
+
   /*used on tx packet to signal when there is no more data to tx for the 
    moment=> packets can be passed to BAL */
   v_U8_t                    ucNoMoreData;
diff --git a/CORE/WDI/DP/src/wlan_qct_wdi_ds.c b/CORE/WDI/DP/src/wlan_qct_wdi_ds.c
index 8798d70..98d549b 100644
--- a/CORE/WDI/DP/src/wlan_qct_wdi_ds.c
+++ b/CORE/WDI/DP/src/wlan_qct_wdi_ds.c
@@ -161,9 +161,13 @@
   switch(ucType)
   {
     case WDI_MAC_DATA_FRAME:
+       if(!pTxMetadata->isEapol)
+       {
        pMemPool = &(pClientData->dataMemPool);
        ucBdPoolType = WDI_DATA_POOL_ID;
-    break;
+       break;
+       }
+    // intentional fall-through to handle eapol packet as mgmt
     case WDI_MAC_MGMT_FRAME:
        pMemPool = &(pClientData->mgmtMemPool);
        ucBdPoolType = WDI_MGMT_POOL_ID;
@@ -195,7 +199,8 @@
   }  
 
   /* resource count only for data packet */
-  if(WDI_MAC_DATA_FRAME == ucType)
+  // EAPOL packet doesn't use data mem pool if being treated as higher priority
+  if(WDI_MAC_DATA_FRAME == ucType && (!pTxMetadata->isEapol))
   {
     WDI_DS_MemPoolIncreaseReserveCount(pMemPool, staId);
   }
diff --git a/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c b/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c
index 61741a4..9e388d8 100644
--- a/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c
+++ b/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c
@@ -90,12 +90,19 @@
   switch(pTxMetadata->frmType) 
   {
     case WDI_MAC_DATA_FRAME:
+    /* note that EAPOL frame hasn't incremented ReserveCount. see
+       WDI_DS_TxPacket() in wlan_qct_wdi_ds.c
+    */
+    if(!pTxMetadata->isEapol)
+    {
       /* SWAP BD header to get STA index for completed frame */
       WDI_SwapTxBd(pvBDHeader);
       staIndex = (wpt_uint8)WDI_TX_BD_GET_STA_ID(pvBDHeader);
       WDI_DS_MemPoolFree(&(pClientData->dataMemPool), pvBDHeader, physBDHeader);
       WDI_DS_MemPoolDecreaseReserveCount(&(pClientData->dataMemPool), staIndex);
       break;
+    }
+    // intentional fall-through to handle eapol packet as mgmt
     case WDI_MAC_MGMT_FRAME:
       WDI_DS_MemPoolFree(&(pClientData->mgmtMemPool), pvBDHeader, physBDHeader);
       break;
@@ -487,8 +494,12 @@
 
   // assign MDPU to correct channel??
   channel =  (pTxMetadata->frmType & WDI_MAC_DATA_FRAME)? 
-      WDTS_CHANNEL_TX_LOW_PRI : WDTS_CHANNEL_TX_HIGH_PRI;
-  
+    /* EAPOL frame uses TX_HIGH_PRIORITY DXE channel
+       To make sure EAPOL (for second session) is pushed even if TX_LO channel
+       already reached to low resource condition
+       This can happen especially in MCC, high data traffic TX in first session
+     */
+      ((pTxMetadata->isEapol) ? WDTS_CHANNEL_TX_HIGH_PRI : WDTS_CHANNEL_TX_LOW_PRI) : WDTS_CHANNEL_TX_HIGH_PRI;
   // Send packet to  Transport Driver. 
   status =  gTransportDriver.xmit(pDTDriverContext, pFrame, channel);
   return status;