xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlme/connection_mgr/core/src/wlan_cm_bss_scoring.c (revision 6d768494e5ce14eb1603a695c86739d12ecc6ec2)
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 
30 #define CM_20MHZ_BW_INDEX                  0
31 #define CM_40MHZ_BW_INDEX                  1
32 #define CM_80MHZ_BW_INDEX                  2
33 #define CM_160MHZ_BW_INDEX                 3
34 #define CM_MAX_BW_INDEX                    4
35 
36 #define CM_PCL_RSSI_THRESHOLD -75
37 
38 #define CM_NSS_1x1_INDEX                   0
39 #define CM_NSS_2x2_INDEX                   1
40 #define CM_NSS_3x3_INDEX                   2
41 #define CM_NSS_4x4_INDEX                   3
42 #define CM_MAX_NSS_INDEX                   4
43 
44 #define CM_BAND_2G_INDEX                   0
45 #define CM_BAND_5G_INDEX                   1
46 #define CM_BAND_6G_INDEX                   2
47 /* 3 is reserved */
48 #define CM_MAX_BAND_INDEX                  4
49 
50 #define CM_SCORE_INDEX_0                   0
51 #define CM_SCORE_INDEX_3                   3
52 #define CM_SCORE_INDEX_7                   7
53 #define CM_SCORE_OFFSET_INDEX_7_4          4
54 #define CM_SCORE_INDEX_11                  11
55 #define CM_SCORE_OFFSET_INDEX_11_8         8
56 #define CM_SCORE_MAX_INDEX                 15
57 #define CM_SCORE_OFFSET_INDEX_15_12        12
58 
59 #define CM_MAX_OCE_WAN_DL_CAP 16
60 
61 #define CM_MAX_CHANNEL_WEIGHT 100
62 #define CM_MAX_CHANNEL_UTILIZATION 100
63 #define CM_MAX_ESTIMATED_AIR_TIME_FRACTION 255
64 #define CM_MAX_AP_LOAD 255
65 
66 #define CM_MAX_WEIGHT_OF_PCL_CHANNELS 255
67 #define CM_PCL_GROUPS_WEIGHT_DIFFERENCE 20
68 
69 /* Congestion threshold (channel load %) to consider band and OCE WAN score */
70 #define CM_CONGESTION_THRSHOLD_FOR_BAND_OCE_SCORE 75
71 
72 #define CM_RSSI_WEIGHTAGE 20
73 #define CM_HT_CAPABILITY_WEIGHTAGE 2
74 #define CM_VHT_CAP_WEIGHTAGE 1
75 #define CM_HE_CAP_WEIGHTAGE 2
76 #define CM_CHAN_WIDTH_WEIGHTAGE 12
77 #define CM_CHAN_BAND_WEIGHTAGE 2
78 #define CM_NSS_WEIGHTAGE 16
79 #define CM_BEAMFORMING_CAP_WEIGHTAGE 2
80 #define CM_PCL_WEIGHT 10
81 #define CM_CHANNEL_CONGESTION_WEIGHTAGE 5
82 #define CM_OCE_WAN_WEIGHTAGE 2
83 #define CM_OCE_AP_TX_POWER_WEIGHTAGE 5
84 #define CM_OCE_SUBNET_ID_WEIGHTAGE 3
85 #define CM_BEST_CANDIDATE_MAX_WEIGHT 200
86 #define CM_MAX_PCT_SCORE 100
87 #define CM_MAX_INDEX_PER_INI 4
88 
89 #define CM_BEST_CANDIDATE_MAX_BSS_SCORE (CM_BEST_CANDIDATE_MAX_WEIGHT * 100)
90 
91 #define CM_GET_SCORE_PERCENTAGE(value32, bw_index) \
92 	QDF_GET_BITS(value32, (8 * (bw_index)), 8)
93 #define CM_SET_SCORE_PERCENTAGE(value32, score_pcnt, bw_index) \
94 	QDF_SET_BITS(value32, (8 * (bw_index)), 8, score_pcnt)
95 
96 static bool cm_is_better_bss(struct scan_cache_entry *bss1,
97 			     struct scan_cache_entry *bss2)
98 {
99 	if (bss1->bss_score > bss2->bss_score)
100 		return true;
101 	else if (bss1->bss_score == bss2->bss_score)
102 		if (bss1->rssi_raw > bss2->rssi_raw)
103 			return true;
104 
105 	return false;
106 }
107 
108 /**
109  * cm_get_rssi_pcnt_for_slot() - calculate rssi % score based on the slot
110  * index between the high rssi and low rssi threshold
111  * @high_rssi_threshold: High rssi of the window
112  * @low_rssi_threshold: low rssi of the window
113  * @high_rssi_pcnt: % score for the high rssi
114  * @low_rssi_pcnt: %score for the low rssi
115  * @bucket_size: bucket size of the window
116  * @bss_rssi: Input rssi for which value need to be calculated
117  *
118  * Return : rssi pct to use for the given rssi
119  */
120 static inline
121 int8_t cm_get_rssi_pcnt_for_slot(int32_t high_rssi_threshold,
122 				 int32_t low_rssi_threshold,
123 				 uint32_t high_rssi_pcnt,
124 				 uint32_t low_rssi_pcnt,
125 				 uint32_t bucket_size, int8_t bss_rssi)
126 {
127 	int8_t slot_index, slot_size, rssi_diff, num_slot, rssi_pcnt;
128 
129 	num_slot = ((high_rssi_threshold -
130 		     low_rssi_threshold) / bucket_size) + 1;
131 	slot_size = ((high_rssi_pcnt - low_rssi_pcnt) +
132 		     (num_slot / 2)) / (num_slot);
133 	rssi_diff = high_rssi_threshold - bss_rssi;
134 	slot_index = (rssi_diff / bucket_size) + 1;
135 	rssi_pcnt = high_rssi_pcnt - (slot_size * slot_index);
136 	if (rssi_pcnt < low_rssi_pcnt)
137 		rssi_pcnt = low_rssi_pcnt;
138 
139 	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",
140 		   high_rssi_threshold, low_rssi_threshold, high_rssi_pcnt,
141 		   low_rssi_pcnt, bucket_size, bss_rssi, num_slot, slot_size,
142 		   rssi_diff, slot_index, rssi_pcnt);
143 
144 	return rssi_pcnt;
145 }
146 
147 /**
148  * cm_calculate_rssi_score() - Calculate RSSI score based on AP RSSI
149  * @score_param: rssi score params
150  * @rssi: rssi of the AP
151  * @rssi_weightage: rssi_weightage out of total weightage
152  *
153  * Return : rssi score
154  */
155 static int32_t cm_calculate_rssi_score(struct rssi_config_score *score_param,
156 				       int32_t rssi, uint8_t rssi_weightage)
157 {
158 	int8_t rssi_pcnt;
159 	int32_t total_rssi_score;
160 	int32_t best_rssi_threshold;
161 	int32_t good_rssi_threshold;
162 	int32_t bad_rssi_threshold;
163 	uint32_t good_rssi_pcnt;
164 	uint32_t bad_rssi_pcnt;
165 	uint32_t good_bucket_size;
166 	uint32_t bad_bucket_size;
167 
168 	best_rssi_threshold = score_param->best_rssi_threshold * (-1);
169 	good_rssi_threshold = score_param->good_rssi_threshold * (-1);
170 	bad_rssi_threshold = score_param->bad_rssi_threshold * (-1);
171 	good_rssi_pcnt = score_param->good_rssi_pcnt;
172 	bad_rssi_pcnt = score_param->bad_rssi_pcnt;
173 	good_bucket_size = score_param->good_rssi_bucket_size;
174 	bad_bucket_size = score_param->bad_rssi_bucket_size;
175 
176 	total_rssi_score = (CM_MAX_PCT_SCORE * rssi_weightage);
177 
178 	/*
179 	 * If RSSI is better than the best rssi threshold then it return full
180 	 * score.
181 	 */
182 	if (rssi > best_rssi_threshold)
183 		return total_rssi_score;
184 	/*
185 	 * If RSSI is less or equal to bad rssi threshold then it return
186 	 * least score.
187 	 */
188 	if (rssi <= bad_rssi_threshold)
189 		return (total_rssi_score * bad_rssi_pcnt) / 100;
190 
191 	/* RSSI lies between best to good rssi threshold */
192 	if (rssi > good_rssi_threshold)
193 		rssi_pcnt = cm_get_rssi_pcnt_for_slot(best_rssi_threshold,
194 				good_rssi_threshold, 100, good_rssi_pcnt,
195 				good_bucket_size, rssi);
196 	else
197 		rssi_pcnt = cm_get_rssi_pcnt_for_slot(good_rssi_threshold,
198 				bad_rssi_threshold, good_rssi_pcnt,
199 				bad_rssi_pcnt, bad_bucket_size,
200 				rssi);
201 
202 	return (total_rssi_score * rssi_pcnt) / 100;
203 }
204 
205 /**
206  * cm_calculate_pcl_score() - Calculate PCL score based on PCL weightage
207  * @pcl_chan_weight: pcl weight of BSS channel
208  * @pcl_weightage: PCL _weightage out of total weightage
209  *
210  * Return : pcl score
211  */
212 static int32_t cm_calculate_pcl_score(int pcl_chan_weight,
213 				      uint8_t pcl_weightage)
214 {
215 	int32_t pcl_score = 0;
216 	int32_t temp_pcl_chan_weight = 0;
217 
218 	if (pcl_chan_weight) {
219 		temp_pcl_chan_weight =
220 			(CM_MAX_WEIGHT_OF_PCL_CHANNELS - pcl_chan_weight);
221 		temp_pcl_chan_weight = qdf_do_div(temp_pcl_chan_weight,
222 					  CM_PCL_GROUPS_WEIGHT_DIFFERENCE);
223 		pcl_score = pcl_weightage - temp_pcl_chan_weight;
224 		if (pcl_score < 0)
225 			pcl_score = 0;
226 	}
227 
228 	return pcl_score * CM_MAX_PCT_SCORE;
229 }
230 
231 /**
232  * cm_rssi_is_same_bucket() - check if both rssi fall in same bucket
233  * @rssi_top_thresh: high rssi threshold of the the window
234  * @low_rssi_threshold: low rssi of the window
235  * @rssi_ref1: rssi ref one
236  * @rssi_ref2: rssi ref two
237  * @bucket_size: bucket size of the window
238  *
239  * Return : true if both fall in same window
240  */
241 static inline bool cm_rssi_is_same_bucket(int8_t rssi_top_thresh,
242 					  int8_t rssi_ref1, int8_t rssi_ref2,
243 					  int8_t bucket_size)
244 {
245 	int8_t rssi_diff1 = 0;
246 	int8_t rssi_diff2 = 0;
247 
248 	rssi_diff1 = rssi_top_thresh - rssi_ref1;
249 	rssi_diff2 = rssi_top_thresh - rssi_ref2;
250 
251 	return (rssi_diff1 / bucket_size) == (rssi_diff2 / bucket_size);
252 }
253 
254 /**
255  * cm_roam_calculate_prorated_pcnt_by_rssi() - Calculate prorated RSSI score
256  * based on AP RSSI. This will be used to determine HT VHT score
257  * @score_param: rssi score params
258  * @rssi: bss rssi
259  * @rssi_weightage: rssi_weightage out of total weightage
260  *
261  * If rssi is greater than good threshold return 100, if less than bad return 0,
262  * if between good and bad, return prorated rssi score for the index.
263  *
264  * Return : rssi prorated score
265  */
266 static int8_t cm_roam_calculate_prorated_pcnt_by_rssi(
267 	struct rssi_config_score *score_param,
268 	int32_t rssi, uint8_t rssi_weightage)
269 {
270 	int32_t good_rssi_threshold;
271 	int32_t bad_rssi_threshold;
272 	int8_t rssi_pref_5g_rssi_thresh;
273 	bool same_bucket;
274 
275 	good_rssi_threshold = score_param->good_rssi_threshold * (-1);
276 	bad_rssi_threshold = score_param->bad_rssi_threshold * (-1);
277 	rssi_pref_5g_rssi_thresh = score_param->rssi_pref_5g_rssi_thresh * (-1);
278 
279 	/* If RSSI is greater than good rssi return full weight */
280 	if (rssi > good_rssi_threshold)
281 		return CM_MAX_PCT_SCORE;
282 
283 	same_bucket = cm_rssi_is_same_bucket(good_rssi_threshold, rssi,
284 					     rssi_pref_5g_rssi_thresh,
285 					     score_param->bad_rssi_bucket_size);
286 	if (same_bucket || (rssi < rssi_pref_5g_rssi_thresh))
287 		return 0;
288 	/* If RSSI is less or equal to bad rssi threshold then it return 0 */
289 	if (rssi <= bad_rssi_threshold)
290 		return 0;
291 
292 	/* If RSSI is between good and bad threshold */
293 	return cm_get_rssi_pcnt_for_slot(good_rssi_threshold,
294 					 bad_rssi_threshold,
295 					 score_param->good_rssi_pcnt,
296 					 score_param->bad_rssi_pcnt,
297 					 score_param->bad_rssi_bucket_size,
298 					 rssi);
299 }
300 
301 /**
302  * cm_calculate_bandwidth_score() - Calculate BW score
303  * @entry: scan entry
304  * @score_config: scoring config
305  * @phy_config: psoc phy configs
306  * @prorated_pct: prorated % to return dependent on RSSI
307  *
308  * Return : bw score
309  */
310 static int32_t cm_calculate_bandwidth_score(struct scan_cache_entry *entry,
311 					    struct scoring_cfg *score_config,
312 					    struct psoc_phy_config *phy_config,
313 					    uint8_t prorated_pct)
314 {
315 	uint32_t score;
316 	int32_t bw_weight_per_idx;
317 	uint8_t bw_above_20 = 0;
318 	uint8_t ch_width_index;
319 	bool is_vht = false;
320 
321 	bw_weight_per_idx = score_config->bandwidth_weight_per_index;
322 
323 	if (WLAN_REG_IS_24GHZ_CH_FREQ(entry->channel.chan_freq)) {
324 		bw_above_20 = phy_config->bw_above_20_24ghz;
325 		if (phy_config->vht_24G_cap)
326 			is_vht = true;
327 	} else if (phy_config->vht_cap) {
328 		is_vht = true;
329 		bw_above_20 = phy_config->bw_above_20_5ghz;
330 	}
331 
332 	if (IS_WLAN_PHYMODE_160MHZ(entry->phy_mode))
333 		ch_width_index = CM_160MHZ_BW_INDEX;
334 	else if (IS_WLAN_PHYMODE_80MHZ(entry->phy_mode))
335 		ch_width_index = CM_80MHZ_BW_INDEX;
336 	else if (IS_WLAN_PHYMODE_40MHZ(entry->phy_mode))
337 		ch_width_index = CM_40MHZ_BW_INDEX;
338 	else
339 		ch_width_index = CM_20MHZ_BW_INDEX;
340 
341 	if (!phy_config->ht_cap &&
342 	    ch_width_index > CM_20MHZ_BW_INDEX)
343 		ch_width_index = CM_20MHZ_BW_INDEX;
344 
345 	if (!is_vht && ch_width_index > CM_40MHZ_BW_INDEX)
346 		ch_width_index = CM_40MHZ_BW_INDEX;
347 
348 	if (bw_above_20 && ch_width_index > CM_20MHZ_BW_INDEX)
349 		score = CM_GET_SCORE_PERCENTAGE(bw_weight_per_idx,
350 						ch_width_index);
351 	else
352 		score = CM_GET_SCORE_PERCENTAGE(bw_weight_per_idx,
353 						CM_20MHZ_BW_INDEX);
354 
355 	return (prorated_pct * score *
356 		score_config->weight_config.chan_width_weightage) /
357 		CM_MAX_PCT_SCORE;
358 }
359 
360 /**
361  * cm_get_score_for_index() - get score for the given index
362  * @index: index for which we need the score
363  * @weightage: weigtage for the param
364  * @score: per slot score
365  *
366  * Return : score for the index
367  */
368 static int32_t cm_get_score_for_index(uint8_t index,
369 				      uint8_t weightage,
370 				      struct per_slot_score *score)
371 {
372 	if (index <= CM_SCORE_INDEX_3)
373 		return weightage * CM_GET_SCORE_PERCENTAGE(
374 				   score->score_pcnt3_to_0,
375 				   index);
376 	else if (index <= CM_SCORE_INDEX_7)
377 		return weightage * CM_GET_SCORE_PERCENTAGE(
378 				   score->score_pcnt7_to_4,
379 				   index - CM_SCORE_OFFSET_INDEX_7_4);
380 	else if (index <= CM_SCORE_INDEX_11)
381 		return weightage * CM_GET_SCORE_PERCENTAGE(
382 				   score->score_pcnt11_to_8,
383 				   index - CM_SCORE_OFFSET_INDEX_11_8);
384 	else
385 		return weightage * CM_GET_SCORE_PERCENTAGE(
386 				   score->score_pcnt15_to_12,
387 				   index - CM_SCORE_OFFSET_INDEX_15_12);
388 }
389 
390 /**
391  * cm_get_congestion_pct() - Calculate congestion pct from esp/qbss load
392  * @entry: bss information
393  *
394  * Return : congestion pct
395  */
396 static int32_t cm_get_congestion_pct(struct scan_cache_entry *entry)
397 {
398 	uint32_t ap_load = 0;
399 	uint32_t est_air_time_percentage = 0;
400 	uint32_t congestion = 0;
401 
402 	if (entry->air_time_fraction) {
403 		/* Convert 0-255 range to percentage */
404 		est_air_time_percentage = entry->air_time_fraction *
405 							CM_MAX_CHANNEL_WEIGHT;
406 		est_air_time_percentage = qdf_do_div(est_air_time_percentage,
407 					   CM_MAX_ESTIMATED_AIR_TIME_FRACTION);
408 		/*
409 		 * Calculate channel congestion from estimated air time
410 		 * fraction.
411 		 */
412 		congestion = CM_MAX_CHANNEL_UTILIZATION -
413 					est_air_time_percentage;
414 	} else if (entry->qbss_chan_load) {
415 		ap_load = (entry->qbss_chan_load * CM_MAX_PCT_SCORE);
416 		/*
417 		 * Calculate ap_load in % from qbss channel load from
418 		 * 0-255 range
419 		 */
420 		congestion = qdf_do_div(ap_load, CM_MAX_AP_LOAD);
421 	}
422 
423 	return congestion;
424 }
425 
426 /**
427  * cm_calculate_congestion_score() - Calculate congestion score
428  * @entry: bss information
429  * @score_params: bss score params
430  * @congestion_pct: congestion pct
431  *
432  * Return : congestion score
433  */
434 static int32_t cm_calculate_congestion_score(struct scan_cache_entry *entry,
435 					     struct scoring_cfg *score_params,
436 					     uint32_t *congestion_pct)
437 {
438 	uint32_t window_size;
439 	uint8_t index;
440 	int32_t good_rssi_threshold;
441 
442 	*congestion_pct = cm_get_congestion_pct(entry);
443 
444 	if (!score_params->esp_qbss_scoring.num_slot)
445 		return 0;
446 
447 	if (score_params->esp_qbss_scoring.num_slot >
448 	    CM_SCORE_MAX_INDEX)
449 		score_params->esp_qbss_scoring.num_slot =
450 			CM_SCORE_MAX_INDEX;
451 
452 	good_rssi_threshold =
453 		score_params->rssi_score.good_rssi_threshold * (-1);
454 
455 	/* For bad zone rssi get score from last index */
456 	if (entry->rssi_raw <= good_rssi_threshold)
457 		return cm_get_score_for_index(
458 			score_params->esp_qbss_scoring.num_slot,
459 			score_params->weight_config.channel_congestion_weightage,
460 			&score_params->esp_qbss_scoring);
461 
462 	if (!*congestion_pct)
463 		return score_params->weight_config.channel_congestion_weightage *
464 			   CM_GET_SCORE_PERCENTAGE(
465 			   score_params->esp_qbss_scoring.score_pcnt3_to_0,
466 			   CM_SCORE_INDEX_0);
467 
468 	window_size = CM_MAX_PCT_SCORE /
469 			score_params->esp_qbss_scoring.num_slot;
470 
471 	/* Desired values are from 1 to 15, as 0 is for not present. so do +1 */
472 	index = qdf_do_div(*congestion_pct, window_size) + 1;
473 
474 	if (index > score_params->esp_qbss_scoring.num_slot)
475 		index = score_params->esp_qbss_scoring.num_slot;
476 
477 	return cm_get_score_for_index(index,
478 		score_params->weight_config.channel_congestion_weightage,
479 		&score_params->esp_qbss_scoring);
480 }
481 
482 /**
483  * cm_calculate_nss_score() - Calculate congestion score
484  * @psoc: psoc ptr
485  * @score_config: scoring config
486  * @ap_nss: ap nss
487  * @prorated_pct: prorated % to return dependent on RSSI
488  *
489  * Return : nss score
490  */
491 static int32_t cm_calculate_nss_score(struct wlan_objmgr_psoc *psoc,
492 				      struct scoring_cfg *score_config,
493 				      uint8_t ap_nss, uint8_t prorated_pct,
494 				      uint32_t sta_nss)
495 {
496 	uint8_t nss;
497 	uint8_t score_pct;
498 
499 	nss = ap_nss;
500 	if (sta_nss < nss)
501 		nss = sta_nss;
502 
503 	/* TODO: enhance for 8x8 */
504 	if (nss == 4)
505 		score_pct = CM_GET_SCORE_PERCENTAGE(
506 				score_config->nss_weight_per_index,
507 				CM_NSS_4x4_INDEX);
508 	else if (nss == 3)
509 		score_pct = CM_GET_SCORE_PERCENTAGE(
510 				score_config->nss_weight_per_index,
511 				CM_NSS_3x3_INDEX);
512 	else if (nss == 2)
513 		score_pct = CM_GET_SCORE_PERCENTAGE(
514 				score_config->nss_weight_per_index,
515 				CM_NSS_2x2_INDEX);
516 	else
517 		score_pct = CM_GET_SCORE_PERCENTAGE(
518 				score_config->nss_weight_per_index,
519 				CM_NSS_1x1_INDEX);
520 
521 	return (score_config->weight_config.nss_weightage * score_pct *
522 		prorated_pct) / CM_MAX_PCT_SCORE;
523 }
524 
525 /**
526  * cm_calculate_oce_wan_score() - Calculate oce wan score
527  * @entry: bss information
528  * @score_params: bss score params
529  *
530  * Return : oce wan score
531  */
532 static int32_t cm_calculate_oce_wan_score(
533 	struct scan_cache_entry *entry,
534 	struct scoring_cfg *score_params)
535 {
536 	uint32_t window_size;
537 	uint8_t index;
538 	struct oce_reduced_wan_metrics wan_metrics;
539 	uint8_t *mbo_oce_ie;
540 
541 	if (!score_params->oce_wan_scoring.num_slot)
542 		return 0;
543 
544 	if (score_params->oce_wan_scoring.num_slot >
545 	    CM_SCORE_MAX_INDEX)
546 		score_params->oce_wan_scoring.num_slot =
547 			CM_SCORE_MAX_INDEX;
548 
549 	window_size = CM_SCORE_MAX_INDEX /
550 			score_params->oce_wan_scoring.num_slot;
551 	mbo_oce_ie = util_scan_entry_mbo_oce(entry);
552 	if (wlan_parse_oce_reduced_wan_metrics_ie(mbo_oce_ie, &wan_metrics)) {
553 		mlme_err("downlink_av_cap %d", wan_metrics.downlink_av_cap);
554 		/* if capacity is 0 return 0 score */
555 		if (!wan_metrics.downlink_av_cap)
556 			return 0;
557 		/* Desired values are from 1 to WLAN_SCORE_MAX_INDEX */
558 		index = qdf_do_div(wan_metrics.downlink_av_cap,
559 				   window_size);
560 	} else {
561 		index = CM_SCORE_INDEX_0;
562 	}
563 
564 	if (index > score_params->oce_wan_scoring.num_slot)
565 		index = score_params->oce_wan_scoring.num_slot;
566 
567 	return cm_get_score_for_index(index,
568 			score_params->weight_config.oce_wan_weightage,
569 			&score_params->oce_wan_scoring);
570 }
571 
572 /**
573  * cm_calculate_oce_subnet_id_weightage() - Calculate oce subnet id weightage
574  * @entry: bss entry
575  * @score_params: bss score params
576  * @oce_subnet_id_present: check if subnet id subelement is present in OCE IE
577  *
578  * Return : oce subnet id score
579  */
580 static uint32_t
581 cm_calculate_oce_subnet_id_weightage(struct scan_cache_entry *entry,
582 				     struct scoring_cfg *score_params,
583 				     bool *oce_subnet_id_present)
584 {
585 	uint32_t score = 0;
586 	uint8_t *mbo_oce_ie;
587 
588 	mbo_oce_ie = util_scan_entry_mbo_oce(entry);
589 	*oce_subnet_id_present = wlan_parse_oce_subnet_id_ie(mbo_oce_ie);
590 
591 	/* Consider 50% weightage if subnet id sub element is present */
592 	if (*oce_subnet_id_present)
593 		score  = score_params->weight_config.oce_subnet_id_weightage *
594 				(CM_MAX_PCT_SCORE / 2);
595 
596 	return score;
597 }
598 
599 /**
600  * cm_calculate_oce_ap_tx_pwr_weightage() - Calculate oce ap tx pwr weightage
601  * @entry: bss entry
602  * @score_params: bss score params
603  * @ap_tx_pwr_dbm: pointer to hold ap tx power
604  *
605  * Return : oce ap tx power score
606  */
607 static uint32_t
608 cm_calculate_oce_ap_tx_pwr_weightage(struct scan_cache_entry *entry,
609 				     struct scoring_cfg *score_params,
610 				     int8_t *ap_tx_pwr_dbm)
611 {
612 	uint8_t *mbo_oce_ie, ap_tx_pwr_factor;
613 	struct rssi_config_score *rssi_score_param;
614 	int32_t best_rssi_threshold, good_rssi_threshold, bad_rssi_threshold;
615 	uint32_t good_rssi_pcnt, bad_rssi_pcnt, good_bucket_size;
616 	uint32_t score, normalized_ap_tx_pwr, bad_bucket_size;
617 	bool ap_tx_pwr_cap_present = true;
618 
619 	mbo_oce_ie = util_scan_entry_mbo_oce(entry);
620 	if (!wlan_parse_oce_ap_tx_pwr_ie(mbo_oce_ie, ap_tx_pwr_dbm)) {
621 		ap_tx_pwr_cap_present = false;
622 		/* If no OCE AP TX pwr, consider Uplink RSSI = Downlink RSSI */
623 		normalized_ap_tx_pwr = entry->rssi_raw;
624 	} else {
625 		/*
626 		 * Normalized ap_tx_pwr =
627 		 * Uplink RSSI = (STA TX Power - * (AP TX power - RSSI)) in dBm.
628 		 * Currently assuming STA Tx Power to be 20dBm, though later it
629 		 * need to fetched from hal-phy API.
630 		 */
631 		normalized_ap_tx_pwr = (20 - (*ap_tx_pwr_dbm - entry->rssi_raw));
632 	}
633 
634 	rssi_score_param = &score_params->rssi_score;
635 
636 	best_rssi_threshold = rssi_score_param->best_rssi_threshold * (-1);
637 	good_rssi_threshold = rssi_score_param->good_rssi_threshold * (-1);
638 	bad_rssi_threshold = rssi_score_param->bad_rssi_threshold * (-1);
639 	good_rssi_pcnt = rssi_score_param->good_rssi_pcnt;
640 	bad_rssi_pcnt = rssi_score_param->bad_rssi_pcnt;
641 	good_bucket_size = rssi_score_param->good_rssi_bucket_size;
642 	bad_bucket_size = rssi_score_param->bad_rssi_bucket_size;
643 
644 	/* Uplink RSSI is better than best rssi threshold */
645 	if (normalized_ap_tx_pwr > best_rssi_threshold) {
646 		ap_tx_pwr_factor = CM_MAX_PCT_SCORE;
647 	} else if (normalized_ap_tx_pwr <= bad_rssi_threshold) {
648 		/* Uplink RSSI is less or equal to bad rssi threshold */
649 		ap_tx_pwr_factor = rssi_score_param->bad_rssi_pcnt;
650 	} else if (normalized_ap_tx_pwr > good_rssi_threshold) {
651 		/* Uplink RSSI lies between best to good rssi threshold */
652 		ap_tx_pwr_factor =
653 			cm_get_rssi_pcnt_for_slot(best_rssi_threshold,
654 				good_rssi_threshold, 100, good_rssi_pcnt,
655 				good_bucket_size, normalized_ap_tx_pwr);
656 	} else {
657 		/* Uplink RSSI lies between good to best rssi threshold */
658 		ap_tx_pwr_factor =
659 			cm_get_rssi_pcnt_for_slot(good_rssi_threshold,
660 				bad_rssi_threshold, good_rssi_pcnt,
661 				bad_rssi_pcnt, bad_bucket_size,
662 				normalized_ap_tx_pwr);
663 	}
664 
665 	score  = score_params->weight_config.oce_ap_tx_pwr_weightage *
666 			ap_tx_pwr_factor;
667 
668 	return score;
669 }
670 
671 #ifdef WLAN_POLICY_MGR_ENABLE
672 
673 static uint32_t cm_get_sta_nss(struct wlan_objmgr_psoc *psoc,
674 			       qdf_freq_t bss_channel_freq,
675 			       uint8_t vdev_nss_2g, uint8_t vdev_nss_5g)
676 {
677 	/*
678 	 * If station support nss as 2*2 but AP support NSS as 1*1,
679 	 * this AP will be given half weight compare to AP which are having
680 	 * NSS as 2*2.
681 	 */
682 
683 	if (policy_mgr_is_chnl_in_diff_band(
684 	    psoc, bss_channel_freq) &&
685 	    policy_mgr_is_hw_dbs_capable(psoc) &&
686 	    !(policy_mgr_is_hw_dbs_2x2_capable(psoc)))
687 		return 1;
688 
689 	return (WLAN_REG_IS_24GHZ_CH_FREQ(bss_channel_freq) ?
690 		vdev_nss_2g :
691 		vdev_nss_5g);
692 }
693 #else
694 static uint32_t cm_get_sta_nss(struct wlan_objmgr_psoc *psoc,
695 			       qdf_freq_t bss_channel_freq,
696 			       uint8_t vdev_nss_2g, uint8_t vdev_nss_5g)
697 {
698 	return (WLAN_REG_IS_24GHZ_CH_FREQ(bss_channel_freq) ?
699 		vdev_nss_2g :
700 		vdev_nss_5g);
701 }
702 #endif
703 
704 /**
705  * cm_get_band_score() - Get band prefernce weightage
706  * freq: Operating frequency of the AP
707  * @score_config: Score configuration
708  *
709  * Return : Band score for AP.
710  */
711 static int
712 cm_get_band_score(uint32_t freq, struct scoring_cfg *score_config)
713 {
714 	uint8_t band_index;
715 	struct weight_cfg *weight_config;
716 
717 	weight_config = &score_config->weight_config;
718 
719 	if (WLAN_REG_IS_5GHZ_CH_FREQ(freq))
720 		band_index = CM_BAND_5G_INDEX;
721 	else if (WLAN_REG_IS_24GHZ_CH_FREQ(freq))
722 		band_index = CM_BAND_2G_INDEX;
723 	else if (WLAN_REG_IS_6GHZ_CHAN_FREQ(freq))
724 		band_index = CM_BAND_6G_INDEX;
725 	else
726 		return 0;
727 
728 	return weight_config->chan_band_weightage *
729 	       CM_GET_SCORE_PERCENTAGE(score_config->band_weight_per_index,
730 				       band_index);
731 }
732 
733 static int cm_calculate_bss_score(struct wlan_objmgr_psoc *psoc,
734 				  struct scan_cache_entry *entry,
735 				  int pcl_chan_weight,
736 				  struct qdf_mac_addr *bssid_hint)
737 {
738 	int32_t score = 0;
739 	int32_t rssi_score = 0;
740 	int32_t pcl_score = 0;
741 	int32_t ht_score = 0;
742 	int32_t vht_score = 0;
743 	int32_t he_score = 0;
744 	int32_t bandwidth_score = 0;
745 	int32_t beamformee_score = 0;
746 	int32_t band_score = 0;
747 	int32_t nss_score = 0;
748 	int32_t congestion_score = 0;
749 	int32_t congestion_pct = 0;
750 	int32_t oce_wan_score = 0;
751 	uint8_t oce_ap_tx_pwr_score = 0;
752 	uint8_t oce_subnet_id_score = 0;
753 	bool oce_subnet_id_present = 0;
754 	int8_t ap_tx_pwr_dbm = 0;
755 	uint8_t prorated_pcnt;
756 	bool is_vht = false;
757 	int8_t good_rssi_threshold;
758 	int8_t rssi_pref_5g_rssi_thresh;
759 	bool same_bucket = false;
760 	bool ap_su_beam_former = false;
761 	struct wlan_ie_vhtcaps *vht_cap;
762 	struct scoring_cfg *score_config;
763 	struct weight_cfg *weight_config;
764 	uint32_t sta_nss;
765 	struct psoc_mlme_obj *mlme_psoc_obj;
766 	struct psoc_phy_config *phy_config;
767 
768 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
769 
770 	if (!mlme_psoc_obj)
771 		return 0;
772 	phy_config = &mlme_psoc_obj->phy_config;
773 	score_config = &mlme_psoc_obj->score_config;
774 	weight_config = &score_config->weight_config;
775 
776 	if (score_config->is_bssid_hint_priority && bssid_hint &&
777 	    qdf_is_macaddr_equal(bssid_hint, &entry->bssid)) {
778 		entry->bss_score = CM_BEST_CANDIDATE_MAX_BSS_SCORE;
779 		mlme_nofl_debug("Candidate(%pM freq %d): rssi %d BSSID hint given, give max score %d",
780 				entry->bssid.bytes, entry->channel.chan_freq,
781 				entry->rssi_raw,
782 				CM_BEST_CANDIDATE_MAX_BSS_SCORE);
783 		return CM_BEST_CANDIDATE_MAX_BSS_SCORE;
784 	}
785 
786 	rssi_score = cm_calculate_rssi_score(&score_config->rssi_score,
787 					     entry->rssi_raw,
788 					     weight_config->rssi_weightage);
789 	score += rssi_score;
790 
791 	pcl_score = cm_calculate_pcl_score(pcl_chan_weight,
792 					   weight_config->pcl_weightage);
793 	score += pcl_score;
794 
795 	prorated_pcnt = cm_roam_calculate_prorated_pcnt_by_rssi(
796 				&score_config->rssi_score, entry->rssi_raw,
797 				weight_config->rssi_weightage);
798 
799 	/*
800 	 * Add HT weight if HT is supported by the AP. In case
801 	 * of 6 GHZ AP, HT and VHT won't be supported so that
802 	 * these weightage to the same by default to match
803 	 * with 2.4/5 GHZ APs where HT, VHT is supported
804 	 */
805 	if (phy_config->ht_cap && (entry->ie_list.htcap ||
806 	    WLAN_REG_IS_6GHZ_CHAN_FREQ(entry->channel.chan_freq)))
807 		ht_score = prorated_pcnt *
808 				weight_config->ht_caps_weightage;
809 	score += ht_score;
810 
811 	if (WLAN_REG_IS_24GHZ_CH_FREQ(entry->channel.chan_freq)) {
812 		if (phy_config->vht_24G_cap)
813 			is_vht = true;
814 	} else if (phy_config->vht_cap) {
815 		is_vht = true;
816 	}
817 
818 	/* Add VHT score to 6 GHZ AP to match with 2.4/5 GHZ APs */
819 	if (is_vht && (entry->ie_list.vhtcap ||
820 	    WLAN_REG_IS_6GHZ_CHAN_FREQ(entry->channel.chan_freq)))
821 		vht_score = prorated_pcnt *
822 				 weight_config->vht_caps_weightage;
823 	score += vht_score;
824 
825 	if (phy_config->he_cap && entry->ie_list.hecap)
826 		he_score = prorated_pcnt *
827 				 weight_config->he_caps_weightage;
828 	score += he_score;
829 
830 	bandwidth_score = cm_calculate_bandwidth_score(entry, score_config,
831 						       phy_config,
832 						       prorated_pcnt);
833 	score += bandwidth_score;
834 
835 	good_rssi_threshold =
836 		score_config->rssi_score.good_rssi_threshold * (-1);
837 	rssi_pref_5g_rssi_thresh =
838 		score_config->rssi_score.rssi_pref_5g_rssi_thresh * (-1);
839 	if (entry->rssi_raw < good_rssi_threshold)
840 		same_bucket = cm_rssi_is_same_bucket(good_rssi_threshold,
841 				entry->rssi_raw, rssi_pref_5g_rssi_thresh,
842 				score_config->rssi_score.bad_rssi_bucket_size);
843 
844 	vht_cap = (struct wlan_ie_vhtcaps *)util_scan_entry_vhtcap(entry);
845 	if (vht_cap && vht_cap->su_beam_former)
846 		ap_su_beam_former = true;
847 	if (phy_config->beamformee_cap && is_vht &&
848 	    ap_su_beam_former &&
849 	    (entry->rssi_raw > rssi_pref_5g_rssi_thresh) && !same_bucket)
850 		beamformee_score = CM_MAX_PCT_SCORE *
851 				weight_config->beamforming_cap_weightage;
852 	score += beamformee_score;
853 
854 	congestion_score = cm_calculate_congestion_score(entry, score_config,
855 							 &congestion_pct);
856 	score += congestion_score;
857 	/*
858 	 * Consider OCE WAN score and band preference score only if
859 	 * congestion_pct is greater than CONGESTION_THRSHOLD_FOR_BAND_OCE_SCORE
860 	 */
861 	if (congestion_pct < CM_CONGESTION_THRSHOLD_FOR_BAND_OCE_SCORE) {
862 		/*
863 		 * If AP is on 5/6 GHZ channel , extra weigtage is added to BSS
864 		 * score. if RSSI is greater tha 5g rssi threshold or fall in
865 		 * same bucket else give weigtage to 2.4 GHZ AP.
866 		 */
867 		if ((entry->rssi_raw > rssi_pref_5g_rssi_thresh) &&
868 		    !same_bucket) {
869 			if (!WLAN_REG_IS_24GHZ_CH_FREQ(entry->channel.chan_freq))
870 				band_score = cm_get_band_score(
871 						entry->channel.chan_freq,
872 						score_config);
873 		} else if (WLAN_REG_IS_24GHZ_CH_FREQ(
874 			   entry->channel.chan_freq)) {
875 			band_score = cm_get_band_score(entry->channel.chan_freq,
876 						       score_config);
877 		}
878 		score += band_score;
879 
880 		oce_wan_score = cm_calculate_oce_wan_score(entry, score_config);
881 		score += oce_wan_score;
882 	}
883 
884 	oce_ap_tx_pwr_score =
885 		cm_calculate_oce_ap_tx_pwr_weightage(entry, score_config,
886 						     &ap_tx_pwr_dbm);
887 	score += oce_ap_tx_pwr_score;
888 
889 	oce_subnet_id_score = cm_calculate_oce_subnet_id_weightage(entry,
890 						score_config,
891 						&oce_subnet_id_present);
892 	score += oce_subnet_id_score;
893 
894 	sta_nss = cm_get_sta_nss(psoc, entry->channel.chan_freq,
895 				 phy_config->vdev_nss_24g,
896 				 phy_config->vdev_nss_5g);
897 
898 	/*
899 	 * If station support nss as 2*2 but AP support NSS as 1*1,
900 	 * this AP will be given half weight compare to AP which are having
901 	 * NSS as 2*2.
902 	 */
903 	nss_score = cm_calculate_nss_score(psoc, score_config, entry->nss,
904 					   prorated_pcnt, sta_nss);
905 	score += nss_score;
906 
907 	mlme_nofl_debug("Candidate(%pM 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 prorated_pcnt %d",
908 			entry->bssid.bytes, entry->channel.chan_freq,
909 			entry->rssi_raw, util_scan_entry_htcap(entry) ? 1 : 0,
910 			util_scan_entry_vhtcap(entry) ? 1 : 0,
911 			util_scan_entry_hecap(entry) ? 1 : 0, ap_su_beam_former,
912 			entry->phy_mode, entry->air_time_fraction,
913 			entry->qbss_chan_load, congestion_pct, entry->nss,
914 			ap_tx_pwr_dbm, oce_subnet_id_present, prorated_pcnt);
915 
916 	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 TOTAL %d",
917 			rssi_score, pcl_score, ht_score,
918 			vht_score, he_score, beamformee_score, bandwidth_score,
919 			band_score, congestion_score, nss_score, oce_wan_score,
920 			oce_ap_tx_pwr_score, oce_subnet_id_score, score);
921 
922 	entry->bss_score = score;
923 
924 	return score;
925 }
926 
927 static bool
928 cm_get_pcl_weight_of_channel(uint32_t chan_freq,
929 			     struct pcl_freq_weight_list *pcl_lst,
930 			     int *pcl_chan_weight)
931 {
932 	int i;
933 	bool found = false;
934 
935 	if (!pcl_lst)
936 		return found;
937 
938 	for (i = 0; i < pcl_lst->num_of_pcl_channels; i++) {
939 		if (pcl_lst->pcl_freq_list[i] == chan_freq) {
940 			*pcl_chan_weight = pcl_lst->pcl_weight_list[i];
941 			found = true;
942 			break;
943 		}
944 	}
945 
946 	return found;
947 }
948 
949 static void cm_list_insert_sorted(qdf_list_t *scan_list,
950 				  struct scan_cache_node *scan_entry)
951 {
952 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
953 	struct scan_cache_node *curr_entry;
954 
955 	qdf_list_peek_front(scan_list, &cur_node);
956 	while (cur_node) {
957 		curr_entry = qdf_container_of(cur_node, struct scan_cache_node,
958 					      node);
959 		if (cm_is_better_bss(scan_entry->entry, curr_entry->entry)) {
960 			qdf_list_insert_before(scan_list, &scan_entry->node,
961 					       &curr_entry->node);
962 			break;
963 		}
964 		qdf_list_peek_next(scan_list, cur_node, &next_node);
965 		cur_node = next_node;
966 		next_node = NULL;
967 	}
968 
969 	if (!cur_node)
970 		qdf_list_insert_back(scan_list, &scan_entry->node);
971 }
972 
973 void wlan_cm_calculate_bss_score(struct wlan_objmgr_psoc *psoc,
974 				 struct pcl_freq_weight_list *pcl_lst,
975 				 qdf_list_t *scan_list,
976 				 struct qdf_mac_addr *bssid_hint)
977 {
978 	struct scan_cache_node *scan_entry;
979 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
980 	struct psoc_mlme_obj *mlme_psoc_obj;
981 	struct scoring_cfg *score_config;
982 	int pcl_chan_weight;
983 	QDF_STATUS status;
984 	struct psoc_phy_config *config;
985 
986 	if (!scan_list) {
987 		mlme_err("Scan list NULL");
988 		return;
989 	}
990 
991 	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
992 	if (!mlme_psoc_obj)
993 		return;
994 
995 	score_config = &mlme_psoc_obj->score_config;
996 	config = &mlme_psoc_obj->phy_config;
997 
998 	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",
999 			config->ht_cap, config->vht_cap,
1000 			config->he_cap, config->vht_24G_cap,
1001 			config->beamformee_cap, config->bw_above_20_24ghz,
1002 			config->bw_above_20_5ghz, config->vdev_nss_24g,
1003 			config->vdev_nss_5g);
1004 
1005 	/* calculate score for each AP */
1006 	if (qdf_list_peek_front(scan_list, &cur_node) != QDF_STATUS_SUCCESS) {
1007 		mlme_err("failed to peer front of scan list");
1008 		return;
1009 	}
1010 
1011 	while (cur_node) {
1012 		qdf_list_peek_next(scan_list, cur_node, &next_node);
1013 		pcl_chan_weight = 0;
1014 		scan_entry = qdf_container_of(cur_node, struct scan_cache_node,
1015 					      node);
1016 
1017 		if (pcl_lst && pcl_lst->num_of_pcl_channels &&
1018 		    scan_entry->entry->rssi_raw > CM_PCL_RSSI_THRESHOLD &&
1019 		    score_config->weight_config.pcl_weightage) {
1020 			if (cm_get_pcl_weight_of_channel(
1021 					scan_entry->entry->channel.chan_freq,
1022 					pcl_lst, &pcl_chan_weight)) {
1023 				mlme_debug("pcl freq %d pcl_chan_weight %d",
1024 					   scan_entry->entry->channel.chan_freq,
1025 					   pcl_chan_weight);
1026 			}
1027 		}
1028 
1029 		cm_calculate_bss_score(psoc, scan_entry->entry, pcl_chan_weight,
1030 				       bssid_hint);
1031 
1032 		/* Remove node from current locaion to add node back shorted */
1033 		status = qdf_list_remove_node(scan_list, cur_node);
1034 		if (QDF_IS_STATUS_ERROR(status)) {
1035 			mlme_err("failed to remove node from scan list");
1036 			return;
1037 		}
1038 		/* Add node back shorted */
1039 		cm_list_insert_sorted(scan_list, scan_entry);
1040 		cur_node = next_node;
1041 		next_node = NULL;
1042 	}
1043 }
1044 
1045 static uint32_t
1046 cm_limit_max_per_index_score(uint32_t per_index_score)
1047 {
1048 	uint8_t i, score;
1049 
1050 	for (i = 0; i < CM_MAX_INDEX_PER_INI; i++) {
1051 		score = CM_GET_SCORE_PERCENTAGE(per_index_score, i);
1052 		if (score > CM_MAX_PCT_SCORE)
1053 			CM_SET_SCORE_PERCENTAGE(per_index_score,
1054 						CM_MAX_PCT_SCORE, i);
1055 	}
1056 
1057 	return per_index_score;
1058 }
1059 
1060 void wlan_cm_init_score_config(struct wlan_objmgr_psoc *psoc,
1061 			       struct scoring_cfg *score_cfg)
1062 {
1063 	uint32_t total_weight;
1064 
1065 	score_cfg->weight_config.rssi_weightage =
1066 		cfg_get(psoc, CFG_SCORING_RSSI_WEIGHTAGE);
1067 	score_cfg->weight_config.ht_caps_weightage =
1068 		cfg_get(psoc, CFG_SCORING_HT_CAPS_WEIGHTAGE);
1069 	score_cfg->weight_config.vht_caps_weightage =
1070 		cfg_get(psoc, CFG_SCORING_VHT_CAPS_WEIGHTAGE);
1071 	score_cfg->weight_config.he_caps_weightage =
1072 		cfg_get(psoc, CFG_SCORING_HE_CAPS_WEIGHTAGE);
1073 	score_cfg->weight_config.chan_width_weightage =
1074 		cfg_get(psoc, CFG_SCORING_CHAN_WIDTH_WEIGHTAGE);
1075 	score_cfg->weight_config.chan_band_weightage =
1076 		cfg_get(psoc, CFG_SCORING_CHAN_BAND_WEIGHTAGE);
1077 	score_cfg->weight_config.nss_weightage =
1078 		cfg_get(psoc, CFG_SCORING_NSS_WEIGHTAGE);
1079 	score_cfg->weight_config.beamforming_cap_weightage =
1080 		cfg_get(psoc, CFG_SCORING_BEAMFORM_CAP_WEIGHTAGE);
1081 	score_cfg->weight_config.pcl_weightage =
1082 		cfg_get(psoc, CFG_SCORING_PCL_WEIGHTAGE);
1083 	score_cfg->weight_config.channel_congestion_weightage =
1084 		cfg_get(psoc, CFG_SCORING_CHAN_CONGESTION_WEIGHTAGE);
1085 	score_cfg->weight_config.oce_wan_weightage =
1086 		cfg_get(psoc, CFG_SCORING_OCE_WAN_WEIGHTAGE);
1087 	score_cfg->weight_config.oce_ap_tx_pwr_weightage =
1088 				cfg_get(psoc, CFG_OCE_AP_TX_PWR_WEIGHTAGE);
1089 	score_cfg->weight_config.oce_subnet_id_weightage =
1090 				cfg_get(psoc, CFG_OCE_SUBNET_ID_WEIGHTAGE);
1091 
1092 	total_weight =  score_cfg->weight_config.rssi_weightage +
1093 			score_cfg->weight_config.ht_caps_weightage +
1094 			score_cfg->weight_config.vht_caps_weightage +
1095 			score_cfg->weight_config.he_caps_weightage +
1096 			score_cfg->weight_config.chan_width_weightage +
1097 			score_cfg->weight_config.chan_band_weightage +
1098 			score_cfg->weight_config.nss_weightage +
1099 			score_cfg->weight_config.beamforming_cap_weightage +
1100 			score_cfg->weight_config.pcl_weightage +
1101 			score_cfg->weight_config.channel_congestion_weightage +
1102 			score_cfg->weight_config.oce_wan_weightage +
1103 			score_cfg->weight_config.oce_ap_tx_pwr_weightage +
1104 			score_cfg->weight_config.oce_subnet_id_weightage;
1105 
1106 	/*
1107 	 * If configured weights are greater than max weight,
1108 	 * fallback to default weights
1109 	 */
1110 	if (total_weight > CM_BEST_CANDIDATE_MAX_WEIGHT) {
1111 		mlme_err("Total weight greater than %d, using default weights",
1112 			 CM_BEST_CANDIDATE_MAX_WEIGHT);
1113 		score_cfg->weight_config.rssi_weightage = CM_RSSI_WEIGHTAGE;
1114 		score_cfg->weight_config.ht_caps_weightage =
1115 						CM_HT_CAPABILITY_WEIGHTAGE;
1116 		score_cfg->weight_config.vht_caps_weightage =
1117 						CM_VHT_CAP_WEIGHTAGE;
1118 		score_cfg->weight_config.he_caps_weightage =
1119 						CM_HE_CAP_WEIGHTAGE;
1120 		score_cfg->weight_config.chan_width_weightage =
1121 						CM_CHAN_WIDTH_WEIGHTAGE;
1122 		score_cfg->weight_config.chan_band_weightage =
1123 						CM_CHAN_BAND_WEIGHTAGE;
1124 		score_cfg->weight_config.nss_weightage = CM_NSS_WEIGHTAGE;
1125 		score_cfg->weight_config.beamforming_cap_weightage =
1126 						CM_BEAMFORMING_CAP_WEIGHTAGE;
1127 		score_cfg->weight_config.pcl_weightage = CM_PCL_WEIGHT;
1128 		score_cfg->weight_config.channel_congestion_weightage =
1129 						CM_CHANNEL_CONGESTION_WEIGHTAGE;
1130 		score_cfg->weight_config.oce_wan_weightage =
1131 						CM_OCE_WAN_WEIGHTAGE;
1132 		score_cfg->weight_config.oce_ap_tx_pwr_weightage =
1133 						CM_OCE_AP_TX_POWER_WEIGHTAGE;
1134 		score_cfg->weight_config.oce_subnet_id_weightage =
1135 						CM_OCE_SUBNET_ID_WEIGHTAGE;
1136 	}
1137 
1138 	score_cfg->rssi_score.best_rssi_threshold =
1139 		cfg_get(psoc, CFG_SCORING_BEST_RSSI_THRESHOLD);
1140 	score_cfg->rssi_score.good_rssi_threshold =
1141 		cfg_get(psoc, CFG_SCORING_GOOD_RSSI_THRESHOLD);
1142 	score_cfg->rssi_score.bad_rssi_threshold =
1143 		cfg_get(psoc, CFG_SCORING_BAD_RSSI_THRESHOLD);
1144 
1145 	score_cfg->rssi_score.good_rssi_pcnt =
1146 		cfg_get(psoc, CFG_SCORING_GOOD_RSSI_PERCENT);
1147 	score_cfg->rssi_score.bad_rssi_pcnt =
1148 		cfg_get(psoc, CFG_SCORING_BAD_RSSI_PERCENT);
1149 
1150 	score_cfg->rssi_score.good_rssi_bucket_size =
1151 		cfg_get(psoc, CFG_SCORING_GOOD_RSSI_BUCKET_SIZE);
1152 	score_cfg->rssi_score.bad_rssi_bucket_size =
1153 		cfg_get(psoc, CFG_SCORING_BAD_RSSI_BUCKET_SIZE);
1154 
1155 	score_cfg->rssi_score.rssi_pref_5g_rssi_thresh =
1156 		cfg_get(psoc, CFG_SCORING_RSSI_PREF_5G_THRESHOLD);
1157 
1158 	score_cfg->esp_qbss_scoring.num_slot =
1159 		cfg_get(psoc, CFG_SCORING_NUM_ESP_QBSS_SLOTS);
1160 	score_cfg->esp_qbss_scoring.score_pcnt3_to_0 =
1161 		cm_limit_max_per_index_score(
1162 			cfg_get(psoc, CFG_SCORING_ESP_QBSS_SCORE_IDX_3_TO_0));
1163 	score_cfg->esp_qbss_scoring.score_pcnt7_to_4 =
1164 		cm_limit_max_per_index_score(
1165 			cfg_get(psoc, CFG_SCORING_ESP_QBSS_SCORE_IDX_7_TO_4));
1166 	score_cfg->esp_qbss_scoring.score_pcnt11_to_8 =
1167 		cm_limit_max_per_index_score(
1168 			cfg_get(psoc, CFG_SCORING_ESP_QBSS_SCORE_IDX_11_TO_8));
1169 	score_cfg->esp_qbss_scoring.score_pcnt15_to_12 =
1170 		cm_limit_max_per_index_score(
1171 			cfg_get(psoc, CFG_SCORING_ESP_QBSS_SCORE_IDX_15_TO_12));
1172 
1173 	score_cfg->oce_wan_scoring.num_slot =
1174 		cfg_get(psoc, CFG_SCORING_NUM_OCE_WAN_SLOTS);
1175 	score_cfg->oce_wan_scoring.score_pcnt3_to_0 =
1176 		cm_limit_max_per_index_score(
1177 			cfg_get(psoc, CFG_SCORING_OCE_WAN_SCORE_IDX_3_TO_0));
1178 	score_cfg->oce_wan_scoring.score_pcnt7_to_4 =
1179 		cm_limit_max_per_index_score(
1180 			cfg_get(psoc, CFG_SCORING_OCE_WAN_SCORE_IDX_7_TO_4));
1181 	score_cfg->oce_wan_scoring.score_pcnt11_to_8 =
1182 		cm_limit_max_per_index_score(
1183 			cfg_get(psoc, CFG_SCORING_OCE_WAN_SCORE_IDX_11_TO_8));
1184 	score_cfg->oce_wan_scoring.score_pcnt15_to_12 =
1185 		cm_limit_max_per_index_score(
1186 			cfg_get(psoc, CFG_SCORING_OCE_WAN_SCORE_IDX_15_TO_12));
1187 
1188 	score_cfg->bandwidth_weight_per_index =
1189 		cm_limit_max_per_index_score(
1190 			cfg_get(psoc, CFG_SCORING_BW_WEIGHT_PER_IDX));
1191 	score_cfg->nss_weight_per_index =
1192 		cm_limit_max_per_index_score(
1193 			cfg_get(psoc, CFG_SCORING_NSS_WEIGHT_PER_IDX));
1194 	score_cfg->band_weight_per_index =
1195 		cm_limit_max_per_index_score(
1196 			cfg_get(psoc, CFG_SCORING_BAND_WEIGHT_PER_IDX));
1197 	score_cfg->is_bssid_hint_priority =
1198 			cfg_get(psoc, CFG_IS_BSSID_HINT_PRIORITY);
1199 }
1200 
1201