diff --git a/components/mlme/core/src/wlan_mlme_main.c b/components/mlme/core/src/wlan_mlme_main.c index f7d4889c9436..26d907ddf05e 100644 --- a/components/mlme/core/src/wlan_mlme_main.c +++ b/components/mlme/core/src/wlan_mlme_main.c @@ -1291,6 +1291,90 @@ static void mlme_init_threshold_cfg(struct wlan_objmgr_psoc *psoc, threshold->frag_threshold = cfg_get(psoc, CFG_FRAG_THRESHOLD); } +static bool +mlme_is_freq_present_in_list(struct acs_weight *normalize_weight_chan_list, + uint8_t num_freq, uint32_t freq, uint8_t *index) +{ + uint8_t i; + + for (i = 0; i < num_freq; i++) { + if (normalize_weight_chan_list[i].chan_freq == freq) { + *index = i; + return true; + } + } + + return false; +} + +static void +mlme_acs_parse_weight_list(struct wlan_objmgr_psoc *psoc, + struct wlan_mlme_acs *acs) +{ + char *acs_weight, *str1, *str2 = NULL, *acs_weight_temp, is_range = '-'; + int freq1, freq2, normalize_factor; + uint8_t num_acs_weight = 0, num_acs_weight_range = 0, index = 0; + struct acs_weight *weight_list = acs->normalize_weight_chan; + struct acs_weight_range *range_list = acs->normalize_weight_range; + + if (!qdf_str_len(cfg_get(psoc, CFG_NORMALIZE_ACS_WEIGHT))) + return; + + acs_weight = qdf_mem_malloc(ACS_WEIGHT_MAX_STR_LEN); + + if (!acs_weight) + return; + + qdf_mem_copy(acs_weight, cfg_get(psoc, CFG_NORMALIZE_ACS_WEIGHT), + ACS_WEIGHT_MAX_STR_LEN); + acs_weight_temp = acs_weight; + + while(acs_weight_temp) { + str1 = strsep(&acs_weight_temp, ","); + if (!str1) + goto end; + freq1 = 0; + freq2 = 0; + if (strchr(str1, is_range)) { + str2 = strsep(&str1, "-"); + sscanf(str2, "%d", &freq1); + sscanf(str1, "%d", &freq2); + strsep(&str1, "="); + sscanf(str1, "%d", &normalize_factor); + + if (num_acs_weight_range == MAX_ACS_WEIGHT_RANGE) + continue; + range_list[num_acs_weight_range].normalize_weight = + normalize_factor; + range_list[num_acs_weight_range].start_freq = freq1; + range_list[num_acs_weight_range++].end_freq = freq2; + } else { + sscanf(str1, "%d", &freq1); + strsep(&str1, "="); + sscanf(str1, "%d", &normalize_factor); + if (mlme_is_freq_present_in_list(weight_list, + num_acs_weight, freq1, + &index)) { + weight_list[index].normalize_weight = + normalize_factor; + } else { + if (num_acs_weight == QDF_MAX_NUM_CHAN) + continue; + + weight_list[num_acs_weight].chan_freq = freq1; + weight_list[num_acs_weight++].normalize_weight = + normalize_factor; + } + } + } + + acs->normalize_weight_num_chan = num_acs_weight; + acs->num_weight_range = num_acs_weight_range; + +end: + qdf_mem_free(acs_weight); +} + static void mlme_init_acs_cfg(struct wlan_objmgr_psoc *psoc, struct wlan_mlme_acs *acs) { @@ -1304,6 +1388,8 @@ static void mlme_init_acs_cfg(struct wlan_objmgr_psoc *psoc, cfg_get(psoc, CFG_USER_ACS_DFS_LTE); acs->is_external_acs_policy = cfg_get(psoc, CFG_EXTERNAL_ACS_POLICY); + + mlme_acs_parse_weight_list(psoc, acs); } QDF_STATUS mlme_init_ibss_cfg(struct wlan_objmgr_psoc *psoc, diff --git a/components/mlme/dispatcher/inc/cfg_mlme_acs.h b/components/mlme/dispatcher/inc/cfg_mlme_acs.h index eeb412a5ba31..405aea11d539 100644 --- a/components/mlme/dispatcher/inc/cfg_mlme_acs.h +++ b/components/mlme/dispatcher/inc/cfg_mlme_acs.h @@ -155,11 +155,36 @@ 1, \ "External ACS Policy Control") +#define ACS_WEIGHT_MAX_STR_LEN 500 + +/* + * + * normalize_acs_weight - Used to control the ACS channel weightage. + * + * This ini is used to specify the weight percentage of the channel. Channel + * weights can be controlled by user to prioritize or de-prioritize channels. + * + * Related: ACS + * + * Supported Feature: ACS + * + * Usage: External + * + * + */ +#define CFG_NORMALIZE_ACS_WEIGHT CFG_INI_STRING( \ + "normalize_acs_weight", \ + 0, \ + ACS_WEIGHT_MAX_STR_LEN, \ + "", \ + "Used to specify the channel weights") + #define CFG_ACS_ALL \ CFG(CFG_ACS_WITH_MORE_PARAM) \ CFG(CFG_AUTO_CHANNEL_SELECT_WEIGHT) \ CFG(CFG_USER_AUTO_CHANNEL_SELECTION) \ CFG(CFG_USER_ACS_DFS_LTE) \ - CFG(CFG_EXTERNAL_ACS_POLICY) + CFG(CFG_EXTERNAL_ACS_POLICY) \ + CFG(CFG_NORMALIZE_ACS_WEIGHT) #endif /* __CFG_MLME_ACS_H */ diff --git a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h index 543043d784e1..a34aa65dbc23 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h @@ -1161,6 +1161,30 @@ struct wlan_mlme_product_details_cfg { char manufacture_product_version[WLAN_CFG_MFR_PRODUCT_VERSION_LEN + 1]; }; +/* + * struct acs_weight - Normalize ACS weight for mentioned channels + * @chan_freq: frequency of the channel + * @normalize_weight: Normalization factor of the frequency + */ +struct acs_weight { + uint32_t chan_freq; + uint8_t normalize_weight; +}; + +/* + * struct acs_weight_range - Normalize ACS weight for mentioned channel range + * @start_freq: frequency of the start channel + * @end_freq: frequency of the end channel + * @normalize_weight: Normalization factor for freq range + */ +struct acs_weight_range { + uint32_t start_freq; + uint32_t end_freq; + uint8_t normalize_weight; +}; + +#define MAX_ACS_WEIGHT_RANGE 10 + /* * struct wlan_mlme_acs - All acs related cfg items * @is_acs_with_more_param - to enable acs with more param @@ -1168,6 +1192,10 @@ struct wlan_mlme_product_details_cfg { * @is_vendor_acs_support - enable application based channel selection * @is_acs_support_for_dfs_ltecoex - enable channel for dfs and lte coex * @is_external_acs_policy - control external policy + * @normalize_weight_chan: Weight factor to be considered in ACS + * @normalize_weight_num_chan: Number of freq items for normalization. + * @normalize_weight_range: Frequency range for weight normalization + * @num_weight_range: num of ranges provided by user */ struct wlan_mlme_acs { bool is_acs_with_more_param; @@ -1175,6 +1203,10 @@ struct wlan_mlme_acs { bool is_vendor_acs_support; bool is_acs_support_for_dfs_ltecoex; bool is_external_acs_policy; + struct acs_weight normalize_weight_chan[QDF_MAX_NUM_CHAN]; + uint16_t normalize_weight_num_chan; + struct acs_weight_range normalize_weight_range[MAX_ACS_WEIGHT_RANGE]; + uint16_t num_weight_range; }; /* diff --git a/core/sap/src/sap_ch_select.c b/core/sap/src/sap_ch_select.c index 2ad41540ddc2..f0405b04d0c9 100644 --- a/core/sap/src/sap_ch_select.c +++ b/core/sap/src/sap_ch_select.c @@ -1399,6 +1399,14 @@ static void sap_compute_spect_weight(tSapChSelSpectInfo *pSpectInfoParams, pSpectInfoParams->numSpectChans; qdf_list_node_t *cur_lst = NULL, *next_lst = NULL; struct scan_cache_node *cur_node = NULL; + uint32_t normalized_weight; + uint8_t normalize_factor; + uint32_t chan_freq; + struct acs_weight *weight_list = + mac->mlme_cfg->acs.normalize_weight_chan; + struct acs_weight_range *range_list = + mac->mlme_cfg->acs.normalize_weight_range; + bool freq_present_in_list = false; bcn_struct = qdf_mem_malloc(sizeof(tSirProbeRespBeacon)); if (!bcn_struct) @@ -1578,6 +1586,44 @@ static void sap_compute_spect_weight(tSapChSelSpectInfo *pSpectInfoParams, pSpectCh->bssCount = SOFTAP_MIN_COUNT; } + chan_freq = wlan_reg_chan_to_freq(mac->pdev, pSpectCh->chNum); + + /* Check if the freq is present in range list */ + for (i = 0; i < mac->mlme_cfg->acs.num_weight_range; i++) { + if (chan_freq >= range_list[i].start_freq && + chan_freq <= range_list[i].end_freq) { + normalize_factor = + range_list[i].normalize_weight; + sap_debug("Range list, freq %d normalize weight factor %d", + chan_freq, normalize_factor); + freq_present_in_list = true; + } + } + + /* Check if user wants a special factor for this freq */ + + for (i = 0; i < mac->mlme_cfg->acs.normalize_weight_num_chan; + i++) { + if (chan_freq == weight_list[i].chan_freq) { + normalize_factor = + weight_list[i].normalize_weight; + sap_debug("freq %d normalize weight factor %d", + chan_freq, normalize_factor); + freq_present_in_list = true; + } + } + + if (freq_present_in_list) { + normalized_weight = + ((SAP_ACS_WEIGHT_MAX - pSpectCh->weight) * + (100 - normalize_factor)) / 100; + sap_debug("freq %d old weight %d new weight %d", + chan_freq, pSpectCh->weight, + pSpectCh->weight + normalized_weight); + pSpectCh->weight += normalized_weight; + freq_present_in_list = false; + } + if (pSpectCh->weight > SAP_ACS_WEIGHT_MAX) pSpectCh->weight = SAP_ACS_WEIGHT_MAX; pSpectCh->weight_copy = pSpectCh->weight; diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c index 4f30bb7bf838..cd7ef6ca6f5b 100644 --- a/core/sap/src/sap_fsm.c +++ b/core/sap/src/sap_fsm.c @@ -3241,6 +3241,12 @@ static QDF_STATUS sap_get_freq_list(struct sap_context *sap_ctx, struct mac_context *mac_ctx; tSapChSelSpectInfo spect_info_obj = { NULL, 0 }; uint16_t ch_width; + uint8_t normalize_factor = 100; + uint32_t chan_freq; + struct acs_weight *weight_list; + struct acs_weight_range *range_list; + bool freq_present_in_list = false; + uint8_t i; mac_ctx = sap_get_mac_context(); if (!mac_ctx) { @@ -3250,6 +3256,9 @@ static QDF_STATUS sap_get_freq_list(struct sap_context *sap_ctx, return QDF_STATUS_E_FAULT; } + weight_list = mac_ctx->mlme_cfg->acs.normalize_weight_chan; + range_list = mac_ctx->mlme_cfg->acs.normalize_weight_range; + dfs_master_enable = mac_ctx->mlme_cfg->dfs_cfg.dfs_master_capable; if (sap_ctx->dfs_mode == ACS_DFS_MODE_DISABLE) dfs_master_enable = false; @@ -3284,8 +3293,7 @@ static QDF_STATUS sap_get_freq_list(struct sap_context *sap_ctx, } /* Allocate the max number of channel supported */ - list = qdf_mem_malloc((NUM_5GHZ_CHANNELS + NUM_24GHZ_CHANNELS) * - sizeof(uint32_t)); + list = qdf_mem_malloc((NUM_CHANNELS) * sizeof(uint32_t)); if (!list) { *num_ch = 0; *freq_list = NULL; @@ -3363,6 +3371,38 @@ static QDF_STATUS sap_get_freq_list(struct sap_context *sap_ctx, WLAN_REG_CH_NUM(loop_count))) continue; + chan_freq = wlan_reg_chan_to_freq(mac_ctx->pdev, + WLAN_REG_CH_NUM(loop_count)); + /* Check if the freq is present in range list */ + for (i = 0; i < mac_ctx->mlme_cfg->acs.num_weight_range; i++) { + if (chan_freq >= range_list[i].start_freq && + chan_freq <= range_list[i].end_freq) { + normalize_factor = + range_list[i].normalize_weight; + sap_debug("Range list, freq %d normalize weight factor %d", + chan_freq, normalize_factor); + freq_present_in_list = true; + } + } + + for (i = 0; + i < mac_ctx->mlme_cfg->acs.normalize_weight_num_chan; + i++) { + if (chan_freq == weight_list[i].chan_freq) { + normalize_factor = + weight_list[i].normalize_weight; + sap_debug("freq %d normalize weight factor %d", + chan_freq, normalize_factor); + freq_present_in_list = true; + } + } + + /* This would mean that the user does not want this freq */ + if (freq_present_in_list && !normalize_factor) { + sap_debug("chan_freq %d ecluded normalize weight 0", + chan_freq); + continue; + } #ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE if ((sap_ctx->acs_cfg->skip_scan_status == eSAP_DO_PAR_ACS_SCAN)) {