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