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