wlan: Split processing of assoc request frame

Split processing of assoc request frame and initialization of
PE/SME data structrures. This is needed to defer the initialization
of PE/SME entries on any external status. SAE authentication status
from hostapd is one such external status.

Change-Id: I9d7ced050441920505f0e12ab6b3ea9c672fe822
CRs-Fixed: 2734533
diff --git a/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c b/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c
index 3cbb408..b16bcdd 100644
--- a/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c
+++ b/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c
@@ -265,6 +265,671 @@
 }
 #endif
 
+bool lim_send_assoc_ind_to_sme(tpAniSirGlobal pMac,
+                            tpPESession psessionEntry,
+                            uint8_t subType,
+                            tpSirMacMgmtHdr pHdr,
+                            tpSirAssocReq pAssocReq,
+                            enum ani_akm_type akm_type,
+                            bool pmfConnection,
+                            bool *assoc_req_copied)
+{
+    uint16_t                    peerIdx;
+    tANI_U8                     updateContext = false;
+    tpDphHashNode               pStaDs;
+    tHalBitVal                  qosMode;
+    struct tLimPreAuthNode      *pStaPreAuthContext;
+    tAniAuthType                authType;
+    tANI_U16                    prevAuthSeqno = 0xFFFF;
+    tHalBitVal                  wsmMode, wmeMode;
+    tANI_U32                    val;
+#ifdef WLAN_FEATURE_11W
+    tPmfSaQueryTimerId          timerId;
+    tANI_U32                    retryInterval;
+#endif
+    tLimMlmStates               mlmPrevState;
+
+    limGetQosMode(psessionEntry, &qosMode);
+
+    /**
+     * Extract 'associated' context for STA, if any.
+     * This is maintained by DPH and created by LIM.
+     */
+    pStaDs = dphLookupHashEntry(pMac, pHdr->sa, &peerIdx, &psessionEntry->dph.dphHashTable);
+
+    /// Extract pre-auth context for the STA, if any.
+    pStaPreAuthContext = limSearchPreAuthList(pMac, pHdr->sa);
+
+    if (pStaDs == NULL)
+    {
+        /// Requesting STA is not currently associated
+        if (peGetCurrentSTAsCount(pMac) == pMac->lim.maxStation)
+        {
+               /**
+                * Maximum number of STAs that AP can handle reached.
+                * Send Association response to peer MAC entity
+                */
+                limLog(pMac, LOGE, FL("Max Sta count reached : %d"),
+                        pMac->lim.maxStation);
+                limRejectAssociation(pMac, pHdr->sa,
+                                    subType, false,
+                                    (tAniAuthType) 0, 0,
+                                    false,
+                                    (tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS,
+                                    psessionEntry);
+
+                return false;
+        }
+
+        /// Check if STA is pre-authenticated.
+        if ((pStaPreAuthContext == NULL) ||
+            (pStaPreAuthContext &&
+            (pStaPreAuthContext->mlmState !=
+                                eLIM_MLM_AUTHENTICATED_STATE)))
+        {
+             /**
+              * STA is not pre-authenticated yet requesting
+              * Re/Association before Authentication.
+              * OR STA is in the process of getting authenticated
+              * and sent Re/Association request.
+              * Send Deauthentication frame with 'prior
+              * authentication required' reason code.
+              */
+              limSendDeauthMgmtFrame(pMac,
+                            eSIR_MAC_STA_NOT_PRE_AUTHENTICATED_REASON, //=9
+                            pHdr->sa, psessionEntry, FALSE);
+
+              limLog(pMac, LOGE, FL("received %s req on sessionid: %d from STA "
+                    "that does not have pre-auth context"MAC_ADDRESS_STR),
+                    (LIM_ASSOC == subType) ? "Assoc" : "ReAssoc",
+                    psessionEntry->peSessionId,
+                    MAC_ADDR_ARRAY(pHdr->sa));
+                    return false;
+        }
+
+        /// Delete 'pre-auth' context of STA
+        authType = pStaPreAuthContext->authType;
+        if (pStaPreAuthContext->authType == eSIR_AUTH_TYPE_SAE)
+            pAssocReq->is_sae_authenticated = true;
+
+        /// Store the previous auth frame's seq no
+        prevAuthSeqno = pStaPreAuthContext->seqNo;
+
+        limDeletePreAuthNode(pMac, pHdr->sa);
+
+        // All is well. Assign AID (after else part)
+
+    } // if (pStaDs == NULL)
+    else
+    {
+        // STA context does exist for this STA
+        if (pStaDs->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE)
+        {
+            /**
+             * Requesting STA is in some 'transient' state?
+             * Ignore the Re/Assoc Req frame by incrementing
+             * debug counter & logging error.
+             */
+            if (subType == LIM_ASSOC)
+            {
+#ifdef WLAN_DEBUG
+                pMac->lim.gLimNumAssocReqDropInvldState++;
+#endif
+                limLog(pMac, LOGE, FL("received Assoc req in state "
+                        "%d from "), pStaDs->mlmStaContext.mlmState);
+            }
+            else
+            {
+#ifdef WLAN_DEBUG
+                pMac->lim.gLimNumReassocReqDropInvldState++;
+#endif
+                limLog(pMac, LOGE, FL("received ReAssoc req in state %d"
+                        " from "), pStaDs->mlmStaContext.mlmState);
+            }
+            limPrintMacAddr(pMac, pHdr->sa, LOG1);
+            limPrintMlmState(pMac, LOG1,
+                            (tLimMlmStates) pStaDs->mlmStaContext.mlmState);
+
+            return false;
+        } // if (pStaDs->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE)
+
+        /* STA sent association Request frame while already in
+         * 'associated' state */
+
+#ifdef WLAN_FEATURE_11W
+        limLog(pMac, LOG1, FL("Re/Assoc request from station that is already associated"));
+        limLog(pMac, LOG1, FL("PMF enabled %d, SA Query state %d"), pStaDs->rmfEnabled,
+                pStaDs->pmfSaQueryState);
+        if (pStaDs->rmfEnabled)
+        {
+            switch (pStaDs->pmfSaQueryState)
+            {
+                // start SA Query procedure, respond to Association Request
+                // with try again later
+                case DPH_SA_QUERY_NOT_IN_PROGRESS:
+                       /*
+                        * We should reset the retry counter before we start
+                        * the SA query procedure, otherwise in next set of SA query
+                        * procedure we will end up using the stale value.
+                        */
+                        pStaDs->pmfSaQueryRetryCount = 0;
+                        limSendAssocRspMgmtFrame(pMac, eSIR_MAC_TRY_AGAIN_LATER, 1,
+                                                pHdr->sa, subType, pStaDs,
+                                                psessionEntry, NULL);
+                        limSendSaQueryRequestFrame(pMac,
+                                (tANI_U8 *)&(pStaDs->pmfSaQueryCurrentTransId),
+                                pHdr->sa, psessionEntry);
+                        pStaDs->pmfSaQueryStartTransId = pStaDs->pmfSaQueryCurrentTransId;
+                        pStaDs->pmfSaQueryCurrentTransId++;
+
+                        // start timer for SA Query retry
+                        if (tx_timer_activate(&pStaDs->pmfSaQueryTimer) != TX_SUCCESS)
+                        {
+                            limLog(pMac, LOGE, FL("PMF SA Query timer activation failed!"));
+                            return false;
+                        }
+
+                        pStaDs->pmfSaQueryState = DPH_SA_QUERY_IN_PROGRESS;
+                        return false;
+
+                // SA Query procedure still going, respond to Association
+                // Request with try again later
+                case DPH_SA_QUERY_IN_PROGRESS:
+                        limSendAssocRspMgmtFrame(pMac, eSIR_MAC_TRY_AGAIN_LATER, 1,
+                                                pHdr->sa, subType, 0, psessionEntry,
+                                                NULL);
+                        return false;
+
+                // SA Query procedure timed out, accept Association Request
+                // normally
+                case DPH_SA_QUERY_TIMED_OUT:
+                        pStaDs->pmfSaQueryState = DPH_SA_QUERY_NOT_IN_PROGRESS;
+                        break;
+            }
+        }
+#endif
+                /* no change in the capability so drop the frame */
+                if ((VOS_TRUE == vos_mem_compare(&pStaDs->mlmStaContext.capabilityInfo,
+                                                &pAssocReq->capabilityInfo,
+                                                sizeof(tSirMacCapabilityInfo)))&&
+                                                (subType == LIM_ASSOC))
+                {
+                    limLog(pMac, LOGE, FL(" Received Assoc req in state %d STAid=%d"),
+                                            pStaDs->mlmStaContext.mlmState,peerIdx);
+                    return false;
+                }
+                else
+                {
+                  /*
+                   * STA sent Re/association Request frame while already in
+                   * 'associated' state. Update STA capabilities and
+                   * send Association response frame with same AID
+                   */
+                    limLog(pMac, LOG1, FL("Received Assoc req from STA already connected"
+                                        " UpdateConext"));
+                    pStaDs->mlmStaContext.capabilityInfo = pAssocReq->capabilityInfo;
+                    if (pStaPreAuthContext &&
+                        (pStaPreAuthContext->mlmState ==
+                                                eLIM_MLM_AUTHENTICATED_STATE))
+                    {
+                        /// STA has triggered pre-auth again
+                        authType = pStaPreAuthContext->authType;
+                        limDeletePreAuthNode(pMac, pHdr->sa);
+                    }
+                    else
+                        authType = pStaDs->mlmStaContext.authType;
+
+                    updateContext = true;
+                    if (dphInitStaState(pMac, pHdr->sa, peerIdx, true, &psessionEntry->dph.dphHashTable)
+                                            == NULL)
+                    {
+                        limLog(pMac, LOGE, FL("could not Init STAid=%d"), peerIdx);
+                        return false;
+                    }
+                }
+                goto sendIndToSme;
+            } // end if (lookup for STA in perStaDs fails)
+
+            // check if sta is allowed per QoS AC rules
+            //if (pMac->dph.gDphQosEnabled || pMac->dph.gDphWmeEnabled)
+            limGetWmeMode(psessionEntry, &wmeMode);
+            if ((qosMode == eHAL_SET) || (wmeMode == eHAL_SET))
+            {
+                // for a qsta, check if the requested Traffic spec
+                // is admissible
+                // for a non-qsta check if the sta can be admitted
+                if (pAssocReq->addtsPresent)
+                {
+                    tANI_U8 tspecIdx = 0; //index in the sch tspec table.
+                    if (limAdmitControlAddTS(pMac, pHdr->sa, &(pAssocReq->addtsReq),
+                                              &(pAssocReq->qosCapability), 0,
+                                              false, NULL, &tspecIdx, psessionEntry) != eSIR_SUCCESS)
+                    {
+                        limLog(pMac, LOGE, FL("AdmitControl: TSPEC rejected"));
+                        limSendAssocRspMgmtFrame(
+                                        pMac,
+                                        eSIR_MAC_QAP_NO_BANDWIDTH_REASON,
+                                        1,
+                                        pHdr->sa,
+                                        subType, 0,psessionEntry, NULL);
+#ifdef WLAN_DEBUG
+                        pMac->lim.gLimNumAssocReqDropACRejectTS++;
+#endif
+                        return false;
+                    }
+                }
+                else if (limAdmitControlAddSta(pMac, pHdr->sa, false)
+                                                != eSIR_SUCCESS)
+                {
+                    limLog(pMac, LOGE, FL("AdmitControl: Sta rejected"));
+                    limSendAssocRspMgmtFrame(
+                            pMac,
+                            eSIR_MAC_QAP_NO_BANDWIDTH_REASON,
+                            1,
+                            pHdr->sa,
+                            subType, 0,psessionEntry, NULL);
+#ifdef WLAN_DEBUG
+                    pMac->lim.gLimNumAssocReqDropACRejectSta++;
+#endif
+                    return false;
+                }
+
+                // else all ok
+                limLog(pMac, LOG1, FL("AdmitControl: Sta OK!"));
+            }
+
+            /**
+             * STA is Associated !
+             */
+            limLog(pMac, LOGE, FL("Received %s Req  successful from "MAC_ADDRESS_STR),
+            (LIM_ASSOC == subType) ? "Assoc" : "ReAssoc", MAC_ADDR_ARRAY(pHdr->sa));
+
+            /**
+             * AID for this association will be same as the peer Index used in DPH table.
+             * Assign unused/least recently used peer Index from perStaDs.
+             * NOTE: limAssignPeerIdx() assigns AID values ranging
+             * between 1 - cfg_item(WNI_CFG_ASSOC_STA_LIMIT)
+             */
+
+            peerIdx = limAssignPeerIdx(pMac, psessionEntry);
+            if (!peerIdx)
+            {
+                // Could not assign AID
+                // Reject association
+                limLog(pMac, LOGE, FL("PeerIdx not avaialble. Reject associaton"));
+
+                limRejectAssociation(pMac, pHdr->sa,
+                                    subType, true, authType,
+                                    peerIdx, false,
+                                    (tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry);
+
+                return false;
+            }
+            /**
+             * Add an entry to hash table maintained by DPH module
+             */
+            pStaDs = dphAddHashEntry(pMac, pHdr->sa, peerIdx, &psessionEntry->dph.dphHashTable);
+
+            if (pStaDs == NULL)
+            {
+                // Could not add hash table entry at DPH
+                limLog(pMac, LOGE,
+                    FL("could not add hash entry at DPH for aid=%d, MacAddr:"
+                    MAC_ADDRESS_STR),
+                    peerIdx,MAC_ADDR_ARRAY(pHdr->sa));
+
+                // Release AID
+                limReleasePeerIdx(pMac, peerIdx, psessionEntry);
+
+                limRejectAssociation(pMac, pHdr->sa,
+                                    subType, true, authType, peerIdx, false,
+                                    (tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry);
+                return false;
+            }
+
+            /// Store the previous auth frame's seq no
+            if (prevAuthSeqno != 0xFFFF)
+            {
+                pStaDs->PrevAuthSeqno = prevAuthSeqno;
+            }
+            /// Store the current assoc seq no
+            pStaDs->PrevAssocSeqno = ((pHdr->seqControl.seqNumHi << 4) |
+                                    (pHdr->seqControl.seqNumLo));
+            limLog(pMac, LOG1, FL("Prev auth seq no %d Prev Assoc seq no. %d"),
+                    pStaDs->PrevAuthSeqno, pStaDs->PrevAssocSeqno);
+
+        sendIndToSme:
+
+            psessionEntry->parsedAssocReq[pStaDs->assocId] = pAssocReq;
+            pStaDs->mlmStaContext.htCapability = pAssocReq->HTCaps.present;
+#ifdef WLAN_FEATURE_11AC
+            pStaDs->mlmStaContext.vhtCapability = pAssocReq->VHTCaps.present;
+#endif
+            pStaDs->qos.addtsPresent = (pAssocReq->addtsPresent==0) ? false : true;
+            pStaDs->qos.addts	     = pAssocReq->addtsReq;
+            pStaDs->qos.capability   = pAssocReq->qosCapability;
+            pStaDs->versionPresent   = 0;
+            /* short slot and short preamble should be updated before doing limaddsta */
+            pStaDs->shortPreambleEnabled = (tANI_U8)pAssocReq->capabilityInfo.shortPreamble;
+            pStaDs->shortSlotTimeEnabled = (tANI_U8)pAssocReq->capabilityInfo.shortSlotTime;
+
+            if (pAssocReq->propIEinfo.versionPresent) //update STA version info
+            {
+                pStaDs->versionPresent = 1;
+                pStaDs->version = pAssocReq->propIEinfo.version;
+            }
+            pStaDs->propCapability = 0;
+            if (pAssocReq->propIEinfo.capabilityPresent)
+            {
+                if (sirGetCfgPropCaps(pMac, &pStaDs->propCapability))
+                    pStaDs->propCapability &= pAssocReq->propIEinfo.capability;
+            }
+
+            pStaDs->valid = 0;
+            pStaDs->mlmStaContext.authType = authType;
+            pStaDs->mlmStaContext.akm_type = akm_type;
+            pStaDs->staType = STA_ENTRY_PEER;
+
+            limLog(pMac, LOGE, FL("auth_type = %d, akm_type = %d"),
+                    authType, akm_type);
+
+            //TODO: If listen interval is more than certain limit, reject the association.
+            //Need to check customer requirements and then implement.
+            pStaDs->mlmStaContext.listenInterval = pAssocReq->listenInterval;
+            pStaDs->mlmStaContext.capabilityInfo = pAssocReq->capabilityInfo;
+
+            /* The following count will be used to knock-off the station if it doesn't
+             * come back to receive the buffered data. The AP will wait for numTimSent number
+             * of beacons after sending TIM information for the station, before assuming that
+             * the station is no more associated and disassociates it
+             */
+
+            /** timWaitCount is used by PMM for monitoring the STA's in PS for LINK*/
+            pStaDs->timWaitCount = (tANI_U8)GET_TIM_WAIT_COUNT(pAssocReq->listenInterval);
+
+            /** Initialise the Current successful MPDU's tranfered to this STA count as 0 */
+            pStaDs->curTxMpduCnt = 0;
+
+            if(IS_DOT11_MODE_HT(psessionEntry->dot11mode) &&
+                (pAssocReq->HTCaps.present))
+            {
+                pStaDs->htGreenfield = (tANI_U8)pAssocReq->HTCaps.greenField;
+                pStaDs->htAMpduDensity = pAssocReq->HTCaps.mpduDensity;
+                pStaDs->htDsssCckRate40MHzSupport = (tANI_U8)pAssocReq->HTCaps.dsssCckMode40MHz;
+                pStaDs->htLsigTXOPProtection = (tANI_U8)pAssocReq->HTCaps.lsigTXOPProtection;
+                pStaDs->htMaxAmsduLength = (tANI_U8)pAssocReq->HTCaps.maximalAMSDUsize;
+                pStaDs->htMaxRxAMpduFactor = pAssocReq->HTCaps.maxRxAMPDUFactor;
+                pStaDs->htMIMOPSState = pAssocReq->HTCaps.mimoPowerSave;
+
+                /* pAssocReq will be copied to psessionEntry->parsedAssocReq later */
+                /* check whether AP is enabled with shortGI */
+                if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_GI_20MHZ, &val) !=
+                                    eSIR_SUCCESS) {
+                    limLog(pMac, LOGE,
+                            FL("could not retrieve shortGI 20Mhz CFG"));
+                    return false;
+                }
+                if (val) {
+                    pStaDs->htShortGI20Mhz = (tANI_U8)pAssocReq->HTCaps.shortGI20MHz;
+                } else {
+                    /* Unset htShortGI20Mhz in ht_caps*/
+                    pAssocReq->HTCaps.shortGI20MHz = 0;
+                    pStaDs->htShortGI20Mhz = 0;
+                }
+
+                if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_GI_40MHZ, &val) !=
+                                    eSIR_SUCCESS) {
+                    limLog(pMac, LOGE,
+                                FL("could not retrieve shortGI 40Mhz CFG"));
+                    return false;
+                }
+                if (val) {
+                    pStaDs->htShortGI40Mhz = (tANI_U8)pAssocReq->HTCaps.shortGI40MHz;
+                } else {
+                    /* Unset htShortGI40Mhz in ht_caps */
+                    pAssocReq->HTCaps.shortGI40MHz = 0;
+                    pStaDs->htShortGI40Mhz = 0;
+                }
+                pStaDs->htSupportedChannelWidthSet = (tANI_U8)pAssocReq->HTCaps.supportedChannelWidthSet;
+                /* peer just follows AP; so when we are softAP/GO, we just store our session entry's secondary channel offset here in peer INFRA STA
+                 * However, if peer's 40MHz channel width support is disabled then secondary channel will be zero
+                 */
+                pStaDs->htSecondaryChannelOffset = (pStaDs->htSupportedChannelWidthSet)?psessionEntry->htSecondaryChannelOffset:0;
+#ifdef WLAN_FEATURE_11AC
+                if(pAssocReq->operMode.present)
+                {
+                    pStaDs->vhtSupportedChannelWidthSet = (tANI_U8)((pAssocReq->operMode.chanWidth == eHT_CHANNEL_WIDTH_80MHZ) ? WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ : WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ);
+                    pStaDs->htSupportedChannelWidthSet	= (tANI_U8)(pAssocReq->operMode.chanWidth ? eHT_CHANNEL_WIDTH_40MHZ : eHT_CHANNEL_WIDTH_20MHZ);
+                }
+                else if (pAssocReq->VHTCaps.present)
+                {
+                    // Check if STA has enabled it's channel bonding mode.
+                    // If channel bonding mode is enabled, we decide based on SAP's current configuration.
+                    // else, we set it to VHT20.
+                    pStaDs->vhtSupportedChannelWidthSet = (tANI_U8)((pStaDs->htSupportedChannelWidthSet == eHT_CHANNEL_WIDTH_20MHZ) ?
+                                                            WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ :
+                                                            psessionEntry->vhtTxChannelWidthSet );
+                }
+
+                // Lesser among the AP and STA bandwidth of operation.
+                pStaDs->htSupportedChannelWidthSet =
+                        (pStaDs->htSupportedChannelWidthSet < psessionEntry->htSupportedChannelWidthSet) ?
+                        pStaDs->htSupportedChannelWidthSet : psessionEntry->htSupportedChannelWidthSet ;
+
+#endif
+                pStaDs->baPolicyFlag = 0xFF;
+                pStaDs->htLdpcCapable = (tANI_U8)pAssocReq->HTCaps.advCodingCap;
+            }
+
+            if(pAssocReq->VHTCaps.present)
+            {
+                pStaDs->vhtLdpcCapable = (tANI_U8)pAssocReq->VHTCaps.ldpcCodingCap;
+            }
+
+#ifdef WLAN_FEATURE_11AC
+            if (limPopulateMatchingRateSet(pMac,
+                                        pStaDs,
+                                        &(pAssocReq->supportedRates),
+                                        &(pAssocReq->extendedRates),
+                                        pAssocReq->HTCaps.supportedMCSSet,
+                                        &(pAssocReq->propIEinfo.propRates),
+                                        psessionEntry , &pAssocReq->VHTCaps)
+                                        != eSIR_SUCCESS)
+#else
+            if (limPopulateMatchingRateSet(pMac,
+                                        pStaDs,
+                                        &(pAssocReq->supportedRates),
+                                        &(pAssocReq->extendedRates),
+                                        pAssocReq->HTCaps.supportedMCSSet,
+                                        &(pAssocReq->propIEinfo.propRates), psessionEntry) != eSIR_SUCCESS)
+#endif
+            {
+                // Could not update hash table entry at DPH with rateset
+                limLog(pMac, LOGE,
+                    FL("could not update hash entry at DPH for aid=%d, MacAddr: "
+                    MAC_ADDRESS_STR),
+                    peerIdx, MAC_ADDR_ARRAY(pHdr->sa));
+
+                // Release AID
+                limReleasePeerIdx(pMac, peerIdx, psessionEntry);
+                limRejectAssociation(pMac, pHdr->sa,
+                                    subType, true, authType, peerIdx, true,
+                                    (tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry);
+
+                pAssocReq = psessionEntry->parsedAssocReq[pStaDs->assocId];
+                return false;
+            }
+
+            vos_mem_copy((tANI_U8 *) &pStaDs->mlmStaContext.propRateSet,
+                        (tANI_U8 *) &(pAssocReq->propIEinfo.propRates),
+                        pAssocReq->propIEinfo.propRates.numPropRates + 1);
+
+            /// Add STA context at MAC HW (BMU, RHP & TFP)
+
+            pStaDs->qosMode    = eANI_BOOLEAN_FALSE;
+            pStaDs->lleEnabled = eANI_BOOLEAN_FALSE;
+            if (pAssocReq->capabilityInfo.qos && (qosMode == eHAL_SET))
+            {
+                pStaDs->lleEnabled = eANI_BOOLEAN_TRUE;
+                pStaDs->qosMode    = eANI_BOOLEAN_TRUE;
+            }
+
+            pStaDs->wmeEnabled = eANI_BOOLEAN_FALSE;
+            pStaDs->wsmEnabled = eANI_BOOLEAN_FALSE;
+            limGetWmeMode(psessionEntry, &wmeMode);
+            //if ((! pStaDs->lleEnabled) && assoc.wmeInfoPresent && pMac->dph.gDphWmeEnabled)
+            if ((! pStaDs->lleEnabled) && pAssocReq->wmeInfoPresent && (wmeMode == eHAL_SET))
+            {
+                pStaDs->wmeEnabled = eANI_BOOLEAN_TRUE;
+                pStaDs->qosMode = eANI_BOOLEAN_TRUE;
+                limGetWsmMode(psessionEntry, &wsmMode);
+                /* WMM_APSD - WMM_SA related processing should be separate; WMM_SA and WMM_APSD
+                can coexist */
+                if( pAssocReq->WMMInfoStation.present)
+                {
+                    /* check whether AP supports or not */
+                    if ((psessionEntry->limSystemRole == eLIM_AP_ROLE)
+                        && (psessionEntry->apUapsdEnable == 0) && (pAssocReq->WMMInfoStation.acbe_uapsd
+                            || pAssocReq->WMMInfoStation.acbk_uapsd
+                            || pAssocReq->WMMInfoStation.acvo_uapsd
+                            || pAssocReq->WMMInfoStation.acvi_uapsd))
+                    {
+                        /**
+                         * Received Re/Association Request from
+                         * STA when UPASD is not supported.
+                         */
+                        limLog( pMac, LOGE, FL( "AP do not support UAPSD so reply "
+                                "to STA accordingly" ));
+                        /* update UAPSD and send it to LIM to add STA */
+                        pStaDs->qos.capability.qosInfo.acbe_uapsd = 0;
+                        pStaDs->qos.capability.qosInfo.acbk_uapsd = 0;
+                        pStaDs->qos.capability.qosInfo.acvo_uapsd = 0;
+                        pStaDs->qos.capability.qosInfo.acvi_uapsd = 0;
+                        pStaDs->qos.capability.qosInfo.maxSpLen =   0;
+                    }
+                    else
+                    {
+                        /* update UAPSD and send it to LIM to add STA */
+                        pStaDs->qos.capability.qosInfo.acbe_uapsd = pAssocReq->WMMInfoStation.acbe_uapsd;
+                        pStaDs->qos.capability.qosInfo.acbk_uapsd = pAssocReq->WMMInfoStation.acbk_uapsd;
+                        pStaDs->qos.capability.qosInfo.acvo_uapsd = pAssocReq->WMMInfoStation.acvo_uapsd;
+                        pStaDs->qos.capability.qosInfo.acvi_uapsd = pAssocReq->WMMInfoStation.acvi_uapsd;
+                        pStaDs->qos.capability.qosInfo.maxSpLen = pAssocReq->WMMInfoStation.max_sp_length;
+                    }
+                }
+                //if (assoc.wsmCapablePresent && pMac->dph.gDphWsmEnabled)
+                if (pAssocReq->wsmCapablePresent && (wsmMode == eHAL_SET))
+                    pStaDs->wsmEnabled = eANI_BOOLEAN_TRUE;
+            }
+
+            // Re/Assoc Response frame to requesting STA
+            pStaDs->mlmStaContext.subType = subType;
+
+            if (pAssocReq->propIEinfo.aniIndicator)
+                pStaDs->aniPeer = 1;
+
+#ifdef WLAN_FEATURE_11W
+            pStaDs->rmfEnabled = (pmfConnection) ? 1 : 0;
+            pStaDs->pmfSaQueryState = DPH_SA_QUERY_NOT_IN_PROGRESS;
+            timerId.fields.sessionId = psessionEntry->peSessionId;
+            timerId.fields.peerIdx = peerIdx;
+            if (wlan_cfgGetInt(pMac, WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL,
+                    &retryInterval) != eSIR_SUCCESS)
+            {
+                limLog(pMac, LOGE, FL("Could not retrieve PMF SA Query retry interval value"));
+                limRejectAssociation(pMac, pHdr->sa,
+                                    subType, true, authType,
+                                    peerIdx, false,
+                                    (tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry);
+                return false;
+            }
+            if (WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_STAMIN > retryInterval)
+            {
+                retryInterval = WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_STADEF;
+            }
+            if (tx_timer_create(&pStaDs->pmfSaQueryTimer, "PMF SA Query timer",
+                                limPmfSaQueryTimerHandler, timerId.value,
+                                SYS_MS_TO_TICKS((retryInterval * 1024) / 1000),
+                                0, TX_NO_ACTIVATE) != TX_SUCCESS)
+            {
+                limLog(pMac, LOGE, FL("could not create PMF SA Query timer"));
+                limRejectAssociation(pMac, pHdr->sa,
+                                    subType, true, authType,
+                                    peerIdx, false,
+                                    (tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry);
+                return false;
+            }
+#endif
+            // BTAMP: Storing the parsed assoc request in the psessionEntry array
+            psessionEntry->parsedAssocReq[pStaDs->assocId] = pAssocReq;
+
+            /* BTAMP: If STA context already exist (ie. updateContext = 1)
+             * for this STA, then we should delete the old one, and add
+             * the new STA. This is taken care of in the limDelSta() routine.
+             *
+             * Prior to BTAMP, we were setting this flag so that when
+             * PE receives SME_ASSOC_CNF, and if this flag is set, then
+             * PE shall delete the old station and then add. But now in
+             * BTAMP, we're directly adding station before waiting for
+             * SME_ASSOC_CNF, so we can do this now.
+             */
+            if (!updateContext)
+            {
+                pStaDs->mlmStaContext.updateContext = 0;
+                // BTAMP: Add STA context at HW - issue WDA_ADD_STA_REQ to HAL
+                if (limAddSta(pMac, pStaDs, false, psessionEntry) != eSIR_SUCCESS)
+                {
+                    limLog(pMac, LOGE, FL("could not Add STA with assocId=%d"),
+                            pStaDs->assocId);
+                    limRejectAssociation( pMac, pStaDs->staAddr, pStaDs->mlmStaContext.subType,
+                            true, pStaDs->mlmStaContext.authType, pStaDs->assocId, true,
+                            (tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry);
+                    pAssocReq = psessionEntry->parsedAssocReq[pStaDs->assocId];
+                    return false;
+                }
+            }
+            else
+            {
+                pStaDs->mlmStaContext.updateContext = 1;
+                mlmPrevState = pStaDs->mlmStaContext.mlmState;
+
+                /* As per the HAL/FW needs the reassoc req need not be calling limDelSta */
+                if(subType != LIM_REASSOC)
+                {
+                    //we need to set the mlmState here in order differentiate in limDelSta.
+                    pStaDs->mlmStaContext.mlmState = eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE;
+                    if(limDelSta(pMac, pStaDs, true, psessionEntry) != eSIR_SUCCESS)
+                    {
+                        limLog(pMac, LOGE, FL("could not DEL STA with assocId=%d staId %d"),
+                                pStaDs->assocId, pStaDs->staIndex);
+                        limRejectAssociation( pMac, pStaDs->staAddr, pStaDs->mlmStaContext.subType, true, pStaDs->mlmStaContext.authType,
+                                pStaDs->assocId, true,(tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry);
+                        //Restoring the state back.
+                        pStaDs->mlmStaContext.mlmState = mlmPrevState;
+                        pAssocReq = psessionEntry->parsedAssocReq[pStaDs->assocId];
+                        return false;
+                    }
+                }
+                else
+                {
+                    /* mlmState is changed in limAddSta context */
+                    /* use the same AID, already allocated */
+                    if (limAddSta(pMac, pStaDs, false, psessionEntry) != eSIR_SUCCESS)
+                    {
+                            limLog(pMac, LOGE, FL( "Could not AddSta with assocId= %d staId %d"),
+                                    pStaDs->assocId, pStaDs->staIndex);
+                            limRejectAssociation( pMac, pStaDs->staAddr, pStaDs->mlmStaContext.subType, true, pStaDs->mlmStaContext.authType,
+                                    pStaDs->assocId, true,(tSirResultCodes) eSIR_MAC_WME_REFUSED_STATUS, psessionEntry);
+                            //Restoring the state back.
+                            pStaDs->mlmStaContext.mlmState = mlmPrevState;
+                            pAssocReq = psessionEntry->parsedAssocReq[pStaDs->assocId];
+                            return false;
+                    }
+                }
+            }
+    return true;
+}
+
 /**---------------------------------------------------------------
 \fn     limProcessAssocReqFrame
 \brief  This function is called by limProcessMessageQueue()
@@ -281,33 +946,28 @@
 limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,
                         tANI_U8 subType, tpPESession psessionEntry)
 {
-    tANI_U8                 updateContext;
     tANI_U8                 *pBody;
     tANI_U16                peerIdx, temp;
     tANI_U32                val;
-    tANI_U16                prevAuthSeqno = 0xFFFF;
     tANI_S32                framelen;
     tSirRetStatus           status;
     tpSirMacMgmtHdr         pHdr;
     struct tLimPreAuthNode  *pStaPreAuthContext;
-    tAniAuthType            authType;
     tSirMacCapabilityInfo   localCapabilities;
     tpDphHashNode           pStaDs = NULL;
     tpSirAssocReq           pAssocReq;
-    tLimMlmStates           mlmPrevState;
     tDot11fIERSN            Dot11fIERSN;
     tDot11fIEWPA            Dot11fIEWPA;
     tANI_U32 phyMode;
     tHalBitVal qosMode;
-    tHalBitVal wsmMode, wmeMode;
+#ifdef WMM_APSD
+    tHalBitVal              wmeMode;
+#endif
     tANI_U8    *wpsIe = NULL;
     tSirMacRateSet  basicRates;
     tANI_U8 i = 0, j = 0;
     tANI_BOOLEAN pmfConnection = eANI_BOOLEAN_FALSE;
-#ifdef WLAN_FEATURE_11W
-    tPmfSaQueryTimerId timerId;
-    tANI_U32 retryInterval;
-#endif
+    bool assoc_req_copied = false;
     enum ani_akm_type akm_type = ANI_AKM_TYPE_NONE;
 
     limGetPhyMode(pMac, &phyMode, psessionEntry);
@@ -498,8 +1158,6 @@
         goto error;
     }
 
-    updateContext = false;
-
     if (limCmpSSid(pMac, &pAssocReq->ssId, psessionEntry) == false)
     {
         limLog(pMac, LOGE, FL("Received %s Req with unmatched ssid ( Received"
@@ -888,9 +1546,26 @@
                     goto error;
                     
                 }
+
                 akm_type = lim_translate_rsn_oui_to_akm_type(
                                     Dot11fIERSN.akm_suite[0]);
 
+                if (akm_type == ANI_AKM_TYPE_SAE) {
+                    if (eSIR_SUCCESS != (status =
+                        lim_check_sae_pmf_cap(psessionEntry, &Dot11fIERSN))) {
+                        /* Reject pmf disable SAE STA */
+                        limLog(pMac, LOGW, FL("Rejecting Re/Assoc req from STA:"
+                                MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->sa));
+                        limSendAssocRspMgmtFrame(
+                                    pMac,
+                                    status,
+                                    1,
+                                    pHdr->sa,
+                                    subType, 0,psessionEntry, NULL);
+                        goto error;
+                    }
+                }
+
             } /* end - if(pAssocReq->rsnPresent) */
             if((!pAssocReq->rsnPresent) && pAssocReq->wpaPresent)
             {
@@ -942,690 +1617,52 @@
 
                     goto error;
                 }/* end - if(pAssocReq->wpa.length) */
+
                 akm_type = lim_translate_rsn_oui_to_akm_type(
-                                        Dot11fIEWPA.auth_suites[0]);
+                                Dot11fIEWPA.auth_suites[0]);
 
             } /* end - if(pAssocReq->wpaPresent) */
         } /* end of if(psessionEntry->pLimStartBssReq->privacy 
             && psessionEntry->pLimStartBssReq->rsnIE->length) */
 
     } /* end of     if( ! pAssocReq->wscInfo.present ) */
+    else
+    {
+        limLog(pMac, LOG1, FL("Assoc req WSE IE is present"));
+    }
 
-    /**
-     * Extract 'associated' context for STA, if any.
-     * This is maintained by DPH and created by LIM.
-     */
-    pStaDs = dphLookupHashEntry(pMac, pHdr->sa, &peerIdx, &psessionEntry->dph.dphHashTable);
-
-    /// Extract pre-auth context for the STA, if any.
+    /* Extract pre-auth context for the STA, if any. */
     pStaPreAuthContext = limSearchPreAuthList(pMac, pHdr->sa);
-
-    if (pStaDs == NULL)
-    {
-        /// Requesting STA is not currently associated
-        if (peGetCurrentSTAsCount(pMac) == pMac->lim.maxStation)
-        {
-            /**
-             * Maximum number of STAs that AP can handle reached.
-             * Send Association response to peer MAC entity
-             */
-            limLog(pMac, LOGE, FL("Max Sta count reached : %d"),
-                                  pMac->lim.maxStation);
-            limRejectAssociation(pMac, pHdr->sa,
-                                 subType, false,
-                                 (tAniAuthType) 0, 0,
-                                 false,
-                                 (tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry);
-
-            goto error;
-        }
-
-        /// Check if STA is pre-authenticated.
-        if ((pStaPreAuthContext == NULL) ||
-            (pStaPreAuthContext &&
-             (pStaPreAuthContext->mlmState !=
-                              eLIM_MLM_AUTHENTICATED_STATE)))
-        {
-            /**
-             * STA is not pre-authenticated yet requesting
-             * Re/Association before Authentication.
-             * OR STA is in the process of getting authenticated
-             * and sent Re/Association request.
-             * Send Deauthentication frame with 'prior
-             * authentication required' reason code.
-             */
-            limSendDeauthMgmtFrame(
-                     pMac,
-                     eSIR_MAC_STA_NOT_PRE_AUTHENTICATED_REASON, //=9
-                     pHdr->sa, psessionEntry, FALSE);
-
-            limLog(pMac, LOGE, FL("received %s req on sessionid: %d from STA "
-            "that does not have pre-auth context"MAC_ADDRESS_STR),
-            (LIM_ASSOC == subType) ? "Assoc" : "ReAssoc",
-            psessionEntry->peSessionId,
-            MAC_ADDR_ARRAY(pHdr->sa));
-            goto error;
-        }
-
-        /// Delete 'pre-auth' context of STA
-        authType = pStaPreAuthContext->authType;
-        if (pStaPreAuthContext->authType == eSIR_AUTH_TYPE_SAE)
-                pAssocReq->is_sae_authenticated = true;
-        /// Store the previous auth frame's seq no
-        prevAuthSeqno = pStaPreAuthContext->seqNo;
-
-
-        limDeletePreAuthNode(pMac, pHdr->sa);
-
-        // All is well. Assign AID (after else part)
-
-    } // if (pStaDs == NULL)
-    else
-    {
-        // STA context does exist for this STA
-
-        if (pStaDs->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE)
-        {
-            /**
-             * Requesting STA is in some 'transient' state?
-             * Ignore the Re/Assoc Req frame by incrementing
-             * debug counter & logging error.
-             */
-            if (subType == LIM_ASSOC)
-            {
-            
-#ifdef WLAN_DEBUG    
-                pMac->lim.gLimNumAssocReqDropInvldState++;
-#endif
-                limLog(pMac, LOGE, FL("received Assoc req in state "
-                   "%d from "), pStaDs->mlmStaContext.mlmState);
-            }
-            else
-            {     
-#ifdef WLAN_DEBUG    
-                pMac->lim.gLimNumReassocReqDropInvldState++;
-#endif
-                limLog(pMac, LOGE, FL("received ReAssoc req in state %d"
-                            " from "), pStaDs->mlmStaContext.mlmState);
-            }
-            limPrintMacAddr(pMac, pHdr->sa, LOG1);
-            limPrintMlmState(pMac, LOG1, (tLimMlmStates) pStaDs->mlmStaContext.mlmState);
-
-            goto error;
-        } // if (pStaDs->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE)
-
-        /* STA sent association Request frame while already in
-         * 'associated' state */
-
-#ifdef WLAN_FEATURE_11W
-        limLog(pMac, LOG1, FL("Re/Assoc request from station that is already associated"));
-        limLog(pMac, LOG1, FL("PMF enabled %d, SA Query state %d"), pStaDs->rmfEnabled,
-               pStaDs->pmfSaQueryState);
-        if (pStaDs->rmfEnabled)
-        {
-            switch (pStaDs->pmfSaQueryState)
-            {
-
-            // start SA Query procedure, respond to Association Request
-            // with try again later
-            case DPH_SA_QUERY_NOT_IN_PROGRESS:
-                /*
-                 * We should reset the retry counter before we start
-                 * the SA query procedure, otherwise in next set of SA query
-                 * procedure we will end up using the stale value.
-                 */
-                pStaDs->pmfSaQueryRetryCount = 0;
-                limSendAssocRspMgmtFrame(pMac, eSIR_MAC_TRY_AGAIN_LATER, 1,
-                                         pHdr->sa, subType, pStaDs,
-                                         psessionEntry, NULL);
-                limSendSaQueryRequestFrame(
-                    pMac, (tANI_U8 *)&(pStaDs->pmfSaQueryCurrentTransId),
-                    pHdr->sa, psessionEntry);
-                pStaDs->pmfSaQueryStartTransId = pStaDs->pmfSaQueryCurrentTransId;
-                pStaDs->pmfSaQueryCurrentTransId++;
-
-                // start timer for SA Query retry
-                if (tx_timer_activate(&pStaDs->pmfSaQueryTimer) != TX_SUCCESS)
-                {
-                    limLog(pMac, LOGE, FL("PMF SA Query timer activation failed!"));
-                    goto error;
-                }
-
-                pStaDs->pmfSaQueryState = DPH_SA_QUERY_IN_PROGRESS;
-                goto error;
-
-            // SA Query procedure still going, respond to Association
-            // Request with try again later
-            case DPH_SA_QUERY_IN_PROGRESS:
-                limSendAssocRspMgmtFrame(pMac, eSIR_MAC_TRY_AGAIN_LATER, 1,
-                                         pHdr->sa, subType, 0, psessionEntry,
-                                         NULL);
-                goto error;
-
-            // SA Query procedure timed out, accept Association Request
-            // normally
-             case DPH_SA_QUERY_TIMED_OUT:
-                pStaDs->pmfSaQueryState = DPH_SA_QUERY_NOT_IN_PROGRESS;
-                break;
-            }
-        }
-#endif
-
-        /* no change in the capability so drop the frame */
-        if ((VOS_TRUE == vos_mem_compare(&pStaDs->mlmStaContext.capabilityInfo,
-                                          &pAssocReq->capabilityInfo,
-                                          sizeof(tSirMacCapabilityInfo)))&&
-                                         (subType == LIM_ASSOC))
-        {
-            limLog(pMac, LOGE, FL(" Received Assoc req in state %d STAid=%d"),
-                                       pStaDs->mlmStaContext.mlmState,peerIdx);
-            goto error;
-        }
-        else
-        {
-         /**
-         * STA sent Re/association Request frame while already in
-         * 'associated' state. Update STA capabilities and
-         * send Association response frame with same AID
-         */
-            limLog(pMac, LOG1, FL("Received Assoc req from STA already connected"
-                                  " UpdateConext"));
-            pStaDs->mlmStaContext.capabilityInfo = pAssocReq->capabilityInfo;
-            if (pStaPreAuthContext &&
-                (pStaPreAuthContext->mlmState ==
-                                           eLIM_MLM_AUTHENTICATED_STATE))
-            {
-                /// STA has triggered pre-auth again
-                authType = pStaPreAuthContext->authType;
-                limDeletePreAuthNode(pMac, pHdr->sa);
-            }
-            else
-                authType = pStaDs->mlmStaContext.authType;
-
-            updateContext = true;
-            if (dphInitStaState(pMac, pHdr->sa, peerIdx, true, &psessionEntry->dph.dphHashTable)
-                                      == NULL)
-            {
-                limLog(pMac, LOGE, FL("could not Init STAid=%d"), peerIdx);
-                goto  error;
-            }
-        }
-       goto sendIndToSme;
-    } // end if (lookup for STA in perStaDs fails)
-
-
-
-    // check if sta is allowed per QoS AC rules
-    //if (pMac->dph.gDphQosEnabled || pMac->dph.gDphWmeEnabled)
-    limGetWmeMode(psessionEntry, &wmeMode);
-    if ((qosMode == eHAL_SET) || (wmeMode == eHAL_SET))
-    {
-        // for a qsta, check if the requested Traffic spec
-        // is admissible
-        // for a non-qsta check if the sta can be admitted
-        if (pAssocReq->addtsPresent)
-        {
-            tANI_U8 tspecIdx = 0; //index in the sch tspec table.
-            if (limAdmitControlAddTS(pMac, pHdr->sa, &(pAssocReq->addtsReq),
-                                     &(pAssocReq->qosCapability), 0, false, NULL, &tspecIdx, psessionEntry) != eSIR_SUCCESS)
-            {
-                limLog(pMac, LOGE, FL("AdmitControl: TSPEC rejected"));
-                limSendAssocRspMgmtFrame(
-                               pMac,
-                               eSIR_MAC_QAP_NO_BANDWIDTH_REASON,
-                               1,
-                               pHdr->sa,
-                               subType, 0,psessionEntry, NULL);
-#ifdef WLAN_DEBUG    
-                pMac->lim.gLimNumAssocReqDropACRejectTS++;
-#endif
-                goto error;
-            }
-        }
-        else if (limAdmitControlAddSta(pMac, pHdr->sa, false)
-                                               != eSIR_SUCCESS)
-        {
-            limLog(pMac, LOGE, FL("AdmitControl: Sta rejected"));
-            limSendAssocRspMgmtFrame(
-                    pMac,
-                    eSIR_MAC_QAP_NO_BANDWIDTH_REASON,
-                    1,
-                    pHdr->sa,
-                    subType, 0,psessionEntry, NULL);
-#ifdef WLAN_DEBUG    
-            pMac->lim.gLimNumAssocReqDropACRejectSta++;
-#endif
-            goto error;
-        }
-
-        // else all ok
-        limLog(pMac, LOG1, FL("AdmitControl: Sta OK!"));
-    }
-
-    /**
-     * STA is Associated !
+    /* SAE authentication is offloaded to hostapd. Hostapd sends
+     * authentication status to driver after completing SAE
+     * authentication (after sending out 4/4 SAE auth frame).
+     * There is a possible race condition where driver gets
+     * assoc request from SAE station before getting authentication
+     * status from hostapd. Don't reject the association in such
+     * cases and defer the processing of assoc request frame by caching
+     * the frame and process it when the auth status is received.
      */
-    limLog(pMac, LOGE, FL("Received %s Req  successful from "MAC_ADDRESS_STR),
-    (LIM_ASSOC == subType) ? "Assoc" : "ReAssoc", MAC_ADDR_ARRAY(pHdr->sa));
+    if (pStaPreAuthContext &&
+        pStaPreAuthContext->authType == eSIR_AUTH_TYPE_SAE &&
+        pStaPreAuthContext->mlmState == eLIM_MLM_WT_SAE_AUTH_STATE) {
+        limLog(pMac, LOG1,
+                FL("Received assoc request frame while SAE authentication is in progress; Defer association request handling till SAE auth status is re                ceived"));
+        lim_defer_sme_indication(pMac, psessionEntry, subType, pHdr,
+                                pAssocReq, pmfConnection,
+                                assoc_req_copied, pStaDs);
+        return;
+    }
 
-    /**
-     * AID for this association will be same as the peer Index used in DPH table.
-     * Assign unused/least recently used peer Index from perStaDs.
-     * NOTE: limAssignPeerIdx() assigns AID values ranging 
-     * between 1 - cfg_item(WNI_CFG_ASSOC_STA_LIMIT)
-     */
-
-    peerIdx = limAssignPeerIdx(pMac, psessionEntry);
-
-    if (!peerIdx)
-    {
-        // Could not assign AID
-        // Reject association
-        limLog(pMac, LOGE, FL("PeerIdx not avaialble. Reject associaton"));
-
-        limRejectAssociation(pMac, pHdr->sa,
-                             subType, true, authType,
-                             peerIdx, false,
-                             (tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry);
-
+    if (!lim_send_assoc_ind_to_sme(pMac, psessionEntry, subType, pHdr,
+                                  pAssocReq, akm_type, pmfConnection,
+                                  &assoc_req_copied))
         goto error;
-    }
-
-    /**
-     * Add an entry to hash table maintained by DPH module
-     */
-
-    pStaDs = dphAddHashEntry(pMac, pHdr->sa, peerIdx, &psessionEntry->dph.dphHashTable);
-
-    if (pStaDs == NULL)
-    {
-        // Could not add hash table entry at DPH
-        limLog(pMac, LOGE,
-           FL("could not add hash entry at DPH for aid=%d, MacAddr:"
-           MAC_ADDRESS_STR),
-           peerIdx,MAC_ADDR_ARRAY(pHdr->sa));
-
-        // Release AID
-        limReleasePeerIdx(pMac, peerIdx, psessionEntry);
-
-        limRejectAssociation(pMac, pHdr->sa,
-                             subType, true, authType, peerIdx, false,
-                             (tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry);
-
-        goto error;
-    }
-
-     /// Store the previous auth frame's seq no
-    if (prevAuthSeqno != 0xFFFF)
-    {
-        pStaDs->PrevAuthSeqno = prevAuthSeqno;
-    }
-     /// Store the current assoc seq no
-    pStaDs->PrevAssocSeqno = ((pHdr->seqControl.seqNumHi << 4) |
-                              (pHdr->seqControl.seqNumLo));
-    limLog(pMac, LOG1, FL("Prev auth seq no %d Prev Assoc seq no. %d"),
-                          pStaDs->PrevAuthSeqno, pStaDs->PrevAssocSeqno);
-
-sendIndToSme:
-
-    psessionEntry->parsedAssocReq[pStaDs->assocId] = pAssocReq;
-
-    pStaDs->mlmStaContext.htCapability = pAssocReq->HTCaps.present;
-#ifdef WLAN_FEATURE_11AC
-    pStaDs->mlmStaContext.vhtCapability = pAssocReq->VHTCaps.present;
-#endif
-    pStaDs->qos.addtsPresent = (pAssocReq->addtsPresent==0) ? false : true;
-    pStaDs->qos.addts        = pAssocReq->addtsReq;
-    pStaDs->qos.capability   = pAssocReq->qosCapability;
-    pStaDs->versionPresent   = 0;
-    /* short slot and short preamble should be updated before doing limaddsta */
-    pStaDs->shortPreambleEnabled = (tANI_U8)pAssocReq->capabilityInfo.shortPreamble;
-    pStaDs->shortSlotTimeEnabled = (tANI_U8)pAssocReq->capabilityInfo.shortSlotTime;
- 
-    if (pAssocReq->propIEinfo.versionPresent) //update STA version info
-    {
-        pStaDs->versionPresent = 1;
-        pStaDs->version = pAssocReq->propIEinfo.version;
-    }
-    pStaDs->propCapability = 0;
-    if (pAssocReq->propIEinfo.capabilityPresent)
-    {
-        if (sirGetCfgPropCaps(pMac, &pStaDs->propCapability))
-            pStaDs->propCapability &= pAssocReq->propIEinfo.capability;
-    }
-
-    pStaDs->valid                  = 0;
-    pStaDs->mlmStaContext.authType = authType;
-    pStaDs->staType = STA_ENTRY_PEER;
-
-    //TODO: If listen interval is more than certain limit, reject the association.
-    //Need to check customer requirements and then implement.
-    pStaDs->mlmStaContext.listenInterval = pAssocReq->listenInterval;
-    pStaDs->mlmStaContext.capabilityInfo = pAssocReq->capabilityInfo;
-
-    /* The following count will be used to knock-off the station if it doesn't
-     * come back to receive the buffered data. The AP will wait for numTimSent number
-     * of beacons after sending TIM information for the station, before assuming that 
-     * the station is no more associated and disassociates it
-     */
-
-    /** timWaitCount is used by PMM for monitoring the STA's in PS for LINK*/
-    pStaDs->timWaitCount = (tANI_U8)GET_TIM_WAIT_COUNT(pAssocReq->listenInterval);
-    
-    /** Initialise the Current successful MPDU's tranfered to this STA count as 0 */
-    pStaDs->curTxMpduCnt = 0;
-
-    if(IS_DOT11_MODE_HT(psessionEntry->dot11mode) &&
-      (pAssocReq->HTCaps.present))
-    {
-        pStaDs->htGreenfield = (tANI_U8)pAssocReq->HTCaps.greenField;
-        pStaDs->htAMpduDensity = pAssocReq->HTCaps.mpduDensity;
-        pStaDs->htDsssCckRate40MHzSupport = (tANI_U8)pAssocReq->HTCaps.dsssCckMode40MHz;
-        pStaDs->htLsigTXOPProtection = (tANI_U8)pAssocReq->HTCaps.lsigTXOPProtection;
-        pStaDs->htMaxAmsduLength = (tANI_U8)pAssocReq->HTCaps.maximalAMSDUsize;
-        pStaDs->htMaxRxAMpduFactor = pAssocReq->HTCaps.maxRxAMPDUFactor;
-        pStaDs->htMIMOPSState = pAssocReq->HTCaps.mimoPowerSave;
-
-        /* pAssocReq will be copied to psessionEntry->parsedAssocReq later */
-        /* check whether AP is enabled with shortGI */
-        if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_GI_20MHZ, &val) !=
-                           eSIR_SUCCESS) {
-           limLog(pMac, LOGE,
-                         FL("could not retrieve shortGI 20Mhz CFG"));
-           goto error;
-        }
-        if (val) {
-            pStaDs->htShortGI20Mhz = (tANI_U8)pAssocReq->HTCaps.shortGI20MHz;
-        } else {
-            /* Unset htShortGI20Mhz in ht_caps*/
-            pAssocReq->HTCaps.shortGI20MHz = 0;
-            pStaDs->htShortGI20Mhz = 0;
-        }
-
-        if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_GI_40MHZ, &val) !=
-                           eSIR_SUCCESS) {
-           limLog(pMac, LOGE,
-                         FL("could not retrieve shortGI 40Mhz CFG"));
-           goto error;
-        }
-        if (val) {
-            pStaDs->htShortGI40Mhz = (tANI_U8)pAssocReq->HTCaps.shortGI40MHz;
-        } else {
-            /* Unset htShortGI40Mhz in ht_caps */
-            pAssocReq->HTCaps.shortGI40MHz = 0;
-            pStaDs->htShortGI40Mhz = 0;
-        }
-        pStaDs->htSupportedChannelWidthSet = (tANI_U8)pAssocReq->HTCaps.supportedChannelWidthSet;
-        /* peer just follows AP; so when we are softAP/GO, we just store our session entry's secondary channel offset here in peer INFRA STA
-         * However, if peer's 40MHz channel width support is disabled then secondary channel will be zero
-         */
-        pStaDs->htSecondaryChannelOffset = (pStaDs->htSupportedChannelWidthSet)?psessionEntry->htSecondaryChannelOffset:0;
-#ifdef WLAN_FEATURE_11AC
-        if(pAssocReq->operMode.present) 
-        {
-            pStaDs->vhtSupportedChannelWidthSet = (tANI_U8)((pAssocReq->operMode.chanWidth == eHT_CHANNEL_WIDTH_80MHZ) ? WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ : WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ);
-            pStaDs->htSupportedChannelWidthSet  = (tANI_U8)(pAssocReq->operMode.chanWidth ? eHT_CHANNEL_WIDTH_40MHZ : eHT_CHANNEL_WIDTH_20MHZ);
-        }
-        else if (pAssocReq->VHTCaps.present)
-        {
-            // Check if STA has enabled it's channel bonding mode. 
-            // If channel bonding mode is enabled, we decide based on SAP's current configuration.
-            // else, we set it to VHT20.
-            pStaDs->vhtSupportedChannelWidthSet = (tANI_U8)((pStaDs->htSupportedChannelWidthSet == eHT_CHANNEL_WIDTH_20MHZ) ? 
-                                                             WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ : 
-                                                             psessionEntry->vhtTxChannelWidthSet );
-        }
-
-        // Lesser among the AP and STA bandwidth of operation.
-        pStaDs->htSupportedChannelWidthSet = 
-                (pStaDs->htSupportedChannelWidthSet < psessionEntry->htSupportedChannelWidthSet) ?
-                pStaDs->htSupportedChannelWidthSet : psessionEntry->htSupportedChannelWidthSet ;
-
-#endif
-        pStaDs->baPolicyFlag = 0xFF;
-        pStaDs->htLdpcCapable = (tANI_U8)pAssocReq->HTCaps.advCodingCap;
-    }
-
-    if(pAssocReq->VHTCaps.present)
-    {
-        pStaDs->vhtLdpcCapable = (tANI_U8)pAssocReq->VHTCaps.ldpcCodingCap;
-    }
-
-#ifdef WLAN_FEATURE_11AC
-if (limPopulateMatchingRateSet(pMac,
-                               pStaDs,
-                               &(pAssocReq->supportedRates),
-                               &(pAssocReq->extendedRates),
-                               pAssocReq->HTCaps.supportedMCSSet,
-                               &(pAssocReq->propIEinfo.propRates),
-                               psessionEntry , &pAssocReq->VHTCaps) 
-                               != eSIR_SUCCESS)
-#else
-
-    if (limPopulateMatchingRateSet(pMac,
-                                   pStaDs,
-                                   &(pAssocReq->supportedRates),
-                                   &(pAssocReq->extendedRates),
-                                   pAssocReq->HTCaps.supportedMCSSet,
-                                   &(pAssocReq->propIEinfo.propRates), psessionEntry) != eSIR_SUCCESS)
-#endif
-    {
-        // Could not update hash table entry at DPH with rateset
-        limLog(pMac, LOGE,
-           FL("could not update hash entry at DPH for aid=%d, MacAddr: "
-           MAC_ADDRESS_STR),
-           peerIdx, MAC_ADDR_ARRAY(pHdr->sa));
-
-                // Release AID
-        limReleasePeerIdx(pMac, peerIdx, psessionEntry);
-
-
-        limRejectAssociation(pMac, pHdr->sa,
-                             subType, true, authType, peerIdx, true,
-                             (tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry);
-
-        pAssocReq = psessionEntry->parsedAssocReq[pStaDs->assocId];
-        goto error;
-    }
-
-    vos_mem_copy((tANI_U8 *) &pStaDs->mlmStaContext.propRateSet,
-                 (tANI_U8 *) &(pAssocReq->propIEinfo.propRates),
-                  pAssocReq->propIEinfo.propRates.numPropRates + 1);
-
-    /// Add STA context at MAC HW (BMU, RHP & TFP)
-
-    pStaDs->qosMode    = eANI_BOOLEAN_FALSE;
-    pStaDs->lleEnabled = eANI_BOOLEAN_FALSE;
-    if (pAssocReq->capabilityInfo.qos && (qosMode == eHAL_SET))
-    {
-        pStaDs->lleEnabled = eANI_BOOLEAN_TRUE;
-        pStaDs->qosMode    = eANI_BOOLEAN_TRUE; 
-    }
-
-    pStaDs->wmeEnabled = eANI_BOOLEAN_FALSE;
-    pStaDs->wsmEnabled = eANI_BOOLEAN_FALSE;
-    limGetWmeMode(psessionEntry, &wmeMode);
-    //if ((! pStaDs->lleEnabled) && assoc.wmeInfoPresent && pMac->dph.gDphWmeEnabled)
-    if ((! pStaDs->lleEnabled) && pAssocReq->wmeInfoPresent && (wmeMode == eHAL_SET))
-    {
-        pStaDs->wmeEnabled = eANI_BOOLEAN_TRUE;
-        pStaDs->qosMode = eANI_BOOLEAN_TRUE;
-        limGetWsmMode(psessionEntry, &wsmMode);
-        /* WMM_APSD - WMM_SA related processing should be separate; WMM_SA and WMM_APSD
-         can coexist */
-        if( pAssocReq->WMMInfoStation.present)
-        {
-            /* check whether AP supports or not */
-            if ((psessionEntry->limSystemRole == eLIM_AP_ROLE)
-                 && (psessionEntry->apUapsdEnable == 0) && (pAssocReq->WMMInfoStation.acbe_uapsd 
-                    || pAssocReq->WMMInfoStation.acbk_uapsd 
-                    || pAssocReq->WMMInfoStation.acvo_uapsd 
-                    || pAssocReq->WMMInfoStation.acvi_uapsd))
-            {
-
-                /**
-                 * Received Re/Association Request from
-                 * STA when UPASD is not supported.
-                 */
-               limLog( pMac, LOGE, FL( "AP do not support UAPSD so reply "
-                                       "to STA accordingly" ));
-               /* update UAPSD and send it to LIM to add STA */
-               pStaDs->qos.capability.qosInfo.acbe_uapsd = 0;
-               pStaDs->qos.capability.qosInfo.acbk_uapsd = 0;
-               pStaDs->qos.capability.qosInfo.acvo_uapsd = 0;
-               pStaDs->qos.capability.qosInfo.acvi_uapsd = 0;
-               pStaDs->qos.capability.qosInfo.maxSpLen =   0;
-
-            }
-            else
-            {
-                /* update UAPSD and send it to LIM to add STA */
-                pStaDs->qos.capability.qosInfo.acbe_uapsd = pAssocReq->WMMInfoStation.acbe_uapsd;
-                pStaDs->qos.capability.qosInfo.acbk_uapsd = pAssocReq->WMMInfoStation.acbk_uapsd;
-                pStaDs->qos.capability.qosInfo.acvo_uapsd = pAssocReq->WMMInfoStation.acvo_uapsd;
-                pStaDs->qos.capability.qosInfo.acvi_uapsd = pAssocReq->WMMInfoStation.acvi_uapsd;
-                pStaDs->qos.capability.qosInfo.maxSpLen = pAssocReq->WMMInfoStation.max_sp_length;
-            }
-        }
-        //if (assoc.wsmCapablePresent && pMac->dph.gDphWsmEnabled)
-        if (pAssocReq->wsmCapablePresent && (wsmMode == eHAL_SET))
-            pStaDs->wsmEnabled = eANI_BOOLEAN_TRUE;
-
-    }
-
-    // Re/Assoc Response frame to requesting STA
-    pStaDs->mlmStaContext.subType = subType;
-
-    if (pAssocReq->propIEinfo.aniIndicator)
-        pStaDs->aniPeer = 1;
-
-#ifdef WLAN_FEATURE_11W
-    pStaDs->rmfEnabled = (pmfConnection) ? 1 : 0;
-    pStaDs->pmfSaQueryState = DPH_SA_QUERY_NOT_IN_PROGRESS;
-    timerId.fields.sessionId = psessionEntry->peSessionId;
-    timerId.fields.peerIdx = peerIdx;
-    if (wlan_cfgGetInt(pMac, WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL,
-                       &retryInterval) != eSIR_SUCCESS)
-    {
-        limLog(pMac, LOGE, FL("Could not retrieve PMF SA Query retry interval value"));
-        limRejectAssociation(pMac, pHdr->sa,
-                             subType, true, authType,
-                             peerIdx, false,
-                             (tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry);
-        goto error;
-    }
-    if (WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_STAMIN > retryInterval)
-    {
-        retryInterval = WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_STADEF;
-    }
-    if (tx_timer_create(&pStaDs->pmfSaQueryTimer, "PMF SA Query timer",
-                        limPmfSaQueryTimerHandler, timerId.value,
-                        SYS_MS_TO_TICKS((retryInterval * 1024) / 1000),
-                        0, TX_NO_ACTIVATE) != TX_SUCCESS)
-    {
-        limLog(pMac, LOGE, FL("could not create PMF SA Query timer"));
-        limRejectAssociation(pMac, pHdr->sa,
-                             subType, true, authType,
-                             peerIdx, false,
-                             (tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry);
-        goto error;
-    }
-#endif
-
-    // BTAMP: Storing the parsed assoc request in the psessionEntry array
-    psessionEntry->parsedAssocReq[pStaDs->assocId] = pAssocReq;
-
-    /* BTAMP: If STA context already exist (ie. updateContext = 1)  
-     * for this STA, then we should delete the old one, and add 
-     * the new STA. This is taken care of in the limDelSta() routine.   
-     *
-     * Prior to BTAMP, we were setting this flag so that when
-     * PE receives SME_ASSOC_CNF, and if this flag is set, then 
-     * PE shall delete the old station and then add. But now in
-     * BTAMP, we're directly adding station before waiting for
-     * SME_ASSOC_CNF, so we can do this now.  
-     */
-    if (!updateContext)
-    {
-        pStaDs->mlmStaContext.updateContext = 0;
-
-        // BTAMP: Add STA context at HW - issue WDA_ADD_STA_REQ to HAL
-        if (limAddSta(pMac, pStaDs, false, psessionEntry) != eSIR_SUCCESS)
-        {
-            limLog(pMac, LOGE, FL("could not Add STA with assocId=%d"),
-                                  pStaDs->assocId);
-            limRejectAssociation( pMac, pStaDs->staAddr, pStaDs->mlmStaContext.subType,
-                                  true, pStaDs->mlmStaContext.authType, pStaDs->assocId, true,
-                                  (tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry);
-
-            pAssocReq = psessionEntry->parsedAssocReq[pStaDs->assocId];
-            goto error;
-        }
-    }
-    else
-    {
-        pStaDs->mlmStaContext.updateContext = 1;
-
-        mlmPrevState = pStaDs->mlmStaContext.mlmState;
-
-        /* As per the HAL/FW needs the reassoc req need not be calling limDelSta */
-        if(subType != LIM_REASSOC)
-        {
-            //we need to set the mlmState here in order differentiate in limDelSta.
-            pStaDs->mlmStaContext.mlmState = eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE;
-            if(limDelSta(pMac, pStaDs, true, psessionEntry) != eSIR_SUCCESS)
-            {
-                limLog(pMac, LOGE, FL("could not DEL STA with assocId=%d staId %d"),
-                                       pStaDs->assocId, pStaDs->staIndex);
-                limRejectAssociation( pMac, pStaDs->staAddr, pStaDs->mlmStaContext.subType, true, pStaDs->mlmStaContext.authType,
-                                      pStaDs->assocId, true,(tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry);
-
-                //Restoring the state back.
-                pStaDs->mlmStaContext.mlmState = mlmPrevState;
-                pAssocReq = psessionEntry->parsedAssocReq[pStaDs->assocId];
-                goto error;
-            }
-        }
-        else
-        {
-            /* mlmState is changed in limAddSta context */
-            /* use the same AID, already allocated */
-            if (limAddSta(pMac, pStaDs, false, psessionEntry) != eSIR_SUCCESS)
-            {
-                    limLog(pMac, LOGE, FL( "Could not AddSta with assocId= %d staId %d"),
-                                            pStaDs->assocId, pStaDs->staIndex);
-                    limRejectAssociation( pMac, pStaDs->staAddr, pStaDs->mlmStaContext.subType, true, pStaDs->mlmStaContext.authType,
-                                          pStaDs->assocId, true,(tSirResultCodes) eSIR_MAC_WME_REFUSED_STATUS, psessionEntry);
-
-                    //Restoring the state back.
-                    pStaDs->mlmStaContext.mlmState = mlmPrevState;
-                    pAssocReq = psessionEntry->parsedAssocReq[pStaDs->assocId];
-                    goto error;
-            }
-
-        }
-
-    }
 
     return;
 
 error:
-    if (pAssocReq != NULL)
-    {
-        if ( pAssocReq->assocReqFrame ) 
-        {
-            vos_mem_free(pAssocReq->assocReqFrame);
-            pAssocReq->assocReqFrame = NULL;
-        }
-
-        vos_mem_free(pAssocReq);
-    }
-
-    /* If it is not duplicate Assoc request then only make to Null */
-    if ((pStaDs != NULL) &&
-          (pStaDs->mlmStaContext.mlmState != eLIM_MLM_WT_ADD_STA_RSP_STATE))
-        psessionEntry->parsedAssocReq[pStaDs->assocId] = NULL;
-
+    lim_process_assoc_cleanup(pMac, psessionEntry, pAssocReq, pStaDs,
+                              assoc_req_copied);
     return;
 
 } /*** end limProcessAssocReqFrame() ***/