qcacld-3.0: Serialize peer create and delete

Peer create is called before peer delete which
triggered assert at firmware.

Remove the duplicate peer entry before creating
a new entry for the same peer by serializing
the messages.

Change-Id: Ibf044df5271e9cd2fc3e869bb28d101d3ea9ad43
CRs-Fixed: 1052279
(cherry picked from commit fe914b42b15af00236e3db8e0d6c7d408c5bc4be)
diff --git a/core/mac/src/pe/lim/lim_assoc_utils.c b/core/mac/src/pe/lim/lim_assoc_utils.c
index 6cd8de9..2fd381a 100644
--- a/core/mac/src/pe/lim/lim_assoc_utils.c
+++ b/core/mac/src/pe/lim/lim_assoc_utils.c
@@ -818,6 +818,25 @@
 						      smetransactionId);
 		}
 
+	} else if (mlmStaContext.cleanupTrigger == eLIM_DUPLICATE_ENTRY) {
+		/**
+		 * LIM driven Disassociation.
+		 * Issue Disassoc Confirm to SME.
+		 */
+		lim_log(pMac, LOGW,
+			FL("Lim Posting DISASSOC_CNF to Sme. Trigger: %d"),
+			mlmStaContext.cleanupTrigger);
+
+		qdf_mem_copy((uint8_t *) &mlmDisassocCnf.peerMacAddr,
+			     (uint8_t *) sta_dsaddr.bytes, QDF_MAC_ADDR_SIZE);
+		mlmDisassocCnf.resultCode = statusCode;
+		mlmDisassocCnf.disassocTrigger = eLIM_DUPLICATE_ENTRY;
+		/* Update PE session Id */
+		mlmDisassocCnf.sessionId = psessionEntry->peSessionId;
+
+		lim_post_sme_message(pMac,
+				     LIM_MLM_DISASSOC_CNF,
+				     (uint32_t *) &mlmDisassocCnf);
 	}
 
 	if (NULL != psessionEntry && !LIM_IS_AP_ROLE(psessionEntry)) {
diff --git a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c
index 85d6346..39a3c48 100644
--- a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c
+++ b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c
@@ -144,15 +144,16 @@
  * will be sent on that session and the STA deletion will happen. After this,
  * the ASSOC request will be processed
  *
- * Return: void
+ * Return: True if duplicate entry found; FALSE otherwise.
  */
-void lim_check_sta_in_pe_entries(tpAniSirGlobal mac_ctx, tpSirMacMgmtHdr hdr,
+static bool lim_check_sta_in_pe_entries(tpAniSirGlobal mac_ctx, tpSirMacMgmtHdr hdr,
 				 uint16_t sessionid)
 {
 	uint8_t i;
 	uint16_t assoc_id = 0;
 	tpDphHashNode sta_ds = NULL;
 	tpPESession session = NULL;
+	bool dup_entry = false;
 
 	for (i = 0; i < mac_ctx->lim.maxBssId; i++) {
 		if ((&mac_ctx->lim.gpSession[i] != NULL) &&
@@ -179,11 +180,18 @@
 				 * msg to SME after delete sta which will update
 				 * the userspace with disconnect
 				 */
-				lim_cleanup_rx_path(mac_ctx, sta_ds, session);
+				sta_ds->mlmStaContext.cleanupTrigger =
+							eLIM_DUPLICATE_ENTRY;
+				sta_ds->mlmStaContext.disassocReason =
+				eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON;
+				lim_send_sme_disassoc_ind(mac_ctx, sta_ds,
+					session);
+				dup_entry = true;
 				break;
 			}
 		}
 	}
+	return dup_entry;
 }
 
 /**
@@ -1718,6 +1726,7 @@
 	tSirMacCapabilityInfo local_cap;
 	tpDphHashNode sta_ds = NULL;
 	tpSirAssocReq assoc_req, tmp_assoc_req;
+	bool dup_entry = false;
 
 	lim_get_phy_mode(mac_ctx, &phy_mode, session);
 
@@ -1781,7 +1790,8 @@
 		return;
 	}
 
-	lim_check_sta_in_pe_entries(mac_ctx, hdr, session->peSessionId);
+	dup_entry = lim_check_sta_in_pe_entries(mac_ctx, hdr,
+						session->peSessionId);
 
 	/* Get pointer to Re/Association Request frame body */
 	frm_body = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
@@ -1963,9 +1973,12 @@
 		session->parsedAssocReq[sta_ds->assocId] = assoc_req;
 	assoc_req_copied = true;
 
-	if (false == lim_update_sta_ctx(mac_ctx, session, assoc_req,
+	/* If it is duplicate entry wait till the peer is deleted */
+	if (dup_entry != true) {
+		if (false == lim_update_sta_ctx(mac_ctx, session, assoc_req,
 					sub_type, sta_ds, update_ctx))
 		goto error;
+	}
 
 	/* AddSta is sucess here */
 	if (LIM_IS_AP_ROLE(session) && IS_DOT11_MODE_HT(session->dot11mode) &&
diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c
index 653ff56..4fdd412 100644
--- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c
+++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c
@@ -58,6 +58,7 @@
 #include "cds_regdomain.h"
 #include "lim_send_messages.h"
 #include "nan_datapath.h"
+#include "lim_assoc_utils.h"
 
 static void lim_handle_join_rsp_status(tpAniSirGlobal mac_ctx,
 	tpPESession session_entry, tSirResultCodes result_code,
@@ -843,13 +844,51 @@
 	uint8_t *pBuf;
 	tSirSmeDisassocRsp *pSirSmeDisassocRsp;
 	tSirSmeDisassocInd *pSirSmeDisassocInd;
-	uint32_t *pMsg;
+	uint32_t *pMsg = NULL;
 	bool failure = false;
+	tpPESession session = NULL;
+	uint16_t i, assoc_id;
+	tpDphHashNode sta_ds = NULL;
 
 	lim_log(pMac, LOG1, FL("Disassoc Ntf with trigger : %d reasonCode: %d"),
 		disassocTrigger, reasonCode);
 
 	switch (disassocTrigger) {
+	case eLIM_DUPLICATE_ENTRY:
+		/*
+		 * Duplicate entry is removed at LIM.
+		 * Initiate new entry for other session
+		 */
+		lim_log(pMac, LOG1,
+			FL("Rcvd eLIM_DUPLICATE_ENTRY for " MAC_ADDRESS_STR),
+			MAC_ADDR_ARRAY(peerMacAddr));
+
+		for (i = 0; i < pMac->lim.maxBssId; i++) {
+			if ((&pMac->lim.gpSession[i] != NULL) &&
+					(pMac->lim.gpSession[i].valid) &&
+					(pMac->lim.gpSession[i].pePersona ==
+								QDF_SAP_MODE)) {
+				/* Find the sta ds entry in another session */
+				session = &pMac->lim.gpSession[i];
+				sta_ds = dph_lookup_hash_entry(pMac,
+						peerMacAddr, &assoc_id,
+						&session->dph.dphHashTable);
+			}
+		}
+		if (sta_ds
+#ifdef WLAN_FEATURE_11W
+			&& (!sta_ds->rmfEnabled)
+#endif
+		) {
+			if (lim_add_sta(pMac, sta_ds, false, session) !=
+					eSIR_SUCCESS)
+					lim_log(pMac, LOGE,
+					FL("could not Add STA with assocId=%d"),
+					sta_ds->assocId);
+		}
+		failure = true;
+		break;
+
 	case eLIM_PEER_ENTITY_DISASSOC:
 		if (reasonCode != eSIR_SME_STA_NOT_ASSOCIATED) {
 			failure = true;
diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h
index 41b5ab2..571579d 100644
--- a/core/mac/src/pe/lim/lim_types.h
+++ b/core/mac/src/pe/lim/lim_types.h
@@ -158,7 +158,8 @@
 	eLIM_PEER_ENTITY_DEAUTH,
 	eLIM_LINK_MONITORING_DEAUTH,
 	eLIM_JOIN_FAILURE,
-	eLIM_REASSOC_REJECT
+	eLIM_REASSOC_REJECT,
+	eLIM_DUPLICATE_ENTRY
 };
 
 /* Reason code to determine the channel change context while sending