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