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