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