xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlme/connection_mgr/core/src/wlan_cm_bss_scoring.c (revision 97f44cd39e4ff816eaa1710279d28cf6b9e65ad9)
1 /*
2  * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /*
18  * DOC: contains bss scoring logic
19  */
20 
21 #ifdef WLAN_POLICY_MGR_ENABLE
22 #include "wlan_policy_mgr_api.h"
23 #endif
24 #include <include/wlan_psoc_mlme.h>
25 #include "wlan_psoc_mlme_api.h"
26 #include "cfg_ucfg_api.h"
27 #include "wlan_cm_bss_score_param.h"
28 #include "wlan_scan_api.h"
29 #include "wlan_crypto_global_api.h"
30 #include "wlan_mgmt_txrx_utils_api.h"
31 #ifdef CONN_MGR_ADV_FEATURE
32 #include "wlan_mlme_api.h"
33 #endif
34 
35 #define CM_20MHZ_BW_INDEX                  0
36 #define CM_40MHZ_BW_INDEX                  1
37 #define CM_80MHZ_BW_INDEX                  2
38 #define CM_160MHZ_BW_INDEX                 3
39 #define CM_MAX_BW_INDEX                    4
40 
41 #define CM_PCL_RSSI_THRESHOLD -75
42 
43 #define CM_NSS_1x1_INDEX                   0
44 #define CM_NSS_2x2_INDEX                   1
45 #define CM_NSS_3x3_INDEX                   2
46 #define CM_NSS_4x4_INDEX                   3
47 #define CM_MAX_NSS_INDEX                   4
48 
49 #define CM_BAND_2G_INDEX                   0
50 #define CM_BAND_5G_INDEX                   1
51 #define CM_BAND_6G_INDEX                   2
52 /* 3 is reserved */
53 #define CM_MAX_BAND_INDEX                  4
54 
55 #define CM_SCORE_INDEX_0                   0
56 #define CM_SCORE_INDEX_3                   3
57 #define CM_SCORE_INDEX_7                   7
58 #define CM_SCORE_OFFSET_INDEX_7_4          4
59 #define CM_SCORE_INDEX_11                  11
60 #define CM_SCORE_OFFSET_INDEX_11_8         8
61 #define CM_SCORE_MAX_INDEX                 15
62 #define CM_SCORE_OFFSET_INDEX_15_12        12
63 
64 #define CM_MAX_OCE_WAN_DL_CAP 16
65 
66 #define CM_MAX_CHANNEL_WEIGHT 100
67 #define CM_MAX_CHANNEL_UTILIZATION 100
68 #define CM_MAX_ESTIMATED_AIR_TIME_FRACTION 255
69 #define CM_MAX_AP_LOAD 255
70 
71 #define CM_MAX_WEIGHT_OF_PCL_CHANNELS 255
72 #define CM_PCL_GROUPS_WEIGHT_DIFFERENCE 20
73 
74 /* Congestion threshold (channel load %) to consider band and OCE WAN score */
75 #define CM_CONGESTION_THRSHOLD_FOR_BAND_OCE_SCORE 75
76 
77 #define CM_RSSI_WEIGHTAGE 20
78 #define CM_HT_CAPABILITY_WEIGHTAGE 2
79 #define CM_VHT_CAP_WEIGHTAGE 1
80 #define CM_HE_CAP_WEIGHTAGE 2
81 #define CM_CHAN_WIDTH_WEIGHTAGE 12
82 #define CM_CHAN_BAND_WEIGHTAGE 2
83 #define CM_NSS_WEIGHTAGE 16
84 #define CM_BEAMFORMING_CAP_WEIGHTAGE 2
85 #define CM_PCL_WEIGHT 10
86 #define CM_CHANNEL_CONGESTION_WEIGHTAGE 5
87 #define CM_OCE_WAN_WEIGHTAGE 2
88 #define CM_OCE_AP_TX_POWER_WEIGHTAGE 5
89 #define CM_OCE_SUBNET_ID_WEIGHTAGE 3
90 #define CM_SAE_PK_AP_WEIGHTAGE 3
91 #define CM_BEST_CANDIDATE_MAX_WEIGHT 200
92 #define CM_MAX_PCT_SCORE 100
93 #define CM_MAX_INDEX_PER_INI 4
94 
95 #define CM_BEST_CANDIDATE_MAX_BSS_SCORE (CM_BEST_CANDIDATE_MAX_WEIGHT * 100)
96 #define CM_AVOID_CANDIDATE_MIN_SCORE 1
97 
98 #define CM_GET_SCORE_PERCENTAGE(value32, bw_index) \
99 	QDF_GET_BITS(value32, (8 * (bw_index)), 8)
100 #define CM_SET_SCORE_PERCENTAGE(value32, score_pcnt, bw_index) \
101 	QDF_SET_BITS(value32, (8 * (bw_index)), 8, score_pcnt)
102 
103 #ifdef CONN_MGR_ADV_FEATURE
104 /* 3.2 us + 0.8 us(GI) */
105 #define PPDU_PAYLOAD_SYMBOL_DUR_US 4
106 /* 12.8 us + (0.8 + 1.6)/2 us(GI) */
107 #define HE_PPDU_PAYLOAD_SYMBOL_DUR_US 14
108 #define MAC_HEADER_LEN 26
109 /* Minimum snrDb supported by LUT */
110 #define SNR_DB_TO_BIT_PER_TONE_LUT_MIN -10
111 /* Maximum snrDb supported by LUT */
112 #define SNR_DB_TO_BIT_PER_TONE_LUT_MAX 9
113 #define DB_NUM 20
114 /*
115  * A fudge factor to represent HW implementation margin in dB.
116  * Predicted throughput matches pretty well with OTA throughput with this
117  * fudge factor.
118  */
119 #define SNR_MARGIN_DB 16
120 #define TWO_IN_DB 3
121 static int32_t
122 SNR_DB_TO_BIT_PER_TONE_LUT[DB_NUM] = {0, 171, 212, 262, 323, 396, 484,
123 586, 706, 844, 1000, 1176, 1370, 1583, 1812, 2058, 2317, 2588, 2870, 3161};
124 #endif
125 
126 static bool cm_is_better_bss(struct scan_cache_entry *bss1,
127 			     struct scan_cache_entry *bss2)
128 {
129 	if (bss1->bss_score > bss2->bss_score)
130 		return true;
131 	else if (bss1->bss_score == bss2->bss_score)
132 		if (bss1->rssi_raw > bss2->rssi_raw)
133 			return true;
134 
135 	return false;
136 }
137 
138 /**
139  * cm_get_rssi_pcnt_for_slot() - calculate rssi % score based on the slot
140  * index between the high rssi and low rssi threshold
141  * @high_rssi_threshold: High rssi of the window
142  * @low_rssi_threshold: low rssi of the window
143  * @high_rssi_pcnt: % score for the high rssi
144  * @low_rssi_pcnt: %score for the low rssi
145  * @bucket_size: bucket size of the window
146  * @bss_rssi: Input rssi for which value need to be calculated
147  *
148  * Return: rssi pct to use for the given rssi
149  */
150 static inline
151 int8_t cm_get_rssi_pcnt_for_slot(int32_t high_rssi_threshold,
152 				 int32_t low_rssi_threshold,
153 				 uint32_t high_rssi_pcnt,
154 				 uint32_t low_rssi_pcnt,
155 				 uint32_t bucket_size, int8_t bss_rssi)
156 {
157 	int8_t slot_index, slot_size, rssi_diff, num_slot, rssi_pcnt;
158 
159 	num_slot = ((high_rssi_threshold -
160 		     low_rssi_threshold) / bucket_size) + 1;
161 	slot_size = ((high_rssi_pcnt - low_rssi_pcnt) +
162 		     (num_slot / 2)) / (num_slot);
163 	rssi_diff = high_rssi_threshold - bss_rssi;
164 	slot_index = (rssi_diff / bucket_size) + 1;
165 	rssi_pcnt = high_rssi_pcnt - (slot_size * slot_index);
166 	if (rssi_pcnt < low_rssi_pcnt)
167 		rssi_pcnt = low_rssi_pcnt;
168 
169 	mlme_debug("Window %d -> %d pcnt range %d -> %d bucket_size %d bss_rssi %d num_slot %d slot_size %d rssi_diff %d slot_index %d rssi_pcnt %d",
170 		   high_rssi_threshold, low_rssi_threshold, high_rssi_pcnt,
171 		   low_rssi_pcnt, bucket_size, bss_rssi, num_slot, slot_size,
172 		   rssi_diff, slot_index, rssi_pcnt);
173 
174 	return rssi_pcnt;
175 }
176 
177 /**
178  * cm_calculate_rssi_score() - Calculate RSSI score based on AP RSSI
179  * @score_param: rssi score params
180  * @rssi: rssi of the AP
181  * @rssi_weightage: rssi_weightage out of total weightage
182  *
183  * Return: rssi score
184  */
185 static int32_t cm_calculate_rssi_score(struct rssi_config_score *score_param,
186 				       int32_t rssi, uint8_t rssi_weightage)
187 {
188 	int8_t rssi_pcnt;
189 	int32_t total_rssi_score;
190 	int32_t best_rssi_threshold;
191 	int32_t good_rssi_threshold;
192 	int32_t bad_rssi_threshold;
193 	uint32_t good_rssi_pcnt;
194 	uint32_t bad_rssi_pcnt;
195 	uint32_t good_bucket_size;
196 	uint32_t bad_bucket_size;
197 
198 	best_rssi_threshold = score_param->best_rssi_threshold * (-1);
199 	good_rssi_threshold = score_param->good_rssi_threshold * (-1);
200 	bad_rssi_threshold = score_param->bad_rssi_threshold * (-1);
201 	good_rssi_pcnt = score_param->good_rssi_pcnt;
202 	bad_rssi_pcnt = score_param->bad_rssi_pcnt;
203 	good_bucket_size = score_param->good_rssi_bucket_size;
204 	bad_bucket_size = score_param->bad_rssi_bucket_size;
205 
206 	total_rssi_score = (CM_MAX_PCT_SCORE * rssi_weightage);
207 
208 	/*
209 	 * If RSSI is better than the best rssi threshold then it return full
210 	 * score.
211 	 */
212 	if (rssi > best_rssi_threshold)
213 		return total_rssi_score;
214 	/*
215 	 * If RSSI is less or equal to bad rssi threshold then it return
216 	 * least score.
217 	 */
218 	if (rssi <= bad_rssi_threshold)
219 		return (total_rssi_score * bad_rssi_pcnt) / 100;
220 
221 	/* RSSI lies between best to good rssi threshold */
222 	if (rssi > good_rssi_threshold)
223 		rssi_pcnt = cm_get_rssi_pcnt_for_slot(best_rssi_threshold,
224 				good_rssi_threshold, 100, good_rssi_pcnt,
225 				good_bucket_size, rssi);
226 	else
227 		rssi_pcnt = cm_get_rssi_pcnt_for_slot(good_rssi_threshold,
228 				bad_rssi_threshold, good_rssi_pcnt,
229 				bad_rssi_pcnt, bad_bucket_size,
230 				rssi);
231 
232 	return (total_rssi_score * rssi_pcnt) / 100;
233 }
234 
235 /**
236  * cm_rssi_is_same_bucket() - check if both rssi fall in same bucket
237  * @rssi_top_thresh: high rssi threshold of the the window
238  * @low_rssi_threshold: low rssi of the window
239  * @rssi_ref1: rssi ref one
240  * @rssi_ref2: rssi ref two
241  * @bucket_size: bucket size of the window
242  *
243  * Return: true if both fall in same window
244  */
245 static inline bool cm_rssi_is_same_bucket(int8_t rssi_top_thresh,
246 					  int8_t rssi_ref1, int8_t rssi_ref2,
247 					  int8_t bucket_size)
248 {
249 	int8_t rssi_diff1 = 0;
250 	int8_t rssi_diff2 = 0;
251 
252 	rssi_diff1 = rssi_top_thresh - rssi_ref1;
253 	rssi_diff2 = rssi_top_thresh - rssi_ref2;
254 
255 	return (rssi_diff1 / bucket_size) == (rssi_diff2 / bucket_size);
256 }
257 
258 /**
259  * cm_roam_calculate_prorated_pcnt_by_rssi() - Calculate prorated RSSI score
260  * based on AP RSSI. This will be used to determine HT VHT score
261  * @score_param: rssi score params
262  * @rssi: bss rssi
263  * @rssi_weightage: rssi_weightage out of total weightage
264  *
265  * If rssi is greater than good threshold return 100, if less than bad return 0,
266  * if between good and bad, return prorated rssi score for the index.
267  *
268  * Return: rssi prorated score
269  */
270 static int8_t cm_roam_calculate_prorated_pcnt_by_rssi(
271 	struct rssi_config_score *score_param,
272 	int32_t rssi, uint8_t rssi_weightage)
273 {
274 	int32_t good_rssi_threshold;
275 	int32_t bad_rssi_threshold;
276 	int8_t rssi_pref_5g_rssi_thresh;
277 	bool same_bucket;
278 
279 	good_rssi_threshold = score_param->good_rssi_threshold * (-1);
280 	bad_rssi_threshold = score_param->bad_rssi_threshold * (-1);
281 	rssi_pref_5g_rssi_thresh = score_param->rssi_pref_5g_rssi_thresh * (-1);
282 
283 	/* If RSSI is greater than good rssi return full weight */
284 	if (rssi > good_rssi_threshold)
285 		return CM_MAX_PCT_SCORE;
286 
287 	same_bucket = cm_rssi_is_same_bucket(good_rssi_threshold, rssi,
288 					     rssi_pref_5g_rssi_thresh,
289 					     score_param->bad_rssi_bucket_size);
290 	if (same_bucket || (rssi < rssi_pref_5g_rssi_thresh))
291 		return 0;
292 	/* If RSSI is less or equal to bad rssi threshold then it return 0 */
293 	if (rssi <= bad_rssi_threshold)
294 		return 0;
295 
296 	/* If RSSI is between good and bad threshold */
297 	return cm_get_rssi_pcnt_for_slot(good_rssi_threshold,
298 					 bad_rssi_threshold,
299 					 score_param->good_rssi_pcnt,
300 					 score_param->bad_rssi_pcnt,
301 					 score_param->bad_rssi_bucket_size,
302 					 rssi);
303 }
304 
305 /**
306  * cm_calculate_bandwidth_score() - Calculate BW score
307  * @entry: scan entry
308  * @score_config: scoring config
309  * @phy_config: psoc phy configs
310  * @prorated_pct: prorated % to return dependent on RSSI
311  *
312  * Return: bw score
313  */
314 static int32_t cm_calculate_bandwidth_score(struct scan_cache_entry *entry,
315 					    struct scoring_cfg *score_config,
316 					    struct psoc_phy_config *phy_config,
317 					    uint8_t prorated_pct)
318 {
319 	uint32_t score;
320 	int32_t bw_weight_per_idx;
321 	uint8_t bw_above_20 = 0;
322 	uint8_t ch_width_index;
323 	bool is_vht = false;
324 
325 	bw_weight_per_idx = score_config->bandwidth_weight_per_index;
326 
327 	if (WLAN_REG_IS_24GHZ_CH_FREQ(entry->channel.chan_freq)) {
328 		bw_above_20 = phy_config->bw_above_20_24ghz;
329 		if (phy_config->vht_24G_cap)
330 			is_vht = true;
331 	} else if (phy_config->vht_cap) {
332 		is_vht = true;
333 		bw_above_20 = phy_config->bw_above_20_5ghz;
334 	}
335 
336 	if (IS_WLAN_PHYMODE_160MHZ(entry->phy_mode))
337 		ch_width_index = CM_160MHZ_BW_INDEX;
338 	else if (IS_WLAN_PHYMODE_80MHZ(entry->phy_mode))
339 		ch_width_index = CM_80MHZ_BW_INDEX;
340 	else if (IS_WLAN_PHYMODE_40MHZ(entry->phy_mode))
341 		ch_width_index = CM_40MHZ_BW_INDEX;
342 	else
343 		ch_width_index = CM_20MHZ_BW_INDEX;
344 
345 	if (!phy_config->ht_cap &&
346 	    ch_width_index > CM_20MHZ_BW_INDEX)
347 		ch_width_index = CM_20MHZ_BW_INDEX;
348 
349 	if (!is_vht && ch_width_index > CM_40MHZ_BW_INDEX)
350 		ch_width_index = CM_40MHZ_BW_INDEX;
351 
352 	if (bw_above_20 && ch_width_index > CM_20MHZ_BW_INDEX)
353 		score = CM_GET_SCORE_PERCENTAGE(bw_weight_per_idx,
354 						ch_width_index);
355 	else
356 		score = CM_GET_SCORE_PERCENTAGE(bw_weight_per_idx,
357 						CM_20MHZ_BW_INDEX);
358 
359 	return (prorated_pct * score *
360 		score_config->weight_config.chan_width_weightage) /
361 		CM_MAX_PCT_SCORE;
362 }
363 
364 /**
365  * cm_get_score_for_index() - get score for the given index
366  * @index: index for which we need the score
367  * @weightage: weigtage for the param
368  * @score: per slot score
369  *
370  * Return: score for the index
371  */
372 static int32_t cm_get_score_for_index(uint8_t index,
373 				      uint8_t weightage,
374 				      struct per_slot_score *score)
375 {
376 	if (index <= CM_SCORE_INDEX_3)
377 		return weightage * CM_GET_SCORE_PERCENTAGE(
378 				   score->score_pcnt3_to_0,
379 				   index);
380 	else if (index <= CM_SCORE_INDEX_7)
381 		return weightage * CM_GET_SCORE_PERCENTAGE(
382 				   score->score_pcnt7_to_4,
383 				   index - CM_SCORE_OFFSET_INDEX_7_4);
384 	else if (index <= CM_SCORE_INDEX_11)
385 		return weightage * CM_GET_SCORE_PERCENTAGE(
386 				   score->score_pcnt11_to_8,
387 				   index - CM_SCORE_OFFSET_INDEX_11_8);
388 	else
389 		return weightage * CM_GET_SCORE_PERCENTAGE(
390 				   score->score_pcnt15_to_12,
391 				   index - CM_SCORE_OFFSET_INDEX_15_12);
392 }
393 
394 /**
395  * cm_get_congestion_pct() - Calculate congestion pct from esp/qbss load
396  * @entry: bss information
397  *
398  * Return: congestion pct
399  */
400 static int32_t cm_get_congestion_pct(struct scan_cache_entry *entry)
401 {
402 	uint32_t ap_load = 0;
403 	uint32_t est_air_time_percentage = 0;
404 	uint32_t congestion = 0;
405 
406 	if (entry->air_time_fraction) {
407 		/* Convert 0-255 range to percentage */
408 		est_air_time_percentage = entry->air_time_fraction *
409 							CM_MAX_CHANNEL_WEIGHT;
410 		est_air_time_percentage = qdf_do_div(est_air_time_percentage,
411 					   CM_MAX_ESTIMATED_AIR_TIME_FRACTION);
412 		/*
413 		 * Calculate channel congestion from estimated air time
414 		 * fraction.
415 		 */
416 		congestion = CM_MAX_CHANNEL_UTILIZATION -
417 					est_air_time_percentage;
418 	} else if (entry->qbss_chan_load) {
419 		ap_load = (entry->qbss_chan_load * CM_MAX_PCT_SCORE);
420 		/*
421 		 * Calculate ap_load in % from qbss channel load from
422 		 * 0-255 range
423 		 */
424 		congestion = qdf_do_div(ap_load, CM_MAX_AP_LOAD);
425 		if (!congestion)
426 			congestion = 1;
427 	}
428 
429 	return congestion;
430 }
431 
432 /**
433  * cm_calculate_congestion_score() - Calculate congestion score
434  * @entry: bss information
435  * @score_params: bss score params
436  * @congestion_pct: congestion pct
437  *
438  * Return: congestion score
439  */
440 static int32_t cm_calculate_congestion_score(struct scan_cache_entry *entry,
441 					     struct scoring_cfg *score_params,
442 					     uint32_t *congestion_pct)
443 {
444 	uint32_t window_size;
445 	uint8_t index;
446 	int32_t good_rssi_threshold;
447 	uint8_t chan_congestion_weight;
448 
449 	*congestion_pct = cm_get_congestion_pct(entry);
450 
451 	if (!score_params->esp_qbss_scoring.num_slot)
452 		return 0;
453 
454 	if (score_params->esp_qbss_scoring.num_slot >
455 	    CM_SCORE_MAX_INDEX)
456 		score_params->esp_qbss_scoring.num_slot =
457 			CM_SCORE_MAX_INDEX;
458 
459 	good_rssi_threshold =
460 		score_params->rssi_score.good_rssi_threshold * (-1);
461 
462 	chan_congestion_weight =
463 		score_params->weight_config.channel_congestion_weightage;
464 
465 	/* For bad zone rssi get score from last index */
466 	if (entry->rssi_raw <= good_rssi_threshold)
467 		return cm_get_score_for_index(
468 			score_params->esp_qbss_scoring.num_slot,
469 			chan_congestion_weight,
470 			&score_params->esp_qbss_scoring);
471 
472 	if (!*congestion_pct)
473 		return chan_congestion_weight *
474 			   CM_GET_SCORE_PERCENTAGE(
475 			   score_params->esp_qbss_scoring.score_pcnt3_to_0,
476 			   CM_SCORE_INDEX_0);
477 
478 	window_size = CM_MAX_PCT_SCORE /
479 			score_params->esp_qbss_scoring.num_slot;
480 
481 	/* Desired values are from 1 to 15, as 0 is for not present. so do +1 */
482 	index = qdf_do_div(*congestion_pct, window_size) + 1;
483 
484 	if (index > score_params->esp_qbss_scoring.num_slot)
485 		index = score_params->esp_qbss_scoring.num_slot;
486 
487 	return cm_get_score_for_index(index,
488 				      chan_congestion_weight,
489 				      &score_params->esp_qbss_scoring);
490 }
491 
492 /**
493  * cm_calculate_nss_score() - Calculate congestion score
494  * @psoc: psoc ptr
495  * @score_config: scoring config
496  * @ap_nss: ap nss
497  * @prorated_pct: prorated % to return dependent on RSSI
498  *
499  * Return: nss score
500  */
501 static int32_t cm_calculate_nss_score(struct wlan_objmgr_psoc *psoc,
502 				      struct scoring_cfg *score_config,
503 				      uint8_t ap_nss, uint8_t prorated_pct,
504 				      uint32_t sta_nss)
505 {
506 	uint8_t nss;
507 	uint8_t score_pct;
508 
509 	nss = ap_nss;
510 	if (sta_nss < nss)
511 		nss = sta_nss;
512 
513 	/* TODO: enhance for 8x8 */
514 	if (nss == 4)
515 		score_pct = CM_GET_SCORE_PERCENTAGE(
516 				score_config->nss_weight_per_index,
517 				CM_NSS_4x4_INDEX);
518 	else if (nss == 3)
519 		score_pct = CM_GET_SCORE_PERCENTAGE(
520 				score_config->nss_weight_per_index,
521 				CM_NSS_3x3_INDEX);
522 	else if (nss == 2)
523 		score_pct = CM_GET_SCORE_PERCENTAGE(
524 				score_config->nss_weight_per_index,
525 				CM_NSS_2x2_INDEX);
526 	else
527 		score_pct = CM_GET_SCORE_PERCENTAGE(
528 				score_config->nss_weight_per_index,
529 				CM_NSS_1x1_INDEX);
530 
531 	return (score_config->weight_config.nss_weightage * score_pct *
532 		prorated_pct) / CM_MAX_PCT_SCORE;
533 }
534 
535 #ifdef WLAN_POLICY_MGR_ENABLE
536 static uint32_t cm_get_sta_nss(struct wlan_objmgr_psoc *psoc,
537 			       qdf_freq_t bss_channel_freq,
538 			       uint8_t vdev_nss_2g, uint8_t vdev_nss_5g)
539 {
540 	/*
541 	 * If station support nss as 2*2 but AP support NSS as 1*1,
542 	 * this AP will be given half weight compare to AP which are having
543 	 * NSS as 2*2.
544 	 */
545 
546 	if (policy_mgr_is_chnl_in_diff_band(
547 	    psoc, bss_channel_freq) &&
548 	    policy_mgr_is_hw_dbs_capable(psoc) &&
549 	    !(policy_mgr_is_hw_dbs_2x2_capable(psoc)))
550 		return 1;
551 
552 	return (WLAN_REG_IS_24GHZ_CH_FREQ(bss_channel_freq) ?
553 		vdev_nss_2g :
554 		vdev_nss_5g);
555 }
556 #else
557 static uint32_t cm_get_sta_nss(struct wlan_objmgr_psoc *psoc,
558 			       qdf_freq_t bss_channel_freq,
559 			       uint8_t vdev_nss_2g, uint8_t vdev_nss_5g)
560 {
561 	return (WLAN_REG_IS_24GHZ_CH_FREQ(bss_channel_freq) ?
562 		vdev_nss_2g :
563 		vdev_nss_5g);
564 }
565 #endif
566 
567 #ifdef CONN_MGR_ADV_FEATURE
568 static bool
569 cm_get_pcl_weight_of_channel(uint32_t chan_freq,
570 			     struct pcl_freq_weight_list *pcl_lst,
571 			     int *pcl_chan_weight)
572 {
573 	int i;
574 	bool found = false;
575 
576 	if (!pcl_lst)
577 		return found;
578 
579 	for (i = 0; i < pcl_lst->num_of_pcl_channels; i++) {
580 		if (pcl_lst->pcl_freq_list[i] == chan_freq) {
581 			*pcl_chan_weight = pcl_lst->pcl_weight_list[i];
582 			found = true;
583 			break;
584 		}
585 	}
586 
587 	return found;
588 }
589 
590 /**
591  * cm_calculate_pcl_score() - Calculate PCL score based on PCL weightage
592  * @pcl_chan_weight: pcl weight of BSS channel
593  * @pcl_weightage: PCL _weightage out of total weightage
594  *
595  * Return: pcl score
596  */
597 static int32_t cm_calculate_pcl_score(int pcl_chan_weight,
598 				      uint8_t pcl_weightage)
599 {
600 	int32_t pcl_score = 0;
601 	int32_t temp_pcl_chan_weight = 0;
602 
603 	if (pcl_chan_weight) {
604 		temp_pcl_chan_weight =
605 			(CM_MAX_WEIGHT_OF_PCL_CHANNELS - pcl_chan_weight);
606 		temp_pcl_chan_weight = qdf_do_div(
607 					temp_pcl_chan_weight,
608 					CM_PCL_GROUPS_WEIGHT_DIFFERENCE);
609 		pcl_score = pcl_weightage - temp_pcl_chan_weight;
610 		if (pcl_score < 0)
611 			pcl_score = 0;
612 	}
613 
614 	return pcl_score * CM_MAX_PCT_SCORE;
615 }
616 
617 /**
618  * cm_calculate_oce_wan_score() - Calculate oce wan score
619  * @entry: bss information
620  * @score_params: bss score params
621  *
622  * Return: oce wan score
623  */
624 static int32_t cm_calculate_oce_wan_score(
625 	struct scan_cache_entry *entry,
626 	struct scoring_cfg *score_params)
627 {
628 	uint32_t window_size;
629 	uint8_t index;
630 	struct oce_reduced_wan_metrics wan_metrics;
631 	uint8_t *mbo_oce_ie;
632 
633 	if (!score_params->oce_wan_scoring.num_slot)
634 		return 0;
635 
636 	if (score_params->oce_wan_scoring.num_slot >
637 	    CM_SCORE_MAX_INDEX)
638 		score_params->oce_wan_scoring.num_slot =
639 			CM_SCORE_MAX_INDEX;
640 
641 	window_size = CM_SCORE_MAX_INDEX /
642 			score_params->oce_wan_scoring.num_slot;
643 	mbo_oce_ie = util_scan_entry_mbo_oce(entry);
644 	if (wlan_parse_oce_reduced_wan_metrics_ie(mbo_oce_ie, &wan_metrics)) {
645 		mlme_err("downlink_av_cap %d", wan_metrics.downlink_av_cap);
646 		/* if capacity is 0 return 0 score */
647 		if (!wan_metrics.downlink_av_cap)
648 			return 0;
649 		/* Desired values are from 1 to WLAN_SCORE_MAX_INDEX */
650 		index = qdf_do_div(wan_metrics.downlink_av_cap,
651 				   window_size);
652 	} else {
653 		index = CM_SCORE_INDEX_0;
654 	}
655 
656 	if (index > score_params->oce_wan_scoring.num_slot)
657 		index = score_params->oce_wan_scoring.num_slot;
658 
659 	return cm_get_score_for_index(index,
660 			score_params->weight_config.oce_wan_weightage,
661 			&score_params->oce_wan_scoring);
662 }
663 
664 /**
665  * cm_calculate_oce_subnet_id_weightage() - Calculate oce subnet id weightage
666  * @entry: bss entry
667  * @score_params: bss score params
668  * @oce_subnet_id_present: check if subnet id subelement is present in OCE IE
669  *
670  * Return: oce subnet id score
671  */
672 static uint32_t
673 cm_calculate_oce_subnet_id_weightage(struct scan_cache_entry *entry,
674 				     struct scoring_cfg *score_params,
675 				     bool *oce_subnet_id_present)
676 {
677 	uint32_t score = 0;
678 	uint8_t *mbo_oce_ie;
679 
680 	mbo_oce_ie = util_scan_entry_mbo_oce(entry);
681 	*oce_subnet_id_present = wlan_parse_oce_subnet_id_ie(mbo_oce_ie);
682 
683 	/* Consider 50% weightage if subnet id sub element is present */
684 	if (*oce_subnet_id_present)
685 		score  = score_params->weight_config.oce_subnet_id_weightage *
686 				(CM_MAX_PCT_SCORE / 2);
687 
688 	return score;
689 }
690 
691 /**
692  * cm_calculate_sae_pk_ap_weightage() - Calculate SAE-PK AP weightage
693  * @entry: bss entry
694  * @score_params: bss score params
695  * @sae_pk_cap_present: sae_pk cap presetn in RSNXE capability field
696  *
697  * Return: SAE-PK AP weightage score
698  */
699 static uint32_t
700 cm_calculate_sae_pk_ap_weightage(struct scan_cache_entry *entry,
701 				 struct scoring_cfg *score_params,
702 				 bool *sae_pk_cap_present)
703 {
704 	const uint8_t *rsnxe_ie;
705 	const uint8_t *rsnxe_cap;
706 	uint8_t cap_len;
707 
708 	rsnxe_ie = util_scan_entry_rsnxe(entry);
709 
710 	rsnxe_cap = wlan_crypto_parse_rsnxe_ie(rsnxe_ie, &cap_len);
711 
712 	if (!rsnxe_cap)
713 		return 0;
714 
715 	*sae_pk_cap_present = *rsnxe_cap & WLAN_CRYPTO_RSNX_CAP_SAE_PK;
716 	if (*sae_pk_cap_present)
717 		return score_params->weight_config.sae_pk_ap_weightage *
718 			CM_MAX_PCT_SCORE;
719 
720 	return 0;
721 }
722 
723 /**
724  * cm_calculate_oce_ap_tx_pwr_weightage() - Calculate oce ap tx pwr weightage
725  * @entry: bss entry
726  * @score_params: bss score params
727  * @ap_tx_pwr_dbm: pointer to hold ap tx power
728  *
729  * Return: oce ap tx power score
730  */
731 static uint32_t
732 cm_calculate_oce_ap_tx_pwr_weightage(struct scan_cache_entry *entry,
733 				     struct scoring_cfg *score_params,
734 				     int8_t *ap_tx_pwr_dbm)
735 {
736 	uint8_t *mbo_oce_ie, ap_tx_pwr_factor;
737 	struct rssi_config_score *rssi_score_param;
738 	int32_t best_rssi_threshold, good_rssi_threshold, bad_rssi_threshold;
739 	uint32_t good_rssi_pcnt, bad_rssi_pcnt, good_bucket_size;
740 	uint32_t score, normalized_ap_tx_pwr, bad_bucket_size;
741 	bool ap_tx_pwr_cap_present = true;
742 
743 	mbo_oce_ie = util_scan_entry_mbo_oce(entry);
744 	if (!wlan_parse_oce_ap_tx_pwr_ie(mbo_oce_ie, ap_tx_pwr_dbm)) {
745 		ap_tx_pwr_cap_present = false;
746 		/* If no OCE AP TX pwr, consider Uplink RSSI = Downlink RSSI */
747 		normalized_ap_tx_pwr = entry->rssi_raw;
748 	} else {
749 		/*
750 		 * Normalized ap_tx_pwr =
751 		 * Uplink RSSI = (STA TX Power - * (AP TX power - RSSI)) in dBm.
752 		 * Currently assuming STA Tx Power to be 20dBm, though later it
753 		 * need to fetched from hal-phy API.
754 		 */
755 		normalized_ap_tx_pwr =
756 			(20 - (*ap_tx_pwr_dbm - entry->rssi_raw));
757 	}
758 
759 	rssi_score_param = &score_params->rssi_score;
760 
761 	best_rssi_threshold = rssi_score_param->best_rssi_threshold * (-1);
762 	good_rssi_threshold = rssi_score_param->good_rssi_threshold * (-1);
763 	bad_rssi_threshold = rssi_score_param->bad_rssi_threshold * (-1);
764 	good_rssi_pcnt = rssi_score_param->good_rssi_pcnt;
765 	bad_rssi_pcnt = rssi_score_param->bad_rssi_pcnt;
766 	good_bucket_size = rssi_score_param->good_rssi_bucket_size;
767 	bad_bucket_size = rssi_score_param->bad_rssi_bucket_size;
768 
769 	/* Uplink RSSI is better than best rssi threshold */
770 	if (normalized_ap_tx_pwr > best_rssi_threshold) {
771 		ap_tx_pwr_factor = CM_MAX_PCT_SCORE;
772 	} else if (normalized_ap_tx_pwr <= bad_rssi_threshold) {
773 		/* Uplink RSSI is less or equal to bad rssi threshold */
774 		ap_tx_pwr_factor = rssi_score_param->bad_rssi_pcnt;
775 	} else if (normalized_ap_tx_pwr > good_rssi_threshold) {
776 		/* Uplink RSSI lies between best to good rssi threshold */
777 		ap_tx_pwr_factor =
778 			cm_get_rssi_pcnt_for_slot(
779 					best_rssi_threshold,
780 					good_rssi_threshold, 100,
781 					good_rssi_pcnt,
782 					good_bucket_size, normalized_ap_tx_pwr);
783 	} else {
784 		/* Uplink RSSI lies between good to best rssi threshold */
785 		ap_tx_pwr_factor =
786 			cm_get_rssi_pcnt_for_slot(
787 					good_rssi_threshold,
788 					bad_rssi_threshold, good_rssi_pcnt,
789 					bad_rssi_pcnt, bad_bucket_size,
790 					normalized_ap_tx_pwr);
791 	}
792 
793 	score  = score_params->weight_config.oce_ap_tx_pwr_weightage *
794 			ap_tx_pwr_factor;
795 
796 	return score;
797 }
798 
799 static bool cm_is_assoc_allowed(struct psoc_mlme_obj *mlme_psoc_obj,
800 				struct scan_cache_entry *entry)
801 {
802 	uint8_t reason;
803 	uint8_t *mbo_oce;
804 	bool check_assoc_disallowed;
805 
806 	mbo_oce = util_scan_entry_mbo_oce(entry);
807 
808 	check_assoc_disallowed =
809 	   mlme_psoc_obj->psoc_cfg.score_config.check_assoc_disallowed;
810 
811 	if (check_assoc_disallowed &&
812 	    wlan_parse_oce_assoc_disallowed_ie(mbo_oce, &reason)) {
813 		mlme_nofl_debug("Candidate("QDF_MAC_ADDR_FMT" freq %d): rssi %d, assoc disallowed set in MBO/OCE IE reason %d",
814 				QDF_MAC_ADDR_REF(entry->bssid.bytes),
815 				entry->channel.chan_freq,
816 				entry->rssi_raw, reason);
817 		return false;
818 	}
819 
820 	return true;
821 }
822 
823 void wlan_cm_set_check_assoc_disallowed(struct wlan_objmgr_psoc *psoc,
824 					bool value)
825 {
826 	struct psoc_mlme_obj *mlme_psoc_obj;
827 
828 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
829 	if (!mlme_psoc_obj)
830 		return;
831 
832 	mlme_psoc_obj->psoc_cfg.score_config.check_assoc_disallowed = value;
833 }
834 
835 void wlan_cm_get_check_assoc_disallowed(struct wlan_objmgr_psoc *psoc,
836 					bool *value)
837 {
838 	struct psoc_mlme_obj *mlme_psoc_obj;
839 
840 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
841 	if (!mlme_psoc_obj) {
842 		*value = false;
843 		return;
844 	}
845 
846 	*value = mlme_psoc_obj->psoc_cfg.score_config.check_assoc_disallowed;
847 }
848 
849 static enum phy_ch_width
850 cm_calculate_bandwidth(struct scan_cache_entry *entry,
851 		       struct psoc_phy_config *phy_config)
852 {
853 	uint8_t bw_above_20 = 0;
854 	bool is_vht = false;
855 	enum phy_ch_width ch_width;
856 
857 	if (WLAN_REG_IS_24GHZ_CH_FREQ(entry->channel.chan_freq)) {
858 		bw_above_20 = phy_config->bw_above_20_24ghz;
859 		if (phy_config->vht_24G_cap)
860 			is_vht = true;
861 	} else if (phy_config->vht_cap) {
862 		is_vht = true;
863 		bw_above_20 = phy_config->bw_above_20_5ghz;
864 	}
865 
866 	if (IS_WLAN_PHYMODE_160MHZ(entry->phy_mode))
867 		ch_width = CH_WIDTH_160MHZ;
868 	else if (IS_WLAN_PHYMODE_80MHZ(entry->phy_mode))
869 		ch_width = CH_WIDTH_80MHZ;
870 	else if (IS_WLAN_PHYMODE_40MHZ(entry->phy_mode))
871 		ch_width = CH_WIDTH_40MHZ;
872 	else
873 		ch_width = CH_WIDTH_20MHZ;
874 
875 	if (!phy_config->ht_cap &&
876 	    ch_width >= CH_WIDTH_20MHZ)
877 		ch_width = CH_WIDTH_20MHZ;
878 
879 	if (!is_vht && ch_width > CH_WIDTH_40MHZ)
880 		ch_width = CH_WIDTH_40MHZ;
881 
882 	if (!bw_above_20)
883 		ch_width = CH_WIDTH_20MHZ;
884 
885 	return ch_width;
886 }
887 
888 static uint8_t cm_etp_get_ba_win_size_from_esp(uint8_t esp_ba_win_size)
889 {
890 	/*
891 	 * BA Window Size subfield is three bits in length and indicates the
892 	 * size of the Block Ack window that is.
893 	 * 802.11-2016.pdf Table 9-262 BA Window Size subfield encoding
894 	 */
895 	switch (esp_ba_win_size) {
896 	case 1: return 2;
897 	case 2: return 4;
898 	case 3: return 6;
899 	case 4: return 8;
900 	case 5: return 16;
901 	case 6: return 32;
902 	case 7: return 64;
903 	default: return 1;
904 	}
905 }
906 
907 static uint16_t cm_get_etp_ntone(bool is_ht, bool is_vht,
908 				 enum phy_ch_width ch_width)
909 {
910 	uint16_t n_sd = 52, n_seg = 1;
911 
912 	if (is_vht) {
913 		/* Refer Table 21-5 in IEEE80211-2016 Spec */
914 		if (ch_width == CH_WIDTH_20MHZ)
915 			n_sd = 52;
916 		else if (ch_width == CH_WIDTH_40MHZ)
917 			n_sd = 108;
918 		else if (ch_width == CH_WIDTH_80MHZ)
919 			n_sd = 234;
920 		else if (ch_width == CH_WIDTH_80P80MHZ)
921 			n_sd = 234, n_seg = 2;
922 		else if (ch_width == CH_WIDTH_160MHZ)
923 			n_sd = 468;
924 	} else if (is_ht) {
925 		/* Refer Table 19-6 in IEEE80211-2016 Spec */
926 		if (ch_width == CH_WIDTH_20MHZ)
927 			n_sd = 52;
928 		if (ch_width == CH_WIDTH_40MHZ)
929 			n_sd = 108;
930 	} else {
931 		n_sd = 48;
932 	}
933 
934 	return (n_sd * n_seg);
935 }
936 
937 /* Refer Table 27-64 etc in Draft P802.11ax_D7.0.txt */
938 static uint16_t cm_get_etp_he_ntone(enum phy_ch_width ch_width)
939 {
940 	uint16_t n_sd = 234, n_seg = 1;
941 
942 	if (ch_width == CH_WIDTH_20MHZ)
943 		n_sd = 234;
944 	else if (ch_width == CH_WIDTH_40MHZ)
945 		n_sd = 468;
946 	else if (ch_width == CH_WIDTH_80MHZ)
947 		n_sd = 980;
948 	else if (ch_width == CH_WIDTH_80P80MHZ)
949 		n_sd = 980, n_seg = 2;
950 	else if (ch_width == CH_WIDTH_160MHZ)
951 		n_sd = 1960;
952 
953 	return (n_sd * n_seg);
954 }
955 
956 static uint16_t cm_get_etp_phy_header_dur_us(bool is_ht, bool is_vht,
957 					     uint8_t nss)
958 {
959 	uint16_t dur_us = 0;
960 
961 	if (is_vht) {
962 		/*
963 		 * Refer Figure 21-4 in 80211-2016 Spec
964 		 * 8 (L-STF) + 8 (L-LTF) + 4 (L-SIG) +
965 		 * 8 (VHT-SIG-A) + 4 (VHT-STF) + 4 (VHT-SIG-B)
966 		 */
967 		dur_us = 36;
968 		/* (nss * VHT-LTF) = (nss * 4) */
969 		dur_us += (nss << 2);
970 	} else if (is_ht) {
971 		/*
972 		 * Refer Figure 19-1 in 80211-2016 Spec
973 		 * 8 (L-STF) + 8 (L-LTF) + 4 (L-SIG) + 8 (HT-SIG) +
974 		 * 4 (HT-STF)
975 		 */
976 		dur_us = 32;
977 		/* (nss * HT-LTF = nss * 4) */
978 		dur_us += (nss << 2);
979 	} else {
980 		/*
981 		 * non-HT
982 		 * Refer Figure 19-1 in 80211-2016 Spec
983 		 * 8 (L-STF) + 8 (L-LTF) + 4 (L-SIG)
984 		 */
985 		dur_us = 20;
986 	}
987 	return dur_us;
988 }
989 
990 static uint32_t
991 cm_get_etp_max_bits_per_sc_1000x_for_nss(struct wlan_objmgr_psoc *psoc,
992 					 struct scan_cache_entry *entry,
993 					 uint8_t nss,
994 					 struct psoc_phy_config *phy_config)
995 {
996 	uint32_t max_bits_per_sc_1000x = 5000; /* 5 * 1000 */
997 	uint8_t mcs_map;
998 	struct wlan_ie_vhtcaps *bss_vht_cap;
999 	struct wlan_ie_hecaps *bss_he_cap;
1000 	uint32_t self_rx_mcs_map;
1001 	QDF_STATUS status;
1002 
1003 	bss_vht_cap = (struct wlan_ie_vhtcaps *)util_scan_entry_vhtcap(entry);
1004 	bss_he_cap = (struct wlan_ie_hecaps *)util_scan_entry_hecap(entry);
1005 	if (!phy_config->vht_cap || !bss_vht_cap) {
1006 		mlme_err("vht unsupported");
1007 		return max_bits_per_sc_1000x;
1008 	}
1009 
1010 	status = wlan_mlme_cfg_get_vht_rx_mcs_map(psoc, &self_rx_mcs_map);
1011 	if (QDF_IS_STATUS_ERROR(status))
1012 		return max_bits_per_sc_1000x;
1013 
1014 	if (nss == 4) {
1015 		mcs_map = (self_rx_mcs_map & 0xC0) >> 6;
1016 		mcs_map = QDF_MIN(mcs_map,
1017 				  (bss_vht_cap->rx_mcs_map & 0xC0) >> 6);
1018 	} else if (nss == 3) {
1019 		mcs_map = (self_rx_mcs_map & 0x30) >> 4;
1020 		mcs_map = QDF_MIN(mcs_map,
1021 				  (bss_vht_cap->rx_mcs_map & 0x30) >> 4);
1022 	} else if (nss == 2) {
1023 		mcs_map = (self_rx_mcs_map & 0x0C) >> 2;
1024 		mcs_map = QDF_MIN(mcs_map,
1025 				  (bss_vht_cap->rx_mcs_map & 0x0C) >> 2);
1026 	} else {
1027 		mcs_map = (self_rx_mcs_map & 0x03);
1028 		mcs_map = QDF_MIN(mcs_map, (bss_vht_cap->rx_mcs_map & 0x03));
1029 	}
1030 	if (bss_he_cap) {
1031 		if (mcs_map == 2)
1032 			max_bits_per_sc_1000x = 8333; /* 10 *5/6 * 1000 */
1033 		else if (mcs_map == 1)
1034 			max_bits_per_sc_1000x = 7500; /* 10 * 3/4 * 1000 */
1035 	} else {
1036 		if (mcs_map == 2)
1037 			max_bits_per_sc_1000x = 6667; /* 8 * 5/6 * 1000 */
1038 		else if (mcs_map == 1)
1039 			max_bits_per_sc_1000x = 6000; /* 8 * 3/4 * 1000 */
1040 	}
1041 	return max_bits_per_sc_1000x;
1042 }
1043 
1044 /* Refer Table 9-163 in 80211-2016 Spec */
1045 static uint32_t cm_etp_get_min_mpdu_ss_us_100x(struct htcap_cmn_ie *htcap)
1046 {
1047 	tSirMacHTParametersInfo *ampdu_param;
1048 	uint8_t ampdu_density;
1049 
1050 	ampdu_param = (tSirMacHTParametersInfo *)&htcap->ampdu_param;
1051 	ampdu_density = ampdu_param->mpduDensity;
1052 
1053 	if (ampdu_density == 1)
1054 		return 25; /* (1/4) * 100 */
1055 	else if (ampdu_density == 2)
1056 		return 50; /* (1/2) * 100 */
1057 	else if (ampdu_density == 3)
1058 		return 100; /* 1 * 100 */
1059 	else if (ampdu_density == 4)
1060 		return 200; /* 2 * 100 */
1061 	else if (ampdu_density == 5)
1062 		return 400; /* 4 * 100 */
1063 	else if (ampdu_density == 6)
1064 		return 800; /* 8 * 100 */
1065 	else if (ampdu_density == 7)
1066 		return 1600; /* 16 * 100 */
1067 	else
1068 		return 100;
1069 }
1070 
1071 /* Refer Table 9-162 in 80211-2016 Spec */
1072 static uint32_t cm_etp_get_max_amsdu_len(struct wlan_objmgr_psoc *psoc,
1073 					 struct htcap_cmn_ie *htcap)
1074 {
1075 	uint8_t bss_max_amsdu;
1076 	uint32_t bss_max_amsdu_len;
1077 	QDF_STATUS status;
1078 
1079 	status = wlan_mlme_get_max_amsdu_num(psoc, &bss_max_amsdu);
1080 	if (QDF_IS_STATUS_ERROR(status))
1081 		bss_max_amsdu_len = 3839;
1082 	else if (bss_max_amsdu == 1)
1083 		bss_max_amsdu_len =  7935;
1084 	else
1085 		bss_max_amsdu_len = 3839;
1086 
1087 	return bss_max_amsdu_len;
1088 }
1089 
1090    // Calculate the number of bits per tone based on the input of SNR in dB
1091     // The output is scaled up by BIT_PER_TONE_SCALE for integer representation
1092 static uint32_t
1093 calculate_bit_per_tone(int32_t rssi, enum phy_ch_width ch_width)
1094 {
1095 	int32_t noise_floor_db_boost;
1096 	int32_t noise_floor_dbm;
1097 	int32_t snr_db;
1098 	int32_t bit_per_tone;
1099 	int32_t lut_in_idx;
1100 
1101 	noise_floor_db_boost = TWO_IN_DB * ch_width;
1102 	noise_floor_dbm = WLAN_NOISE_FLOOR_DBM_DEFAULT + noise_floor_db_boost +
1103 			SNR_MARGIN_DB;
1104 	snr_db = rssi - noise_floor_dbm;
1105 	if (snr_db <= SNR_DB_TO_BIT_PER_TONE_LUT_MAX) {
1106 		lut_in_idx = QDF_MAX(snr_db, SNR_DB_TO_BIT_PER_TONE_LUT_MIN)
1107 			- SNR_DB_TO_BIT_PER_TONE_LUT_MIN;
1108 		lut_in_idx = QDF_MIN(lut_in_idx, DB_NUM - 1);
1109 		bit_per_tone = SNR_DB_TO_BIT_PER_TONE_LUT[lut_in_idx];
1110 	} else {
1111 		/*
1112 		 * SNR_tone = 10^(SNR/10)
1113 		 * log2(1+SNR_tone) ~= log2(SNR_tone) =
1114 		 * log10(SNR_tone)/log10(2) = log10(10^(SNR/10)) / 0.3
1115 		 * = (SNR/10) / 0.3 = SNR/3
1116 		 * So log2(1+SNR_tone) = SNR/3. 1000x for this is SNR*334
1117 		 */
1118 		bit_per_tone = snr_db * 334;
1119 	}
1120 
1121 	return bit_per_tone;
1122 }
1123 
1124 static uint32_t
1125 cm_calculate_etp(struct wlan_objmgr_psoc *psoc,
1126 		 struct scan_cache_entry *entry,
1127 		 struct etp_params  *etp_param,
1128 		 uint8_t max_nss, enum phy_ch_width ch_width,
1129 		 bool is_ht, bool is_vht, bool is_he,
1130 		 int8_t rssi,
1131 		 struct psoc_phy_config *phy_config)
1132 {
1133 	uint16_t ntone;
1134 	uint16_t phy_hdr_dur_us, max_amsdu_len = 1500, min_mpdu_ss_us_100x = 0;
1135 	uint32_t max_bits_per_sc_1000x, log_2_snr_tone_1000x;
1136 	uint32_t ppdu_payload_dur_us = 0, mpdu_per_ampdu, mpdu_per_ppdu;
1137 	uint32_t single_ppdu_dur_us, estimated_throughput_mbps, data_rate_kbps;
1138 	struct htcap_cmn_ie *htcap;
1139 
1140 	htcap = (struct htcap_cmn_ie *)util_scan_entry_htcap(entry);
1141 	if (ch_width > CH_WIDTH_160MHZ)
1142 		return CM_AVOID_CANDIDATE_MIN_SCORE;
1143 
1144 	if (is_he)
1145 		ntone = cm_get_etp_he_ntone(ch_width);
1146 	else
1147 		ntone = cm_get_etp_ntone(is_ht, is_vht, ch_width);
1148 	phy_hdr_dur_us = cm_get_etp_phy_header_dur_us(is_ht, is_vht, max_nss);
1149 
1150 	max_bits_per_sc_1000x =
1151 		cm_get_etp_max_bits_per_sc_1000x_for_nss(psoc, entry,
1152 							 max_nss, phy_config);
1153 	if (rssi < WLAN_NOISE_FLOOR_DBM_DEFAULT)
1154 		return CM_AVOID_CANDIDATE_MIN_SCORE;
1155 
1156 	log_2_snr_tone_1000x = calculate_bit_per_tone(rssi, ch_width);
1157 
1158 	/* Eq. R-2 Pg:3508 in 80211-2016 Spec */
1159 	if (is_he)
1160 		data_rate_kbps =
1161 			QDF_MIN(log_2_snr_tone_1000x, max_bits_per_sc_1000x) *
1162 			(max_nss * ntone) / HE_PPDU_PAYLOAD_SYMBOL_DUR_US;
1163 	else
1164 		data_rate_kbps =
1165 			QDF_MIN(log_2_snr_tone_1000x, max_bits_per_sc_1000x) *
1166 			(max_nss * ntone) / PPDU_PAYLOAD_SYMBOL_DUR_US;
1167 	mlme_debug("data_rate_kbps: %d", data_rate_kbps);
1168 	if (data_rate_kbps < 1000) {
1169 		/* Return ETP as 1 since datarate is not even 1 Mbps */
1170 		return CM_AVOID_CANDIDATE_MIN_SCORE;
1171 	}
1172 	/* compute MPDU_p_PPDU */
1173 	if (is_ht) {
1174 		min_mpdu_ss_us_100x =
1175 			cm_etp_get_min_mpdu_ss_us_100x(htcap);
1176 		max_amsdu_len =
1177 			cm_etp_get_max_amsdu_len(psoc, htcap);
1178 		ppdu_payload_dur_us =
1179 			etp_param->data_ppdu_dur_target_us - phy_hdr_dur_us;
1180 		mpdu_per_ampdu =
1181 			QDF_MIN(qdf_ceil(ppdu_payload_dur_us * 100,
1182 					 min_mpdu_ss_us_100x),
1183 				qdf_ceil(ppdu_payload_dur_us *
1184 					 (data_rate_kbps / 1000),
1185 					 (MAC_HEADER_LEN + max_amsdu_len) * 8));
1186 		mpdu_per_ppdu = QDF_MIN(etp_param->ba_window_size,
1187 					QDF_MAX(1, mpdu_per_ampdu));
1188 	} else {
1189 		mpdu_per_ppdu = 1;
1190 	}
1191 
1192 	/* compute PPDU_Dur */
1193 	single_ppdu_dur_us =
1194 		qdf_ceil((MAC_HEADER_LEN + max_amsdu_len) * mpdu_per_ppdu * 8,
1195 			 (data_rate_kbps / 1000) * PPDU_PAYLOAD_SYMBOL_DUR_US);
1196 	single_ppdu_dur_us *= PPDU_PAYLOAD_SYMBOL_DUR_US;
1197 	single_ppdu_dur_us += phy_hdr_dur_us;
1198 
1199 	estimated_throughput_mbps =
1200 		qdf_ceil(mpdu_per_ppdu * max_amsdu_len * 8, single_ppdu_dur_us);
1201 	estimated_throughput_mbps =
1202 		(estimated_throughput_mbps *
1203 		 etp_param->airtime_fraction) /
1204 		 CM_MAX_ESTIMATED_AIR_TIME_FRACTION;
1205 
1206 	if (estimated_throughput_mbps < CM_AVOID_CANDIDATE_MIN_SCORE)
1207 		estimated_throughput_mbps = CM_AVOID_CANDIDATE_MIN_SCORE;
1208 	if (estimated_throughput_mbps > CM_BEST_CANDIDATE_MAX_BSS_SCORE)
1209 		estimated_throughput_mbps = CM_BEST_CANDIDATE_MAX_BSS_SCORE;
1210 
1211 	mlme_nofl_debug("Candidate("QDF_MAC_ADDR_FMT" freq %d): rssi %d HT %d VHT %d HE %d ATF: %d NSS %d, ch_width: %d",
1212 			QDF_MAC_ADDR_REF(entry->bssid.bytes),
1213 			entry->channel.chan_freq,
1214 			entry->rssi_raw, is_ht, is_vht, is_he,
1215 			etp_param->airtime_fraction,
1216 			entry->nss, ch_width);
1217 	if (is_ht)
1218 		mlme_nofl_debug("min_mpdu_ss_us_100x = %d, max_amsdu_len = %d, ppdu_payload_dur_us = %d, mpdu_per_ampdu = %d, mpdu_per_ppdu = %d, ba_window_size = %d",
1219 				min_mpdu_ss_us_100x, max_amsdu_len,
1220 				ppdu_payload_dur_us, mpdu_per_ampdu,
1221 				mpdu_per_ppdu, etp_param->ba_window_size);
1222 	mlme_nofl_debug("ETP score params: ntone: %d, phy_hdr_dur_us: %d, max_bits_per_sc_1000x: %d, log_2_snr_tone_1000x: %d mpdu_p_ppdu = %d, max_amsdu_len = %d, ppdu_dur_us = %d, total score = %d",
1223 			ntone, phy_hdr_dur_us, max_bits_per_sc_1000x,
1224 			log_2_snr_tone_1000x, mpdu_per_ppdu, max_amsdu_len,
1225 			single_ppdu_dur_us, estimated_throughput_mbps);
1226 
1227 	return estimated_throughput_mbps;
1228 }
1229 
1230 static uint32_t
1231 cm_calculate_etp_score(struct wlan_objmgr_psoc *psoc,
1232 		       struct scan_cache_entry *entry,
1233 		       struct psoc_phy_config *phy_config)
1234 {
1235 	enum phy_ch_width ch_width;
1236 	uint32_t nss;
1237 	bool is_he_intersect = false;
1238 	bool is_vht_intersect = false;
1239 	bool is_ht_intersect = false;
1240 	struct wlan_esp_info *esp;
1241 	struct wlan_esp_ie *esp_ie;
1242 	struct etp_params etp_param;
1243 
1244 	if (phy_config->he_cap && entry->ie_list.hecap)
1245 		is_he_intersect = true;
1246 	if ((phy_config->vht_cap || phy_config->vht_24G_cap) &&
1247 	    (entry->ie_list.vhtcap ||
1248 	     WLAN_REG_IS_6GHZ_CHAN_FREQ(entry->channel.chan_freq)))
1249 		is_vht_intersect = true;
1250 	if (phy_config->ht_cap && entry->ie_list.htcap)
1251 		is_ht_intersect = true;
1252 	nss = cm_get_sta_nss(psoc, entry->channel.chan_freq,
1253 			     phy_config->vdev_nss_24g,
1254 			     phy_config->vdev_nss_5g);
1255 	nss = QDF_MIN(nss, entry->nss);
1256 	ch_width = cm_calculate_bandwidth(entry, phy_config);
1257 
1258 	/* Initialize default ETP params */
1259 	etp_param.airtime_fraction = 255 / 2;
1260 	etp_param.ba_window_size = 32;
1261 	etp_param.data_ppdu_dur_target_us = 5000; /* 5 msec */
1262 
1263 	if (entry->air_time_fraction) {
1264 		etp_param.airtime_fraction = entry->air_time_fraction;
1265 		esp_ie = (struct wlan_esp_ie *)
1266 			util_scan_entry_esp_info(entry);
1267 		if (esp_ie) {
1268 			esp = &esp_ie->esp_info_AC_BE;
1269 			etp_param.ba_window_size =
1270 				cm_etp_get_ba_win_size_from_esp(esp->ba_window_size);
1271 			etp_param.data_ppdu_dur_target_us =
1272 					50 * esp->ppdu_duration;
1273 			mlme_debug("esp ba_window_size: %d, ppdu_duration: %d",
1274 				   esp->ba_window_size, esp->ppdu_duration);
1275 		}
1276 	} else if (entry->qbss_chan_load) {
1277 		mlme_debug("qbss_chan_load: %d", entry->qbss_chan_load);
1278 		etp_param.airtime_fraction =
1279 			CM_MAX_ESTIMATED_AIR_TIME_FRACTION -
1280 			entry->qbss_chan_load;
1281 	}
1282 	/* If ini vendor_roam_score_algorithm=1, just calculate ETP of all
1283 	 * bssid of ssid selected by high layer, and try to connect AP by
1284 	 * order of ETP, legacy algorithm with following Parameters/Weightage
1285 	 * becomes useless. ETP should be [1Mbps, 20000Mbps],matches score
1286 	 * range: [1, 20000]
1287 	 */
1288 	return cm_calculate_etp(psoc, entry,
1289 				  &etp_param,
1290 				  nss,
1291 				  ch_width,
1292 				  is_ht_intersect,
1293 				  is_vht_intersect,
1294 				  is_he_intersect,
1295 				  entry->rssi_raw,
1296 				  phy_config);
1297 }
1298 
1299 #ifdef CONFIG_BAND_6GHZ
1300 static bool cm_check_h2e_support(const uint8_t *rsnxe, uint8_t sae_pwe)
1301 {
1302 	const uint8_t *rsnxe_cap;
1303 	uint8_t cap_len;
1304 
1305 	rsnxe_cap = wlan_crypto_parse_rsnxe_ie(rsnxe, &cap_len);
1306 	if (!rsnxe_cap) {
1307 		mlme_debug("RSNXE caps not present");
1308 		return false;
1309 	}
1310 
1311 	if (*rsnxe_cap & WLAN_CRYPTO_RSNX_CAP_SAE_H2E)
1312 		return true;
1313 
1314 	mlme_debug("RSNXE caps %x dont have H2E support", *rsnxe_cap);
1315 
1316 	return false;
1317 }
1318 #endif
1319 #else
1320 static bool
1321 cm_get_pcl_weight_of_channel(uint32_t chan_freq,
1322 			     struct pcl_freq_weight_list *pcl_lst,
1323 			     int *pcl_chan_weight)
1324 {
1325 	return false;
1326 }
1327 
1328 static int32_t cm_calculate_pcl_score(int pcl_chan_weight,
1329 				      uint8_t pcl_weightage)
1330 {
1331 	return 0;
1332 }
1333 
1334 static int32_t cm_calculate_oce_wan_score(struct scan_cache_entry *entry,
1335 					  struct scoring_cfg *score_params)
1336 {
1337 	return 0;
1338 }
1339 
1340 static uint32_t
1341 cm_calculate_oce_subnet_id_weightage(struct scan_cache_entry *entry,
1342 				     struct scoring_cfg *score_params,
1343 				     bool *oce_subnet_id_present)
1344 {
1345 	return 0;
1346 }
1347 
1348 static uint32_t
1349 cm_calculate_sae_pk_ap_weightage(struct scan_cache_entry *entry,
1350 				 struct scoring_cfg *score_params,
1351 				 bool *sae_pk_cap_present)
1352 {
1353 	return 0;
1354 }
1355 
1356 static uint32_t
1357 cm_calculate_oce_ap_tx_pwr_weightage(struct scan_cache_entry *entry,
1358 				     struct scoring_cfg *score_params,
1359 				     int8_t *ap_tx_pwr_dbm)
1360 {
1361 	return 0;
1362 }
1363 
1364 static inline bool cm_is_assoc_allowed(struct psoc_mlme_obj *mlme_psoc_obj,
1365 				       struct scan_cache_entry *entry)
1366 {
1367 	return true;
1368 }
1369 
1370 static uint32_t
1371 cm_calculate_etp_score(struct wlan_objmgr_psoc *psoc,
1372 		       struct scan_cache_entry *entry,
1373 		       struct psoc_phy_config *phy_config)
1374 {
1375 	return 0;
1376 }
1377 
1378 #ifdef CONFIG_BAND_6GHZ
1379 static bool cm_check_h2e_support(const uint8_t *rsnxe, uint8_t sae_pwe)
1380 {
1381 	/* limiting to H2E usage only */
1382 	if (sae_pwe == 1)
1383 		return true;
1384 
1385 	mlme_debug("sae_pwe %d is not H2E", sae_pwe);
1386 
1387 	return false;
1388 }
1389 #endif
1390 #endif
1391 
1392 /**
1393  * cm_get_band_score() - Get band prefernce weightage
1394  * freq: Operating frequency of the AP
1395  * @score_config: Score configuration
1396  *
1397  * Return: Band score for AP.
1398  */
1399 static int
1400 cm_get_band_score(uint32_t freq, struct scoring_cfg *score_config)
1401 {
1402 	uint8_t band_index;
1403 	struct weight_cfg *weight_config;
1404 
1405 	weight_config = &score_config->weight_config;
1406 
1407 	if (WLAN_REG_IS_5GHZ_CH_FREQ(freq))
1408 		band_index = CM_BAND_5G_INDEX;
1409 	else if (WLAN_REG_IS_24GHZ_CH_FREQ(freq))
1410 		band_index = CM_BAND_2G_INDEX;
1411 	else if (WLAN_REG_IS_6GHZ_CHAN_FREQ(freq))
1412 		band_index = CM_BAND_6G_INDEX;
1413 	else
1414 		return 0;
1415 
1416 	return weight_config->chan_band_weightage *
1417 	       CM_GET_SCORE_PERCENTAGE(score_config->band_weight_per_index,
1418 				       band_index);
1419 }
1420 
1421 static int cm_calculate_bss_score(struct wlan_objmgr_psoc *psoc,
1422 				  struct scan_cache_entry *entry,
1423 				  int pcl_chan_weight,
1424 				  struct qdf_mac_addr *bssid_hint)
1425 {
1426 	int32_t score = 0;
1427 	int32_t rssi_score = 0;
1428 	int32_t pcl_score = 0;
1429 	int32_t ht_score = 0;
1430 	int32_t vht_score = 0;
1431 	int32_t he_score = 0;
1432 	int32_t bandwidth_score = 0;
1433 	int32_t beamformee_score = 0;
1434 	int32_t band_score = 0;
1435 	int32_t nss_score = 0;
1436 	int32_t congestion_score = 0;
1437 	int32_t congestion_pct = 0;
1438 	int32_t oce_wan_score = 0;
1439 	uint8_t oce_ap_tx_pwr_score = 0;
1440 	uint8_t oce_subnet_id_score = 0;
1441 	uint32_t sae_pk_score = 0;
1442 	bool oce_subnet_id_present = 0;
1443 	bool sae_pk_cap_present = 0;
1444 	int8_t ap_tx_pwr_dbm = 0;
1445 	uint8_t prorated_pcnt;
1446 	bool is_vht = false;
1447 	int8_t good_rssi_threshold;
1448 	int8_t rssi_pref_5g_rssi_thresh;
1449 	bool same_bucket = false;
1450 	bool ap_su_beam_former = false;
1451 	struct wlan_ie_vhtcaps *vht_cap;
1452 	struct scoring_cfg *score_config;
1453 	struct weight_cfg *weight_config;
1454 	uint32_t sta_nss;
1455 	struct psoc_mlme_obj *mlme_psoc_obj;
1456 	struct psoc_phy_config *phy_config;
1457 
1458 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
1459 	if (!mlme_psoc_obj)
1460 		return 0;
1461 
1462 	phy_config = &mlme_psoc_obj->psoc_cfg.phy_config;
1463 	score_config = &mlme_psoc_obj->psoc_cfg.score_config;
1464 	weight_config = &score_config->weight_config;
1465 
1466 	if (score_config->is_bssid_hint_priority && bssid_hint &&
1467 	    qdf_is_macaddr_equal(bssid_hint, &entry->bssid)) {
1468 		entry->bss_score = CM_BEST_CANDIDATE_MAX_BSS_SCORE;
1469 		mlme_nofl_debug("Candidate("QDF_MAC_ADDR_FMT" freq %d): rssi %d BSSID hint given, give max score %d",
1470 				QDF_MAC_ADDR_REF(entry->bssid.bytes),
1471 				entry->channel.chan_freq,
1472 				entry->rssi_raw,
1473 				CM_BEST_CANDIDATE_MAX_BSS_SCORE);
1474 		return CM_BEST_CANDIDATE_MAX_BSS_SCORE;
1475 	}
1476 	if (score_config->vendor_roam_score_algorithm) {
1477 		score = cm_calculate_etp_score(psoc, entry, phy_config);
1478 		entry->bss_score = score;
1479 		return score;
1480 	}
1481 	rssi_score = cm_calculate_rssi_score(&score_config->rssi_score,
1482 					     entry->rssi_raw,
1483 					     weight_config->rssi_weightage);
1484 	score += rssi_score;
1485 
1486 	pcl_score = cm_calculate_pcl_score(pcl_chan_weight,
1487 					   weight_config->pcl_weightage);
1488 	score += pcl_score;
1489 
1490 	prorated_pcnt = cm_roam_calculate_prorated_pcnt_by_rssi(
1491 				&score_config->rssi_score, entry->rssi_raw,
1492 				weight_config->rssi_weightage);
1493 
1494 	/*
1495 	 * Add HT weight if HT is supported by the AP. In case
1496 	 * of 6 GHZ AP, HT and VHT won't be supported so that
1497 	 * these weightage to the same by default to match
1498 	 * with 2.4/5 GHZ APs where HT, VHT is supported
1499 	 */
1500 	if (phy_config->ht_cap && (entry->ie_list.htcap ||
1501 	    WLAN_REG_IS_6GHZ_CHAN_FREQ(entry->channel.chan_freq)))
1502 		ht_score = prorated_pcnt *
1503 				weight_config->ht_caps_weightage;
1504 	score += ht_score;
1505 
1506 	if (WLAN_REG_IS_24GHZ_CH_FREQ(entry->channel.chan_freq)) {
1507 		if (phy_config->vht_24G_cap)
1508 			is_vht = true;
1509 	} else if (phy_config->vht_cap) {
1510 		is_vht = true;
1511 	}
1512 
1513 	/* Add VHT score to 6 GHZ AP to match with 2.4/5 GHZ APs */
1514 	if (is_vht && (entry->ie_list.vhtcap ||
1515 	    WLAN_REG_IS_6GHZ_CHAN_FREQ(entry->channel.chan_freq)))
1516 		vht_score = prorated_pcnt *
1517 				 weight_config->vht_caps_weightage;
1518 	score += vht_score;
1519 
1520 	if (phy_config->he_cap && entry->ie_list.hecap)
1521 		he_score = prorated_pcnt *
1522 				 weight_config->he_caps_weightage;
1523 	score += he_score;
1524 
1525 	bandwidth_score = cm_calculate_bandwidth_score(entry, score_config,
1526 						       phy_config,
1527 						       prorated_pcnt);
1528 	score += bandwidth_score;
1529 
1530 	good_rssi_threshold =
1531 		score_config->rssi_score.good_rssi_threshold * (-1);
1532 	rssi_pref_5g_rssi_thresh =
1533 		score_config->rssi_score.rssi_pref_5g_rssi_thresh * (-1);
1534 	if (entry->rssi_raw < good_rssi_threshold)
1535 		same_bucket = cm_rssi_is_same_bucket(good_rssi_threshold,
1536 				entry->rssi_raw, rssi_pref_5g_rssi_thresh,
1537 				score_config->rssi_score.bad_rssi_bucket_size);
1538 
1539 	vht_cap = (struct wlan_ie_vhtcaps *)util_scan_entry_vhtcap(entry);
1540 	if (vht_cap && vht_cap->su_beam_former)
1541 		ap_su_beam_former = true;
1542 	if (phy_config->beamformee_cap && is_vht &&
1543 	    ap_su_beam_former &&
1544 	    (entry->rssi_raw > rssi_pref_5g_rssi_thresh) && !same_bucket)
1545 		beamformee_score = CM_MAX_PCT_SCORE *
1546 				weight_config->beamforming_cap_weightage;
1547 	score += beamformee_score;
1548 
1549 	congestion_score = cm_calculate_congestion_score(entry, score_config,
1550 							 &congestion_pct);
1551 	score += congestion_score;
1552 	/*
1553 	 * Consider OCE WAN score and band preference score only if
1554 	 * congestion_pct is greater than CONGESTION_THRSHOLD_FOR_BAND_OCE_SCORE
1555 	 */
1556 	if (congestion_pct < CM_CONGESTION_THRSHOLD_FOR_BAND_OCE_SCORE) {
1557 		/*
1558 		 * If AP is on 5/6 GHZ channel , extra weigtage is added to BSS
1559 		 * score. if RSSI is greater tha 5g rssi threshold or fall in
1560 		 * same bucket else give weigtage to 2.4 GHZ AP.
1561 		 */
1562 		if ((entry->rssi_raw > rssi_pref_5g_rssi_thresh) &&
1563 		    !same_bucket) {
1564 			if (!WLAN_REG_IS_24GHZ_CH_FREQ(entry->channel.chan_freq))
1565 				band_score = cm_get_band_score(
1566 						entry->channel.chan_freq,
1567 						score_config);
1568 		} else if (WLAN_REG_IS_24GHZ_CH_FREQ(
1569 			   entry->channel.chan_freq)) {
1570 			band_score = cm_get_band_score(entry->channel.chan_freq,
1571 						       score_config);
1572 		}
1573 		score += band_score;
1574 
1575 		oce_wan_score = cm_calculate_oce_wan_score(entry, score_config);
1576 		score += oce_wan_score;
1577 	}
1578 
1579 	oce_ap_tx_pwr_score =
1580 		cm_calculate_oce_ap_tx_pwr_weightage(entry, score_config,
1581 						     &ap_tx_pwr_dbm);
1582 	score += oce_ap_tx_pwr_score;
1583 
1584 	oce_subnet_id_score = cm_calculate_oce_subnet_id_weightage(entry,
1585 						score_config,
1586 						&oce_subnet_id_present);
1587 	score += oce_subnet_id_score;
1588 
1589 	sae_pk_score = cm_calculate_sae_pk_ap_weightage(entry, score_config,
1590 							&sae_pk_cap_present);
1591 	score += sae_pk_score;
1592 
1593 	sta_nss = cm_get_sta_nss(psoc, entry->channel.chan_freq,
1594 				 phy_config->vdev_nss_24g,
1595 				 phy_config->vdev_nss_5g);
1596 
1597 	/*
1598 	 * If station support nss as 2*2 but AP support NSS as 1*1,
1599 	 * this AP will be given half weight compare to AP which are having
1600 	 * NSS as 2*2.
1601 	 */
1602 	nss_score = cm_calculate_nss_score(psoc, score_config, entry->nss,
1603 					   prorated_pcnt, sta_nss);
1604 	score += nss_score;
1605 
1606 	mlme_nofl_debug("Candidate("QDF_MAC_ADDR_FMT" freq %d): rssi %d HT %d VHT %d HE %d su bfer %d phy %d  air time frac %d qbss %d cong_pct %d NSS %d ap_tx_pwr_dbm %d oce_subnet_id_present %d sae_pk_cap_present %d prorated_pcnt %d",
1607 			QDF_MAC_ADDR_REF(entry->bssid.bytes),
1608 			entry->channel.chan_freq,
1609 			entry->rssi_raw, util_scan_entry_htcap(entry) ? 1 : 0,
1610 			util_scan_entry_vhtcap(entry) ? 1 : 0,
1611 			util_scan_entry_hecap(entry) ? 1 : 0, ap_su_beam_former,
1612 			entry->phy_mode, entry->air_time_fraction,
1613 			entry->qbss_chan_load, congestion_pct, entry->nss,
1614 			ap_tx_pwr_dbm, oce_subnet_id_present,
1615 			sae_pk_cap_present, prorated_pcnt);
1616 
1617 	mlme_nofl_debug("Scores: rssi %d pcl %d ht %d vht %d he %d bfee %d bw %d band %d congestion %d nss %d oce wan %d oce ap tx pwr %d subnet %d sae_pk %d TOTAL %d",
1618 			rssi_score, pcl_score, ht_score,
1619 			vht_score, he_score, beamformee_score, bandwidth_score,
1620 			band_score, congestion_score, nss_score, oce_wan_score,
1621 			oce_ap_tx_pwr_score, oce_subnet_id_score,
1622 			sae_pk_score, score);
1623 
1624 	entry->bss_score = score;
1625 
1626 	return score;
1627 }
1628 
1629 static void cm_list_insert_sorted(qdf_list_t *scan_list,
1630 				  struct scan_cache_node *scan_entry)
1631 {
1632 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
1633 	struct scan_cache_node *curr_entry;
1634 
1635 	qdf_list_peek_front(scan_list, &cur_node);
1636 	while (cur_node) {
1637 		curr_entry = qdf_container_of(cur_node, struct scan_cache_node,
1638 					      node);
1639 		if (cm_is_better_bss(scan_entry->entry, curr_entry->entry)) {
1640 			qdf_list_insert_before(scan_list, &scan_entry->node,
1641 					       &curr_entry->node);
1642 			break;
1643 		}
1644 		qdf_list_peek_next(scan_list, cur_node, &next_node);
1645 		cur_node = next_node;
1646 		next_node = NULL;
1647 	}
1648 
1649 	if (!cur_node)
1650 		qdf_list_insert_back(scan_list, &scan_entry->node);
1651 }
1652 
1653 void wlan_cm_calculate_bss_score(struct wlan_objmgr_pdev *pdev,
1654 				 struct pcl_freq_weight_list *pcl_lst,
1655 				 qdf_list_t *scan_list,
1656 				 struct qdf_mac_addr *bssid_hint)
1657 {
1658 	struct scan_cache_node *scan_entry;
1659 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
1660 	struct psoc_mlme_obj *mlme_psoc_obj;
1661 	struct scoring_cfg *score_config;
1662 	int pcl_chan_weight;
1663 	QDF_STATUS status;
1664 	struct psoc_phy_config *config;
1665 	enum cm_blacklist_action blacklist_action;
1666 	struct wlan_objmgr_psoc *psoc;
1667 	bool assoc_allowed;
1668 	struct scan_cache_node *force_connect_candidate = NULL;
1669 	bool are_all_candidate_blacklisted = true;
1670 
1671 	psoc = wlan_pdev_get_psoc(pdev);
1672 
1673 	if (!psoc) {
1674 		mlme_err("psoc NULL");
1675 		return;
1676 	}
1677 	if (!scan_list) {
1678 		mlme_err("Scan list NULL");
1679 		return;
1680 	}
1681 
1682 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
1683 	if (!mlme_psoc_obj)
1684 		return;
1685 
1686 	score_config = &mlme_psoc_obj->psoc_cfg.score_config;
1687 	config = &mlme_psoc_obj->psoc_cfg.phy_config;
1688 
1689 	mlme_nofl_debug("Self caps: HT %d VHT %d HE %d VHT_24Ghz %d BF cap %d bw_above_20_24ghz %d bw_above_20_5ghz %d 2.4G NSS %d 5G NSS %d",
1690 			config->ht_cap, config->vht_cap,
1691 			config->he_cap, config->vht_24G_cap,
1692 			config->beamformee_cap, config->bw_above_20_24ghz,
1693 			config->bw_above_20_5ghz, config->vdev_nss_24g,
1694 			config->vdev_nss_5g);
1695 
1696 	/* calculate score for each AP */
1697 	if (qdf_list_peek_front(scan_list, &cur_node) != QDF_STATUS_SUCCESS) {
1698 		mlme_err("failed to peer front of scan list");
1699 		return;
1700 	}
1701 
1702 	while (cur_node) {
1703 		qdf_list_peek_next(scan_list, cur_node, &next_node);
1704 		pcl_chan_weight = 0;
1705 		scan_entry = qdf_container_of(cur_node, struct scan_cache_node,
1706 					      node);
1707 
1708 		assoc_allowed = cm_is_assoc_allowed(mlme_psoc_obj,
1709 						    scan_entry->entry);
1710 
1711 		if (assoc_allowed)
1712 			blacklist_action = wlan_blacklist_action_on_bssid(pdev,
1713 							scan_entry->entry);
1714 		else
1715 			blacklist_action = CM_BLM_FORCE_REMOVE;
1716 
1717 		if (blacklist_action == CM_BLM_NO_ACTION ||
1718 		    blacklist_action == CM_BLM_AVOID)
1719 			are_all_candidate_blacklisted = false;
1720 
1721 		if (blacklist_action == CM_BLM_NO_ACTION &&
1722 		    pcl_lst && pcl_lst->num_of_pcl_channels &&
1723 		    scan_entry->entry->rssi_raw > CM_PCL_RSSI_THRESHOLD &&
1724 		    score_config->weight_config.pcl_weightage) {
1725 			if (cm_get_pcl_weight_of_channel(
1726 					scan_entry->entry->channel.chan_freq,
1727 					pcl_lst, &pcl_chan_weight)) {
1728 				mlme_debug("pcl freq %d pcl_chan_weight %d",
1729 					   scan_entry->entry->channel.chan_freq,
1730 					   pcl_chan_weight);
1731 			}
1732 		}
1733 
1734 		if (blacklist_action == CM_BLM_NO_ACTION ||
1735 		    (are_all_candidate_blacklisted && blacklist_action == CM_BLM_REMOVE)) {
1736 			cm_calculate_bss_score(psoc, scan_entry->entry,
1737 					       pcl_chan_weight, bssid_hint);
1738 		} else if (blacklist_action == CM_BLM_AVOID) {
1739 			/* add min score so that it is added back in the end */
1740 			scan_entry->entry->bss_score =
1741 					CM_AVOID_CANDIDATE_MIN_SCORE;
1742 			mlme_nofl_debug("Candidate("QDF_MAC_ADDR_FMT" freq %d): rssi %d, is in Avoidlist, give min score %d",
1743 					QDF_MAC_ADDR_REF(scan_entry->entry->bssid.bytes),
1744 					scan_entry->entry->channel.chan_freq,
1745 					scan_entry->entry->rssi_raw,
1746 					scan_entry->entry->bss_score);
1747 		}
1748 
1749 		/*
1750 		 * The below logic is added to select the best candidate
1751 		 * amongst the blacklisted candidates. This is done to
1752 		 * handle a case where all the BSSIDs become blacklisted
1753 		 * and hence there are continuous connection failures.
1754 		 * With the below logic if the action on BSSID is to remove
1755 		 * then we keep a backup node and restore the candidate
1756 		 * list.
1757 		 */
1758 		if (blacklist_action == CM_BLM_REMOVE &&
1759 		    are_all_candidate_blacklisted) {
1760 			if (!force_connect_candidate) {
1761 				force_connect_candidate =
1762 					qdf_mem_malloc(
1763 					   sizeof(*force_connect_candidate));
1764 				if (!force_connect_candidate)
1765 					return;
1766 				force_connect_candidate->entry =
1767 					util_scan_copy_cache_entry(scan_entry->entry);
1768 				if (!force_connect_candidate->entry)
1769 					return;
1770 			} else if (cm_is_better_bss(
1771 				   scan_entry->entry,
1772 				   force_connect_candidate->entry)) {
1773 				util_scan_free_cache_entry(
1774 					force_connect_candidate->entry);
1775 				force_connect_candidate->entry =
1776 				  util_scan_copy_cache_entry(scan_entry->entry);
1777 				if (!force_connect_candidate->entry)
1778 					return;
1779 			}
1780 		}
1781 
1782 		/* Remove node from current location to add node back sorted */
1783 		status = qdf_list_remove_node(scan_list, cur_node);
1784 		if (QDF_IS_STATUS_ERROR(status)) {
1785 			mlme_err("failed to remove node for BSS "QDF_MAC_ADDR_FMT" from scan list",
1786 				 QDF_MAC_ADDR_REF(scan_entry->entry->bssid.bytes));
1787 			return;
1788 		}
1789 
1790 		/*
1791 		 * If CM_BLM_REMOVE ie blacklisted or assoc not allowed then
1792 		 * free the entry else add back to the list sorted
1793 		 */
1794 		if (blacklist_action == CM_BLM_REMOVE ||
1795 		    blacklist_action == CM_BLM_FORCE_REMOVE) {
1796 			if (assoc_allowed)
1797 				mlme_nofl_debug("Candidate("QDF_MAC_ADDR_FMT" freq %d): rssi %d, blm action %d is in Blacklist, remove entry",
1798 					QDF_MAC_ADDR_REF(scan_entry->entry->bssid.bytes),
1799 					scan_entry->entry->channel.chan_freq,
1800 					scan_entry->entry->rssi_raw,
1801 					blacklist_action);
1802 			util_scan_free_cache_entry(scan_entry->entry);
1803 			qdf_mem_free(scan_entry);
1804 		} else {
1805 			cm_list_insert_sorted(scan_list, scan_entry);
1806 		}
1807 
1808 		cur_node = next_node;
1809 		next_node = NULL;
1810 	}
1811 
1812 	if (are_all_candidate_blacklisted && force_connect_candidate) {
1813 		mlme_nofl_debug("All candidates in blacklist, Candidate("QDF_MAC_ADDR_FMT" freq %d): rssi %d, selected for connection",
1814 			QDF_MAC_ADDR_REF(force_connect_candidate->entry->bssid.bytes),
1815 			force_connect_candidate->entry->channel.chan_freq,
1816 			force_connect_candidate->entry->rssi_raw);
1817 		cm_list_insert_sorted(scan_list, force_connect_candidate);
1818 	} else if (force_connect_candidate) {
1819 		util_scan_free_cache_entry(force_connect_candidate->entry);
1820 		qdf_mem_free(force_connect_candidate);
1821 	}
1822 }
1823 
1824 #ifdef CONFIG_BAND_6GHZ
1825 bool wlan_cm_6ghz_allowed_for_akm(struct wlan_objmgr_psoc *psoc,
1826 				  uint32_t key_mgmt, uint16_t rsn_caps,
1827 				  const uint8_t *rsnxe, uint8_t sae_pwe)
1828 {
1829 	struct psoc_mlme_obj *mlme_psoc_obj;
1830 	struct scoring_cfg *config;
1831 
1832 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
1833 	if (!mlme_psoc_obj)
1834 		return false;
1835 
1836 	config = &mlme_psoc_obj->psoc_cfg.score_config;
1837 	/*
1838 	 * if check_6ghz_security is not set check if key_mgmt_mask_6ghz is set
1839 	 * if key_mgmt_mask_6ghz is set check if AKM matches the user configured
1840 	 * 6Ghz security
1841 	 */
1842 	if (!config->check_6ghz_security) {
1843 		if (!config->key_mgmt_mask_6ghz)
1844 			return true;
1845 		/* Check if AKM is allowed as per user 6Ghz allowed AKM mask */
1846 		if ((config->key_mgmt_mask_6ghz & key_mgmt) != key_mgmt) {
1847 			mlme_debug("user configured mask %x didnt match AKM %x",
1848 				   config->key_mgmt_mask_6ghz , key_mgmt);
1849 			return false;
1850 		}
1851 
1852 		return true;
1853 	}
1854 
1855 	/* Check if the AKM is allowed as per the 6Ghz allowed AKM mask */
1856 	if ((key_mgmt & ALLOWED_KEYMGMT_6G_MASK) != key_mgmt)
1857 		return false;
1858 
1859 	/* if check_6ghz_security is set validate all checks for 6Ghz */
1860 	if (!(rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED))
1861 		return false;
1862 
1863 	/* for SAE we need to check H2E support */
1864 	if (!(QDF_HAS_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_SAE) ||
1865 	    QDF_HAS_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_SAE)))
1866 		return true;
1867 
1868 	return cm_check_h2e_support(rsnxe, sae_pwe);
1869 }
1870 
1871 void wlan_cm_set_check_6ghz_security(struct wlan_objmgr_psoc *psoc,
1872 				     bool value)
1873 {
1874 	struct psoc_mlme_obj *mlme_psoc_obj;
1875 
1876 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
1877 	if (!mlme_psoc_obj)
1878 		return;
1879 
1880 	mlme_psoc_obj->psoc_cfg.score_config.check_6ghz_security = value;
1881 }
1882 
1883 void wlan_cm_reset_check_6ghz_security(struct wlan_objmgr_psoc *psoc)
1884 {
1885 	struct psoc_mlme_obj *mlme_psoc_obj;
1886 
1887 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
1888 	if (!mlme_psoc_obj)
1889 		return;
1890 
1891 	mlme_psoc_obj->psoc_cfg.score_config.check_6ghz_security =
1892 					cfg_get(psoc, CFG_CHECK_6GHZ_SECURITY);
1893 }
1894 
1895 bool wlan_cm_get_check_6ghz_security(struct wlan_objmgr_psoc *psoc)
1896 {
1897 	struct psoc_mlme_obj *mlme_psoc_obj;
1898 
1899 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
1900 	if (!mlme_psoc_obj)
1901 		return false;
1902 
1903 	return mlme_psoc_obj->psoc_cfg.score_config.check_6ghz_security;
1904 }
1905 
1906 void wlan_cm_set_6ghz_key_mgmt_mask(struct wlan_objmgr_psoc *psoc,
1907 				     uint32_t value)
1908 {
1909 	struct psoc_mlme_obj *mlme_psoc_obj;
1910 
1911 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
1912 	if (!mlme_psoc_obj)
1913 		return;
1914 
1915 	mlme_psoc_obj->psoc_cfg.score_config.key_mgmt_mask_6ghz = value;
1916 }
1917 
1918 uint32_t wlan_cm_get_6ghz_key_mgmt_mask(struct wlan_objmgr_psoc *psoc)
1919 {
1920 	struct psoc_mlme_obj *mlme_psoc_obj;
1921 
1922 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
1923 	if (!mlme_psoc_obj)
1924 		return DEFAULT_KEYMGMT_6G_MASK;
1925 
1926 	return mlme_psoc_obj->psoc_cfg.score_config.key_mgmt_mask_6ghz;
1927 }
1928 
1929 static void cm_fill_6ghz_params(struct wlan_objmgr_psoc *psoc,
1930 				struct scoring_cfg *score_cfg)
1931 {
1932 	/* Allow all security in 6Ghz by default */
1933 	score_cfg->check_6ghz_security = cfg_get(psoc, CFG_CHECK_6GHZ_SECURITY);
1934 	score_cfg->key_mgmt_mask_6ghz =
1935 				cfg_get(psoc, CFG_6GHZ_ALLOWED_AKM_MASK);
1936 }
1937 #else
1938 static inline void cm_fill_6ghz_params(struct wlan_objmgr_psoc *psoc,
1939 				       struct scoring_cfg *score_cfg)
1940 {
1941 }
1942 #endif
1943 
1944 static uint32_t
1945 cm_limit_max_per_index_score(uint32_t per_index_score)
1946 {
1947 	uint8_t i, score;
1948 
1949 	for (i = 0; i < CM_MAX_INDEX_PER_INI; i++) {
1950 		score = CM_GET_SCORE_PERCENTAGE(per_index_score, i);
1951 		if (score > CM_MAX_PCT_SCORE)
1952 			CM_SET_SCORE_PERCENTAGE(per_index_score,
1953 						CM_MAX_PCT_SCORE, i);
1954 	}
1955 
1956 	return per_index_score;
1957 }
1958 
1959 void wlan_cm_init_score_config(struct wlan_objmgr_psoc *psoc,
1960 			       struct scoring_cfg *score_cfg)
1961 {
1962 	uint32_t total_weight;
1963 
1964 	score_cfg->weight_config.rssi_weightage =
1965 		cfg_get(psoc, CFG_SCORING_RSSI_WEIGHTAGE);
1966 	score_cfg->weight_config.ht_caps_weightage =
1967 		cfg_get(psoc, CFG_SCORING_HT_CAPS_WEIGHTAGE);
1968 	score_cfg->weight_config.vht_caps_weightage =
1969 		cfg_get(psoc, CFG_SCORING_VHT_CAPS_WEIGHTAGE);
1970 	score_cfg->weight_config.he_caps_weightage =
1971 		cfg_get(psoc, CFG_SCORING_HE_CAPS_WEIGHTAGE);
1972 	score_cfg->weight_config.chan_width_weightage =
1973 		cfg_get(psoc, CFG_SCORING_CHAN_WIDTH_WEIGHTAGE);
1974 	score_cfg->weight_config.chan_band_weightage =
1975 		cfg_get(psoc, CFG_SCORING_CHAN_BAND_WEIGHTAGE);
1976 	score_cfg->weight_config.nss_weightage =
1977 		cfg_get(psoc, CFG_SCORING_NSS_WEIGHTAGE);
1978 	score_cfg->weight_config.beamforming_cap_weightage =
1979 		cfg_get(psoc, CFG_SCORING_BEAMFORM_CAP_WEIGHTAGE);
1980 	score_cfg->weight_config.pcl_weightage =
1981 		cfg_get(psoc, CFG_SCORING_PCL_WEIGHTAGE);
1982 	score_cfg->weight_config.channel_congestion_weightage =
1983 		cfg_get(psoc, CFG_SCORING_CHAN_CONGESTION_WEIGHTAGE);
1984 	score_cfg->weight_config.oce_wan_weightage =
1985 		cfg_get(psoc, CFG_SCORING_OCE_WAN_WEIGHTAGE);
1986 	score_cfg->weight_config.oce_ap_tx_pwr_weightage =
1987 				cfg_get(psoc, CFG_OCE_AP_TX_PWR_WEIGHTAGE);
1988 	score_cfg->weight_config.oce_subnet_id_weightage =
1989 				cfg_get(psoc, CFG_OCE_SUBNET_ID_WEIGHTAGE);
1990 	score_cfg->weight_config.sae_pk_ap_weightage =
1991 				cfg_get(psoc, CFG_SAE_PK_AP_WEIGHTAGE);
1992 
1993 	total_weight =  score_cfg->weight_config.rssi_weightage +
1994 			score_cfg->weight_config.ht_caps_weightage +
1995 			score_cfg->weight_config.vht_caps_weightage +
1996 			score_cfg->weight_config.he_caps_weightage +
1997 			score_cfg->weight_config.chan_width_weightage +
1998 			score_cfg->weight_config.chan_band_weightage +
1999 			score_cfg->weight_config.nss_weightage +
2000 			score_cfg->weight_config.beamforming_cap_weightage +
2001 			score_cfg->weight_config.pcl_weightage +
2002 			score_cfg->weight_config.channel_congestion_weightage +
2003 			score_cfg->weight_config.oce_wan_weightage +
2004 			score_cfg->weight_config.oce_ap_tx_pwr_weightage +
2005 			score_cfg->weight_config.oce_subnet_id_weightage +
2006 			score_cfg->weight_config.sae_pk_ap_weightage;
2007 
2008 	/*
2009 	 * If configured weights are greater than max weight,
2010 	 * fallback to default weights
2011 	 */
2012 	if (total_weight > CM_BEST_CANDIDATE_MAX_WEIGHT) {
2013 		mlme_err("Total weight greater than %d, using default weights",
2014 			 CM_BEST_CANDIDATE_MAX_WEIGHT);
2015 		score_cfg->weight_config.rssi_weightage = CM_RSSI_WEIGHTAGE;
2016 		score_cfg->weight_config.ht_caps_weightage =
2017 						CM_HT_CAPABILITY_WEIGHTAGE;
2018 		score_cfg->weight_config.vht_caps_weightage =
2019 						CM_VHT_CAP_WEIGHTAGE;
2020 		score_cfg->weight_config.he_caps_weightage =
2021 						CM_HE_CAP_WEIGHTAGE;
2022 		score_cfg->weight_config.chan_width_weightage =
2023 						CM_CHAN_WIDTH_WEIGHTAGE;
2024 		score_cfg->weight_config.chan_band_weightage =
2025 						CM_CHAN_BAND_WEIGHTAGE;
2026 		score_cfg->weight_config.nss_weightage = CM_NSS_WEIGHTAGE;
2027 		score_cfg->weight_config.beamforming_cap_weightage =
2028 						CM_BEAMFORMING_CAP_WEIGHTAGE;
2029 		score_cfg->weight_config.pcl_weightage = CM_PCL_WEIGHT;
2030 		score_cfg->weight_config.channel_congestion_weightage =
2031 						CM_CHANNEL_CONGESTION_WEIGHTAGE;
2032 		score_cfg->weight_config.oce_wan_weightage =
2033 						CM_OCE_WAN_WEIGHTAGE;
2034 		score_cfg->weight_config.oce_ap_tx_pwr_weightage =
2035 						CM_OCE_AP_TX_POWER_WEIGHTAGE;
2036 		score_cfg->weight_config.oce_subnet_id_weightage =
2037 						CM_OCE_SUBNET_ID_WEIGHTAGE;
2038 		score_cfg->weight_config.sae_pk_ap_weightage =
2039 						CM_SAE_PK_AP_WEIGHTAGE;
2040 	}
2041 
2042 	score_cfg->rssi_score.best_rssi_threshold =
2043 		cfg_get(psoc, CFG_SCORING_BEST_RSSI_THRESHOLD);
2044 	score_cfg->rssi_score.good_rssi_threshold =
2045 		cfg_get(psoc, CFG_SCORING_GOOD_RSSI_THRESHOLD);
2046 	score_cfg->rssi_score.bad_rssi_threshold =
2047 		cfg_get(psoc, CFG_SCORING_BAD_RSSI_THRESHOLD);
2048 
2049 	score_cfg->rssi_score.good_rssi_pcnt =
2050 		cfg_get(psoc, CFG_SCORING_GOOD_RSSI_PERCENT);
2051 	score_cfg->rssi_score.bad_rssi_pcnt =
2052 		cfg_get(psoc, CFG_SCORING_BAD_RSSI_PERCENT);
2053 
2054 	score_cfg->rssi_score.good_rssi_bucket_size =
2055 		cfg_get(psoc, CFG_SCORING_GOOD_RSSI_BUCKET_SIZE);
2056 	score_cfg->rssi_score.bad_rssi_bucket_size =
2057 		cfg_get(psoc, CFG_SCORING_BAD_RSSI_BUCKET_SIZE);
2058 
2059 	score_cfg->rssi_score.rssi_pref_5g_rssi_thresh =
2060 		cfg_get(psoc, CFG_SCORING_RSSI_PREF_5G_THRESHOLD);
2061 
2062 	score_cfg->esp_qbss_scoring.num_slot =
2063 		cfg_get(psoc, CFG_SCORING_NUM_ESP_QBSS_SLOTS);
2064 	score_cfg->esp_qbss_scoring.score_pcnt3_to_0 =
2065 		cm_limit_max_per_index_score(
2066 			cfg_get(psoc, CFG_SCORING_ESP_QBSS_SCORE_IDX_3_TO_0));
2067 	score_cfg->esp_qbss_scoring.score_pcnt7_to_4 =
2068 		cm_limit_max_per_index_score(
2069 			cfg_get(psoc, CFG_SCORING_ESP_QBSS_SCORE_IDX_7_TO_4));
2070 	score_cfg->esp_qbss_scoring.score_pcnt11_to_8 =
2071 		cm_limit_max_per_index_score(
2072 			cfg_get(psoc, CFG_SCORING_ESP_QBSS_SCORE_IDX_11_TO_8));
2073 	score_cfg->esp_qbss_scoring.score_pcnt15_to_12 =
2074 		cm_limit_max_per_index_score(
2075 			cfg_get(psoc, CFG_SCORING_ESP_QBSS_SCORE_IDX_15_TO_12));
2076 
2077 	score_cfg->oce_wan_scoring.num_slot =
2078 		cfg_get(psoc, CFG_SCORING_NUM_OCE_WAN_SLOTS);
2079 	score_cfg->oce_wan_scoring.score_pcnt3_to_0 =
2080 		cm_limit_max_per_index_score(
2081 			cfg_get(psoc, CFG_SCORING_OCE_WAN_SCORE_IDX_3_TO_0));
2082 	score_cfg->oce_wan_scoring.score_pcnt7_to_4 =
2083 		cm_limit_max_per_index_score(
2084 			cfg_get(psoc, CFG_SCORING_OCE_WAN_SCORE_IDX_7_TO_4));
2085 	score_cfg->oce_wan_scoring.score_pcnt11_to_8 =
2086 		cm_limit_max_per_index_score(
2087 			cfg_get(psoc, CFG_SCORING_OCE_WAN_SCORE_IDX_11_TO_8));
2088 	score_cfg->oce_wan_scoring.score_pcnt15_to_12 =
2089 		cm_limit_max_per_index_score(
2090 			cfg_get(psoc, CFG_SCORING_OCE_WAN_SCORE_IDX_15_TO_12));
2091 
2092 	score_cfg->bandwidth_weight_per_index =
2093 		cm_limit_max_per_index_score(
2094 			cfg_get(psoc, CFG_SCORING_BW_WEIGHT_PER_IDX));
2095 	score_cfg->nss_weight_per_index =
2096 		cm_limit_max_per_index_score(
2097 			cfg_get(psoc, CFG_SCORING_NSS_WEIGHT_PER_IDX));
2098 	score_cfg->band_weight_per_index =
2099 		cm_limit_max_per_index_score(
2100 			cfg_get(psoc, CFG_SCORING_BAND_WEIGHT_PER_IDX));
2101 	score_cfg->is_bssid_hint_priority =
2102 			cfg_get(psoc, CFG_IS_BSSID_HINT_PRIORITY);
2103 	score_cfg->vendor_roam_score_algorithm =
2104 			cfg_get(psoc, CFG_VENDOR_ROAM_SCORE_ALGORITHM);
2105 	score_cfg->check_assoc_disallowed = true;
2106 	cm_fill_6ghz_params(psoc, score_cfg);
2107 }
2108