Browse Source

qcacld-3.0: Handle disassoc and deauth during LFR3 roaming

Ignore the disassociation and deauthentication requests from
the old AP once roaming is in progress. Memorize the
received disassoc/deauth. If the roaming is not successful
and current AP's connection is retained, then the earlier
received disassoc/deauth can be honored and disconnect can
be triggered internally.

Change-Id: I5fa4d154c17e08904d839b8a889020680d662021
CRs-Fixed: 2160681
Varun Reddy Yeturu 7 years ago
parent
commit
b5d858ec80

+ 3 - 3
core/mac/src/pe/include/lim_api.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -242,11 +242,11 @@ tMgmtFrmDropReason lim_is_pkt_candidate_for_drop(tpAniSirGlobal pMac,
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 QDF_STATUS pe_roam_synch_callback(tpAniSirGlobal mac_ctx,
 	struct sSirSmeRoamOffloadSynchInd *roam_sync_ind_ptr,
-	tpSirBssDescription  bss_desc_ptr);
+	tpSirBssDescription  bss_desc_ptr, enum sir_roam_op_code reason);
 #else
 static inline QDF_STATUS pe_roam_synch_callback(tpAniSirGlobal mac_ctx,
 	struct sSirSmeRoamOffloadSynchInd *roam_sync_ind_ptr,
-	tpSirBssDescription  bss_desc_ptr)
+	tpSirBssDescription  bss_desc_ptr, enum sir_roam_op_code reason)
 {
 	return QDF_STATUS_E_NOSUPPORT;
 }

+ 4 - 0
core/mac/src/pe/include/lim_session.h

@@ -551,6 +551,10 @@ typedef struct sPESession       /* Added to Support BT-AMP */
 	bool is_session_obss_offload_enabled;
 	bool is_obss_reset_timer_initialized;
 	bool sae_pmk_cached;
+	bool fw_roaming_started;
+	bool recvd_deauth_while_roaming;
+	bool recvd_disassoc_while_roaming;
+	bool deauth_disassoc_rc;
 } tPESession, *tpPESession;
 
 /*-------------------------------------------------------------------------

+ 40 - 5
core/mac/src/pe/lim/lim_api.c

@@ -2080,6 +2080,7 @@ static inline void lim_copy_and_free_hlp_data_from_session(
  * @mac_ctx: MAC Context
  * @roam_sync_ind_ptr: Roam synch indication buffer pointer
  * @bss_desc: BSS Descriptor pointer
+ * @reason: Reason for calling callback which decides the action to be taken.
  *
  * This is a PE level callback called from WMA to complete the roam synch
  * propagation at PE level and also fill the BSS descriptor which will be
@@ -2089,7 +2090,7 @@ static inline void lim_copy_and_free_hlp_data_from_session(
  */
 QDF_STATUS pe_roam_synch_callback(tpAniSirGlobal mac_ctx,
 	roam_offload_synch_ind *roam_sync_ind_ptr,
-	tpSirBssDescription  bss_desc)
+	tpSirBssDescription  bss_desc, enum sir_roam_op_code reason)
 {
 	tpPESession session_ptr;
 	tpPESession ft_session_ptr;
@@ -2104,20 +2105,54 @@ QDF_STATUS pe_roam_synch_callback(tpAniSirGlobal mac_ctx,
 		pe_err("LFR3:roam_sync_ind_ptr is NULL");
 		return status;
 	}
-	pe_debug("LFR3:Received WMA_ROAM_OFFLOAD_SYNCH_IND LFR3:auth: %d vdevId: %d",
-		roam_sync_ind_ptr->authStatus, roam_sync_ind_ptr->roamedVdevId);
-	lim_print_mac_addr(mac_ctx, roam_sync_ind_ptr->bssid.bytes,
-			QDF_TRACE_LEVEL_DEBUG);
 	session_ptr = pe_find_session_by_sme_session_id(mac_ctx,
 				roam_sync_ind_ptr->roamedVdevId);
 	if (session_ptr == NULL) {
 		pe_err("LFR3:Unable to find session");
 		return status;
 	}
+
 	if (!LIM_IS_STA_ROLE(session_ptr)) {
 		pe_err("LFR3:session is not in STA mode");
 		return status;
 	}
+
+	pe_debug("LFR3: PE callback reason: %d", reason);
+	switch (reason) {
+	case SIR_ROAMING_START:
+		session_ptr->fw_roaming_started = true;
+		return QDF_STATUS_SUCCESS;
+	case SIR_ROAMING_ABORT:
+		session_ptr->fw_roaming_started = false;
+		/*
+		 * If there was a disassoc or deauth that was received
+		 * during roaming and it was not honored, then we have
+		 * to internally initiate a disconnect because with
+		 * ROAM_ABORT we come back to original AP.
+		 */
+		if (session_ptr->recvd_deauth_while_roaming)
+			lim_perform_deauth(mac_ctx, session_ptr,
+					   session_ptr->deauth_disassoc_rc,
+					   session_ptr->bssId, 0);
+		if (session_ptr->recvd_disassoc_while_roaming) {
+			lim_disassoc_tdls_peers(mac_ctx, session_ptr,
+						session_ptr->bssId);
+			lim_perform_disassoc(mac_ctx, 0,
+					     session_ptr->deauth_disassoc_rc,
+					     session_ptr, session_ptr->bssId);
+		}
+		return QDF_STATUS_SUCCESS;
+	case SIR_ROAM_SYNCH_PROPAGATION:
+		session_ptr->fw_roaming_started = false;
+		break;
+	default:
+		return status;
+	}
+
+	pe_debug("LFR3:Received WMA_ROAM_OFFLOAD_SYNCH_IND LFR3:auth: %d vdevId: %d",
+		roam_sync_ind_ptr->authStatus, roam_sync_ind_ptr->roamedVdevId);
+	lim_print_mac_addr(mac_ctx, roam_sync_ind_ptr->bssid.bytes,
+			QDF_TRACE_LEVEL_DEBUG);
 	/*
 	 * If deauth from AP already in progress, ignore Roam Synch Indication
 	 * from firmware.

+ 143 - 109
core/mac/src/pe/lim/lim_process_deauth_frame.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -71,11 +71,8 @@ lim_process_deauth_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
 			 tpPESession psessionEntry)
 {
 	uint8_t *pBody;
-	uint16_t aid, reasonCode;
+	uint16_t reasonCode;
 	tpSirMacMgmtHdr pHdr;
-	tLimMlmAssocCnf mlmAssocCnf;
-	tLimMlmDeauthInd mlmDeauthInd;
-	tpDphHashNode pStaDs;
 	tpPESession pRoamSessionEntry = NULL;
 	uint8_t roamSessionId;
 #ifdef WLAN_FEATURE_11W
@@ -253,8 +250,30 @@ lim_process_deauth_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
 		pe_find_session_by_bssid(pMac, psessionEntry->limReAssocbssId,
 							&roamSessionId);
 
-	if (lim_is_reassoc_in_progress(pMac, psessionEntry)
-	    || lim_is_reassoc_in_progress(pMac, pRoamSessionEntry)) {
+	if (lim_is_reassoc_in_progress(pMac, psessionEntry) ||
+	    lim_is_reassoc_in_progress(pMac, pRoamSessionEntry) ||
+	    psessionEntry->fw_roaming_started) {
+		/*
+		 * For LFR3, the roaming bssid is not known during ROAM_START,
+		 * so check if the deauth is received from current AP when
+		 * roaming is being done in the firmware
+		 */
+		if (psessionEntry->fw_roaming_started &&
+		    IS_CURRENT_BSSID(pMac, pHdr->sa, psessionEntry)) {
+			pe_debug("LFR3: Drop deauth frame from connected AP");
+			/*
+			 * recvd_deauth_while_roaming will be stored in the
+			 * current AP session amd if roaming has been aborted
+			 * for some reason and come back to same AP, then issue
+			 * a disconnect internally if this flag is true. There
+			 * is no need to reset this flag to false, because if
+			 * roaming succeeds, then this session gets deleted and
+			 * new session is created.
+			 */
+			psessionEntry->recvd_deauth_while_roaming = true;
+			psessionEntry->deauth_disassoc_rc = reasonCode;
+			return;
+		}
 		if (!IS_REASSOC_BSSID(pMac, pHdr->sa, psessionEntry)) {
 			pe_debug("Rcv Deauth from unknown/different "
 				"AP while ReAssoc. Ignore " MAC_ADDRESS_STR
@@ -299,14 +318,30 @@ lim_process_deauth_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
 		}
 	}
 
-	pStaDs =
-		dph_lookup_hash_entry(pMac, pHdr->sa, &aid,
-				      &psessionEntry->dph.dphHashTable);
+	lim_perform_deauth(pMac, psessionEntry, reasonCode, pHdr->sa,
+			   frame_rssi);
+
 
+} /*** end lim_process_deauth_frame() ***/
+
+void lim_perform_deauth(tpAniSirGlobal mac_ctx, tpPESession pe_session,
+			uint16_t rc, tSirMacAddr addr, int32_t frame_rssi)
+{
+	tLimMlmDeauthInd mlmDeauthInd;
+	tLimMlmAssocCnf mlmAssocCnf;
+	uint16_t aid;
+	tpDphHashNode sta_ds;
+
+	sta_ds = dph_lookup_hash_entry(mac_ctx, addr, &aid,
+				       &pe_session->dph.dphHashTable);
+	if (sta_ds == NULL) {
+		pe_debug("Hash entry not found");
+		return;
+	}
 	/* Check for pre-assoc states */
-	switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) {
+	switch (GET_LIM_SYSTEM_ROLE(pe_session)) {
 	case eLIM_STA_ROLE:
-		switch (psessionEntry->limMlmState) {
+		switch (pe_session->limMlmState) {
 		case eLIM_MLM_WT_AUTH_FRAME2_STATE:
 			/**
 			 * AP sent Deauth frame while waiting
@@ -316,34 +351,34 @@ lim_process_deauth_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
 
 			pe_debug("received Deauth frame state %X with failure "
 				"code %d from " MAC_ADDRESS_STR,
-				       psessionEntry->limMlmState, reasonCode,
-				       MAC_ADDR_ARRAY(pHdr->sa));
+				pe_session->limMlmState, rc,
+				MAC_ADDR_ARRAY(addr));
 
-			lim_restore_from_auth_state(pMac,
-						    eSIR_SME_DEAUTH_WHILE_JOIN,
-						    reasonCode, psessionEntry);
+			lim_restore_from_auth_state(mac_ctx,
+				eSIR_SME_DEAUTH_WHILE_JOIN,
+				rc, pe_session);
 
 			return;
 
 		case eLIM_MLM_AUTHENTICATED_STATE:
 			pe_debug("received Deauth frame state %X with "
-				 "reasonCode=%d from " MAC_ADDRESS_STR,
-				psessionEntry->limMlmState, reasonCode,
-				MAC_ADDR_ARRAY(pHdr->sa));
+				"reasonCode=%d from " MAC_ADDRESS_STR,
+				pe_session->limMlmState, rc,
+				MAC_ADDR_ARRAY(addr));
 			/* / Issue Deauth Indication to SME. */
 			qdf_mem_copy((uint8_t *) &mlmDeauthInd.peerMacAddr,
-				     pHdr->sa, sizeof(tSirMacAddr));
-			mlmDeauthInd.reasonCode = reasonCode;
+				addr, sizeof(tSirMacAddr));
+				mlmDeauthInd.reasonCode = rc;
 
-			psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE;
+			pe_session->limMlmState = eLIM_MLM_IDLE_STATE;
 			MTRACE(mac_trace
-				       (pMac, TRACE_CODE_MLM_STATE,
-				       psessionEntry->peSessionId,
-				       psessionEntry->limMlmState));
+				(mac_ctx, TRACE_CODE_MLM_STATE,
+				 pe_session->peSessionId,
+				 pe_session->limMlmState));
 
-			lim_post_sme_message(pMac,
-					     LIM_MLM_DEAUTH_IND,
-					     (uint32_t *) &mlmDeauthInd);
+			lim_post_sme_message(mac_ctx,
+					LIM_MLM_DEAUTH_IND,
+					(uint32_t *) &mlmDeauthInd);
 			return;
 
 		case eLIM_MLM_WT_ASSOC_RSP_STATE:
@@ -353,102 +388,102 @@ lim_process_deauth_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
 			 * if any and issue ASSOC_CNF to SME.
 			 */
 			pe_debug("received Deauth frame state %X with "
-				   "reasonCode=%d from " MAC_ADDRESS_STR,
-				psessionEntry->limMlmState, reasonCode,
-				MAC_ADDR_ARRAY(pHdr->sa));
-			if (lim_search_pre_auth_list(pMac, pHdr->sa))
-				lim_delete_pre_auth_node(pMac, pHdr->sa);
-
-			if (psessionEntry->pLimMlmJoinReq) {
-				qdf_mem_free(psessionEntry->pLimMlmJoinReq);
-				psessionEntry->pLimMlmJoinReq = NULL;
+				"reasonCode=%d from " MAC_ADDRESS_STR,
+				pe_session->limMlmState, rc,
+				MAC_ADDR_ARRAY(addr));
+			if (lim_search_pre_auth_list(mac_ctx, addr))
+				lim_delete_pre_auth_node(mac_ctx, addr);
+
+			if (pe_session->pLimMlmJoinReq) {
+				qdf_mem_free(pe_session->pLimMlmJoinReq);
+				pe_session->pLimMlmJoinReq = NULL;
 			}
 
 			mlmAssocCnf.resultCode = eSIR_SME_DEAUTH_WHILE_JOIN;
-			mlmAssocCnf.protStatusCode = reasonCode;
+			mlmAssocCnf.protStatusCode = rc;
 
 			/* PE session Id */
-			mlmAssocCnf.sessionId = psessionEntry->peSessionId;
+			mlmAssocCnf.sessionId = pe_session->peSessionId;
 
-			psessionEntry->limMlmState =
-				psessionEntry->limPrevMlmState;
+			pe_session->limMlmState =
+			pe_session->limPrevMlmState;
 			MTRACE(mac_trace
-				       (pMac, TRACE_CODE_MLM_STATE,
-				       psessionEntry->peSessionId,
-				       psessionEntry->limMlmState));
+				(mac_ctx, TRACE_CODE_MLM_STATE,
+				 pe_session->peSessionId,
+				 pe_session->limMlmState));
 
 			/* Deactive Association response timeout */
-			lim_deactivate_and_change_timer(pMac,
-							eLIM_ASSOC_FAIL_TIMER);
+			lim_deactivate_and_change_timer(mac_ctx,
+					eLIM_ASSOC_FAIL_TIMER);
 
-			lim_post_sme_message(pMac,
-					     LIM_MLM_ASSOC_CNF,
-					     (uint32_t *) &mlmAssocCnf);
+			lim_post_sme_message(mac_ctx,
+					LIM_MLM_ASSOC_CNF,
+			(uint32_t *) &mlmAssocCnf);
 
 			return;
 
 		case eLIM_MLM_WT_ADD_STA_RSP_STATE:
-			psessionEntry->fDeauthReceived = true;
+			pe_session->fDeauthReceived = true;
 			pe_debug("Received Deauth frame in state %X with Reason "
-				       "Code %d from Peer" MAC_ADDRESS_STR,
-				       psessionEntry->limMlmState, reasonCode,
-				       MAC_ADDR_ARRAY(pHdr->sa));
+				"Code %d from Peer" MAC_ADDRESS_STR,
+				pe_session->limMlmState, rc,
+				MAC_ADDR_ARRAY(addr));
 			return;
 
 		case eLIM_MLM_IDLE_STATE:
 		case eLIM_MLM_LINK_ESTABLISHED_STATE:
 #ifdef FEATURE_WLAN_TDLS
-			if ((NULL != pStaDs)
-			    && (STA_ENTRY_TDLS_PEER == pStaDs->staType)) {
+			if ((NULL != sta_ds)
+				&& (STA_ENTRY_TDLS_PEER == sta_ds->staType)) {
 				pe_err("received Deauth frame in state %X with "
 					"reason code %d from Tdls peer"
 					MAC_ADDRESS_STR,
-					psessionEntry->limMlmState, reasonCode,
-					MAC_ADDR_ARRAY(pHdr->sa));
-				lim_send_sme_tdls_del_sta_ind(pMac, pStaDs,
-							      psessionEntry,
-							      reasonCode);
-				return;
+					pe_session->limMlmState, rc,
+					MAC_ADDR_ARRAY(addr));
+			lim_send_sme_tdls_del_sta_ind(mac_ctx, sta_ds,
+							pe_session,
+							rc);
+			return;
 			} else {
 
-				/*
-				 * Delete all the TDLS peers only if Deauth
-				 * is received from the AP
-				 */
-				if (IS_CURRENT_BSSID(pMac, pHdr->sa, psessionEntry))
-					lim_delete_tdls_peers(pMac, psessionEntry);
+			/*
+			 * Delete all the TDLS peers only if Deauth
+			 * is received from the AP
+			 */
+				if (IS_CURRENT_BSSID(mac_ctx, addr, pe_session))
+					lim_delete_tdls_peers(mac_ctx, pe_session);
 #endif
 			/**
 			 * This could be Deauthentication frame from
 			 * a BSS with which pre-authentication was
 			 * performed. Delete Pre-auth entry if found.
 			 */
-			if (lim_search_pre_auth_list(pMac, pHdr->sa))
-				lim_delete_pre_auth_node(pMac, pHdr->sa);
+			if (lim_search_pre_auth_list(mac_ctx, addr))
+				lim_delete_pre_auth_node(mac_ctx, addr);
 #ifdef FEATURE_WLAN_TDLS
-		}
+			}
 #endif
 			break;
 
 		case eLIM_MLM_WT_REASSOC_RSP_STATE:
 			pe_err("received Deauth frame state %X with "
 				"reasonCode=%d from " MAC_ADDRESS_STR,
-				psessionEntry->limMlmState, reasonCode,
-				MAC_ADDR_ARRAY(pHdr->sa));
+				pe_session->limMlmState, rc,
+				MAC_ADDR_ARRAY(addr));
 			break;
 
 		case eLIM_MLM_WT_FT_REASSOC_RSP_STATE:
 			pe_err("received Deauth frame in FT state %X with "
 				"reasonCode=%d from " MAC_ADDRESS_STR,
-				       psessionEntry->limMlmState, reasonCode,
-				       MAC_ADDR_ARRAY(pHdr->sa));
+				pe_session->limMlmState, rc,
+				MAC_ADDR_ARRAY(addr));
 			break;
 
 		default:
 			pe_err("received Deauth frame in state %X with "
 				"reasonCode=%d from " MAC_ADDRESS_STR,
-				       psessionEntry->limMlmState, reasonCode,
-				       MAC_ADDR_ARRAY(pHdr->sa));
+				pe_session->limMlmState, rc,
+				MAC_ADDR_ARRAY(addr));
 			return;
 		}
 		break;
@@ -460,7 +495,6 @@ lim_process_deauth_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
 		break;
 
 	default:
-
 		return;
 	} /* end switch (pMac->lim.gLimSystemRole) */
 
@@ -468,30 +502,30 @@ lim_process_deauth_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
 	 * Extract 'associated' context for STA, if any.
 	 * This is maintained by DPH and created by LIM.
 	 */
-	if (NULL == pStaDs) {
-		pe_err("pStaDs is NULL");
+	if (NULL == sta_ds) {
+		pe_err("sta_ds is NULL");
 		return;
 	}
 
-	if ((pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_STA_RSP_STATE) ||
-	    (pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_BSS_RSP_STATE)) {
+	if ((sta_ds->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_STA_RSP_STATE) ||
+	    (sta_ds->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_BSS_RSP_STATE)) {
 		/**
 		 * Already in the process of deleting context for the peer
 		 * and received Deauthentication frame. Log and Ignore.
 		 */
 		pe_err("received Deauth frame from peer that is in state %X, addr "
-			MAC_ADDRESS_STR, pStaDs->mlmStaContext.mlmState,
-			       MAC_ADDR_ARRAY(pHdr->sa));
+			MAC_ADDRESS_STR, sta_ds->mlmStaContext.mlmState,
+			MAC_ADDR_ARRAY(addr));
 		return;
 	}
-	pStaDs->mlmStaContext.disassocReason = (tSirMacReasonCodes) reasonCode;
-	pStaDs->mlmStaContext.cleanupTrigger = eLIM_PEER_ENTITY_DEAUTH;
+	sta_ds->mlmStaContext.disassocReason = (tSirMacReasonCodes) rc;
+	sta_ds->mlmStaContext.cleanupTrigger = eLIM_PEER_ENTITY_DEAUTH;
 
 	/* / Issue Deauth Indication to SME. */
 	qdf_mem_copy((uint8_t *) &mlmDeauthInd.peerMacAddr,
-		     pStaDs->staAddr, sizeof(tSirMacAddr));
+			sta_ds->staAddr, sizeof(tSirMacAddr));
 	mlmDeauthInd.reasonCode =
-		(uint8_t) pStaDs->mlmStaContext.disassocReason;
+		(uint8_t) sta_ds->mlmStaContext.disassocReason;
 	mlmDeauthInd.deauthTrigger = eLIM_PEER_ENTITY_DEAUTH;
 
 	/*
@@ -500,18 +534,18 @@ lim_process_deauth_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
 	 * failure result code. SME will post the disconnect to the
 	 * supplicant and the latter would start a fresh assoc.
 	 */
-	if (lim_is_reassoc_in_progress(pMac, psessionEntry)) {
+	if (lim_is_reassoc_in_progress(mac_ctx, pe_session)) {
 		/**
 		 * AP may have 'aged-out' our Pre-auth
 		 * context. Delete local pre-auth context
 		 * if any and issue REASSOC_CNF to SME.
 		 */
-		if (lim_search_pre_auth_list(pMac, pHdr->sa))
-			lim_delete_pre_auth_node(pMac, pHdr->sa);
+		if (lim_search_pre_auth_list(mac_ctx, addr))
+			lim_delete_pre_auth_node(mac_ctx, addr);
 
-		if (psessionEntry->limAssocResponseData) {
-			qdf_mem_free(psessionEntry->limAssocResponseData);
-			psessionEntry->limAssocResponseData = NULL;
+		if (pe_session->limAssocResponseData) {
+			qdf_mem_free(pe_session->limAssocResponseData);
+			pe_session->limAssocResponseData = NULL;
 		}
 
 		pe_debug("Rcv Deauth from ReAssoc AP Issue REASSOC_CNF");
@@ -521,29 +555,29 @@ lim_process_deauth_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
 		 * Using eSIR_SME_FT_REASSOC_FAILURE does not seem to clean-up
 		 * properly and we end up seeing "transmit queue timeout".
 		 */
-		lim_post_reassoc_failure(pMac,
-					 eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE,
-					 eSIR_MAC_UNSPEC_FAILURE_STATUS,
-					 psessionEntry);
+		lim_post_reassoc_failure(mac_ctx,
+				eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE,
+				eSIR_MAC_UNSPEC_FAILURE_STATUS,
+				pe_session);
 		return;
 	}
 	/* reset the deauthMsgCnt here since we are able to Process
-	* the deauth frame and sending up the indication as well */
-	if (pMac->lim.deauthMsgCnt != 0) {
-		pMac->lim.deauthMsgCnt = 0;
+	 * the deauth frame and sending up the indication as well */
+	if (mac_ctx->lim.deauthMsgCnt != 0) {
+		mac_ctx->lim.deauthMsgCnt = 0;
 	}
-	if (LIM_IS_STA_ROLE(psessionEntry))
-		wma_tx_abort(psessionEntry->smeSessionId);
+	if (LIM_IS_STA_ROLE(pe_session))
+		wma_tx_abort(pe_session->smeSessionId);
 
-	lim_update_lost_link_info(pMac, psessionEntry, frame_rssi);
+	lim_update_lost_link_info(mac_ctx, pe_session, frame_rssi);
 
 	/* / Deauthentication from peer MAC entity */
-	if (LIM_IS_STA_ROLE(psessionEntry))
-		lim_post_sme_message(pMac, LIM_MLM_DEAUTH_IND,
-			     (uint32_t *) &mlmDeauthInd);
+	if (LIM_IS_STA_ROLE(pe_session))
+		lim_post_sme_message(mac_ctx, LIM_MLM_DEAUTH_IND,
+				(uint32_t *) &mlmDeauthInd);
 
 	/* send eWNI_SME_DEAUTH_IND to SME */
-	lim_send_sme_deauth_ind(pMac, pStaDs, psessionEntry);
+	lim_send_sme_deauth_ind(mac_ctx, sta_ds, pe_session);
 	return;
 
-} /*** end lim_process_deauth_frame() ***/
+}

+ 76 - 33
core/mac/src/pe/lim/lim_process_disassoc_frame.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -77,7 +77,6 @@ lim_process_disassoc_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
 	uint16_t aid, reasonCode;
 	tpSirMacMgmtHdr pHdr;
 	tpDphHashNode pStaDs;
-	tLimMlmDisassocInd mlmDisassocInd;
 #ifdef WLAN_FEATURE_11W
 	uint32_t frameLen;
 #endif
@@ -203,13 +202,25 @@ lim_process_disassoc_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
 
 	/** If we are in the Wait for ReAssoc Rsp state */
 	if (lim_is_reassoc_in_progress(pMac, psessionEntry)) {
+		/*
+		 * For LFR3, the roaming bssid is not known during ROAM_START,
+		 * so check if the disassoc is received from current AP when
+		 * roaming is being done in the firmware
+		 */
+		if (psessionEntry->fw_roaming_started &&
+		    IS_CURRENT_BSSID(pMac, pHdr->sa, psessionEntry)) {
+			pe_debug("Dropping disassoc frame from connected AP");
+			psessionEntry->recvd_disassoc_while_roaming = true;
+			psessionEntry->deauth_disassoc_rc = reasonCode;
+			return;
+		}
 		/** If we had received the DisAssoc from,
 		 *     a. the Current AP during ReAssociate to different AP in same ESS
 		 *     b. Unknown AP
 		 *   drop/ignore the DisAssoc received
 		 */
 		if (!IS_REASSOC_BSSID(pMac, pHdr->sa, psessionEntry)) {
-			pe_err("Ignore the DisAssoc received, while Processing ReAssoc with different/unknown AP");
+			pe_err("Ignore DisAssoc while Processing ReAssoc");
 			return;
 		}
 		/** If the Disassoc is received from the new AP to which we tried to ReAssociate
@@ -287,20 +298,7 @@ lim_process_disassoc_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
 			MAC_ADDR_ARRAY(pHdr->sa));
 		return;
 	}
-#ifdef FEATURE_WLAN_TDLS
-		/**
-		 *  Delete all the TDLS peers only if Disassoc is received
-		 *  from the AP
-		 */
-		if ((LIM_IS_STA_ROLE(psessionEntry)) &&
-			((pStaDs->mlmStaContext.mlmState ==
-					eLIM_MLM_LINK_ESTABLISHED_STATE) ||
-			(pStaDs->mlmStaContext.mlmState ==
-					eLIM_MLM_IDLE_STATE)) &&
-			(IS_CURRENT_BSSID(pMac, pHdr->sa, psessionEntry)))
-			lim_delete_tdls_peers(pMac, psessionEntry);
-#endif
-
+	lim_disassoc_tdls_peers(pMac, psessionEntry, pHdr->sa);
 	if (pStaDs->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE) {
 		/**
 		 * Requesting STA is in some 'transient' state?
@@ -316,20 +314,65 @@ lim_process_disassoc_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
 
 	} /* if (pStaDs->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE) */
 
-	pStaDs->mlmStaContext.cleanupTrigger = eLIM_PEER_ENTITY_DISASSOC;
-	pStaDs->mlmStaContext.disassocReason = (tSirMacReasonCodes) reasonCode;
+	lim_perform_disassoc(pMac, frame_rssi, reasonCode,
+			     psessionEntry, pHdr->sa);
+
+} /*** end lim_process_disassoc_frame() ***/
+
+#ifdef FEATURE_WLAN_TDLS
+void lim_disassoc_tdls_peers(tpAniSirGlobal mac_ctx,
+				    tpPESession pe_session, tSirMacAddr addr)
+{
+	tpDphHashNode sta_ds;
+	uint16_t aid;
+
+	sta_ds = dph_lookup_hash_entry(mac_ctx, addr, &aid,
+				       &pe_session->dph.dphHashTable);
+	if (sta_ds == NULL) {
+		pe_debug("Hash entry not found");
+		return;
+	}
+	/**
+	 *  Delete all the TDLS peers only if Disassoc is received
+	 *  from the AP
+	 */
+	if ((LIM_IS_STA_ROLE(pe_session)) &&
+	    ((sta_ds->mlmStaContext.mlmState ==
+	      eLIM_MLM_LINK_ESTABLISHED_STATE) ||
+	     (sta_ds->mlmStaContext.mlmState ==
+	      eLIM_MLM_IDLE_STATE)) &&
+	    (IS_CURRENT_BSSID(mac_ctx, addr, pe_session)))
+		lim_delete_tdls_peers(mac_ctx, pe_session);
+}
+#endif
+
+void lim_perform_disassoc(tpAniSirGlobal mac_ctx, int32_t frame_rssi,
+			  uint16_t rc, tpPESession pe_session, tSirMacAddr addr)
+{
+	tLimMlmDisassocInd mlmDisassocInd;
+	uint16_t aid;
+	tpDphHashNode sta_ds;
+
+	sta_ds = dph_lookup_hash_entry(mac_ctx, addr, &aid,
+				       &pe_session->dph.dphHashTable);
+	if (sta_ds == NULL) {
+		pe_debug("Hash entry not found");
+		return;
+	}
+	sta_ds->mlmStaContext.cleanupTrigger = eLIM_PEER_ENTITY_DISASSOC;
+	sta_ds->mlmStaContext.disassocReason = (tSirMacReasonCodes) rc;
 
 	/* Issue Disassoc Indication to SME. */
 	qdf_mem_copy((uint8_t *) &mlmDisassocInd.peerMacAddr,
-		     (uint8_t *) pStaDs->staAddr, sizeof(tSirMacAddr));
+			(uint8_t *) sta_ds->staAddr, sizeof(tSirMacAddr));
 	mlmDisassocInd.reasonCode =
-		(uint8_t) pStaDs->mlmStaContext.disassocReason;
+		(uint8_t) sta_ds->mlmStaContext.disassocReason;
 	mlmDisassocInd.disassocTrigger = eLIM_PEER_ENTITY_DISASSOC;
 
 	/* Update PE session Id  */
-	mlmDisassocInd.sessionId = psessionEntry->peSessionId;
+	mlmDisassocInd.sessionId = pe_session->peSessionId;
 
-	if (lim_is_reassoc_in_progress(pMac, psessionEntry)) {
+	if (lim_is_reassoc_in_progress(mac_ctx, pe_session)) {
 
 		/* If we're in the middle of ReAssoc and received disassoc from
 		 * the ReAssoc AP, then notify SME by sending REASSOC_RSP with
@@ -338,22 +381,22 @@ lim_process_disassoc_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
 		 */
 		pe_debug("received Disassoc from AP while waiting for Reassoc Rsp");
 
-		if (psessionEntry->limAssocResponseData) {
-			qdf_mem_free(psessionEntry->limAssocResponseData);
-			psessionEntry->limAssocResponseData = NULL;
+		if (pe_session->limAssocResponseData) {
+			qdf_mem_free(pe_session->limAssocResponseData);
+			pe_session->limAssocResponseData = NULL;
 		}
 
-		lim_restore_pre_reassoc_state(pMac, eSIR_SME_REASSOC_REFUSED,
-					      reasonCode, psessionEntry);
+		lim_restore_pre_reassoc_state(mac_ctx, eSIR_SME_REASSOC_REFUSED,
+				rc, pe_session);
 		return;
 	}
 
-	lim_update_lost_link_info(pMac, psessionEntry, frame_rssi);
-	lim_post_sme_message(pMac, LIM_MLM_DISASSOC_IND,
-			     (uint32_t *) &mlmDisassocInd);
+	lim_update_lost_link_info(mac_ctx, pe_session, frame_rssi);
+	lim_post_sme_message(mac_ctx, LIM_MLM_DISASSOC_IND,
+			(uint32_t *) &mlmDisassocInd);
 
 	/* send eWNI_SME_DISASSOC_IND to SME */
-	lim_send_sme_disassoc_ind(pMac, pStaDs, psessionEntry);
+	lim_send_sme_disassoc_ind(mac_ctx, sta_ds, pe_session);
 
 	return;
-} /*** end lim_process_disassoc_frame() ***/
+}

+ 43 - 0
core/mac/src/pe/lim/lim_types.h

@@ -471,7 +471,50 @@ void lim_send_mlm_assoc_ind(tpAniSirGlobal pMac, tpDphHashNode pStaDs,
 
 void lim_process_assoc_rsp_frame(tpAniSirGlobal, uint8_t *, uint8_t, tpPESession);
 void lim_process_disassoc_frame(tpAniSirGlobal, uint8_t *, tpPESession);
+/*
+ * lim_perform_disassoc() - Actual action taken after receiving disassoc
+ * @mac_ctx: Global MAC context
+ * @frame_rssi: RSSI of the frame
+ * @rc: Reason code of the deauth
+ * @pe_session: PE session entry pointer
+ * @addr: BSSID from which the disassoc is received
+ *
+ * Return: None
+ */
+void lim_perform_disassoc(tpAniSirGlobal mac_ctx, int32_t frame_rssi,
+			  uint16_t rc, tpPESession pe_session,
+			  tSirMacAddr addr);
+/*
+ * lim_disassoc_tdls_peers() - Disassoc action for tdls peers
+ * @mac_ctx: Global MAC context
+ * @pe_session: PE session entry pointer
+ * @addr: BSSID from which the disassoc is received
+ *
+ * Return: None
+ */
+#ifdef FEATURE_WLAN_TDLS
+void lim_disassoc_tdls_peers(tpAniSirGlobal mac_ctx,
+				    tpPESession pe_session, tSirMacAddr addr);
+#else
+void lim_disassoc_tdls_peers(tpAniSirGlobal mac_ctx,
+				    tpPESession pe_session, tSirMacAddr addr)
+{
+	return;
+}
+#endif
 void lim_process_deauth_frame(tpAniSirGlobal, uint8_t *, tpPESession);
+/*
+ * lim_perform_deauth() - Actual action taken after receiving deauth
+ * @mac_ctx: Global MAC context
+ * @pe_session: PE session entry pointer
+ * @rc: Reason code of the deauth
+ * @addr: BSSID from which the deauth is received
+ * @frame_rssi: RSSI of the frame
+ *
+ * Return: None
+ */
+void lim_perform_deauth(tpAniSirGlobal mac_ctx, tpPESession pe_session,
+			uint16_t rc, tSirMacAddr addr, int32_t frame_rssi);
 void lim_process_action_frame(tpAniSirGlobal, uint8_t *, tpPESession);
 void lim_process_action_frame_no_session(tpAniSirGlobal pMac, uint8_t *pRxMetaInfo);
 

+ 2 - 1
core/wma/inc/wma.h

@@ -1531,7 +1531,8 @@ typedef struct {
 		enum sir_roam_op_code reason);
 	QDF_STATUS (*pe_roam_synch_cb)(tpAniSirGlobal mac,
 		roam_offload_synch_ind *roam_synch_data,
-		tpSirBssDescription  bss_desc_ptr);
+		tpSirBssDescription  bss_desc_ptr,
+		enum sir_roam_op_code reason);
 	qdf_wake_lock_t wmi_cmd_rsp_wake_lock;
 	qdf_runtime_lock_t wmi_cmd_rsp_runtime_lock;
 	uint32_t fine_time_measurement_cap;

+ 4 - 2
core/wma/inc/wma_types.h

@@ -771,7 +771,8 @@ QDF_STATUS wma_register_roaming_callbacks(
 			enum sir_roam_op_code reason),
 		QDF_STATUS (*pe_roam_synch_cb)(tpAniSirGlobal mac,
 			roam_offload_synch_ind *roam_synch_data,
-			tpSirBssDescription  bss_desc_ptr));
+			tpSirBssDescription  bss_desc_ptr,
+			enum sir_roam_op_code reason));
 #else
 static inline QDF_STATUS wma_register_roaming_callbacks(
 		QDF_STATUS (*csr_roam_synch_cb)(tpAniSirGlobal mac,
@@ -780,7 +781,8 @@ static inline QDF_STATUS wma_register_roaming_callbacks(
 			enum sir_roam_op_code reason),
 		QDF_STATUS (*pe_roam_synch_cb)(tpAniSirGlobal mac,
 			roam_offload_synch_ind *roam_synch_data,
-			tpSirBssDescription  bss_desc_ptr))
+			tpSirBssDescription  bss_desc_ptr,
+			enum sir_roam_op_code reason))
 {
 	return QDF_STATUS_E_NOSUPPORT;
 }

+ 2 - 1
core/wma/src/wma_mgmt.c

@@ -3945,7 +3945,8 @@ QDF_STATUS wma_register_roaming_callbacks(
 		enum sir_roam_op_code reason),
 	QDF_STATUS (*pe_roam_synch_cb)(tpAniSirGlobal mac,
 		roam_offload_synch_ind *roam_synch_data,
-		tpSirBssDescription  bss_desc_ptr))
+		tpSirBssDescription  bss_desc_ptr,
+		enum sir_roam_op_code reason))
 {
 
 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);

+ 5 - 1
core/wma/src/wma_scan_roam.c

@@ -2830,7 +2830,8 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event,
 	qdf_mem_zero(bss_desc_ptr, sizeof(tSirBssDescription) + ie_len);
 	if (QDF_IS_STATUS_ERROR(wma->pe_roam_synch_cb(
 			(tpAniSirGlobal)wma->mac_context,
-			roam_synch_ind_ptr, bss_desc_ptr))) {
+			roam_synch_ind_ptr, bss_desc_ptr,
+			SIR_ROAM_SYNCH_PROPAGATION))) {
 		WMA_LOGE("LFR3: PE roam synch cb failed");
 		status = -EBUSY;
 		goto cleanup_label;
@@ -6138,6 +6139,9 @@ int wma_roam_event_callback(WMA_HANDLE handle, uint8_t *event_buf,
 		if (wmi_event->notif == WMI_ROAM_NOTIF_ROAM_ABORT)
 			op_code = SIR_ROAMING_ABORT;
 		roam_synch_data->roamedVdevId = wmi_event->vdev_id;
+		wma_handle->pe_roam_synch_cb(
+				(tpAniSirGlobal)wma_handle->mac_context,
+				roam_synch_data, NULL, op_code);
 		wma_handle->csr_roam_synch_cb(
 				(tpAniSirGlobal)wma_handle->mac_context,
 				roam_synch_data, NULL, op_code);