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