Переглянути джерело

qcacld-3.0: Normalize the channel weights according to ini

Normalize the weights of the frequencies for ACS scan
if the user has changed them in the ini.
This is done as legacy devices wont be able to scan
the newly added 6ghz frequencies, and thus wont
be able to associate with the SAP if it starts
on 6ghz channels.

Change-Id: I2dd2f706c248f5339bde06963540d0874d08b847
CRs-Fixed: 2543007
gaurank kathpalia 5 роки тому
батько
коміт
c0d0841183

+ 86 - 0
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,

+ 26 - 1
components/mlme/dispatcher/inc/cfg_mlme_acs.h

@@ -155,11 +155,36 @@
 		1, \
 		"External ACS Policy Control")
 
+#define ACS_WEIGHT_MAX_STR_LEN            500
+
+/*
+ * <ini>
+ * 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
+ *
+ * </ini>
+ */
+#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 */

+ 32 - 0
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;
 };
 
 /*

+ 46 - 0
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;

+ 42 - 2
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)) {