Prechádzať zdrojové kódy

qcacld-3.0: dynamic channel switch implementation

When dynamic channel switch is enabled, trigger acs and switch to best
channel if wlan interference is found in 5g mac.

Change-Id: I56661f5c42a233a0dc0a6400d75cb8f5c0019706
CRs-Fixed: 2599176
Huashan Qu 5 rokov pred
rodič
commit
1b3be2948e

+ 30 - 1
components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h

@@ -72,6 +72,7 @@ typedef const enum policy_mgr_conc_next_action
  * @CSA_REASON_LTE_COEX: LTE coex.
  * @CSA_REASON_CONCURRENT_NAN_EVENT: NAN concurrency.
  * @CSA_REASON_BAND_RESTRICTED: band disabled or re-enabled
+ * @CSA_REASON_DCS: DCS
  *
  */
 enum sap_csa_reason_code {
@@ -84,7 +85,8 @@ enum sap_csa_reason_code {
 	CSA_REASON_UNSAFE_CHANNEL,
 	CSA_REASON_LTE_COEX,
 	CSA_REASON_CONCURRENT_NAN_EVENT,
-	CSA_REASON_BAND_RESTRICTED
+	CSA_REASON_BAND_RESTRICTED,
+	CSA_REASON_DCS,
 };
 
 /**
@@ -1878,6 +1880,33 @@ QDF_STATUS policy_mgr_get_chan_by_session_id(struct wlan_objmgr_psoc *psoc,
 					     uint8_t session_id,
 					     uint32_t *ch_freq);
 
+/**
+ * policy_mgr_get_sap_go_count_on_mac() - Provide the count of sap and go on
+ * given mac
+ * @psoc: PSOC object information
+ * @list: To provide the vdev_id of the satisfied sap and go (optional)
+ * @mac_id: MAC ID
+ *
+ * This function provides the count of the matched sap and go
+ *
+ * Return: count of the satisfied sap and go
+ */
+uint32_t policy_mgr_get_sap_go_count_on_mac(struct wlan_objmgr_psoc *psoc,
+					    uint32_t *list, uint8_t mac_id);
+
+/**
+ * policy_mgr_is_sta_gc_active_on_mac() - Is there active sta/gc for a
+ * given mac id
+ * @psoc: PSOC object information
+ * @mac_id: MAC ID
+ *
+ * Checks if there is active sta/gc for a given mac id
+ *
+ * Return: true if there is active sta/gc for a given mac id, false otherwise
+ */
+bool policy_mgr_is_sta_gc_active_on_mac(struct wlan_objmgr_psoc *psoc,
+					uint8_t mac_id);
+
 /**
  * policy_mgr_get_mac_id_by_session_id() - Get MAC ID for a given session ID
  * @psoc: PSOC object information

+ 72 - 1
components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c

@@ -2564,7 +2564,8 @@ policy_mgr_allow_concurrency_csa(struct wlan_objmgr_psoc *psoc,
 	 */
 	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
 
-	if (forced && reason == CSA_REASON_UNSAFE_CHANNEL)
+	if (forced && (reason == CSA_REASON_UNSAFE_CHANNEL ||
+		       reason == CSA_REASON_DCS))
 		policy_mgr_store_and_del_conn_info_by_chan_and_mode(
 			psoc, old_ch_freq, mode, info, &num_cxn_del);
 	else
@@ -3065,6 +3066,44 @@ bool policy_mgr_is_multiple_active_sta_sessions(struct wlan_objmgr_psoc *psoc)
 		psoc, PM_STA_MODE, NULL) > 1;
 }
 
+bool policy_mgr_is_sta_gc_active_on_mac(struct wlan_objmgr_psoc *psoc,
+					uint8_t mac_id)
+{
+	uint32_t list[MAX_NUMBER_OF_CONC_CONNECTIONS];
+	uint32_t index, count;
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("Invalid Context");
+		return false;
+	}
+
+	count = policy_mgr_mode_specific_connection_count(
+		psoc, PM_STA_MODE, list);
+	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
+	for (index = 0; index < count; index++) {
+		if (mac_id == pm_conc_connection_list[list[index]].mac) {
+			qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
+			return true;
+		}
+	}
+	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
+
+	count = policy_mgr_mode_specific_connection_count(
+		psoc, PM_P2P_CLIENT_MODE, list);
+	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
+	for (index = 0; index < count; index++) {
+		if (mac_id == pm_conc_connection_list[list[index]].mac) {
+			qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
+			return true;
+		}
+	}
+	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
+
+	return false;
+}
+
 /**
  * policy_mgr_is_sta_active_connection_exists() - Check if a STA
  * connection is active
@@ -3361,6 +3400,38 @@ QDF_STATUS policy_mgr_get_mac_id_by_session_id(struct wlan_objmgr_psoc *psoc,
 	return QDF_STATUS_E_FAILURE;
 }
 
+uint32_t policy_mgr_get_sap_go_count_on_mac(struct wlan_objmgr_psoc *psoc,
+					    uint32_t *list, uint8_t mac_id)
+{
+	uint32_t conn_index;
+	uint32_t count = 0;
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("Invalid Context");
+		return count;
+	}
+
+	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
+	for (conn_index = 0; conn_index < MAX_NUMBER_OF_CONC_CONNECTIONS;
+	     conn_index++) {
+		if (pm_conc_connection_list[conn_index].mac == mac_id &&
+		    pm_conc_connection_list[conn_index].in_use &&
+		    (pm_conc_connection_list[conn_index].mode == PM_SAP_MODE ||
+		     pm_conc_connection_list[conn_index].mode ==
+		     PM_P2P_GO_MODE)) {
+			if (list)
+				list[count] =
+				    pm_conc_connection_list[conn_index].vdev_id;
+			count++;
+		}
+	}
+	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
+
+	return count;
+}
+
 QDF_STATUS policy_mgr_get_mcc_session_id_on_mac(struct wlan_objmgr_psoc *psoc,
 					uint8_t mac_id, uint8_t session_id,
 					uint8_t *mcc_session_id)

+ 9 - 1
core/hdd/src/wlan_hdd_cfg80211.c

@@ -1950,6 +1950,9 @@ int wlan_hdd_cfg80211_start_acs(struct hdd_adapter *adapter)
 		if (status > 0) {
 			/*notify hostapd about channel override */
 			wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
+			wlansap_dcs_set_wlan_interference_mitigation_on_band(
+						WLAN_HDD_GET_SAP_CTX_PTR(adapter),
+						sap_config);
 			return 0;
 		}
 	}
@@ -2001,6 +2004,8 @@ int wlan_hdd_cfg80211_start_acs(struct hdd_adapter *adapter)
 	if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
 		sap_config->acs_cfg.acs_mode = true;
 
+	qdf_atomic_set(&adapter->session.ap.acs_in_progress, 1);
+
 	return 0;
 }
 
@@ -3141,6 +3146,9 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
 				sap_config->acs_cfg.vht_seg1_center_ch_freq;
 			/*notify hostapd about channel override */
 			wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
+			wlansap_dcs_set_wlan_interference_mitigation_on_band(
+					WLAN_HDD_GET_SAP_CTX_PTR(adapter),
+					sap_config);
 			ret = 0;
 			goto out;
 		}
@@ -3358,7 +3366,7 @@ static int hdd_get_acs_evt_data_len(void)
  * @pri_channel: SAP ACS procedure selected Primary channel
  * @sec_channel: SAP ACS procedure selected secondary channel
  *
- * This is a callback function from SAP module on ACS procedure is completed.
+ * This is a callback function on ACS procedure is completed.
  * This function send the ACS selected channel information to hostapd
  *
  * Return: None

+ 187 - 0
core/hdd/src/wlan_hdd_dcs.c

@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: wlan_hdd_dcs.c
+ *
+ * DCS implementation.
+ *
+ */
+
+#include <wlan_hdd_hostapd.h>
+#include <wlan_hdd_dcs.h>
+#include <wlan_hdd_includes.h>
+#include <wlan_dcs_ucfg_api.h>
+/**
+ * hdd_dcs_cb() - hdd dcs specific callback
+ * @psoc: psoc
+ * @mac_id: mac_id
+ * @interference_type: wlan or continuous wave interference type
+ * @arg: List of arguments
+ *
+ * This callback is registered with dcs component to start acs operation
+ *
+ * Return: None
+ */
+static void hdd_dcs_cb(struct wlan_objmgr_psoc *psoc, uint8_t mac_id,
+		       uint8_t interference_type, void *arg)
+{
+	struct hdd_context *hdd_ctx = (struct hdd_context *)arg;
+	struct hdd_adapter *adapter;
+	uint32_t count;
+	uint32_t list[MAX_NUMBER_OF_CONC_CONNECTIONS];
+	uint32_t index;
+
+	/*
+	 * so far CAP_DCS_CWIM interference mitigation is not supported
+	 */
+	if (interference_type == CAP_DCS_CWIM) {
+		hdd_debug("CW interference mitigation is not supported");
+		return;
+	}
+
+	if (policy_mgr_is_force_scc(psoc) &&
+	    policy_mgr_is_sta_gc_active_on_mac(psoc, mac_id)) {
+		hdd_debug("force scc %d, mac id %d sta gc count %d",
+			  policy_mgr_is_force_scc(psoc), mac_id,
+			  policy_mgr_is_sta_gc_active_on_mac(psoc, mac_id));
+		return;
+	}
+
+	count = policy_mgr_get_sap_go_count_on_mac(psoc, list, mac_id);
+	for (index = 0; index < count; index++) {
+		adapter = hdd_get_adapter_by_vdev(hdd_ctx, list[index]);
+		if (wlansap_dcs_is_wlan_interference_mitigation_enabled(
+			WLAN_HDD_GET_SAP_CTX_PTR(adapter))) {
+			hdd_debug("DCS triggers ACS on vdev_id=%u, mac_id=%u",
+				  list[index], mac_id);
+			wlan_hdd_cfg80211_start_acs(adapter);
+			return;
+		}
+	}
+}
+
+void hdd_dcs_register_cb(struct hdd_context *hdd_ctx)
+{
+	ucfg_dcs_register_cb(hdd_ctx->psoc, hdd_dcs_cb, hdd_ctx);
+}
+
+void hdd_dcs_hostapd_set_chan(struct hdd_context *hdd_ctx,
+			      uint8_t vdev_id,
+			      qdf_freq_t dcs_ch_freq)
+{
+	QDF_STATUS status;
+	uint8_t mac_id;
+	uint32_t list[MAX_NUMBER_OF_CONC_CONNECTIONS];
+	uint32_t conn_index, count;
+	struct hdd_adapter *adapter;
+	uint32_t dcs_ch = wlan_reg_freq_to_chan(hdd_ctx->pdev, dcs_ch_freq);
+
+	status = policy_mgr_get_mac_id_by_session_id(hdd_ctx->psoc, vdev_id,
+						     &mac_id);
+
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("get mac id failed");
+		return;
+	}
+	count = policy_mgr_get_sap_go_count_on_mac(hdd_ctx->psoc, list, mac_id);
+
+	/*
+	 * Dcs can only be enabled after all vdev finish csa.
+	 * Set vdev starting for every vdev before doing csa.
+	 * The CSA triggered by DCS will be done in serial.
+	 */
+	for (conn_index = 0; conn_index < count; conn_index++) {
+		adapter = hdd_get_adapter_by_vdev(hdd_ctx, list[conn_index]);
+
+		if (adapter->session.ap.operating_chan_freq != dcs_ch_freq)
+			wlansap_dcs_set_vdev_starting(
+				WLAN_HDD_GET_SAP_CTX_PTR(adapter), true);
+		else
+			wlansap_dcs_set_vdev_starting(
+				WLAN_HDD_GET_SAP_CTX_PTR(adapter), false);
+	}
+	for (conn_index = 0; conn_index < count; conn_index++) {
+		adapter = hdd_get_adapter_by_vdev(hdd_ctx, list[conn_index]);
+
+		if (adapter->session.ap.operating_chan_freq != dcs_ch_freq) {
+			hdd_ctx->acs_policy.acs_chan_freq = AUTO_CHANNEL_SELECT;
+			hdd_debug("dcs triggers old ch:%d new ch:%d",
+				  adapter->session.ap.operating_chan_freq,
+				  dcs_ch_freq);
+			wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc,
+						    adapter->vdev_id,
+						    CSA_REASON_DCS);
+			hdd_switch_sap_channel(adapter, dcs_ch, true);
+
+			return;
+		}
+	}
+}
+
+/**
+ * hdd_dcs_hostapd_enable_wlan_interference_mitigation() - enable wlan
+ * interference mitigation
+ * @hdd_ctx: hdd ctx
+ * @vdev_id: vdev id
+ *
+ * This function is used to enable wlan interference mitigation through
+ * send dcs command.
+ *
+ * Return: None
+ */
+static void hdd_dcs_hostapd_enable_wlan_interference_mitigation(
+					struct hdd_context *hdd_ctx,
+					uint8_t vdev_id)
+{
+	QDF_STATUS status;
+	uint8_t mac_id;
+	struct hdd_adapter *adapter;
+
+	status = policy_mgr_get_mac_id_by_session_id(hdd_ctx->psoc, vdev_id,
+						     &mac_id);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("get mac id failed");
+		return;
+	}
+	adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
+
+	if (wlansap_dcs_is_wlan_interference_mitigation_enabled(
+			WLAN_HDD_GET_SAP_CTX_PTR(adapter)) &&
+	    wlan_reg_is_5ghz_ch_freq(adapter->session.ap.operating_chan_freq))
+		ucfg_config_dcs_enable(hdd_ctx->psoc, mac_id, CAP_DCS_WLANIM);
+	ucfg_wlan_dcs_cmd(hdd_ctx->psoc, mac_id, true);
+}
+
+void hdd_dcs_chan_select_complete(struct hdd_adapter *adapter)
+{
+	qdf_freq_t dcs_freq;
+	struct hdd_context *hdd_ctx;
+
+	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+	if (!hdd_ctx) {
+		hdd_err("Invalid HDD context pointer");
+		return;
+	}
+
+	dcs_freq = wlansap_dcs_get_freq(WLAN_HDD_GET_SAP_CTX_PTR(adapter));
+	if (dcs_freq && dcs_freq != adapter->session.ap.operating_chan_freq)
+		hdd_dcs_hostapd_set_chan(hdd_ctx, adapter->vdev_id, dcs_freq);
+	else
+		hdd_dcs_hostapd_enable_wlan_interference_mitigation(
+							hdd_ctx,
+							adapter->vdev_id);
+}

+ 81 - 0
core/hdd/src/wlan_hdd_dcs.h

@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: wlan_hdd_dcs.h
+ *
+ * WLAN Host Device Driver dcs related implementation
+ *
+ */
+
+#if !defined(WLAN_HDD_DCS_H)
+#define WLAN_HDD_DCS_H
+
+#include <wlan_hdd_main.h>
+
+#ifdef DCS_INTERFERENCE_DETECTION
+/**
+ * hdd_dcs_register_cb() - register dcs callback
+ * @hdd_ctx: hdd ctx
+ *
+ * This function is used to register the HDD callbacks with dcs component
+ *
+ * Return: None
+ */
+void hdd_dcs_register_cb(struct hdd_context *hdd_ctx);
+
+/**
+ * hdd_dcs_hostapd_set_chan() - switch sap channel to dcs channel
+ * @hdd_ctx: hdd ctx
+ * @vdev_id: vdev id
+ * @dcs_ch_freq: dcs channel freq
+ *
+ * This function is used to switch sap channel to dcs channel using (E)CSA
+ *
+ * Return: None
+ */
+void hdd_dcs_hostapd_set_chan(struct hdd_context *hdd_ctx,
+			      uint8_t vdev_id,
+			      qdf_freq_t dcs_ch_freq);
+
+/**
+ * hdd_dcs_chan_select_complete() - dcs triggered channel select
+ * complete handling
+ * @adapter: hdd adapter pointer
+ *
+ * When dcs triggered channel select complete, this function is used to do
+ * switch sap to new dcs channel or just to enable interference mitigation
+ *
+ * Return: None
+ */
+void hdd_dcs_chan_select_complete(struct hdd_adapter *adapter);
+#else
+static inline void hdd_dcs_register_cb(struct hdd_context *hdd_ctx)
+{
+}
+
+static inline void hdd_dcs_hostapd_set_chan(struct hdd_context *hdd_ctx,
+					    uint8_t vdev_id,
+					    qdf_freq_t dcs_ch_freq)
+{
+}
+
+static inline void hdd_dcs_chan_select_complete(struct hdd_adapter *adapter)
+{
+}
+#endif
+
+#endif /* end #if !defined(WLAN_HDD_DCS_H) */

+ 36 - 5
core/hdd/src/wlan_hdd_hostapd.c

@@ -93,6 +93,7 @@
 #include <wlan_reg_services_api.h>
 #include "wlan_hdd_sta_info.h"
 #include "ftm_time_sync_ucfg_api.h"
+#include <wlan_hdd_dcs.h>
 
 #define ACS_SCAN_EXPIRY_TIMEOUT_S 4
 
@@ -2586,7 +2587,15 @@ QDF_STATUS hdd_hostapd_sap_event_cb(struct sap_event *sap_event,
 			      ap_ctx->sap_config.acs_cfg.pri_ch_freq,
 			      ap_ctx->sap_config.acs_cfg.ch_width);
 
-		wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
+		if (qdf_atomic_read(&adapter->session.ap.acs_in_progress) &&
+		    test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
+			hdd_dcs_chan_select_complete(adapter);
+		} else {
+			wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
+			wlansap_dcs_set_wlan_interference_mitigation_on_band(
+					WLAN_HDD_GET_SAP_CTX_PTR(adapter),
+					&ap_ctx->sap_config);
+		}
 
 		return QDF_STATUS_SUCCESS;
 	case eSAP_ECSA_CHANGE_CHAN_IND:
@@ -2630,6 +2639,11 @@ QDF_STATUS hdd_hostapd_sap_event_cb(struct sap_event *sap_event,
 		if (ap_ctx->sap_context->csa_reason ==
 		    CSA_REASON_UNSAFE_CHANNEL)
 			hdd_unsafe_channel_restart_sap(hdd_ctx);
+		else if (ap_ctx->sap_context->csa_reason == CSA_REASON_DCS)
+			hdd_dcs_hostapd_set_chan(
+				hdd_ctx, adapter->vdev_id,
+				adapter->session.ap.operating_chan_freq);
+
 		return QDF_STATUS_SUCCESS;
 
 	default:
@@ -2883,6 +2897,7 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_chan_freq,
 	uint8_t scc_on_lte_coex = 0;
 	bool is_p2p_go_session = false;
 	struct wlan_objmgr_vdev *vdev;
+	bool strict;
 
 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
 	ret = wlan_hdd_validate_context(hdd_ctx);
@@ -3004,11 +3019,20 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_chan_freq,
 		is_p2p_go_session = true;
 	hdd_objmgr_put_vdev(vdev);
 
+	strict = is_p2p_go_session;
+	/*
+	 * scc_on_lte_coex should be considered only when csa is triggered
+	 * by unsafe channel.
+	 */
+	if (sap_ctx->csa_reason == CSA_REASON_UNSAFE_CHANNEL)
+		strict = strict || (forced && !scc_on_lte_coex);
+	else
+		strict = strict || forced;
 	status = wlansap_set_channel_change_with_csa(
 		WLAN_HDD_GET_SAP_CTX_PTR(adapter),
 		target_chan_freq,
 		target_bw,
-		(forced && !scc_on_lte_coex) || is_p2p_go_session);
+		strict);
 
 	if (QDF_STATUS_SUCCESS != status) {
 		hdd_err("SAP set channel failed for channel freq: %d, bw: %d",
@@ -3372,7 +3396,7 @@ QDF_STATUS hdd_init_ap_mode(struct hdd_adapter *adapter, bool reinit)
 	struct hdd_hostapd_state *phostapdBuf;
 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
-	struct sap_context *sap_context = NULL;
+	struct sap_context *sap_ctx;
 	int ret;
 	enum dfs_mode acs_dfs_mode;
 	bool acs_with_more_param = 0;
@@ -3384,8 +3408,8 @@ QDF_STATUS hdd_init_ap_mode(struct hdd_adapter *adapter, bool reinit)
 	hdd_debug("SSR in progress: %d", reinit);
 	qdf_atomic_init(&adapter->session.ap.acs_in_progress);
 
-	sap_context = hdd_hostapd_init_sap_session(adapter, reinit);
-	if (!sap_context) {
+	sap_ctx = hdd_hostapd_init_sap_session(adapter, reinit);
+	if (!sap_ctx) {
 		hdd_err("Invalid sap_ctx");
 		goto error_release_vdev;
 	}
@@ -3474,6 +3498,9 @@ QDF_STATUS hdd_init_ap_mode(struct hdd_adapter *adapter, bool reinit)
 
 	if (!reinit) {
 		adapter->session.ap.sap_config.acs_cfg.acs_mode = false;
+		wlansap_dcs_set_vdev_wlan_interference_mitigation(sap_ctx,
+								  false);
+		wlansap_dcs_set_vdev_starting(sap_ctx, false);
 		qdf_mem_zero(&adapter->session.ap.sap_config.acs_cfg,
 			     sizeof(struct sap_acs_cfg));
 	}
@@ -5746,6 +5773,7 @@ static int __wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy,
 	tSirUpdateIE update_ie;
 	int ret;
 	mac_handle_t mac_handle;
+	struct sap_context *sap_ctx;
 
 	hdd_enter();
 
@@ -5811,6 +5839,9 @@ static int __wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy,
 
 	cds_flush_work(&adapter->sap_stop_bss_work);
 	adapter->session.ap.sap_config.acs_cfg.acs_mode = false;
+	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(adapter);
+	wlansap_dcs_set_vdev_wlan_interference_mitigation(sap_ctx, false);
+	wlansap_dcs_set_vdev_starting(sap_ctx, false);
 	qdf_atomic_set(&adapter->session.ap.acs_in_progress, 0);
 	hdd_debug("Disabling queues");
 	wlan_hdd_netif_queue_control(adapter,

+ 3 - 0
core/hdd/src/wlan_hdd_main.c

@@ -180,6 +180,7 @@
 #include <wlan_hdd_sar_limits.h>
 #include "cfg_nan_api.h"
 #include "wlan_hdd_btc_chain_mode.h"
+#include <wlan_hdd_dcs.h>
 
 #ifdef MODULE
 #define WLAN_MODULE_NAME  module_name(THIS_MODULE)
@@ -342,6 +343,7 @@ static const struct category_info cinfo[MAX_SUPPORTED_CATEGORY] = {
 	[QDF_MODULE_ID_CMN_MLME] = {QDF_TRACE_LEVEL_ALL},
 	[QDF_MODULE_ID_NAN] = {QDF_TRACE_LEVEL_ALL},
 	[QDF_MODULE_ID_CP_STATS] = {QDF_TRACE_LEVEL_ALL},
+	[QDF_MODULE_ID_DCS] = {QDF_TRACE_LEVEL_ALL},
 	[QDF_MODULE_ID_INTEROP_ISSUES_AP] = {QDF_TRACE_LEVEL_ALL},
 	[QDF_MODULE_ID_BLACKLIST_MGR] = {QDF_TRACE_LEVEL_ALL},
 	[QDF_MODULE_ID_DIRECT_BUF_RX] = {QDF_TRACE_LEVEL_ALL},
@@ -13396,6 +13398,7 @@ int hdd_register_cb(struct hdd_context *hdd_ctx)
 					   hdd_lost_link_info_cb);
 
 	wlan_hdd_register_cp_stats_cb(hdd_ctx);
+	hdd_dcs_register_cb(hdd_ctx);
 
 	/* print error and not block the startup process */
 	if (!QDF_IS_STATUS_SUCCESS(status))

+ 137 - 0
core/sap/inc/sap_api.h

@@ -619,6 +619,19 @@ typedef struct sSapDfsInfo {
 	uint16_t reduced_beacon_interval;
 } tSapDfsInfo;
 
+#ifdef DCS_INTERFERENCE_DETECTION
+/**
+ * struct sap_dcs_info - record sap dcs information.
+ * @wlan_interference_mitigation_enable: wlan interference mitigation
+ *                                       is enabled per vdev.
+ * @is_vdev_starting: is vdev doing restart because of dcs.
+ */
+struct sap_dcs_info {
+	bool wlan_interference_mitigation_enable[WLAN_MAX_VDEVS];
+	bool is_vdev_starting[WLAN_MAX_VDEVS];
+};
+#endif
+
 struct sap_ctx_list {
 	void *sap_context;
 	enum QDF_OPMODE sapPersona;
@@ -633,6 +646,9 @@ typedef struct tagSapStruct {
 #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
 	bool acs_with_more_param;
 	bool enable_dfs_phy_error_logs;
+#ifdef DCS_INTERFERENCE_DETECTION
+	struct sap_dcs_info dcs_info;
+#endif
 } tSapStruct, *tpSapStruct;
 
 /**
@@ -1469,6 +1485,127 @@ wlansap_get_safe_channel_from_pcl_and_acs_range(struct sap_context *sap_ctx);
  */
 qdf_freq_t wlansap_get_chan_band_restrict(struct sap_context *sap_ctx);
 
+#ifdef DCS_INTERFERENCE_DETECTION
+/**
+ * wlansap_dcs_set_vdev_wlan_interference_mitigation() - set wlan
+ * interference mitigation enable information per vdev
+ * @sap_context: sap context
+ * @wlan_interference_mitigation_enable: wlan interference mitigation
+ *                                       enable or not
+ *
+ * This function is used to set whether wlan interference mitigation
+ * enable or not
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlansap_dcs_set_vdev_wlan_interference_mitigation(
+				struct sap_context *sap_context,
+				bool wlan_interference_mitigation_enable);
+
+/**
+ * wlansap_dcs_set_wlan_interference_mitigation_on_band() - set wlan
+ * interference mitigation enable information based on band information
+ * @sap_context: sap context
+ * @sap_cfg: sap config
+ *
+ * This function is used to set whether wlan interference mitigation
+ * enable or not based on band information
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlansap_dcs_set_wlan_interference_mitigation_on_band(
+					struct sap_context *sap_context,
+					struct sap_config *sap_cfg);
+
+/**
+ * wlansap_dcs_set_vdev_starting() - set vdev starting
+ * @sap_context: sap context
+ * @vdev_starting: vdev in starting states
+ *
+ * This function is used to set whether vdev starting or not
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlansap_dcs_set_vdev_starting(struct sap_context *sap_context,
+					 bool vdev_starting);
+
+/**
+ * wlansap_dcs_is_wlan_interference_mitigation_enabled() - get wlan interference
+ * mitigation enabled information
+ * @sap_context: sap context
+ *
+ * This function is used to get wlan interference mitigation enabled information
+ * with given sap
+ *
+ * Return: true if wlan interference mitigation is enabled with given sap
+ */
+bool wlansap_dcs_is_wlan_interference_mitigation_enabled(
+					struct sap_context *sap_context);
+
+/**
+ * wlansap_dcs_get_freq() - get dcs channel frequency
+ * @sap_context: sap context
+ *
+ * This function is used to get dcs channel frequency with give sap
+ *
+ * Return: sap dcs channel frequency
+ */
+qdf_freq_t wlansap_dcs_get_freq(struct sap_context *sap_context);
+#else
+static inline QDF_STATUS wlansap_dcs_set_vdev_wlan_interference_mitigation(
+				struct sap_context *sap_context,
+				bool wlan_interference_mitigation_enable)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline QDF_STATUS wlansap_dcs_set_wlan_interference_mitigation_on_band(
+						struct sap_context *sap_context,
+						struct sap_config *sap_cfg)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline QDF_STATUS wlansap_dcs_set_vdev_starting(
+	struct sap_context *sap_context, bool vdev_starting)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline bool wlansap_dcs_is_wlan_interference_mitigation_enabled(
+					struct sap_context *sap_context)
+{
+	return false;
+}
+
+static inline qdf_freq_t wlansap_dcs_get_freq(struct sap_context *sap_context)
+{
+	return 0;
+}
+#endif
+
+/**
+ * wlansap_dump_acs_ch_freq() - print acs channel frequency
+ * @sap_ctx: sap context
+ *
+ * This function is used to print acs channel frequecny
+ *
+ * Return: None
+ */
+void wlansap_dump_acs_ch_freq(struct sap_context *sap_context);
+
+/**
+ * wlansap_set_acs_ch_freq() - set acs channel frequency
+ * @sap_ctx: sap context
+ * @ch_freq: ch_freq to be set
+ *
+ * This function is used to set acs channel frequency
+ *
+ * Return: None
+ */
+void wlansap_set_acs_ch_freq(struct sap_context *sap_context,
+			     qdf_freq_t ch_freq);
+
 /**
  * sap_acquire_vdev_ref() - Increment reference count for vdev object
  * @psoc: Object Manager PSoC object

+ 4 - 2
core/sap/src/sap_api_link_cntl.c

@@ -334,7 +334,7 @@ QDF_STATUS wlansap_pre_start_bss_acs_scan_callback(mac_handle_t mac_handle,
 			scan_status);
 		oper_channel =
 			sap_select_default_oper_chan(sap_ctx->acs_cfg);
-		sap_ctx->chan_freq = oper_channel;
+		wlansap_set_acs_ch_freq(sap_ctx, oper_channel);
 		sap_ctx->acs_cfg->pri_ch_freq = oper_channel;
 		sap_config_acs_result(mac_handle, sap_ctx,
 				      sap_ctx->acs_cfg->ht_sec_ch_freq);
@@ -354,11 +354,13 @@ QDF_STATUS wlansap_pre_start_bss_acs_scan_callback(mac_handle_t mac_handle,
 		oper_channel = sap_select_default_oper_chan(sap_ctx->acs_cfg);
 	}
 
-	sap_ctx->chan_freq = oper_channel;
+	wlansap_set_acs_ch_freq(sap_ctx, oper_channel);
 	sap_ctx->acs_cfg->pri_ch_freq = oper_channel;
 	sap_config_acs_result(mac_handle, sap_ctx,
 			      sap_ctx->acs_cfg->ht_sec_ch_freq);
 
+	wlansap_dump_acs_ch_freq(sap_ctx);
+
 	sap_ctx->sap_state = eSAP_ACS_CHANNEL_SELECTED;
 	sap_ctx->sap_status = eSAP_STATUS_SUCCESS;
 close_session:

+ 10 - 5
core/sap/src/sap_fsm.c

@@ -846,6 +846,7 @@ QDF_STATUS sap_channel_sel(struct sap_context *sap_context)
 	uint8_t vdev_id;
 	uint32_t scan_id;
 	uint8_t *self_mac;
+	uint32_t default_op_freq;
 
 	mac_handle = cds_get_context(QDF_MODULE_ID_SME);
 	if (!mac_handle) {
@@ -861,7 +862,7 @@ QDF_STATUS sap_channel_sel(struct sap_context *sap_context)
 			  FL("Invalid MAC context"));
 		return QDF_STATUS_E_FAILURE;
 	}
-	if (sap_context->chan_freq)
+	if (sap_context->fsm_state != SAP_STARTED && sap_context->chan_freq)
 		return sap_validate_chan(sap_context, true, false);
 
 	if (policy_mgr_concurrent_beaconing_sessions_running(mac_ctx->psoc) ||
@@ -956,12 +957,13 @@ QDF_STATUS sap_channel_sel(struct sap_context *sap_context)
 			QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_HIGH,
 				  FL("SAP Configuring default ch, Ch_freq=%d"),
 				  sap_context->chan_freq);
-			sap_context->chan_freq = sap_select_default_oper_chan(
-					sap_context->acs_cfg);
+			default_op_freq = sap_select_default_oper_chan(
+						sap_context->acs_cfg);
+			wlansap_set_acs_ch_freq(sap_context, default_op_freq);
 
 			if (sap_context->freq_list) {
-				sap_context->chan_freq =
-					sap_context->freq_list[0];
+				wlansap_set_acs_ch_freq(
+					sap_context, sap_context->freq_list[0]);
 				qdf_mem_free(sap_context->freq_list);
 				sap_context->freq_list = NULL;
 				sap_context->num_of_channel = 0;
@@ -974,6 +976,7 @@ QDF_STATUS sap_channel_sel(struct sap_context *sap_context)
 			qdf_ret_status = QDF_STATUS_E_FAILURE;
 			goto release_vdev_ref;
 		} else {
+			wlansap_dump_acs_ch_freq(sap_context);
 			host_log_acs_scan_start(scan_id, vdev_id);
 		}
 #ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
@@ -990,6 +993,8 @@ QDF_STATUS sap_channel_sel(struct sap_context *sap_context)
 	}
 #endif
 
+	wlansap_dump_acs_ch_freq(sap_context);
+
 	qdf_ret_status = QDF_STATUS_SUCCESS;
 
 release_vdev_ref:

+ 4 - 0
core/sap/src/sap_internal.h

@@ -126,6 +126,10 @@ struct sap_context {
 	uint32_t chan_freq;
 	uint32_t sec_ch_freq;
 
+#ifdef DCS_INTERFERENCE_DETECTION
+	qdf_freq_t dcs_ch_freq;
+#endif
+
 	/* Include the SME(CSR) sessionId here */
 	uint8_t sessionId;
 

+ 151 - 1
core/sap/src/sap_module.c

@@ -518,7 +518,7 @@ wlansap_set_scan_acs_channel_params(struct sap_config *config,
 	}
 
 	/* Channel selection is auto or configured */
-	psap_ctx->chan_freq = config->chan_freq;
+	wlansap_set_acs_ch_freq(psap_ctx, config->chan_freq);
 	psap_ctx->dfs_mode = config->acs_dfs_mode;
 #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
 	psap_ctx->cc_switch_mode = config->cc_switch_mode;
@@ -1317,6 +1317,8 @@ static char *sap_get_csa_reason_str(enum sap_csa_reason_code reason)
 		return "CONCURRENT_NAN_EVENT";
 	case CSA_REASON_BAND_RESTRICTED:
 		return "BAND_RESTRICTED";
+	case CSA_REASON_DCS:
+		return "DCS";
 	default:
 		return "UNKNOWN";
 	}
@@ -2385,6 +2387,7 @@ void sap_undo_acs(struct sap_context *sap_ctx, struct sap_config *sap_cfg)
 	acs_cfg->master_ch_list_count = 0;
 	acs_cfg->acs_mode = false;
 	sap_ctx->num_of_channel = 0;
+	wlansap_dcs_set_vdev_wlan_interference_mitigation(sap_ctx, false);
 }
 
 QDF_STATUS wlansap_acs_chselect(struct sap_context *sap_context,
@@ -3036,3 +3039,150 @@ qdf_freq_t wlansap_get_chan_band_restrict(struct sap_context *sap_ctx)
 	return restart_freq;
 }
 
+#ifdef DCS_INTERFERENCE_DETECTION
+QDF_STATUS wlansap_dcs_set_vdev_wlan_interference_mitigation(
+				struct sap_context *sap_context,
+				bool wlan_interference_mitigation_enable)
+{
+	struct mac_context *mac;
+
+	if (!sap_context) {
+		sap_err("Invalid SAP context pointer");
+		return QDF_STATUS_E_FAULT;
+	}
+
+	mac = sap_get_mac_context();
+	if (!mac) {
+		sap_err("Invalid MAC context");
+		return QDF_STATUS_E_FAULT;
+	}
+
+	mac->sap.dcs_info.
+		wlan_interference_mitigation_enable[sap_context->sessionId] =
+					wlan_interference_mitigation_enable;
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS wlansap_dcs_set_wlan_interference_mitigation_on_band(
+					struct sap_context *sap_context,
+					struct sap_config *sap_cfg)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	bool wlan_interference_mitigation_enable = false;
+
+	if (WLAN_REG_IS_5GHZ_CH_FREQ(sap_cfg->acs_cfg.pri_ch_freq))
+		wlan_interference_mitigation_enable = true;
+
+	status = wlansap_dcs_set_vdev_wlan_interference_mitigation(
+					sap_context,
+					wlan_interference_mitigation_enable);
+	return status;
+}
+
+QDF_STATUS wlansap_dcs_set_vdev_starting(struct sap_context *sap_context,
+					 bool vdev_starting)
+{
+	struct mac_context *mac;
+
+	if (!sap_context) {
+		sap_err("Invalid SAP context pointer");
+		return QDF_STATUS_E_FAULT;
+	}
+
+	mac = sap_get_mac_context();
+	if (!mac) {
+		sap_err("Invalid MAC context");
+		return QDF_STATUS_E_FAULT;
+	}
+
+	mac->sap.dcs_info.is_vdev_starting[sap_context->sessionId] =
+							vdev_starting;
+
+	return QDF_STATUS_SUCCESS;
+}
+
+bool wlansap_dcs_is_wlan_interference_mitigation_enabled(
+					struct sap_context *sap_context)
+{
+	struct mac_context *mac;
+
+	if (!sap_context) {
+		sap_err("Invalid SAP context pointer");
+		return false;
+	}
+
+	mac = sap_get_mac_context();
+	if (!mac) {
+		sap_err("Invalid MAC context");
+		return false;
+	}
+
+	return mac->sap.dcs_info.
+		wlan_interference_mitigation_enable[sap_context->sessionId];
+}
+
+qdf_freq_t wlansap_dcs_get_freq(struct sap_context *sap_context)
+{
+	if (!sap_context) {
+		sap_err("Invalid SAP context pointer");
+		return false;
+	}
+
+	return sap_context->dcs_ch_freq;
+}
+
+void wlansap_dump_acs_ch_freq(struct sap_context *sap_context)
+{
+	if (!sap_context) {
+		sap_err("Invalid sap_debug");
+		return;
+	}
+
+	if (sap_context->fsm_state == SAP_STARTED)
+		sap_info("ACS dump DCS freq=%d", sap_context->dcs_ch_freq);
+	else
+		sap_info("ACS dump ch_freq=%d", sap_context->chan_freq);
+}
+
+void wlansap_set_acs_ch_freq(struct sap_context *sap_context,
+			     qdf_freq_t ch_freq)
+{
+	if (!sap_context) {
+		sap_err("Invalid sap_debug");
+		return;
+	}
+
+	if (sap_context->fsm_state == SAP_STARTED) {
+		sap_context->dcs_ch_freq = ch_freq;
+		sap_debug("ACS configuring dcs_ch_freq=%d",
+			  sap_context->dcs_ch_freq);
+	} else {
+		sap_context->chan_freq = ch_freq;
+		sap_debug("ACS configuring ch_freq=%d",
+			  sap_context->chan_freq);
+	}
+}
+#else
+void wlansap_dump_acs_ch_freq(struct sap_context *sap_context)
+{
+	if (!sap_context) {
+		sap_err("Invalid sap_debug");
+		return;
+	}
+
+	sap_info("ACS dump ch_freq=%d", sap_context->chan_freq);
+}
+
+void wlansap_set_acs_ch_freq(struct sap_context *sap_context,
+			     qdf_freq_t ch_freq)
+{
+	if (!sap_context) {
+		sap_err("Invalid sap_debug");
+		return;
+	}
+
+	sap_context->chan_freq = ch_freq;
+	sap_debug("ACS configuring ch_freq=%d", sap_context->chan_freq);
+}
+#endif

+ 85 - 4
core/wma/src/wma_dev_if.c

@@ -87,6 +87,10 @@
 #include "wlan_utility.h"
 #include "wlan_coex_ucfg_api.h"
 
+#ifdef DCS_INTERFERENCE_DETECTION
+#include <wlan_dcs_ucfg_api.h>
+#endif
+
 QDF_STATUS wma_find_vdev_id_by_addr(tp_wma_handle wma, uint8_t *addr,
 				    uint8_t *vdev_id)
 {
@@ -1183,6 +1187,81 @@ QDF_STATUS wma_handle_channel_switch_resp(tp_wma_handle wma,
 	return QDF_STATUS_SUCCESS;
 }
 
+#ifdef DCS_INTERFERENCE_DETECTION
+/**
+ * wma_dcs_clear_vdev_starting() - clear vdev starting within dcs information
+ * @mac_ctx: mac context
+ * @vdev_id: vdev id
+ *
+ * This function is used to clear vdev starting within dcs information
+ *
+ * Return: None
+ */
+static void wma_dcs_clear_vdev_starting(struct mac_context *mac_ctx,
+					uint32_t vdev_id)
+{
+	mac_ctx->sap.dcs_info.is_vdev_starting[vdev_id] = false;
+}
+
+/**
+ * wma_dcs_wlan_interference_mitigation_enable() - enable wlan
+ * interference mitigation
+ * @mac_ctx: mac context
+ * @mac_id: mac id
+ * @vdev_id: vdev id
+ *
+ * This function is used to enable wlan interference mitigation through
+ * send dcs command
+ *
+ * Return: None
+ */
+static void wma_dcs_wlan_interference_mitigation_enable(
+					struct mac_context *mac_ctx,
+					uint32_t mac_id,
+					uint32_t vdev_id)
+{
+	int vdev_index;
+	uint32_t list[MAX_NUMBER_OF_CONC_CONNECTIONS];
+	uint32_t count;
+	bool wlan_interference_mitigation_enable =
+			mac_ctx->sap.dcs_info.
+				wlan_interference_mitigation_enable[vdev_id];
+
+	count = policy_mgr_get_sap_go_count_on_mac(
+			mac_ctx->psoc, list, mac_id);
+
+	for (vdev_index = 0; vdev_index < count; vdev_index++) {
+		if (mac_ctx->sap.dcs_info.is_vdev_starting[list[vdev_index]]) {
+			WMA_LOGE("vdev %d: does not finish restart",
+				 list[vdev_index]);
+			return;
+		}
+		wlan_interference_mitigation_enable =
+			wlan_interference_mitigation_enable ||
+		mac_ctx->sap.dcs_info.
+			wlan_interference_mitigation_enable[list[vdev_index]];
+	}
+
+	if (wlan_interference_mitigation_enable)
+		ucfg_config_dcs_enable(
+			mac_ctx->psoc, mac_id, CAP_DCS_WLANIM);
+	ucfg_wlan_dcs_cmd(mac_ctx->psoc, mac_id, true);
+}
+#else
+static void wma_dcs_wlan_interference_mitigation_enable(
+					struct mac_context *mac_ctx,
+					uint32_t mac_id,
+					uint32_t vdev_id)
+{
+}
+
+
+static void wma_dcs_clear_vdev_starting(struct mac_context *mac_ctx,
+					uint32_t vdev_id)
+{
+}
+#endif
+
 QDF_STATUS wma_vdev_start_resp_handler(struct vdev_mlme_obj *vdev_mlme,
 				       struct vdev_start_response *rsp)
 {
@@ -1190,9 +1269,7 @@ QDF_STATUS wma_vdev_start_resp_handler(struct vdev_mlme_obj *vdev_mlme,
 	struct wma_txrx_node *iface;
 	target_resource_config *wlan_res_cfg;
 	struct wlan_objmgr_psoc *psoc;
-#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
 	struct mac_context *mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
-#endif
 	QDF_STATUS status;
 	enum vdev_assoc_type assoc_type = VDEV_ASSOC;
 	struct vdev_mlme_obj *mlme_obj;
@@ -1208,14 +1285,12 @@ QDF_STATUS wma_vdev_start_resp_handler(struct vdev_mlme_obj *vdev_mlme,
 		return QDF_STATUS_E_FAILURE;
 	}
 
-#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
 	if (!mac_ctx) {
 		WMA_LOGE("%s: Failed to get mac_ctx", __func__);
 		policy_mgr_set_do_hw_mode_change_flag(
 			psoc, false);
 		return QDF_STATUS_E_FAILURE;
 	}
-#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
 
 	wlan_res_cfg = lmac_get_tgt_res_cfg(psoc);
 	if (!wlan_res_cfg) {
@@ -1257,6 +1332,12 @@ QDF_STATUS wma_vdev_start_resp_handler(struct vdev_mlme_obj *vdev_mlme,
 	}
 
 	iface = &wma->interfaces[rsp->vdev_id];
+	if (wma_is_vdev_in_ap_mode(wma, rsp->vdev_id)) {
+		wma_dcs_clear_vdev_starting(mac_ctx, rsp->vdev_id);
+		wma_dcs_wlan_interference_mitigation_enable(mac_ctx,
+							    iface->mac_id,
+							    rsp->vdev_id);
+	}
 
 #ifdef FEATURE_AP_MCC_CH_AVOIDANCE
 	if (rsp->status == QDF_STATUS_SUCCESS