ソースを参照

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
Abhishek Singh 6 年 前
コミット
20a8e44ab2

+ 31 - 0
components/mlme/core/inc/wlan_mlme_vdev_mgr_interface.h

@@ -23,8 +23,20 @@
 #define _WLAN_MLME_VDEV_MGR_INT_API_H_
 
 #ifdef CONFIG_VDEV_SM
+#include <wlan_objmgr_vdev_obj.h>
 #include "include/wlan_vdev_mlme.h"
 
+/**
+ * struct mlme_legacy_priv - VDEV MLME legacy priv object
+ * @chan_switch_in_progress: flag to indicate that channel switch is in progress
+ * @hidden_ssid_restart_in_progress: flag to indicate hidden ssid restart is
+ *                                   in progress
+ */
+struct mlme_legacy_priv {
+	bool chan_switch_in_progress;
+	bool hidden_ssid_restart_in_progress;
+};
+
 /**
  * mlme_register_vdev_mgr_ops() - Register vdev mgr ops
  * @vdev_mlme: vdev mlme object
@@ -43,5 +55,24 @@ QDF_STATUS mlme_register_vdev_mgr_ops(void *mlme);
  * Return: QDF_STATUS
  */
 QDF_STATUS mlme_unregister_vdev_mgr_ops(struct vdev_mlme_obj *vdev_mlme);
+
+/**
+ * ap_mlme_set_chan_switch_in_progress() - set mlme priv restart in progress
+ * @vdev: vdev pointer
+ * @val: value to be set
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS ap_mlme_set_chan_switch_in_progress(struct wlan_objmgr_vdev *vdev,
+					       bool val);
+
+/**
+ * ap_mlme_get_chan_switch_in_progress() - get mlme priv restart in progress
+ * @vdev: vdev pointer
+ *
+ * Return: value of mlme priv restart in progress
+ */
+bool ap_mlme_get_chan_switch_in_progress(struct wlan_objmgr_vdev *vdev);
+
 #endif
 #endif

+ 62 - 7
components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c

@@ -18,7 +18,6 @@
 /**
  * DOC: define internal APIs related to the mlme component
  */
-#include <wlan_objmgr_vdev_obj.h>
 #include "wlan_mlme_main.h"
 #include "wlan_mlme_vdev_mgr_interface.h"
 #include "lim_utils.h"
@@ -460,20 +459,19 @@ static QDF_STATUS ap_mlme_vdev_start_req_failed(struct vdev_mlme_obj *vdev_mlme,
 }
 
 /**
- * sap_mlme_vdev_restart_send() a callback to send vdev restart
+ * ap_mlme_vdev_restart_send() a callback to send vdev restart
  * @vdev_mlme: vdev mlme object
- * @event_data_len: event data length
- * @event_data: event data
+ * @data_len: event data length
+ * @data: event data
  *
  * This function is called to initiate and send vdev restart req
  *
  * Return: QDF_STATUS
  */
 static QDF_STATUS ap_mlme_vdev_restart_send(struct vdev_mlme_obj *vdev_mlme,
-					    uint16_t event_data_len,
-					    void *event_data)
+					    uint16_t data_len, void *data)
 {
-	return QDF_STATUS_SUCCESS;
+	return lim_ap_mlme_vdev_restart_send(vdev_mlme, data_len, data);
 }
 
 static QDF_STATUS ap_mlme_vdev_stop_start_send(struct vdev_mlme_obj *vdev_mlme,
@@ -484,15 +482,72 @@ static QDF_STATUS ap_mlme_vdev_stop_start_send(struct vdev_mlme_obj *vdev_mlme,
 	return QDF_STATUS_SUCCESS;
 }
 
+QDF_STATUS ap_mlme_set_chan_switch_in_progress(struct wlan_objmgr_vdev *vdev,
+					       bool val)
+{
+	struct vdev_mlme_obj *vdev_mlme;
+	struct mlme_legacy_priv *mlme_priv;
+
+	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
+	if (!vdev_mlme) {
+		mlme_err("vdev component object is NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	mlme_priv = (struct mlme_legacy_priv *)vdev_mlme->legacy_vdev_ptr;
+
+	mlme_priv->chan_switch_in_progress = val;
+
+	return QDF_STATUS_SUCCESS;
+}
+
+bool ap_mlme_get_chan_switch_in_progress(struct wlan_objmgr_vdev *vdev)
+{
+	struct vdev_mlme_obj *vdev_mlme;
+	struct mlme_legacy_priv *mlme_priv;
+
+	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
+	if (!vdev_mlme) {
+		mlme_err("vdev component object is NULL");
+		return false;
+	}
+
+	mlme_priv = (struct mlme_legacy_priv *)vdev_mlme->legacy_vdev_ptr;
+
+	return mlme_priv->chan_switch_in_progress;
+}
+
+/**
+ * ap_mlme_vdev_legacy_hdl_create () - Create sap mlme legacy priv object
+ * @vdev_mlme: vdev mlme object
+ *
+ * Return: QDF_STATUS
+ */
 static
 QDF_STATUS ap_mlme_vdev_legacy_hdl_create(struct vdev_mlme_obj *vdev_mlme)
 {
+	vdev_mlme->legacy_vdev_ptr =
+		qdf_mem_malloc(sizeof(struct mlme_legacy_priv));
+	if (!vdev_mlme->legacy_vdev_ptr) {
+		mlme_err("failed to allocate meory for legacy_vdev_ptr");
+		return QDF_STATUS_E_NOMEM;
+	}
+
 	return QDF_STATUS_SUCCESS;
 }
 
+/**
+ * ap_mlme_vdev_legacy_hdl_destroy () - Destroy sap mlme legacy priv object
+ * @vdev_mlme: vdev mlme object
+ *
+ * Return: QDF_STATUS
+ */
 static
 QDF_STATUS ap_mlme_vdev_legacy_hdl_destroy(struct vdev_mlme_obj *vdev_mlme)
 {
+	qdf_mem_free(vdev_mlme->legacy_vdev_ptr);
+	vdev_mlme->legacy_vdev_ptr = NULL;
+
 	return QDF_STATUS_SUCCESS;
 }
 

+ 2 - 0
core/mac/inc/wni_api.h

@@ -229,6 +229,8 @@ enum eWniMsgTypes {
 	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
 };
 

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

@@ -561,6 +561,8 @@ typedef struct sPESession       /* Added to Support BT-AMP */
 	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 {

+ 5 - 0
core/mac/src/pe/lim/lim_process_message_queue.c

@@ -2080,6 +2080,11 @@ static void lim_process_messages(tpAniSirGlobal mac_ctx,
 		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;

+ 39 - 0
core/mac/src/pe/lim/lim_process_sme_req_messages.c

@@ -5024,6 +5024,9 @@ static void lim_process_sme_channel_change_request(tpAniSirGlobal mac_ctx,
 		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 @@ static void lim_process_sme_channel_change_request(tpAniSirGlobal mac_ctx,
 	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 @@ static void lim_process_sme_channel_change_request(tpAniSirGlobal mac_ctx,
 			max_tx_pwr, session_entry->peSessionId,
 			ch_change_req->cac_duration_ms,
 			ch_change_req->dfs_regdomain);
+#endif
 }
 
 /******************************************************************************
@@ -6154,3 +6175,21 @@ void lim_process_obss_color_collision_info(tpAniSirGlobal mac_ctx,
 	}
 }
 #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

+ 1 - 1
core/mac/src/pe/lim/lim_send_sme_rsp_messages.c

@@ -2374,7 +2374,7 @@ lim_send_sme_ap_channel_switch_resp(tpAniSirGlobal pMac,
 	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);

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

@@ -1083,6 +1083,16 @@ void lim_process_assoc_failure_timeout(tpAniSirGlobal mac_ctx,
  */
 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
  *

+ 40 - 3
core/mac/src/pe/lim/lim_utils.c

@@ -8463,6 +8463,21 @@ QDF_STATUS lim_ap_mlme_vdev_start_send(struct vdev_mlme_obj *vdev_mlme,
 	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 @@ QDF_STATUS lim_ap_mlme_vdev_update_beacon(struct vdev_mlme_obj *vdev_mlme,
 		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 @@ QDF_STATUS lim_ap_mlme_vdev_stop_send(struct vdev_mlme_obj *vdev_mlme,
 	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)

+ 16 - 0
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_disconnect_peers(struct vdev_mlme_obj *vdev_mlme,
  */
 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 */

+ 2 - 0
core/mac/src/sys/legacy/src/utils/src/mac_trace.c

@@ -378,6 +378,8 @@ uint8_t *mac_trace_get_sme_msg_string(uint16_t sme_msg)
 		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";

+ 8 - 0
core/sap/src/sap_api_link_cntl.c

@@ -1191,6 +1191,14 @@ wlansap_roam_callback(void *ctx, struct csr_roam_info *csr_roam_info,
 		wlansap_roam_process_dfs_radar_found(mac_ctx, sap_ctx,
 						&qdf_ret_status);
 		break;
+	case eCSR_ROAM_RESULT_CSA_RESTART_RSP:
+		qdf_ret_status = wlansap_dfs_send_csa_ie_request(sap_ctx);
+
+		if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status))
+			QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_HIGH,
+				  FL("CSR roam_result = eCSR_ROAM_RESULT_CSA_RESTART_RSP %d"),
+				  roam_result);
+		break;
 	case eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS:
 		wlansap_roam_process_dfs_chansw_update(hal, sap_ctx,
 				&qdf_ret_status);

+ 16 - 3
core/sap/src/sap_fsm.c

@@ -2262,7 +2262,11 @@ sap_fsm_state_init(struct sap_context *sap_ctx,
 				  QDF_TRACE_LEVEL_ERROR,
 				  FL("sap_goto_starting failed"));
 	} else if (msg == eSAP_DFS_CHANNEL_CAC_START) {
-#ifndef CONFIG_VDEV_SM
+#ifdef CONFIG_VDEV_SM
+		sap_ctx->fsm_state = SAP_STARTING;
+		QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_MED,
+			  FL("from state SAP_INIT => SAP_STARTING"));
+#else
 		/*
 		 * No need of state check here, caller is expected to perform
 		 * the checks before sending the event
@@ -2681,12 +2685,19 @@ static QDF_STATUS sap_fsm_state_started(struct sap_context *sap_ctx,
 					  QDF_TRACE_LEVEL_INFO_MED,
 					  FL("sapdfs: Sending CSAIE for sapctx[%pK]"),
 					  temp_sap_ctx);
+#ifdef CONFIG_VDEV_SM
+				qdf_status = sme_csa_restart(mac_ctx,
+						       temp_sap_ctx->sessionId);
+#else
 
 				qdf_status =
 					wlansap_dfs_send_csa_ie_request(temp_sap_ctx);
+#endif
 			}
 		}
-	} else if (eSAP_CHANNEL_SWITCH_ANNOUNCEMENT_START == msg) {
+	}
+#ifndef CONFIG_VDEV_SM
+	else if (eSAP_CHANNEL_SWITCH_ANNOUNCEMENT_START == msg) {
 		enum QDF_OPMODE persona;
 
 		if (!sap_ctx) {
@@ -2704,7 +2715,9 @@ static QDF_STATUS sap_fsm_state_started(struct sap_context *sap_ctx,
 
 		if ((QDF_SAP_MODE == persona) || (QDF_P2P_GO_MODE == persona))
 			qdf_status = wlansap_dfs_send_csa_ie_request(sap_ctx);
-	} else {
+	}
+#endif
+	else {
 		QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
 			  FL("in state %s, invalid event msg %d"),
 			  "SAP_STARTED", msg);

+ 2 - 1
core/sap/src/sap_fsm_ext.h

@@ -42,8 +42,9 @@ typedef enum {
 	eSAP_DFS_CHANNEL_CAC_END,
 	eSAP_DFS_CHNL_SWITCH_ANNOUNCEMENT_START,
 	eSAP_OPERATING_CHANNEL_CHANGED,
+#ifndef CONFIG_VDEV_SM
 	eSAP_CHANNEL_SWITCH_ANNOUNCEMENT_START,
-
+#endif
 	eSAP_NO_MSG
 } eSapMsg_t;
 

+ 6 - 3
core/sap/src/sap_module.c

@@ -1264,8 +1264,9 @@ QDF_STATUS wlansap_set_channel_change_with_csa(struct sap_context *sapContext,
 					       enum phy_ch_width target_bw,
 					       bool strict)
 {
-
+#ifndef CONFIG_VDEV_SM
 	tWLAN_SAPEvent sapEvent;
+#endif
 	tpAniSirGlobal pMac = NULL;
 	void *hHal = NULL;
 	bool valid;
@@ -1394,7 +1395,9 @@ QDF_STATUS wlansap_set_channel_change_with_csa(struct sap_context *sapContext,
 			pMac->sap.SapDfsInfo.cac_state =
 					eSAP_DFS_DO_NOT_SKIP_CAC;
 			sap_cac_reset_notify(hHal);
-
+#ifdef CONFIG_VDEV_SM
+			sme_csa_restart(hHal, sapContext->sessionId);
+#else
 			/*
 			 * Post the eSAP_CHANNEL_SWITCH_ANNOUNCEMENT_START
 			 * to SAP state machine to process the channel
@@ -1407,7 +1410,7 @@ QDF_STATUS wlansap_set_channel_change_with_csa(struct sap_context *sapContext,
 			sapEvent.u2 = 0;
 
 			sap_fsm(sapContext, &sapEvent);
-
+#endif
 		} else {
 			QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
 				  "%s: Failed to request Channel Change, since SAP is not in SAP_STARTED state",

+ 1 - 0
core/sme/inc/csr_api.h

@@ -571,6 +571,7 @@ typedef enum {
 	eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND,
 	eCSR_ROAM_RESULT_CHANNEL_CHANGE_SUCCESS,
 	eCSR_ROAM_RESULT_CHANNEL_CHANGE_FAILURE,
+	eCSR_ROAM_RESULT_CSA_RESTART_RSP,
 	eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS,
 	eCSR_ROAM_EXT_CHG_CHNL_UPDATE_IND,
 

+ 12 - 0
core/sme/inc/sme_api.h

@@ -875,6 +875,18 @@ QDF_STATUS sme_roam_channel_change_req(tHalHandle hHal,
 
 QDF_STATUS sme_roam_start_beacon_req(tHalHandle hHal,
 		struct qdf_mac_addr bssid, uint8_t dfsCacWaitStatus);
+
+#ifdef CONFIG_VDEV_SM
+/**
+ * sme_csa_restart() - request CSA IE transmission from PE
+ * @mac_ctx: mac context
+ * @session_id: SAP session id
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS sme_csa_restart(tpAniSirGlobal mac_ctx, uint8_t session_id);
+#endif
+
 QDF_STATUS sme_roam_csa_ie_request(tHalHandle hHal, struct qdf_mac_addr bssid,
 				   uint8_t targetChannel, uint8_t csaIeReqd,
 				   struct ch_params *ch_params);

+ 26 - 0
core/sme/src/common/sme_api.c

@@ -1319,6 +1319,16 @@ static QDF_STATUS dfs_msg_processor(tpAniSirGlobal mac,
 			  session_id);
 		break;
 	}
+	case eWNI_SME_CSA_RESTART_RSP:
+	{
+		session_id = msg->bodyval;
+		roam_status = 0;
+		roam_result = eCSR_ROAM_RESULT_CSA_RESTART_RSP;
+		QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
+			  "sapdfs: Received eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_REQ vdevid%d",
+			  session_id);
+		break;
+	}
 	default:
 	{
 		sme_err("Invalid DFS message: 0x%x", msg->type);
@@ -2108,6 +2118,7 @@ QDF_STATUS sme_process_msg(tpAniSirGlobal pMac, struct scheduler_msg *pMsg)
 	case eWNI_SME_DFS_RADAR_FOUND:
 	case eWNI_SME_DFS_CAC_COMPLETE:
 	case eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND:
+	case eWNI_SME_CSA_RESTART_RSP:
 		status = dfs_msg_processor(pMac, pMsg);
 		qdf_mem_free(pMsg->bodyptr);
 		break;
@@ -10466,6 +10477,21 @@ QDF_STATUS sme_roam_start_beacon_req(tHalHandle hHal, struct qdf_mac_addr bssid,
 	return status;
 }
 
+#ifdef CONFIG_VDEV_SM
+QDF_STATUS sme_csa_restart(tpAniSirGlobal mac_ctx, uint8_t session_id)
+{
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+
+	status = sme_acquire_global_lock(&mac_ctx->sme);
+	if (QDF_IS_STATUS_SUCCESS(status)) {
+		status = csr_csa_restart(mac_ctx, session_id);
+		sme_release_global_lock(&mac_ctx->sme);
+	}
+
+	return status;
+}
+#endif
+
 /**
  * sme_roam_csa_ie_request() - request CSA IE transmission from PE
  * @hHal: handle returned by mac_open

+ 19 - 0
core/sme/src/csr/csr_api_roam.c

@@ -20909,6 +20909,25 @@ QDF_STATUS csr_send_ext_change_channel(tpAniSirGlobal mac_ctx, uint32_t channel,
 	return status;
 }
 
+#ifdef CONFIG_VDEV_SM
+QDF_STATUS csr_csa_restart(tpAniSirGlobal mac_ctx, uint8_t session_id)
+{
+	QDF_STATUS status;
+	struct scheduler_msg message = {0};
+
+	/* Serialize the req through MC thread */
+	message.bodyval = session_id;
+	message.type    = eWNI_SME_CSA_RESTART_REQ;
+	status = scheduler_post_msg(QDF_MODULE_ID_PE, &message);
+	if (!QDF_IS_STATUS_SUCCESS(status)) {
+		sme_err("scheduler_post_msg failed!(err=%d)", status);
+		status = QDF_STATUS_E_FAILURE;
+	}
+
+	return status;
+}
+#endif
+
 /**
  * csr_roam_send_chan_sw_ie_request() - Request to transmit CSA IE
  * @mac_ctx:        Global MAC context

+ 11 - 0
core/sme/src/csr/csr_inside_api.h

@@ -999,6 +999,17 @@ void csr_clear_votes_for_country_info(tpAniSirGlobal pMac);
 
 QDF_STATUS csr_send_ext_change_channel(tpAniSirGlobal mac_ctx,
 				uint32_t channel, uint8_t session_id);
+#ifdef CONFIG_VDEV_SM
+/**
+ * csr_csa_start() - request CSA IE transmission from PE
+ * @mac_ctx: handle returned by mac_open
+ * @session_id: SAP session id
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS csr_csa_restart(tpAniSirGlobal mac_ctx, uint8_t session_id);
+#endif
+
 
 #ifdef QCA_HT_2040_COEX
 QDF_STATUS csr_set_ht2040_mode(tpAniSirGlobal pMac, uint32_t sessionId,

+ 1 - 0
core/sme/src/csr/csr_util.c

@@ -355,6 +355,7 @@ const char *get_e_csr_roam_result_str(eCsrRoamResult val)
 		CASE_RETURN_STR(eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND);
 		CASE_RETURN_STR(eCSR_ROAM_RESULT_CHANNEL_CHANGE_SUCCESS);
 		CASE_RETURN_STR(eCSR_ROAM_RESULT_CHANNEL_CHANGE_FAILURE);
+		CASE_RETURN_STR(eCSR_ROAM_RESULT_CSA_RESTART_RSP);
 		CASE_RETURN_STR(eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS);
 		CASE_RETURN_STR(eCSR_ROAM_EXT_CHG_CHNL_UPDATE_IND);
 		CASE_RETURN_STR(eCSR_ROAM_RESULT_NDI_CREATE_RSP);

+ 1 - 0
core/wma/inc/wma_api.h

@@ -34,6 +34,7 @@
 #include "wma_sar_public_structs.h"
 #include <cdp_txrx_ops.h>
 #include "include/wlan_vdev_mlme.h"
+#include "wlan_mlme_vdev_mgr_interface.h"
 
 typedef void *WMA_HANDLE;
 

+ 6 - 1
core/wma/src/wma_dev_if.c

@@ -1305,9 +1305,14 @@ int wma_vdev_start_resp_handler(void *handle, uint8_t *cmd_param_info,
 							&iface->beacon_filter);
 			}
 		}
-
+#ifdef CONFIG_VDEV_SM
+		wlan_vdev_mlme_sm_deliver_evt(iface->vdev,
+					      WLAN_VDEV_SM_EV_RESTART_RESP,
+					      sizeof(*params), params);
+#else
 		wma_send_msg_high_priority(wma, WMA_SWITCH_CHANNEL_RSP,
 					   (void *)params, 0);
+#endif
 	} else if (req_msg->msg_type == WMA_ADD_BSS_REQ) {
 		tpAddBssParams bssParams = (tpAddBssParams) req_msg->user_data;
 

+ 12 - 1
core/wma/src/wma_utils.c

@@ -4815,7 +4815,18 @@ wma_ap_vdev_send_start_resp(struct vdev_mlme_obj *vdev_mlme,
 QDF_STATUS wma_ap_mlme_vdev_start_continue(struct vdev_mlme_obj *vdev_mlme,
 					   uint16_t data_len, void *data)
 {
-	return wma_ap_vdev_send_start_resp(vdev_mlme, data);
+	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	if (ap_mlme_get_chan_switch_in_progress(vdev_mlme->vdev)) {
+		wma_send_msg_high_priority(wma, WMA_SWITCH_CHANNEL_RSP,
+					   data, 0);
+		ap_mlme_set_chan_switch_in_progress(vdev_mlme->vdev, false);
+	} else {
+		status = wma_ap_vdev_send_start_resp(vdev_mlme, data);
+	}
+
+	return status;
 }
 
 QDF_STATUS wma_ap_mlme_vdev_stop_continue(struct vdev_mlme_obj *vdev_mlme,