qcacld-3.0: Enhance SAP beacon template updation during DFS CSA

The hosts sends the beacon template to firmware through the
command WMI_BCN_TMPL_CMDID. The firmware sends a TX complete
indication via the WMI_OFFLOAD_BCN_TX_STATUS_EVENT and upon
receiving this host decrements the CSA count.
The hosts waits until the csa count becomes zero and then sends
vdev restart to firmware. There are some issues with this
implementation when 10 beacons with CSA are taking more time
than 1 sec. This is because in STA+SAP case sometime the
WMI_OFFLOAD_BCN_TX_STATUS_EVENT is received after in 200-300ms.
If the host doesn't receive the channel change event, it gets
struck in the channel change.

To avoid this scenario, send the beacon template to the firmware
for every beacon interval without waiting for the beacon TX
complete indication from FW except for the first beacon template
updation. Introduced a new timer (ap_ecsa_timer) to update the
firmware with the beacon template.

Change-Id: I377768b87c96fd5064aa04d1ed5434a475e656ef
CRs-Fixed: 2294661
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 d90522a..50c44f4 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
@@ -2298,32 +2298,6 @@
 	return;
 }
 
-/*--------------------------------------------------------------------------
-   \brief lim_send_dfs_chan_sw_ie_update()
-   This timer handler updates the channel switch IE in beacon template
-
-   \param pMac - pointer to global adapter context
-   \return     - channel to scan from valid session else zero.
-   \sa
-   --------------------------------------------------------------------------*/
-static void
-lim_send_dfs_chan_sw_ie_update(tpAniSirGlobal pMac, tpPESession psessionEntry)
-{
-
-	/* Update the beacon template and send to FW */
-	if (sch_set_fixed_beacon_fields(pMac, psessionEntry) != QDF_STATUS_SUCCESS) {
-		pe_err("Unable to set CSA IE in beacon");
-		return;
-	}
-
-	/* Send update beacon template message */
-	lim_send_beacon_ind(pMac, psessionEntry);
-	pe_debug("Updated CSA IE, IE COUNT: %d",
-		       psessionEntry->gLimChannelSwitch.switchCount);
-
-	return;
-}
-
 /** -----------------------------------------------------------------
    \brief lim_send_sme_ap_channel_switch_resp() - sends
    eWNI_SME_CHANNEL_CHANGE_RSP
@@ -2479,116 +2453,60 @@
 }
 #endif
 
-/** -----------------------------------------------------------------
-   \brief lim_process_beacon_tx_success_ind() - This function is used
-   explicitly to handle successful beacon transmission indication
-   from the FW. This is a generic event generated by the FW afer the
-   first beacon is sent out after the beacon template update by the
-   host
-   \param pMac - global mac structure
-   \param psessionEntry - session info
-   \return none
-   \sa
-   ----------------------------------------------------------------- */
 void
-lim_process_beacon_tx_success_ind(tpAniSirGlobal pMac, uint16_t msgType, void *event)
+lim_process_beacon_tx_success_ind(tpAniSirGlobal mac_ctx, uint16_t msgType,
+				  void *event)
 {
-	/* Currently, this event is used only for DFS channel switch announcement
-	 * IE update in the template. If required to be used for other IE updates
-	 * add appropriate code by introducing a state variable
-	 */
-	tpPESession psessionEntry;
-	struct scheduler_msg mmhMsg = {0};
-	tSirSmeCSAIeTxCompleteRsp *pChanSwTxResponse;
-	struct sir_beacon_tx_complete_rsp *beacon_tx_comp_rsp_ptr;
-	uint8_t length = sizeof(tSirSmeCSAIeTxCompleteRsp);
-	tpSirFirstBeaconTxCompleteInd pBcnTxInd =
+	tpPESession session;
+	struct scheduler_msg msg = {0};
+	struct sir_beacon_tx_complete_rsp *bcn_tx_comp_rsp;
+	tpSirFirstBeaconTxCompleteInd bcn_ind =
 		(tSirFirstBeaconTxCompleteInd *) event;
-	uint8_t ch, ch_width;
+	QDF_STATUS status;
 
-	psessionEntry = pe_find_session_by_bss_idx(pMac, pBcnTxInd->bssIdx);
-	if (psessionEntry == NULL) {
-		pe_err("Session Does not exist for given sessionID");
+	session = pe_find_session_by_bss_idx(mac_ctx, bcn_ind->bssIdx);
+	if (!session) {
+		pe_err("Session Does not exist for given session id");
 		return;
 	}
 
-	pe_debug("role: %d swIe: %d opIe: %d",
-		GET_LIM_SYSTEM_ROLE(psessionEntry),
-		psessionEntry->dfsIncludeChanSwIe,
-		psessionEntry->gLimOperatingMode.present);
+	pe_debug("role: %d swIe: %d opIe: %d switch cnt:%d",
+		 GET_LIM_SYSTEM_ROLE(session),
+		 session->dfsIncludeChanSwIe,
+		 session->gLimOperatingMode.present,
+		 session->gLimChannelSwitch.switchCount);
 
-	if (LIM_IS_AP_ROLE(psessionEntry) &&
-	    true == psessionEntry->dfsIncludeChanSwIe) {
+	if (!LIM_IS_AP_ROLE(session))
+		return;
 
-		if (psessionEntry->gLimChannelSwitch.switchCount) {
-			/* Decrement the beacon switch count */
-			psessionEntry->gLimChannelSwitch.switchCount--;
-			pe_debug("current beacon count %d",
-				psessionEntry->gLimChannelSwitch.switchCount);
-		}
+	if (session->dfsIncludeChanSwIe &&
+	    (session->gLimChannelSwitch.switchCount ==
+	    mac_ctx->sap.SapDfsInfo.sap_ch_switch_beacon_cnt))
+		lim_process_ap_ecsa_timeout(session);
 
-		/* Send only 5 beacons with CSA IE Set in when a radar is detected */
-		if (psessionEntry->gLimChannelSwitch.switchCount > 0) {
-			/*
-			 * Send the next beacon with updated CSA IE count
-			 */
-			lim_send_dfs_chan_sw_ie_update(pMac, psessionEntry);
 
-			ch = psessionEntry->gLimChannelSwitch.primaryChannel;
-			ch_width = psessionEntry->gLimChannelSwitch.ch_width;
-			if (pMac->sap.SapDfsInfo.dfs_beacon_tx_enhanced)
-				/* Send Action frame after updating beacon */
-				lim_send_chan_switch_action_frame(pMac,
-					ch, ch_width, psessionEntry);
-
-		} else {
-			/* Done with CSA IE update, send response back to SME */
-			psessionEntry->gLimChannelSwitch.switchCount = 0;
-			if (pMac->sap.SapDfsInfo.disable_dfs_ch_switch == false)
-				psessionEntry->gLimChannelSwitch.switchMode = 0;
-			psessionEntry->dfsIncludeChanSwIe = false;
-			psessionEntry->dfsIncludeChanWrapperIe = false;
-
-			pChanSwTxResponse = (tSirSmeCSAIeTxCompleteRsp *)
-					    qdf_mem_malloc(length);
-
-			if (NULL == pChanSwTxResponse) {
-				pe_err("AllocateMemory failed for tSirSmeCSAIeTxCompleteRsp");
-				return;
-			}
-
-			pChanSwTxResponse->sessionId =
-				psessionEntry->smeSessionId;
-			pChanSwTxResponse->chanSwIeTxStatus =
-				QDF_STATUS_SUCCESS;
-
-			mmhMsg.type = eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND;
-			mmhMsg.bodyptr = pChanSwTxResponse;
-			mmhMsg.bodyval = 0;
-			lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
-		}
-	}
-
-	if (LIM_IS_AP_ROLE(psessionEntry) &&
-		psessionEntry->gLimOperatingMode.present) {
+	if (session->gLimOperatingMode.present) {
 		/* Done with nss update, send response back to SME */
-		psessionEntry->gLimOperatingMode.present = 0;
-		beacon_tx_comp_rsp_ptr = (struct sir_beacon_tx_complete_rsp *)
-				qdf_mem_malloc(sizeof(*beacon_tx_comp_rsp_ptr));
-		if (NULL == beacon_tx_comp_rsp_ptr) {
-			pe_err("AllocateMemory failed for beacon_tx_comp_rsp_ptr");
+		session->gLimOperatingMode.present = 0;
+		bcn_tx_comp_rsp = (struct sir_beacon_tx_complete_rsp *)
+				  qdf_mem_malloc(sizeof(*bcn_tx_comp_rsp));
+		if (NULL == bcn_tx_comp_rsp) {
+			pe_err("AllocateMemory failed for bcn_tx_comp_rsp");
 			return;
 		}
-		beacon_tx_comp_rsp_ptr->session_id =
-			psessionEntry->smeSessionId;
-		beacon_tx_comp_rsp_ptr->tx_status = QDF_STATUS_SUCCESS;
-		mmhMsg.type = eWNI_SME_NSS_UPDATE_RSP;
-		mmhMsg.bodyptr = beacon_tx_comp_rsp_ptr;
-		mmhMsg.bodyval = 0;
-		lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+		bcn_tx_comp_rsp->session_id = session->smeSessionId;
+		bcn_tx_comp_rsp->tx_status = QDF_STATUS_SUCCESS;
+		msg.type = eWNI_SME_NSS_UPDATE_RSP;
+		msg.bodyptr = bcn_tx_comp_rsp;
+		msg.bodyval = 0;
+		status = scheduler_post_msg(QDF_MODULE_ID_SME, &msg);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			sme_err("Failed to post eWNI_SME_NSS_UPDATE_RSP");
+			qdf_mem_free(bcn_tx_comp_rsp);
+		}
 	}
 
-	lim_handle_bss_color_change_ie(pMac, psessionEntry);
+	lim_handle_bss_color_change_ie(mac_ctx, session);
 
 	return;
 }