qcacld-3.0: Wait for peer delete response from firmware

Currently driver does not wait for peer del response from firmware,
but posts del sta response indication to SME immediately. This
can cause an assert in firmware if driver receives add sta
immediately before even del sta response from firmware. Add
changes to wait for peer del response from firmware to fix
this.

Change-Id: I16a84256f4a1ed971c17eb3139faac5622eadda4
CRs-Fixed: 2008940
diff --git a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c
index f1f9c53..d732644 100644
--- a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c
+++ b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c
@@ -1990,6 +1990,13 @@
 	lim_log(pMac, LOG1, FL("Del STA RSP received. Status:%d AssocID:%d"),
 			pDelStaParams->status, pDelStaParams->assocId);
 
+#ifdef FEATURE_WLAN_TDLS
+	if (pDelStaParams->staType == STA_ENTRY_TDLS_PEER) {
+		lim_log(pMac, LOG1, FL("TDLS Del STA RSP received."));
+		lim_process_tdls_del_sta_rsp(pMac, limMsgQ, psessionEntry);
+		return;
+	}
+#endif
 	if (QDF_STATUS_SUCCESS != pDelStaParams->status)
 		lim_log(pMac, LOGE, FL(
 			"Del STA failed! Status:%d, proceeding with Del BSS"),
diff --git a/core/mac/src/pe/lim/lim_process_tdls.c b/core/mac/src/pe/lim/lim_process_tdls.c
index 1b19d44..a382137 100644
--- a/core/mac/src/pe/lim/lim_process_tdls.c
+++ b/core/mac/src/pe/lim/lim_process_tdls.c
@@ -2769,7 +2769,8 @@
  */
 static tpDphHashNode lim_tdls_del_sta(tpAniSirGlobal pMac,
 				      struct qdf_mac_addr peerMac,
-				      tpPESession psessionEntry)
+				      tpPESession psessionEntry,
+				      bool resp_reqd)
 {
 	tSirRetStatus status = eSIR_SUCCESS;
 	uint16_t peerIdx = 0;
@@ -2783,11 +2784,13 @@
 		lim_log(pMac, LOG1, FL("DEL STA peer MAC: "MAC_ADDRESS_STR),
 		       MAC_ADDR_ARRAY(pStaDs->staAddr));
 
-		lim_log(pMac, LOG1, FL("STA type = %x, sta idx = %x"),
+		lim_log(pMac, LOG1,
+		       FL("STA type = %x, sta idx = %x resp_reqd %d"),
 		       pStaDs->staType,
-		       pStaDs->staIndex);
+		       pStaDs->staIndex,
+		       resp_reqd);
 
-		status = lim_del_sta(pMac, pStaDs, false, psessionEntry);
+		status = lim_del_sta(pMac, pStaDs, resp_reqd, psessionEntry);
 	}
 
 	return pStaDs;
@@ -3151,7 +3154,6 @@
 	tSirTdlsDelStaReq *pDelStaReq = (tSirTdlsDelStaReq *) pMsgBuf;
 	tpPESession psessionEntry;
 	uint8_t sessionId;
-	tpDphHashNode pStaDs = NULL;
 
 	lim_log(pMac, LOG1, FL("TDLS Delete STA Request Recieved"));
 	psessionEntry =
@@ -3190,25 +3192,8 @@
 		goto lim_tdls_del_sta_error;
 	}
 
-	pStaDs = lim_tdls_del_sta(pMac, pDelStaReq->peermac, psessionEntry);
-
-	/* now send indication to SME-->HDD->TL to remove STA from TL */
-
-	if (pStaDs) {
-		lim_send_sme_tdls_del_sta_rsp(pMac, psessionEntry->smeSessionId,
-					      pDelStaReq->peermac, pStaDs,
-					      eSIR_SUCCESS);
-		lim_release_peer_idx(pMac, pStaDs->assocId, psessionEntry);
-
-		/* Clear the aid in peerAIDBitmap as this aid is now in freepool */
-		CLEAR_PEER_AID_BITMAP(psessionEntry->peerAIDBitmap,
-				      pStaDs->assocId);
-		lim_delete_dph_hash_entry(pMac, pStaDs->staAddr, pStaDs->assocId,
-					  psessionEntry);
-
-		return eSIR_SUCCESS;
-
-	}
+	lim_tdls_del_sta(pMac, pDelStaReq->peermac, psessionEntry, true);
+	return eSIR_SUCCESS;
 
 lim_tdls_del_sta_error:
 	lim_send_sme_tdls_del_sta_rsp(pMac, psessionEntry->smeSessionId,
@@ -3433,7 +3418,7 @@
 						QDF_MAC_ADDR_SIZE);
 
 				lim_tdls_del_sta(mac_ctx, mac_addr,
-						session_entry);
+						session_entry, false);
 
 				dph_delete_hash_entry(mac_ctx,
 					stads->staAddr, stads->assocId,
@@ -3452,4 +3437,68 @@
 	return eSIR_SUCCESS;
 }
 
+/**
+ * lim_process_tdls_del_sta_rsp() - Handle WDA_DELETE_STA_RSP for TDLS
+ * @mac_ctx: Global MAC context
+ * @lim_msg: LIM message
+ * @pe_session: PE session
+ *
+ * Return: None
+ */
+void lim_process_tdls_del_sta_rsp(tpAniSirGlobal mac_ctx,
+				  struct scheduler_msg *lim_msg,
+				  tpPESession session_entry)
+{
+	tpDeleteStaParams del_sta_params = (tpDeleteStaParams) lim_msg->bodyptr;
+	tpDphHashNode sta_ds;
+	uint16_t peer_idx = 0;
+	struct qdf_mac_addr peer_mac;
+
+	if (!del_sta_params) {
+		lim_log(mac_ctx, LOGE,
+			FL("del_sta_params is NULL"));
+		return;
+	}
+
+	sta_ds = dph_lookup_hash_entry(mac_ctx, del_sta_params->staMac,
+			&peer_idx, &session_entry->dph.dphHashTable);
+	if (!sta_ds) {
+		lim_log(mac_ctx, LOGE,
+			FL("DPH Entry for STA %X is missing."),
+			DPH_STA_HASH_INDEX_PEER);
+		goto skip_event;
+	}
+
+	qdf_mem_copy(peer_mac.bytes,
+			del_sta_params->staMac, QDF_MAC_ADDR_SIZE);
+
+	if (QDF_STATUS_SUCCESS != del_sta_params->status) {
+		lim_log(mac_ctx, LOGE, FL("DEL STA failed!"));
+		lim_send_sme_tdls_del_sta_rsp(mac_ctx,
+				      session_entry->smeSessionId,
+				      peer_mac, NULL, eSIR_FAILURE);
+		goto skip_event;
+	}
+
+	lim_log(mac_ctx, LOG1, FL("DEL STA success"));
+
+	/* now send indication to SME-->HDD->TL to remove STA from TL */
+
+	lim_send_sme_tdls_del_sta_rsp(mac_ctx, session_entry->smeSessionId,
+				      peer_mac, sta_ds,
+				      eSIR_SUCCESS);
+	lim_release_peer_idx(mac_ctx, sta_ds->assocId, session_entry);
+
+	/* Clear the aid in peerAIDBitmap as this aid is now in freepool */
+	CLEAR_PEER_AID_BITMAP(session_entry->peerAIDBitmap,
+			      sta_ds->assocId);
+	lim_delete_dph_hash_entry(mac_ctx, sta_ds->staAddr, sta_ds->assocId,
+				  session_entry);
+
+skip_event:
+	qdf_mem_free(del_sta_params);
+	lim_msg->bodyptr = NULL;
+}
+
+
 #endif
diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h
index a77b388..fdb9cac 100644
--- a/core/mac/src/pe/lim/lim_types.h
+++ b/core/mac/src/pe/lim/lim_types.h
@@ -551,6 +551,9 @@
 tSirRetStatus lim_delete_tdls_peers(tpAniSirGlobal mac_ctx,
 				    tpPESession session_entry);
 QDF_STATUS lim_process_tdls_add_sta_rsp(tpAniSirGlobal pMac, void *msg, tpPESession);
+void lim_process_tdls_del_sta_rsp(tpAniSirGlobal mac_ctx,
+				  struct scheduler_msg *lim_msg,
+				  tpPESession session_entry);
 #else
 static inline tSirRetStatus lim_delete_tdls_peers(tpAniSirGlobal mac_ctx,
 						tpPESession session_entry)
diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c
index 7e821c6..b1ac7cb 100644
--- a/core/sme/src/common/sme_api.c
+++ b/core/sme/src/common/sme_api.c
@@ -9939,6 +9939,7 @@
 	case eSME_TDLS_PEER_STATE_TEARDOWN:
 		pTdlsPeerStateParams->peerState =
 			WMA_TDLS_PEER_STATE_TEARDOWN;
+		pTdlsPeerStateParams->resp_reqd = false;
 		break;
 
 	case eSME_TDLS_PEER_ADD_MAC_ADDR:
diff --git a/core/wma/inc/wma_if.h b/core/wma/inc/wma_if.h
index 8fc563c..f8066e1 100644
--- a/core/wma/inc/wma_if.h
+++ b/core/wma/inc/wma_if.h
@@ -1238,6 +1238,7 @@
 	tSirMacAddr peerMacAddr;
 	uint32_t peerState;
 	tTdlsPeerCapParams peerCap;
+	bool resp_reqd;
 } tTdlsPeerStateParams;
 
 /**
diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c
index b507186..a8196af 100644
--- a/core/wma/src/wma_dev_if.c
+++ b/core/wma/src/wma_dev_if.c
@@ -4131,6 +4131,8 @@
 static void wma_del_tdls_sta(tp_wma_handle wma, tpDeleteStaParams del_sta)
 {
 	tTdlsPeerStateParams *peerStateParams;
+	struct wma_target_req *msg;
+	int status;
 
 	peerStateParams = qdf_mem_malloc(sizeof(tTdlsPeerStateParams));
 	if (!peerStateParams) {
@@ -4142,6 +4144,7 @@
 
 	peerStateParams->peerState = WMA_TDLS_PEER_STATE_TEARDOWN;
 	peerStateParams->vdevId = del_sta->smesessionId;
+	peerStateParams->resp_reqd = del_sta->respReqd;
 	qdf_mem_copy(&peerStateParams->peerMacAddr,
 		     &del_sta->staMac, sizeof(tSirMacAddr));
 
@@ -4150,9 +4153,48 @@
 		 __func__, peerStateParams->peerMacAddr,
 		 peerStateParams->peerState);
 
-	wma_update_tdls_peer_state(wma, peerStateParams);
+	status = wma_update_tdls_peer_state(wma, peerStateParams);
 
-	del_sta->status = QDF_STATUS_SUCCESS;
+	if (status < 0) {
+		WMA_LOGE("%s: wma_update_tdls_peer_state returned failure",
+				__func__);
+		goto send_del_rsp;
+	}
+
+	if (del_sta->respReqd &&
+			WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
+				WMI_SERVICE_SYNC_DELETE_CMDS)) {
+		del_sta->status = QDF_STATUS_SUCCESS;
+		msg = wma_fill_hold_req(wma,
+				del_sta->smesessionId,
+				WMA_DELETE_STA_REQ,
+				WMA_DELETE_STA_RSP_START, del_sta,
+				WMA_DELETE_STA_TIMEOUT);
+		if (!msg) {
+			WMA_LOGP(FL("Failed to allocate vdev_id %d"),
+					peerStateParams->vdevId);
+			wma_remove_req(wma,
+					peerStateParams->vdevId,
+					WMA_DELETE_STA_RSP_START);
+			del_sta->status = QDF_STATUS_E_NOMEM;
+			goto send_del_rsp;
+		}
+		/*
+		 * Acquire wake lock and bus lock till
+		 * firmware sends the response
+		 */
+		cds_host_diag_log_work(&wma->
+				wmi_cmd_rsp_wake_lock,
+				WMA_FW_RSP_EVENT_WAKE_LOCK_DURATION,
+				WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
+		qdf_wake_lock_timeout_acquire(&wma->
+				wmi_cmd_rsp_wake_lock,
+				WMA_FW_RSP_EVENT_WAKE_LOCK_DURATION);
+		qdf_runtime_pm_prevent_suspend(wma->
+				wmi_cmd_rsp_runtime_lock);
+	}
+
+	return;
 
 send_del_rsp:
 	if (del_sta->respReqd) {