wlan: Add assoc resp transmission handler in case of failure

It may be possible that in case of assoc failure, host may send delSTA
even before FW tries to tx association response frame queued by host
which may cause response timeout failure in peer.

Add changes to clean up Rx path only after assoc resp tx success.

Change-Id: Id5f9ffcc9211662ceb62f9af962fc6005c089650
CRs-Fixed: 2061969
diff --git a/CORE/MAC/src/pe/lim/limApi.c b/CORE/MAC/src/pe/lim/limApi.c
index ddac0e6..b21ad3a 100644
--- a/CORE/MAC/src/pe/lim/limApi.c
+++ b/CORE/MAC/src/pe/lim/limApi.c
@@ -703,6 +703,18 @@
    return retCode;
 }
 
+static void
+limInitAssocRspCompletiontionList(tpAniSirGlobal pMac)
+{
+    vos_list_init(&pMac->assoc_rsp_completion_list);
+}
+
+static void
+limDestroyAssocRspCompletiontionList(tpAniSirGlobal pMac)
+{
+    vos_list_destroy(&pMac->assoc_rsp_completion_list);
+}
+
 /**
  * limInitialize()
  *
@@ -753,6 +765,7 @@
     // Initializations for maintaining peers in IBSS
     limIbssInit(pMac);
 
+    limInitAssocRspCompletiontionList(pMac);
     pmmInitialize(pMac);
 
     
@@ -946,7 +959,7 @@
         vos_mem_free(pMac->lim.gpLimMlmScanReq);
         pMac->lim.gpLimMlmScanReq = NULL;
     }
-
+    limDestroyAssocRspCompletiontionList(pMac);
 #if 0
     if(NULL != pMac->lim.beacon)
     {
diff --git a/CORE/MAC/src/pe/lim/limAssocUtils.c b/CORE/MAC/src/pe/lim/limAssocUtils.c
index 90024d1..41a952d 100644
--- a/CORE/MAC/src/pe/lim/limAssocUtils.c
+++ b/CORE/MAC/src/pe/lim/limAssocUtils.c
@@ -1011,6 +1011,8 @@
                      tANI_U16 staId, tANI_U8 deleteSta, tSirResultCodes rCode, tpPESession psessionEntry )
 {
     tpDphHashNode       pStaDs;
+    assoc_rsp_tx_context *tx_complete_context = NULL;
+    vos_list_node_t *pNode= NULL;
 
     limLog(pMac, LOG1, FL("Sessionid: %d authType: %d subType: %d "
            "addPreAuthContext: %d staId: %d deleteSta: %d rCode : %d "
@@ -1049,23 +1051,38 @@
 
             return;
         }
+       vos_list_peek_front(&pMac->assoc_rsp_completion_list, &pNode);
+
+       tx_complete_context = vos_mem_malloc(sizeof(*tx_complete_context));
+       if (!tx_complete_context)
+       {
+            limLog(pMac, LOGW,
+                   FL("Failed to allocate memory"));
+
+            return;
+       }
+       tx_complete_context->psessionID = psessionEntry->peSessionId;
+       tx_complete_context->staId = staId;
+
+       if (pNode)
+            vos_list_insert_back(&pMac->assoc_rsp_completion_list,
+                              &tx_complete_context->node);
+       else
+            vos_list_insert_front(&pMac->assoc_rsp_completion_list,
+                              &tx_complete_context->node);
 
         /**
          * Polaris has state for this STA.
          * Trigger cleanup.
          */
         pStaDs->mlmStaContext.cleanupTrigger = eLIM_REASSOC_REJECT;
-
-        // Receive path cleanup
-        limCleanupRxPath(pMac, pStaDs, psessionEntry);
-   
         // Send Re/Association Response with
         // status code to requesting STA.
         limSendAssocRspMgmtFrame(pMac,
                                  rCode,
                                  0,
                                  peerAddr,
-                                 subType, 0,psessionEntry);
+                                 subType, 0,psessionEntry, tx_complete_context);
 
         if ( psessionEntry->parsedAssocReq[pStaDs->assocId] != NULL)
         {
@@ -1085,7 +1102,7 @@
                                  eSIR_MAC_MAX_ASSOC_STA_REACHED_STATUS,
                                  1,
                                  peerAddr,
-                                 subType, 0,psessionEntry);
+                                 subType, 0,psessionEntry, NULL);
         // Log error
         limLog(pMac, LOGW,
            FL("received Re/Assoc req when max associated STAs reached from "));
diff --git a/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c b/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c
index c08e9e0..e1b7978 100644
--- a/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c
+++ b/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c
@@ -260,7 +260,7 @@
                 limSendAssocRspMgmtFrame( pMac, eSIR_SUCCESS,
                     pStaDs->assocId, pStaDs->staAddr,
                     pStaDs->mlmStaContext.subType, pStaDs,
-                    psessionEntry);
+                    psessionEntry, NULL);
                 limLog(pMac, LOGE,
                     FL("DUT already received an assoc request frame "
                         "and STA is sending another assoc req.So, do not "
@@ -300,7 +300,7 @@
                     eSIR_MAC_UNSPEC_FAILURE_STATUS,
                     1,
                     pHdr->sa,
-                    subType, 0,psessionEntry);
+                    subType, 0,psessionEntry, NULL);
         return ;
     }
 
@@ -312,7 +312,7 @@
                                     eSIR_MAC_MIC_FAILURE_REASON,
                                     1,
                                     pHdr->sa,
-                                    subType, 0, psessionEntry);
+                                    subType, 0, psessionEntry, NULL);
         return;
     }
 
@@ -336,7 +336,8 @@
         limLog(pMac, LOGW,
                FL("Parse error AssocRequest, length=%d from "MAC_ADDRESS_STR),
                              framelen, MAC_ADDR_ARRAY(pHdr->sa));
-        limSendAssocRspMgmtFrame(pMac, eSIR_MAC_UNSPEC_FAILURE_STATUS, 1, pHdr->sa, subType, 0, psessionEntry);
+        limSendAssocRspMgmtFrame(pMac, eSIR_MAC_UNSPEC_FAILURE_STATUS, 1,
+                                 pHdr->sa, subType, 0, psessionEntry, NULL);
         goto error;
     }
 
@@ -378,7 +379,7 @@
                         eSIR_MAC_CAPABILITIES_NOT_SUPPORTED_STATUS,
                         1,
                         pHdr->sa,
-                        subType, 0,psessionEntry);
+                        subType, 0,psessionEntry ,NULL);
 
         goto error;
     }
@@ -403,7 +404,7 @@
                              eSIR_MAC_UNSPEC_FAILURE_STATUS,
                              1,
                              pHdr->sa,
-                             subType, 0,psessionEntry);
+                             subType, 0,psessionEntry, NULL);
 
         goto error;
     }
@@ -442,7 +443,7 @@
                     eSIR_MAC_BASIC_RATES_NOT_SUPPORTED_STATUS,
                     1,
                     pHdr->sa,
-                    subType, 0,psessionEntry);
+                    subType, 0,psessionEntry, NULL);
 
         goto error;
     }
@@ -455,7 +456,7 @@
         limLog(pMac, LOGE, FL("SOFTAP was in 11G only mode, rejecting legacy "
                               "STA : "MAC_ADDRESS_STR),MAC_ADDR_ARRAY(pHdr->sa));
         limSendAssocRspMgmtFrame( pMac, eSIR_MAC_CAPABILITIES_NOT_SUPPORTED_STATUS, 
-                                  1, pHdr->sa, subType, 0, psessionEntry );
+                                  1, pHdr->sa, subType, 0, psessionEntry, NULL);
         goto error;
 
     }//end if phyMode == 11G_only
@@ -467,7 +468,7 @@
         limLog(pMac, LOGE, FL("SOFTAP was in 11N only mode, rejecting legacy "
                               "STA : "MAC_ADDRESS_STR),MAC_ADDR_ARRAY(pHdr->sa));
         limSendAssocRspMgmtFrame( pMac, eSIR_MAC_CAPABILITIES_NOT_SUPPORTED_STATUS, 
-                                  1, pHdr->sa, subType, 0, psessionEntry );
+                                  1, pHdr->sa, subType, 0, psessionEntry, NULL);
         goto error;
     }//end if PhyMode == 11N_only
 
@@ -554,7 +555,7 @@
                     eSIR_MAC_OUTSIDE_SCOPE_OF_SPEC_STATUS,
                     1,
                     pHdr->sa,
-                    subType, 0,psessionEntry);
+                    subType, 0,psessionEntry, NULL);
 
         goto error;
     }
@@ -584,7 +585,7 @@
                            eSIR_MAC_BASIC_RATES_NOT_SUPPORTED_STATUS,
                            1,
                            pHdr->sa,
-                           subType, 0,psessionEntry);
+                           subType, 0,psessionEntry, NULL);
 
             
 #ifdef WLAN_DEBUG    
@@ -621,7 +622,7 @@
                            eSIR_MAC_WME_REFUSED_STATUS,
                            1,
                            pHdr->sa,
-                           subType, 0,psessionEntry);
+                           subType, 0,psessionEntry, NULL);
 
             goto error;
         }
@@ -710,7 +711,7 @@
                                FL("Invalid RSNIE received"));
                         limSendAssocRspMgmtFrame(pMac,
                               eSIR_MAC_INVALID_RSN_IE_CAPABILITIES_STATUS,
-                              1, pHdr->sa, subType, 0,psessionEntry);
+                              1, pHdr->sa, subType, 0,psessionEntry, NULL);
                         goto error;
                     }
 
@@ -732,7 +733,7 @@
                                            status,
                                            1,
                                            pHdr->sa,
-                                           subType, 0,psessionEntry);
+                                           subType, 0,psessionEntry, NULL);
 
                             goto error;
 
@@ -751,7 +752,7 @@
                                        eSIR_MAC_UNSUPPORTED_RSN_IE_VERSION_STATUS,
                                        1,
                                        pHdr->sa,
-                                       subType, 0,psessionEntry);
+                                       subType, 0,psessionEntry, NULL);
                         goto error;
 
                     }
@@ -768,7 +769,7 @@
                                    eSIR_MAC_INVALID_INFORMATION_ELEMENT_STATUS,
                                    1,
                                    pHdr->sa,
-                                   subType, 0,psessionEntry);
+                                   subType, 0,psessionEntry, NULL);
 
                     goto error;
                     
@@ -787,7 +788,7 @@
                         limLog(pMac, LOGE, FL("Invalid WPA IE"));
                         limSendAssocRspMgmtFrame(pMac,
                             eSIR_MAC_INVALID_INFORMATION_ELEMENT_STATUS,
-                            1, pHdr->sa, subType, 0,psessionEntry);
+                            1, pHdr->sa, subType, 0,psessionEntry, NULL);
                         goto error;
                     }
                     /* check the groupwise and pairwise cipher suites */
@@ -803,7 +804,7 @@
                                        status,
                                        1,
                                        pHdr->sa,
-                                       subType, 0,psessionEntry);
+                                       subType, 0,psessionEntry, NULL);
                         goto error;
 
                     }
@@ -820,7 +821,7 @@
                                    eSIR_MAC_INVALID_INFORMATION_ELEMENT_STATUS,
                                    1,
                                    pHdr->sa,
-                                   subType, 0,psessionEntry);
+                                   subType, 0,psessionEntry, NULL);
 
                     goto error;
                 }/* end - if(pAssocReq->wpa.length) */
@@ -949,7 +950,8 @@
                  */
                 pStaDs->pmfSaQueryRetryCount = 0;
                 limSendAssocRspMgmtFrame(pMac, eSIR_MAC_TRY_AGAIN_LATER, 1,
-                                         pHdr->sa, subType, pStaDs, psessionEntry);
+                                         pHdr->sa, subType, pStaDs,
+                                         psessionEntry, NULL);
                 limSendSaQueryRequestFrame(
                     pMac, (tANI_U8 *)&(pStaDs->pmfSaQueryCurrentTransId),
                     pHdr->sa, psessionEntry);
@@ -970,7 +972,8 @@
             // Request with try again later
             case DPH_SA_QUERY_IN_PROGRESS:
                 limSendAssocRspMgmtFrame(pMac, eSIR_MAC_TRY_AGAIN_LATER, 1,
-                                         pHdr->sa, subType, 0, psessionEntry);
+                                         pHdr->sa, subType, 0, psessionEntry,
+                                         NULL);
                 goto error;
 
             // SA Query procedure timed out, accept Association Request
@@ -1046,7 +1049,7 @@
                                eSIR_MAC_QAP_NO_BANDWIDTH_REASON,
                                1,
                                pHdr->sa,
-                               subType, 0,psessionEntry);
+                               subType, 0,psessionEntry, NULL);
 #ifdef WLAN_DEBUG    
                 pMac->lim.gLimNumAssocReqDropACRejectTS++;
 #endif
@@ -1062,7 +1065,7 @@
                     eSIR_MAC_QAP_NO_BANDWIDTH_REASON,
                     1,
                     pHdr->sa,
-                    subType, 0,psessionEntry);
+                    subType, 0,psessionEntry, NULL);
 #ifdef WLAN_DEBUG    
             pMac->lim.gLimNumAssocReqDropACRejectSta++;
 #endif
diff --git a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
index f749a8c..2f29a56 100644
--- a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
+++ b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
@@ -4030,8 +4030,10 @@
          */
         pStaDs->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE;
         limLog(pMac, LOG1, FL("sending Assoc Rsp frame to STA (assoc id=%d) "), pStaDs->assocId);
-        limSendAssocRspMgmtFrame( pMac, eSIR_SUCCESS, pStaDs->assocId, pStaDs->staAddr, 
-                                  pStaDs->mlmStaContext.subType, pStaDs, psessionEntry);
+        limSendAssocRspMgmtFrame(pMac, eSIR_SUCCESS, pStaDs->assocId,
+                                 pStaDs->staAddr,
+                                 pStaDs->mlmStaContext.subType, pStaDs,
+                                 psessionEntry, NULL);
         goto end;      
     } // (assocCnf.statusCode == eSIR_SME_SUCCESS)
     else
diff --git a/CORE/MAC/src/pe/lim/limSendManagementFrames.c b/CORE/MAC/src/pe/lim/limSendManagementFrames.c
index 1799c44..3dfc11b 100644
--- a/CORE/MAC/src/pe/lim/limSendManagementFrames.c
+++ b/CORE/MAC/src/pe/lim/limSendManagementFrames.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -1384,7 +1384,8 @@
                          tANI_U16       aid,
                          tSirMacAddr    peerMacAddr,
                          tANI_U8        subType,
-                         tpDphHashNode  pSta,tpPESession psessionEntry)
+                         tpDphHashNode  pSta,tpPESession psessionEntry,
+                         assoc_rsp_tx_context *tx_complete_context)
 {
     static tDot11fAssocResponse frm;
     tANI_U8             *pFrame, *macAddr;
@@ -1763,14 +1764,29 @@
 
     if (IS_FEATURE_SUPPORTED_BY_FW(ENHANCED_TXBD_COMPLETION))
     {
-        limLog(pMac, LOG1, FL("Re/AssocRsp - txBdToken %u"), pMac->lim.txBdToken);
+        limLog(pMac, LOG1, FL("Re/AssocRsp - txBdToken %u"),
+               pMac->lim.txBdToken);
         /// Queue Association Response frame in high priority WQ
-        halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes,
+        if (tx_complete_context)
+        {
+            tx_complete_context->txBdToken = pMac->lim.txBdToken;
+            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, limAssocRspTxCompleteCnf,
+                txFlag, pMac->lim.txBdToken);
+        }
+        else
+            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, limTxBdComplete,
-                txFlag, pMac->lim.txBdToken );
+                txFlag, pMac->lim.txBdToken);
+
         pMac->lim.txBdToken++;
     }
     else
diff --git a/CORE/MAC/src/pe/lim/limTypes.h b/CORE/MAC/src/pe/lim/limTypes.h
index 88a2abe..5fd9ce0 100644
--- a/CORE/MAC/src/pe/lim/limTypes.h
+++ b/CORE/MAC/src/pe/lim/limTypes.h
@@ -694,7 +694,9 @@
 void limSendAddtsRspActionFrame(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr,
                            tANI_U16 statusCode, tSirAddtsReqInfo *addts, tSirMacScheduleIE *pSchedule,tpPESession);
 
-void limSendAssocRspMgmtFrame(tpAniSirGlobal, tANI_U16, tANI_U16, tSirMacAddr, tANI_U8, tpDphHashNode pSta,tpPESession);
+void limSendAssocRspMgmtFrame(tpAniSirGlobal, tANI_U16, tANI_U16, tSirMacAddr,
+                              tANI_U8, tpDphHashNode pSta,tpPESession,
+                              assoc_rsp_tx_context *tx_complete_context);
 
 void limSendNullDataFrame(tpAniSirGlobal, tpDphHashNode);
 void limSendDisassocMgmtFrame(tpAniSirGlobal, tANI_U16, tSirMacAddr, tpPESession, tANI_BOOLEAN waitForAck);
diff --git a/CORE/MAC/src/pe/lim/limUtils.c b/CORE/MAC/src/pe/lim/limUtils.c
index abcd9b7..661b588 100644
--- a/CORE/MAC/src/pe/lim/limUtils.c
+++ b/CORE/MAC/src/pe/lim/limUtils.c
@@ -8534,6 +8534,84 @@
     return eHAL_STATUS_SUCCESS;
 }
 
+eHalStatus limAssocRspTxCompleteCnf(tpAniSirGlobal pMac, void *pData)
+{
+    tpSirTxBdStatus pTxBdStatus;
+    tpDphHashNode pStaDs;
+    tpPESession psessionEntry;
+    VOS_STATUS vosStatus;
+    vos_list_node_t *pNode= NULL, *pNext = NULL;
+    assoc_rsp_tx_context *tmp_tx_context = NULL;
+
+    if (!pData)
+    {
+       limLog(pMac, LOGE, FL("pData is NULL"));
+       return eHAL_STATUS_FAILURE;
+    }
+
+    pTxBdStatus = (tpSirTxBdStatus) pData;
+
+    limLog(pMac, LOG1, FL("txBdToken %u, txBdStatus %u"),
+            pTxBdStatus->txBdToken, pTxBdStatus->txCompleteStatus);
+
+    vos_list_peek_front(&pMac->assoc_rsp_completion_list,
+             &pNode);
+
+    while(pNode)
+    {
+       tmp_tx_context = container_of(pNode, assoc_rsp_tx_context, node);
+       if (tmp_tx_context->txBdToken != pTxBdStatus->txBdToken)
+       {
+        limLog(pMac, LOG1, FL("expecting txBdToken %u, got txBdToken %u"),
+            tmp_tx_context->txBdToken, pTxBdStatus->txBdToken);
+
+        vosStatus = vos_list_peek_next (
+                &pMac->assoc_rsp_completion_list,
+                pNode, &pNext );
+        pNode = pNext;
+        pNext = NULL;
+      }
+      else
+      {
+        limLog(pMac, LOG1, FL("expecting txBdToken %u, got txBdToken %u"),
+            tmp_tx_context->txBdToken, pTxBdStatus->txBdToken);
+        break;
+      }
+    }
+
+    if (!tmp_tx_context) {
+        limLog(pMac, LOGE, FL("context is NULL"));
+        return eHAL_STATUS_SUCCESS;
+    }
+    psessionEntry = peFindSessionBySessionId(pMac, tmp_tx_context->psessionID);
+    if (!psessionEntry) {
+        limLog(pMac, LOGE, FL("failed to get psession pointer"));
+        vos_list_remove_node(&pMac->assoc_rsp_completion_list,
+                pNode);
+        vos_mem_free(tmp_tx_context);
+        return eHAL_STATUS_SUCCESS;
+    }
+    pStaDs = dphGetHashEntry(pMac, tmp_tx_context->staId,
+                             &psessionEntry->dph.dphHashTable);
+    if (pStaDs == NULL)
+    {
+        limLog(pMac, LOGW,
+               FL("STA context not found"));
+        vos_list_remove_node(&pMac->assoc_rsp_completion_list,
+                pNode);
+        vos_mem_free(tmp_tx_context);
+
+        return eHAL_STATUS_SUCCESS;
+    }
+
+    /* Receive path cleanup */
+    limCleanupRxPath(pMac, pStaDs, psessionEntry);
+    vos_list_remove_node(&pMac->assoc_rsp_completion_list,
+                pNode);
+    vos_mem_free(tmp_tx_context);
+
+    return eHAL_STATUS_SUCCESS;
+}
 /**
  * lim_is_robust_mgmt_action_frame() - Check if action catagory is
  * robust action frame
diff --git a/CORE/MAC/src/pe/lim/limUtils.h b/CORE/MAC/src/pe/lim/limUtils.h
index af21b05..8083629 100644
--- a/CORE/MAC/src/pe/lim/limUtils.h
+++ b/CORE/MAC/src/pe/lim/limUtils.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -573,6 +573,7 @@
 void limDecrementPendingMgmtCount (tpAniSirGlobal pMac);
 
 eHalStatus limTxBdComplete(tpAniSirGlobal pMac, void *pData);
+eHalStatus limAssocRspTxCompleteCnf(tpAniSirGlobal pMac, void *pData);
 bool lim_is_robust_mgmt_action_frame(uint8 action_catagory);
 tANI_U8 lim_compute_ext_cap_ie_length (tDot11fIEExtCap *ext_cap);
 void lim_update_caps_info_for_bss(tpAniSirGlobal mac_ctx,