wlan: Wait for ack and issue delsta after transmitting the disassoc/Deauth.

After transmitting the Disassoc/Deauth frames, wait for ack and then
issue delsta.
This will ensures that Disassoc/Deauth being transmitted over the air
before deleting the sta structures for corresponding session.

Change-Id: I23107cf454ad605728e7b75cc1cd3134c5d6cdd8
CR-Fixed: 414558,411684
diff --git a/CORE/MAC/src/pe/lim/limSendManagementFrames.c b/CORE/MAC/src/pe/lim/limSendManagementFrames.c
index 7753391..77f7b7c 100644
--- a/CORE/MAC/src/pe/lim/limSendManagementFrames.c
+++ b/CORE/MAC/src/pe/lim/limSendManagementFrames.c
@@ -44,6 +44,9 @@
 #include "limStaHashApi.h"
 #include "schApi.h"
 #include "limSendMessages.h"
+#include "limAssocUtils.h"
+#include "limFT.h"
+
 #if defined WLAN_FEATURE_VOWIFI
 #include "rrmApi.h"
 #endif
@@ -3666,6 +3669,155 @@
     return;
 } /*** end limSendAuthMgmtFrame() ***/
 
+eHalStatus limSendDeauthCnf(tpAniSirGlobal pMac)
+{
+    tANI_U16                aid;
+    tpDphHashNode           pStaDs;
+    tLimMlmDeauthReq        *pMlmDeauthReq;
+    tLimMlmDeauthCnf        mlmDeauthCnf;
+    tpPESession             psessionEntry;
+
+    pMlmDeauthReq = pMac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq;
+    if (pMlmDeauthReq)
+    {
+        if (tx_timer_running(&pMac->lim.limTimers.gLimDeauthAckTimer))
+        {
+            limDeactivateAndChangeTimer(pMac, eLIM_DEAUTH_ACK_TIMER);
+        }
+
+        if((psessionEntry = peFindSessionBySessionId(pMac, pMlmDeauthReq->sessionId))== NULL)
+        {
+
+            PELOGE(limLog(pMac, LOGE,
+                        FL("session does not exist for given sessionId\n"));)
+                mlmDeauthCnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
+            goto end;
+        }
+
+        pStaDs = dphLookupHashEntry(pMac, pMlmDeauthReq->peerMacAddr, &aid, &psessionEntry->dph.dphHashTable);
+        if (pStaDs == NULL)
+        {
+            mlmDeauthCnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
+            goto end;
+        }
+
+
+        /// Receive path cleanup with dummy packet
+        limCleanupRxPath(pMac, pStaDs,psessionEntry);
+        /// Free up buffer allocated for mlmDeauthReq
+        palFreeMemory( pMac->hHdd, (tANI_U8 *) pMlmDeauthReq);
+        pMac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq = NULL;
+    }
+    return eHAL_STATUS_SUCCESS;
+end:
+    palCopyMemory( pMac->hHdd, (tANI_U8 *) &mlmDeauthCnf.peerMacAddr,
+            (tANI_U8 *) pMlmDeauthReq->peerMacAddr,
+            sizeof(tSirMacAddr));
+    mlmDeauthCnf.deauthTrigger = pMlmDeauthReq->deauthTrigger;
+    mlmDeauthCnf.aid           = pMlmDeauthReq->aid;
+    mlmDeauthCnf.sessionId = pMlmDeauthReq->sessionId;
+
+    // Free up buffer allocated
+    // for mlmDeauthReq
+    palFreeMemory( pMac->hHdd, (tANI_U8 *) pMlmDeauthReq);
+
+    limPostSmeMessage(pMac,
+            LIM_MLM_DEAUTH_CNF,
+            (tANI_U32 *) &mlmDeauthCnf);
+    return eHAL_STATUS_SUCCESS;
+}
+
+eHalStatus limSendDisassocCnf(tpAniSirGlobal pMac)
+{
+    tANI_U16                 aid;
+    tpDphHashNode            pStaDs;
+    tLimMlmDisassocCnf       mlmDisassocCnf;
+    tpPESession              psessionEntry;
+    tLimMlmDisassocReq       *pMlmDisassocReq;
+
+    pMlmDisassocReq = pMac->lim.limDisassocDeauthCnfReq.pMlmDisassocReq;
+    if (pMlmDisassocReq)
+    {
+        if (tx_timer_running(&pMac->lim.limTimers.gLimDisassocAckTimer))
+        {
+            limDeactivateAndChangeTimer(pMac, eLIM_DISASSOC_ACK_TIMER);
+        }
+
+        if((psessionEntry = peFindSessionBySessionId(pMac, pMlmDisassocReq->sessionId))== NULL)
+        {
+
+            PELOGE(limLog(pMac, LOGE,
+                        FL("session does not exist for given sessionId\n"));)
+                mlmDisassocCnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
+            goto end;
+        }
+
+        pStaDs = dphLookupHashEntry(pMac, pMlmDisassocReq->peerMacAddr, &aid, &psessionEntry->dph.dphHashTable);
+        if (pStaDs == NULL)
+        {
+            mlmDisassocCnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
+            goto end;
+        }
+
+        /// Receive path cleanup with dummy packet
+        if(eSIR_SUCCESS != limCleanupRxPath(pMac, pStaDs, psessionEntry))
+        {
+            mlmDisassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
+            goto end;
+        }
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+        if  ( (psessionEntry->limSystemRole == eLIM_STA_ROLE ) &&
+                (
+#ifdef FEATURE_WLAN_CCX
+                 (psessionEntry->isCCXconnection ) ||
+#endif
+                 (psessionEntry->is11Rconnection )) &&
+                (pMlmDisassocReq->reasonCode != eSIR_MAC_DISASSOC_DUE_TO_FTHANDOFF_REASON))
+        {
+            PELOGE(limLog(pMac, LOGE, FL("FT Preauth Session Cleanup \n"));)
+                limFTCleanup(pMac);
+        }
+#endif
+
+        /// Free up buffer allocated for mlmDisassocReq
+        palFreeMemory( pMac->hHdd, (tANI_U8 *) pMlmDisassocReq);
+        pMac->lim.limDisassocDeauthCnfReq.pMlmDisassocReq = NULL;
+        return eHAL_STATUS_SUCCESS;
+    }
+    else
+    {
+        return eHAL_STATUS_SUCCESS;
+    }
+end:
+    palCopyMemory( pMac->hHdd, (tANI_U8 *) &mlmDisassocCnf.peerMacAddr,
+            (tANI_U8 *) pMlmDisassocReq->peerMacAddr,
+            sizeof(tSirMacAddr));
+    mlmDisassocCnf.aid = pMlmDisassocReq->aid;
+    mlmDisassocCnf.disassocTrigger = pMlmDisassocReq->disassocTrigger;
+
+    /* Update PE session ID*/
+    mlmDisassocCnf.sessionId = pMlmDisassocReq->sessionId;
+
+    /// Free up buffer allocated for mlmDisassocReq
+    palFreeMemory( pMac->hHdd, (tANI_U8 *) pMlmDisassocReq);
+
+    limPostSmeMessage(pMac,
+            LIM_MLM_DISASSOC_CNF,
+            (tANI_U32 *) &mlmDisassocCnf);
+    return eHAL_STATUS_SUCCESS;
+}
+
+eHalStatus limDisassocTxCompleteCnf(tpAniSirGlobal pMac, tANI_U32 txCompleteSuccess)
+{
+    return limSendDisassocCnf(pMac);
+}
+
+eHalStatus limDeauthTxCompleteCnf(tpAniSirGlobal pMac, tANI_U32 txCompleteSuccess)
+{
+    return limSendDeauthCnf(pMac);
+}
+
 /**
  * \brief This function is called to send Disassociate frame.
  *
@@ -3684,7 +3836,9 @@
 void
 limSendDisassocMgmtFrame(tpAniSirGlobal pMac,
                          tANI_U16       nReason,
-                         tSirMacAddr    peer,tpPESession psessionEntry)
+                         tSirMacAddr    peer,
+                         tpPESession psessionEntry,
+                         tANI_BOOLEAN waitForAck)
 {
     tDot11fDisassociation frm;
     tANI_U8              *pFrame;
@@ -3694,7 +3848,7 @@
     void                 *pPacket;
     eHalStatus            halstatus;
     tANI_U8               txFlag = 0;
-
+    tANI_U32              val = 0;
     if(NULL == psessionEntry)
     {
         return;
@@ -3784,21 +3938,52 @@
         txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
     }
 
-    // Queue Disassociation frame in high priority WQ
-    halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes,
-                            HAL_TXRX_FRM_802_11_MGMT,
-                            ANI_TXDIR_TODS,
-                            7,//SMAC_SWBD_TX_TID_MGMT_HIGH,
-                            limTxComplete, pFrame, txFlag );
-    if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
+    if (waitForAck)
     {
-        limLog( pMac, LOGE, FL("Failed to send Disassociation "
-                               "(%X)!\n"),
-                nSirStatus );
-        //Pkt will be freed up by the callback
-        return;
-    }
+        // Queue Disassociation frame in high priority WQ
+        /* get the duration from the request */
+        halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes,
+                HAL_TXRX_FRM_802_11_MGMT,
+                ANI_TXDIR_TODS,
+                7,//SMAC_SWBD_TX_TID_MGMT_HIGH,
+                limTxComplete, pFrame, limDisassocTxCompleteCnf,
+                txFlag );
+        val = SYS_MS_TO_TICKS(LIM_DISASSOC_DEAUTH_ACK_TIMEOUT);
 
+        if (tx_timer_change(
+                    &pMac->lim.limTimers.gLimDisassocAckTimer, val, 0)
+                != TX_SUCCESS)
+        {
+            limLog(pMac, LOGP,
+                    FL("Unable to change Disassoc ack Timer val\n"));
+            return;
+        }
+        else if(TX_SUCCESS != tx_timer_activate(
+                    &pMac->lim.limTimers.gLimDisassocAckTimer))
+        {
+            limLog(pMac, LOGP,
+                    FL("Unable to activate Disassoc ack Timer\n"));
+            limDeactivateAndChangeTimer(pMac, eLIM_DISASSOC_ACK_TIMER);
+            return;
+        }
+    }
+    else
+    {
+        // Queue Disassociation frame in high priority WQ
+        halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes,
+                HAL_TXRX_FRM_802_11_MGMT,
+                ANI_TXDIR_TODS,
+                7,//SMAC_SWBD_TX_TID_MGMT_HIGH,
+                limTxComplete, pFrame, txFlag );
+        if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
+        {
+            limLog( pMac, LOGE, FL("Failed to send Disassociation "
+                        "(%X)!\n"),
+                    nSirStatus );
+            //Pkt will be freed up by the callback
+            return;
+        }
+    }
 } // End limSendDisassocMgmtFrame.
 
 /**
@@ -3818,7 +4003,9 @@
 void
 limSendDeauthMgmtFrame(tpAniSirGlobal pMac,
                        tANI_U16       nReason,
-                       tSirMacAddr    peer,tpPESession psessionEntry)
+                       tSirMacAddr    peer,
+                       tpPESession psessionEntry,
+                       tANI_BOOLEAN waitForAck)
 {
     tDot11fDeAuth    frm;
     tANI_U8         *pFrame;
@@ -3828,7 +4015,7 @@
     void            *pPacket;
     eHalStatus       halstatus;
     tANI_U8          txFlag = 0;
-
+    tANI_U32         val = 0;
     if(NULL == psessionEntry)
     {
         return;
@@ -3918,19 +4105,58 @@
         txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
     }
 
-    // Queue Disassociation frame in high priority WQ
-    halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes,
-                            HAL_TXRX_FRM_802_11_MGMT,
-                            ANI_TXDIR_TODS,
-                            7,//SMAC_SWBD_TX_TID_MGMT_HIGH,
-                            limTxComplete, pFrame, txFlag );
-    if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
+    if (waitForAck)
     {
-        limLog( pMac, LOGE, FL("Failed to send De-Authentication "
-                               "(%X)!\n"),
-                nSirStatus );
-        //Pkt will be freed up by the callback
-        return;
+        // Queue Disassociation frame in high priority WQ
+        halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes,
+                HAL_TXRX_FRM_802_11_MGMT,
+                ANI_TXDIR_TODS,
+                7,//SMAC_SWBD_TX_TID_MGMT_HIGH,
+                limTxComplete, pFrame, limDeauthTxCompleteCnf, txFlag );
+        if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
+        {
+            limLog( pMac, LOGE, FL("Failed to send De-Authentication "
+                        "(%X)!\n"),
+                    nSirStatus );
+            //Pkt will be freed up by the callback
+            return;
+        }
+
+        val = SYS_MS_TO_TICKS(LIM_DISASSOC_DEAUTH_ACK_TIMEOUT);
+
+        if (tx_timer_change(
+                    &pMac->lim.limTimers.gLimDeauthAckTimer, val, 0)
+                != TX_SUCCESS)
+        {
+            limLog(pMac, LOGP,
+                    FL("Unable to change Deauth ack Timer val\n"));
+            return;
+        }
+        else if(TX_SUCCESS != tx_timer_activate(
+                    &pMac->lim.limTimers.gLimDeauthAckTimer))
+        {
+            limLog(pMac, LOGP,
+                    FL("Unable to activate Deauth ack Timer\n"));
+            limDeactivateAndChangeTimer(pMac, eLIM_DEAUTH_ACK_TIMER);
+            return;
+        }
+    }
+    else
+    {
+        // Queue Disassociation frame in high priority WQ
+        halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes,
+                HAL_TXRX_FRM_802_11_MGMT,
+                ANI_TXDIR_TODS,
+                7,//SMAC_SWBD_TX_TID_MGMT_HIGH,
+                limTxComplete, pFrame, txFlag );
+        if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
+        {
+            limLog( pMac, LOGE, FL("Failed to send De-Authentication "
+                        "(%X)!\n"),
+                    nSirStatus );
+            //Pkt will be freed up by the callback
+            return;
+        }
     }
 
 } // End limSendDeauthMgmtFrame.