Explorar el Código

qcacld-3.0: Enable monitor mode based on VDEV SM

Enable monitor mode based on VDEV SM

Change-Id: I3ed95a7d741b802a67432bc8d8bcab05fe1b51d5
CRs-Fixed: 2457147
Jinwei Chen hace 5 años
padre
commit
8cb25b3042

+ 127 - 0
components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c

@@ -27,6 +27,7 @@
 
 static struct vdev_mlme_ops sta_mlme_ops;
 static struct vdev_mlme_ops ap_mlme_ops;
+static struct vdev_mlme_ops mon_mlme_ops;
 static struct mlme_ext_ops ext_ops;
 
 bool mlme_is_vdev_in_beaconning_mode(enum QDF_OPMODE vdev_opmode)
@@ -74,6 +75,8 @@ QDF_STATUS mlme_register_vdev_mgr_ops(struct vdev_mlme_obj *vdev_mlme)
 
 	if (mlme_is_vdev_in_beaconning_mode(vdev->vdev_mlme.vdev_opmode))
 		vdev_mlme->ops = &ap_mlme_ops;
+	else if (vdev->vdev_mlme.vdev_opmode == QDF_MONITOR_MODE)
+		vdev_mlme->ops = &mon_mlme_ops;
 	else
 		vdev_mlme->ops = &sta_mlme_ops;
 
@@ -468,6 +471,7 @@ static QDF_STATUS vdevmgr_mlme_vdev_down_send(struct vdev_mlme_obj *vdev_mlme,
 			  vdev_mlme->vdev->vdev_objmgr.vdev_id);
 	return wma_ap_mlme_vdev_down_send(vdev_mlme, data_len, data);
 }
+
 /**
  * vdevmgr_notify_down_complete() - callback to indicate vdev down is completed
  * @vdev_mlme: vdev mlme object
@@ -844,6 +848,119 @@ static QDF_STATUS ap_vdev_dfs_cac_timer_stop(struct vdev_mlme_obj *vdev_mlme,
 	return QDF_STATUS_SUCCESS;
 }
 
+/**
+ * mon_mlme_vdev_start_restart_send () - send vdev start/restart req
+ * @vdev_mlme: vdev mlme object
+ * @data_len: event data length
+ * @data: event data
+ *
+ * This function is called to initiate actions of VDEV start/restart
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS mon_mlme_vdev_start_restart_send(
+	struct vdev_mlme_obj *vdev_mlme,
+	uint16_t data_len, void *data)
+{
+	mlme_legacy_debug("vdev id = %d",
+			  vdev_mlme->vdev->vdev_objmgr.vdev_id);
+	return lim_mon_mlme_vdev_start_send(vdev_mlme, data_len, data);
+}
+
+/**
+ * mon_start_continue () - vdev start rsp calback
+ * @vdev_mlme: vdev mlme object
+ * @data_len: event data length
+ * @data: event data
+ *
+ * This function is called to handle the VDEV START/RESTART calback
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS mon_mlme_start_continue(struct vdev_mlme_obj *vdev_mlme,
+					  uint16_t data_len, void *data)
+{
+	mlme_legacy_debug("vdev id = %d",
+			  vdev_mlme->vdev->vdev_objmgr.vdev_id);
+	return wma_mon_mlme_vdev_start_continue(vdev_mlme, data_len, data);
+}
+
+/**
+ * mon_mlme_vdev_up_send() - callback to send vdev up
+ * @vdev_mlme: vdev mlme object
+ * @data_len: event data length
+ * @data: event data
+ *
+ * This function is called to send vdev up req
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS mon_mlme_vdev_up_send(struct vdev_mlme_obj *vdev_mlme,
+					uint16_t data_len, void *data)
+{
+	mlme_legacy_debug("vdev id = %d",
+			  vdev_mlme->vdev->vdev_objmgr.vdev_id);
+	return wma_mon_mlme_vdev_up_send(vdev_mlme, data_len, data);
+}
+
+/**
+ * mon_mlme_vdev_disconnect_peers() - callback to disconnect all connected peers
+ * @vdev_mlme: vdev mlme object
+ * @data_len: event data length
+ * @data: event data
+ *
+ * montior mode no connected peers, only do VDEV state transition.
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS mon_mlme_vdev_disconnect_peers(
+		struct vdev_mlme_obj *vdev_mlme,
+		uint16_t data_len, void *data)
+{
+	mlme_legacy_debug("vdev id = %d",
+			  vdev_mlme->vdev->vdev_objmgr.vdev_id);
+	return wlan_vdev_mlme_sm_deliver_evt(
+				vdev_mlme->vdev,
+				WLAN_VDEV_SM_EV_DISCONNECT_COMPLETE,
+				0, NULL);
+}
+
+/**
+ * mon_mlme_vdev_stop_send() - callback to send stop vdev request
+ * @vdev_mlme: vdev mlme object
+ * @data_len: event data length
+ * @data: event data
+ *
+ * This function is called to send stop vdev request
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS mon_mlme_vdev_stop_send(struct vdev_mlme_obj *vdev_mlme,
+					  uint16_t data_len, void *data)
+{
+	mlme_legacy_debug("vdev id = %d",
+			  vdev_mlme->vdev->vdev_objmgr.vdev_id);
+	return wma_mon_mlme_vdev_stop_send(vdev_mlme, data_len, data);
+}
+
+/**
+ * mon_mlme_vdev_down_send() - callback to send vdev down req
+ * @vdev_mlme: vdev mlme object
+ * @data_len: event data length
+ * @data: event data
+ *
+ * This function is called to send vdev down req
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS mon_mlme_vdev_down_send(struct vdev_mlme_obj *vdev_mlme,
+					  uint16_t data_len, void *data)
+{
+	mlme_legacy_debug("vdev id = %d",
+			  vdev_mlme->vdev->vdev_objmgr.vdev_id);
+	return wma_mon_mlme_vdev_down_send(vdev_mlme, data_len, data);
+}
+
 /**
  * struct sta_mlme_ops - VDEV MLME operation callbacks strucutre for sta
  * @mlme_vdev_start_send:               callback to initiate actions of VDEV
@@ -934,6 +1051,16 @@ static struct vdev_mlme_ops ap_mlme_ops = {
 	.mlme_vdev_is_newchan_no_cac = ap_mlme_vdev_is_newchan_no_cac,
 };
 
+static struct vdev_mlme_ops mon_mlme_ops = {
+	.mlme_vdev_start_send = mon_mlme_vdev_start_restart_send,
+	.mlme_vdev_restart_send = mon_mlme_vdev_start_restart_send,
+	.mlme_vdev_start_continue = mon_mlme_start_continue,
+	.mlme_vdev_up_send = mon_mlme_vdev_up_send,
+	.mlme_vdev_disconnect_peers = mon_mlme_vdev_disconnect_peers,
+	.mlme_vdev_stop_send = mon_mlme_vdev_stop_send,
+	.mlme_vdev_down_send = mon_mlme_vdev_down_send,
+};
+
 /**
  * struct mlme_ext_ops - VDEV MLME legacy global callbacks structure
  * @mlme_vdev_ext_hdl_create:           callback to invoke creation of legacy

+ 1 - 1
core/dp/txrx/ol_txrx.c

@@ -5810,7 +5810,7 @@ static struct cdp_me_ops ol_ops_me = {
 };
 
 static struct cdp_mon_ops ol_ops_mon = {
-	/* EMPTY FOR MCL */
+	.txrx_monitor_record_channel = ol_htt_mon_note_chan,
 };
 
 static struct cdp_host_stats_ops ol_ops_host_stats = {

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

@@ -4996,11 +4996,36 @@ static void lim_process_sme_start_beacon_req(struct mac_context *mac, uint32_t *
 	}
 }
 
+static void lim_mon_change_channel(
+	struct mac_context *mac_ctx,
+	struct pe_session *session_entry)
+{
+	if (wlan_vdev_mlme_get_state(session_entry->vdev) == WLAN_VDEV_S_INIT)
+		wlan_vdev_mlme_sm_deliver_evt(session_entry->vdev,
+					      WLAN_VDEV_SM_EV_START,
+					      sizeof(*session_entry),
+					      session_entry);
+	else if (wlan_vdev_mlme_get_state(session_entry->vdev) ==
+		 WLAN_VDEV_S_UP) {
+		mlme_set_chan_switch_in_progress(session_entry->vdev, true);
+		wlan_vdev_mlme_sm_deliver_evt(session_entry->vdev,
+					      WLAN_VDEV_SM_EV_FW_VDEV_RESTART,
+					      sizeof(*session_entry),
+					      session_entry);
+	} else {
+		pe_err("Invalid vdev state to change channel");
+	}
+}
+
 static void lim_change_channel(
 	struct mac_context *mac_ctx,
 	struct pe_session *session_entry)
 {
+	if (session_entry->bssType == eSIR_MONITOR_MODE)
+		return lim_mon_change_channel(mac_ctx, session_entry);
+
 	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,

+ 29 - 0
core/mac/src/pe/lim/lim_utils.c

@@ -8097,6 +8097,35 @@ QDF_STATUS lim_ap_mlme_vdev_start_req_failed(struct vdev_mlme_obj *vdev_mlme,
 	return QDF_STATUS_SUCCESS;
 }
 
+QDF_STATUS lim_mon_mlme_vdev_start_send(struct vdev_mlme_obj *vdev_mlme,
+					uint16_t data_len, void *data)
+{
+	struct mac_context *mac_ctx;
+	struct pe_session *session = (struct pe_session *)data;
+
+	if (!data) {
+		pe_err("data is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	mac_ctx = session->mac_ctx;
+	if (!mac_ctx) {
+		pe_err("mac_ctx is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	lim_set_channel(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;
+}
+
 void lim_send_start_bss_confirm(struct mac_context *mac_ctx,
 				tLimMlmStartCnf *start_cnf)
 {

+ 14 - 0
core/mac/src/pe/lim/lim_utils.h

@@ -1682,6 +1682,20 @@ QDF_STATUS lim_ap_mlme_vdev_restart_send(struct vdev_mlme_obj *vdev_mlme,
 QDF_STATUS lim_ap_mlme_vdev_start_req_failed(struct vdev_mlme_obj *vdev_mlme,
 					     uint16_t data_len, void *data);
 
+/**
+ * lim_mon_mlme_vdev_start_send() - Invokes VDEV start operation
+ * @vdev_mlme_obj:  VDEV MLME comp object
+ * @data_len: data size
+ * @data: event data
+ *
+ * API invokes VDEV start operation
+ *
+ * Return: SUCCESS on successful completion of start operation
+ *         FAILURE, if it fails due to any
+ */
+QDF_STATUS lim_mon_mlme_vdev_start_send(struct vdev_mlme_obj *vdev_mlme,
+					uint16_t data_len, void *event);
+
 #ifdef CRYPTO_SET_KEY_CONVERGED
 static inline bool lim_is_set_key_req_converged(void)
 {

+ 65 - 9
core/wma/inc/wma_api.h

@@ -452,7 +452,7 @@ bool wma_get_hidden_ssid_restart_in_progress(struct wma_txrx_node *iface);
 bool wma_get_channel_switch_in_progress(struct wma_txrx_node *iface);
 
 /**
- * wma_sta_mlme_vdev_start_continue - VDEV start response handling
+ * wma_sta_mlme_vdev_start_continue() - VDEV start response handling
  * @vdev_mlme_obj:  VDEV MLME comp object
  * @data_len: data size
  * @data: event data
@@ -466,7 +466,7 @@ QDF_STATUS wma_sta_mlme_vdev_start_continue(struct vdev_mlme_obj *vdev_mlme,
 					    uint16_t data_len, void *data);
 
 /**
- * wma_sta_mlme_vdev_roam_notify - VDEV roam notify handling
+ * wma_sta_mlme_vdev_roam_notify() - VDEV roam notify handling
  * @vdev_mlme_obj:  VDEV MLME comp object
  * @data_len: data size
  * @data: event data
@@ -480,7 +480,7 @@ QDF_STATUS wma_sta_mlme_vdev_roam_notify(struct vdev_mlme_obj *vdev_mlme,
 					 uint16_t data_len, void *data);
 
 /**
- * wma_ap_mlme_vdev_start_continue - VDEV start response handling
+ * wma_ap_mlme_vdev_start_continue() - VDEV start response handling
  * @vdev_mlme_obj:  VDEV MLME comp object
  * @data_len: data size
  * @data: event data
@@ -494,7 +494,7 @@ QDF_STATUS wma_ap_mlme_vdev_start_continue(struct vdev_mlme_obj *vdev_mlme,
 					   uint16_t data_len, void *data);
 
 /**
- * wma_sta_vdev_up_send - Send VDEV UP command
+ * wma_sta_vdev_up_send() - Send VDEV UP command
  * @vdev_mlme_obj:  VDEV MLME comp object
  * @data_len: data size
  * @data: event data
@@ -508,7 +508,7 @@ QDF_STATUS wma_sta_vdev_up_send(struct vdev_mlme_obj *vdev_mlme,
 				uint16_t data_len, void *data);
 
 /**
- * wma_mlme_vdev_stop_continue - VDEV stop response handling
+ * wma_mlme_vdev_stop_continue() - VDEV stop response handling
  * @vdev_mlme_obj:  VDEV MLME comp object
  * @data_len: data size
  * @data: event data
@@ -522,7 +522,7 @@ QDF_STATUS wma_mlme_vdev_stop_continue(struct vdev_mlme_obj *vdev_mlme,
 				       uint16_t data_len, void *data);
 
 /**
- * wma_ap_mlme_vdev_down_send - VDEV down operation
+ * wma_ap_mlme_vdev_down_send() - VDEV down operation
  * @vdev_mlme_obj:  VDEV MLME comp object
  * @data_len: data size
  * @data: event data
@@ -536,7 +536,7 @@ QDF_STATUS wma_ap_mlme_vdev_down_send(struct vdev_mlme_obj *vdev_mlme,
 				      uint16_t data_len, void *data);
 
 /**
- * wma_mlme_vdev_notify_down_complete - VDEV init state transition
+ * wma_mlme_vdev_notify_down_complete() - VDEV init state transition
  * notification
  * @vdev_mlme_obj:  VDEV MLME comp object
  * @data_len: data size
@@ -552,7 +552,7 @@ wma_mlme_vdev_notify_down_complete(struct vdev_mlme_obj *vdev_mlme,
 				   uint16_t data_len, void *data);
 
 /**
- * wma_ap_mlme_vdev_stop_start_send - handle vdev stop during start req
+ * wma_ap_mlme_vdev_stop_start_send() - handle vdev stop during start req
  * @vdev_mlme_obj:  VDEV MLME comp object
  * @type: restart req or start req
  * @data_len: data size
@@ -567,7 +567,7 @@ QDF_STATUS wma_ap_mlme_vdev_stop_start_send(struct vdev_mlme_obj *vdev_mlme,
 					    uint16_t data_len, void *data);
 
 /**
- * wma_sta_mlme_vdev_down_send - VDEV down operation
+ * wma_sta_mlme_vdev_down_send() - VDEV down operation
  * @vdev_mlme_obj:  VDEV MLME comp object
  * @data_len: data size
  * @data: event data
@@ -580,6 +580,62 @@ QDF_STATUS wma_ap_mlme_vdev_stop_start_send(struct vdev_mlme_obj *vdev_mlme,
 QDF_STATUS wma_sta_mlme_vdev_down_send(struct vdev_mlme_obj *vdev_mlme,
 				       uint16_t data_len, void *data);
 
+/**
+ * wma_mon_mlme_vdev_start_continue() - VDEV start response handling
+ * @vdev_mlme_obj:  VDEV MLME comp object
+ * @data_len: data size
+ * @data: event data
+ *
+ * API invokes VDEV start response actions
+ *
+ * Return: SUCCESS on successful completion of start response operation
+ *         FAILURE, if it fails due to any
+ */
+QDF_STATUS wma_mon_mlme_vdev_start_continue(struct vdev_mlme_obj *vdev_mlme,
+					    uint16_t data_len, void *data);
+
+/**
+ * wma_mon_mlme_vdev_up_send() - Send VDEV UP command
+ * @vdev_mlme_obj:  VDEV MLME comp object
+ * @data_len: data size
+ * @data: event data
+ *
+ * API invokes VDEV UP Command
+ *
+ * Return: SUCCESS on successful completion of start response operation
+ *         FAILURE, if it fails due to any
+ */
+QDF_STATUS wma_mon_mlme_vdev_up_send(struct vdev_mlme_obj *vdev_mlme,
+				     uint16_t data_len, void *data);
+
+/**
+ * wma_mon_mlme_vdev_stop_send() - VDEV stop operation
+ * @vdev_mlme_obj:  VDEV MLME comp object
+ * @data_len: data size
+ * @data: event data
+ *
+ * API invokes VDEV stop operation
+ *
+ * Return: SUCCESS on successful completion of VDEV stop operation
+ *         FAILURE, if it fails due to any
+ */
+QDF_STATUS wma_mon_mlme_vdev_stop_send(struct vdev_mlme_obj *vdev_mlme,
+				       uint16_t data_len, void *data);
+
+/**
+ * wma_mon_mlme_vdev_down_send() - VDEV down operation
+ * @vdev_mlme_obj:  VDEV MLME comp object
+ * @data_len: data size
+ * @data: event data
+ *
+ * API invokes VDEV down operation
+ *
+ * Return: SUCCESS on successful completion of VDEV down operation
+ *         FAILURE, if it fails due to any
+ */
+QDF_STATUS wma_mon_mlme_vdev_down_send(struct vdev_mlme_obj *vdev_mlme,
+				       uint16_t data_len, void *data);
+
 #ifdef FEATURE_WLM_STATS
 /**
  * typedef wma_wlm_stats_cb() - Callback function for WLM stats

+ 10 - 8
core/wma/src/wma_dev_if.c

@@ -735,14 +735,13 @@ wma_release_vdev_ref(struct wma_txrx_node *iface)
 static void wma_handle_monitor_mode_vdev_detach(tp_wma_handle wma,
 						uint8_t vdev_id)
 {
-	if (wma_send_vdev_stop_to_fw(wma, vdev_id)) {
-		WMA_LOGE("%s: %d Failed to send vdev stop", __func__, __LINE__);
-		wma_remove_vdev_req(wma, vdev_id,
-				    WMA_TARGET_REQ_TYPE_VDEV_STOP);
-	}
+	struct wma_txrx_node *iface;
 
-	if (wma_send_vdev_down_to_fw(wma, vdev_id) != QDF_STATUS_SUCCESS)
-		WMA_LOGE("Failed to send vdev down cmd: vdev %d", vdev_id);
+	iface = &wma->interfaces[vdev_id];
+	wlan_vdev_mlme_sm_deliver_evt(iface->vdev,
+				      WLAN_VDEV_SM_EV_DOWN,
+				      0, NULL);
+	iface->vdev_active = false;
 }
 
 static QDF_STATUS wma_handle_vdev_detach(tp_wma_handle wma_handle,
@@ -1037,8 +1036,10 @@ QDF_STATUS wma_vdev_detach(tp_wma_handle wma_handle,
 				pdel_sta_self_req_param, generateRsp);
 	}
 
-	if (QDF_IS_STATUS_SUCCESS(status))
+	if (QDF_IS_STATUS_SUCCESS(status) &&
+	    iface->type != WMI_VDEV_TYPE_MONITOR)
 		iface->vdev_active = false;
+
 	return status;
 
 send_fail_rsp:
@@ -2636,6 +2637,7 @@ wma_handle_vdev_stop_rsp(tp_wma_handle wma,
 	struct wma_txrx_node *iface;
 
 	iface = &wma->interfaces[resp_event->vdev_id];
+
 	return wlan_vdev_mlme_sm_deliver_evt(iface->vdev,
 					     WLAN_VDEV_SM_EV_STOP_RESP,
 					     sizeof(*resp_event), resp_event);

+ 7 - 9
core/wma/src/wma_scan_roam.c

@@ -76,6 +76,7 @@
 #include "wlan_mlme_api.h"
 #include <wlan_mlme_main.h>
 #include <wlan_crypto_global_api.h>
+#include <cdp_txrx_mon.h>
 
 #ifdef FEATURE_WLAN_EXTSCAN
 #define WMA_EXTSCAN_CYCLE_WAKE_LOCK_DURATION WAKELOCK_DURATION_RECOMMENDED
@@ -3517,12 +3518,6 @@ void wma_set_channel(tp_wma_handle wma, tpSwitchChannelParams params)
 		}
 	}
 
-	if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam() &&
-	    wma_is_vdev_up(vdev_id)) {
-		WMA_LOGD("%s: setting channel switch to true for vdev_id:%d",
-			 __func__, req.vdev_id);
-	}
-
 	msg = wma_fill_vdev_req(wma, req.vdev_id, WMA_CHNL_SWITCH_REQ,
 			WMA_TARGET_REQ_TYPE_VDEV_START, params,
 			WMA_VDEV_START_REQUEST_TIMEOUT);
@@ -3543,9 +3538,12 @@ void wma_set_channel(tp_wma_handle wma, tpSwitchChannelParams params)
 		goto send_resp;
 	}
 
-	/* This is temporary, should be removed */
-	if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam())
-		ol_htt_mon_note_chan(pdev, req.chan);
+	/*
+	 * Record monitor mode channel here in case HW
+	 * indicate RX PPDU TLV with invalid channel number.
+	 */
+	if (intr[vdev_id].type == WMI_VDEV_TYPE_MONITOR)
+		cdp_record_monitor_chan_num(soc, pdev, req.chan);
 
 	return;
 send_resp:

+ 97 - 0
core/wma/src/wma_utils.c

@@ -5064,6 +5064,103 @@ QDF_STATUS wma_ap_mlme_vdev_stop_start_send(struct vdev_mlme_obj *vdev_mlme,
 	return wma_vdev_send_start_resp(wma, bss_params);
 }
 
+QDF_STATUS wma_mon_mlme_vdev_start_continue(struct vdev_mlme_obj *vdev_mlme,
+					    uint16_t data_len, void *data)
+{
+	if (mlme_is_chan_switch_in_progress(vdev_mlme->vdev))
+		mlme_set_chan_switch_in_progress(vdev_mlme->vdev, false);
+
+	wlan_vdev_mlme_sm_deliver_evt(vdev_mlme->vdev,
+				      WLAN_VDEV_SM_EV_START_SUCCESS,
+				      data_len,
+				      data);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS wma_mon_mlme_vdev_up_send(struct vdev_mlme_obj *vdev_mlme,
+				     uint16_t data_len, void *data)
+{
+	struct vdev_up_params param;
+	uint8_t vdev_id;
+	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
+	QDF_STATUS status;
+	struct wma_txrx_node *iface;
+
+	if (!wma) {
+		WMA_LOGE("%s wma handle is NULL", __func__);
+		return QDF_STATUS_E_INVAL;
+	}
+	vdev_id = wlan_vdev_get_id(vdev_mlme->vdev);
+	param.vdev_id = vdev_id;
+	iface = &wma->interfaces[vdev_id];
+
+	status = wma_send_vdev_up_to_fw(wma, &param, iface->bssid);
+
+	if (QDF_IS_STATUS_ERROR(status))
+		WMA_LOGE("%s: Failed to send vdev up cmd: vdev %d bssid %pM",
+			 __func__, vdev_id, iface->bssid);
+
+	wma_send_msg_high_priority(wma, WMA_SWITCH_CHANNEL_RSP,
+				   data, 0);
+
+	return status;
+}
+
+QDF_STATUS wma_mon_mlme_vdev_stop_send(struct vdev_mlme_obj *vdev_mlme,
+				       uint16_t data_len, void *data)
+{
+	uint8_t vdev_id;
+	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
+	QDF_STATUS status;
+
+	if (!wma) {
+		WMA_LOGE("%s wma handle is NULL", __func__);
+		return QDF_STATUS_E_INVAL;
+	}
+	vdev_id = wlan_vdev_get_id(vdev_mlme->vdev);
+
+	status = wma_send_vdev_stop_to_fw(wma, vdev_id);
+
+	if (QDF_IS_STATUS_ERROR(status))
+		WMA_LOGE("%s: Failed to send vdev stop cmd: vdev %d",
+			 __func__, vdev_id);
+
+	wlan_vdev_mlme_sm_deliver_evt(vdev_mlme->vdev,
+				      WLAN_VDEV_SM_EV_MLME_DOWN_REQ,
+				      0,
+				      NULL);
+
+	return status;
+}
+
+QDF_STATUS wma_mon_mlme_vdev_down_send(struct vdev_mlme_obj *vdev_mlme,
+				       uint16_t data_len, void *data)
+{
+	uint8_t vdev_id;
+	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
+	QDF_STATUS status;
+
+	if (!wma) {
+		WMA_LOGE("%s wma handle is NULL", __func__);
+		return QDF_STATUS_E_INVAL;
+	}
+	vdev_id = wlan_vdev_get_id(vdev_mlme->vdev);
+
+	status = wma_send_vdev_down_to_fw(wma, vdev_id);
+
+	if (QDF_IS_STATUS_ERROR(status))
+		WMA_LOGE("%s: Failed to send vdev down cmd: vdev %d",
+			 __func__, vdev_id);
+
+	wlan_vdev_mlme_sm_deliver_evt(vdev_mlme->vdev,
+				      WLAN_VDEV_SM_EV_DOWN_COMPLETE,
+				      0,
+				      NULL);
+
+	return status;
+}
+
 #ifdef FEATURE_WLM_STATS
 int wma_wlm_stats_req(int vdev_id, uint32_t bitmask, uint32_t max_size,
 		      wma_wlm_stats_cb cb, void *cookie)