qcacld-3.0: Add vdev state machine for CSA and radar

Add vdev state machine for Channel change and to handle
radar indication.

Change-Id: Ib5a5476510ffe55611325c98dd9779261c7bd9a3
CRs-Fixed: 2316574
diff --git a/core/mac/inc/wni_api.h b/core/mac/inc/wni_api.h
index 6f91694..cd535ca 100644
--- a/core/mac/inc/wni_api.h
+++ b/core/mac/inc/wni_api.h
@@ -229,6 +229,8 @@
 	eWNI_SME_SET_ADDBA_ACCEPT,
 	eWNI_SME_UPDATE_EDCA_PROFILE,
 	WNI_SME_UPDATE_MU_EDCA_PARAMS,
+	eWNI_SME_CSA_RESTART_REQ,
+	eWNI_SME_CSA_RESTART_RSP,
 	eWNI_SME_MSG_TYPES_END
 };
 
diff --git a/core/mac/src/pe/include/lim_session.h b/core/mac/src/pe/include/lim_session.h
index 113afcc..edc3fc8 100644
--- a/core/mac/src/pe/include/lim_session.h
+++ b/core/mac/src/pe/include/lim_session.h
@@ -561,6 +561,8 @@
 	uint8_t peer_twt_responder;
 #endif
 	bool enable_session_twt_support;
+	uint32_t cac_duration_ms;
+	uint32_t dfs_regdomain;
 } tPESession, *tpPESession;
 
 struct session_params {
diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c
index ab698a4..ebcc04e 100644
--- a/core/mac/src/pe/lim/lim_process_message_queue.c
+++ b/core/mac/src/pe/lim/lim_process_message_queue.c
@@ -2080,6 +2080,11 @@
 		qdf_mem_free((void *)msg->bodyptr);
 		msg->bodyptr = NULL;
 		break;
+#ifdef CONFIG_VDEV_SM
+	case eWNI_SME_CSA_RESTART_REQ:
+		lim_send_csa_restart_req(mac_ctx, msg->bodyval);
+		break;
+#endif
 	default:
 		qdf_mem_free((void *)msg->bodyptr);
 		msg->bodyptr = NULL;
diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c
index be20acb..b83d007 100644
--- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c
+++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c
@@ -5024,6 +5024,9 @@
 		ch_change_req->targetChannel;
 	session_entry->limRFBand =
 		lim_get_rf_band(session_entry->currentOperChannel);
+	session_entry->cac_duration_ms = ch_change_req->cac_duration_ms;
+	session_entry->dfs_regdomain = ch_change_req->dfs_regdomain;
+	session_entry->maxTxPower = max_tx_pwr;
 
 	/* Update the global beacon filter */
 	lim_update_bcn_probe_filter(mac_ctx, session_entry);
@@ -5045,6 +5048,23 @@
 	qdf_mem_copy(&session_entry->extRateSet,
 			&ch_change_req->extended_rateset,
 			sizeof(session_entry->extRateSet));
+
+#ifdef CONFIG_VDEV_SM
+	ap_mlme_set_chan_switch_in_progress(session_entry->vdev, true);
+	if (wlan_vdev_mlme_get_state(session_entry->vdev) ==
+	    WLAN_VDEV_S_DFS_CAC_WAIT)
+		wlan_vdev_mlme_sm_deliver_evt(session_entry->vdev,
+					      WLAN_VDEV_SM_EV_RADAR_DETECTED,
+					      sizeof(*session_entry),
+					      session_entry);
+	else
+		wlan_vdev_mlme_sm_deliver_evt(session_entry->vdev,
+					      WLAN_VDEV_SM_EV_CSA_COMPLETE,
+					      sizeof(*session_entry),
+					      session_entry);
+
+
+#else
 	lim_set_channel(mac_ctx, ch_change_req->targetChannel,
 			session_entry->ch_center_freq_seg0,
 			session_entry->ch_center_freq_seg1,
@@ -5052,6 +5072,7 @@
 			max_tx_pwr, session_entry->peSessionId,
 			ch_change_req->cac_duration_ms,
 			ch_change_req->dfs_regdomain);
+#endif
 }
 
 /******************************************************************************
@@ -6154,3 +6175,21 @@
 	}
 }
 #endif
+
+#ifdef CONFIG_VDEV_SM
+void lim_send_csa_restart_req(tpAniSirGlobal mac_ctx, uint8_t vdev_id)
+{
+	tpPESession session;
+
+	session = pe_find_session_by_sme_session_id(mac_ctx, vdev_id);
+
+	if (!session) {
+		pe_err("session not found for vdev id %d", vdev_id);
+		return;
+	}
+
+	wlan_vdev_mlme_sm_deliver_evt(session->vdev,
+				      WLAN_VDEV_SM_EV_CSA_RESTART,
+				      sizeof(*session), session);
+}
+#endif
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 cdc3606..6a7f87b 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
@@ -2374,7 +2374,7 @@
 	if (!is_ch_dfs) {
 		if (channelId == psessionEntry->currentOperChannel) {
 			lim_apply_configuration(pMac, psessionEntry);
-			lim_send_beacon_ind(pMac, psessionEntry);
+			lim_send_beacon(pMac, psessionEntry);
 		} else {
 			pe_debug("Failed to Transmit Beacons on channel: %d after AP channel change response",
 				       psessionEntry->bcnLen);
diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h
index 7031a91..489a2a1 100644
--- a/core/mac/src/pe/lim/lim_types.h
+++ b/core/mac/src/pe/lim/lim_types.h
@@ -1083,6 +1083,16 @@
  */
 void lim_send_mgmt_frame_tx(tpAniSirGlobal mac_ctx,
 		struct scheduler_msg *msg);
+
+/**
+ * lim_send_csa_restart_req() - send csa restart req
+ * @mac_ctx Pointer to Global MAC structure
+ * @vdev_id: vdev id
+ *
+ * Return: None
+ */
+void lim_send_csa_restart_req(tpAniSirGlobal mac_ctx, uint8_t vdev_id);
+
 /**
  * lim_process_mlm_start_req() - process MLM_START_REQ message
  *
diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c
index 57bf7ef..3b93acd 100644
--- a/core/mac/src/pe/lim/lim_utils.c
+++ b/core/mac/src/pe/lim/lim_utils.c
@@ -8463,6 +8463,21 @@
 	return QDF_STATUS_SUCCESS;
 }
 
+static inline void lim_send_csa_restart_resp(tpAniSirGlobal mac_ctx,
+					     tpPESession session)
+{
+	struct scheduler_msg msg = {0};
+	QDF_STATUS status;
+
+	msg.type = eWNI_SME_CSA_RESTART_RSP;
+	msg.bodyptr = NULL;
+	msg.bodyval = session->smeSessionId;
+
+	status = scheduler_post_msg(QDF_MODULE_ID_SME, &msg);
+	if (QDF_IS_STATUS_ERROR(status))
+		sme_err("Failed to post eWNI_SME_CSA_RESTART_RSP");
+}
+
 QDF_STATUS lim_ap_mlme_vdev_update_beacon(struct vdev_mlme_obj *vdev_mlme,
 					  enum beacon_update_op op,
 					  uint16_t data_len, void *data)
@@ -8473,11 +8488,12 @@
 		pe_err("event_data is NULL");
 		return QDF_STATUS_E_INVAL;
 	}
+	session = (tpPESession)data;
 
-	if (op == BEACON_INIT) {
-		session = (tpPESession)data;
+	if (op == BEACON_INIT)
 		lim_send_beacon_ind(session->mac_ctx, session);
-	}
+	else if (op == BEACON_CSA)
+		lim_send_csa_restart_resp(session->mac_ctx, session);
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -8518,6 +8534,27 @@
 	return lim_send_vdev_stop((tpPESession)data);
 }
 
+QDF_STATUS lim_ap_mlme_vdev_restart_send(struct vdev_mlme_obj *vdev_mlme,
+					 uint16_t data_len, void *data)
+{
+	tpPESession session = (tpPESession)data;
+
+	if (!data) {
+		pe_err("data is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	lim_set_channel(session->mac_ctx, session->currentOperChannel,
+			session->ch_center_freq_seg0,
+			session->ch_center_freq_seg1,
+			session->ch_width,
+			session->maxTxPower, session->peSessionId,
+			session->cac_duration_ms,
+			session->dfs_regdomain);
+
+	return QDF_STATUS_SUCCESS;
+}
+
 #else
 
 void lim_send_beacon(tpAniSirGlobal mac_ctx, tpPESession session)
diff --git a/core/mac/src/pe/lim/lim_utils.h b/core/mac/src/pe/lim/lim_utils.h
index 0ac4fd6..6e5fc3d 100644
--- a/core/mac/src/pe/lim/lim_utils.h
+++ b/core/mac/src/pe/lim/lim_utils.h
@@ -37,6 +37,7 @@
 #include "lim_timer_utils.h"
 #include "lim_trace.h"
 #include "include/wlan_vdev_mlme.h"
+#include "wlan_mlme_vdev_mgr_interface.h"
 
 typedef enum {
 	ONE_BYTE = 1,
@@ -1566,6 +1567,21 @@
  */
 QDF_STATUS lim_ap_mlme_vdev_stop_send(struct vdev_mlme_obj *vdev_mlme,
 				      uint16_t data_len, void *data);
+
+/**
+ * lim_ap_mlme_vdev_restart_send - Invokes VDEV restart operation
+ * @vdev_mlme_obj:  VDEV MLME comp object
+ * @data_len: data size
+ * @data: event data
+ *
+ * API invokes VDEV restart operation
+ *
+ * Return: SUCCESS on successful completion of restart operation
+ *         FAILURE, if it fails due to any
+ */
+QDF_STATUS lim_ap_mlme_vdev_restart_send(struct vdev_mlme_obj *vdev_mlme,
+					 uint16_t data_len, void *data);
+
 #endif
 
 #endif /* __LIM_UTILS_H */
diff --git a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c
index 34e48e5..b0e08bb 100644
--- a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c
+++ b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c
@@ -378,6 +378,8 @@
 		CASE_RETURN_STRING(eWNI_SME_TRIGGER_SAE);
 		CASE_RETURN_STRING(eWNI_SME_SEND_MGMT_FRAME_TX);
 		CASE_RETURN_STRING(eWNI_SME_SEND_SAE_MSG);
+		CASE_RETURN_STRING(eWNI_SME_CSA_RESTART_REQ);
+		CASE_RETURN_STRING(eWNI_SME_CSA_RESTART_RSP);
 		CASE_RETURN_STRING(eWNI_SME_MSG_TYPES_END);
 	default:
 		return (uint8_t *) "UNKNOWN";