diff --git a/Kbuild b/Kbuild
index f85c14afc8..4996acece0 100644
--- a/Kbuild
+++ b/Kbuild
@@ -2618,6 +2618,9 @@ cppflags-$(CONFIG_HOST_OPCLASS) += -DHOST_OPCLASS
#Flag to enable/disable TARGET_11D_SCAN
cppflags-$(CONFIG_TARGET_11D_SCAN) += -DTARGET_11D_SCAN
+#Flag to enable/disable avoid acs frequency list feature
+cppflags-$(CONFIG_SAP_AVOID_ACS_FREQ_LIST) += -DSAP_AVOID_ACS_FREQ_LIST
+
#Flag to enable Dynamic Voltage WDCVS (Config Voltage Mode)
cppflags-$(CONFIG_WLAN_DYNAMIC_CVM) += -DFEATURE_WLAN_DYNAMIC_CVM
diff --git a/components/mlme/core/src/wlan_mlme_main.c b/components/mlme/core/src/wlan_mlme_main.c
index 0e42dbddff..a97fa69fc2 100644
--- a/components/mlme/core/src/wlan_mlme_main.c
+++ b/components/mlme/core/src/wlan_mlme_main.c
@@ -2252,6 +2252,30 @@ static void mlme_init_mwc_cfg(struct wlan_objmgr_psoc *psoc,
}
#endif
+#ifdef SAP_AVOID_ACS_FREQ_LIST
+static void mlme_init_acs_avoid_freq_list(struct wlan_objmgr_psoc *psoc,
+ struct wlan_mlme_reg *reg)
+{
+ qdf_size_t avoid_acs_freq_list_num = 0;
+ uint8_t i;
+
+ qdf_uint16_array_parse(cfg_get(psoc, CFG_SAP_AVOID_ACS_FREQ_LIST),
+ reg->avoid_acs_freq_list,
+ CFG_VALID_CHANNEL_LIST_LEN,
+ &avoid_acs_freq_list_num);
+ reg->avoid_acs_freq_list_num = avoid_acs_freq_list_num;
+
+ for (i = 0; i < avoid_acs_freq_list_num; i++)
+ mlme_legacy_debug("avoid_acs_freq %d",
+ reg->avoid_acs_freq_list[i]);
+}
+#else
+static void mlme_init_acs_avoid_freq_list(struct wlan_objmgr_psoc *psoc,
+ struct wlan_mlme_reg *reg)
+{
+}
+#endif
+
static void mlme_init_reg_cfg(struct wlan_objmgr_psoc *psoc,
struct wlan_mlme_reg *reg)
{
@@ -2274,6 +2298,7 @@ static void mlme_init_reg_cfg(struct wlan_objmgr_psoc *psoc,
qdf_str_lcopy(reg->country_code, cfg_default(CFG_COUNTRY_CODE),
sizeof(reg->country_code));
reg->country_code_len = (uint8_t)sizeof(reg->country_code);
+ mlme_init_acs_avoid_freq_list(psoc, reg);
}
static void
diff --git a/components/mlme/dispatcher/inc/cfg_mlme_reg.h b/components/mlme/dispatcher/inc/cfg_mlme_reg.h
index f7972a130d..502226923f 100644
--- a/components/mlme/dispatcher/inc/cfg_mlme_reg.h
+++ b/components/mlme/dispatcher/inc/cfg_mlme_reg.h
@@ -95,6 +95,39 @@
0, \
"enable/disable ETSI SRD channels in master mode")
+#ifdef SAP_AVOID_ACS_FREQ_LIST
+#define SAP_AVOID_ACS_FREQ_LIST_DEFAULT ""
+
+/*
+ *
+ * sap_avoid_acs_freq_list - Avoid configured frequencies from acs
+ * @Default: No frequencies are configured, it means consider all
+ * the frequencies for acs
+ *
+ * This ini is to configure the frequencies which needs to be
+ * avoided during acs and sap will not come up on these channels
+ * Ex: sap_avoid_acs_freq_list=2412,2417,2422,2427,2467,2472
+ *
+ * Related: Feature flag SAP_AVOID_ACS_FREQ_LIST
+ *
+ * Supported Feature: SAP
+ *
+ * Usage: External
+ *
+ *
+ */
+
+#define CFG_SAP_AVOID_ACS_FREQ_LIST CFG_INI_STRING( \
+ "sap_avoid_acs_freq_list", \
+ 0, \
+ CFG_VALID_CHANNEL_LIST_STRING_LEN, \
+ SAP_AVOID_ACS_FREQ_LIST_DEFAULT, \
+ "Avoid configured frequencies during acs")
+#define CFG_SAP_AVOID_ACS_FREQ_LIST_ALL CFG(CFG_SAP_AVOID_ACS_FREQ_LIST)
+#else
+#define CFG_SAP_AVOID_ACS_FREQ_LIST_ALL
+#endif
+
/*
*
* restart_beaconing_on_chan_avoid_event - control the beaconing entity to move
@@ -217,6 +250,7 @@
CFG(CFG_INDOOR_CHANNEL_SUPPORT) \
CFG(CFG_SCAN_11D_INTERVAL) \
CFG(CFG_VALID_CHANNEL_LIST) \
- CFG(CFG_COUNTRY_CODE)
+ CFG(CFG_COUNTRY_CODE) \
+ CFG_SAP_AVOID_ACS_FREQ_LIST_ALL
#endif /* CFG_MLME_REG_H__ */
diff --git a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h
index 5c9cbe4f11..ff076f710a 100644
--- a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h
+++ b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h
@@ -2038,6 +2038,9 @@ struct wlan_mlme_mwc {
* @country_code: country code
* @country_code_len: country code length
* @enable_11d_in_world_mode: Whether to enable 11d scan in world mode or not
+ * @avoid_acs_freq_list: List of the frequencies which need to be avoided
+ * during acs
+ * @avoid_acs_freq_list_num: Number of the frequencies to be avoided during acs
*/
struct wlan_mlme_reg {
uint32_t self_gen_frm_pwr;
@@ -2051,6 +2054,10 @@ struct wlan_mlme_reg {
uint8_t country_code[CFG_COUNTRY_CODE_LEN + 1];
uint8_t country_code_len;
bool enable_11d_in_world_mode;
+#ifdef SAP_AVOID_ACS_FREQ_LIST
+ uint16_t avoid_acs_freq_list[CFG_VALID_CHANNEL_LIST_LEN];
+ uint8_t avoid_acs_freq_list_num;
+#endif
};
/**
diff --git a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h
index 0a9f6e5393..2b4fee3bb8 100644
--- a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h
+++ b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h
@@ -3660,6 +3660,30 @@ QDF_STATUS
ucfg_mlme_get_etsi13_srd_chan_in_master_mode(struct wlan_objmgr_psoc *psoc,
bool *value);
+#ifdef SAP_AVOID_ACS_FREQ_LIST
+/**
+ * ucfg_mlme_get_acs_avoid_freq_list - get acs avoid frequency list
+ * @psoc: pointer to psoc object
+ * @freq_list: Pointer to output freq list
+ * @freq_list_num: Pointer to the output number of frequencies filled
+ * in the freq_list
+ *
+ * Return: QDF Status
+ */
+QDF_STATUS
+ucfg_mlme_get_acs_avoid_freq_list(struct wlan_objmgr_psoc *psoc,
+ uint16_t *freq_list, uint8_t *freq_list_num);
+
+#else
+static inline QDF_STATUS
+ucfg_mlme_get_acs_avoid_freq_list(struct wlan_objmgr_psoc *psoc,
+ uint16_t *freq_list, uint8_t *freq_list_num)
+{
+ *freq_list_num = 0;
+ return QDF_STATUS_E_INVAL;
+}
+#endif
+
/**
* ucfg_mlme_get_11d_in_world_mode - get whether 11d is enabled in world mode
* in master mode
diff --git a/components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c b/components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c
index 93d8a09aa0..fd4e376ac5 100644
--- a/components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c
+++ b/components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c
@@ -1414,6 +1414,34 @@ ucfg_mlme_get_etsi13_srd_chan_in_master_mode(struct wlan_objmgr_psoc *psoc,
return QDF_STATUS_SUCCESS;
}
+#ifdef SAP_AVOID_ACS_FREQ_LIST
+QDF_STATUS
+ucfg_mlme_get_acs_avoid_freq_list(struct wlan_objmgr_psoc *psoc,
+ uint16_t *freq_list, uint8_t *freq_list_num)
+{
+ struct wlan_mlme_psoc_obj *mlme_obj;
+ qdf_size_t avoid_acs_freq_list_num;
+
+ mlme_obj = mlme_get_psoc_obj(psoc);
+ if (!mlme_obj) {
+ qdf_uint16_array_parse(
+ cfg_default(CFG_SAP_AVOID_ACS_FREQ_LIST),
+ freq_list, CFG_VALID_CHANNEL_LIST_LEN,
+ &avoid_acs_freq_list_num);
+ *freq_list_num = avoid_acs_freq_list_num;
+
+ mlme_legacy_err("Failed to get MLME Obj");
+ return QDF_STATUS_E_INVAL;
+ }
+
+ *freq_list_num = mlme_obj->cfg.reg.avoid_acs_freq_list_num;
+ qdf_mem_copy(freq_list, mlme_obj->cfg.reg.avoid_acs_freq_list,
+ *freq_list_num * sizeof(uint16_t));
+
+ return QDF_STATUS_SUCCESS;
+}
+#endif
+
QDF_STATUS
ucfg_mlme_get_11d_in_world_mode(struct wlan_objmgr_psoc *psoc,
bool *value)
diff --git a/configs/default_defconfig b/configs/default_defconfig
index b06dc789f1..0e9efa581a 100644
--- a/configs/default_defconfig
+++ b/configs/default_defconfig
@@ -656,6 +656,9 @@ CONFIG_LTE_COEX := y
#Flag to enable/disable TARGET 11d scan
CONFIG_TARGET_11D_SCAN := y
+#Flag to enable/disable Avoid acs freq feature
+CONFIG_SAP_AVOID_ACS_FREQ_LIST := y
+
#Flag to enable HOST OPCLASS feature
CONFIG_HOST_OPCLASS := y
diff --git a/configs/genoa.common b/configs/genoa.common
index aa7f0aa814..e25b4d5c94 100644
--- a/configs/genoa.common
+++ b/configs/genoa.common
@@ -53,6 +53,9 @@ CONFIG_WLAN_DYNAMIC_CVM := n
CONFIG_WLAN_WEXT_SUPPORT_ENABLE := y
CONFIG_HOST_11D_SCAN := y
+#Flag to enable/disable Avoid acs freq feature
+CONFIG_SAP_AVOID_ACS_FREQ_LIST := n
+
ifeq ($(CONFIG_ARCH_MSM8996), y)
CONFIG_CHANNEL_HOPPING_ALL_BANDS := y
endif
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index 2f168d5b2e..1753f1a69d 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -2529,6 +2529,55 @@ int hdd_start_vendor_acs(struct hdd_adapter *adapter)
return status;
}
+/**
+ * hdd_avoid_acs_channels() - Avoid acs channels
+ * @hdd_ctx: Pointer to the hdd context
+ * @sap_config: Sap config structure pointer
+ *
+ * This function avoids channels from the acs corresponding to
+ * the frequencies configured in the ini sap_avoid_acs_freq_list
+ *
+ * Return: None
+ */
+
+#ifdef SAP_AVOID_ACS_FREQ_LIST
+static void hdd_avoid_acs_channels(struct hdd_context *hdd_ctx,
+ struct sap_config *sap_config)
+{
+ int i, j, ch_cnt = 0;
+ uint16_t avoid_acs_freq_list[CFG_VALID_CHANNEL_LIST_LEN];
+ uint8_t avoid_acs_freq_list_num;
+
+ hdd_enter();
+
+ ucfg_mlme_get_acs_avoid_freq_list(hdd_ctx->psoc,
+ avoid_acs_freq_list,
+ &avoid_acs_freq_list_num);
+
+ for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
+ for (j = 0; j < avoid_acs_freq_list_num; j++) {
+ if (sap_config->acs_cfg.ch_list[i] ==
+ wlan_reg_freq_to_chan(
+ hdd_ctx->pdev,
+ avoid_acs_freq_list[j])) {
+ hdd_debug("skip channel %d",
+ sap_config->acs_cfg.ch_list[i]);
+ break;
+ }
+ }
+ if (j == avoid_acs_freq_list_num)
+ sap_config->acs_cfg.ch_list[ch_cnt++] =
+ sap_config->acs_cfg.ch_list[i];
+ }
+ sap_config->acs_cfg.ch_list_count = ch_cnt;
+}
+#else
+static void hdd_avoid_acs_channels(struct hdd_context *hdd_ctx,
+ struct sap_config *sap_config)
+{
+}
+#endif
+
/**
* __wlan_hdd_cfg80211_do_acs(): CFG80211 handler function for DO_ACS Vendor CMD
* @wiphy: Linux wiphy struct pointer
@@ -2762,6 +2811,9 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
}
sap_config->acs_cfg.ch_list_count = ch_cnt;
}
+
+ hdd_avoid_acs_channels(hdd_ctx, sap_config);
+
hdd_debug("get pcl for DO_ACS vendor command");
pm_mode =