diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h
index ea48a60620e0..37edc42e8691 100644
--- a/core/hdd/inc/wlan_hdd_cfg.h
+++ b/core/hdd/inc/wlan_hdd_cfg.h
@@ -9923,6 +9923,85 @@ enum l1ss_sleep_allowed {
#define CFG_FILS_MAX_CHAN_GUARD_TIME_MAX (10)
#define CFG_FILS_MAX_CHAN_GUARD_TIME_DEFAULT (0)
+/*
+ * enum hdd_external_acs_policy - External ACS policy
+ * @HDD_EXTERNAL_ACS_PCL_PREFERRED -Preferable for ACS to select a
+ * channel with non-zero pcl weight.
+ * @HDD_EXTERNAL_ACS_PCL_MANDATORY -Mandatory for ACS to select a
+ * channel with non-zero pcl weight.
+ *
+ * enum hdd_external_acs_policy is used to select the ACS policy.
+ *
+ */
+enum hdd_external_acs_policy {
+ HDD_EXTERNAL_ACS_PCL_PREFERRED = 0,
+ HDD_EXTERNAL_ACS_PCL_MANDATORY = 1,
+};
+
+/*
+ *
+ * external_acs_policy - External ACS policy control
+ * @Min: 0
+ * @Max: 1
+ * @Default: 0
+ *
+ * Values are per enum hdd_external_acs_policy.
+ *
+ * This ini is used to control the external ACS policy.
+ *
+ * Related: None
+ *
+ * Supported Feature: ACS
+ *
+ * Usage: Internal/External
+ *
+ *
+ */
+#define CFG_EXTERNAL_ACS_POLICY "acs_policy"
+#define CFG_EXTERNAL_ACS_POLICY_MIN (HDD_EXTERNAL_ACS_PCL_PREFERRED)
+#define CFG_EXTERNAL_ACS_POLICY_MAX (HDD_EXTERNAL_ACS_PCL_MANDATORY)
+#define CFG_EXTERNAL_ACS_POLICY_DEFAULT (HDD_EXTERNAL_ACS_PCL_PREFERRED)
+
+/*
+ * enum hdd_external_acs_policyl - Preferred freq band for external ACS
+ * @HDD_EXTERNAL_ACS_FREQ_BAND_24GHZ -2.4GHz band
+ * @HDD_EXTERNAL_ACS_FREQ_BAND_5GHZ -5GHz band
+ *
+ * enum hdd_external_acs_freq_band is used to select the freq band for ACS.
+ *
+ */
+enum hdd_external_acs_freq_band {
+ HDD_EXTERNAL_ACS_FREQ_BAND_24GHZ = 0,
+ HDD_EXTERNAL_ACS_FREQ_BAND_5GHZ = 1,
+};
+
+/*
+ *
+ * external_acs_freq_band - External ACS freq band
+ * @Min: 0
+ * @Max: 1
+ * @Default: 0
+ *
+ * Values are per enum hdd_external_acs_freq_band.
+ *
+ * This ini is used to select the ACS freq band. Currently
+ * the external ACS module doesn't support channels from
+ * both the bands. Once multiple band support is added in
+ * ICM, this ini can be removed
+ *
+ * Related: None
+ *
+ * Supported Feature: ACS
+ *
+ * Usage: Internal/External
+ *
+ *
+ */
+#define CFG_EXTERNAL_ACS_FREQ_BAND "acs_freq_band"
+#define CFG_EXTERNAL_ACS_FREQ_BAND_MIN (HDD_EXTERNAL_ACS_FREQ_BAND_24GHZ)
+#define CFG_EXTERNAL_ACS_FREQ_BAND_MAX (HDD_EXTERNAL_ACS_FREQ_BAND_5GHZ)
+#define CFG_EXTERNAL_ACS_FREQ_BAND_DEFAULT (HDD_EXTERNAL_ACS_FREQ_BAND_24GHZ)
+
/*
* Type declarations
*/
@@ -10647,6 +10726,8 @@ struct hdd_config {
bool qcn_ie_support;
bool reg_offload_enabled;
uint8_t fils_max_chan_guard_time;
+ enum hdd_external_acs_policy external_acs_policy;
+ enum hdd_external_acs_freq_band external_acs_freq_band;
};
#define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var))
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h
index d652f030335f..467e62434903 100644
--- a/core/hdd/inc/wlan_hdd_main.h
+++ b/core/hdd/inc/wlan_hdd_main.h
@@ -1620,12 +1620,14 @@ struct hdd_context_s {
* struct hdd_vendor_acs_chan_params - vendor acs channel parameters
* @channel_count: channel count
* @channel_list: pointer to channel list
+ * @pcl_count: pcl list count
* @vendor_pcl_list: pointer to pcl list
* @vendor_weight_list: pointer to pcl weight list
*/
struct hdd_vendor_acs_chan_params {
uint32_t channel_count;
uint8_t *channel_list;
+ uint32_t pcl_count;
uint8_t *vendor_pcl_list;
uint8_t *vendor_weight_list;
};
@@ -2250,6 +2252,7 @@ bool hdd_set_connection_in_progress(bool value);
* @ap_adapter: adapter
* @channel_count: valid channel count
* @channel_list: valid channel list
+ * @band: frequency band
*
* This API returns valid channel list for SAP after removing nol and
* channel which lies outside of configuration.
@@ -2258,7 +2261,8 @@ bool hdd_set_connection_in_progress(bool value);
*/
int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
uint32_t *channel_count,
- uint8_t *channel_list);
+ uint8_t *channel_list,
+ eCsrBand band);
/**
* wlan_hdd_init_chan_info() - initialize channel info variables
* @hdd_ctx: hdd ctx
diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c
index c096627bd306..afd17a95a9ab 100644
--- a/core/hdd/src/wlan_hdd_cfg.c
+++ b/core/hdd/src/wlan_hdd_cfg.c
@@ -4318,6 +4318,19 @@ struct reg_table_entry g_registry_table[] = {
CFG_FILS_MAX_CHAN_GUARD_TIME_DEFAULT,
CFG_FILS_MAX_CHAN_GUARD_TIME_MIN,
CFG_FILS_MAX_CHAN_GUARD_TIME_MAX),
+ REG_VARIABLE(CFG_EXTERNAL_ACS_POLICY, WLAN_PARAM_Integer,
+ struct hdd_config, external_acs_policy,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_EXTERNAL_ACS_POLICY_DEFAULT,
+ CFG_EXTERNAL_ACS_POLICY_MIN,
+ CFG_EXTERNAL_ACS_POLICY_MAX),
+
+ REG_VARIABLE(CFG_EXTERNAL_ACS_FREQ_BAND, WLAN_PARAM_Integer,
+ struct hdd_config, external_acs_freq_band,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_EXTERNAL_ACS_FREQ_BAND_DEFAULT,
+ CFG_EXTERNAL_ACS_FREQ_BAND_MIN,
+ CFG_EXTERNAL_ACS_FREQ_BAND_MAX),
};
@@ -5819,6 +5832,12 @@ void hdd_cfg_print(hdd_context_t *pHddCtx)
hdd_info("Name = [%s] Value = [%d]",
CFG_ARP_AC_CATEGORY,
pHddCtx->config->arp_ac_category);
+ hdd_info("Name = [%s] Value = [%d]",
+ CFG_EXTERNAL_ACS_POLICY,
+ pHddCtx->config->external_acs_policy);
+ hdd_info("Name = [%s] Value = [%d]",
+ CFG_EXTERNAL_ACS_FREQ_BAND,
+ pHddCtx->config->external_acs_freq_band);
}
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index 042d37a7914b..01293e2eda90 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -1437,32 +1437,74 @@ static void hdd_update_vendor_pcl_list(hdd_context_t *hdd_ctx,
tsap_Config_t *sap_config)
{
int i, j;
+ bool found;
- for (i = 0; i < acs_chan_params->channel_count; i++) {
- for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
- if (acs_chan_params->channel_list[i] ==
+ if (HDD_EXTERNAL_ACS_PCL_MANDATORY ==
+ hdd_ctx->config->external_acs_policy) {
+ /*
+ * In preferred channels mandatory case, PCL shall
+ * contain only the preferred channels from the
+ * application. If those channels are not present
+ * in the driver PCL, then set the weight to zero
+ */
+ for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
+ acs_chan_params->vendor_pcl_list[i] =
+ sap_config->acs_cfg.ch_list[i];
+ acs_chan_params->vendor_weight_list[i] = 0;
+ for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
+ if (sap_config->acs_cfg.ch_list[i] ==
sap_config->acs_cfg.pcl_channels[j]) {
+ acs_chan_params->vendor_weight_list[i] =
+ sap_config->
+ acs_cfg.pcl_channels_weight_list[j];
+ break;
+ }
+ }
+ }
+ acs_chan_params->pcl_count = sap_config->acs_cfg.ch_list_count;
+ } else {
+ /*
+ * In preferred channels not mandatory case update the
+ * PCL weight to zero for those channels which are not
+ * present in the application's preferred channel list for
+ * ACS
+ */
+ for (i = 0; i < sap_config->acs_cfg.pcl_ch_count; i++) {
+ found = false;
+ for (j = 0; j < sap_config->acs_cfg.ch_list_count;
+ j++) {
+ if (sap_config->acs_cfg.pcl_channels[i] ==
+ sap_config->acs_cfg.ch_list[j]) {
+ acs_chan_params->vendor_pcl_list[i] =
+ sap_config->
+ acs_cfg.pcl_channels[i];
+ acs_chan_params->
+ vendor_weight_list[i] =
+ sap_config->acs_cfg.
+ pcl_channels_weight_list[i];
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
acs_chan_params->vendor_pcl_list[i] =
- sap_config->acs_cfg.pcl_channels[j];
- acs_chan_params->vendor_weight_list[i] =
- sap_config->acs_cfg.
- pcl_channels_weight_list[j];
- break;
- } else {
- acs_chan_params->vendor_pcl_list[i] =
- acs_chan_params->channel_list[i];
+ sap_config->acs_cfg.pcl_channels[i];
acs_chan_params->vendor_weight_list[i] = 0;
}
}
- }
- if (hdd_ctx->unsafe_channel_count == 0)
- return;
- /* Update unsafe channel weight as zero */
- for (i = 0; i < acs_chan_params->channel_count; i++) {
- for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
- if (acs_chan_params->channel_list[i] ==
+
+ acs_chan_params->pcl_count = sap_config->acs_cfg.pcl_ch_count;
+
+ if (hdd_ctx->unsafe_channel_count == 0)
+ return;
+ /* Update unsafe channel weight as zero */
+ for (i = 0; i < acs_chan_params->pcl_count; i++) {
+ for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
+ if (acs_chan_params->vendor_pcl_list[i] ==
hdd_ctx->unsafe_channel_list[j]) {
- acs_chan_params->vendor_weight_list[i] = 0;
+ acs_chan_params->
+ vendor_weight_list[i] = 0;
+ }
}
}
}
@@ -1497,6 +1539,7 @@ static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
return -ENOMEM;
}
+ sap_config->channel_info_count = channel_count;
for (i = 0; i < channel_count; i++) {
icv = &sap_config->channel_info[i];
chan = channel_list[i];
@@ -1591,7 +1634,7 @@ hdd_cfg80211_update_channel_info(struct sk_buff *skb,
if (!nla_attr)
goto fail;
- for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
+ for (i = 0; i < sap_config->channel_info_count; i++) {
channel = nla_nest_start(skb, i);
if (!channel)
goto fail;
@@ -1687,7 +1730,9 @@ fail:
return -EINVAL;
}
-static void hdd_get_scan_band(tsap_Config_t *sap_config, eCsrBand *band)
+static void hdd_get_scan_band(hdd_context_t *hdd_ctx,
+ tsap_Config_t *sap_config,
+ eCsrBand *band)
{
/* Get scan band */
if ((sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) ||
@@ -1701,7 +1746,11 @@ static void hdd_get_scan_band(tsap_Config_t *sap_config, eCsrBand *band)
/* Auto is not supported currently */
if (!((*band == eCSR_BAND_24) || (eCSR_BAND_5G == *band))) {
hdd_err("invalid band");
- *band = eCSR_BAND_24;
+ if (HDD_EXTERNAL_ACS_FREQ_BAND_24GHZ ==
+ hdd_ctx->config->external_acs_freq_band)
+ *band = eCSR_BAND_24;
+ else
+ *band = eCSR_BAND_5G;
}
}
@@ -1718,6 +1767,9 @@ void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
eCsrBand band = eCSR_BAND_24;
eCsrPhyMode phy_mode;
+ enum qca_wlan_vendor_attr_external_acs_policy acs_policy;
+ uint32_t i;
+
if (!hdd_ctx) {
hdd_err("HDD context is NULL");
@@ -1727,12 +1779,14 @@ void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
ENTER();
sap_config = &adapter->sessionCtx.ap.sapConfig;
+ hdd_get_scan_band(hdd_ctx, &adapter->sessionCtx.ap.sapConfig, &band);
/* Get valid channels for SAP */
wlan_hdd_sap_get_valid_channellist(adapter,
- &channel_count, channel_list);
+ &channel_count,
+ channel_list,
+ band);
hdd_update_reg_chan_info(adapter, channel_count, channel_list);
- hdd_get_scan_band(&adapter->sessionCtx.ap.sapConfig, &band);
/* Get phymode */
phy_mode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
@@ -1758,6 +1812,33 @@ void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
sap_config);
+
+ if (acs_chan_params.channel_count) {
+ hdd_debug("ACS channel list: len: %d",
+ acs_chan_params.channel_count);
+ for (i = 0; i < acs_chan_params.channel_count; i++)
+ hdd_debug("%d ", acs_chan_params.channel_list[i]);
+ }
+
+ if (acs_chan_params.pcl_count) {
+ hdd_debug("ACS PCL list: len: %d",
+ acs_chan_params.pcl_count);
+ for (i = 0; i < acs_chan_params.pcl_count; i++)
+ hdd_debug("channel:%d, weight:%d ",
+ acs_chan_params.
+ vendor_pcl_list[i],
+ acs_chan_params.
+ vendor_weight_list[i]);
+ }
+
+ if (HDD_EXTERNAL_ACS_PCL_MANDATORY ==
+ hdd_ctx->config->external_acs_policy) {
+ acs_policy =
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY;
+ } else {
+ acs_policy =
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED;
+ }
/* Update values in NL buffer */
if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
reason) ||
@@ -1781,9 +1862,13 @@ void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
hdd_err("nla put fail");
goto fail;
}
- status = hdd_cfg80211_update_pcl(skb, channel_count,
- QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
- vendor_pcl_list, vendor_weight_list);
+ status =
+ hdd_cfg80211_update_pcl(skb,
+ acs_chan_params.
+ pcl_count,
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
+ vendor_pcl_list,
+ vendor_weight_list);
if (status != 0)
goto fail;
@@ -1794,6 +1879,13 @@ void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
if (status != 0)
goto fail;
+ status = nla_put_u32(skb,
+ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY,
+ acs_policy);
+
+ if (status != 0)
+ goto fail;
+
cfg80211_vendor_event(skb, GFP_KERNEL);
return;
fail:
@@ -2009,6 +2101,17 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
if (QDF_STATUS_SUCCESS != status)
hdd_err("Get PCL failed");
+ if (sap_config->acs_cfg.pcl_ch_count) {
+ hdd_debug("ACS config PCL: len: %d",
+ sap_config->acs_cfg.pcl_ch_count);
+ for (i = 0; i < sap_config->acs_cfg.pcl_ch_count; i++)
+ hdd_debug("channel:%d, weight:%d ",
+ sap_config->acs_cfg.
+ pcl_channels[i],
+ sap_config->acs_cfg.
+ pcl_channels_weight_list[i]);
+ }
+
/* ACS override for android */
if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
!hdd_ctx->config->sap_force_11n_for_11ac) {
@@ -7334,17 +7437,42 @@ static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
uint32_t *channel_count,
- uint8_t *channel_list)
+ uint8_t *channel_list,
+ eCsrBand band)
{
tsap_Config_t *sap_config;
+ hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+ uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
+ uint32_t chan_count;
+ uint8_t i;
+ QDF_STATUS status;
sap_config = &adapter->sessionCtx.ap.sapConfig;
- qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
- sap_config->acs_cfg.ch_list_count);
- *channel_count = sap_config->acs_cfg.ch_list_count;
+ status =
+ policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
+ tmp_chan_list,
+ &chan_count);
+ if (QDF_IS_STATUS_ERROR(status)) {
+ hdd_err("Failed to get channel list");
+ return -EINVAL;
+ }
+ for (i = 0; i < chan_count; i++) {
+ if (*channel_count < QDF_MAX_NUM_CHAN) {
+ if ((eCSR_BAND_24 == band) &&
+ (WLAN_REG_IS_24GHZ_CH(tmp_chan_list[i]))) {
+ channel_list[*channel_count] = tmp_chan_list[i];
+ *channel_count += 1;
+ } else if ((eCSR_BAND_5G == band) &&
+ (WLAN_REG_IS_5GHZ_CH(tmp_chan_list[i]))) {
+ channel_list[*channel_count] = tmp_chan_list[i];
+ *channel_count += 1;
+ }
+ } else {
+ break;
+ }
+ }
wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
-
if (*channel_count == 0) {
hdd_err("no valid channel found");
return -EINVAL;
diff --git a/core/sap/inc/sap_api.h b/core/sap/inc/sap_api.h
index 223cca7b2cb8..987bdd6c7466 100644
--- a/core/sap/inc/sap_api.h
+++ b/core/sap/inc/sap_api.h
@@ -618,6 +618,7 @@ typedef struct sap_Config {
tSirMacRateSet extended_rates;
enum sap_acs_dfs_mode acs_dfs_mode;
struct hdd_channel_info *channel_info;
+ uint32_t channel_info_count;
bool dfs_cac_offload;
} tsap_Config_t;