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