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