xref: /wlan-driver/qca-wifi-host-cmn/umac/mlme/connection_mgr/core/src/wlan_cm_bss_scoring.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1 /*
2  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /**
19  * DOC: contains bss scoring logic
20  */
21 
22 #ifdef WLAN_POLICY_MGR_ENABLE
23 #include "wlan_policy_mgr_api.h"
24 #endif
25 #include <include/wlan_psoc_mlme.h>
26 #include "wlan_psoc_mlme_api.h"
27 #include "cfg_ucfg_api.h"
28 #include "wlan_cm_bss_score_param.h"
29 #include "wlan_scan_api.h"
30 #include "wlan_crypto_global_api.h"
31 #include "wlan_mgmt_txrx_utils_api.h"
32 #ifdef CONN_MGR_ADV_FEATURE
33 #include "wlan_mlme_api.h"
34 #include "wlan_wfa_tgt_if_tx_api.h"
35 #endif
36 #include "wlan_cm_main_api.h"
37 #include "wlan_cm_public_struct.h"
38 
39 #define CM_PCL_RSSI_THRESHOLD -75
40 
41 #define TWO_LINK_BOOST 20
42 #define ONE_LINK_MLMR_BOOST 10
43 #define CANDIDATE_DUMP_MAX_LEN 255
44 
45 #define LINK_SCORE                     BIT(0)
46 #define ASSOC_LINK                     BIT(1)
47 
48 #define IS_LINK_SCORE(ml_flag)         ml_flag & LINK_SCORE
49 #define IS_ASSOC_LINK(ml_flag)         ml_flag & ASSOC_LINK
50 
51 #define CM_BAND_2G_INDEX                   0
52 #define CM_BAND_5G_INDEX                   1
53 #define CM_BAND_6G_INDEX                   2
54 /* 3 is reserved */
55 #define CM_MAX_BAND_INDEX                  4
56 
57 #define CM_SCORE_INDEX_0                   0
58 #define CM_SCORE_INDEX_3                   3
59 #define CM_SCORE_INDEX_7                   7
60 #define CM_SCORE_OFFSET_INDEX_7_4          4
61 #define CM_SCORE_INDEX_11                  11
62 #define CM_SCORE_OFFSET_INDEX_11_8         8
63 #define CM_SCORE_MAX_INDEX                 15
64 #define CM_SCORE_OFFSET_INDEX_15_12        12
65 
66 #define CM_MAX_OCE_WAN_DL_CAP 16
67 
68 #define CM_MAX_CHANNEL_WEIGHT 100
69 #define CM_MAX_CHANNEL_UTILIZATION 100
70 #define CM_MAX_ESTIMATED_AIR_TIME_FRACTION 255
71 #define CM_MAX_AP_LOAD 255
72 
73 #define CM_MAX_WEIGHT_OF_PCL_CHANNELS 255
74 #define CM_PCL_GROUPS_WEIGHT_DIFFERENCE 20
75 
76 /* Congestion threshold (channel load %) to consider band and OCE WAN score */
77 #define CM_CONGESTION_THRSHOLD_FOR_BAND_OCE_SCORE 75
78 
79 #define CM_RSSI_WEIGHTAGE 20
80 #define CM_HT_CAPABILITY_WEIGHTAGE 2
81 #define CM_VHT_CAP_WEIGHTAGE 1
82 #define CM_HE_CAP_WEIGHTAGE 2
83 #define CM_CHAN_WIDTH_WEIGHTAGE 12
84 #define CM_CHAN_BAND_WEIGHTAGE 2
85 #define CM_NSS_WEIGHTAGE 20
86 #define CM_SECURITY_WEIGHTAGE 4
87 #define CM_BEAMFORMING_CAP_WEIGHTAGE 2
88 #define CM_PCL_WEIGHT 10
89 #define CM_CHANNEL_CONGESTION_WEIGHTAGE 5
90 #define CM_OCE_WAN_WEIGHTAGE 2
91 #define CM_OCE_AP_TX_POWER_WEIGHTAGE 5
92 #define CM_OCE_SUBNET_ID_WEIGHTAGE 3
93 #define CM_SAE_PK_AP_WEIGHTAGE 30
94 #define CM_BEST_CANDIDATE_MAX_WEIGHT 200
95 #define CM_MAX_PCT_SCORE 100
96 #define CM_MAX_INDEX_PER_INI 4
97 #define CM_SLO_CONGESTION_MAX_SCORE 80
98 #define CM_ASSOC_INK_BEST_BOOST 20
99 
100 /*
101  * This macro give percentage value of security_weightage to be used as per
102  * security Eg if AP security is WPA 10% will be given for AP.
103  *
104  * Indexes are defined in this way.
105  *     0 Index (BITS 0-7): WPA - Def 25%
106  *     1 Index (BITS 8-15): WPA2- Def 50%
107  *     2 Index (BITS 16-23): WPA3- Def 100%
108  *     3 Index (BITS 24-31): reserved
109  *
110  * if AP security is Open/WEP 0% will be given for AP
111  * These percentage values are stored in HEX. For any index max value, can be 64
112  */
113 #define CM_SECURITY_INDEX_WEIGHTAGE 0x00643219
114 
115 #define CM_BEST_CANDIDATE_MAX_BSS_SCORE (CM_BEST_CANDIDATE_MAX_WEIGHT * 100)
116 #define CM_AVOID_CANDIDATE_MIN_SCORE 1
117 
118 #define CM_GET_SCORE_PERCENTAGE(value32, bw_index) \
119 	QDF_GET_BITS(value32, (8 * (bw_index)), 8)
120 #define CM_SET_SCORE_PERCENTAGE(value32, score_pcnt, bw_index) \
121 	QDF_SET_BITS(value32, (8 * (bw_index)), 8, score_pcnt)
122 
123 #ifdef CONN_MGR_ADV_FEATURE
124 /* 3.2 us + 0.8 us(GI) */
125 #define PPDU_PAYLOAD_SYMBOL_DUR_US 4
126 /* 12.8 us + (0.8 + 1.6)/2 us(GI) */
127 #define HE_PPDU_PAYLOAD_SYMBOL_DUR_US 14
128 #define MAC_HEADER_LEN 26
129 /* Minimum snrDb supported by LUT */
130 #define SNR_DB_TO_BIT_PER_TONE_LUT_MIN -10
131 /* Maximum snrDb supported by LUT */
132 #define SNR_DB_TO_BIT_PER_TONE_LUT_MAX 9
133 #define DB_NUM 20
134 /*
135  * A fudge factor to represent HW implementation margin in dB.
136  * Predicted throughput matches pretty well with OTA throughput with this
137  * fudge factor.
138  */
139 #define SNR_MARGIN_DB 16
140 #define TWO_IN_DB 3
141 static int32_t
142 SNR_DB_TO_BIT_PER_TONE_LUT[DB_NUM] = {0, 171, 212, 262, 323, 396, 484,
143 586, 706, 844, 1000, 1176, 1370, 1583, 1812, 2058, 2317, 2588, 2870, 3161};
144 #endif
145 
cm_is_better_bss(struct scan_cache_entry * bss1,struct scan_cache_entry * bss2)146 static bool cm_is_better_bss(struct scan_cache_entry *bss1,
147 			     struct scan_cache_entry *bss2)
148 {
149 	if (bss1->bss_score > bss2->bss_score)
150 		return true;
151 	else if (bss1->bss_score == bss2->bss_score)
152 		if (bss1->rssi_raw > bss2->rssi_raw)
153 			return true;
154 
155 	return false;
156 }
157 
158 /**
159  * cm_get_rssi_pcnt_for_slot() - calculate rssi % score based on the slot
160  * index between the high rssi and low rssi threshold
161  * @high_rssi_threshold: High rssi of the window
162  * @low_rssi_threshold: low rssi of the window
163  * @high_rssi_pcnt: % score for the high rssi
164  * @low_rssi_pcnt: %score for the low rssi
165  * @bucket_size: bucket size of the window
166  * @bss_rssi: Input rssi for which value need to be calculated
167  *
168  * Return: rssi pct to use for the given rssi
169  */
170 static inline
cm_get_rssi_pcnt_for_slot(int32_t high_rssi_threshold,int32_t low_rssi_threshold,uint32_t high_rssi_pcnt,uint32_t low_rssi_pcnt,uint32_t bucket_size,int8_t bss_rssi)171 int8_t cm_get_rssi_pcnt_for_slot(int32_t high_rssi_threshold,
172 				 int32_t low_rssi_threshold,
173 				 uint32_t high_rssi_pcnt,
174 				 uint32_t low_rssi_pcnt,
175 				 uint32_t bucket_size, int8_t bss_rssi)
176 {
177 	int8_t slot_index, slot_size, rssi_diff, num_slot, rssi_pcnt;
178 
179 	num_slot = ((high_rssi_threshold -
180 		     low_rssi_threshold) / bucket_size) + 1;
181 	slot_size = ((high_rssi_pcnt - low_rssi_pcnt) +
182 		     (num_slot / 2)) / (num_slot);
183 	rssi_diff = high_rssi_threshold - bss_rssi;
184 	slot_index = (rssi_diff / bucket_size) + 1;
185 	rssi_pcnt = high_rssi_pcnt - (slot_size * slot_index);
186 	if (rssi_pcnt < low_rssi_pcnt)
187 		rssi_pcnt = low_rssi_pcnt;
188 
189 	return rssi_pcnt;
190 }
191 
192 /**
193  * cm_calculate_rssi_score() - Calculate RSSI score based on AP RSSI
194  * @score_param: rssi score params
195  * @rssi: rssi of the AP
196  * @rssi_weightage: rssi_weightage out of total weightage
197  *
198  * Return: rssi score
199  */
cm_calculate_rssi_score(struct rssi_config_score * score_param,int32_t rssi,uint8_t rssi_weightage)200 static int32_t cm_calculate_rssi_score(struct rssi_config_score *score_param,
201 				       int32_t rssi, uint8_t rssi_weightage)
202 {
203 	int8_t rssi_pcnt;
204 	int32_t total_rssi_score;
205 	int32_t best_rssi_threshold;
206 	int32_t good_rssi_threshold;
207 	int32_t bad_rssi_threshold;
208 	uint32_t good_rssi_pcnt;
209 	uint32_t bad_rssi_pcnt;
210 	uint32_t good_bucket_size;
211 	uint32_t bad_bucket_size;
212 
213 	best_rssi_threshold = score_param->best_rssi_threshold * (-1);
214 	good_rssi_threshold = score_param->good_rssi_threshold * (-1);
215 	bad_rssi_threshold = score_param->bad_rssi_threshold * (-1);
216 	good_rssi_pcnt = score_param->good_rssi_pcnt;
217 	bad_rssi_pcnt = score_param->bad_rssi_pcnt;
218 	good_bucket_size = score_param->good_rssi_bucket_size;
219 	bad_bucket_size = score_param->bad_rssi_bucket_size;
220 
221 	total_rssi_score = (CM_MAX_PCT_SCORE * rssi_weightage);
222 
223 	/*
224 	 * If RSSI is better than the best rssi threshold then it return full
225 	 * score.
226 	 */
227 	if (rssi > best_rssi_threshold)
228 		return total_rssi_score;
229 	/*
230 	 * If RSSI is less or equal to bad rssi threshold then it return
231 	 * least score.
232 	 */
233 	if (rssi <= bad_rssi_threshold)
234 		return (total_rssi_score * bad_rssi_pcnt) / 100;
235 
236 	/* RSSI lies between best to good rssi threshold */
237 	if (rssi > good_rssi_threshold)
238 		rssi_pcnt = cm_get_rssi_pcnt_for_slot(best_rssi_threshold,
239 				good_rssi_threshold, 100, good_rssi_pcnt,
240 				good_bucket_size, rssi);
241 	else
242 		rssi_pcnt = cm_get_rssi_pcnt_for_slot(good_rssi_threshold,
243 				bad_rssi_threshold, good_rssi_pcnt,
244 				bad_rssi_pcnt, bad_bucket_size,
245 				rssi);
246 
247 	return (total_rssi_score * rssi_pcnt) / 100;
248 }
249 
250 /**
251  * cm_rssi_is_same_bucket() - check if both rssi fall in same bucket
252  * @rssi_top_thresh: high rssi threshold of the the window
253  * @rssi_ref1: rssi ref one
254  * @rssi_ref2: rssi ref two
255  * @bucket_size: bucket size of the window
256  *
257  * Return: true if both fall in same window
258  */
cm_rssi_is_same_bucket(int8_t rssi_top_thresh,int8_t rssi_ref1,int8_t rssi_ref2,int8_t bucket_size)259 static inline bool cm_rssi_is_same_bucket(int8_t rssi_top_thresh,
260 					  int8_t rssi_ref1, int8_t rssi_ref2,
261 					  int8_t bucket_size)
262 {
263 	int8_t rssi_diff1 = 0;
264 	int8_t rssi_diff2 = 0;
265 
266 	rssi_diff1 = rssi_top_thresh - rssi_ref1;
267 	rssi_diff2 = rssi_top_thresh - rssi_ref2;
268 
269 	return (rssi_diff1 / bucket_size) == (rssi_diff2 / bucket_size);
270 }
271 
272 /**
273  * cm_get_rssi_prorate_pct() - Calculate prorated RSSI score
274  * based on AP RSSI. This will be used to determine HT VHT score
275  * @score_param: rssi score params
276  * @rssi: bss rssi
277  * @rssi_weightage: rssi_weightage out of total weightage
278  *
279  * If rssi is greater than good threshold return 100, if less than bad return 0,
280  * if between good and bad, return prorated rssi score for the index.
281  *
282  * Return: rssi prorated score
283  */
284 static int8_t
cm_get_rssi_prorate_pct(struct rssi_config_score * score_param,int32_t rssi,uint8_t rssi_weightage)285 cm_get_rssi_prorate_pct(struct rssi_config_score *score_param,
286 			int32_t rssi, uint8_t rssi_weightage)
287 {
288 	int32_t good_rssi_threshold;
289 	int32_t bad_rssi_threshold;
290 	int8_t rssi_pref_5g_rssi_thresh;
291 	bool same_bucket;
292 
293 	good_rssi_threshold = score_param->good_rssi_threshold * (-1);
294 	bad_rssi_threshold = score_param->bad_rssi_threshold * (-1);
295 	rssi_pref_5g_rssi_thresh = score_param->rssi_pref_5g_rssi_thresh * (-1);
296 
297 	/* If RSSI is greater than good rssi return full weight */
298 	if (rssi > good_rssi_threshold)
299 		return CM_MAX_PCT_SCORE;
300 
301 	same_bucket = cm_rssi_is_same_bucket(good_rssi_threshold, rssi,
302 					     rssi_pref_5g_rssi_thresh,
303 					     score_param->bad_rssi_bucket_size);
304 	if (same_bucket || (rssi < rssi_pref_5g_rssi_thresh))
305 		return 0;
306 	/* If RSSI is less or equal to bad rssi threshold then it return 0 */
307 	if (rssi <= bad_rssi_threshold)
308 		return 0;
309 
310 	/* If RSSI is between good and bad threshold */
311 	return cm_get_rssi_pcnt_for_slot(good_rssi_threshold,
312 					 bad_rssi_threshold,
313 					 score_param->good_rssi_pcnt,
314 					 score_param->bad_rssi_pcnt,
315 					 score_param->bad_rssi_bucket_size,
316 					 rssi);
317 }
318 
319 /**
320  * cm_get_score_for_index() - get score for the given index
321  * @index: index for which we need the score
322  * @weightage: weigtage for the param
323  * @score: per slot score
324  *
325  * Return: score for the index
326  */
cm_get_score_for_index(uint8_t index,uint8_t weightage,struct per_slot_score * score)327 static int32_t cm_get_score_for_index(uint8_t index,
328 				      uint8_t weightage,
329 				      struct per_slot_score *score)
330 {
331 	if (index <= CM_SCORE_INDEX_3)
332 		return weightage * CM_GET_SCORE_PERCENTAGE(
333 				   score->score_pcnt3_to_0,
334 				   index);
335 	else if (index <= CM_SCORE_INDEX_7)
336 		return weightage * CM_GET_SCORE_PERCENTAGE(
337 				   score->score_pcnt7_to_4,
338 				   index - CM_SCORE_OFFSET_INDEX_7_4);
339 	else if (index <= CM_SCORE_INDEX_11)
340 		return weightage * CM_GET_SCORE_PERCENTAGE(
341 				   score->score_pcnt11_to_8,
342 				   index - CM_SCORE_OFFSET_INDEX_11_8);
343 	else
344 		return weightage * CM_GET_SCORE_PERCENTAGE(
345 				   score->score_pcnt15_to_12,
346 				   index - CM_SCORE_OFFSET_INDEX_15_12);
347 }
348 
349 /**
350  * cm_get_congestion_pct() - Calculate congestion pct from esp/qbss load
351  * @entry: bss information
352  *
353  * Return: congestion pct
354  */
cm_get_congestion_pct(struct scan_cache_entry * entry)355 static int32_t cm_get_congestion_pct(struct scan_cache_entry *entry)
356 {
357 	uint32_t ap_load = 0;
358 	uint32_t est_air_time_percentage = 0;
359 	uint32_t congestion = 0;
360 
361 	if (entry->air_time_fraction) {
362 		/* Convert 0-255 range to percentage */
363 		est_air_time_percentage = entry->air_time_fraction *
364 							CM_MAX_CHANNEL_WEIGHT;
365 		est_air_time_percentage = qdf_do_div(est_air_time_percentage,
366 					   CM_MAX_ESTIMATED_AIR_TIME_FRACTION);
367 		/*
368 		 * Calculate channel congestion from estimated air time
369 		 * fraction.
370 		 */
371 		congestion = CM_MAX_CHANNEL_UTILIZATION -
372 					est_air_time_percentage;
373 		if (!congestion)
374 			congestion = 1;
375 	} else if (util_scan_entry_qbssload(entry)) {
376 		ap_load = (entry->qbss_chan_load * CM_MAX_PCT_SCORE);
377 		/*
378 		 * Calculate ap_load in % from qbss channel load from
379 		 * 0-255 range
380 		 */
381 		congestion = qdf_do_div(ap_load, CM_MAX_AP_LOAD);
382 		if (!congestion)
383 			congestion = 1;
384 	}
385 
386 	return congestion;
387 }
388 
389 /**
390  * cm_calculate_congestion_score() - Calculate congestion score
391  * @entry: bss information
392  * @score_params: bss score params
393  * @congestion_pct: congestion pct
394  * @rssi_bad_zone:
395  *
396  * Return: congestion score
397  */
cm_calculate_congestion_score(struct scan_cache_entry * entry,struct scoring_cfg * score_params,uint32_t * congestion_pct,bool rssi_bad_zone)398 static int32_t cm_calculate_congestion_score(struct scan_cache_entry *entry,
399 					     struct scoring_cfg *score_params,
400 					     uint32_t *congestion_pct,
401 					     bool rssi_bad_zone)
402 {
403 	uint32_t window_size;
404 	uint8_t index;
405 	int32_t good_rssi_threshold;
406 	uint8_t chan_congestion_weight;
407 
408 	chan_congestion_weight =
409 		score_params->weight_config.channel_congestion_weightage;
410 
411 	if (!entry)
412 		return chan_congestion_weight *
413 			   CM_GET_SCORE_PERCENTAGE(
414 			   score_params->esp_qbss_scoring.score_pcnt3_to_0,
415 			   CM_SCORE_INDEX_0);
416 
417 	*congestion_pct = cm_get_congestion_pct(entry);
418 
419 	if (!score_params->esp_qbss_scoring.num_slot)
420 		return 0;
421 
422 	if (score_params->esp_qbss_scoring.num_slot >
423 	    CM_SCORE_MAX_INDEX)
424 		score_params->esp_qbss_scoring.num_slot =
425 			CM_SCORE_MAX_INDEX;
426 
427 	good_rssi_threshold =
428 		score_params->rssi_score.good_rssi_threshold * (-1);
429 
430 	/* For bad zone rssi get score from last index */
431 	if (rssi_bad_zone || entry->rssi_raw <= good_rssi_threshold)
432 		return cm_get_score_for_index(
433 			score_params->esp_qbss_scoring.num_slot,
434 			chan_congestion_weight,
435 			&score_params->esp_qbss_scoring);
436 
437 	if (!*congestion_pct)
438 		return chan_congestion_weight *
439 			   CM_GET_SCORE_PERCENTAGE(
440 			   score_params->esp_qbss_scoring.score_pcnt3_to_0,
441 			   CM_SCORE_INDEX_0);
442 
443 	window_size = CM_MAX_PCT_SCORE /
444 			score_params->esp_qbss_scoring.num_slot;
445 
446 	/* Desired values are from 1 to 15, as 0 is for not present. so do +1 */
447 	index = qdf_do_div(*congestion_pct, window_size) + 1;
448 
449 	if (index > score_params->esp_qbss_scoring.num_slot)
450 		index = score_params->esp_qbss_scoring.num_slot;
451 
452 	return cm_get_score_for_index(index,
453 				      chan_congestion_weight,
454 				      &score_params->esp_qbss_scoring);
455 }
456 
457 /**
458  * cm_calculate_nss_score() - Calculate congestion score
459  * @psoc: psoc ptr
460  * @score_config: scoring config
461  * @ap_nss: ap nss
462  * @prorated_pct: prorated % to return dependent on RSSI
463  * @sta_nss: Sta NSS
464  *
465  * Return: nss score
466  */
cm_calculate_nss_score(struct wlan_objmgr_psoc * psoc,struct scoring_cfg * score_config,uint8_t ap_nss,uint8_t prorated_pct,uint32_t sta_nss)467 static int32_t cm_calculate_nss_score(struct wlan_objmgr_psoc *psoc,
468 				      struct scoring_cfg *score_config,
469 				      uint8_t ap_nss, uint8_t prorated_pct,
470 				      uint32_t sta_nss)
471 {
472 	uint8_t nss;
473 	uint8_t score_pct;
474 
475 	nss = ap_nss;
476 	if (sta_nss < nss)
477 		nss = sta_nss;
478 
479 	if (nss == 8)
480 		score_pct = CM_MAX_PCT_SCORE;
481 	if (nss == 4)
482 		score_pct = CM_GET_SCORE_PERCENTAGE(
483 				score_config->nss_weight_per_index[0],
484 				CM_NSS_4x4_INDEX);
485 	else if (nss == 3)
486 		score_pct = CM_GET_SCORE_PERCENTAGE(
487 				score_config->nss_weight_per_index[0],
488 				CM_NSS_3x3_INDEX);
489 	else if (nss == 2)
490 		score_pct = CM_GET_SCORE_PERCENTAGE(
491 				score_config->nss_weight_per_index[0],
492 				CM_NSS_2x2_INDEX);
493 	else
494 		score_pct = CM_GET_SCORE_PERCENTAGE(
495 				score_config->nss_weight_per_index[0],
496 				CM_NSS_1x1_INDEX);
497 
498 	return (score_config->weight_config.nss_weightage * score_pct *
499 		prorated_pct) / CM_MAX_PCT_SCORE;
500 }
501 
cm_calculate_security_score(struct scoring_cfg * score_config,struct security_info neg_sec_info)502 static int32_t cm_calculate_security_score(struct scoring_cfg *score_config,
503 					   struct security_info neg_sec_info)
504 {
505 	uint32_t authmode, key_mgmt, ucastcipherset;
506 	uint8_t score_pct = 0;
507 
508 	authmode = neg_sec_info.authmodeset;
509 	key_mgmt = neg_sec_info.key_mgmt;
510 	ucastcipherset = neg_sec_info.ucastcipherset;
511 
512 	if (QDF_HAS_PARAM(authmode, WLAN_CRYPTO_AUTH_FILS_SK) ||
513 	    QDF_HAS_PARAM(authmode, WLAN_CRYPTO_AUTH_SAE) ||
514 	    QDF_HAS_PARAM(authmode, WLAN_CRYPTO_AUTH_CCKM) ||
515 	    QDF_HAS_PARAM(authmode, WLAN_CRYPTO_AUTH_RSNA) ||
516 	    QDF_HAS_PARAM(authmode, WLAN_CRYPTO_AUTH_8021X)) {
517 		if (QDF_HAS_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_SAE) ||
518 		    QDF_HAS_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_SAE) ||
519 		    QDF_HAS_PARAM(key_mgmt,
520 				  WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B) ||
521 		    QDF_HAS_PARAM(key_mgmt,
522 				  WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B_192) ||
523 		    QDF_HAS_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FILS_SHA256) ||
524 		    QDF_HAS_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FILS_SHA384) ||
525 		    QDF_HAS_PARAM(key_mgmt,
526 				  WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA256) ||
527 		    QDF_HAS_PARAM(key_mgmt,
528 				  WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA384) ||
529 		    QDF_HAS_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_OWE) ||
530 		    QDF_HAS_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_DPP) ||
531 		    QDF_HAS_PARAM(key_mgmt,
532 				  WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384) ||
533 		    QDF_HAS_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_SAE_EXT_KEY) ||
534 		    QDF_HAS_PARAM(key_mgmt,
535 				  WLAN_CRYPTO_KEY_MGMT_FT_SAE_EXT_KEY)) {
536 			/*If security is WPA3, consider score_pct = 100%*/
537 			score_pct = CM_GET_SCORE_PERCENTAGE(
538 					score_config->security_weight_per_index,
539 					CM_SECURITY_WPA3_INDEX);
540 		} else if (QDF_HAS_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_PSK) ||
541 			   QDF_HAS_PARAM(key_mgmt,
542 					 WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X) ||
543 			   QDF_HAS_PARAM(key_mgmt,
544 					 WLAN_CRYPTO_KEY_MGMT_FT_PSK) ||
545 			   QDF_HAS_PARAM(key_mgmt,
546 				WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256) ||
547 			   QDF_HAS_PARAM(key_mgmt,
548 					 WLAN_CRYPTO_KEY_MGMT_PSK_SHA256)) {
549 			/*If security is WPA2, consider score_pct = 50%*/
550 			score_pct = CM_GET_SCORE_PERCENTAGE(
551 				score_config->security_weight_per_index,
552 				CM_SECURITY_WPA2_INDEX);
553 		}
554 	} else if (QDF_HAS_PARAM(authmode, WLAN_CRYPTO_AUTH_SHARED) ||
555 		   QDF_HAS_PARAM(authmode, WLAN_CRYPTO_AUTH_WPA) ||
556 		   QDF_HAS_PARAM(authmode, WLAN_CRYPTO_AUTH_WAPI)) {
557 		/*If security is WPA, consider score_pct = 25%*/
558 		score_pct = CM_GET_SCORE_PERCENTAGE(
559 				score_config->security_weight_per_index,
560 				CM_SECURITY_WPA_INDEX);
561 	}
562 
563 	return (score_config->weight_config.security_weightage * score_pct) /
564 			CM_MAX_PCT_SCORE;
565 }
566 
567 #ifdef WLAN_POLICY_MGR_ENABLE
cm_get_sta_nss(struct wlan_objmgr_psoc * psoc,qdf_freq_t bss_channel_freq,uint8_t vdev_nss_2g,uint8_t vdev_nss_5g)568 static uint32_t cm_get_sta_nss(struct wlan_objmgr_psoc *psoc,
569 			       qdf_freq_t bss_channel_freq,
570 			       uint8_t vdev_nss_2g, uint8_t vdev_nss_5g)
571 {
572 	/*
573 	 * If station support nss as 2*2 but AP support NSS as 1*1,
574 	 * this AP will be given half weight compare to AP which are having
575 	 * NSS as 2*2.
576 	 */
577 
578 	if (policy_mgr_is_chnl_in_diff_band(
579 	    psoc, bss_channel_freq) &&
580 	    policy_mgr_is_hw_dbs_capable(psoc) &&
581 	    !(policy_mgr_is_hw_dbs_2x2_capable(psoc)))
582 		return 1;
583 
584 	return (WLAN_REG_IS_24GHZ_CH_FREQ(bss_channel_freq) ?
585 		vdev_nss_2g :
586 		vdev_nss_5g);
587 }
588 #else
cm_get_sta_nss(struct wlan_objmgr_psoc * psoc,qdf_freq_t bss_channel_freq,uint8_t vdev_nss_2g,uint8_t vdev_nss_5g)589 static uint32_t cm_get_sta_nss(struct wlan_objmgr_psoc *psoc,
590 			       qdf_freq_t bss_channel_freq,
591 			       uint8_t vdev_nss_2g, uint8_t vdev_nss_5g)
592 {
593 	return (WLAN_REG_IS_24GHZ_CH_FREQ(bss_channel_freq) ?
594 		vdev_nss_2g :
595 		vdev_nss_5g);
596 }
597 #endif
598 
599 #ifdef CONN_MGR_ADV_FEATURE
600 static bool
cm_get_pcl_weight_of_channel(uint32_t chan_freq,struct pcl_freq_weight_list * pcl_lst,int * pcl_chan_weight)601 cm_get_pcl_weight_of_channel(uint32_t chan_freq,
602 			     struct pcl_freq_weight_list *pcl_lst,
603 			     int *pcl_chan_weight)
604 {
605 	int i;
606 	bool found = false;
607 
608 	if (!pcl_lst)
609 		return found;
610 
611 	for (i = 0; i < pcl_lst->num_of_pcl_channels; i++) {
612 		if (pcl_lst->pcl_freq_list[i] == chan_freq) {
613 			*pcl_chan_weight = pcl_lst->pcl_weight_list[i];
614 			found = true;
615 			break;
616 		}
617 	}
618 
619 	return found;
620 }
621 
622 /**
623  * cm_calculate_pcl_score() - Calculate PCL score based on PCL weightage
624  * @psoc: psoc ptr
625  * @pcl_chan_weight: pcl weight of BSS channel
626  * @pcl_weightage: PCL _weightage out of total weightage
627  *
628  * Return: pcl score
629  */
cm_calculate_pcl_score(struct wlan_objmgr_psoc * psoc,int pcl_chan_weight,uint8_t pcl_weightage)630 static int32_t cm_calculate_pcl_score(struct wlan_objmgr_psoc *psoc,
631 				      int pcl_chan_weight,
632 				      uint8_t pcl_weightage)
633 {
634 	int32_t pcl_score = 0;
635 	int32_t temp_pcl_chan_weight = 0;
636 
637 	/*
638 	 * Don’t consider pcl weightage for STA connection,
639 	 * if primary interface is configured.
640 	 */
641 	if (!policy_mgr_is_pcl_weightage_required(psoc))
642 		return 0;
643 
644 	/*
645 	 * Always choose the best candidate for non-DBS,
646 	 * irrespective of the band.
647 	 */
648 	if (!policy_mgr_is_hw_dbs_capable(psoc))
649 		return 0;
650 
651 	if (pcl_chan_weight) {
652 		temp_pcl_chan_weight =
653 			(CM_MAX_WEIGHT_OF_PCL_CHANNELS - pcl_chan_weight);
654 		temp_pcl_chan_weight = qdf_do_div(
655 					temp_pcl_chan_weight,
656 					CM_PCL_GROUPS_WEIGHT_DIFFERENCE);
657 		pcl_score = pcl_weightage - temp_pcl_chan_weight;
658 		if (pcl_score < 0)
659 			pcl_score = 0;
660 	}
661 
662 	return pcl_score * CM_MAX_PCT_SCORE;
663 }
664 
665 /**
666  * cm_calculate_oce_wan_score() - Calculate oce wan score
667  * @entry: bss information
668  * @score_params: bss score params
669  *
670  * Return: oce wan score
671  */
cm_calculate_oce_wan_score(struct scan_cache_entry * entry,struct scoring_cfg * score_params)672 static int32_t cm_calculate_oce_wan_score(
673 	struct scan_cache_entry *entry,
674 	struct scoring_cfg *score_params)
675 {
676 	uint32_t window_size;
677 	uint8_t index;
678 	struct oce_reduced_wan_metrics wan_metrics;
679 	uint8_t *mbo_oce_ie;
680 
681 	if (!score_params->oce_wan_scoring.num_slot)
682 		return 0;
683 
684 	if (score_params->oce_wan_scoring.num_slot >
685 	    CM_SCORE_MAX_INDEX)
686 		score_params->oce_wan_scoring.num_slot =
687 			CM_SCORE_MAX_INDEX;
688 
689 	window_size = CM_SCORE_MAX_INDEX /
690 			score_params->oce_wan_scoring.num_slot;
691 	mbo_oce_ie = util_scan_entry_mbo_oce(entry);
692 	if (wlan_parse_oce_reduced_wan_metrics_ie(mbo_oce_ie, &wan_metrics)) {
693 		mlme_err("downlink_av_cap %d", wan_metrics.downlink_av_cap);
694 		/* if capacity is 0 return 0 score */
695 		if (!wan_metrics.downlink_av_cap)
696 			return 0;
697 		/* Desired values are from 1 to WLAN_SCORE_MAX_INDEX */
698 		index = qdf_do_div(wan_metrics.downlink_av_cap,
699 				   window_size);
700 	} else {
701 		index = CM_SCORE_INDEX_0;
702 	}
703 
704 	if (index > score_params->oce_wan_scoring.num_slot)
705 		index = score_params->oce_wan_scoring.num_slot;
706 
707 	return cm_get_score_for_index(index,
708 			score_params->weight_config.oce_wan_weightage,
709 			&score_params->oce_wan_scoring);
710 }
711 
712 /**
713  * cm_calculate_oce_subnet_id_weightage() - Calculate oce subnet id weightage
714  * @entry: bss entry
715  * @score_params: bss score params
716  * @oce_subnet_id_present: check if subnet id subelement is present in OCE IE
717  *
718  * Return: oce subnet id score
719  */
720 static uint32_t
cm_calculate_oce_subnet_id_weightage(struct scan_cache_entry * entry,struct scoring_cfg * score_params,bool * oce_subnet_id_present)721 cm_calculate_oce_subnet_id_weightage(struct scan_cache_entry *entry,
722 				     struct scoring_cfg *score_params,
723 				     bool *oce_subnet_id_present)
724 {
725 	uint32_t score = 0;
726 	uint8_t *mbo_oce_ie;
727 
728 	mbo_oce_ie = util_scan_entry_mbo_oce(entry);
729 	*oce_subnet_id_present = wlan_parse_oce_subnet_id_ie(mbo_oce_ie);
730 
731 	/* Consider 50% weightage if subnet id sub element is present */
732 	if (*oce_subnet_id_present)
733 		score  = score_params->weight_config.oce_subnet_id_weightage *
734 				(CM_MAX_PCT_SCORE / 2);
735 
736 	return score;
737 }
738 
739 /**
740  * cm_calculate_sae_pk_ap_weightage() - Calculate SAE-PK AP weightage
741  * @entry: bss entry
742  * @score_params: bss score params
743  * @sae_pk_cap_present: sae_pk cap presetn in RSNXE capability field
744  *
745  * Return: SAE-PK AP weightage score
746  */
747 static uint32_t
cm_calculate_sae_pk_ap_weightage(struct scan_cache_entry * entry,struct scoring_cfg * score_params,bool * sae_pk_cap_present)748 cm_calculate_sae_pk_ap_weightage(struct scan_cache_entry *entry,
749 				 struct scoring_cfg *score_params,
750 				 bool *sae_pk_cap_present)
751 {
752 	const uint8_t *rsnxe_ie;
753 	const uint8_t *rsnxe_cap;
754 	uint8_t cap_len;
755 
756 	rsnxe_ie = util_scan_entry_rsnxe(entry);
757 
758 	rsnxe_cap = wlan_crypto_parse_rsnxe_ie(rsnxe_ie, &cap_len);
759 
760 	if (!rsnxe_cap)
761 		return 0;
762 
763 	*sae_pk_cap_present = *rsnxe_cap & WLAN_CRYPTO_RSNX_CAP_SAE_PK;
764 	if (*sae_pk_cap_present)
765 		return score_params->weight_config.sae_pk_ap_weightage *
766 			CM_MAX_PCT_SCORE;
767 
768 	return 0;
769 }
770 
771 /**
772  * cm_calculate_oce_ap_tx_pwr_weightage() - Calculate oce ap tx pwr weightage
773  * @entry: bss entry
774  * @score_params: bss score params
775  * @ap_tx_pwr_dbm: pointer to hold ap tx power
776  *
777  * Return: oce ap tx power score
778  */
779 static uint32_t
cm_calculate_oce_ap_tx_pwr_weightage(struct scan_cache_entry * entry,struct scoring_cfg * score_params,int8_t * ap_tx_pwr_dbm)780 cm_calculate_oce_ap_tx_pwr_weightage(struct scan_cache_entry *entry,
781 				     struct scoring_cfg *score_params,
782 				     int8_t *ap_tx_pwr_dbm)
783 {
784 	uint8_t *mbo_oce_ie, ap_tx_pwr_factor;
785 	struct rssi_config_score *rssi_score_param;
786 	int32_t best_rssi_threshold, good_rssi_threshold, bad_rssi_threshold;
787 	uint32_t good_rssi_pcnt, bad_rssi_pcnt, good_bucket_size;
788 	uint32_t score, normalized_ap_tx_pwr, bad_bucket_size;
789 	bool ap_tx_pwr_cap_present = true;
790 
791 	mbo_oce_ie = util_scan_entry_mbo_oce(entry);
792 	if (!wlan_parse_oce_ap_tx_pwr_ie(mbo_oce_ie, ap_tx_pwr_dbm)) {
793 		ap_tx_pwr_cap_present = false;
794 		/* If no OCE AP TX pwr, consider Uplink RSSI = Downlink RSSI */
795 		normalized_ap_tx_pwr = entry->rssi_raw;
796 	} else {
797 		/*
798 		 * Normalized ap_tx_pwr =
799 		 * Uplink RSSI = (STA TX Power - * (AP TX power - RSSI)) in dBm.
800 		 * Currently assuming STA Tx Power to be 20dBm, though later it
801 		 * need to fetched from hal-phy API.
802 		 */
803 		normalized_ap_tx_pwr =
804 			(20 - (*ap_tx_pwr_dbm - entry->rssi_raw));
805 	}
806 
807 	rssi_score_param = &score_params->rssi_score;
808 
809 	best_rssi_threshold = rssi_score_param->best_rssi_threshold * (-1);
810 	good_rssi_threshold = rssi_score_param->good_rssi_threshold * (-1);
811 	bad_rssi_threshold = rssi_score_param->bad_rssi_threshold * (-1);
812 	good_rssi_pcnt = rssi_score_param->good_rssi_pcnt;
813 	bad_rssi_pcnt = rssi_score_param->bad_rssi_pcnt;
814 	good_bucket_size = rssi_score_param->good_rssi_bucket_size;
815 	bad_bucket_size = rssi_score_param->bad_rssi_bucket_size;
816 
817 	/* Uplink RSSI is better than best rssi threshold */
818 	if (normalized_ap_tx_pwr > best_rssi_threshold) {
819 		ap_tx_pwr_factor = CM_MAX_PCT_SCORE;
820 	} else if (normalized_ap_tx_pwr <= bad_rssi_threshold) {
821 		/* Uplink RSSI is less or equal to bad rssi threshold */
822 		ap_tx_pwr_factor = rssi_score_param->bad_rssi_pcnt;
823 	} else if (normalized_ap_tx_pwr > good_rssi_threshold) {
824 		/* Uplink RSSI lies between best to good rssi threshold */
825 		ap_tx_pwr_factor =
826 			cm_get_rssi_pcnt_for_slot(
827 					best_rssi_threshold,
828 					good_rssi_threshold, 100,
829 					good_rssi_pcnt,
830 					good_bucket_size, normalized_ap_tx_pwr);
831 	} else {
832 		/* Uplink RSSI lies between good to best rssi threshold */
833 		ap_tx_pwr_factor =
834 			cm_get_rssi_pcnt_for_slot(
835 					good_rssi_threshold,
836 					bad_rssi_threshold, good_rssi_pcnt,
837 					bad_rssi_pcnt, bad_bucket_size,
838 					normalized_ap_tx_pwr);
839 	}
840 
841 	score  = score_params->weight_config.oce_ap_tx_pwr_weightage *
842 			ap_tx_pwr_factor;
843 
844 	return score;
845 }
846 
cm_is_assoc_allowed(struct psoc_mlme_obj * mlme_psoc_obj,struct scan_cache_entry * entry)847 static bool cm_is_assoc_allowed(struct psoc_mlme_obj *mlme_psoc_obj,
848 				struct scan_cache_entry *entry)
849 {
850 	uint8_t reason;
851 	uint8_t *mbo_oce;
852 	bool check_assoc_disallowed;
853 
854 	mbo_oce = util_scan_entry_mbo_oce(entry);
855 
856 	check_assoc_disallowed =
857 	   mlme_psoc_obj->psoc_cfg.score_config.check_assoc_disallowed;
858 
859 	if (check_assoc_disallowed &&
860 	    wlan_parse_oce_assoc_disallowed_ie(mbo_oce, &reason)) {
861 		mlme_nofl_debug("Candidate("QDF_MAC_ADDR_FMT" freq %d): rssi %d, assoc disallowed set in MBO/OCE IE reason %d",
862 				QDF_MAC_ADDR_REF(entry->bssid.bytes),
863 				entry->channel.chan_freq,
864 				entry->rssi_raw, reason);
865 		return false;
866 	}
867 
868 	return true;
869 }
870 
wlan_cm_set_check_assoc_disallowed(struct wlan_objmgr_psoc * psoc,bool value)871 void wlan_cm_set_check_assoc_disallowed(struct wlan_objmgr_psoc *psoc,
872 					bool value)
873 {
874 	struct psoc_mlme_obj *mlme_psoc_obj;
875 
876 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
877 	if (!mlme_psoc_obj)
878 		return;
879 
880 	mlme_psoc_obj->psoc_cfg.score_config.check_assoc_disallowed = value;
881 }
882 
wlan_cm_get_check_assoc_disallowed(struct wlan_objmgr_psoc * psoc,bool * value)883 void wlan_cm_get_check_assoc_disallowed(struct wlan_objmgr_psoc *psoc,
884 					bool *value)
885 {
886 	struct psoc_mlme_obj *mlme_psoc_obj;
887 
888 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
889 	if (!mlme_psoc_obj) {
890 		*value = false;
891 		return;
892 	}
893 
894 	*value = mlme_psoc_obj->psoc_cfg.score_config.check_assoc_disallowed;
895 }
896 
897 static enum phy_ch_width
cm_calculate_bandwidth(struct scan_cache_entry * entry,struct psoc_phy_config * phy_config)898 cm_calculate_bandwidth(struct scan_cache_entry *entry,
899 		       struct psoc_phy_config *phy_config)
900 {
901 	uint8_t bw_above_20 = 0;
902 	bool is_vht = false;
903 	enum phy_ch_width ch_width;
904 
905 	if (WLAN_REG_IS_24GHZ_CH_FREQ(entry->channel.chan_freq)) {
906 		bw_above_20 = phy_config->bw_above_20_24ghz;
907 		if (phy_config->vht_24G_cap)
908 			is_vht = true;
909 	} else if (phy_config->vht_cap) {
910 		is_vht = true;
911 		bw_above_20 = phy_config->bw_above_20_5ghz;
912 	}
913 
914 	if (IS_WLAN_PHYMODE_160MHZ(entry->phy_mode))
915 		ch_width = CH_WIDTH_160MHZ;
916 	else if (IS_WLAN_PHYMODE_80MHZ(entry->phy_mode))
917 		ch_width = CH_WIDTH_80MHZ;
918 	else if (IS_WLAN_PHYMODE_40MHZ(entry->phy_mode))
919 		ch_width = CH_WIDTH_40MHZ;
920 	else
921 		ch_width = CH_WIDTH_20MHZ;
922 
923 	if (!phy_config->ht_cap &&
924 	    ch_width >= CH_WIDTH_20MHZ)
925 		ch_width = CH_WIDTH_20MHZ;
926 
927 	if (!is_vht && ch_width > CH_WIDTH_40MHZ)
928 		ch_width = CH_WIDTH_40MHZ;
929 
930 	if (!bw_above_20)
931 		ch_width = CH_WIDTH_20MHZ;
932 
933 	return ch_width;
934 }
935 
cm_etp_get_ba_win_size_from_esp(uint8_t esp_ba_win_size)936 static uint8_t cm_etp_get_ba_win_size_from_esp(uint8_t esp_ba_win_size)
937 {
938 	/*
939 	 * BA Window Size subfield is three bits in length and indicates the
940 	 * size of the Block Ack window that is.
941 	 * 802.11-2016.pdf Table 9-262 BA Window Size subfield encoding
942 	 */
943 	switch (esp_ba_win_size) {
944 	case 1: return 2;
945 	case 2: return 4;
946 	case 3: return 6;
947 	case 4: return 8;
948 	case 5: return 16;
949 	case 6: return 32;
950 	case 7: return 64;
951 	default: return 1;
952 	}
953 }
954 
cm_get_etp_ntone(bool is_ht,bool is_vht,enum phy_ch_width ch_width)955 static uint16_t cm_get_etp_ntone(bool is_ht, bool is_vht,
956 				 enum phy_ch_width ch_width)
957 {
958 	uint16_t n_sd = 52, n_seg = 1;
959 
960 	if (is_vht) {
961 		/* Refer Table 21-5 in IEEE80211-2016 Spec */
962 		if (ch_width == CH_WIDTH_20MHZ)
963 			n_sd = 52;
964 		else if (ch_width == CH_WIDTH_40MHZ)
965 			n_sd = 108;
966 		else if (ch_width == CH_WIDTH_80MHZ)
967 			n_sd = 234;
968 		else if (ch_width == CH_WIDTH_80P80MHZ)
969 			n_sd = 234, n_seg = 2;
970 		else if (ch_width == CH_WIDTH_160MHZ)
971 			n_sd = 468;
972 	} else if (is_ht) {
973 		/* Refer Table 19-6 in IEEE80211-2016 Spec */
974 		if (ch_width == CH_WIDTH_20MHZ)
975 			n_sd = 52;
976 		if (ch_width == CH_WIDTH_40MHZ)
977 			n_sd = 108;
978 	} else {
979 		n_sd = 48;
980 	}
981 
982 	return (n_sd * n_seg);
983 }
984 
985 /* Refer Table 27-64 etc in Draft P802.11ax_D7.0.txt */
cm_get_etp_he_ntone(enum phy_ch_width ch_width)986 static uint16_t cm_get_etp_he_ntone(enum phy_ch_width ch_width)
987 {
988 	uint16_t n_sd = 234, n_seg = 1;
989 
990 	if (ch_width == CH_WIDTH_20MHZ)
991 		n_sd = 234;
992 	else if (ch_width == CH_WIDTH_40MHZ)
993 		n_sd = 468;
994 	else if (ch_width == CH_WIDTH_80MHZ)
995 		n_sd = 980;
996 	else if (ch_width == CH_WIDTH_80P80MHZ)
997 		n_sd = 980, n_seg = 2;
998 	else if (ch_width == CH_WIDTH_160MHZ)
999 		n_sd = 1960;
1000 
1001 	return (n_sd * n_seg);
1002 }
1003 
cm_get_etp_phy_header_dur_us(bool is_ht,bool is_vht,uint8_t nss)1004 static uint16_t cm_get_etp_phy_header_dur_us(bool is_ht, bool is_vht,
1005 					     uint8_t nss)
1006 {
1007 	uint16_t dur_us = 0;
1008 
1009 	if (is_vht) {
1010 		/*
1011 		 * Refer Figure 21-4 in 80211-2016 Spec
1012 		 * 8 (L-STF) + 8 (L-LTF) + 4 (L-SIG) +
1013 		 * 8 (VHT-SIG-A) + 4 (VHT-STF) + 4 (VHT-SIG-B)
1014 		 */
1015 		dur_us = 36;
1016 		/* (nss * VHT-LTF) = (nss * 4) */
1017 		dur_us += (nss << 2);
1018 	} else if (is_ht) {
1019 		/*
1020 		 * Refer Figure 19-1 in 80211-2016 Spec
1021 		 * 8 (L-STF) + 8 (L-LTF) + 4 (L-SIG) + 8 (HT-SIG) +
1022 		 * 4 (HT-STF)
1023 		 */
1024 		dur_us = 32;
1025 		/* (nss * HT-LTF = nss * 4) */
1026 		dur_us += (nss << 2);
1027 	} else {
1028 		/*
1029 		 * non-HT
1030 		 * Refer Figure 19-1 in 80211-2016 Spec
1031 		 * 8 (L-STF) + 8 (L-LTF) + 4 (L-SIG)
1032 		 */
1033 		dur_us = 20;
1034 	}
1035 	return dur_us;
1036 }
1037 
1038 static uint32_t
cm_get_etp_max_bits_per_sc_1000x_for_nss(struct wlan_objmgr_psoc * psoc,struct scan_cache_entry * entry,uint8_t nss,struct psoc_phy_config * phy_config)1039 cm_get_etp_max_bits_per_sc_1000x_for_nss(struct wlan_objmgr_psoc *psoc,
1040 					 struct scan_cache_entry *entry,
1041 					 uint8_t nss,
1042 					 struct psoc_phy_config *phy_config)
1043 {
1044 	uint32_t max_bits_per_sc_1000x = 5000; /* 5 * 1000 */
1045 	uint8_t mcs_map;
1046 	struct wlan_ie_vhtcaps *bss_vht_cap;
1047 	struct wlan_ie_hecaps *bss_he_cap;
1048 	uint32_t self_rx_mcs_map;
1049 	QDF_STATUS status;
1050 
1051 	bss_vht_cap = (struct wlan_ie_vhtcaps *)util_scan_entry_vhtcap(entry);
1052 	bss_he_cap = (struct wlan_ie_hecaps *)util_scan_entry_hecap(entry);
1053 	if (!phy_config->vht_cap || !bss_vht_cap)
1054 		return max_bits_per_sc_1000x;
1055 
1056 	status = wlan_mlme_cfg_get_vht_rx_mcs_map(psoc, &self_rx_mcs_map);
1057 	if (QDF_IS_STATUS_ERROR(status))
1058 		return max_bits_per_sc_1000x;
1059 
1060 	if (nss == 4) {
1061 		mcs_map = (self_rx_mcs_map & 0xC0) >> 6;
1062 		mcs_map = QDF_MIN(mcs_map,
1063 				  (bss_vht_cap->rx_mcs_map & 0xC0) >> 6);
1064 	} else if (nss == 3) {
1065 		mcs_map = (self_rx_mcs_map & 0x30) >> 4;
1066 		mcs_map = QDF_MIN(mcs_map,
1067 				  (bss_vht_cap->rx_mcs_map & 0x30) >> 4);
1068 	} else if (nss == 2) {
1069 		mcs_map = (self_rx_mcs_map & 0x0C) >> 2;
1070 		mcs_map = QDF_MIN(mcs_map,
1071 				  (bss_vht_cap->rx_mcs_map & 0x0C) >> 2);
1072 	} else {
1073 		mcs_map = (self_rx_mcs_map & 0x03);
1074 		mcs_map = QDF_MIN(mcs_map, (bss_vht_cap->rx_mcs_map & 0x03));
1075 	}
1076 	if (bss_he_cap) {
1077 		if (mcs_map == 2)
1078 			max_bits_per_sc_1000x = 8333; /* 10 *5/6 * 1000 */
1079 		else if (mcs_map == 1)
1080 			max_bits_per_sc_1000x = 7500; /* 10 * 3/4 * 1000 */
1081 	} else {
1082 		if (mcs_map == 2)
1083 			max_bits_per_sc_1000x = 6667; /* 8 * 5/6 * 1000 */
1084 		else if (mcs_map == 1)
1085 			max_bits_per_sc_1000x = 6000; /* 8 * 3/4 * 1000 */
1086 	}
1087 	return max_bits_per_sc_1000x;
1088 }
1089 
1090 /* Refer Table 9-163 in 80211-2016 Spec */
cm_etp_get_min_mpdu_ss_us_100x(struct htcap_cmn_ie * htcap)1091 static uint32_t cm_etp_get_min_mpdu_ss_us_100x(struct htcap_cmn_ie *htcap)
1092 {
1093 	tSirMacHTParametersInfo *ampdu_param;
1094 	uint8_t ampdu_density;
1095 
1096 	ampdu_param = (tSirMacHTParametersInfo *)&htcap->ampdu_param;
1097 	ampdu_density = ampdu_param->mpduDensity;
1098 
1099 	if (ampdu_density == 1)
1100 		return 25; /* (1/4) * 100 */
1101 	else if (ampdu_density == 2)
1102 		return 50; /* (1/2) * 100 */
1103 	else if (ampdu_density == 3)
1104 		return 100; /* 1 * 100 */
1105 	else if (ampdu_density == 4)
1106 		return 200; /* 2 * 100 */
1107 	else if (ampdu_density == 5)
1108 		return 400; /* 4 * 100 */
1109 	else if (ampdu_density == 6)
1110 		return 800; /* 8 * 100 */
1111 	else if (ampdu_density == 7)
1112 		return 1600; /* 16 * 100 */
1113 	else
1114 		return 100;
1115 }
1116 
1117 /* Refer Table 9-162 in 80211-2016 Spec */
cm_etp_get_max_amsdu_len(struct wlan_objmgr_psoc * psoc,struct htcap_cmn_ie * htcap)1118 static uint32_t cm_etp_get_max_amsdu_len(struct wlan_objmgr_psoc *psoc,
1119 					 struct htcap_cmn_ie *htcap)
1120 {
1121 	uint8_t bss_max_amsdu;
1122 	uint32_t bss_max_amsdu_len;
1123 	QDF_STATUS status;
1124 
1125 	status = wlan_mlme_get_max_amsdu_num(psoc, &bss_max_amsdu);
1126 	if (QDF_IS_STATUS_ERROR(status))
1127 		bss_max_amsdu_len = 3839;
1128 	else if (bss_max_amsdu == 1)
1129 		bss_max_amsdu_len =  7935;
1130 	else
1131 		bss_max_amsdu_len = 3839;
1132 
1133 	return bss_max_amsdu_len;
1134 }
1135 
1136    // Calculate the number of bits per tone based on the input of SNR in dB
1137     // The output is scaled up by BIT_PER_TONE_SCALE for integer representation
1138 static uint32_t
calculate_bit_per_tone(int32_t rssi,enum phy_ch_width ch_width)1139 calculate_bit_per_tone(int32_t rssi, enum phy_ch_width ch_width)
1140 {
1141 	int32_t noise_floor_db_boost;
1142 	int32_t noise_floor_dbm;
1143 	int32_t snr_db;
1144 	int32_t bit_per_tone;
1145 	int32_t lut_in_idx;
1146 
1147 	noise_floor_db_boost = TWO_IN_DB * ch_width;
1148 	noise_floor_dbm = WLAN_NOISE_FLOOR_DBM_DEFAULT + noise_floor_db_boost +
1149 			SNR_MARGIN_DB;
1150 	snr_db = rssi - noise_floor_dbm;
1151 	if (snr_db <= SNR_DB_TO_BIT_PER_TONE_LUT_MAX) {
1152 		lut_in_idx = QDF_MAX(snr_db, SNR_DB_TO_BIT_PER_TONE_LUT_MIN)
1153 			- SNR_DB_TO_BIT_PER_TONE_LUT_MIN;
1154 		lut_in_idx = QDF_MIN(lut_in_idx, DB_NUM - 1);
1155 		bit_per_tone = SNR_DB_TO_BIT_PER_TONE_LUT[lut_in_idx];
1156 	} else {
1157 		/*
1158 		 * SNR_tone = 10^(SNR/10)
1159 		 * log2(1+SNR_tone) ~= log2(SNR_tone) =
1160 		 * log10(SNR_tone)/log10(2) = log10(10^(SNR/10)) / 0.3
1161 		 * = (SNR/10) / 0.3 = SNR/3
1162 		 * So log2(1+SNR_tone) = SNR/3. 1000x for this is SNR*334
1163 		 */
1164 		bit_per_tone = snr_db * 334;
1165 	}
1166 
1167 	return bit_per_tone;
1168 }
1169 
1170 static uint32_t
cm_calculate_etp(struct wlan_objmgr_psoc * psoc,struct scan_cache_entry * entry,struct etp_params * etp_param,uint8_t max_nss,enum phy_ch_width ch_width,bool is_ht,bool is_vht,bool is_he,int8_t rssi,struct psoc_phy_config * phy_config,uint8_t ml_flag)1171 cm_calculate_etp(struct wlan_objmgr_psoc *psoc,
1172 		 struct scan_cache_entry *entry,
1173 		 struct etp_params  *etp_param,
1174 		 uint8_t max_nss, enum phy_ch_width ch_width,
1175 		 bool is_ht, bool is_vht, bool is_he,
1176 		 int8_t rssi,
1177 		 struct psoc_phy_config *phy_config, uint8_t ml_flag)
1178 {
1179 	uint16_t ntone;
1180 	uint16_t phy_hdr_dur_us, max_amsdu_len = 1500, min_mpdu_ss_us_100x = 0;
1181 	uint32_t max_bits_per_sc_1000x, log_2_snr_tone_1000x;
1182 	uint32_t ppdu_payload_dur_us = 0, mpdu_per_ampdu, mpdu_per_ppdu;
1183 	uint32_t single_ppdu_dur_us, estimated_throughput_mbps, data_rate_kbps;
1184 	struct htcap_cmn_ie *htcap;
1185 
1186 	htcap = (struct htcap_cmn_ie *)util_scan_entry_htcap(entry);
1187 	if (ch_width > CH_WIDTH_160MHZ)
1188 		return CM_AVOID_CANDIDATE_MIN_SCORE;
1189 
1190 	if (is_he)
1191 		ntone = cm_get_etp_he_ntone(ch_width);
1192 	else
1193 		ntone = cm_get_etp_ntone(is_ht, is_vht, ch_width);
1194 	phy_hdr_dur_us = cm_get_etp_phy_header_dur_us(is_ht, is_vht, max_nss);
1195 
1196 	max_bits_per_sc_1000x =
1197 		cm_get_etp_max_bits_per_sc_1000x_for_nss(psoc, entry,
1198 							 max_nss, phy_config);
1199 	if (rssi < WLAN_NOISE_FLOOR_DBM_DEFAULT)
1200 		return CM_AVOID_CANDIDATE_MIN_SCORE;
1201 
1202 	log_2_snr_tone_1000x = calculate_bit_per_tone(rssi, ch_width);
1203 
1204 	/* Eq. R-2 Pg:3508 in 80211-2016 Spec */
1205 	if (is_he)
1206 		data_rate_kbps =
1207 			QDF_MIN(log_2_snr_tone_1000x, max_bits_per_sc_1000x) *
1208 			(max_nss * ntone) / HE_PPDU_PAYLOAD_SYMBOL_DUR_US;
1209 	else
1210 		data_rate_kbps =
1211 			QDF_MIN(log_2_snr_tone_1000x, max_bits_per_sc_1000x) *
1212 			(max_nss * ntone) / PPDU_PAYLOAD_SYMBOL_DUR_US;
1213 	if (data_rate_kbps < 1000) {
1214 		/* Return ETP as 1 since datarate is not even 1 Mbps */
1215 		mlme_nofl_debug("%s("QDF_MAC_ADDR_FMT" freq %d): data_rate_kbps %d is less than 1Mbps, so return score %d",
1216 				IS_ASSOC_LINK(ml_flag) ? "Candidate" : "Partner",
1217 				QDF_MAC_ADDR_REF(entry->bssid.bytes),
1218 				entry->channel.chan_freq, data_rate_kbps,
1219 				CM_AVOID_CANDIDATE_MIN_SCORE);
1220 		return CM_AVOID_CANDIDATE_MIN_SCORE;
1221 	}
1222 	/* compute MPDU_p_PPDU */
1223 	if (is_ht) {
1224 		min_mpdu_ss_us_100x =
1225 			cm_etp_get_min_mpdu_ss_us_100x(htcap);
1226 		max_amsdu_len =
1227 			cm_etp_get_max_amsdu_len(psoc, htcap);
1228 		ppdu_payload_dur_us =
1229 			etp_param->data_ppdu_dur_target_us - phy_hdr_dur_us;
1230 		mpdu_per_ampdu =
1231 			QDF_MIN(qdf_ceil(ppdu_payload_dur_us * 100,
1232 					 min_mpdu_ss_us_100x),
1233 				qdf_ceil(ppdu_payload_dur_us *
1234 					 (data_rate_kbps / 1000),
1235 					 (MAC_HEADER_LEN + max_amsdu_len) * 8));
1236 		mpdu_per_ppdu = QDF_MIN(etp_param->ba_window_size,
1237 					QDF_MAX(1, mpdu_per_ampdu));
1238 	} else {
1239 		mpdu_per_ppdu = 1;
1240 	}
1241 
1242 	/* compute PPDU_Dur */
1243 	single_ppdu_dur_us =
1244 		qdf_ceil((MAC_HEADER_LEN + max_amsdu_len) * mpdu_per_ppdu * 8,
1245 			 (data_rate_kbps / 1000) * PPDU_PAYLOAD_SYMBOL_DUR_US);
1246 	single_ppdu_dur_us *= PPDU_PAYLOAD_SYMBOL_DUR_US;
1247 	single_ppdu_dur_us += phy_hdr_dur_us;
1248 
1249 	estimated_throughput_mbps =
1250 		qdf_ceil(mpdu_per_ppdu * max_amsdu_len * 8, single_ppdu_dur_us);
1251 	estimated_throughput_mbps =
1252 		(estimated_throughput_mbps *
1253 		 etp_param->airtime_fraction) /
1254 		 CM_MAX_ESTIMATED_AIR_TIME_FRACTION;
1255 
1256 	if (estimated_throughput_mbps < CM_AVOID_CANDIDATE_MIN_SCORE)
1257 		estimated_throughput_mbps = CM_AVOID_CANDIDATE_MIN_SCORE;
1258 	if (estimated_throughput_mbps > CM_BEST_CANDIDATE_MAX_BSS_SCORE)
1259 		estimated_throughput_mbps = CM_BEST_CANDIDATE_MAX_BSS_SCORE;
1260 
1261 	mlme_nofl_debug("%s("QDF_MAC_ADDR_FMT" freq %d): rssi %d HT %d VHT %d HE %d ATF %d NSS %d ch_width %d data_rate %d",
1262 			IS_ASSOC_LINK(ml_flag) ? "Candidate" : "Partner",
1263 			QDF_MAC_ADDR_REF(entry->bssid.bytes),
1264 			entry->channel.chan_freq, entry->rssi_raw, is_ht,
1265 			is_vht, is_he, etp_param->airtime_fraction,
1266 			entry->nss, ch_width, data_rate_kbps);
1267 	if (is_ht)
1268 		mlme_nofl_debug("min_mpdu_ss_us_100x %d max_amsdu %d ppdu_payload_dur_us %d mpdu_per_ampdu %d mpdu_per_ppdu %d ba_window %d",
1269 				min_mpdu_ss_us_100x, max_amsdu_len,
1270 				ppdu_payload_dur_us, mpdu_per_ampdu,
1271 				mpdu_per_ppdu, etp_param->ba_window_size);
1272 	mlme_nofl_debug("ETP score: ntone %d phy_hdr_dur_us %d max_bits_per_sc_1000x %d snr_tone_1000x %d mpdu_p_ppdu %d max_amsdu %d ppdu_dur_us %d TOTAL %d",
1273 			ntone, phy_hdr_dur_us, max_bits_per_sc_1000x,
1274 			log_2_snr_tone_1000x, mpdu_per_ppdu, max_amsdu_len,
1275 			single_ppdu_dur_us, estimated_throughput_mbps);
1276 
1277 	return estimated_throughput_mbps;
1278 }
1279 
1280 static uint32_t
cm_calculate_etp_score(struct wlan_objmgr_psoc * psoc,struct scan_cache_entry * entry,struct psoc_phy_config * phy_config,enum MLO_TYPE bss_mlo_type,uint8_t ml_flag)1281 cm_calculate_etp_score(struct wlan_objmgr_psoc *psoc,
1282 		       struct scan_cache_entry *entry,
1283 		       struct psoc_phy_config *phy_config,
1284 		       enum MLO_TYPE bss_mlo_type, uint8_t ml_flag)
1285 {
1286 	enum phy_ch_width ch_width;
1287 	uint32_t nss;
1288 	bool is_he_intersect = false;
1289 	bool is_vht_intersect = false;
1290 	bool is_ht_intersect = false;
1291 	struct wlan_esp_info *esp;
1292 	struct wlan_esp_ie *esp_ie;
1293 	struct etp_params etp_param;
1294 	int8_t mlo_prefer_percentage = 0;
1295 	uint32_t score;
1296 	int32_t mlo_score = 0;
1297 
1298 	if (phy_config->he_cap && entry->ie_list.hecap)
1299 		is_he_intersect = true;
1300 	if ((phy_config->vht_cap || phy_config->vht_24G_cap) &&
1301 	    (entry->ie_list.vhtcap ||
1302 	     WLAN_REG_IS_6GHZ_CHAN_FREQ(entry->channel.chan_freq)))
1303 		is_vht_intersect = true;
1304 	if (phy_config->ht_cap && entry->ie_list.htcap)
1305 		is_ht_intersect = true;
1306 	nss = cm_get_sta_nss(psoc, entry->channel.chan_freq,
1307 			     phy_config->vdev_nss_24g,
1308 			     phy_config->vdev_nss_5g);
1309 	nss = QDF_MIN(nss, entry->nss);
1310 	ch_width = cm_calculate_bandwidth(entry, phy_config);
1311 
1312 	/* Initialize default ETP params */
1313 	etp_param.airtime_fraction = 255 / 2;
1314 	etp_param.ba_window_size = 32;
1315 	etp_param.data_ppdu_dur_target_us = 5000; /* 5 msec */
1316 
1317 	if (entry->air_time_fraction) {
1318 		etp_param.airtime_fraction = entry->air_time_fraction;
1319 		esp_ie = (struct wlan_esp_ie *)
1320 			util_scan_entry_esp_info(entry);
1321 		if (esp_ie) {
1322 			esp = &esp_ie->esp_info_AC_BE;
1323 			etp_param.ba_window_size =
1324 				cm_etp_get_ba_win_size_from_esp(esp->ba_window_size);
1325 			etp_param.data_ppdu_dur_target_us =
1326 					50 * esp->ppdu_duration;
1327 			mlme_debug("esp ba_window_size: %d, ppdu_duration: %d",
1328 				   esp->ba_window_size, esp->ppdu_duration);
1329 		}
1330 	} else if (entry->qbss_chan_load) {
1331 		mlme_debug("qbss_chan_load: %d", entry->qbss_chan_load);
1332 		etp_param.airtime_fraction =
1333 			CM_MAX_ESTIMATED_AIR_TIME_FRACTION -
1334 			entry->qbss_chan_load;
1335 	}
1336 	/* If ini vendor_roam_score_algorithm=1, just calculate ETP of all
1337 	 * bssid of ssid selected by high layer, and try to connect AP by
1338 	 * order of ETP, legacy algorithm with following Parameters/Weightage
1339 	 * becomes useless. ETP should be [1Mbps, 20000Mbps],matches score
1340 	 * range: [1, 20000]
1341 	 */
1342 	score = cm_calculate_etp(psoc, entry,
1343 				 &etp_param,
1344 				 nss,
1345 				 ch_width,
1346 				 is_ht_intersect,
1347 				 is_vht_intersect,
1348 				 is_he_intersect,
1349 				 entry->rssi_raw,
1350 				 phy_config,
1351 				 ml_flag);
1352 	if (bss_mlo_type == SLO)
1353 		return score;
1354 	wlan_mlme_get_mlo_prefer_percentage(psoc, &mlo_prefer_percentage);
1355 	if (mlo_prefer_percentage) {
1356 		mlo_score = score;
1357 		mlo_score = mlo_score +
1358 			   (mlo_score * mlo_prefer_percentage) / 100;
1359 		score = mlo_score;
1360 	}
1361 	return score;
1362 }
1363 #else
1364 static bool
cm_get_pcl_weight_of_channel(uint32_t chan_freq,struct pcl_freq_weight_list * pcl_lst,int * pcl_chan_weight)1365 cm_get_pcl_weight_of_channel(uint32_t chan_freq,
1366 			     struct pcl_freq_weight_list *pcl_lst,
1367 			     int *pcl_chan_weight)
1368 {
1369 	return false;
1370 }
1371 
cm_calculate_pcl_score(struct wlan_objmgr_psoc * psoc,int pcl_chan_weight,uint8_t pcl_weightage)1372 static int32_t cm_calculate_pcl_score(struct wlan_objmgr_psoc *psoc,
1373 				      int pcl_chan_weight,
1374 				      uint8_t pcl_weightage)
1375 {
1376 	return 0;
1377 }
1378 
cm_calculate_oce_wan_score(struct scan_cache_entry * entry,struct scoring_cfg * score_params)1379 static int32_t cm_calculate_oce_wan_score(struct scan_cache_entry *entry,
1380 					  struct scoring_cfg *score_params)
1381 {
1382 	return 0;
1383 }
1384 
1385 static uint32_t
cm_calculate_oce_subnet_id_weightage(struct scan_cache_entry * entry,struct scoring_cfg * score_params,bool * oce_subnet_id_present)1386 cm_calculate_oce_subnet_id_weightage(struct scan_cache_entry *entry,
1387 				     struct scoring_cfg *score_params,
1388 				     bool *oce_subnet_id_present)
1389 {
1390 	return 0;
1391 }
1392 
1393 static uint32_t
cm_calculate_sae_pk_ap_weightage(struct scan_cache_entry * entry,struct scoring_cfg * score_params,bool * sae_pk_cap_present)1394 cm_calculate_sae_pk_ap_weightage(struct scan_cache_entry *entry,
1395 				 struct scoring_cfg *score_params,
1396 				 bool *sae_pk_cap_present)
1397 {
1398 	return 0;
1399 }
1400 
1401 static uint32_t
cm_calculate_oce_ap_tx_pwr_weightage(struct scan_cache_entry * entry,struct scoring_cfg * score_params,int8_t * ap_tx_pwr_dbm)1402 cm_calculate_oce_ap_tx_pwr_weightage(struct scan_cache_entry *entry,
1403 				     struct scoring_cfg *score_params,
1404 				     int8_t *ap_tx_pwr_dbm)
1405 {
1406 	return 0;
1407 }
1408 
cm_is_assoc_allowed(struct psoc_mlme_obj * mlme_psoc_obj,struct scan_cache_entry * entry)1409 static inline bool cm_is_assoc_allowed(struct psoc_mlme_obj *mlme_psoc_obj,
1410 				       struct scan_cache_entry *entry)
1411 {
1412 	return true;
1413 }
1414 
1415 static uint32_t
cm_calculate_etp_score(struct wlan_objmgr_psoc * psoc,struct scan_cache_entry * entry,struct psoc_phy_config * phy_config,enum MLO_TYPE bss_mlo_type,uint8_t ml_flag)1416 cm_calculate_etp_score(struct wlan_objmgr_psoc *psoc,
1417 		       struct scan_cache_entry *entry,
1418 		       struct psoc_phy_config *phy_config,
1419 		       enum MLO_TYPE bss_mlo_type, uint8_t ml_flag)
1420 {
1421 	return 0;
1422 }
1423 #endif
1424 
1425 /**
1426  * cm_get_band_score() - Get band preference weightage
1427  * @freq: Operating frequency of the AP
1428  * @score_config: Score configuration
1429  *
1430  * Return: Band score for AP.
1431  */
1432 static int
cm_get_band_score(uint32_t freq,struct scoring_cfg * score_config)1433 cm_get_band_score(uint32_t freq, struct scoring_cfg *score_config)
1434 {
1435 	uint8_t band_index;
1436 	struct weight_cfg *weight_config;
1437 
1438 	weight_config = &score_config->weight_config;
1439 
1440 	if (WLAN_REG_IS_5GHZ_CH_FREQ(freq))
1441 		band_index = CM_BAND_5G_INDEX;
1442 	else if (WLAN_REG_IS_24GHZ_CH_FREQ(freq))
1443 		band_index = CM_BAND_2G_INDEX;
1444 	else if (WLAN_REG_IS_6GHZ_CHAN_FREQ(freq))
1445 		band_index = CM_BAND_6G_INDEX;
1446 	else
1447 		return 0;
1448 
1449 	return weight_config->chan_band_weightage *
1450 	       CM_GET_SCORE_PERCENTAGE(score_config->band_weight_per_index,
1451 				       band_index);
1452 }
1453 
1454 #ifdef WLAN_FEATURE_11BE
1455 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
1456 #if defined (SAP_MULTI_LINK_EMULATION)
wlan_cm_is_eht_allowed_for_current_security(struct wlan_objmgr_psoc * psoc,struct scan_cache_entry * entry,bool is_mlo_connect)1457 bool wlan_cm_is_eht_allowed_for_current_security(struct wlan_objmgr_psoc *psoc,
1458 						 struct scan_cache_entry *entry,
1459 						 bool is_mlo_connect)
1460 {
1461 	return true;
1462 }
1463 #else
wlan_cm_is_eht_allowed_for_current_security(struct wlan_objmgr_psoc * psoc,struct scan_cache_entry * entry,bool is_mlo_connect)1464 bool wlan_cm_is_eht_allowed_for_current_security(struct wlan_objmgr_psoc *psoc,
1465 						 struct scan_cache_entry *entry,
1466 						 bool is_mlo_connect)
1467 {
1468 	bool rf_test_mode = false;
1469 	QDF_STATUS status;
1470 	struct security_info *neg_sec_info;
1471 	uint32_t oem_eht_cfg = 0x0;
1472 	bool mlie_present;
1473 
1474 	status = wlan_mlme_is_rf_test_mode_enabled(psoc, &rf_test_mode);
1475 	if (!QDF_IS_STATUS_SUCCESS(status)) {
1476 		mlme_err("Get rf test mode failed");
1477 		return false;
1478 	}
1479 	if (rf_test_mode) {
1480 		mlme_debug("rf test mode is enabled, ignore setting");
1481 		return true;
1482 	}
1483 
1484 	if (!entry->ie_list.rsn) {
1485 		mlme_debug(QDF_MAC_ADDR_FMT ": RSN IE not present",
1486 			   QDF_MAC_ADDR_REF(entry->bssid.bytes));
1487 		return false;
1488 	}
1489 
1490 	/* Get the OEM EHT configuration. */
1491 	status = wlan_mlme_get_oem_eht_mlo_config(psoc, &oem_eht_cfg);
1492 	if (QDF_IS_STATUS_ERROR(status)) {
1493 		mlme_rl_nofl_err("OEM EHT cfg get failed");
1494 		return false;
1495 	}
1496 
1497 	/* Check if the AP is ML capable or not */
1498 	mlie_present = entry->ie_list.multi_link_bv ? true : false;
1499 
1500 	neg_sec_info = &entry->neg_sec_info;
1501 	if (neg_sec_info->rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED) {
1502 		/* For entreprise APs, only check if PMF is enabled or not */
1503 		if (WLAN_CRYPTO_IS_AKM_ENTERPRISE(neg_sec_info->key_mgmt))
1504 			return true;
1505 
1506 		/* For APs which are both WPA3 and WPA2, only check WPA3 as it
1507 		 * is the more secure AKM.
1508 		 */
1509 		if (WLAN_CRYPTO_IS_WPA3(neg_sec_info->key_mgmt)) {
1510 			if (!WLAN_CRYPTO_IS_AKM_SAE(neg_sec_info->key_mgmt))
1511 				return true;
1512 
1513 			/* If OEM enables APs with HnP to connect, don't check
1514 			 * whether RSNXE has H2E bit set or not. It will be
1515 			 * allowing both HnP and H2E APs.
1516 			 *
1517 			 * If the AP is ML capable, return:
1518 			 *    -True, if H2E is not required and not for ML assoc
1519 			 *    -True, if INI bit value for MLO assoc is set.
1520 			 *
1521 			 * If AP is not ML capable, return:
1522 			 *    -True, if INI bit value for allowing EHT only
1523 			 *     connection is set.
1524 			 */
1525 			if (mlie_present) {
1526 				if (!is_mlo_connect &&
1527 				    !WLAN_CRYPTO_WPA3_SAE_OEM_EHT_CFG_IS_STRICT_H2E(oem_eht_cfg)) {
1528 					return true;
1529 				} else if (is_mlo_connect &&
1530 					   (oem_eht_cfg & WLAN_HOST_CRYPTO_WPA3_SAE_ALLOW_MLO_HnP)) {
1531 					return true;
1532 				}
1533 			} else if (!is_mlo_connect &&
1534 				   (oem_eht_cfg & WLAN_HOST_CRYPTO_WPA3_SAE_ALLOW_NON_MLO_EHT_HnP)) {
1535 				return true;
1536 			}
1537 
1538 			/* If OEM wants strict H2E mandatory for EHT/MLO, then
1539 			 * allow only if candidate has H2E capability
1540 			 */
1541 			return util_scan_entry_sae_h2e_capable(entry);
1542 		} else if (WLAN_CRYPTO_IS_WPA2(neg_sec_info->key_mgmt) &&
1543 			   WLAN_CRYPTO_WPA2_OEM_EHT_CFG_PMF_ALLOWED(oem_eht_cfg)) {
1544 			/* Only checks whether PMF APs are allowed or not via
1545 			 * the INI cfg.
1546 			 * Even if no-PMF APs are allowed to connect, PMF APs
1547 			 * will not be allowed to connect if the bitmap is not
1548 			 * set for PMF APs.
1549 			 *
1550 			 * If the AP is ML capable, return:
1551 			 *     -True, if not for MLO connection
1552 			 *     -INI BIT value for allowing MLO assoc with PMF
1553 			 *      enabled APs.
1554 			 *
1555 			 * If the AP is not ML capable, return:
1556 			 *     -INI BIT value for allowing EHT only connection
1557 			 *      for PMF enabled APS.
1558 			 *
1559 			 */
1560 			if (mlie_present) {
1561 				if (!is_mlo_connect)
1562 					return true;
1563 				return (oem_eht_cfg & WLAN_HOST_CRYPTO_WPA2_ALLOW_MLO_MFPC_SET);
1564 			} else {
1565 				return (oem_eht_cfg & WLAN_HOST_CRYPTO_WPA2_ALLOW_NON_MLO_EHT_MFPC_SET);
1566 			}
1567 		} else {
1568 			return false;
1569 		}
1570 	} else if (!WLAN_CRYPTO_IS_WPA3(neg_sec_info->key_mgmt) &&
1571 		   WLAN_CRYPTO_IS_WPA2(neg_sec_info->key_mgmt) &&
1572 		   WLAN_CRYPTO_WPA2_OEM_EHT_CFG_NO_PMF_ALLOWED(oem_eht_cfg)) {
1573 		/*
1574 		 * Only checks whether no PMF APs are allowed or not via the INI
1575 		 * cfg.
1576 		 * All WPA3 configurations has to be PMF, so only allow
1577 		 * non-WPA3 WPA2 APs in this condition.
1578 		 *
1579 		 * If the AP is ML capable, return:
1580 		 *     -True, if not for MLO connection
1581 		 *     -INI BIT value for allowing MLO assoc with Non-PMF
1582 		 *      capable APs.
1583 		 *
1584 		 * If the AP is not ML capable, return:
1585 		 *     -INI BIT value for allowing EHT only connection
1586 		 *      for Non-PMF capable APs.
1587 		 */
1588 		if (mlie_present) {
1589 			if (!is_mlo_connect)
1590 				return true;
1591 			return (oem_eht_cfg & WLAN_HOST_CRYPTO_WPA2_ALLOW_MLO);
1592 		} else {
1593 			return (oem_eht_cfg & WLAN_HOST_CRYPTO_WPA2_ALLOW_NON_MLO_EHT);
1594 		}
1595 	} else {
1596 		return false;
1597 	}
1598 }
1599 #endif
1600 #endif
1601 
cm_calculate_eht_score(struct wlan_objmgr_psoc * psoc,struct scan_cache_entry * entry,struct scoring_cfg * score_config,struct psoc_phy_config * phy_config,uint8_t prorated_pcnt)1602 static int cm_calculate_eht_score(struct wlan_objmgr_psoc *psoc,
1603 				  struct scan_cache_entry *entry,
1604 				  struct scoring_cfg *score_config,
1605 				  struct psoc_phy_config *phy_config,
1606 				  uint8_t prorated_pcnt)
1607 {
1608 	uint32_t eht_caps_score;
1609 	struct weight_cfg *weight_config;
1610 
1611 	if (!phy_config->eht_cap || !entry->ie_list.ehtcap)
1612 		return 0;
1613 
1614 	if (!wlan_cm_is_eht_allowed_for_current_security(psoc, entry, false))
1615 		return 0;
1616 
1617 	weight_config = &score_config->weight_config;
1618 	eht_caps_score = prorated_pcnt * weight_config->eht_caps_weightage;
1619 
1620 	return eht_caps_score;
1621 }
1622 
1623 /**
1624  * cm_get_puncture_bw() - Get puncture band width
1625  * @entry: Bss scan entry
1626  *
1627  * Return: Total bandwidth of punctured subchannels (unit: MHz)
1628  */
cm_get_puncture_bw(struct scan_cache_entry * entry)1629 static uint16_t cm_get_puncture_bw(struct scan_cache_entry *entry)
1630 {
1631 	uint16_t puncture_bitmap;
1632 	uint8_t num_puncture_bw = 0;
1633 
1634 	puncture_bitmap = entry->channel.puncture_bitmap;
1635 	while (puncture_bitmap) {
1636 		if (puncture_bitmap & 1)
1637 			++num_puncture_bw;
1638 		puncture_bitmap >>= 1;
1639 	}
1640 	return num_puncture_bw * 20;
1641 }
1642 
cm_get_su_beam_former(struct scan_cache_entry * entry)1643 static bool cm_get_su_beam_former(struct scan_cache_entry *entry)
1644 {
1645 	struct wlan_ie_ehtcaps *eht_cap;
1646 	struct wlan_eht_cap_info *eht_cap_info;
1647 
1648 	eht_cap = (struct wlan_ie_ehtcaps *)util_scan_entry_ehtcap(entry);
1649 	if (eht_cap) {
1650 		eht_cap_info = (struct wlan_eht_cap_info *)eht_cap->eht_mac_cap;
1651 		if (eht_cap_info->su_beamformer)
1652 			return true;
1653 	}
1654 
1655 	return false;
1656 }
1657 #else
cm_calculate_eht_score(struct wlan_objmgr_psoc * psoc,struct scan_cache_entry * entry,struct scoring_cfg * score_config,struct psoc_phy_config * phy_config,uint8_t prorated_pcnt)1658 static int cm_calculate_eht_score(struct wlan_objmgr_psoc *psoc,
1659 				  struct scan_cache_entry *entry,
1660 				  struct scoring_cfg *score_config,
1661 				  struct psoc_phy_config *phy_config,
1662 				  uint8_t prorated_pcnt)
1663 {
1664 	return 0;
1665 }
1666 
cm_get_puncture_bw(struct scan_cache_entry * entry)1667 static uint16_t cm_get_puncture_bw(struct scan_cache_entry *entry)
1668 {
1669 	return 0;
1670 }
1671 
cm_get_su_beam_former(struct scan_cache_entry * entry)1672 static bool cm_get_su_beam_former(struct scan_cache_entry *entry)
1673 {
1674 	return false;
1675 }
1676 #endif
1677 
1678 #define CM_BAND_WIDTH_NUM 16
1679 #define CM_BAND_WIDTH_UNIT 20
1680 uint16_t link_bw_score[CM_BAND_WIDTH_NUM] = {
1681 9, 18, 27, 35, 44, 53, 56, 67, 74, 80, 86, 90, 93, 96, 98, 100};
1682 
cm_get_bw_score(uint8_t bw_weightage,uint16_t bw,uint8_t prorated_pcnt)1683 static uint32_t cm_get_bw_score(uint8_t bw_weightage, uint16_t bw,
1684 				uint8_t prorated_pcnt)
1685 {
1686 	uint32_t score;
1687 	uint8_t index;
1688 
1689 	index = bw / CM_BAND_WIDTH_UNIT - 1;
1690 	if (index >= CM_BAND_WIDTH_NUM)
1691 		index = CM_BAND_WIDTH_NUM - 1;
1692 	score = bw_weightage * link_bw_score[index]
1693 		* prorated_pcnt / CM_MAX_PCT_SCORE;
1694 
1695 	return score;
1696 }
1697 
1698 /**
1699  * cm_get_ch_width() - Get channel width of bss scan entry
1700  * @entry: Bss scan entry
1701  * @phy_config: Phy config
1702  *
1703  * Return: Channel width (unit: MHz)
1704  */
cm_get_ch_width(struct scan_cache_entry * entry,struct psoc_phy_config * phy_config)1705 static uint16_t cm_get_ch_width(struct scan_cache_entry *entry,
1706 				struct psoc_phy_config *phy_config)
1707 {
1708 	uint16_t bw, total_bw = 0;
1709 	uint8_t bw_above_20 = 0;
1710 	bool is_vht = false;
1711 
1712 	if (WLAN_REG_IS_24GHZ_CH_FREQ(entry->channel.chan_freq)) {
1713 		bw_above_20 = phy_config->bw_above_20_24ghz;
1714 		if (phy_config->vht_24G_cap)
1715 			is_vht = true;
1716 	} else if (phy_config->vht_cap) {
1717 		is_vht = true;
1718 		bw_above_20 = phy_config->bw_above_20_5ghz;
1719 	}
1720 	if (IS_WLAN_PHYMODE_320MHZ(entry->phy_mode))
1721 		bw = 320;
1722 	else if (IS_WLAN_PHYMODE_160MHZ(entry->phy_mode))
1723 		bw = 160;
1724 	else if (IS_WLAN_PHYMODE_80MHZ(entry->phy_mode))
1725 		bw = 80;
1726 	else if (IS_WLAN_PHYMODE_40MHZ(entry->phy_mode))
1727 		bw = 40;
1728 	else
1729 		bw = 20;
1730 	if (!phy_config->ht_cap && bw > 20)
1731 		bw = 20;
1732 
1733 	if (!is_vht && bw > 40)
1734 		bw = 40;
1735 
1736 	total_bw = bw - cm_get_puncture_bw(entry);
1737 
1738 	return total_bw;
1739 }
1740 
1741 #ifdef WLAN_FEATURE_11BE_MLO
1742 #define CM_MLO_BAD_RSSI_PCT 61
1743 #define CM_MLO_CONGESTION_PCT_BAD_RSSI 6
1744 
1745 static uint8_t mlo_boost_pct[MLO_TYPE_MAX] = {0, 10, CM_MAX_PCT_SCORE};
1746 
1747 /**
1748  * struct mlo_rssi_pct: MLO AP rssi joint factor and score percent
1749  * @joint_factor: rssi joint factor (0 - 100)
1750  * @rssi_pcnt: Rssi score percent (0 - 100)
1751  * @prorate_pcnt: RSSI prorated percent
1752  */
1753 struct mlo_rssi_pct {
1754 	uint16_t joint_factor;
1755 	uint16_t rssi_pcnt;
1756 	uint16_t prorate_pcnt;
1757 };
1758 
1759 #define CM_RSSI_BUCKET_NUM 7
1760 static struct mlo_rssi_pct mlo_rssi_pcnt[CM_RSSI_BUCKET_NUM] = {
1761 {80, 100, 100}, {60, 87, 100}, {44, 74, 100}, {30, 61, 100}, {20, 48, 54},
1762 {10, 35, 28}, {0, 22, 1} };
1763 
1764 /**
1765  * cm_get_mlo_rssi_score() - Calculate joint rssi score for MLO AP
1766  * @rssi_weightage: rssi weightage
1767  * @link1_rssi: link1 rssi
1768  * @link2_rssi: link2 rssi
1769  * @prorate_pcnt: pointer to store RSSI prorated percent
1770  *
1771  * Return: MLO AP joint rssi score
1772  */
cm_get_mlo_rssi_score(uint8_t rssi_weightage,int8_t link1_rssi,int8_t link2_rssi,uint16_t * prorate_pcnt)1773 static uint32_t cm_get_mlo_rssi_score(uint8_t rssi_weightage, int8_t link1_rssi,
1774 				      int8_t link2_rssi, uint16_t *prorate_pcnt)
1775 {
1776 	int8_t link1_factor = 0, link2_factor = 0;
1777 	int32_t joint_factor = 0;
1778 	int16_t rssi_pcnt = 0;
1779 	int8_t i;
1780 
1781 	/* Calculate RSSI score -- using joint rssi, but limit to 2 links */
1782 	link1_factor = QDF_MAX(QDF_MIN(link1_rssi, -50), -95) + 95;
1783 	link2_factor = QDF_MAX(QDF_MIN(link2_rssi, -50), -95) + 95;
1784 	joint_factor = QDF_MIN((link1_factor * link1_factor +
1785 			    link2_factor * link2_factor) * 100 / (2 * 45 * 45),
1786 			    100);
1787 	for (i = 0; i < CM_RSSI_BUCKET_NUM; i++)
1788 		if (joint_factor > mlo_rssi_pcnt[i].joint_factor) {
1789 			rssi_pcnt = mlo_rssi_pcnt[i].rssi_pcnt;
1790 			*prorate_pcnt = mlo_rssi_pcnt[i].prorate_pcnt;
1791 			break;
1792 		}
1793 
1794 	return (rssi_weightage * rssi_pcnt);
1795 }
1796 
cm_calculate_emlsr_score(struct weight_cfg * weight_config)1797 static inline int cm_calculate_emlsr_score(struct weight_cfg *weight_config)
1798 {
1799 	return weight_config->emlsr_weightage * mlo_boost_pct[MLSR];
1800 }
1801 
cm_get_entry(qdf_list_t * scan_list,struct qdf_mac_addr * link_addr)1802 struct scan_cache_entry *cm_get_entry(qdf_list_t *scan_list,
1803 				      struct qdf_mac_addr *link_addr)
1804 {
1805 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
1806 	struct scan_cache_node *curr_entry = NULL;
1807 
1808 	qdf_list_peek_front(scan_list, &cur_node);
1809 	while (cur_node) {
1810 		curr_entry = qdf_container_of(cur_node, struct scan_cache_node,
1811 					      node);
1812 		if (!qdf_mem_cmp(&curr_entry->entry->mac_addr,
1813 				 link_addr, QDF_MAC_ADDR_SIZE))
1814 			return curr_entry->entry;
1815 
1816 		qdf_list_peek_next(scan_list, cur_node, &next_node);
1817 		cur_node = next_node;
1818 		next_node = NULL;
1819 	}
1820 
1821 	return NULL;
1822 }
1823 
1824 #ifdef CONN_MGR_ADV_FEATURE
cm_get_sta_mlo_conn_max_num(struct wlan_objmgr_psoc * psoc)1825 static uint8_t cm_get_sta_mlo_conn_max_num(struct wlan_objmgr_psoc *psoc)
1826 {
1827 	return wlan_mlme_get_sta_mlo_conn_max_num(psoc);
1828 }
1829 
is_freq_dbs_or_sbs(struct wlan_objmgr_psoc * psoc,qdf_freq_t freq_1,qdf_freq_t freq_2)1830 static bool is_freq_dbs_or_sbs(struct wlan_objmgr_psoc *psoc,
1831 			       qdf_freq_t freq_1,
1832 			       qdf_freq_t freq_2)
1833 {
1834 	return !policy_mgr_2_freq_always_on_same_mac(psoc, freq_1, freq_2);
1835 }
1836 
1837 #else
1838 static inline
cm_get_sta_mlo_conn_max_num(struct wlan_objmgr_psoc * psoc)1839 uint8_t cm_get_sta_mlo_conn_max_num(struct wlan_objmgr_psoc *psoc)
1840 {
1841 	return WLAN_UMAC_MLO_MAX_DEV;
1842 }
1843 
is_freq_dbs_or_sbs(struct wlan_objmgr_psoc * psoc,qdf_freq_t freq_1,qdf_freq_t freq_2)1844 static inline bool is_freq_dbs_or_sbs(struct wlan_objmgr_psoc *psoc,
1845 				      qdf_freq_t freq_1,
1846 				      qdf_freq_t freq_2)
1847 {
1848 	return false;
1849 }
1850 #endif
1851 
1852 /**
1853  * cm_bss_mlo_type() - Get mlo type of bss scan entry
1854  * @psoc: Pointer of psoc object
1855  * @entry: Bss scan entry
1856  * @scan_list:
1857  *
1858  * Return: MLO AP type: SLO, MLMR or EMLSR.
1859  */
cm_bss_mlo_type(struct wlan_objmgr_psoc * psoc,struct scan_cache_entry * entry,qdf_list_t * scan_list)1860 enum MLO_TYPE cm_bss_mlo_type(struct wlan_objmgr_psoc *psoc,
1861 			      struct scan_cache_entry *entry,
1862 			      qdf_list_t *scan_list)
1863 {
1864 	uint8_t mlo_link_num;
1865 	uint8_t i;
1866 	uint32_t freq_entry;
1867 	uint32_t freq[MLD_MAX_LINKS - 1];
1868 	struct scan_cache_entry *entry_partner[MLD_MAX_LINKS - 1];
1869 	bool multi_link = false;
1870 
1871 	mlo_link_num = cm_get_sta_mlo_conn_max_num(psoc);
1872 	if (!entry->ie_list.multi_link_bv)
1873 		return SLO;
1874 	else if (!entry->ml_info.num_links)
1875 		return SLO;
1876 	else if (mlo_link_num == 1)
1877 		return SLO;
1878 
1879 	for (i = 0; i < entry->ml_info.num_links; i++) {
1880 		if (!entry->ml_info.link_info[i].is_valid_link)
1881 			continue;
1882 		freq_entry = entry->channel.chan_freq;
1883 		freq[i] = entry->ml_info.link_info[i].freq;
1884 		entry_partner[i] =
1885 			cm_get_entry(scan_list,
1886 				     &entry->ml_info.link_info[i].link_addr);
1887 		if (entry_partner[i])
1888 			freq[i] = entry_partner[i]->channel.chan_freq;
1889 		if (is_freq_dbs_or_sbs(psoc, freq[i], freq_entry)) {
1890 			return MLMR;
1891 		} else if (freq[i] == freq_entry) {
1892 			mlme_debug("Partner " QDF_MAC_ADDR_FMT
1893 				   " freq %d same as assoc freq, invalid it",
1894 				   QDF_MAC_ADDR_REF(entry->ml_info.link_info[i].link_addr.bytes),
1895 				   freq[i]);
1896 			entry->ml_info.link_info[i].is_valid_link = false;
1897 		} else {
1898 			multi_link = true;
1899 		}
1900 	}
1901 
1902 	if (multi_link)
1903 		return MLSR;
1904 	else
1905 		return SLO;
1906 }
1907 
1908 /**
1909  * cm_get_mlo_congestion_score() - Get mlo jointer congestion percent
1910  * @bw1: channel width of link1
1911  * @bw2: channel width of link2
1912  * @congestion_score1: congestion score of link1
1913  * @congestion_score2: congestion score of link2
1914  * @score_params: score param
1915  *
1916  * Return: Mlo jointer congestion percent
1917  */
1918 static uint32_t
cm_get_mlo_congestion_score(uint16_t bw1,uint16_t bw2,uint32_t congestion_score1,uint32_t congestion_score2,struct scoring_cfg * score_params)1919 cm_get_mlo_congestion_score(uint16_t bw1,
1920 			    uint16_t bw2,
1921 			    uint32_t congestion_score1,
1922 			    uint32_t congestion_score2,
1923 			    struct scoring_cfg *score_params)
1924 {
1925 	uint32_t congestion_best;
1926 	uint32_t congestion_worst;
1927 	uint32_t congestion_weight;
1928 
1929 	congestion_weight =
1930 		score_params->weight_config.channel_congestion_weightage;
1931 	if (congestion_score1 > congestion_score2) {
1932 		congestion_best = congestion_score1;
1933 		congestion_worst = congestion_score2 * bw1 / (bw1 + bw2);
1934 	} else if (congestion_score1 < congestion_score2) {
1935 		congestion_best = congestion_score2;
1936 		congestion_worst = congestion_score1 * bw2 / (bw1 + bw2);
1937 	} else {
1938 		congestion_best = congestion_score1;
1939 		congestion_worst = congestion_score2 / 2;
1940 	}
1941 	congestion_best = congestion_best * CM_SLO_CONGESTION_MAX_SCORE /
1942 			 CM_MAX_PCT_SCORE;
1943 	congestion_worst = congestion_worst * CM_SLO_CONGESTION_MAX_SCORE /
1944 			 CM_MAX_PCT_SCORE;
1945 	congestion_worst = QDF_MIN(congestion_worst, 20 * congestion_weight);
1946 
1947 	return congestion_best + congestion_worst;
1948 }
1949 
1950 /**
1951  * cm_estimate_rssi() - Get estimated rssi by frequency
1952  * @rssi_entry: Rssi of bss scan entry
1953  * @freq_entry: Frequency of bss scan entry
1954  * @freq_partner: Frequency of partner link of MLO
1955  *
1956  * Estimated equation: RSSI(2G) = RSSI(5G) + 7 = RSSI(6G) + 8
1957  *
1958  * Return: Estimated rssi of partner link of MLO
1959  */
cm_estimate_rssi(int8_t rssi_entry,uint32_t freq_entry,uint32_t freq_partner)1960 static int8_t cm_estimate_rssi(int8_t rssi_entry, uint32_t freq_entry,
1961 			       uint32_t freq_partner)
1962 {
1963 	if (wlan_reg_is_24ghz_ch_freq(freq_entry)) {
1964 		if (wlan_reg_is_5ghz_ch_freq(freq_partner))
1965 			return rssi_entry - 7;
1966 		else if (wlan_reg_is_6ghz_chan_freq(freq_partner))
1967 			return rssi_entry - 8;
1968 	} else if (wlan_reg_is_5ghz_ch_freq(freq_entry)) {
1969 		if (wlan_reg_is_24ghz_ch_freq(freq_partner))
1970 			return rssi_entry + 7;
1971 		else if (wlan_reg_is_6ghz_chan_freq(freq_partner))
1972 			return rssi_entry - 1;
1973 	} else if (wlan_reg_is_6ghz_chan_freq(freq_entry)) {
1974 		if (wlan_reg_is_24ghz_ch_freq(freq_partner))
1975 			return rssi_entry + 8;
1976 		else if (wlan_reg_is_5ghz_ch_freq(freq_partner))
1977 			return rssi_entry + 1;
1978 	}
1979 
1980 	return rssi_entry;
1981 }
1982 
1983 static int cm_calculate_bss_score(struct wlan_objmgr_psoc *psoc,
1984 				  struct scan_cache_entry *entry,
1985 				  int pcl_chan_weight,
1986 				  struct qdf_mac_addr *bssid_hint,
1987 				  qdf_list_t *scan_list,
1988 				  uint8_t ml_flag);
1989 
1990 /**
1991  * cm_calculate_mlo_bss_score() - Calculate mlo bss score
1992  * @psoc: Pointer to psoc object
1993  * @entry: Bss scan entry
1994  * @score_params: score parameters
1995  * @phy_config: Phy config
1996  * @scan_list: Scan entry list of bss candidates after filtering
1997  * @rssi_prorated_pct: Rssi prorated percent
1998  * @pcl_chan_weight: PCL chan weight
1999  *
2000  * For MLMR case, besides adding MLMR boost score,
2001  * calculate joint RSSI/band width/congestion score for combination of
2002  * scan entry + each partner link, select highest total score as candidate
2003  * combination, only activate that partner link.
2004  *
2005  * Return: MLO AP joint total score
2006  */
cm_calculate_mlo_bss_score(struct wlan_objmgr_psoc * psoc,struct scan_cache_entry * entry,struct scoring_cfg * score_params,struct psoc_phy_config * phy_config,qdf_list_t * scan_list,uint8_t * rssi_prorated_pct,int pcl_chan_weight)2007 static int cm_calculate_mlo_bss_score(struct wlan_objmgr_psoc *psoc,
2008 				      struct scan_cache_entry *entry,
2009 				      struct scoring_cfg *score_params,
2010 				      struct psoc_phy_config *phy_config,
2011 				      qdf_list_t *scan_list,
2012 				      uint8_t *rssi_prorated_pct,
2013 				      int pcl_chan_weight)
2014 {
2015 	struct scan_cache_entry *entry_partner[MLD_MAX_LINKS - 1];
2016 	int32_t rssi[MLD_MAX_LINKS - 1];
2017 	uint32_t rssi_score[MLD_MAX_LINKS - 1] = {};
2018 	uint16_t prorated_pct[MLD_MAX_LINKS - 1] = {};
2019 	uint32_t freq[MLD_MAX_LINKS - 1];
2020 	uint16_t ch_width[MLD_MAX_LINKS - 1];
2021 	uint32_t bandwidth_score[MLD_MAX_LINKS - 1] = {};
2022 	uint32_t congestion_pct[MLD_MAX_LINKS - 1] = {};
2023 	uint32_t congestion_score[MLD_MAX_LINKS - 1] = {};
2024 	uint32_t cong_total_score[MLD_MAX_LINKS - 1] = {};
2025 	uint32_t total_score[MLD_MAX_LINKS - 1] = {};
2026 	uint8_t i, j;
2027 	uint16_t chan_width;
2028 	uint32_t best_total_score = 0;
2029 	uint8_t best_partner_index = 0;
2030 	uint32_t cong_pct = 0;
2031 	uint32_t cong_score = 0;
2032 	uint32_t freq_entry;
2033 	struct weight_cfg *weight_config;
2034 	struct partner_link_info *link;
2035 	struct wlan_objmgr_pdev *pdev;
2036 	bool rssi_bad_zone;
2037 	bool eht_capab;
2038 	struct partner_link_info tmp_link_info;
2039 	uint32_t tmp_total_score = 0;
2040 	uint32_t assoc_score = 0;
2041 	uint32_t link_score[MLD_MAX_LINKS - 1] = {0};
2042 	bool is_assoc_link_best = true;
2043 	uint32_t assoc_band_score;
2044 	uint32_t link_band_score[MLD_MAX_LINKS - 1] = {0};
2045 	uint32_t total_band_score[MLD_MAX_LINKS - 1] = {0};
2046 
2047 	wlan_psoc_mlme_get_11be_capab(psoc, &eht_capab);
2048 	if (!eht_capab)
2049 		return 0;
2050 
2051 	weight_config = &score_params->weight_config;
2052 	freq_entry = entry->channel.chan_freq;
2053 	chan_width = cm_get_ch_width(entry, phy_config);
2054 	cong_score = cm_calculate_congestion_score(entry,
2055 						   score_params,
2056 						   &cong_pct, false);
2057 
2058 	assoc_score =
2059 		cm_calculate_bss_score(psoc, entry, pcl_chan_weight,
2060 				       NULL, scan_list, LINK_SCORE | ASSOC_LINK);
2061 	entry->ml_info.link_score = assoc_score;
2062 
2063 	assoc_band_score = cm_get_band_score(entry->channel.chan_freq,
2064 					     score_params);
2065 
2066 	link = &entry->ml_info.link_info[0];
2067 	for (i = 0; i < entry->ml_info.num_links; i++) {
2068 		if (!link[i].is_valid_link)
2069 			continue;
2070 		entry_partner[i] = cm_get_entry(scan_list, &link[i].link_addr);
2071 		if (entry_partner[i])
2072 			freq[i] = entry_partner[i]->channel.chan_freq;
2073 		else
2074 			freq[i] = link[i].freq;
2075 		if (!is_freq_dbs_or_sbs(psoc, freq[i], freq_entry)) {
2076 			mlme_nofl_debug("freq %d and %d can't be MLMR",
2077 					freq[i], freq_entry);
2078 			continue;
2079 		}
2080 
2081 		if (entry_partner[i]) {
2082 			link_score[i] =
2083 				cm_calculate_bss_score(psoc, entry_partner[i],
2084 						       pcl_chan_weight,
2085 						       NULL, scan_list, LINK_SCORE);
2086 			entry_partner[i]->ml_info.link_score = link_score[i];
2087 
2088 			rssi[i] = entry_partner[i]->rssi_raw;
2089 			ch_width[i] = cm_get_ch_width(entry_partner[i],
2090 						      phy_config);
2091 		} else {
2092 			rssi[i] = cm_estimate_rssi(entry->rssi_raw,
2093 						   freq_entry,
2094 						   freq[i]);
2095 			pdev = psoc->soc_objmgr.wlan_pdev_list[0];
2096 			ch_width[i] =
2097 				wlan_reg_get_op_class_width(pdev,
2098 							    link[i].op_class,
2099 							    true);
2100 			mlme_nofl_debug("No entry for partner, estimate with rnr");
2101 		}
2102 		rssi_score[i] =
2103 			cm_get_mlo_rssi_score(weight_config->rssi_weightage,
2104 					      entry->rssi_raw, rssi[i],
2105 					      &prorated_pct[i]);
2106 
2107 		bandwidth_score[i] =
2108 			cm_get_bw_score(weight_config->chan_width_weightage,
2109 					chan_width + ch_width[i],
2110 					prorated_pct[i]);
2111 
2112 		rssi_bad_zone = prorated_pct[i] < CM_MAX_PCT_SCORE;
2113 		congestion_score[i] =
2114 			cm_calculate_congestion_score(entry_partner[i],
2115 						      score_params,
2116 						      &congestion_pct[i],
2117 						      rssi_bad_zone);
2118 		cong_total_score[i] =
2119 			cm_get_mlo_congestion_score(chan_width,
2120 						    ch_width[i],
2121 						    cong_score,
2122 						    congestion_score[i],
2123 						    score_params);
2124 
2125 		link_band_score[i] = cm_get_band_score(freq[i], score_params);
2126 		total_band_score[i] =
2127 			(assoc_band_score + link_band_score[i]) / 2;
2128 
2129 		total_score[i] = rssi_score[i] + bandwidth_score[i] +
2130 				 cong_total_score[i] + total_band_score[i];
2131 		if (total_score[i] > best_total_score) {
2132 			best_total_score = total_score[i];
2133 			best_partner_index = i;
2134 		}
2135 
2136 		mlme_nofl_debug("ML idx %d score: freq (%d + %d) rssi %u pror %u bw %u congest %u %u %u band score: %u %u total %u",
2137 				i, freq_entry, freq[i], rssi_score[i],
2138 				prorated_pct[i], bandwidth_score[i], cong_score,
2139 				congestion_score[i], cong_total_score[i],
2140 				assoc_band_score, link_band_score[i],
2141 				total_score[i]);
2142 	}
2143 
2144 	*rssi_prorated_pct = prorated_pct[best_partner_index];
2145 
2146 	/* reorder the link idx per score */
2147 	for (j = 0; j < entry->ml_info.num_links; j++) {
2148 		tmp_total_score = total_score[j];
2149 		best_partner_index = j;
2150 		for (i = j + 1; i < entry->ml_info.num_links; i++) {
2151 			if (tmp_total_score < total_score[i]) {
2152 				tmp_total_score = total_score[i];
2153 				best_partner_index = i;
2154 			}
2155 		}
2156 
2157 		if (best_partner_index != j) {
2158 			tmp_link_info = entry->ml_info.link_info[j];
2159 			entry->ml_info.link_info[j] =
2160 				entry->ml_info.link_info[best_partner_index];
2161 			entry->ml_info.link_info[best_partner_index] =
2162 							tmp_link_info;
2163 			total_score[best_partner_index] = total_score[j];
2164 		}
2165 		total_score[j] = 0;
2166 	}
2167 
2168 	for (i = 0; i < entry->ml_info.num_links; i++) {
2169 		if (link_score[i] > assoc_score) {
2170 			is_assoc_link_best = false;
2171 			break;
2172 		}
2173 	}
2174 	if (is_assoc_link_best) {
2175 		mlme_nofl_debug("assoc link (freq %d) is best, boost %d",
2176 				freq_entry, CM_ASSOC_INK_BEST_BOOST);
2177 		best_total_score += CM_ASSOC_INK_BEST_BOOST;
2178 	}
2179 
2180 	best_total_score += weight_config->mlo_weightage *
2181 			    mlo_boost_pct[MLMR];
2182 	entry->ml_info.ml_bss_score = best_total_score;
2183 
2184 	return best_total_score;
2185 }
2186 
2187 #else
cm_calculate_emlsr_score(struct weight_cfg * weight_config)2188 static inline int cm_calculate_emlsr_score(struct weight_cfg *weight_config)
2189 {
2190 	return 0;
2191 }
2192 
cm_calculate_mlo_bss_score(struct wlan_objmgr_psoc * psoc,struct scan_cache_entry * entry,struct scoring_cfg * score_params,struct psoc_phy_config * phy_config,qdf_list_t * scan_list,uint8_t * rssi_prorated_pct,int pcl_chan_weight)2193 static int cm_calculate_mlo_bss_score(struct wlan_objmgr_psoc *psoc,
2194 				      struct scan_cache_entry *entry,
2195 				      struct scoring_cfg *score_params,
2196 				      struct psoc_phy_config *phy_config,
2197 				      qdf_list_t *scan_list,
2198 				      uint8_t *rssi_prorated_pct,
2199 				      int pcl_chan_weight)
2200 {
2201 	return 0;
2202 }
2203 #endif
2204 
2205 #if defined(WLAN_FEATURE_11BE_MLO) && defined(CONN_MGR_ADV_FEATURE)
2206 static void
cm_sort_vendor_algo_mlo_bss_entry(struct wlan_objmgr_psoc * psoc,struct scan_cache_entry * entry,struct psoc_phy_config * phy_config,qdf_list_t * scan_list,enum MLO_TYPE bss_mlo_type)2207 cm_sort_vendor_algo_mlo_bss_entry(struct wlan_objmgr_psoc *psoc,
2208 				  struct scan_cache_entry *entry,
2209 				  struct psoc_phy_config *phy_config,
2210 				  qdf_list_t *scan_list,
2211 				  enum MLO_TYPE bss_mlo_type)
2212 {
2213 	struct scan_cache_entry *entry_partner[MLD_MAX_LINKS - 1];
2214 	uint32_t freq[MLD_MAX_LINKS - 1];
2215 	uint32_t etp_score[MLD_MAX_LINKS - 1] = {0};
2216 	uint32_t total_score[MLD_MAX_LINKS - 1] = {0};
2217 	uint8_t i, j;
2218 	uint32_t best_total_score = 0;
2219 	uint8_t best_partner_index = 0;
2220 	uint32_t freq_entry;
2221 	struct partner_link_info *link;
2222 	bool eht_capab;
2223 	struct partner_link_info tmp_link_info;
2224 	uint32_t tmp_total_score = 0;
2225 	uint8_t mlo_support_link_num;
2226 
2227 	wlan_psoc_mlme_get_11be_capab(psoc, &eht_capab);
2228 	if (!eht_capab)
2229 		return;
2230 
2231 	mlo_support_link_num = wlan_mlme_get_sta_mlo_conn_max_num(psoc);
2232 	link = &entry->ml_info.link_info[0];
2233 	freq_entry = entry->channel.chan_freq;
2234 	for (i = 0; i < entry->ml_info.num_links; i++) {
2235 		if (!link[i].is_valid_link)
2236 			continue;
2237 
2238 		entry_partner[i] = cm_get_entry(scan_list, &link[i].link_addr);
2239 		if (entry_partner[i])
2240 			freq[i] = entry_partner[i]->channel.chan_freq;
2241 		else
2242 			freq[i] = link[i].freq;
2243 
2244 		if (policy_mgr_2_freq_always_on_same_mac(psoc, freq[i],
2245 							 freq_entry)) {
2246 			total_score[i] = 0;
2247 			if (!wlan_mlme_is_5gl_5gh_mlsr_supported(psoc)) {
2248 				mlme_nofl_debug("Partner(" QDF_MAC_ADDR_FMT " freq %d): assoc freq %d can't be MLMR",
2249 						QDF_MAC_ADDR_REF(link[i].link_addr.bytes),
2250 						freq[i], freq_entry);
2251 				if (mlo_support_link_num <= WLAN_MAX_ML_DEFAULT_LINK ||
2252 				    entry->ml_info.num_links <
2253 				    WLAN_MAX_ML_DEFAULT_LINK)
2254 					link[i].is_valid_link = false;
2255 			}
2256 			continue;
2257 		}
2258 
2259 		if (!entry_partner[i])
2260 			continue;
2261 
2262 		etp_score[i] = cm_calculate_etp_score(psoc, entry_partner[i],
2263 						      phy_config, bss_mlo_type,
2264 						      0);
2265 
2266 		total_score[i] = etp_score[i];
2267 		if (total_score[i] > best_total_score) {
2268 			best_total_score = total_score[i];
2269 			best_partner_index = i;
2270 		}
2271 	}
2272 
2273 	/* reorder the link idx per score */
2274 	for (j = 0; j < entry->ml_info.num_links; j++) {
2275 		tmp_total_score = total_score[j];
2276 		best_partner_index = j;
2277 		for (i = j + 1; i < entry->ml_info.num_links; i++) {
2278 			if (tmp_total_score < total_score[i]) {
2279 				tmp_total_score = total_score[i];
2280 				best_partner_index = i;
2281 			}
2282 		}
2283 
2284 		if (best_partner_index != j) {
2285 			tmp_link_info = entry->ml_info.link_info[j];
2286 			entry->ml_info.link_info[j] =
2287 				entry->ml_info.link_info[best_partner_index];
2288 			entry->ml_info.link_info[best_partner_index] =
2289 							tmp_link_info;
2290 			total_score[best_partner_index] = total_score[j];
2291 		}
2292 		total_score[j] = 0;
2293 	}
2294 }
2295 #else
2296 static void
cm_sort_vendor_algo_mlo_bss_entry(struct wlan_objmgr_psoc * psoc,struct scan_cache_entry * entry,struct psoc_phy_config * phy_config,qdf_list_t * scan_list,enum MLO_TYPE bss_mlo_type)2297 cm_sort_vendor_algo_mlo_bss_entry(struct wlan_objmgr_psoc *psoc,
2298 				  struct scan_cache_entry *entry,
2299 				  struct psoc_phy_config *phy_config,
2300 				  qdf_list_t *scan_list,
2301 				  enum MLO_TYPE bss_mlo_type)
2302 {}
2303 #endif
2304 
2305 /**
2306  * cm_calculate_ml_scores() - Calculate mlo score of AP
2307  * @psoc: Pointer to psoc object
2308  * @entry: Bss scan entry
2309  * @score_config: Score config
2310  * @phy_config: Self phy config
2311  * @scan_list: Scan entry list of bss candidates after filtering
2312  * @ml_flag: MLO flag
2313  * @bss_mlo_type: Bss MLO type
2314  * @pcl_chan_weight:  PCL channel weight
2315  * @rssi_prorated_pct: RSSI prorated pencentage
2316  *
2317  * For MLO AP, consider partner link to calculate combined score,
2318  * For legacy/SLO AP or link, get total score of RSSI, bandwidth,
2319  * congestion and band.
2320  *
2321  * Return: MLO score of AP
2322  */
cm_calculate_ml_scores(struct wlan_objmgr_psoc * psoc,struct scan_cache_entry * entry,struct scoring_cfg * score_config,struct psoc_phy_config * phy_config,qdf_list_t * scan_list,uint8_t ml_flag,enum MLO_TYPE bss_mlo_type,int pcl_chan_weight,uint8_t * rssi_prorated_pct)2323 static int cm_calculate_ml_scores(struct wlan_objmgr_psoc *psoc,
2324 				  struct scan_cache_entry *entry,
2325 				  struct scoring_cfg *score_config,
2326 				  struct psoc_phy_config *phy_config,
2327 				  qdf_list_t *scan_list, uint8_t ml_flag,
2328 				  enum MLO_TYPE bss_mlo_type,
2329 				  int pcl_chan_weight,
2330 				  uint8_t *rssi_prorated_pct)
2331 {
2332 	int32_t score = 0;
2333 	int32_t rssi_score = 0;
2334 	int32_t congestion_pct = 0;
2335 	int32_t bandwidth_score = 0;
2336 	int32_t congestion_score = 0;
2337 	uint8_t prorated_pcnt = 0;
2338 	int32_t band_score = 0;
2339 	struct weight_cfg *weight_config;
2340 
2341 	weight_config = &score_config->weight_config;
2342 	if (IS_LINK_SCORE(ml_flag) || bss_mlo_type == SLO ||
2343 	    bss_mlo_type == MLSR ||
2344 	    !wlan_cm_is_eht_allowed_for_current_security(psoc, entry, false)) {
2345 		rssi_score =
2346 			cm_calculate_rssi_score(&score_config->rssi_score,
2347 						entry->rssi_raw,
2348 						weight_config->rssi_weightage);
2349 		prorated_pcnt =
2350 			cm_get_rssi_prorate_pct(&score_config->rssi_score,
2351 						entry->rssi_raw,
2352 						weight_config->rssi_weightage);
2353 		score += rssi_score;
2354 		bandwidth_score =
2355 			cm_get_bw_score(weight_config->chan_width_weightage,
2356 					cm_get_ch_width(entry, phy_config),
2357 					prorated_pcnt);
2358 		score += bandwidth_score;
2359 
2360 		congestion_score =
2361 			cm_calculate_congestion_score(entry,
2362 						      score_config,
2363 						      &congestion_pct, 0);
2364 		score += congestion_score * CM_SLO_CONGESTION_MAX_SCORE /
2365 			 CM_MAX_PCT_SCORE;
2366 
2367 		band_score = cm_get_band_score(entry->channel.chan_freq,
2368 					       score_config);
2369 		score += band_score;
2370 
2371 		if (bss_mlo_type == MLSR)
2372 			score += cm_calculate_emlsr_score(weight_config);
2373 	} else {
2374 		score += cm_calculate_mlo_bss_score(psoc, entry, score_config,
2375 						    phy_config, scan_list,
2376 						    &prorated_pcnt,
2377 						    pcl_chan_weight);
2378 	}
2379 
2380 	*rssi_prorated_pct = prorated_pcnt;
2381 
2382 	return score;
2383 }
2384 
2385 static bool
cm_check_and_update_bssid_hint_entry_bss_score(struct scan_cache_entry * entry,struct scoring_cfg * score_config,struct qdf_mac_addr * bssid_hint,uint8_t ml_flag)2386 cm_check_and_update_bssid_hint_entry_bss_score(struct scan_cache_entry *entry,
2387 					       struct scoring_cfg *score_config,
2388 					       struct qdf_mac_addr *bssid_hint,
2389 					       uint8_t ml_flag)
2390 {
2391 	if (!score_config->is_bssid_hint_priority)
2392 		return false;
2393 
2394 	if (!bssid_hint || !qdf_is_macaddr_equal(bssid_hint, &entry->bssid))
2395 		return false;
2396 
2397 	entry->bss_score = entry->bss_score + CM_BEST_CANDIDATE_MAX_BSS_SCORE;
2398 	mlme_nofl_debug("%s("QDF_MAC_ADDR_FMT" freq %d): rssi %d BSSID hint given, give max score %d",
2399 			IS_ASSOC_LINK(ml_flag) ? "Candidate" : "Partner",
2400 			QDF_MAC_ADDR_REF(entry->bssid.bytes),
2401 			entry->channel.chan_freq, entry->rssi_raw,
2402 			entry->bss_score);
2403 	return true;
2404 }
2405 
2406 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
cm_vendor_specific_boost(struct wlan_objmgr_psoc * psoc,struct scan_cache_entry * entry,int32_t score)2407 static void cm_vendor_specific_boost(struct wlan_objmgr_psoc *psoc,
2408 				     struct scan_cache_entry *entry,
2409 				     int32_t score)
2410 {
2411 	struct partner_link_info *link = NULL;
2412 	uint32_t freq = 0;
2413 	uint32_t freq_entry = 0;
2414 
2415 	/* Add boost of 20% for 2 link candidate */
2416 	if (entry->ml_info.num_links == TWO_LINK)
2417 		score = score  + (score * TWO_LINK_BOOST) / 100;
2418 
2419 	if (entry->ml_info.num_links == ONE_LINK) {
2420 		freq_entry = entry->channel.chan_freq;
2421 		link = &entry->ml_info.link_info[0];
2422 
2423 		if (!link[0].is_valid_link)
2424 			return;
2425 
2426 		freq = link[0].freq;
2427 
2428 		/* Add boost of 10% for one link MLMR candidate  */
2429 		if (!policy_mgr_are_2_freq_on_same_mac(psoc,
2430 						       freq,
2431 						       freq_entry))
2432 			score = score + (score * ONE_LINK_MLMR_BOOST) / 100;
2433 		}
2434 
2435 	entry->bss_score = score;
2436 }
2437 #else
cm_vendor_specific_boost(struct wlan_objmgr_psoc * psoc,struct scan_cache_entry * entry,int32_t score)2438 static void cm_vendor_specific_boost(struct wlan_objmgr_psoc *psoc,
2439 				     struct scan_cache_entry *entry,
2440 				     int32_t score)
2441 {
2442 }
2443 #endif
2444 
2445 /**
2446  * cm_calculate_bss_score() - Calculate score of AP or 1 link of MLO AP
2447  * @psoc: Pointer to psoc object
2448  * @entry: Bss scan entry
2449  * @pcl_chan_weight: pcl chan weight
2450  * @bssid_hint: bssid hint
2451  * @scan_list: Scan entry list of bss candidates after filtering
2452  * @ml_flag: ML related bitmap
2453  *           BIT(0): SET, if score is for link.
2454  *           BIT(1): SET, if it is for Assoc link.
2455  *
2456  * For MLO AP, consider partner link to calculate combined score, prefer to
2457  * select best link as assoc link.
2458  * For legacy AP or 1 link of MLO AP, just consider single link.
2459  * Prefer to select AP of higher score to connect by sort AP by score.
2460  *
2461  * Return: score of AP or 1 link of MLO AP
2462  */
cm_calculate_bss_score(struct wlan_objmgr_psoc * psoc,struct scan_cache_entry * entry,int pcl_chan_weight,struct qdf_mac_addr * bssid_hint,qdf_list_t * scan_list,uint8_t ml_flag)2463 static int cm_calculate_bss_score(struct wlan_objmgr_psoc *psoc,
2464 				  struct scan_cache_entry *entry,
2465 				  int pcl_chan_weight,
2466 				  struct qdf_mac_addr *bssid_hint,
2467 				  qdf_list_t *scan_list,
2468 				  uint8_t ml_flag)
2469 {
2470 	int32_t score = 0;
2471 	int32_t rssi_score = 0;
2472 	int32_t pcl_score = 0;
2473 	int32_t ht_score = 0;
2474 	int32_t vht_score = 0;
2475 	int32_t he_score = 0;
2476 	int32_t bandwidth_score = 0;
2477 	int32_t beamformee_score = 0;
2478 	int32_t band_score = 0;
2479 	int32_t nss_score = 0;
2480 	int32_t security_score = 0;
2481 	int32_t congestion_score = 0;
2482 	int32_t congestion_pct = 0;
2483 	int32_t oce_wan_score = 0;
2484 	uint8_t oce_ap_tx_pwr_score = 0;
2485 	uint8_t oce_subnet_id_score = 0;
2486 	uint32_t sae_pk_score = 0;
2487 	bool oce_subnet_id_present = 0;
2488 	bool sae_pk_cap_present = 0;
2489 	int8_t ap_tx_pwr_dbm = 0;
2490 	uint8_t prorated_pcnt = 0;
2491 	bool is_vht = false;
2492 	int8_t good_rssi_threshold;
2493 	int8_t rssi_pref_5g_rssi_thresh;
2494 	bool same_bucket = false;
2495 	bool ap_su_beam_former = false;
2496 	struct wlan_ie_vhtcaps *vht_cap;
2497 	struct wlan_ie_hecaps *he_cap;
2498 	struct scoring_cfg *score_config;
2499 	struct weight_cfg *weight_config;
2500 	uint32_t sta_nss;
2501 	struct psoc_mlme_obj *mlme_psoc_obj;
2502 	struct psoc_phy_config *phy_config;
2503 	uint32_t eht_score;
2504 	enum MLO_TYPE bss_mlo_type;
2505 	int ml_score = 0;
2506 
2507 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
2508 	if (!mlme_psoc_obj)
2509 		return 0;
2510 
2511 	phy_config = &mlme_psoc_obj->psoc_cfg.phy_config;
2512 	score_config = &mlme_psoc_obj->psoc_cfg.score_config;
2513 	weight_config = &score_config->weight_config;
2514 
2515 	bss_mlo_type = cm_bss_mlo_type(psoc, entry, scan_list);
2516 	if (score_config->vendor_roam_score_algorithm) {
2517 		score = cm_calculate_etp_score(psoc, entry, phy_config,
2518 					       bss_mlo_type, ml_flag);
2519 		entry->bss_score = score;
2520 		if (bss_mlo_type == MLMR || bss_mlo_type == MLSR)
2521 			cm_sort_vendor_algo_mlo_bss_entry(psoc, entry,
2522 							  phy_config, scan_list,
2523 							  bss_mlo_type);
2524 		/* vendor specific boost */
2525 		cm_vendor_specific_boost(psoc, entry, score);
2526 
2527 		if (cm_check_and_update_bssid_hint_entry_bss_score(entry,
2528 								   score_config,
2529 								   bssid_hint,
2530 								   ml_flag))
2531 			return CM_BEST_CANDIDATE_MAX_BSS_SCORE;
2532 
2533 		mlme_nofl_debug("Candidate score("QDF_MAC_ADDR_FMT" freq %d): rssi %d score %d",
2534 				QDF_MAC_ADDR_REF(entry->bssid.bytes),
2535 				entry->channel.chan_freq,
2536 				entry->rssi_raw, entry->bss_score);
2537 
2538 		return score;
2539 	}
2540 
2541 	ml_score += cm_calculate_ml_scores(psoc, entry, score_config,
2542 					   phy_config, scan_list,
2543 					   ml_flag, bss_mlo_type,
2544 					   pcl_chan_weight,
2545 					   &prorated_pcnt);
2546 	score += ml_score;
2547 
2548 	/*
2549 	 * Check if the given entry matches with the BSSID Hint after
2550 	 * calculating ML Scores as the cm_calculate_ml_scores() also sorts
2551 	 * the partner links based on hw mode capabilities & link scores
2552 	 */
2553 	if (cm_check_and_update_bssid_hint_entry_bss_score(entry, score_config,
2554 							   bssid_hint, ml_flag))
2555 		return CM_BEST_CANDIDATE_MAX_BSS_SCORE;
2556 
2557 	pcl_score = cm_calculate_pcl_score(psoc, pcl_chan_weight,
2558 					   weight_config->pcl_weightage);
2559 	score += pcl_score;
2560 
2561 	/*
2562 	 * Add HT weight if HT is supported by the AP. In case
2563 	 * of 6 GHZ AP, HT and VHT won't be supported so that
2564 	 * these weightage to the same by default to match
2565 	 * with 2.4/5 GHZ APs where HT, VHT is supported
2566 	 */
2567 	if (phy_config->ht_cap && (entry->ie_list.htcap ||
2568 	    WLAN_REG_IS_6GHZ_CHAN_FREQ(entry->channel.chan_freq)))
2569 		ht_score = prorated_pcnt *
2570 				weight_config->ht_caps_weightage;
2571 	score += ht_score;
2572 
2573 	if (WLAN_REG_IS_24GHZ_CH_FREQ(entry->channel.chan_freq)) {
2574 		if (phy_config->vht_24G_cap)
2575 			is_vht = true;
2576 	} else if (phy_config->vht_cap) {
2577 		is_vht = true;
2578 	}
2579 
2580 	/* Add VHT score to 6 GHZ AP to match with 2.4/5 GHZ APs */
2581 	if (is_vht && (entry->ie_list.vhtcap ||
2582 	    WLAN_REG_IS_6GHZ_CHAN_FREQ(entry->channel.chan_freq)))
2583 		vht_score = prorated_pcnt *
2584 				 weight_config->vht_caps_weightage;
2585 	score += vht_score;
2586 
2587 	if (phy_config->he_cap && entry->ie_list.hecap)
2588 		he_score = prorated_pcnt *
2589 			   weight_config->he_caps_weightage;
2590 	score += he_score;
2591 
2592 	good_rssi_threshold =
2593 		score_config->rssi_score.good_rssi_threshold * (-1);
2594 	rssi_pref_5g_rssi_thresh =
2595 		score_config->rssi_score.rssi_pref_5g_rssi_thresh * (-1);
2596 	if (entry->rssi_raw < good_rssi_threshold)
2597 		same_bucket = cm_rssi_is_same_bucket(good_rssi_threshold,
2598 				entry->rssi_raw, rssi_pref_5g_rssi_thresh,
2599 				score_config->rssi_score.bad_rssi_bucket_size);
2600 
2601 	vht_cap = (struct wlan_ie_vhtcaps *)util_scan_entry_vhtcap(entry);
2602 	he_cap = (struct wlan_ie_hecaps *)util_scan_entry_hecap(entry);
2603 
2604 	if (vht_cap && vht_cap->su_beam_former) {
2605 		ap_su_beam_former = true;
2606 	} else if (he_cap && QDF_GET_BITS(*(he_cap->he_phy_cap.phy_cap_bytes +
2607 		   WLAN_HE_PHYCAP_SU_BFER_OFFSET), WLAN_HE_PHYCAP_SU_BFER_IDX,
2608 		   WLAN_HE_PHYCAP_SU_BFER_BITS)) {
2609 		ap_su_beam_former = true;
2610 	} else {
2611 		ap_su_beam_former = cm_get_su_beam_former(entry);
2612 	}
2613 
2614 	if (phy_config->beamformee_cap && is_vht &&
2615 	    ap_su_beam_former &&
2616 	    (entry->rssi_raw > rssi_pref_5g_rssi_thresh) && !same_bucket)
2617 		beamformee_score = CM_MAX_PCT_SCORE *
2618 				weight_config->beamforming_cap_weightage;
2619 	score += beamformee_score;
2620 
2621 	/*
2622 	 * Consider OCE WAN score score only if
2623 	 * congestion_pct is greater than CONGESTION_THRSHOLD_FOR_BAND_OCE_SCORE
2624 	 */
2625 	if (congestion_pct < CM_CONGESTION_THRSHOLD_FOR_BAND_OCE_SCORE) {
2626 		oce_wan_score = cm_calculate_oce_wan_score(entry, score_config);
2627 		score += oce_wan_score;
2628 	}
2629 
2630 	oce_ap_tx_pwr_score =
2631 		cm_calculate_oce_ap_tx_pwr_weightage(entry, score_config,
2632 						     &ap_tx_pwr_dbm);
2633 	score += oce_ap_tx_pwr_score;
2634 
2635 	oce_subnet_id_score = cm_calculate_oce_subnet_id_weightage(entry,
2636 						score_config,
2637 						&oce_subnet_id_present);
2638 	score += oce_subnet_id_score;
2639 
2640 	sae_pk_score = cm_calculate_sae_pk_ap_weightage(entry, score_config,
2641 							&sae_pk_cap_present);
2642 	score += sae_pk_score;
2643 
2644 	sta_nss = cm_get_sta_nss(psoc, entry->channel.chan_freq,
2645 				 phy_config->vdev_nss_24g,
2646 				 phy_config->vdev_nss_5g);
2647 
2648 	/*
2649 	 * If station support nss as 2*2 but AP support NSS as 1*1,
2650 	 * this AP will be given half weight compare to AP which are having
2651 	 * NSS as 2*2.
2652 	 */
2653 	nss_score = cm_calculate_nss_score(psoc, score_config, entry->nss,
2654 					   prorated_pcnt, sta_nss);
2655 	score += nss_score;
2656 
2657 	/*
2658 	 * Since older FW will stick to the single AKM for roaming,
2659 	 * no need to check the fw capability.
2660 	 */
2661 	security_score = cm_calculate_security_score(score_config,
2662 						     entry->neg_sec_info);
2663 	score += security_score;
2664 
2665 	eht_score = cm_calculate_eht_score(psoc, entry, score_config,
2666 					   phy_config,
2667 					   prorated_pcnt);
2668 	score += eht_score;
2669 
2670 	if (!(IS_LINK_SCORE(ml_flag)))
2671 		entry->bss_score = score;
2672 
2673 	if (bss_mlo_type == SLO || IS_LINK_SCORE(ml_flag))
2674 		mlme_nofl_debug("%s("QDF_MAC_ADDR_FMT" freq %d): rssi %d HT %d VHT %d HE %d EHT %d su_bfer %d phy %d atf %d qbss %d cong_pct %d NSS %d ap_tx_pwr %d oce_subnet %d sae_pk_cap %d prorated_pcnt %d keymgmt 0x%x mlo type %d",
2675 				IS_ASSOC_LINK(ml_flag) ? "Candidate" : "Partner",
2676 				QDF_MAC_ADDR_REF(entry->bssid.bytes),
2677 				entry->channel.chan_freq,
2678 				entry->rssi_raw,
2679 				util_scan_entry_htcap(entry) ? 1 : 0,
2680 				util_scan_entry_vhtcap(entry) ? 1 : 0,
2681 				util_scan_entry_hecap(entry) ? 1 : 0,
2682 				util_scan_entry_ehtcap(entry) ? 1 : 0,
2683 				ap_su_beam_former,
2684 				entry->phy_mode, entry->air_time_fraction,
2685 				entry->qbss_chan_load, congestion_pct,
2686 				entry->nss, ap_tx_pwr_dbm,
2687 				oce_subnet_id_present, sae_pk_cap_present,
2688 				prorated_pcnt, entry->neg_sec_info.key_mgmt,
2689 				bss_mlo_type);
2690 
2691 	mlme_nofl_debug("%s score("QDF_MAC_ADDR_FMT" freq %d): rssi %d pcl %d ht %d vht %d he %d bfee %d bw %d band %d cong %d nss %d oce_wan %d oce_ap_pwr %d oce_subnet %d sae_pk %d eht %d security %d ml %d TOTAL %d",
2692 			IS_LINK_SCORE(ml_flag) ? "Link" : "Candidate",
2693 			QDF_MAC_ADDR_REF(entry->bssid.bytes),
2694 			entry->channel.chan_freq,
2695 			rssi_score, pcl_score, ht_score,
2696 			vht_score, he_score, beamformee_score, bandwidth_score,
2697 			band_score, congestion_score, nss_score, oce_wan_score,
2698 			oce_ap_tx_pwr_score, oce_subnet_id_score,
2699 			sae_pk_score, eht_score, security_score, ml_score,
2700 			score);
2701 
2702 	return score;
2703 }
2704 
cm_list_insert_sorted(qdf_list_t * scan_list,struct scan_cache_node * scan_entry)2705 static void cm_list_insert_sorted(qdf_list_t *scan_list,
2706 				  struct scan_cache_node *scan_entry)
2707 {
2708 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
2709 	struct scan_cache_node *curr_entry;
2710 
2711 	qdf_list_peek_front(scan_list, &cur_node);
2712 	while (cur_node) {
2713 		curr_entry = qdf_container_of(cur_node, struct scan_cache_node,
2714 					      node);
2715 		if (cm_is_better_bss(scan_entry->entry, curr_entry->entry)) {
2716 			qdf_list_insert_before(scan_list, &scan_entry->node,
2717 					       &curr_entry->node);
2718 			break;
2719 		}
2720 		qdf_list_peek_next(scan_list, cur_node, &next_node);
2721 		cur_node = next_node;
2722 		next_node = NULL;
2723 	}
2724 
2725 	if (!cur_node)
2726 		qdf_list_insert_back(scan_list, &scan_entry->node);
2727 }
2728 
2729 #ifdef CONN_MGR_ADV_FEATURE
2730 /**
2731  * cm_is_bad_rssi_entry() - check the entry have rssi value, if rssi is lower
2732  * than threshold limit, then it is considered ad bad rssi value.
2733  * @scan_entry: pointer to scan cache entry
2734  * @score_config: pointer to score config structure
2735  * @bssid_hint: bssid hint
2736  *
2737  * Return: true if rssi is lower than threshold
2738  */
2739 static
cm_is_bad_rssi_entry(struct scan_cache_entry * scan_entry,struct scoring_cfg * score_config,struct qdf_mac_addr * bssid_hint)2740 bool cm_is_bad_rssi_entry(struct scan_cache_entry *scan_entry,
2741 			  struct scoring_cfg *score_config,
2742 			  struct qdf_mac_addr *bssid_hint)
2743 {
2744 	int8_t rssi_threshold =
2745 		score_config->rssi_score.con_non_hint_target_rssi_threshold;
2746 
2747 	 /* do not need to consider BSSID hint if it is invalid entry(zero) */
2748 	if (qdf_is_macaddr_zero(bssid_hint))
2749 		return false;
2750 
2751 	if (score_config->is_bssid_hint_priority &&
2752 	    !qdf_is_macaddr_equal(bssid_hint, &scan_entry->bssid) &&
2753 	    scan_entry->rssi_raw < rssi_threshold) {
2754 		mlme_nofl_debug("Candidate(" QDF_MAC_ADDR_FMT "  freq %d): remove entry, rssi %d lower than rssi_threshold %d",
2755 				QDF_MAC_ADDR_REF(scan_entry->bssid.bytes),
2756 				scan_entry->channel.chan_freq,
2757 				scan_entry->rssi_raw, rssi_threshold);
2758 		return true;
2759 	}
2760 
2761 	return false;
2762 }
2763 
2764 /**
2765  * cm_update_bss_score_for_mac_addr_matching() - boost score based on mac
2766  * address matching
2767  * @scan_entry: pointer to scan cache entry
2768  * @self_mac: pointer to bssid to be matched
2769  *
2770  * Some IOT APs only allow to connect if last 3 bytes of BSSID
2771  * and self MAC is same. They create a new bssid on receiving
2772  * unicast probe/auth req from STA and allow STA to connect to
2773  * this matching BSSID only. So boost the matching BSSID to try
2774  * to connect to this BSSID.
2775  *
2776  * Return: void
2777  */
2778 static void
cm_update_bss_score_for_mac_addr_matching(struct scan_cache_node * scan_entry,struct qdf_mac_addr * self_mac)2779 cm_update_bss_score_for_mac_addr_matching(struct scan_cache_node *scan_entry,
2780 					  struct qdf_mac_addr *self_mac)
2781 {
2782 	struct qdf_mac_addr *scan_entry_bssid;
2783 
2784 	if (!self_mac)
2785 		return;
2786 	scan_entry_bssid = &scan_entry->entry->bssid;
2787 	if (QDF_IS_LAST_3_BYTES_OF_MAC_SAME(
2788 		self_mac, scan_entry_bssid)) {
2789 		mlme_nofl_debug("Candidate("QDF_MAC_ADDR_FMT" freq %d): boost bss score due to same last 3 byte match",
2790 				QDF_MAC_ADDR_REF(
2791 				scan_entry_bssid->bytes),
2792 				scan_entry->entry->channel.chan_freq);
2793 		scan_entry->entry->bss_score =
2794 			CM_BEST_CANDIDATE_MAX_BSS_SCORE;
2795 	}
2796 }
2797 #else
2798 static inline
cm_is_bad_rssi_entry(struct scan_cache_entry * scan_entry,struct scoring_cfg * score_config,struct qdf_mac_addr * bssid_hint)2799 bool cm_is_bad_rssi_entry(struct scan_cache_entry *scan_entry,
2800 			  struct scoring_cfg *score_config,
2801 			  struct qdf_mac_addr *bssid_hint)
2802 
2803 {
2804 	return false;
2805 }
2806 
2807 static void
cm_update_bss_score_for_mac_addr_matching(struct scan_cache_node * scan_entry,struct qdf_mac_addr * self_mac)2808 cm_update_bss_score_for_mac_addr_matching(struct scan_cache_node *scan_entry,
2809 					  struct qdf_mac_addr *self_mac)
2810 {
2811 }
2812 #endif
2813 
2814 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
cm_print_candidate_list(qdf_list_t * candidate_list)2815 void cm_print_candidate_list(qdf_list_t *candidate_list)
2816 {
2817 	struct scan_cache_node *scan_entry = NULL;
2818 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
2819 	uint32_t freq_entry = 0;
2820 	struct partner_link_info *link = NULL;
2821 	uint8_t i = 0;
2822 	uint32_t len = 0;
2823 	char log_str[CANDIDATE_DUMP_MAX_LEN] = {0};
2824 	uint32_t str_len = CANDIDATE_DUMP_MAX_LEN;
2825 
2826 	if (qdf_list_peek_front(candidate_list, &cur_node) !=
2827 	    QDF_STATUS_SUCCESS) {
2828 		mlme_err("failed to get front of candidate_list");
2829 		return;
2830 	}
2831 
2832 	while (cur_node) {
2833 		qdf_list_peek_next(candidate_list, cur_node, &next_node);
2834 
2835 		scan_entry = qdf_container_of(cur_node, struct scan_cache_node,
2836 					      node);
2837 		link = scan_entry->entry->ml_info.link_info;
2838 		freq_entry = scan_entry->entry->channel.chan_freq;
2839 
2840 		if (scan_entry->entry->ml_info.num_links)
2841 			len += qdf_scnprintf(log_str + len, str_len - len, "num_link %d partners ",
2842 					     scan_entry->entry->ml_info.num_links);
2843 		for (i = 0; i < scan_entry->entry->ml_info.num_links; i++)
2844 			len += qdf_scnprintf(log_str + len, str_len - len, QDF_MAC_ADDR_FMT " freq (%d) link_id %d is_valid_link %d ",
2845 					     QDF_MAC_ADDR_REF(link[i].link_addr.bytes),
2846 					     link[i].freq, link[i].link_id,
2847 					     link[i].is_valid_link);
2848 		mlme_debug("Candidate(" QDF_MAC_ADDR_FMT " freq %d self_link_id %d): %s bss_score %d ",
2849 			   QDF_MAC_ADDR_REF(scan_entry->entry->bssid.bytes),
2850 			   scan_entry->entry->channel.chan_freq,
2851 			   scan_entry->entry->ml_info.self_link_id,
2852 			   log_str,
2853 			   scan_entry->entry->bss_score);
2854 		cur_node = next_node;
2855 		next_node = NULL;
2856 		memset(log_str, 0, sizeof(*log_str));
2857 		len = 0;
2858 	}
2859 }
2860 
2861 /**
2862  * cm_find_and_remove_dup_candidate() - remove duplicate candidate
2863  * @bss_entry: bss scan entry
2864  * @next_can: next candidate
2865  * @candidate_list: candidate list
2866  *
2867  * Ex1:
2868  * Single AP1 3 link  6 GHz 2 GHz 5 GHz
2869  *
2870  * All possible combination of candidate[INPUT]
2871  * AP1 6 GHz + 2 GHz + 5 GHz
2872  * AP1 6 GHz + 2 GHz
2873  * AP1 6 GHz + 5 GHz
2874  * AP1 6 GHz
2875  * AP1 2 GHz + 5 GHz + 6 GHz
2876  * AP1 2 GHz + 5 GHz
2877  * AP1 2 GHz + 6 GHz
2878  * AP1 2 GHz
2879  * AP1 5 GHz + 6 GHz + 2 GHz
2880  * AP1 5 GHz + 6 GHz
2881  * AP1 5 GHz + 2 GHz
2882  * AP1 5 GHz
2883  *
2884  * All possible valid unique combination of candidate after applying [OUTPUT]
2885  * filter.
2886  * AP1 6 GHz + 2 GHz + 5 GHz
2887  * AP1 6 GHz + 2 GHz
2888  * AP1 6 GHz + 5 GHz
2889  * AP1 6 GHz
2890  * AP1 5 GHz + 2 GHz
2891  * AP1 5 GHz
2892  * AP1 2 GHz
2893  *
2894  * Return: none
2895  */
cm_find_and_remove_dup_candidate(struct scan_cache_node * bss_entry,qdf_list_node_t * next_can,qdf_list_t * candidate_list)2896 static void cm_find_and_remove_dup_candidate(struct scan_cache_node *bss_entry,
2897 					     qdf_list_node_t  *next_can,
2898 					     qdf_list_t *candidate_list)
2899 {
2900 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
2901 	struct scan_cache_node *scan_node;
2902 	uint8_t i = 0, j = 0;
2903 	int match = 0;
2904 	uint8_t bss_num_link = 0, curr_num_link = 0;
2905 	struct partner_link_info *cur_can = NULL, *bss_can = NULL;
2906 	uint32_t size = 0;
2907 
2908 	bss_num_link = bss_entry->entry->ml_info.num_links;
2909 
2910 	cur_node = next_can;
2911 	size = qdf_list_size(candidate_list);
2912 
2913 	while (cur_node && size > 0) {
2914 		qdf_list_peek_next(candidate_list, cur_node, &next_node);
2915 
2916 		scan_node  = qdf_container_of(cur_node, struct scan_cache_node,
2917 					      node);
2918 		curr_num_link = scan_node->entry->ml_info.num_links;
2919 		cur_can = scan_node->entry->ml_info.link_info;
2920 		bss_can = bss_entry->entry->ml_info.link_info;
2921 
2922 		if (scan_node->entry->ml_info.num_links !=
2923 		    bss_entry->entry->ml_info.num_links)
2924 			goto next;
2925 
2926 		match = 0;
2927 		for (i = 0; i < bss_num_link; i++)
2928 			if (qdf_is_macaddr_equal(&bss_entry->entry->bssid,
2929 						 &scan_node->entry->bssid) ||
2930 			    qdf_is_macaddr_equal(&bss_entry->entry->bssid,
2931 						 &cur_can[i].link_addr))
2932 				match++;
2933 		for (i = 0; i < bss_num_link; i++) {
2934 			for (j = 0; j < curr_num_link; j++) {
2935 				if (cur_can[j].is_valid_link &&
2936 				    (qdf_is_macaddr_equal(
2937 						&cur_can[j].link_addr,
2938 						&bss_can[i].link_addr) ||
2939 				    qdf_is_macaddr_equal(
2940 						&cur_can[j].link_addr,
2941 						&bss_can[i].link_addr) ||
2942 				    qdf_is_macaddr_equal(
2943 						&scan_node->entry->bssid,
2944 						&bss_can[i].link_addr))) {
2945 					match++;
2946 					if (match == bss_num_link + 1) {
2947 						qdf_list_remove_node(
2948 							candidate_list,
2949 							cur_node);
2950 						util_scan_free_cache_entry(
2951 							scan_node->entry);
2952 						qdf_mem_free(cur_node);
2953 						goto next;
2954 					}
2955 				}
2956 			}
2957 		}
2958 next:
2959 	cur_node = next_node;
2960 	next_node = NULL;
2961 	size--;
2962 	}
2963 }
2964 
2965 /**
2966  * cm_mlo_generate_candidate_list() - generate candidate list
2967  * @candidate_list: candidate list
2968  *
2969  * For any candidate list this api generates all possible unique
2970  * candidates from mlo candidates
2971  * Input candidate list
2972  * c1 6 GHz + 2 GHz + 5 GHz
2973  * c2 2 GHz + 5 GHz + 6 GHz
2974  * c3 5 GHz + 6 GHz + 2 GHz
2975  *
2976  * Output candidate list
2977  * AP1 6 GHz + 2 GHz + 5 GHz
2978  * AP1 6 GHz + 2 GHz
2979  * AP1 6 GHz + 5 GHz
2980  * AP1 6 GHz
2981  * AP1 2 GHz + 5 GHz + 6 GHz
2982  * AP1 2 GHz + 5 GHz
2983  * AP1 2 GHz + 6 GHz
2984  * AP1 2 GHz
2985  * AP1 5 GHz + 6 GHz + 2 GHz
2986  * AP1 5 GHz + 6 GHz
2987  * AP1 5 GHz + 2 GHz
2988  * AP1 5 GHz
2989  *
2990  * Return none
2991  */
cm_mlo_generate_candidate_list(qdf_list_t * candidate_list)2992 static void cm_mlo_generate_candidate_list(qdf_list_t *candidate_list)
2993 {
2994 	struct scan_cache_entry *tmp_scan_entry = NULL;
2995 	struct scan_cache_node *scan_entry = NULL, *scan_node = NULL;
2996 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
2997 	struct partner_link_info *link = NULL;
2998 	struct partner_link_info tmp = {0};
2999 	uint32_t num_link = 0;
3000 	uint32_t i = 0;
3001 	uint32_t j = 0;
3002 
3003 	if (qdf_list_peek_front(candidate_list, &cur_node) !=
3004 	    QDF_STATUS_SUCCESS) {
3005 		mlme_err("failed to get front of candidate_list");
3006 		return;
3007 	}
3008 	while (cur_node) {
3009 		qdf_list_peek_next(candidate_list, cur_node, &next_node);
3010 
3011 		scan_entry = qdf_container_of(cur_node, struct scan_cache_node,
3012 					      node);
3013 		num_link = scan_entry->entry->ml_info.num_links;
3014 
3015 		for (i = 0; i < num_link; i++) {
3016 			tmp_scan_entry = util_scan_copy_cache_entry(
3017 						scan_entry->entry);
3018 			scan_node = qdf_mem_malloc_atomic(sizeof(*scan_node));
3019 			if (!scan_node) {
3020 				util_scan_free_cache_entry(tmp_scan_entry);
3021 				goto next;
3022 			}
3023 
3024 			scan_node->entry = tmp_scan_entry;
3025 			scan_node->entry->ml_info.num_links = i;
3026 			link = scan_node->entry->ml_info.link_info;
3027 			for (j = i; j < num_link; j++)
3028 				link[j].is_valid_link = false;
3029 			qdf_list_insert_after(candidate_list,
3030 					      &scan_node->node,
3031 					      &scan_entry->node);
3032 
3033 			if (i == 1) {
3034 				tmp_scan_entry = util_scan_copy_cache_entry(
3035 							scan_entry->entry);
3036 				scan_node = qdf_mem_malloc_atomic(
3037 						sizeof(*scan_node));
3038 				if (!scan_node) {
3039 					util_scan_free_cache_entry(
3040 							tmp_scan_entry);
3041 					goto next;
3042 				}
3043 
3044 				scan_node->entry = tmp_scan_entry;
3045 				scan_node->entry->ml_info.num_links = i;
3046 				link = scan_node->entry->ml_info.link_info;
3047 				tmp  = link[1];
3048 				link[1] = link[0];
3049 				link[0] = tmp;
3050 				for (j = i; j < num_link; j++)
3051 					link[j].is_valid_link = false;
3052 				qdf_list_insert_after(candidate_list,
3053 						      &scan_node->node,
3054 						      &scan_entry->node);
3055 			}
3056 		}
3057 next:
3058 		cur_node = next_node;
3059 		next_node = NULL;
3060 	}
3061 }
3062 
cm_eliminate_common_candidate(qdf_list_t * candidate_list)3063 static void cm_eliminate_common_candidate(qdf_list_t *candidate_list)
3064 {
3065 	struct scan_cache_node *scan_entry = NULL;
3066 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
3067 	uint32_t size = 0;
3068 	QDF_STATUS status;
3069 
3070 	size = qdf_list_size(candidate_list);
3071 
3072 	if (qdf_list_peek_front(candidate_list, &cur_node) !=
3073 		QDF_STATUS_SUCCESS) {
3074 		mlme_err("failed to get front of candidate_list");
3075 		return;
3076 	}
3077 
3078 	while (cur_node && size > 0) {
3079 		qdf_list_peek_next(candidate_list, cur_node, &next_node);
3080 
3081 		scan_entry = qdf_container_of(cur_node,
3082 					      struct scan_cache_node, node);
3083 
3084 		cm_find_and_remove_dup_candidate(scan_entry,
3085 						 next_node, candidate_list);
3086 
3087 		/*
3088 		 * Find next again as next entry might have deleted.
3089 		 * If reach end of list, next_node won't be updated, may still
3090 		 * be freed node, but it's next is itself, qdf_list_peek_next
3091 		 * will return QDF_STATUS_E_EMPTY, need break loop, or double
3092 		 * free will happen.
3093 		 */
3094 		status = qdf_list_peek_next(candidate_list, cur_node,
3095 					    &next_node);
3096 		if (QDF_IS_STATUS_ERROR(status))
3097 			break;
3098 
3099 		cur_node = next_node;
3100 		next_node = NULL;
3101 		size--;
3102 	}
3103 }
3104 
cm_validate_partner_links(struct wlan_objmgr_psoc * psoc,struct scan_cache_entry * entry,qdf_list_t * scan_list)3105 static void cm_validate_partner_links(struct wlan_objmgr_psoc *psoc,
3106 				      struct scan_cache_entry *entry,
3107 				      qdf_list_t *scan_list)
3108 {
3109 	uint8_t idx;
3110 	struct scan_cache_entry *partner_entry;
3111 	struct partner_link_info *partner_info;
3112 	struct wlan_objmgr_peer *peer;
3113 
3114 	if (!entry->ie_list.multi_link_bv || !entry->ml_info.num_links)
3115 		return;
3116 
3117 	for (idx = 0; idx < entry->ml_info.num_links; idx++) {
3118 		partner_info = &entry->ml_info.link_info[idx];
3119 		if (!partner_info->is_valid_link)
3120 			continue;
3121 
3122 		peer = wlan_objmgr_get_peer_by_mac(psoc,
3123 						   partner_info->link_addr.bytes,
3124 						   WLAN_MLME_CM_ID);
3125 		if (peer) {
3126 			mlme_debug(QDF_MAC_ADDR_FMT "link (%d) dup peer existed",
3127 				   QDF_MAC_ADDR_REF(partner_info->link_addr.bytes),
3128 				   partner_info->freq);
3129 			partner_info->is_valid_link = false;
3130 			wlan_objmgr_peer_release_ref(peer, WLAN_MLME_CM_ID);
3131 			continue;
3132 		}
3133 
3134 		if (partner_info->link_id == entry->ml_info.self_link_id) {
3135 			mlme_err(QDF_MAC_ADDR_FMT " dup link id %d",
3136 				 QDF_MAC_ADDR_REF(partner_info->link_addr.bytes),
3137 				 partner_info->link_id);
3138 			partner_info->is_valid_link = false;
3139 		}
3140 
3141 		if (qdf_is_macaddr_equal(&partner_info->link_addr,
3142 					 &entry->bssid)) {
3143 			mlme_err(QDF_MAC_ADDR_FMT " link id %d dup mac",
3144 				 QDF_MAC_ADDR_REF(partner_info->link_addr.bytes),
3145 				 partner_info->link_id);
3146 			partner_info->is_valid_link = false;
3147 		}
3148 
3149 		/*
3150 		 * If partner link is not found in the current candidate list
3151 		 * don't treat it as failure, it can be removed post ML
3152 		 * probe resp generation time.
3153 		 */
3154 		partner_entry = cm_get_entry(scan_list,
3155 					     &partner_info->link_addr);
3156 		if (!partner_entry)
3157 			continue;
3158 
3159 		if (wlan_scan_entries_contain_cmn_akm(entry, partner_entry) &&
3160 		    wlan_cm_is_eht_allowed_for_current_security(psoc,
3161 								partner_entry,
3162 								true)) {
3163 			continue;
3164 		}
3165 
3166 		partner_info->is_valid_link = false;
3167 		mlme_debug(QDF_MAC_ADDR_FMT "link (%d) akm not matching",
3168 			   QDF_MAC_ADDR_REF(partner_entry->bssid.bytes),
3169 			   partner_info->freq);
3170 	}
3171 }
3172 #else
3173 
cm_mlo_generate_candidate_list(qdf_list_t * candidate_list)3174 static void cm_mlo_generate_candidate_list(qdf_list_t *candidate_list)
3175 {
3176 }
3177 
cm_eliminate_common_candidate(qdf_list_t * candidate_list)3178 static void cm_eliminate_common_candidate(qdf_list_t *candidate_list)
3179 {
3180 }
3181 
3182 static inline void
cm_validate_partner_links(struct wlan_objmgr_psoc * psoc,struct scan_cache_entry * entry,qdf_list_t * scan_list)3183 cm_validate_partner_links(struct wlan_objmgr_psoc *psoc,
3184 			  struct scan_cache_entry *entry,
3185 			  qdf_list_t *scan_list)
3186 {
3187 }
3188 #endif
wlan_cm_calculate_bss_score(struct wlan_objmgr_pdev * pdev,struct pcl_freq_weight_list * pcl_lst,qdf_list_t * scan_list,struct qdf_mac_addr * bssid_hint,struct qdf_mac_addr * self_mac)3189 void wlan_cm_calculate_bss_score(struct wlan_objmgr_pdev *pdev,
3190 				 struct pcl_freq_weight_list *pcl_lst,
3191 				 qdf_list_t *scan_list,
3192 				 struct qdf_mac_addr *bssid_hint,
3193 				 struct qdf_mac_addr *self_mac)
3194 {
3195 	struct scan_cache_node *scan_entry;
3196 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
3197 	struct psoc_mlme_obj *mlme_psoc_obj;
3198 	struct scoring_cfg *score_config;
3199 	int pcl_chan_weight;
3200 	QDF_STATUS status;
3201 	struct psoc_phy_config *config;
3202 	enum cm_denylist_action denylist_action;
3203 	struct wlan_objmgr_psoc *psoc;
3204 	bool assoc_allowed;
3205 	struct scan_cache_node *force_connect_candidate = NULL;
3206 	bool are_all_candidate_denylisted = true;
3207 	bool is_rssi_bad = false;
3208 
3209 	psoc = wlan_pdev_get_psoc(pdev);
3210 
3211 	if (!psoc) {
3212 		mlme_err("psoc NULL");
3213 		return;
3214 	}
3215 	if (!scan_list) {
3216 		mlme_err("Scan list NULL");
3217 		return;
3218 	}
3219 
3220 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
3221 	if (!mlme_psoc_obj)
3222 		return;
3223 
3224 	score_config = &mlme_psoc_obj->psoc_cfg.score_config;
3225 	config = &mlme_psoc_obj->psoc_cfg.phy_config;
3226 
3227 	mlme_nofl_debug("Self caps: HT %d VHT %d HE %d EHT %d VHT_24Ghz %d BF cap %d bw_above_20_24ghz %d bw_above_20_5ghz %d 2.4G NSS %d 5G NSS %d",
3228 			config->ht_cap, config->vht_cap,
3229 			config->he_cap, config->eht_cap, config->vht_24G_cap,
3230 			config->beamformee_cap, config->bw_above_20_24ghz,
3231 			config->bw_above_20_5ghz, config->vdev_nss_24g,
3232 			config->vdev_nss_5g);
3233 
3234 	cm_mlo_generate_candidate_list(scan_list);
3235 
3236 	/* calculate score for each AP */
3237 	if (qdf_list_peek_front(scan_list, &cur_node) != QDF_STATUS_SUCCESS) {
3238 		mlme_err("failed to peer front of scan list");
3239 		return;
3240 	}
3241 
3242 	while (cur_node) {
3243 		qdf_list_peek_next(scan_list, cur_node, &next_node);
3244 		pcl_chan_weight = 0;
3245 		scan_entry = qdf_container_of(cur_node, struct scan_cache_node,
3246 					      node);
3247 
3248 		is_rssi_bad = cm_is_bad_rssi_entry(scan_entry->entry,
3249 						   score_config, bssid_hint);
3250 
3251 		assoc_allowed = cm_is_assoc_allowed(mlme_psoc_obj,
3252 						    scan_entry->entry);
3253 
3254 		if (assoc_allowed && !is_rssi_bad)
3255 			denylist_action = wlan_denylist_action_on_bssid(pdev,
3256 							scan_entry->entry);
3257 		else
3258 			denylist_action = CM_DLM_FORCE_REMOVE;
3259 
3260 		if (denylist_action == CM_DLM_NO_ACTION ||
3261 		    denylist_action == CM_DLM_AVOID)
3262 			are_all_candidate_denylisted = false;
3263 
3264 		if (denylist_action == CM_DLM_NO_ACTION &&
3265 		    pcl_lst && pcl_lst->num_of_pcl_channels &&
3266 		    scan_entry->entry->rssi_raw > CM_PCL_RSSI_THRESHOLD &&
3267 		    score_config->weight_config.pcl_weightage) {
3268 			if (cm_get_pcl_weight_of_channel(
3269 					scan_entry->entry->channel.chan_freq,
3270 					pcl_lst, &pcl_chan_weight)) {
3271 				mlme_debug("pcl freq %d pcl_chan_weight %d",
3272 					   scan_entry->entry->channel.chan_freq,
3273 					   pcl_chan_weight);
3274 			}
3275 		}
3276 
3277 		/* Check if the partner links RSN caps are matching. */
3278 		cm_validate_partner_links(psoc, scan_entry->entry, scan_list);
3279 		if (denylist_action == CM_DLM_NO_ACTION ||
3280 		    (are_all_candidate_denylisted && denylist_action ==
3281 		     CM_DLM_REMOVE)) {
3282 			cm_calculate_bss_score(psoc, scan_entry->entry,
3283 					       pcl_chan_weight, bssid_hint,
3284 					       scan_list, ASSOC_LINK);
3285 		} else if (denylist_action == CM_DLM_AVOID) {
3286 			/* add min score so that it is added back in the end */
3287 			scan_entry->entry->bss_score =
3288 					CM_AVOID_CANDIDATE_MIN_SCORE;
3289 			mlme_nofl_debug("Candidate("QDF_MAC_ADDR_FMT" freq %d): rssi %d, is in Avoidlist, give min score %d",
3290 					QDF_MAC_ADDR_REF(scan_entry->entry->bssid.bytes),
3291 					scan_entry->entry->channel.chan_freq,
3292 					scan_entry->entry->rssi_raw,
3293 					scan_entry->entry->bss_score);
3294 		} else {
3295 			mlme_nofl_debug("Candidate("QDF_MAC_ADDR_FMT" freq %d): denylist_action %d",
3296 					QDF_MAC_ADDR_REF(scan_entry->entry->bssid.bytes),
3297 					scan_entry->entry->channel.chan_freq,
3298 					denylist_action);
3299 		}
3300 
3301 		cm_update_bss_score_for_mac_addr_matching(scan_entry, self_mac);
3302 		/*
3303 		 * The below logic is added to select the best candidate
3304 		 * amongst the denylisted candidates. This is done to
3305 		 * handle a case where all the BSSIDs become denylisted
3306 		 * and hence there are continuous connection failures.
3307 		 * With the below logic if the action on BSSID is to remove
3308 		 * then we keep a backup node and restore the candidate
3309 		 * list.
3310 		 */
3311 		if (denylist_action == CM_DLM_REMOVE &&
3312 		    are_all_candidate_denylisted) {
3313 			if (!force_connect_candidate) {
3314 				force_connect_candidate =
3315 					qdf_mem_malloc(
3316 					   sizeof(*force_connect_candidate));
3317 				if (!force_connect_candidate)
3318 					return;
3319 				force_connect_candidate->entry =
3320 					util_scan_copy_cache_entry(scan_entry->entry);
3321 				if (!force_connect_candidate->entry)
3322 					return;
3323 			} else if (cm_is_better_bss(
3324 				   scan_entry->entry,
3325 				   force_connect_candidate->entry)) {
3326 				util_scan_free_cache_entry(
3327 					force_connect_candidate->entry);
3328 				force_connect_candidate->entry =
3329 				  util_scan_copy_cache_entry(scan_entry->entry);
3330 				if (!force_connect_candidate->entry)
3331 					return;
3332 			}
3333 		}
3334 
3335 		/* Remove node from current location to add node back sorted */
3336 		status = qdf_list_remove_node(scan_list, cur_node);
3337 		if (QDF_IS_STATUS_ERROR(status)) {
3338 			mlme_err("failed to remove node for BSS "QDF_MAC_ADDR_FMT" from scan list",
3339 				 QDF_MAC_ADDR_REF(scan_entry->entry->bssid.bytes));
3340 			return;
3341 		}
3342 
3343 		/*
3344 		 * If CM_DLM_REMOVE ie denylisted or assoc not allowed then
3345 		 * free the entry else add back to the list sorted
3346 		 */
3347 		if (denylist_action == CM_DLM_REMOVE ||
3348 		    denylist_action == CM_DLM_FORCE_REMOVE) {
3349 			if (assoc_allowed && !is_rssi_bad)
3350 				mlme_nofl_debug("Candidate( " QDF_MAC_ADDR_FMT " freq %d): rssi %d, dlm action %d is in Denylist, remove entry",
3351 					QDF_MAC_ADDR_REF(scan_entry->entry->bssid.bytes),
3352 					scan_entry->entry->channel.chan_freq,
3353 					scan_entry->entry->rssi_raw,
3354 					denylist_action);
3355 			util_scan_free_cache_entry(scan_entry->entry);
3356 			qdf_mem_free(scan_entry);
3357 		} else {
3358 			cm_list_insert_sorted(scan_list, scan_entry);
3359 		}
3360 
3361 		cur_node = next_node;
3362 		next_node = NULL;
3363 	}
3364 
3365 	if (are_all_candidate_denylisted && force_connect_candidate) {
3366 		mlme_nofl_debug("All candidates in denylist, Candidate( " QDF_MAC_ADDR_FMT " freq %d): rssi %d, selected for connection",
3367 			QDF_MAC_ADDR_REF(force_connect_candidate->entry->bssid.bytes),
3368 			force_connect_candidate->entry->channel.chan_freq,
3369 			force_connect_candidate->entry->rssi_raw);
3370 		cm_list_insert_sorted(scan_list, force_connect_candidate);
3371 	} else if (force_connect_candidate) {
3372 		util_scan_free_cache_entry(force_connect_candidate->entry);
3373 		qdf_mem_free(force_connect_candidate);
3374 	}
3375 
3376 	cm_eliminate_common_candidate(scan_list);
3377 	/* print all vendor candidates*/
3378 	cm_print_candidate_list(scan_list);
3379 }
3380 
3381 #ifdef CONFIG_BAND_6GHZ
3382 #ifdef CONN_MGR_ADV_FEATURE
wlan_cm_wfa_get_test_feature_flags(struct wlan_objmgr_psoc * psoc)3383 static bool wlan_cm_wfa_get_test_feature_flags(struct wlan_objmgr_psoc *psoc)
3384 {
3385 	return wlan_wfa_get_test_feature_flags(psoc, WFA_TEST_IGNORE_RSNXE);
3386 }
3387 #else
wlan_cm_wfa_get_test_feature_flags(struct wlan_objmgr_psoc * psoc)3388 static bool wlan_cm_wfa_get_test_feature_flags(struct wlan_objmgr_psoc *psoc)
3389 {
3390 	return false;
3391 }
3392 #endif
3393 
wlan_cm_6ghz_allowed_for_akm(struct wlan_objmgr_psoc * psoc,uint32_t key_mgmt,uint16_t rsn_caps,const uint8_t * rsnxe,uint8_t sae_pwe,bool is_wps)3394 bool wlan_cm_6ghz_allowed_for_akm(struct wlan_objmgr_psoc *psoc,
3395 				  uint32_t key_mgmt, uint16_t rsn_caps,
3396 				  const uint8_t *rsnxe, uint8_t sae_pwe,
3397 				  bool is_wps)
3398 {
3399 	struct psoc_mlme_obj *mlme_psoc_obj;
3400 	struct scoring_cfg *config;
3401 
3402 	/* Allow connection for WPS security */
3403 	if (is_wps)
3404 		return true;
3405 
3406 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
3407 	if (!mlme_psoc_obj)
3408 		return false;
3409 
3410 	config = &mlme_psoc_obj->psoc_cfg.score_config;
3411 	/*
3412 	 * if check_6ghz_security is not set check if key_mgmt_mask_6ghz is set
3413 	 * if key_mgmt_mask_6ghz is set check if AKM matches the user configured
3414 	 * 6Ghz security
3415 	 */
3416 	if (!config->check_6ghz_security) {
3417 		if (!config->key_mgmt_mask_6ghz)
3418 			return true;
3419 		/*
3420 		 * Check if any AKM is allowed as per user 6Ghz allowed AKM mask
3421 		 */
3422 		if (!(config->key_mgmt_mask_6ghz & key_mgmt)) {
3423 			mlme_debug("user configured mask %x didn't match AKM %x",
3424 				   config->key_mgmt_mask_6ghz , key_mgmt);
3425 			return false;
3426 		}
3427 
3428 		return true;
3429 	}
3430 
3431 	/* Check if any AKM is allowed as per the 6Ghz allowed AKM mask */
3432 	if (!(key_mgmt & ALLOWED_KEYMGMT_6G_MASK)) {
3433 		mlme_debug("AKM 0x%x didn't match with allowed 6ghz AKM 0x%x",
3434 			   key_mgmt, ALLOWED_KEYMGMT_6G_MASK);
3435 		return false;
3436 	}
3437 
3438 	/* if check_6ghz_security is set validate all checks for 6Ghz */
3439 	if (!(rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED)) {
3440 		mlme_debug("PMF not enabled for 6GHz AP");
3441 		return false;
3442 	}
3443 
3444 	/* for SAE we need to check H2E support */
3445 	if (!(QDF_HAS_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_SAE) ||
3446 	    QDF_HAS_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_SAE) ||
3447 	    QDF_HAS_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_SAE_EXT_KEY) ||
3448 	    QDF_HAS_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_SAE_EXT_KEY)))
3449 		return true;
3450 
3451 	return (util_is_rsnxe_h2e_capable(rsnxe) ||
3452 		wlan_cm_wfa_get_test_feature_flags(psoc));
3453 }
3454 
wlan_cm_set_check_6ghz_security(struct wlan_objmgr_psoc * psoc,bool value)3455 void wlan_cm_set_check_6ghz_security(struct wlan_objmgr_psoc *psoc,
3456 				     bool value)
3457 {
3458 	struct psoc_mlme_obj *mlme_psoc_obj;
3459 
3460 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
3461 	if (!mlme_psoc_obj)
3462 		return;
3463 
3464 	mlme_debug("6ghz security check val %x", value);
3465 	mlme_psoc_obj->psoc_cfg.score_config.check_6ghz_security = value;
3466 }
3467 
wlan_cm_reset_check_6ghz_security(struct wlan_objmgr_psoc * psoc)3468 void wlan_cm_reset_check_6ghz_security(struct wlan_objmgr_psoc *psoc)
3469 {
3470 	struct psoc_mlme_obj *mlme_psoc_obj;
3471 
3472 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
3473 	if (!mlme_psoc_obj)
3474 		return;
3475 
3476 	mlme_psoc_obj->psoc_cfg.score_config.check_6ghz_security =
3477 					cfg_get(psoc, CFG_CHECK_6GHZ_SECURITY);
3478 }
3479 #if defined (SAP_MULTI_LINK_EMULATION)
3480 	/*Disable security check for 2link SAP emulation */
wlan_cm_get_check_6ghz_security(struct wlan_objmgr_psoc * psoc)3481 bool wlan_cm_get_check_6ghz_security(struct wlan_objmgr_psoc *psoc)
3482 {
3483 	return true;
3484 }
3485 #else
wlan_cm_get_check_6ghz_security(struct wlan_objmgr_psoc * psoc)3486 bool wlan_cm_get_check_6ghz_security(struct wlan_objmgr_psoc *psoc)
3487 {
3488 	struct psoc_mlme_obj *mlme_psoc_obj;
3489 
3490 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
3491 	if (!mlme_psoc_obj)
3492 		return false;
3493 
3494 	return mlme_psoc_obj->psoc_cfg.score_config.check_6ghz_security;
3495 }
3496 #endif
wlan_cm_set_standard_6ghz_conn_policy(struct wlan_objmgr_psoc * psoc,bool value)3497 void wlan_cm_set_standard_6ghz_conn_policy(struct wlan_objmgr_psoc *psoc,
3498 					   bool value)
3499 {
3500 	struct psoc_mlme_obj *mlme_psoc_obj;
3501 
3502 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
3503 	if (!mlme_psoc_obj)
3504 		return;
3505 
3506 	mlme_debug("6ghz standard connection policy val %x", value);
3507 	mlme_psoc_obj->psoc_cfg.score_config.standard_6ghz_conn_policy = value;
3508 }
3509 
wlan_cm_get_standard_6ghz_conn_policy(struct wlan_objmgr_psoc * psoc)3510 bool wlan_cm_get_standard_6ghz_conn_policy(struct wlan_objmgr_psoc *psoc)
3511 {
3512 	struct psoc_mlme_obj *mlme_psoc_obj;
3513 
3514 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
3515 	if (!mlme_psoc_obj)
3516 		return false;
3517 
3518 	return mlme_psoc_obj->psoc_cfg.score_config.standard_6ghz_conn_policy;
3519 }
3520 
wlan_cm_set_disable_vlp_sta_conn_to_sp_ap(struct wlan_objmgr_psoc * psoc,bool value)3521 void wlan_cm_set_disable_vlp_sta_conn_to_sp_ap(struct wlan_objmgr_psoc *psoc,
3522 					       bool value)
3523 {
3524 	struct psoc_mlme_obj *mlme_psoc_obj;
3525 
3526 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
3527 	if (!mlme_psoc_obj)
3528 		return;
3529 
3530 	mlme_debug("disable_vlp_sta_conn_to_sp_ap val %x", value);
3531 	mlme_psoc_obj->psoc_cfg.score_config.disable_vlp_sta_conn_to_sp_ap = value;
3532 }
3533 
wlan_cm_get_disable_vlp_sta_conn_to_sp_ap(struct wlan_objmgr_psoc * psoc)3534 bool wlan_cm_get_disable_vlp_sta_conn_to_sp_ap(struct wlan_objmgr_psoc *psoc)
3535 {
3536 	struct psoc_mlme_obj *mlme_psoc_obj;
3537 
3538 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
3539 	if (!mlme_psoc_obj)
3540 		return false;
3541 
3542 	return mlme_psoc_obj->psoc_cfg.score_config.disable_vlp_sta_conn_to_sp_ap;
3543 }
3544 
wlan_cm_set_6ghz_key_mgmt_mask(struct wlan_objmgr_psoc * psoc,uint32_t value)3545 void wlan_cm_set_6ghz_key_mgmt_mask(struct wlan_objmgr_psoc *psoc,
3546 				     uint32_t value)
3547 {
3548 	struct psoc_mlme_obj *mlme_psoc_obj;
3549 
3550 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
3551 	if (!mlme_psoc_obj)
3552 		return;
3553 
3554 	mlme_debug("key_mgmt_mask_6ghz %x", value);
3555 	mlme_psoc_obj->psoc_cfg.score_config.key_mgmt_mask_6ghz = value;
3556 }
3557 
wlan_cm_get_6ghz_key_mgmt_mask(struct wlan_objmgr_psoc * psoc)3558 uint32_t wlan_cm_get_6ghz_key_mgmt_mask(struct wlan_objmgr_psoc *psoc)
3559 {
3560 	struct psoc_mlme_obj *mlme_psoc_obj;
3561 
3562 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
3563 	if (!mlme_psoc_obj)
3564 		return DEFAULT_KEYMGMT_6G_MASK;
3565 
3566 	return mlme_psoc_obj->psoc_cfg.score_config.key_mgmt_mask_6ghz;
3567 }
3568 
cm_fill_6ghz_params(struct wlan_objmgr_psoc * psoc,struct scoring_cfg * score_cfg)3569 static void cm_fill_6ghz_params(struct wlan_objmgr_psoc *psoc,
3570 				struct scoring_cfg *score_cfg)
3571 {
3572 	/* Allow all security in 6Ghz by default */
3573 	score_cfg->check_6ghz_security = cfg_get(psoc, CFG_CHECK_6GHZ_SECURITY);
3574 	score_cfg->key_mgmt_mask_6ghz =
3575 				cfg_get(psoc, CFG_6GHZ_ALLOWED_AKM_MASK);
3576 }
3577 #else
cm_fill_6ghz_params(struct wlan_objmgr_psoc * psoc,struct scoring_cfg * score_cfg)3578 static inline void cm_fill_6ghz_params(struct wlan_objmgr_psoc *psoc,
3579 				       struct scoring_cfg *score_cfg)
3580 {
3581 }
3582 #endif
3583 
3584 static uint32_t
cm_limit_max_per_index_score(uint32_t per_index_score)3585 cm_limit_max_per_index_score(uint32_t per_index_score)
3586 {
3587 	uint8_t i, score;
3588 
3589 	for (i = 0; i < CM_MAX_INDEX_PER_INI; i++) {
3590 		score = CM_GET_SCORE_PERCENTAGE(per_index_score, i);
3591 		if (score > CM_MAX_PCT_SCORE)
3592 			CM_SET_SCORE_PERCENTAGE(per_index_score,
3593 						CM_MAX_PCT_SCORE, i);
3594 	}
3595 
3596 	return per_index_score;
3597 }
3598 
3599 #ifdef WLAN_FEATURE_11BE_MLO
3600 
3601 #define CM_EHT_CAP_WEIGHTAGE 2
3602 #define CM_MLO_WEIGHTAGE 3
3603 #define CM_WLM_INDICATION_WEIGHTAGE 2
3604 #define CM_EMLSR_WEIGHTAGE 3
cm_init_mlo_score_config(struct wlan_objmgr_psoc * psoc,struct scoring_cfg * score_cfg,uint32_t * total_weight)3605 static void cm_init_mlo_score_config(struct wlan_objmgr_psoc *psoc,
3606 				     struct scoring_cfg *score_cfg,
3607 				     uint32_t *total_weight)
3608 {
3609 	score_cfg->weight_config.eht_caps_weightage =
3610 		cfg_get(psoc, CFG_SCORING_EHT_CAPS_WEIGHTAGE);
3611 
3612 	score_cfg->weight_config.mlo_weightage =
3613 		cfg_get(psoc, CFG_SCORING_MLO_WEIGHTAGE);
3614 
3615 	score_cfg->weight_config.wlm_indication_weightage =
3616 		cfg_get(psoc, CFG_SCORING_WLM_INDICATION_WEIGHTAGE);
3617 
3618 	score_cfg->weight_config.joint_rssi_alpha =
3619 				cfg_get(psoc, CFG_SCORING_JOINT_RSSI_ALPHA);
3620 
3621 	score_cfg->weight_config.low_band_rssi_boost =
3622 				cfg_get(psoc, CFG_SCORING_LOW_BAND_RSSI_BOOST);
3623 
3624 	score_cfg->weight_config.joint_esp_alpha =
3625 				cfg_get(psoc, CFG_SCORING_JOINT_ESP_ALPHA);
3626 
3627 	score_cfg->weight_config.low_band_esp_boost =
3628 				cfg_get(psoc, CFG_SCORING_LOW_BAND_ESP_BOOST);
3629 
3630 	score_cfg->weight_config.joint_oce_alpha =
3631 				cfg_get(psoc, CFG_SCORING_JOINT_OCE_ALPHA);
3632 
3633 	score_cfg->weight_config.low_band_oce_boost =
3634 				cfg_get(psoc, CFG_SCORING_LOW_BAND_OCE_BOOST);
3635 
3636 	score_cfg->weight_config.emlsr_weightage =
3637 		cfg_get(psoc, CFG_SCORING_EMLSR_WEIGHTAGE);
3638 
3639 	score_cfg->mlsr_link_selection =
3640 		cfg_get(psoc, CFG_SCORING_MLSR_LINK_SELECTION);
3641 
3642 	*total_weight += score_cfg->weight_config.eht_caps_weightage +
3643 			 score_cfg->weight_config.mlo_weightage +
3644 			 score_cfg->weight_config.wlm_indication_weightage +
3645 			 score_cfg->weight_config.emlsr_weightage;
3646 }
3647 
cm_set_default_mlo_weights(struct scoring_cfg * score_cfg)3648 static void cm_set_default_mlo_weights(struct scoring_cfg *score_cfg)
3649 {
3650 	score_cfg->weight_config.eht_caps_weightage = CM_EHT_CAP_WEIGHTAGE;
3651 	score_cfg->weight_config.mlo_weightage = CM_MLO_WEIGHTAGE;
3652 	score_cfg->weight_config.wlm_indication_weightage =
3653 						CM_WLM_INDICATION_WEIGHTAGE;
3654 	score_cfg->weight_config.emlsr_weightage = CM_EMLSR_WEIGHTAGE;
3655 }
3656 
cm_init_bw_weight_per_index(struct wlan_objmgr_psoc * psoc,struct scoring_cfg * score_cfg)3657 static void cm_init_bw_weight_per_index(struct wlan_objmgr_psoc *psoc,
3658 					struct scoring_cfg *score_cfg)
3659 {
3660 	score_cfg->bandwidth_weight_per_index[0] =
3661 		cm_limit_max_per_index_score(
3662 			cfg_get(psoc, CFG_SCORING_BW_WEIGHT_PER_IDX));
3663 
3664 	score_cfg->bandwidth_weight_per_index[1] =
3665 		cm_limit_max_per_index_score(
3666 			cfg_get(psoc, CFG_SCORING_BW_WEIGHT_PER_IDX_4_TO_7));
3667 
3668 	score_cfg->bandwidth_weight_per_index[2] =
3669 		cm_limit_max_per_index_score(
3670 		     cfg_get(psoc, CFG_SCORING_BW_WEIGHT_PER_IDX_8_TO_11));
3671 
3672 	score_cfg->bandwidth_weight_per_index[3] =
3673 		cm_limit_max_per_index_score(
3674 		    cfg_get(psoc, CFG_SCORING_BW_WEIGHT_PER_IDX_12_TO_15));
3675 
3676 	score_cfg->bandwidth_weight_per_index[4] =
3677 		cm_limit_max_per_index_score(
3678 		    cfg_get(psoc, CFG_SCORING_BW_WEIGHT_PER_IDX_16_TO_19));
3679 
3680 	score_cfg->bandwidth_weight_per_index[5] =
3681 		cm_limit_max_per_index_score(
3682 		    cfg_get(psoc, CFG_SCORING_BW_WEIGHT_PER_IDX_20_TO_23));
3683 
3684 	score_cfg->bandwidth_weight_per_index[6] =
3685 		cm_limit_max_per_index_score(
3686 		    cfg_get(psoc, CFG_SCORING_BW_WEIGHT_PER_IDX_24_TO_27));
3687 
3688 	score_cfg->bandwidth_weight_per_index[7] =
3689 		cm_limit_max_per_index_score(
3690 		    cfg_get(psoc, CFG_SCORING_BW_WEIGHT_PER_IDX_28_TO_31));
3691 
3692 	score_cfg->bandwidth_weight_per_index[8] =
3693 		cm_limit_max_per_index_score(
3694 		    cfg_get(psoc, CFG_SCORING_BW_WEIGHT_PER_IDX_32_TO_35));
3695 }
3696 
cm_init_nss_weight_per_index(struct wlan_objmgr_psoc * psoc,struct scoring_cfg * score_cfg)3697 static void cm_init_nss_weight_per_index(struct wlan_objmgr_psoc *psoc,
3698 					 struct scoring_cfg *score_cfg)
3699 {
3700 	score_cfg->nss_weight_per_index[0] =
3701 		cm_limit_max_per_index_score(
3702 			cfg_get(psoc, CFG_SCORING_NSS_WEIGHT_PER_IDX));
3703 
3704 	score_cfg->nss_weight_per_index[1] =
3705 		cm_limit_max_per_index_score(
3706 		      cfg_get(psoc, CFG_SCORING_ML_NSS_WEIGHT_PER_IDX_4_TO_7));
3707 }
3708 #else
cm_init_mlo_score_config(struct wlan_objmgr_psoc * psoc,struct scoring_cfg * score_cfg,uint32_t * total_weight)3709 static void cm_init_mlo_score_config(struct wlan_objmgr_psoc *psoc,
3710 				     struct scoring_cfg *score_cfg,
3711 				     uint32_t *total_weight)
3712 {
3713 }
3714 
cm_set_default_mlo_weights(struct scoring_cfg * score_cfg)3715 static void cm_set_default_mlo_weights(struct scoring_cfg *score_cfg)
3716 {
3717 }
3718 
3719 #ifdef WLAN_FEATURE_11BE
cm_init_bw_weight_per_index(struct wlan_objmgr_psoc * psoc,struct scoring_cfg * score_cfg)3720 static void cm_init_bw_weight_per_index(struct wlan_objmgr_psoc *psoc,
3721 					struct scoring_cfg *score_cfg)
3722 {
3723 	score_cfg->bandwidth_weight_per_index[0] =
3724 		cm_limit_max_per_index_score(
3725 			cfg_get(psoc, CFG_SCORING_BW_WEIGHT_PER_IDX));
3726 
3727 	score_cfg->bandwidth_weight_per_index[1] =
3728 		cm_limit_max_per_index_score(
3729 			cfg_get(psoc, CFG_SCORING_BW_WEIGHT_PER_IDX_4_TO_7));
3730 
3731 	score_cfg->bandwidth_weight_per_index[2] =
3732 		cm_limit_max_per_index_score(
3733 		     cfg_get(psoc, CFG_SCORING_BW_WEIGHT_PER_IDX_8_TO_11));
3734 }
3735 #else
cm_init_bw_weight_per_index(struct wlan_objmgr_psoc * psoc,struct scoring_cfg * score_cfg)3736 static void cm_init_bw_weight_per_index(struct wlan_objmgr_psoc *psoc,
3737 					struct scoring_cfg *score_cfg)
3738 {
3739 	score_cfg->bandwidth_weight_per_index[0] =
3740 		cm_limit_max_per_index_score(
3741 			cfg_get(psoc, CFG_SCORING_BW_WEIGHT_PER_IDX));
3742 }
3743 #endif
3744 
cm_init_nss_weight_per_index(struct wlan_objmgr_psoc * psoc,struct scoring_cfg * score_cfg)3745 static void cm_init_nss_weight_per_index(struct wlan_objmgr_psoc *psoc,
3746 					 struct scoring_cfg *score_cfg)
3747 {
3748 	score_cfg->nss_weight_per_index[0] =
3749 		cm_limit_max_per_index_score(
3750 			cfg_get(psoc, CFG_SCORING_NSS_WEIGHT_PER_IDX));
3751 }
3752 #endif
3753 
wlan_cm_init_score_config(struct wlan_objmgr_psoc * psoc,struct scoring_cfg * score_cfg)3754 void wlan_cm_init_score_config(struct wlan_objmgr_psoc *psoc,
3755 			       struct scoring_cfg *score_cfg)
3756 {
3757 	uint32_t total_weight;
3758 
3759 	score_cfg->weight_config.rssi_weightage =
3760 		cfg_get(psoc, CFG_SCORING_RSSI_WEIGHTAGE);
3761 	score_cfg->weight_config.ht_caps_weightage =
3762 		cfg_get(psoc, CFG_SCORING_HT_CAPS_WEIGHTAGE);
3763 	score_cfg->weight_config.vht_caps_weightage =
3764 		cfg_get(psoc, CFG_SCORING_VHT_CAPS_WEIGHTAGE);
3765 	score_cfg->weight_config.he_caps_weightage =
3766 		cfg_get(psoc, CFG_SCORING_HE_CAPS_WEIGHTAGE);
3767 	score_cfg->weight_config.chan_width_weightage =
3768 		cfg_get(psoc, CFG_SCORING_CHAN_WIDTH_WEIGHTAGE);
3769 	score_cfg->weight_config.chan_band_weightage =
3770 		cfg_get(psoc, CFG_SCORING_CHAN_BAND_WEIGHTAGE);
3771 	score_cfg->weight_config.nss_weightage =
3772 		cfg_get(psoc, CFG_SCORING_NSS_WEIGHTAGE);
3773 	score_cfg->weight_config.beamforming_cap_weightage =
3774 		cfg_get(psoc, CFG_SCORING_BEAMFORM_CAP_WEIGHTAGE);
3775 	score_cfg->weight_config.pcl_weightage =
3776 		cfg_get(psoc, CFG_SCORING_PCL_WEIGHTAGE);
3777 	score_cfg->weight_config.channel_congestion_weightage =
3778 		cfg_get(psoc, CFG_SCORING_CHAN_CONGESTION_WEIGHTAGE);
3779 	score_cfg->weight_config.oce_wan_weightage =
3780 		cfg_get(psoc, CFG_SCORING_OCE_WAN_WEIGHTAGE);
3781 	score_cfg->weight_config.oce_ap_tx_pwr_weightage =
3782 				cfg_get(psoc, CFG_OCE_AP_TX_PWR_WEIGHTAGE);
3783 	score_cfg->weight_config.oce_subnet_id_weightage =
3784 				cfg_get(psoc, CFG_OCE_SUBNET_ID_WEIGHTAGE);
3785 	score_cfg->weight_config.sae_pk_ap_weightage =
3786 				cfg_get(psoc, CFG_SAE_PK_AP_WEIGHTAGE);
3787 	score_cfg->weight_config.security_weightage = CM_SECURITY_WEIGHTAGE;
3788 
3789 	total_weight =  score_cfg->weight_config.rssi_weightage +
3790 			score_cfg->weight_config.ht_caps_weightage +
3791 			score_cfg->weight_config.vht_caps_weightage +
3792 			score_cfg->weight_config.he_caps_weightage +
3793 			score_cfg->weight_config.chan_width_weightage +
3794 			score_cfg->weight_config.chan_band_weightage +
3795 			score_cfg->weight_config.nss_weightage +
3796 			score_cfg->weight_config.beamforming_cap_weightage +
3797 			score_cfg->weight_config.pcl_weightage +
3798 			score_cfg->weight_config.channel_congestion_weightage +
3799 			score_cfg->weight_config.oce_wan_weightage +
3800 			score_cfg->weight_config.oce_ap_tx_pwr_weightage +
3801 			score_cfg->weight_config.oce_subnet_id_weightage +
3802 			score_cfg->weight_config.sae_pk_ap_weightage +
3803 			score_cfg->weight_config.security_weightage;
3804 
3805 	cm_init_mlo_score_config(psoc, score_cfg, &total_weight);
3806 
3807 	/*
3808 	 * If configured weights are greater than max weight,
3809 	 * fallback to default weights
3810 	 */
3811 	if (total_weight > CM_BEST_CANDIDATE_MAX_WEIGHT) {
3812 		mlme_err("Total weight greater than %d, using default weights",
3813 			 CM_BEST_CANDIDATE_MAX_WEIGHT);
3814 		score_cfg->weight_config.rssi_weightage = CM_RSSI_WEIGHTAGE;
3815 		score_cfg->weight_config.ht_caps_weightage =
3816 						CM_HT_CAPABILITY_WEIGHTAGE;
3817 		score_cfg->weight_config.vht_caps_weightage =
3818 						CM_VHT_CAP_WEIGHTAGE;
3819 		score_cfg->weight_config.he_caps_weightage =
3820 						CM_HE_CAP_WEIGHTAGE;
3821 		score_cfg->weight_config.chan_width_weightage =
3822 						CM_CHAN_WIDTH_WEIGHTAGE;
3823 		score_cfg->weight_config.chan_band_weightage =
3824 						CM_CHAN_BAND_WEIGHTAGE;
3825 		score_cfg->weight_config.nss_weightage = CM_NSS_WEIGHTAGE;
3826 		score_cfg->weight_config.beamforming_cap_weightage =
3827 						CM_BEAMFORMING_CAP_WEIGHTAGE;
3828 		score_cfg->weight_config.pcl_weightage = CM_PCL_WEIGHT;
3829 		score_cfg->weight_config.channel_congestion_weightage =
3830 						CM_CHANNEL_CONGESTION_WEIGHTAGE;
3831 		score_cfg->weight_config.oce_wan_weightage =
3832 						CM_OCE_WAN_WEIGHTAGE;
3833 		score_cfg->weight_config.oce_ap_tx_pwr_weightage =
3834 						CM_OCE_AP_TX_POWER_WEIGHTAGE;
3835 		score_cfg->weight_config.oce_subnet_id_weightage =
3836 						CM_OCE_SUBNET_ID_WEIGHTAGE;
3837 		score_cfg->weight_config.sae_pk_ap_weightage =
3838 						CM_SAE_PK_AP_WEIGHTAGE;
3839 		cm_set_default_mlo_weights(score_cfg);
3840 	}
3841 
3842 	score_cfg->rssi_score.best_rssi_threshold =
3843 		cfg_get(psoc, CFG_SCORING_BEST_RSSI_THRESHOLD);
3844 	score_cfg->rssi_score.good_rssi_threshold =
3845 		cfg_get(psoc, CFG_SCORING_GOOD_RSSI_THRESHOLD);
3846 	score_cfg->rssi_score.bad_rssi_threshold =
3847 		cfg_get(psoc, CFG_SCORING_BAD_RSSI_THRESHOLD);
3848 
3849 	score_cfg->rssi_score.good_rssi_pcnt =
3850 		cfg_get(psoc, CFG_SCORING_GOOD_RSSI_PERCENT);
3851 	score_cfg->rssi_score.bad_rssi_pcnt =
3852 		cfg_get(psoc, CFG_SCORING_BAD_RSSI_PERCENT);
3853 
3854 	score_cfg->rssi_score.good_rssi_bucket_size =
3855 		cfg_get(psoc, CFG_SCORING_GOOD_RSSI_BUCKET_SIZE);
3856 	score_cfg->rssi_score.bad_rssi_bucket_size =
3857 		cfg_get(psoc, CFG_SCORING_BAD_RSSI_BUCKET_SIZE);
3858 
3859 	score_cfg->rssi_score.rssi_pref_5g_rssi_thresh =
3860 		cfg_get(psoc, CFG_SCORING_RSSI_PREF_5G_THRESHOLD);
3861 
3862 	score_cfg->rssi_score.con_non_hint_target_rssi_threshold =
3863 		cfg_get(psoc, CFG_CON_NON_HINT_TARGET_MIN_RSSI);
3864 
3865 	score_cfg->esp_qbss_scoring.num_slot =
3866 		cfg_get(psoc, CFG_SCORING_NUM_ESP_QBSS_SLOTS);
3867 	score_cfg->esp_qbss_scoring.score_pcnt3_to_0 =
3868 		cm_limit_max_per_index_score(
3869 			cfg_get(psoc, CFG_SCORING_ESP_QBSS_SCORE_IDX_3_TO_0));
3870 	score_cfg->esp_qbss_scoring.score_pcnt7_to_4 =
3871 		cm_limit_max_per_index_score(
3872 			cfg_get(psoc, CFG_SCORING_ESP_QBSS_SCORE_IDX_7_TO_4));
3873 	score_cfg->esp_qbss_scoring.score_pcnt11_to_8 =
3874 		cm_limit_max_per_index_score(
3875 			cfg_get(psoc, CFG_SCORING_ESP_QBSS_SCORE_IDX_11_TO_8));
3876 	score_cfg->esp_qbss_scoring.score_pcnt15_to_12 =
3877 		cm_limit_max_per_index_score(
3878 			cfg_get(psoc, CFG_SCORING_ESP_QBSS_SCORE_IDX_15_TO_12));
3879 
3880 	score_cfg->oce_wan_scoring.num_slot =
3881 		cfg_get(psoc, CFG_SCORING_NUM_OCE_WAN_SLOTS);
3882 	score_cfg->oce_wan_scoring.score_pcnt3_to_0 =
3883 		cm_limit_max_per_index_score(
3884 			cfg_get(psoc, CFG_SCORING_OCE_WAN_SCORE_IDX_3_TO_0));
3885 	score_cfg->oce_wan_scoring.score_pcnt7_to_4 =
3886 		cm_limit_max_per_index_score(
3887 			cfg_get(psoc, CFG_SCORING_OCE_WAN_SCORE_IDX_7_TO_4));
3888 	score_cfg->oce_wan_scoring.score_pcnt11_to_8 =
3889 		cm_limit_max_per_index_score(
3890 			cfg_get(psoc, CFG_SCORING_OCE_WAN_SCORE_IDX_11_TO_8));
3891 	score_cfg->oce_wan_scoring.score_pcnt15_to_12 =
3892 		cm_limit_max_per_index_score(
3893 			cfg_get(psoc, CFG_SCORING_OCE_WAN_SCORE_IDX_15_TO_12));
3894 
3895 	score_cfg->band_weight_per_index =
3896 		cm_limit_max_per_index_score(
3897 			cfg_get(psoc, CFG_SCORING_BAND_WEIGHT_PER_IDX));
3898 	score_cfg->is_bssid_hint_priority =
3899 			cfg_get(psoc, CFG_IS_BSSID_HINT_PRIORITY);
3900 	score_cfg->vendor_roam_score_algorithm =
3901 			cfg_get(psoc, CFG_VENDOR_ROAM_SCORE_ALGORITHM);
3902 	score_cfg->check_assoc_disallowed = true;
3903 	cm_fill_6ghz_params(psoc, score_cfg);
3904 
3905 	cm_init_bw_weight_per_index(psoc, score_cfg);
3906 	cm_init_nss_weight_per_index(psoc, score_cfg);
3907 	score_cfg->security_weight_per_index = CM_SECURITY_INDEX_WEIGHTAGE;
3908 }
3909