1 /* 2 * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /*=========================================================================== 21 22 s a p C h S e l e c t . C 23 OVERVIEW: 24 25 This software unit holds the implementation of the WLAN SAP modules 26 functions for channel selection. 27 28 DEPENDENCIES: 29 30 Are listed for each API below. 31 ===========================================================================*/ 32 33 /*-------------------------------------------------------------------------- 34 Include Files 35 ------------------------------------------------------------------------*/ 36 #include "qdf_trace.h" 37 #include "csr_api.h" 38 #include "sme_api.h" 39 #include "sap_ch_select.h" 40 #include "sap_internal.h" 41 #ifdef ANI_OS_TYPE_QNX 42 #include "stdio.h" 43 #endif 44 #ifdef FEATURE_AP_MCC_CH_AVOIDANCE 45 #include "lim_utils.h" 46 #include "parser_api.h" 47 #include <wlan_utility.h> 48 #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ 49 #include "cds_utils.h" 50 #include "pld_common.h" 51 #include "wlan_reg_services_api.h" 52 #include <wlan_scan_utils_api.h> 53 #include <wlan_cp_stats_mc_ucfg_api.h> 54 #include <wlan_policy_mgr_api.h> 55 56 /*-------------------------------------------------------------------------- 57 Function definitions 58 --------------------------------------------------------------------------*/ 59 60 /*-------------------------------------------------------------------------- 61 Defines 62 --------------------------------------------------------------------------*/ 63 #define SAP_DEBUG 64 65 #define IS_RSSI_VALID(extRssi, rssi) \ 66 ( \ 67 ((extRssi < rssi) ? true : false) \ 68 ) 69 70 #define SET_ACS_BAND(acs_band, sap_ctx) \ 71 { \ 72 if (sap_ctx->acs_cfg->start_ch_freq <= \ 73 WLAN_REG_CH_TO_FREQ(CHAN_ENUM_2484) && \ 74 sap_ctx->acs_cfg->end_ch_freq <= \ 75 WLAN_REG_CH_TO_FREQ(CHAN_ENUM_2484)) \ 76 acs_band = eCSR_DOT11_MODE_11g; \ 77 else if (sap_ctx->acs_cfg->start_ch_freq >= \ 78 WLAN_REG_CH_TO_FREQ(CHAN_ENUM_2484))\ 79 acs_band = eCSR_DOT11_MODE_11a; \ 80 else \ 81 acs_band = eCSR_DOT11_MODE_abg; \ 82 } 83 84 #define ACS_WEIGHT_AMOUNT_LOCAL 240 85 86 #define ACS_WEIGHT_AMOUNT_CONFIG(weights) \ 87 (((weights) & 0xf) + \ 88 (((weights) & 0xf0) >> 4) + \ 89 (((weights) & 0xf00) >> 8) + \ 90 (((weights) & 0xf000) >> 12) + \ 91 (((weights) & 0xf0000) >> 16) + \ 92 (((weights) & 0xf00000) >> 20) + \ 93 (((weights) & 0xf000000) >> 24)) 94 95 /* 96 * LSH/RSH 4 to enhance the accurate since 97 * need to do modulation to ACS_WEIGHT_AMOUNT_LOCAL. 98 */ 99 #define ACS_WEIGHT_COMPUTE(weights, weight, factor, base) \ 100 (((((((((weight) << 4) * ACS_WEIGHT_AMOUNT_LOCAL * (factor)) + \ 101 (ACS_WEIGHT_AMOUNT_CONFIG((weights)) >> 1)) / \ 102 ACS_WEIGHT_AMOUNT_CONFIG((weights))) + \ 103 ((base) >> 1)) / (base)) + 8) >> 4) 104 105 #define ACS_WEIGHT_CFG_TO_LOCAL(weights, weight) \ 106 (((((((weight) << 4) * ACS_WEIGHT_AMOUNT_LOCAL) + \ 107 (ACS_WEIGHT_AMOUNT_CONFIG((weights)) >> 1)) / \ 108 ACS_WEIGHT_AMOUNT_CONFIG((weights))) + 8) >> 4) 109 110 #define ACS_WEIGHT_SOFTAP_RSSI_CFG(weights) \ 111 ((weights) & 0xf) 112 113 #define ACS_WEIGHT_SOFTAP_COUNT_CFG(weights) \ 114 (((weights) & 0xf0) >> 4) 115 116 #define ACS_WEIGHT_SOFTAP_NOISE_FLOOR_CFG(weights) \ 117 (((weights) & 0xf00) >> 8) 118 119 #define ACS_WEIGHT_SOFTAP_CHANNEL_FREE_CFG(weights) \ 120 (((weights) & 0xf000) >> 12) 121 122 #define ACS_WEIGHT_SOFTAP_TX_POWER_RANGE_CFG(weights) \ 123 (((weights) & 0xf0000) >> 16) 124 125 #define ACS_WEIGHT_SOFTAP_TX_POWER_THROUGHPUT_CFG(weights) \ 126 (((weights) & 0xf00000) >> 20) 127 128 #define ACS_WEIGHT_SOFTAP_REG_MAX_POWER_CFG(weights) \ 129 (((weights) & 0xf000000) >> 24) 130 131 typedef struct { 132 uint16_t chStartNum; 133 uint32_t weight; 134 } sapAcsChannelInfo; 135 136 sapAcsChannelInfo acs_ht40_channels5_g[] = { 137 {36, SAP_ACS_WEIGHT_MAX}, 138 {44, SAP_ACS_WEIGHT_MAX}, 139 {52, SAP_ACS_WEIGHT_MAX}, 140 {60, SAP_ACS_WEIGHT_MAX}, 141 {100, SAP_ACS_WEIGHT_MAX}, 142 {108, SAP_ACS_WEIGHT_MAX}, 143 {116, SAP_ACS_WEIGHT_MAX}, 144 {124, SAP_ACS_WEIGHT_MAX}, 145 {132, SAP_ACS_WEIGHT_MAX}, 146 {140, SAP_ACS_WEIGHT_MAX}, 147 {149, SAP_ACS_WEIGHT_MAX}, 148 {157, SAP_ACS_WEIGHT_MAX}, 149 }; 150 151 sapAcsChannelInfo acs_ht80_channels[] = { 152 {36, SAP_ACS_WEIGHT_MAX}, 153 {52, SAP_ACS_WEIGHT_MAX}, 154 {100, SAP_ACS_WEIGHT_MAX}, 155 {116, SAP_ACS_WEIGHT_MAX}, 156 {132, SAP_ACS_WEIGHT_MAX}, 157 {149, SAP_ACS_WEIGHT_MAX}, 158 }; 159 160 sapAcsChannelInfo acs_vht160_channels[] = { 161 {36, SAP_ACS_WEIGHT_MAX}, 162 {100, SAP_ACS_WEIGHT_MAX}, 163 }; 164 165 sapAcsChannelInfo acs_ht40_channels24_g[] = { 166 {1, SAP_ACS_WEIGHT_MAX}, 167 {2, SAP_ACS_WEIGHT_MAX}, 168 {3, SAP_ACS_WEIGHT_MAX}, 169 {4, SAP_ACS_WEIGHT_MAX}, 170 {9, SAP_ACS_WEIGHT_MAX}, 171 }; 172 173 #define CHANNEL_165 165 174 175 /* rssi discount for channels in PCL */ 176 #define PCL_RSSI_DISCOUNT 10 177 178 #ifdef FEATURE_AP_MCC_CH_AVOIDANCE 179 /** 180 * sap_check_n_add_channel() - checks and add given channel in sap context's 181 * avoid_channels_info struct 182 * @sap_ctx: sap context. 183 * @new_channel: channel to be added to sap_ctx's avoid ch info 184 * 185 * sap_ctx contains sap_avoid_ch_info strcut containing the list of channels on 186 * which MDM device's AP with MCC was detected. This function will add channels 187 * to that list after checking for duplicates. 188 * 189 * Return: true: if channel was added or already present 190 * else false: if channel list was already full. 191 */ 192 static bool 193 sap_check_n_add_channel(struct sap_context *sap_ctx, 194 uint8_t new_channel) 195 { 196 uint8_t i = 0; 197 struct sap_avoid_channels_info *ie_info = 198 &sap_ctx->sap_detected_avoid_ch_ie; 199 200 for (i = 0; i < sizeof(ie_info->channels); i++) { 201 if (ie_info->channels[i] == new_channel) 202 break; 203 204 if (ie_info->channels[i] == 0) { 205 ie_info->channels[i] = new_channel; 206 break; 207 } 208 } 209 if (i == sizeof(ie_info->channels)) 210 return false; 211 else 212 return true; 213 } 214 /** 215 * sap_check_n_add_overlapped_chnls() - checks & add overlapped channels 216 * to primary channel in 2.4Ghz band. 217 * @sap_ctx: sap context. 218 * @primary_channel: primary channel to be avoided. 219 * 220 * sap_ctx contains sap_avoid_ch_info struct containing the list of channels on 221 * which MDM device's AP with MCC was detected. This function will add channels 222 * to that list after checking for duplicates. 223 * 224 * Return: true: if channel was added or already present 225 * else false: if channel list was already full. 226 */ 227 static bool 228 sap_check_n_add_overlapped_chnls(struct sap_context *sap_ctx, 229 uint8_t primary_channel) 230 { 231 uint8_t i = 0, j = 0, upper_chnl = 0, lower_chnl = 0; 232 struct sap_avoid_channels_info *ie_info = 233 &sap_ctx->sap_detected_avoid_ch_ie; 234 /* 235 * if primary channel less than channel 1 or out of 2g band then 236 * no further process is required. return true in this case. 237 */ 238 if (primary_channel < CHANNEL_1 || primary_channel > CHANNEL_14) 239 return true; 240 241 /* lower channel is one channel right before primary channel */ 242 lower_chnl = primary_channel - 1; 243 /* upper channel is one channel right after primary channel */ 244 upper_chnl = primary_channel + 1; 245 246 /* lower channel needs to be non-zero, zero is not valid channel */ 247 if (lower_chnl > (CHANNEL_1 - 1)) { 248 for (i = 0; i < sizeof(ie_info->channels); i++) { 249 if (ie_info->channels[i] == lower_chnl) 250 break; 251 if (ie_info->channels[i] == 0) { 252 ie_info->channels[i] = lower_chnl; 253 break; 254 } 255 } 256 } 257 /* upper channel needs to be atleast last channel in 2.4Ghz band */ 258 if (upper_chnl < (CHANNEL_14 + 1)) { 259 for (j = 0; j < sizeof(ie_info->channels); j++) { 260 if (ie_info->channels[j] == upper_chnl) 261 break; 262 if (ie_info->channels[j] == 0) { 263 ie_info->channels[j] = upper_chnl; 264 break; 265 } 266 } 267 } 268 if (i == sizeof(ie_info->channels) || j == sizeof(ie_info->channels)) 269 return false; 270 else 271 return true; 272 } 273 274 /** 275 * sap_process_avoid_ie() - processes the detected Q2Q IE 276 * context's avoid_channels_info struct 277 * @mac_ctx: pointer to mac_context structure 278 * @sap_ctx: sap context. 279 * @scan_list: scan results for ACS scan. 280 * @spect_info: spectrum weights array to update 281 * 282 * Detection of Q2Q IE indicates presence of another MDM device with its AP 283 * operating in MCC mode. This function parses the scan results and processes 284 * the Q2Q IE if found. It then extracts the channels and populates them in 285 * sap_ctx struct. It also increases the weights of those channels so that 286 * ACS logic will avoid those channels in its selection algorithm. 287 * 288 * Return: void 289 */ 290 static void 291 sap_process_avoid_ie(struct mac_context *mac_ctx, 292 struct sap_context *sap_ctx, 293 qdf_list_t *scan_list, 294 struct sap_sel_ch_info *spect_info) 295 { 296 const uint8_t *temp_ptr = NULL; 297 uint8_t i = 0; 298 struct sAvoidChannelIE *avoid_ch_ie; 299 struct sap_ch_info *spect_ch = NULL; 300 qdf_list_node_t *cur_lst = NULL, *next_lst = NULL; 301 struct scan_cache_node *cur_node = NULL; 302 uint32_t chan_freq; 303 304 spect_ch = spect_info->ch_info; 305 306 if (scan_list) 307 qdf_list_peek_front(scan_list, &cur_lst); 308 309 while (cur_lst) { 310 cur_node = qdf_container_of(cur_lst, struct scan_cache_node, 311 node); 312 313 temp_ptr = wlan_get_vendor_ie_ptr_from_oui( 314 SIR_MAC_QCOM_VENDOR_OUI, 315 SIR_MAC_QCOM_VENDOR_SIZE, 316 util_scan_entry_ie_data(cur_node->entry), 317 util_scan_entry_ie_len(cur_node->entry)); 318 319 if (temp_ptr) { 320 avoid_ch_ie = (struct sAvoidChannelIE *)temp_ptr; 321 if (avoid_ch_ie->type != 322 QCOM_VENDOR_IE_MCC_AVOID_CH) { 323 qdf_list_peek_next(scan_list, 324 cur_lst, &next_lst); 325 cur_lst = next_lst; 326 next_lst = NULL; 327 continue; 328 } 329 330 sap_ctx->sap_detected_avoid_ch_ie.present = 1; 331 332 chan_freq = 333 wlan_reg_legacy_chan_to_freq(mac_ctx->pdev, 334 avoid_ch_ie->channel); 335 336 sap_debug("Q2Q-IE avoid freq = %d", chan_freq); 337 /* add this channel to to_avoid channel list */ 338 sap_check_n_add_channel(sap_ctx, avoid_ch_ie->channel); 339 sap_check_n_add_overlapped_chnls(sap_ctx, 340 avoid_ch_ie->channel); 341 /* 342 * Mark weight of these channel present in IE to MAX 343 * so that ACS logic will to avoid thse channels 344 */ 345 for (i = 0; i < spect_info->num_ch; i++) { 346 if (spect_ch[i].chan_freq != chan_freq) 347 continue; 348 /* 349 * weight is set more than max so that, 350 * in the case of other channels being 351 * assigned max weight due to noise, 352 * they may be preferred over channels 353 * with Q2Q IE. 354 */ 355 spect_ch[i].weight = SAP_ACS_WEIGHT_MAX + 1; 356 spect_ch[i].weight_copy = 357 SAP_ACS_WEIGHT_MAX + 1; 358 break; 359 } 360 } 361 362 qdf_list_peek_next(scan_list, cur_lst, &next_lst); 363 cur_lst = next_lst; 364 next_lst = NULL; 365 } 366 } 367 #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ 368 369 /** 370 * sap_select_preferred_channel_from_channel_list() - to calc best channel 371 * @best_ch_freq: best chan freq already calculated among all the channels 372 * @sap_ctx: sap context 373 * @spectinfo_param: Pointer to sap_sel_ch_info structure 374 * 375 * This function calculates the best channel among the configured channel list. 376 * If channel list not configured then returns the best channel calculated 377 * among all the channel list. 378 * 379 * Return: uint32_t best channel frequency 380 */ 381 static 382 uint32_t sap_select_preferred_channel_from_channel_list(uint32_t best_ch_freq, 383 struct sap_context *sap_ctx, 384 struct sap_sel_ch_info *spectinfo_param) 385 { 386 /* 387 * If Channel List is not Configured don't do anything 388 * Else return the Best Channel from the Channel List 389 */ 390 if ((!sap_ctx->acs_cfg->freq_list) || 391 (!spectinfo_param) || 392 (!sap_ctx->acs_cfg->ch_list_count)) 393 return best_ch_freq; 394 395 if (wlansap_is_channel_present_in_acs_list(best_ch_freq, 396 sap_ctx->acs_cfg->freq_list, 397 sap_ctx->acs_cfg->ch_list_count)) 398 return best_ch_freq; 399 400 return SAP_CHANNEL_NOT_SELECTED; 401 } 402 403 /** 404 * sap_chan_sel_init() - Initialize channel select 405 * @mac: Opaque handle to the global MAC context 406 * @ch_info_params: Pointer to tSapChSelSpectInfo structure 407 * @sap_ctx: Pointer to SAP Context 408 * @ignore_acs_range: Whether ignore channel which is out of acs range 409 * 410 * Function sap_chan_sel_init allocates the memory, initializes the 411 * structures used by the channel selection algorithm 412 * 413 * Return: bool Success or FAIL 414 */ 415 static bool sap_chan_sel_init(struct mac_context *mac, 416 struct sap_sel_ch_info *ch_info_params, 417 struct sap_context *sap_ctx, 418 bool ignore_acs_range) 419 { 420 struct sap_ch_info *ch_info = NULL; 421 uint32_t *ch_list = NULL; 422 uint16_t num_chan = 0; 423 bool include_dfs_ch = true; 424 uint8_t sta_sap_scc_on_dfs_chnl_config_value; 425 bool ch_support_puncture; 426 427 ch_info_params->num_ch = 428 mac->scan.base_channels.numChannels; 429 430 /* Allocate memory for weight computation of 2.4GHz */ 431 ch_info = qdf_mem_malloc((ch_info_params->num_ch) * 432 sizeof(*ch_info)); 433 if (!ch_info) 434 return false; 435 436 /* Initialize the pointers in the DfsParams to the allocated memory */ 437 ch_info_params->ch_info = ch_info; 438 439 ch_list = mac->scan.base_channels.channel_freq_list; 440 441 policy_mgr_get_sta_sap_scc_on_dfs_chnl(mac->psoc, 442 &sta_sap_scc_on_dfs_chnl_config_value); 443 #if defined(FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE) 444 if (sap_ctx->dfs_ch_disable == true) 445 include_dfs_ch = false; 446 #endif 447 if (!mac->mlme_cfg->dfs_cfg.dfs_master_capable || 448 ACS_DFS_MODE_DISABLE == sap_ctx->dfs_mode) 449 include_dfs_ch = false; 450 451 /* Fill the channel number in the spectrum in the operating freq band */ 452 for (num_chan = 0; 453 num_chan < ch_info_params->num_ch; 454 num_chan++, ch_list++, ch_info++) { 455 ch_support_puncture = false; 456 ch_info->chan_freq = *ch_list; 457 /* Initialise for all channels */ 458 ch_info->rssi_agr = SOFTAP_MIN_RSSI; 459 /* Initialise max ACS weight for all channels */ 460 ch_info->weight = SAP_ACS_WEIGHT_MAX; 461 462 /* check if the channel is in NOL denylist */ 463 if (sap_dfs_is_channel_in_nol_list( 464 sap_ctx, *ch_list, 465 PHY_SINGLE_CHANNEL_CENTERED)) { 466 if (sap_acs_is_puncture_applicable(sap_ctx->acs_cfg)) { 467 sap_debug_rl("freq %d is in NOL list, can be punctured", 468 *ch_list); 469 ch_support_puncture = true; 470 } else { 471 sap_debug_rl("freq %d is in NOL list", 472 *ch_list); 473 continue; 474 } 475 } 476 477 if (!include_dfs_ch || 478 (sta_sap_scc_on_dfs_chnl_config_value == 479 PM_STA_SAP_ON_DFS_MASTER_MODE_DISABLED && 480 !policy_mgr_is_sta_sap_scc(mac->psoc, 481 ch_info->chan_freq))) { 482 if (wlan_reg_is_dfs_for_freq(mac->pdev, 483 ch_info->chan_freq)) { 484 sap_debug("DFS Ch %d not considered for ACS. include_dfs_ch %u, sta_sap_scc_on_dfs_chnl_config_value %d", 485 *ch_list, include_dfs_ch, 486 sta_sap_scc_on_dfs_chnl_config_value); 487 continue; 488 } 489 } 490 491 if (!policy_mgr_is_sap_freq_allowed(mac->psoc, *ch_list)) { 492 if (sap_acs_is_puncture_applicable(sap_ctx->acs_cfg)) { 493 sap_info("freq %d is not allowed, can be punctured", 494 *ch_list); 495 ch_support_puncture = true; 496 } else { 497 sap_info("Skip freq %d", *ch_list); 498 continue; 499 } 500 } 501 502 /* OFDM rates are not supported on frequency 2484 */ 503 if (*ch_list == 2484 && 504 eCSR_DOT11_MODE_11b != sap_ctx->phyMode) 505 continue; 506 507 /* Skip DSRC channels */ 508 if (wlan_reg_is_dsrc_freq(ch_info->chan_freq)) 509 continue; 510 511 /* Skip indoor channels for non-scc indoor scenario*/ 512 if (!policy_mgr_is_sap_go_interface_allowed_on_indoor( 513 mac->pdev, 514 sap_ctx->sessionId, 515 *ch_list)) { 516 sap_debug("Do not allow SAP on indoor frequency %u", 517 *ch_list); 518 continue; 519 } 520 521 /* 522 * Skip the channels which are not in ACS config from user 523 * space 524 */ 525 if (!ignore_acs_range && 526 !wlansap_is_channel_present_in_acs_list( 527 *ch_list, sap_ctx->acs_cfg->freq_list, 528 sap_ctx->acs_cfg->ch_list_count)) { 529 if (wlansap_is_channel_present_in_acs_list( 530 ch_info->chan_freq, 531 sap_ctx->acs_cfg->master_freq_list, 532 sap_ctx->acs_cfg->master_ch_list_count)) 533 ch_info->weight = SAP_ACS_WEIGHT_ADJUSTABLE; 534 continue; 535 } 536 537 ch_info->valid = true; 538 if (!ch_support_puncture) 539 ch_info->weight = 0; 540 } 541 542 return true; 543 } 544 545 /** 546 * sapweight_rssi_count() - calculates the channel weight due to rssi 547 * and data count(here number of BSS observed) 548 * @sap_ctx : Softap context 549 * @rssi : Max signal strength received from a BSS for the channel 550 * @count : Number of BSS observed in the channel 551 * 552 * Return: uint32_t Calculated channel weight based on above two 553 */ 554 static 555 uint32_t sapweight_rssi_count(struct sap_context *sap_ctx, int8_t rssi, 556 uint16_t count) 557 { 558 int32_t rssiWeight = 0; 559 int32_t countWeight = 0; 560 uint32_t rssicountWeight = 0; 561 uint8_t softap_rssi_weight_cfg, softap_count_weight_cfg; 562 uint8_t softap_rssi_weight_local, softap_count_weight_local; 563 564 softap_rssi_weight_cfg = 565 ACS_WEIGHT_SOFTAP_RSSI_CFG(sap_ctx->auto_channel_select_weight); 566 567 softap_count_weight_cfg = 568 ACS_WEIGHT_SOFTAP_COUNT_CFG(sap_ctx->auto_channel_select_weight); 569 570 softap_rssi_weight_local = 571 ACS_WEIGHT_CFG_TO_LOCAL(sap_ctx->auto_channel_select_weight, 572 softap_rssi_weight_cfg); 573 574 softap_count_weight_local = 575 ACS_WEIGHT_CFG_TO_LOCAL(sap_ctx->auto_channel_select_weight, 576 softap_count_weight_cfg); 577 578 /* Weight from RSSI */ 579 rssiWeight = ACS_WEIGHT_COMPUTE(sap_ctx->auto_channel_select_weight, 580 softap_rssi_weight_cfg, 581 rssi - SOFTAP_MIN_RSSI, 582 SOFTAP_MAX_RSSI - SOFTAP_MIN_RSSI); 583 584 if (rssiWeight > softap_rssi_weight_local) 585 rssiWeight = softap_rssi_weight_local; 586 587 else if (rssiWeight < 0) 588 rssiWeight = 0; 589 590 /* Weight from data count */ 591 countWeight = ACS_WEIGHT_COMPUTE(sap_ctx->auto_channel_select_weight, 592 softap_count_weight_cfg, 593 count - SOFTAP_MIN_COUNT, 594 SOFTAP_MAX_COUNT - SOFTAP_MIN_COUNT); 595 596 if (countWeight > softap_count_weight_local) 597 countWeight = softap_count_weight_local; 598 599 rssicountWeight = rssiWeight + countWeight; 600 601 return rssicountWeight; 602 } 603 604 /** 605 * sap_get_channel_status() - get channel info via channel number 606 * @p_mac: Pointer to Global MAC structure 607 * @chan_freq: channel frequency 608 * 609 * Return: chan status info 610 */ 611 static struct channel_status *sap_get_channel_status 612 (struct mac_context *p_mac, uint32_t chan_freq) 613 { 614 if (!p_mac->sap.acs_with_more_param) 615 return NULL; 616 617 return ucfg_mc_cp_stats_get_channel_status(p_mac->pdev, chan_freq); 618 } 619 620 #ifndef WLAN_FEATURE_SAP_ACS_OPTIMIZE 621 /** 622 * sap_clear_channel_status() - clear chan info 623 * @p_mac: Pointer to Global MAC structure 624 * 625 * Return: none 626 */ 627 static void sap_clear_channel_status(struct mac_context *p_mac) 628 { 629 if (!p_mac->sap.acs_with_more_param) 630 return; 631 632 ucfg_mc_cp_stats_clear_channel_status(p_mac->pdev); 633 } 634 #else 635 static void sap_clear_channel_status(struct mac_context *p_mac) 636 { 637 } 638 #endif 639 640 /** 641 * sap_weight_channel_noise_floor() - compute noise floor weight 642 * @sap_ctx: sap context 643 * @channel_stat: Pointer to chan status info 644 * 645 * Return: channel noise floor weight 646 */ 647 static uint32_t sap_weight_channel_noise_floor(struct sap_context *sap_ctx, 648 struct channel_status 649 *channel_stat) 650 { 651 uint32_t noise_floor_weight; 652 uint8_t softap_nf_weight_cfg; 653 uint8_t softap_nf_weight_local; 654 655 softap_nf_weight_cfg = 656 ACS_WEIGHT_SOFTAP_NOISE_FLOOR_CFG 657 (sap_ctx->auto_channel_select_weight); 658 659 softap_nf_weight_local = 660 ACS_WEIGHT_CFG_TO_LOCAL(sap_ctx->auto_channel_select_weight, 661 softap_nf_weight_cfg); 662 663 if (!channel_stat || channel_stat->channel_freq == 0) 664 return softap_nf_weight_local; 665 666 noise_floor_weight = (channel_stat->noise_floor == 0) ? 0 : 667 (ACS_WEIGHT_COMPUTE( 668 sap_ctx->auto_channel_select_weight, 669 softap_nf_weight_cfg, 670 channel_stat->noise_floor - 671 SOFTAP_MIN_NF, 672 SOFTAP_MAX_NF - SOFTAP_MIN_NF)); 673 674 if (noise_floor_weight > softap_nf_weight_local) 675 noise_floor_weight = softap_nf_weight_local; 676 677 sap_debug("nf=%d, nfwc=%d, nfwl=%d, nfw=%d freq=%d", 678 channel_stat->noise_floor, 679 softap_nf_weight_cfg, softap_nf_weight_local, 680 noise_floor_weight, channel_stat->channel_freq); 681 682 return noise_floor_weight; 683 } 684 685 /** 686 * sap_weight_channel_free() - compute channel free weight 687 * @sap_ctx: sap context 688 * @channel_stat: Pointer to chan status info 689 * 690 * Return: channel free weight 691 */ 692 static uint32_t sap_weight_channel_free(struct sap_context *sap_ctx, 693 struct channel_status 694 *channel_stat) 695 { 696 uint32_t channel_free_weight; 697 uint8_t softap_channel_free_weight_cfg; 698 uint8_t softap_channel_free_weight_local; 699 uint32_t rx_clear_count = 0; 700 uint32_t cycle_count = 0; 701 702 softap_channel_free_weight_cfg = 703 ACS_WEIGHT_SOFTAP_CHANNEL_FREE_CFG 704 (sap_ctx->auto_channel_select_weight); 705 706 softap_channel_free_weight_local = 707 ACS_WEIGHT_CFG_TO_LOCAL(sap_ctx->auto_channel_select_weight, 708 softap_channel_free_weight_cfg); 709 710 if (!channel_stat || channel_stat->channel_freq == 0) 711 return softap_channel_free_weight_local; 712 713 rx_clear_count = channel_stat->rx_clear_count - 714 channel_stat->tx_frame_count - 715 channel_stat->rx_frame_count; 716 cycle_count = channel_stat->cycle_count; 717 718 /* LSH 4, otherwise it is always 0. */ 719 channel_free_weight = (cycle_count == 0) ? 0 : 720 (ACS_WEIGHT_COMPUTE( 721 sap_ctx->auto_channel_select_weight, 722 softap_channel_free_weight_cfg, 723 ((rx_clear_count << 8) + 724 (cycle_count >> 1))/cycle_count - 725 (SOFTAP_MIN_CHNFREE << 8), 726 (SOFTAP_MAX_CHNFREE - 727 SOFTAP_MIN_CHNFREE) << 8)); 728 729 if (channel_free_weight > softap_channel_free_weight_local) 730 channel_free_weight = softap_channel_free_weight_local; 731 732 sap_debug_rl("rcc=%d, cc=%d, tc=%d, rc=%d, cfwc=%d, cfwl=%d, cfw=%d", 733 rx_clear_count, cycle_count, 734 channel_stat->tx_frame_count, 735 channel_stat->rx_frame_count, 736 softap_channel_free_weight_cfg, 737 softap_channel_free_weight_local, 738 channel_free_weight); 739 740 return channel_free_weight; 741 } 742 743 /** 744 * sap_weight_channel_txpwr_range() - compute channel tx power range weight 745 * @sap_ctx: sap context 746 * @channel_stat: Pointer to chan status info 747 * 748 * Return: tx power range weight 749 */ 750 static uint32_t sap_weight_channel_txpwr_range(struct sap_context *sap_ctx, 751 struct channel_status 752 *channel_stat) 753 { 754 uint32_t txpwr_weight_low_speed; 755 uint8_t softap_txpwr_range_weight_cfg; 756 uint8_t softap_txpwr_range_weight_local; 757 758 softap_txpwr_range_weight_cfg = 759 ACS_WEIGHT_SOFTAP_TX_POWER_RANGE_CFG 760 (sap_ctx->auto_channel_select_weight); 761 762 softap_txpwr_range_weight_local = 763 ACS_WEIGHT_CFG_TO_LOCAL(sap_ctx->auto_channel_select_weight, 764 softap_txpwr_range_weight_cfg); 765 766 if (!channel_stat || channel_stat->channel_freq == 0) 767 return softap_txpwr_range_weight_local; 768 769 770 txpwr_weight_low_speed = (channel_stat->chan_tx_pwr_range == 0) ? 0 : 771 (ACS_WEIGHT_COMPUTE( 772 sap_ctx->auto_channel_select_weight, 773 softap_txpwr_range_weight_cfg, 774 SOFTAP_MAX_TXPWR - 775 channel_stat->chan_tx_pwr_range, 776 SOFTAP_MAX_TXPWR - SOFTAP_MIN_TXPWR)); 777 778 if (txpwr_weight_low_speed > softap_txpwr_range_weight_local) 779 txpwr_weight_low_speed = softap_txpwr_range_weight_local; 780 781 sap_debug_rl("tpr=%d, tprwc=%d, tprwl=%d, tprw=%d", 782 channel_stat->chan_tx_pwr_range, 783 softap_txpwr_range_weight_cfg, 784 softap_txpwr_range_weight_local, 785 txpwr_weight_low_speed); 786 787 return txpwr_weight_low_speed; 788 } 789 790 /** 791 * sap_weight_channel_txpwr_tput() - compute channel tx power 792 * throughput weight 793 * @sap_ctx: sap context 794 * @channel_stat: Pointer to chan status info 795 * 796 * Return: tx power throughput weight 797 */ 798 static uint32_t sap_weight_channel_txpwr_tput(struct sap_context *sap_ctx, 799 struct channel_status 800 *channel_stat) 801 { 802 uint32_t txpwr_weight_high_speed; 803 uint8_t softap_txpwr_tput_weight_cfg; 804 uint8_t softap_txpwr_tput_weight_local; 805 806 softap_txpwr_tput_weight_cfg = 807 ACS_WEIGHT_SOFTAP_TX_POWER_THROUGHPUT_CFG 808 (sap_ctx->auto_channel_select_weight); 809 810 softap_txpwr_tput_weight_local = 811 ACS_WEIGHT_CFG_TO_LOCAL(sap_ctx->auto_channel_select_weight, 812 softap_txpwr_tput_weight_cfg); 813 814 if (!channel_stat || channel_stat->channel_freq == 0) 815 return softap_txpwr_tput_weight_local; 816 817 txpwr_weight_high_speed = (channel_stat->chan_tx_pwr_throughput == 0) 818 ? 0 : (ACS_WEIGHT_COMPUTE( 819 sap_ctx->auto_channel_select_weight, 820 softap_txpwr_tput_weight_cfg, 821 SOFTAP_MAX_TXPWR - 822 channel_stat->chan_tx_pwr_throughput, 823 SOFTAP_MAX_TXPWR - SOFTAP_MIN_TXPWR)); 824 825 if (txpwr_weight_high_speed > softap_txpwr_tput_weight_local) 826 txpwr_weight_high_speed = softap_txpwr_tput_weight_local; 827 828 sap_debug_rl("tpt=%d, tptwc=%d, tptwl=%d, tptw=%d", 829 channel_stat->chan_tx_pwr_throughput, 830 softap_txpwr_tput_weight_cfg, 831 softap_txpwr_tput_weight_local, 832 txpwr_weight_high_speed); 833 834 return txpwr_weight_high_speed; 835 } 836 837 /** 838 * sap_weight_channel_status() - compute chan status weight 839 * @sap_ctx: sap context 840 * @channel_stat: Pointer to chan status info 841 * 842 * Return: chan status weight 843 */ 844 static 845 uint32_t sap_weight_channel_status(struct sap_context *sap_ctx, 846 struct channel_status *channel_stat) 847 { 848 return sap_weight_channel_noise_floor(sap_ctx, channel_stat) + 849 sap_weight_channel_free(sap_ctx, channel_stat) + 850 sap_weight_channel_txpwr_range(sap_ctx, channel_stat) + 851 sap_weight_channel_txpwr_tput(sap_ctx, channel_stat); 852 } 853 854 /** 855 * sap_update_rssi_bsscount() - updates bss count and rssi effect. 856 * 857 * @ch_info: Channel Information 858 * @offset: Channel Offset 859 * @sap_24g: Channel is in 2.4G or 5G 860 * @ch_start: the start of channel array 861 * @ch_end: the end of channel array 862 * 863 * sap_update_rssi_bsscount updates bss count and rssi effect based 864 * on the channel offset. 865 * 866 * Return: None. 867 */ 868 869 static void sap_update_rssi_bsscount(struct sap_ch_info *ch_info, 870 int32_t offset, bool sap_24g, 871 struct sap_ch_info *ch_start, 872 struct sap_ch_info *ch_end) 873 { 874 struct sap_ch_info *chan_info = NULL; 875 int32_t rssi, rsssi_effect; 876 877 chan_info = (ch_info + offset); 878 if (chan_info && chan_info >= ch_start && 879 chan_info < ch_end) { 880 if (!WLAN_REG_IS_SAME_BAND_FREQS(ch_info->chan_freq, 881 chan_info->chan_freq)) 882 return; 883 ++chan_info->bss_count; 884 switch (offset) { 885 case -1: 886 case 1: 887 rsssi_effect = sap_24g ? 888 SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY : 889 SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; 890 break; 891 case -2: 892 case 2: 893 rsssi_effect = sap_24g ? 894 SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY : 895 SAP_SUBBAND2_RSSI_EFFECT_PRIMARY; 896 break; 897 case -3: 898 case 3: 899 rsssi_effect = sap_24g ? 900 SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY : 901 SAP_SUBBAND3_RSSI_EFFECT_PRIMARY; 902 break; 903 case -4: 904 case 4: 905 rsssi_effect = sap_24g ? 906 SAP_24GHZ_FOURTH_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY : 907 SAP_SUBBAND4_RSSI_EFFECT_PRIMARY; 908 break; 909 case -5: 910 case 5: 911 rsssi_effect = SAP_SUBBAND5_RSSI_EFFECT_PRIMARY; 912 break; 913 case -6: 914 case 6: 915 rsssi_effect = SAP_SUBBAND6_RSSI_EFFECT_PRIMARY; 916 break; 917 case -7: 918 case 7: 919 rsssi_effect = SAP_SUBBAND7_RSSI_EFFECT_PRIMARY; 920 break; 921 default: 922 rsssi_effect = 0; 923 break; 924 } 925 926 rssi = ch_info->rssi_agr + rsssi_effect; 927 if (IS_RSSI_VALID(chan_info->rssi_agr, rssi)) 928 chan_info->rssi_agr = rssi; 929 if (chan_info->rssi_agr < SOFTAP_MIN_RSSI) 930 chan_info->rssi_agr = SOFTAP_MIN_RSSI; 931 } 932 } 933 934 /** 935 * sap_update_rssi_bsscount_vht_5G() - updates bss count and rssi effect. 936 * 937 * @spect_ch: Channel Information 938 * @offset: Channel Offset 939 * @num_ch: no.of channels 940 * @ch_start: the start of spect ch array 941 * @ch_end: the end of spect ch array 942 * 943 * sap_update_rssi_bsscount_vht_5G updates bss count and rssi effect based 944 * on the channel offset. 945 * 946 * Return: None. 947 */ 948 949 static void sap_update_rssi_bsscount_vht_5G( 950 struct sap_ch_info *spect_ch, 951 int32_t offset, 952 uint16_t num_ch, 953 struct sap_ch_info *ch_start, 954 struct sap_ch_info *ch_end) 955 { 956 int32_t ch_offset; 957 uint16_t i, cnt; 958 959 if (!offset) 960 return; 961 if (offset > 0) 962 cnt = num_ch; 963 else 964 cnt = num_ch + 1; 965 for (i = 0; i < cnt; i++) { 966 ch_offset = offset + i; 967 if (ch_offset == 0) 968 continue; 969 sap_update_rssi_bsscount(spect_ch, ch_offset, false, 970 ch_start, ch_end); 971 } 972 } 973 /** 974 * sap_interference_rssi_count_5G() - sap_interference_rssi_count 975 * considers the Adjacent channel rssi and 976 * data count(here number of BSS observed) 977 * @spect_ch: Channel Information 978 * @chan_width: Channel width parsed from beacon IE 979 * @sec_chan_offset: Secondary Channel Offset 980 * @ch_freq0: frequency_0 for the given channel. 981 * @ch_freq1: frequency_1 for the given channel. 982 * @op_chan_freq: Operating channel frequency. 983 * @ch_start: the start of spect ch array 984 * @ch_end: the end of spect ch array 985 * 986 * sap_interference_rssi_count_5G considers the Adjacent channel rssi 987 * and data count(here number of BSS observed) 988 * 989 * Return: NA. 990 */ 991 992 static void sap_interference_rssi_count_5G(struct sap_ch_info *spect_ch, 993 uint16_t chan_width, 994 uint16_t sec_chan_offset, 995 uint32_t ch_freq0, 996 uint32_t ch_freq1, 997 uint32_t op_chan_freq, 998 struct sap_ch_info *ch_start, 999 struct sap_ch_info *ch_end) 1000 { 1001 uint16_t num_ch; 1002 int32_t offset = 0; 1003 1004 sap_debug("freq = %d, ch width = %d, ch_freq0 = %d ch_freq1 = %d", 1005 op_chan_freq, chan_width, ch_freq0, ch_freq1); 1006 1007 switch (chan_width) { 1008 case eHT_CHANNEL_WIDTH_40MHZ: 1009 switch (sec_chan_offset) { 1010 /* Above the Primary Channel */ 1011 case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: 1012 sap_update_rssi_bsscount(spect_ch, 1, false, 1013 ch_start, ch_end); 1014 return; 1015 1016 /* Below the Primary channel */ 1017 case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: 1018 sap_update_rssi_bsscount(spect_ch, -1, false, 1019 ch_start, ch_end); 1020 return; 1021 } 1022 return; 1023 case eHT_CHANNEL_WIDTH_80MHZ: 1024 case eHT_CHANNEL_WIDTH_80P80MHZ: 1025 num_ch = 3; 1026 if ((ch_freq0 - op_chan_freq) == 30) { 1027 offset = 1; 1028 } else if ((ch_freq0 - op_chan_freq) == 10) { 1029 offset = -1; 1030 } else if ((ch_freq0 - op_chan_freq) == -10) { 1031 offset = -2; 1032 } else if ((ch_freq0 - op_chan_freq) == -30) { 1033 offset = -3; 1034 } 1035 break; 1036 case eHT_CHANNEL_WIDTH_160MHZ: 1037 num_ch = 7; 1038 if ((ch_freq0 - op_chan_freq) == 70) 1039 offset = 1; 1040 else if ((ch_freq0 - op_chan_freq) == 50) 1041 offset = -1; 1042 else if ((ch_freq0 - op_chan_freq) == 30) 1043 offset = -2; 1044 else if ((ch_freq0 - op_chan_freq) == 10) 1045 offset = -3; 1046 else if ((ch_freq0 - op_chan_freq) == -10) 1047 offset = -4; 1048 else if ((ch_freq0 - op_chan_freq) == -30) 1049 offset = -5; 1050 else if ((ch_freq0 - op_chan_freq) == -50) 1051 offset = -6; 1052 else if ((ch_freq0 - op_chan_freq) == -70) 1053 offset = -7; 1054 break; 1055 default: 1056 return; 1057 } 1058 1059 sap_update_rssi_bsscount_vht_5G(spect_ch, offset, num_ch, ch_start, 1060 ch_end); 1061 } 1062 1063 /** 1064 * sap_interference_rssi_count() - sap_interference_rssi_count 1065 * considers the Adjacent channel rssi 1066 * and data count(here number of BSS observed) 1067 * @spect_ch: Channel Information 1068 * @ch_start: the start of spect ch array 1069 * @ch_end: the end of spect ch array 1070 * @mac: Opaque handle to the global MAC context 1071 * 1072 * sap_interference_rssi_count considers the Adjacent channel rssi 1073 * and data count(here number of BSS observed) 1074 * 1075 * Return: None. 1076 */ 1077 1078 static void sap_interference_rssi_count(struct sap_ch_info *spect_ch, 1079 struct sap_ch_info *ch_start, 1080 struct sap_ch_info *ch_end, 1081 struct mac_context *mac) 1082 { 1083 if (!spect_ch) { 1084 sap_err("spect_ch is NULL"); 1085 return; 1086 } 1087 1088 switch (wlan_reg_freq_to_chan(mac->pdev, spect_ch->chan_freq)) { 1089 case CHANNEL_1: 1090 sap_update_rssi_bsscount(spect_ch, 1, true, 1091 ch_start, ch_end); 1092 sap_update_rssi_bsscount(spect_ch, 2, true, 1093 ch_start, ch_end); 1094 sap_update_rssi_bsscount(spect_ch, 3, true, 1095 ch_start, ch_end); 1096 sap_update_rssi_bsscount(spect_ch, 4, true, 1097 ch_start, ch_end); 1098 break; 1099 1100 case CHANNEL_2: 1101 sap_update_rssi_bsscount(spect_ch, -1, true, 1102 ch_start, ch_end); 1103 sap_update_rssi_bsscount(spect_ch, 1, true, 1104 ch_start, ch_end); 1105 sap_update_rssi_bsscount(spect_ch, 2, true, 1106 ch_start, ch_end); 1107 sap_update_rssi_bsscount(spect_ch, 3, true, 1108 ch_start, ch_end); 1109 sap_update_rssi_bsscount(spect_ch, 4, true, 1110 ch_start, ch_end); 1111 break; 1112 case CHANNEL_3: 1113 sap_update_rssi_bsscount(spect_ch, -2, true, 1114 ch_start, ch_end); 1115 sap_update_rssi_bsscount(spect_ch, -1, true, 1116 ch_start, ch_end); 1117 sap_update_rssi_bsscount(spect_ch, 1, true, 1118 ch_start, ch_end); 1119 sap_update_rssi_bsscount(spect_ch, 2, true, 1120 ch_start, ch_end); 1121 sap_update_rssi_bsscount(spect_ch, 3, true, 1122 ch_start, ch_end); 1123 sap_update_rssi_bsscount(spect_ch, 4, true, 1124 ch_start, ch_end); 1125 break; 1126 case CHANNEL_4: 1127 sap_update_rssi_bsscount(spect_ch, -3, true, 1128 ch_start, ch_end); 1129 sap_update_rssi_bsscount(spect_ch, -2, true, 1130 ch_start, ch_end); 1131 sap_update_rssi_bsscount(spect_ch, -1, true, 1132 ch_start, ch_end); 1133 sap_update_rssi_bsscount(spect_ch, 1, true, 1134 ch_start, ch_end); 1135 sap_update_rssi_bsscount(spect_ch, 2, true, 1136 ch_start, ch_end); 1137 sap_update_rssi_bsscount(spect_ch, 3, true, 1138 ch_start, ch_end); 1139 sap_update_rssi_bsscount(spect_ch, 4, true, 1140 ch_start, ch_end); 1141 break; 1142 1143 case CHANNEL_5: 1144 case CHANNEL_6: 1145 case CHANNEL_7: 1146 case CHANNEL_8: 1147 case CHANNEL_9: 1148 case CHANNEL_10: 1149 sap_update_rssi_bsscount(spect_ch, -4, true, 1150 ch_start, ch_end); 1151 sap_update_rssi_bsscount(spect_ch, -3, true, 1152 ch_start, ch_end); 1153 sap_update_rssi_bsscount(spect_ch, -2, true, 1154 ch_start, ch_end); 1155 sap_update_rssi_bsscount(spect_ch, -1, true, 1156 ch_start, ch_end); 1157 sap_update_rssi_bsscount(spect_ch, 1, true, 1158 ch_start, ch_end); 1159 sap_update_rssi_bsscount(spect_ch, 2, true, 1160 ch_start, ch_end); 1161 sap_update_rssi_bsscount(spect_ch, 3, true, 1162 ch_start, ch_end); 1163 sap_update_rssi_bsscount(spect_ch, 4, true, 1164 ch_start, ch_end); 1165 break; 1166 1167 case CHANNEL_11: 1168 sap_update_rssi_bsscount(spect_ch, -4, true, 1169 ch_start, ch_end); 1170 sap_update_rssi_bsscount(spect_ch, -3, true, 1171 ch_start, ch_end); 1172 sap_update_rssi_bsscount(spect_ch, -2, true, 1173 ch_start, ch_end); 1174 sap_update_rssi_bsscount(spect_ch, -1, true, 1175 ch_start, ch_end); 1176 sap_update_rssi_bsscount(spect_ch, 1, true, 1177 ch_start, ch_end); 1178 sap_update_rssi_bsscount(spect_ch, 2, true, 1179 ch_start, ch_end); 1180 sap_update_rssi_bsscount(spect_ch, 3, true, 1181 ch_start, ch_end); 1182 break; 1183 1184 case CHANNEL_12: 1185 sap_update_rssi_bsscount(spect_ch, -4, true, 1186 ch_start, ch_end); 1187 sap_update_rssi_bsscount(spect_ch, -3, true, 1188 ch_start, ch_end); 1189 sap_update_rssi_bsscount(spect_ch, -2, true, 1190 ch_start, ch_end); 1191 sap_update_rssi_bsscount(spect_ch, -1, true, 1192 ch_start, ch_end); 1193 sap_update_rssi_bsscount(spect_ch, 1, true, 1194 ch_start, ch_end); 1195 sap_update_rssi_bsscount(spect_ch, 2, true, 1196 ch_start, ch_end); 1197 break; 1198 1199 case CHANNEL_13: 1200 sap_update_rssi_bsscount(spect_ch, -4, true, 1201 ch_start, ch_end); 1202 sap_update_rssi_bsscount(spect_ch, -3, true, 1203 ch_start, ch_end); 1204 sap_update_rssi_bsscount(spect_ch, -2, true, 1205 ch_start, ch_end); 1206 sap_update_rssi_bsscount(spect_ch, -1, true, 1207 ch_start, ch_end); 1208 sap_update_rssi_bsscount(spect_ch, 1, true, 1209 ch_start, ch_end); 1210 break; 1211 1212 case CHANNEL_14: 1213 sap_update_rssi_bsscount(spect_ch, -4, true, 1214 ch_start, ch_end); 1215 sap_update_rssi_bsscount(spect_ch, -3, true, 1216 ch_start, ch_end); 1217 sap_update_rssi_bsscount(spect_ch, -2, true, 1218 ch_start, ch_end); 1219 sap_update_rssi_bsscount(spect_ch, -1, true, 1220 ch_start, ch_end); 1221 break; 1222 1223 default: 1224 break; 1225 } 1226 } 1227 1228 /** 1229 * ch_in_pcl() - Is channel in the Preferred Channel List (PCL) 1230 * @sap_ctx: SAP context which contains the current PCL 1231 * @ch_freq: Input channel number to be checked 1232 * 1233 * Check if a channel is in the preferred channel list 1234 * 1235 * Return: True if channel is in PCL, else False 1236 */ 1237 static bool ch_in_pcl(struct sap_context *sap_ctx, uint32_t ch_freq) 1238 { 1239 uint32_t i; 1240 1241 for (i = 0; i < sap_ctx->acs_cfg->pcl_ch_count; i++) { 1242 if (ch_freq == sap_ctx->acs_cfg->pcl_chan_freq[i]) 1243 return true; 1244 } 1245 1246 return false; 1247 } 1248 1249 /** 1250 * sap_upd_chan_spec_params() - sap_upd_chan_spec_params 1251 * updates channel parameters obtained from Beacon 1252 * @scan_entry: Beacon structure populated by scan 1253 * @ch_width: Channel width 1254 * @sec_ch_offset: Secondary Channel Offset 1255 * @center_freq0: Central frequency 0 for the given channel 1256 * @center_freq1: Central frequency 1 for the given channel 1257 * 1258 * sap_upd_chan_spec_params updates the spectrum channels based on the 1259 * scan_entry 1260 * 1261 * Return: NA. 1262 */ 1263 static void 1264 sap_upd_chan_spec_params(struct scan_cache_node *scan_entry, 1265 tSirMacHTChannelWidth *ch_width, 1266 uint16_t *sec_ch_offset, 1267 uint32_t *center_freq0, 1268 uint32_t *center_freq1) 1269 { 1270 enum wlan_phymode phy_mode; 1271 struct channel_info *chan; 1272 1273 phy_mode = util_scan_entry_phymode(scan_entry->entry); 1274 chan = util_scan_entry_channel(scan_entry->entry); 1275 1276 if (IS_WLAN_PHYMODE_160MHZ(phy_mode)) { 1277 if (phy_mode == WLAN_PHYMODE_11AC_VHT80_80 || 1278 phy_mode == WLAN_PHYMODE_11AXA_HE80_80) { 1279 *ch_width = eHT_CHANNEL_WIDTH_80P80MHZ; 1280 *center_freq0 = chan->cfreq0; 1281 *center_freq1 = chan->cfreq1; 1282 } else { 1283 *ch_width = eHT_CHANNEL_WIDTH_160MHZ; 1284 if (chan->cfreq1) 1285 *center_freq0 = chan->cfreq1; 1286 else 1287 *center_freq0 = chan->cfreq0; 1288 } 1289 1290 } else if (IS_WLAN_PHYMODE_80MHZ(phy_mode)) { 1291 *ch_width = eHT_CHANNEL_WIDTH_80MHZ; 1292 *center_freq0 = chan->cfreq0; 1293 } else if (IS_WLAN_PHYMODE_40MHZ(phy_mode)) { 1294 if (chan->cfreq0 > chan->chan_freq) 1295 *sec_ch_offset = PHY_DOUBLE_CHANNEL_LOW_PRIMARY; 1296 else 1297 *sec_ch_offset = PHY_DOUBLE_CHANNEL_HIGH_PRIMARY; 1298 *ch_width = eHT_CHANNEL_WIDTH_40MHZ; 1299 *center_freq0 = chan->cfreq0; 1300 } else { 1301 *ch_width = eHT_CHANNEL_WIDTH_20MHZ; 1302 } 1303 } 1304 1305 /** 1306 * sap_weight_channel_reg_max_power() - API to calculate channel weight of max 1307 * tx power allowed 1308 * @sap_ctx: SAP context 1309 * @freq: channel frequency 1310 * 1311 * This function get channel tx power limit from secondary current channel 1312 * list and calculate weight with power factor configure 1313 * 1314 * Return: channel power weight 1315 */ 1316 static uint32_t 1317 sap_weight_channel_reg_max_power(struct sap_context *sap_ctx, qdf_freq_t freq) 1318 { 1319 struct wlan_objmgr_pdev *pdev; 1320 int32_t power_weight; 1321 uint8_t power_weight_cfg, power_weight_local; 1322 uint16_t eirp_pwr, psd_pwr; 1323 bool is_psd; 1324 uint32_t chan_flags; 1325 QDF_STATUS status; 1326 1327 power_weight_cfg = ACS_WEIGHT_SOFTAP_REG_MAX_POWER_CFG( 1328 sap_ctx->auto_channel_select_weight); 1329 1330 /* reg max power factor not configure, return zero weight */ 1331 if (!power_weight_cfg) 1332 return 0; 1333 1334 power_weight_local = ACS_WEIGHT_CFG_TO_LOCAL( 1335 sap_ctx->auto_channel_select_weight, power_weight_cfg); 1336 1337 if (!sap_ctx->vdev) { 1338 sap_err("sap ctx vdev is null."); 1339 return power_weight_local; 1340 } 1341 pdev = wlan_vdev_get_pdev(sap_ctx->vdev); 1342 status = wlan_reg_get_chan_pwr_attr_from_secondary_list_for_freq( 1343 pdev, freq, &is_psd, &eirp_pwr, &psd_pwr, &chan_flags); 1344 if (status != QDF_STATUS_SUCCESS) { 1345 sap_err("fail to get power attribute."); 1346 return power_weight_local; 1347 } 1348 1349 if (eirp_pwr > REG_MAX_EIRP_POWER) { 1350 sap_debug("eirp_pwr %d exceed max", eirp_pwr); 1351 eirp_pwr = REG_MAX_EIRP_POWER; 1352 } 1353 if (eirp_pwr < REG_MIN_EIRP_POWER) { 1354 sap_debug("eirp_pwr %d below min", eirp_pwr); 1355 eirp_pwr = REG_MIN_EIRP_POWER; 1356 } 1357 1358 power_weight = ACS_WEIGHT_COMPUTE( 1359 sap_ctx->auto_channel_select_weight, 1360 power_weight_cfg, 1361 REG_MAX_EIRP_POWER - eirp_pwr, 1362 REG_MAX_EIRP_POWER - REG_MIN_EIRP_POWER); 1363 1364 if (power_weight > power_weight_local) 1365 power_weight = power_weight_local; 1366 else if (power_weight < 0) 1367 power_weight = 0; 1368 1369 return power_weight; 1370 } 1371 1372 static void 1373 sap_normalize_channel_weight_with_factors(struct mac_context *mac, 1374 struct sap_ch_info *spect_ch) 1375 { 1376 uint32_t normalized_weight; 1377 uint8_t normalize_factor = 100; 1378 uint8_t dfs_normalize_factor; 1379 uint32_t chan_freq, i; 1380 struct acs_weight *weight_list = 1381 mac->mlme_cfg->acs.normalize_weight_chan; 1382 struct acs_weight_range *range_list = 1383 mac->mlme_cfg->acs.normalize_weight_range; 1384 bool freq_present_in_list = false; 1385 1386 chan_freq = spect_ch->chan_freq; 1387 1388 /* Check if the freq is present in range list */ 1389 for (i = 0; i < mac->mlme_cfg->acs.num_weight_range; i++) { 1390 if (chan_freq >= range_list[i].start_freq && 1391 chan_freq <= range_list[i].end_freq) { 1392 normalize_factor = range_list[i].normalize_weight; 1393 sap_debug_rl("Range list, freq %d normalize weight factor %d", 1394 chan_freq, normalize_factor); 1395 freq_present_in_list = true; 1396 } 1397 } 1398 1399 /* Check if user wants a special factor for this freq */ 1400 for (i = 0; i < mac->mlme_cfg->acs.normalize_weight_num_chan; i++) { 1401 if (chan_freq == weight_list[i].chan_freq) { 1402 normalize_factor = weight_list[i].normalize_weight; 1403 sap_debug("freq %d normalize weight factor %d", 1404 chan_freq, normalize_factor); 1405 freq_present_in_list = true; 1406 } 1407 } 1408 1409 if (wlan_reg_is_dfs_for_freq(mac->pdev, chan_freq)) { 1410 dfs_normalize_factor = MLME_GET_DFS_CHAN_WEIGHT( 1411 mac->mlme_cfg->acs.np_chan_weightage); 1412 if (freq_present_in_list) 1413 normalize_factor = qdf_min(dfs_normalize_factor, 1414 normalize_factor); 1415 else 1416 normalize_factor = dfs_normalize_factor; 1417 freq_present_in_list = true; 1418 sap_debug_rl("DFS channel weightage %d min %d", 1419 dfs_normalize_factor, normalize_factor); 1420 } 1421 1422 if (freq_present_in_list) { 1423 normalized_weight = 1424 ((SAP_ACS_WEIGHT_MAX - spect_ch->weight) * 1425 (100 - normalize_factor)) / 100; 1426 sap_debug_rl("freq %d old weight %d new weight %d", 1427 chan_freq, spect_ch->weight, 1428 spect_ch->weight + normalized_weight); 1429 spect_ch->weight += normalized_weight; 1430 } 1431 } 1432 1433 /** 1434 * sap_update_6ghz_max_weight() - Update 6 GHz channel max weight 1435 * @ch_info_params: Pointer to the sap_sel_ch_info structure 1436 * @max_valid_weight: max valid weight on 6 GHz channels 1437 * 1438 * If ACS frequency list includes 6 GHz channels, the user prefers 1439 * to start SAP on 6 GHz as much as possible. The acs logic in 1440 * sap_chan_sel_init will mark channel weight to Max weight value 1441 * of SAP_ACS_WEIGHT_MAX if channel is no in ACS channel list(filtered 1442 * by PCL). 1443 * In ACS bw 160 case, sometime the combined weight of 8 channels 1444 * on 6 GHz(some of them have weight SAP_ACS_WEIGHT_MAX) 1445 * may higher than 5 GHz channels and finally select 5 GHz channel. 1446 * This API is to update the 6 GHz weight to max valid weight in 1447 * 6 GHz instead of value SAP_ACS_WEIGHT_MAX. All those channels have 1448 * special weight value SAP_ACS_WEIGHT_ADJUSTABLE which is assigned 1449 * sap_chan_sel_init. 1450 * 1451 * Return: void 1452 */ 1453 static void sap_update_6ghz_max_weight(struct sap_sel_ch_info *ch_info_params, 1454 uint32_t max_valid_weight) 1455 { 1456 uint8_t chn_num; 1457 struct sap_ch_info *pspect_ch; 1458 1459 sap_debug("max_valid_weight_on_6ghz_channels %d", 1460 max_valid_weight); 1461 if (!max_valid_weight) 1462 return; 1463 for (chn_num = 0; chn_num < ch_info_params->num_ch; 1464 chn_num++) { 1465 pspect_ch = &ch_info_params->ch_info[chn_num]; 1466 if (!wlan_reg_is_6ghz_chan_freq(pspect_ch->chan_freq)) 1467 continue; 1468 if (pspect_ch->weight == SAP_ACS_WEIGHT_ADJUSTABLE) { 1469 pspect_ch->weight = max_valid_weight; 1470 pspect_ch->weight_copy = pspect_ch->weight; 1471 } 1472 } 1473 } 1474 1475 /** 1476 * sap_update_5ghz_low_freq_weight() - Update weight of 5GHz low frequency 1477 * @psoc: Pointer to psoc 1478 * @ch_info_params: Pointer to sap_sel_ch_info structure 1479 * 1480 * This api helps to lower the 5GHz low frequency weight by 1481 * SAP_NORMALISE_ACS_WEIGHT so that it will get more preference to get 1482 * selected during ACS. 1483 * 1484 * Return: void 1485 */ 1486 static void sap_update_5ghz_low_freq_weight( 1487 struct wlan_objmgr_psoc *psoc, 1488 struct sap_sel_ch_info *ch_info_params) 1489 { 1490 uint8_t ch_num; 1491 qdf_freq_t freq; 1492 uint32_t weight; 1493 1494 if (!policy_mgr_is_hw_sbs_capable(psoc)) 1495 return; 1496 1497 for (ch_num = 0; ch_num < ch_info_params->num_ch; ch_num++) { 1498 freq = ch_info_params->ch_info[ch_num].chan_freq; 1499 weight = ch_info_params->ch_info[ch_num].weight; 1500 if (policy_mgr_is_given_freq_5g_low(psoc, freq)) { 1501 /* 1502 * Lower the weight by SAP_NORMALISE_ACS_WEIGHT i.e 5% 1503 * from channel weight itself. Later if required, modify 1504 * this value. 1505 * Here are the few observation captured which results 1506 * to go with SAP_NORMALISE_ACS_WEIGHT. 1507 * 1508 * +-----------+-------------+------------+---------------+--------------------------------------+ 1509 * | freq | bss_count | rssi | weight | observation | 1510 * +---------------------------------------------------------------------------------------------+ 1511 * | 5G low | >6 | -76 - -56 | 17419 - 17774 | Diff b/w 5G low & 5G high min weight | 1512 * | 5G high | <4 | -100 - -50 | 16842 - 17685 | is ~5% of 5G low min weight | 1513 * | | | | | | 1514 * | 5G low | >6 | -77 - -54 | 17419 - 17730 | Diff b/w 5G low & 5G high min weight | 1515 * | 5G high | <4 | -100 - -50 | 16842 - 17552 | is ~5% of 5G low min weight | 1516 * | | | | | | 1517 * | 5G low | >5 | -77 - -57 | 17286 - 17552 | Diff b/w 5G low & 5G high min weight | 1518 * | 5G high | <4 | -100 - -50 | 16842 - 17596 | is ~5% of 5G low min weight | 1519 * +-----------+-------------+------------+---------------+--------------------------------------+ 1520 */ 1521 1522 weight = weight - ((weight * SAP_NORMALISE_ACS_WEIGHT ) / 100); 1523 ch_info_params->ch_info[ch_num].weight = weight; 1524 } 1525 } 1526 } 1527 1528 /** 1529 * sap_compute_spect_weight() - Compute spectrum weight 1530 * @ch_info_params: Pointer to the tSpectInfoParams structure 1531 * @mac: Pointer to mac_context struucture 1532 * @scan_list: Pointer to channel list 1533 * @sap_ctx: Context of the SAP 1534 * 1535 * Main function for computing the weight of each channel in the 1536 * spectrum based on the RSSI value of the BSSes on the channel 1537 * and number of BSS 1538 */ 1539 static void sap_compute_spect_weight(struct sap_sel_ch_info *ch_info_params, 1540 struct mac_context *mac, 1541 qdf_list_t *scan_list, 1542 struct sap_context *sap_ctx) 1543 { 1544 int8_t rssi = 0; 1545 uint8_t chn_num = 0; 1546 struct sap_ch_info *ch_info = ch_info_params->ch_info; 1547 tSirMacHTChannelWidth ch_width = 0; 1548 uint16_t secondaryChannelOffset; 1549 uint32_t center_freq0, center_freq1, chan_freq; 1550 uint8_t i; 1551 bool found; 1552 struct sap_ch_info *ch_start = ch_info_params->ch_info; 1553 struct sap_ch_info *ch_end = ch_info_params->ch_info + 1554 ch_info_params->num_ch; 1555 qdf_list_node_t *cur_lst = NULL, *next_lst = NULL; 1556 struct scan_cache_node *cur_node = NULL; 1557 uint32_t rssi_bss_weight = 0, chan_status_weight = 0, power_weight = 0; 1558 uint32_t max_valid_weight_6ghz = 0; 1559 1560 sap_debug("Computing spectral weight"); 1561 1562 if (scan_list) 1563 qdf_list_peek_front(scan_list, &cur_lst); 1564 while (cur_lst) { 1565 cur_node = qdf_container_of(cur_lst, struct scan_cache_node, 1566 node); 1567 ch_info = ch_info_params->ch_info; 1568 /* Defining the default values, so that any value will hold the default values */ 1569 1570 secondaryChannelOffset = PHY_SINGLE_CHANNEL_CENTERED; 1571 center_freq0 = 0; 1572 center_freq1 = 0; 1573 1574 chan_freq = 1575 util_scan_entry_channel_frequency(cur_node->entry); 1576 1577 sap_upd_chan_spec_params(cur_node, &ch_width, 1578 &secondaryChannelOffset, 1579 ¢er_freq0, ¢er_freq1); 1580 1581 /* Processing for each tCsrScanResultInfo in the tCsrScanResult DLink list */ 1582 for (chn_num = 0; chn_num < ch_info_params->num_ch; 1583 chn_num++) { 1584 1585 if (chan_freq != ch_info->chan_freq) { 1586 ch_info++; 1587 continue; 1588 } 1589 1590 if (ch_info->rssi_agr < cur_node->entry->rssi_raw) 1591 ch_info->rssi_agr = cur_node->entry->rssi_raw; 1592 1593 ++ch_info->bss_count; 1594 1595 if (WLAN_REG_IS_24GHZ_CH_FREQ(chan_freq)) 1596 sap_interference_rssi_count(ch_info, ch_start, 1597 ch_end, mac); 1598 else 1599 sap_interference_rssi_count_5G( 1600 ch_info, ch_width, secondaryChannelOffset, 1601 center_freq0, center_freq1, chan_freq, 1602 ch_start, ch_end); 1603 1604 ch_info++; 1605 break; 1606 1607 } 1608 1609 qdf_list_peek_next(scan_list, cur_lst, &next_lst); 1610 cur_lst = next_lst; 1611 next_lst = NULL; 1612 } 1613 1614 /* Calculate the weights for all channels in the spectrum ch_info */ 1615 ch_info = ch_info_params->ch_info; 1616 1617 for (chn_num = 0; chn_num < (ch_info_params->num_ch); 1618 chn_num++) { 1619 1620 /* 1621 rssi : Maximum received signal strength among all BSS on that channel 1622 bss_count : Number of BSS on that channel 1623 */ 1624 1625 rssi = (int8_t)ch_info->rssi_agr; 1626 if (ch_in_pcl(sap_ctx, ch_info->chan_freq)) 1627 rssi -= PCL_RSSI_DISCOUNT; 1628 1629 if (rssi < SOFTAP_MIN_RSSI) 1630 rssi = SOFTAP_MIN_RSSI; 1631 1632 if (ch_info->weight == SAP_ACS_WEIGHT_MAX || 1633 ch_info->weight == SAP_ACS_WEIGHT_ADJUSTABLE) { 1634 ch_info->weight_copy = ch_info->weight; 1635 goto debug_info; 1636 } 1637 1638 /* There may be channels in scanlist, which were not sent to 1639 * FW for scanning as part of ACS scan list, but they do have an 1640 * effect on the neighbouring channels, so they help to find a 1641 * suitable channel, but there weight should be max as they were 1642 * and not meant to be included in the ACS scan results. 1643 * So just assign RSSI as -100, bsscount as 0, and weight as max 1644 * to them, so that they always stay low in sorting of best 1645 * channels which were included in ACS scan list 1646 */ 1647 found = false; 1648 for (i = 0; i < sap_ctx->num_of_channel; i++) { 1649 if (ch_info->chan_freq == sap_ctx->freq_list[i]) { 1650 /* Scan channel was included in ACS scan list */ 1651 found = true; 1652 break; 1653 } 1654 } 1655 1656 rssi_bss_weight = 0; 1657 chan_status_weight = 0; 1658 power_weight = 0; 1659 if (found) { 1660 rssi_bss_weight = sapweight_rssi_count( 1661 sap_ctx, 1662 rssi, 1663 ch_info->bss_count); 1664 chan_status_weight = sap_weight_channel_status( 1665 sap_ctx, 1666 sap_get_channel_status( 1667 mac, ch_info->chan_freq)); 1668 power_weight = sap_weight_channel_reg_max_power( 1669 sap_ctx, ch_info->chan_freq); 1670 ch_info->weight = SAPDFS_NORMALISE_1000 * 1671 (rssi_bss_weight + chan_status_weight 1672 + power_weight); 1673 } else { 1674 if (wlansap_is_channel_present_in_acs_list( 1675 ch_info->chan_freq, 1676 sap_ctx->acs_cfg->master_freq_list, 1677 sap_ctx->acs_cfg->master_ch_list_count)) 1678 ch_info->weight = SAP_ACS_WEIGHT_ADJUSTABLE; 1679 else 1680 ch_info->weight = SAP_ACS_WEIGHT_MAX; 1681 ch_info->rssi_agr = SOFTAP_MIN_RSSI; 1682 rssi = SOFTAP_MIN_RSSI; 1683 ch_info->bss_count = SOFTAP_MIN_COUNT; 1684 } 1685 1686 sap_normalize_channel_weight_with_factors(mac, ch_info); 1687 1688 if (ch_info->weight > SAP_ACS_WEIGHT_MAX) 1689 ch_info->weight = SAP_ACS_WEIGHT_MAX; 1690 ch_info->weight_copy = ch_info->weight; 1691 1692 debug_info: 1693 if (wlan_reg_is_6ghz_chan_freq(ch_info->chan_freq) && 1694 ch_info->weight < SAP_ACS_WEIGHT_ADJUSTABLE && 1695 max_valid_weight_6ghz < ch_info->weight) 1696 max_valid_weight_6ghz = ch_info->weight; 1697 1698 sap_debug("freq %d valid %d weight %d(%d,%d,%d) rssi %d bss %d", 1699 ch_info->chan_freq, ch_info->valid, 1700 ch_info->weight, rssi_bss_weight, 1701 chan_status_weight, power_weight, 1702 ch_info->rssi_agr, ch_info->bss_count); 1703 1704 ch_info++; 1705 } 1706 sap_update_6ghz_max_weight(ch_info_params, 1707 max_valid_weight_6ghz); 1708 1709 if (policy_mgr_is_vdev_ll_lt_sap(mac->psoc, sap_ctx->vdev_id)) 1710 sap_update_5ghz_low_freq_weight(mac->psoc, ch_info_params); 1711 1712 sap_clear_channel_status(mac); 1713 } 1714 1715 void sap_chan_sel_exit(struct sap_sel_ch_info *ch_info_params) 1716 { 1717 /* Free all the allocated memory */ 1718 qdf_mem_free(ch_info_params->ch_info); 1719 } 1720 1721 /*========================================================================== 1722 FUNCTION sap_sort_chl_weight 1723 1724 DESCRIPTION 1725 Function to sort the channels with the least weight first for 20MHz channels 1726 1727 DEPENDENCIES 1728 NA. 1729 1730 PARAMETERS 1731 1732 IN 1733 ch_info_params : Pointer to the tSapChSelSpectInfo structure 1734 1735 RETURN VALUE 1736 void : NULL 1737 1738 SIDE EFFECTS 1739 ============================================================================*/ 1740 static void sap_sort_chl_weight(struct sap_sel_ch_info *ch_info_params) 1741 { 1742 struct sap_ch_info temp; 1743 1744 struct sap_ch_info *ch_info = NULL; 1745 uint32_t i = 0, j = 0, min_weight_index = 0; 1746 1747 ch_info = ch_info_params->ch_info; 1748 for (i = 0; i < ch_info_params->num_ch; i++) { 1749 min_weight_index = i; 1750 for (j = i + 1; j < ch_info_params->num_ch; j++) { 1751 if (ch_info[j].weight < 1752 ch_info[min_weight_index].weight) { 1753 min_weight_index = j; 1754 } else if (ch_info[j].weight == 1755 ch_info[min_weight_index].weight) { 1756 if (ch_info[j].bss_count < 1757 ch_info[min_weight_index].bss_count) 1758 min_weight_index = j; 1759 } 1760 } 1761 if (min_weight_index != i) { 1762 qdf_mem_copy(&temp, &ch_info[min_weight_index], 1763 sizeof(*ch_info)); 1764 qdf_mem_copy(&ch_info[min_weight_index], &ch_info[i], 1765 sizeof(*ch_info)); 1766 qdf_mem_copy(&ch_info[i], &temp, sizeof(*ch_info)); 1767 } 1768 } 1769 } 1770 1771 /** 1772 * sap_override_6ghz_psc_minidx() - override mindex to 6 GHz PSC channel's idx 1773 * @mac_ctx: pointer to max context 1774 * @spectinfo: Pointer to array of tSach_infoInfo 1775 * @count: number of tSach_infoInfo element to search 1776 * @minidx: index to be overridden 1777 * 1778 * Return: QDF STATUS 1779 */ 1780 static void 1781 sap_override_6ghz_psc_minidx(struct mac_context *mac_ctx, 1782 struct sap_ch_info *spectinfo, 1783 uint8_t count, 1784 uint8_t *minidx) 1785 { 1786 uint8_t i; 1787 1788 if (!mac_ctx->mlme_cfg->acs.acs_prefer_6ghz_psc) 1789 return; 1790 1791 for (i = 0; i < count; i++) { 1792 if (wlan_reg_is_6ghz_chan_freq( 1793 spectinfo[i].chan_freq) && 1794 wlan_reg_is_6ghz_psc_chan_freq( 1795 spectinfo[i].chan_freq)) { 1796 *minidx = i; 1797 return; 1798 } 1799 } 1800 } 1801 1802 /** 1803 * sap_sort_chl_weight_80_mhz() - to sort the channels with the least weight 1804 * @mac_ctx: pointer to max context 1805 * @sap_ctx: Pointer to the struct sap_context *structure 1806 * @ch_info_params: Pointer to the tSapChSelSpectInfo structure 1807 * Function to sort the channels with the least weight first for HT80 channels 1808 * 1809 * Return: QDF STATUS 1810 */ 1811 static QDF_STATUS 1812 sap_sort_chl_weight_80_mhz(struct mac_context *mac_ctx, 1813 struct sap_context *sap_ctx, 1814 struct sap_sel_ch_info *ch_info_params) 1815 { 1816 uint8_t i, j; 1817 struct sap_ch_info *chan_info; 1818 uint8_t minIdx; 1819 struct ch_params acs_ch_params = {0}; 1820 int8_t center_freq_diff; 1821 uint32_t combined_weight; 1822 uint32_t min_ch_weight; 1823 uint32_t valid_chans = 0; 1824 bool has_valid; 1825 1826 chan_info = ch_info_params->ch_info; 1827 1828 for (j = 0; j < ch_info_params->num_ch; j++) { 1829 1830 if (chan_info[j].weight_calc_done) 1831 continue; 1832 1833 acs_ch_params.ch_width = CH_WIDTH_80MHZ; 1834 sap_acs_set_puncture_support(sap_ctx, &acs_ch_params); 1835 1836 wlan_reg_set_channel_params_for_pwrmode(mac_ctx->pdev, 1837 chan_info[j].chan_freq, 1838 0, &acs_ch_params, 1839 REG_CURRENT_PWR_MODE); 1840 1841 /* Check if the freq supports 80 Mhz */ 1842 if (acs_ch_params.ch_width != CH_WIDTH_80MHZ) { 1843 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 4; 1844 chan_info[j].weight_calc_done = true; 1845 continue; 1846 } 1847 1848 center_freq_diff = acs_ch_params.mhz_freq_seg0 - 1849 chan_info[j].chan_freq; 1850 1851 /* This channel frequency does not have all channels */ 1852 if (center_freq_diff != 30) { 1853 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 4; 1854 chan_info[j].weight_calc_done = true; 1855 continue; 1856 } 1857 1858 /* no other freq left for 80 Mhz operation in spectrum */ 1859 if (j + 3 > ch_info_params->num_ch) 1860 continue; 1861 1862 /* Check whether all frequencies are present for 80 Mhz */ 1863 1864 if (!(((chan_info[j].chan_freq + 20) == 1865 chan_info[j + 1].chan_freq) && 1866 ((chan_info[j].chan_freq + 40) == 1867 chan_info[j + 2].chan_freq) && 1868 ((chan_info[j].chan_freq + 60) == 1869 chan_info[j + 3].chan_freq))) { 1870 /* 1871 * some channels does not exist in pSectInfo array, 1872 * skip this channel and those in the same HT80 width 1873 */ 1874 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 4; 1875 chan_info[j].weight_calc_done = true; 1876 if ((chan_info[j].chan_freq + 20) == 1877 chan_info[j + 1].chan_freq) { 1878 chan_info[j + 1].weight = 1879 SAP_ACS_WEIGHT_MAX * 4; 1880 chan_info[j + 1].weight_calc_done = true; 1881 } 1882 if ((chan_info[j].chan_freq + 40) == 1883 chan_info[j + 2].chan_freq) { 1884 chan_info[j + 2].weight = 1885 SAP_ACS_WEIGHT_MAX * 4; 1886 chan_info[j + 2].weight_calc_done = true; 1887 } 1888 if ((chan_info[j].chan_freq + 60) == 1889 chan_info[j + 3].chan_freq) { 1890 chan_info[j + 3].weight = 1891 SAP_ACS_WEIGHT_MAX * 4; 1892 chan_info[j + 3].weight_calc_done = true; 1893 } 1894 1895 continue; 1896 } 1897 1898 /* We have 4 channels to calculate cumulative weight */ 1899 1900 combined_weight = chan_info[j].weight + 1901 chan_info[j + 1].weight + 1902 chan_info[j + 2].weight + 1903 chan_info[j + 3].weight; 1904 1905 min_ch_weight = chan_info[j].weight; 1906 minIdx = 0; 1907 has_valid = false; 1908 1909 for (i = 0; i < 4; i++) { 1910 if (min_ch_weight > chan_info[j + i].weight) { 1911 min_ch_weight = chan_info[j + i].weight; 1912 minIdx = i; 1913 } 1914 chan_info[j + i].weight = SAP_ACS_WEIGHT_MAX * 4; 1915 chan_info[j + i].weight_calc_done = true; 1916 if (chan_info[j + i].valid) 1917 has_valid = true; 1918 } 1919 sap_override_6ghz_psc_minidx(mac_ctx, &chan_info[j], 4, 1920 &minIdx); 1921 1922 chan_info[j + minIdx].weight = combined_weight; 1923 if (has_valid) 1924 valid_chans++; 1925 1926 sap_debug("best freq = %d for 80mhz center freq %d combined weight = %d valid %d cnt %d", 1927 chan_info[j + minIdx].chan_freq, 1928 acs_ch_params.mhz_freq_seg0, 1929 combined_weight, has_valid, valid_chans); 1930 } 1931 1932 if (!valid_chans) { 1933 sap_debug("no valid chan bonding with CH_WIDTH_80MHZ"); 1934 return QDF_STATUS_E_INVAL; 1935 } 1936 1937 sap_sort_chl_weight(ch_info_params); 1938 1939 return QDF_STATUS_SUCCESS; 1940 } 1941 1942 /** 1943 * sap_sort_chl_weight_160_mhz() - to sort the channels with the least weight 1944 * @mac_ctx: pointer to max context 1945 * @sap_ctx: Pointer to the struct sap_context *structure 1946 * @ch_info_params: Pointer to the tSapChSelSpectInfo structure 1947 * 1948 * Function to sort the channels with the least weight first for VHT160 channels 1949 * 1950 * Return: QDF STATUS 1951 */ 1952 static QDF_STATUS 1953 sap_sort_chl_weight_160_mhz(struct mac_context *mac_ctx, 1954 struct sap_context *sap_ctx, 1955 struct sap_sel_ch_info *ch_info_params) 1956 { 1957 uint8_t i, j; 1958 struct sap_ch_info *chan_info; 1959 uint8_t minIdx; 1960 struct ch_params acs_ch_params = {0}; 1961 int8_t center_freq_diff; 1962 uint32_t combined_weight; 1963 uint32_t min_ch_weight; 1964 uint32_t valid_chans = 0; 1965 bool has_valid; 1966 1967 chan_info = ch_info_params->ch_info; 1968 1969 for (j = 0; j < ch_info_params->num_ch; j++) { 1970 1971 if (chan_info[j].weight_calc_done) 1972 continue; 1973 1974 acs_ch_params.ch_width = CH_WIDTH_160MHZ; 1975 sap_acs_set_puncture_support(sap_ctx, &acs_ch_params); 1976 1977 wlan_reg_set_channel_params_for_pwrmode(mac_ctx->pdev, 1978 chan_info[j].chan_freq, 1979 0, &acs_ch_params, 1980 REG_CURRENT_PWR_MODE); 1981 1982 /* Check if the freq supports 160 Mhz */ 1983 if (acs_ch_params.ch_width != CH_WIDTH_160MHZ) { 1984 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 8; 1985 chan_info[j].weight_calc_done = true; 1986 continue; 1987 } 1988 1989 center_freq_diff = acs_ch_params.mhz_freq_seg1 - 1990 chan_info[j].chan_freq; 1991 1992 /* This channel frequency does not have all channels */ 1993 if (center_freq_diff != 70) { 1994 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 8; 1995 chan_info[j].weight_calc_done = true; 1996 continue; 1997 } 1998 1999 /* no other freq left for 160 Mhz operation in spectrum */ 2000 if (j + 7 > ch_info_params->num_ch) 2001 continue; 2002 2003 /* Check whether all frequencies are present for 160 Mhz */ 2004 2005 if (!(((chan_info[j].chan_freq + 20) == 2006 chan_info[j + 1].chan_freq) && 2007 ((chan_info[j].chan_freq + 40) == 2008 chan_info[j + 2].chan_freq) && 2009 ((chan_info[j].chan_freq + 60) == 2010 chan_info[j + 3].chan_freq) && 2011 ((chan_info[j].chan_freq + 80) == 2012 chan_info[j + 4].chan_freq) && 2013 ((chan_info[j].chan_freq + 100) == 2014 chan_info[j + 5].chan_freq) && 2015 ((chan_info[j].chan_freq + 120) == 2016 chan_info[j + 6].chan_freq) && 2017 ((chan_info[j].chan_freq + 140) == 2018 chan_info[j + 7].chan_freq))) { 2019 /* 2020 * some channels does not exist in pSectInfo array, 2021 * skip this channel and those in the same VHT160 width 2022 */ 2023 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 8; 2024 chan_info[j].weight_calc_done = true; 2025 if ((chan_info[j].chan_freq + 20) == 2026 chan_info[j + 1].chan_freq) { 2027 chan_info[j + 1].weight = 2028 SAP_ACS_WEIGHT_MAX * 8; 2029 chan_info[j + 1].weight_calc_done = true; 2030 } 2031 if ((chan_info[j].chan_freq + 40) == 2032 chan_info[j + 2].chan_freq) { 2033 chan_info[j + 2].weight = 2034 SAP_ACS_WEIGHT_MAX * 8; 2035 chan_info[j + 2].weight_calc_done = true; 2036 } 2037 if ((chan_info[j].chan_freq + 60) == 2038 chan_info[j + 3].chan_freq) { 2039 chan_info[j + 3].weight = 2040 SAP_ACS_WEIGHT_MAX * 8; 2041 chan_info[j + 3].weight_calc_done = true; 2042 } 2043 if ((chan_info[j].chan_freq + 80) == 2044 chan_info[j + 4].chan_freq) { 2045 chan_info[j + 4].weight = 2046 SAP_ACS_WEIGHT_MAX * 8; 2047 chan_info[j + 4].weight_calc_done = true; 2048 } 2049 if ((chan_info[j].chan_freq + 100) == 2050 chan_info[j + 5].chan_freq) { 2051 chan_info[j + 5].weight = 2052 SAP_ACS_WEIGHT_MAX * 8; 2053 chan_info[j + 5].weight_calc_done = true; 2054 } 2055 if ((chan_info[j].chan_freq + 120) == 2056 chan_info[j + 6].chan_freq) { 2057 chan_info[j + 6].weight = 2058 SAP_ACS_WEIGHT_MAX * 8; 2059 chan_info[j + 6].weight_calc_done = true; 2060 } 2061 if ((chan_info[j].chan_freq + 140) == 2062 chan_info[j + 7].chan_freq) { 2063 chan_info[j + 7].weight = 2064 SAP_ACS_WEIGHT_MAX * 8; 2065 chan_info[j + 7].weight_calc_done = true; 2066 } 2067 2068 continue; 2069 } 2070 2071 /* We have 8 channels to calculate cumulative weight */ 2072 2073 combined_weight = chan_info[j].weight + 2074 chan_info[j + 1].weight + 2075 chan_info[j + 2].weight + 2076 chan_info[j + 3].weight + 2077 chan_info[j + 4].weight + 2078 chan_info[j + 5].weight + 2079 chan_info[j + 6].weight + 2080 chan_info[j + 7].weight; 2081 2082 min_ch_weight = chan_info[j].weight; 2083 minIdx = 0; 2084 has_valid = false; 2085 2086 for (i = 0; i < 8; i++) { 2087 if (min_ch_weight > chan_info[j + i].weight) { 2088 min_ch_weight = chan_info[j + i].weight; 2089 minIdx = i; 2090 } 2091 chan_info[j + i].weight = SAP_ACS_WEIGHT_MAX * 8; 2092 chan_info[j + i].weight_calc_done = true; 2093 if (chan_info[j + i].valid) 2094 has_valid = true; 2095 } 2096 sap_override_6ghz_psc_minidx(mac_ctx, &chan_info[j], 8, 2097 &minIdx); 2098 2099 chan_info[j + minIdx].weight = combined_weight; 2100 if (has_valid) 2101 valid_chans++; 2102 2103 sap_debug("best freq = %d for 160mhz center freq %d combined weight = %d valid %d cnt %d", 2104 chan_info[j + minIdx].chan_freq, 2105 acs_ch_params.mhz_freq_seg1, 2106 combined_weight, has_valid, valid_chans); 2107 } 2108 2109 if (!valid_chans) { 2110 sap_debug("no valid chan bonding with CH_WIDTH_160MHZ"); 2111 return QDF_STATUS_E_INVAL; 2112 } 2113 2114 sap_sort_chl_weight(ch_info_params); 2115 2116 return QDF_STATUS_SUCCESS; 2117 } 2118 2119 #if defined(WLAN_FEATURE_11BE) 2120 /** 2121 * sap_sort_chl_weight_320_mhz() - to sort the channels with the least weight 2122 * @mac_ctx: pointer to max context 2123 * @sap_ctx: Pointer to the struct sap_context *structure 2124 * @ch_info_params: Pointer to the tSapChSelSpectInfo structure 2125 * 2126 * Function to sort the channels with the least weight first for 320MHz channels 2127 * 2128 * Return: QDF STATUS 2129 */ 2130 static QDF_STATUS 2131 sap_sort_chl_weight_320_mhz(struct mac_context *mac_ctx, 2132 struct sap_context *sap_ctx, 2133 struct sap_sel_ch_info *ch_info_params) 2134 { 2135 uint8_t i, j; 2136 struct sap_ch_info *chan_info; 2137 uint8_t minIdx; 2138 struct ch_params acs_ch_params = {0}; 2139 uint32_t combined_weight; 2140 uint32_t min_ch_weight; 2141 uint32_t valid_chans = 0; 2142 bool has_valid; 2143 2144 chan_info = ch_info_params->ch_info; 2145 2146 for (j = 0; j < ch_info_params->num_ch; j++) { 2147 if (chan_info[j].weight_calc_done) 2148 continue; 2149 2150 qdf_mem_zero(&acs_ch_params, sizeof(acs_ch_params)); 2151 acs_ch_params.ch_width = CH_WIDTH_320MHZ; 2152 sap_acs_set_puncture_support(sap_ctx, &acs_ch_params); 2153 2154 wlan_reg_set_channel_params_for_pwrmode(mac_ctx->pdev, 2155 chan_info[j].chan_freq, 2156 0, &acs_ch_params, 2157 REG_CURRENT_PWR_MODE); 2158 2159 /* Check if the freq supports 320 Mhz */ 2160 if (acs_ch_params.ch_width != CH_WIDTH_320MHZ) { 2161 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 16; 2162 chan_info[j].weight_calc_done = true; 2163 continue; 2164 } 2165 2166 /* no other freq left for 320 Mhz operation in spectrum */ 2167 if (j + 15 > ch_info_params->num_ch) { 2168 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 16; 2169 chan_info[j].weight_calc_done = true; 2170 continue; 2171 } 2172 2173 /* Check whether all frequencies are present for 160 Mhz */ 2174 2175 if (!(((chan_info[j].chan_freq + 20) == 2176 chan_info[j + 1].chan_freq) && 2177 ((chan_info[j].chan_freq + 40) == 2178 chan_info[j + 2].chan_freq) && 2179 ((chan_info[j].chan_freq + 60) == 2180 chan_info[j + 3].chan_freq) && 2181 ((chan_info[j].chan_freq + 80) == 2182 chan_info[j + 4].chan_freq) && 2183 ((chan_info[j].chan_freq + 100) == 2184 chan_info[j + 5].chan_freq) && 2185 ((chan_info[j].chan_freq + 120) == 2186 chan_info[j + 6].chan_freq) && 2187 ((chan_info[j].chan_freq + 140) == 2188 chan_info[j + 7].chan_freq) && 2189 ((chan_info[j].chan_freq + 160) == 2190 chan_info[j + 8].chan_freq) && 2191 ((chan_info[j].chan_freq + 180) == 2192 chan_info[j + 9].chan_freq) && 2193 ((chan_info[j].chan_freq + 200) == 2194 chan_info[j + 10].chan_freq) && 2195 ((chan_info[j].chan_freq + 220) == 2196 chan_info[j + 11].chan_freq) && 2197 ((chan_info[j].chan_freq + 240) == 2198 chan_info[j + 12].chan_freq) && 2199 ((chan_info[j].chan_freq + 260) == 2200 chan_info[j + 13].chan_freq) && 2201 ((chan_info[j].chan_freq + 280) == 2202 chan_info[j + 14].chan_freq) && 2203 ((chan_info[j].chan_freq + 300) == 2204 chan_info[j + 15].chan_freq))) { 2205 /* 2206 * some channels does not exist in pSectInfo array, 2207 * skip this channel and those in the same ETH320 width 2208 */ 2209 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 16; 2210 chan_info[j].weight_calc_done = true; 2211 if ((chan_info[j].chan_freq + 20) == 2212 chan_info[j + 1].chan_freq) { 2213 chan_info[j + 1].weight = 2214 SAP_ACS_WEIGHT_MAX * 16; 2215 chan_info[j + 1].weight_calc_done = true; 2216 } 2217 if ((chan_info[j].chan_freq + 40) == 2218 chan_info[j + 2].chan_freq) { 2219 chan_info[j + 2].weight = 2220 SAP_ACS_WEIGHT_MAX * 16; 2221 chan_info[j + 2].weight_calc_done = true; 2222 } 2223 if ((chan_info[j].chan_freq + 60) == 2224 chan_info[j + 3].chan_freq) { 2225 chan_info[j + 3].weight = 2226 SAP_ACS_WEIGHT_MAX * 16; 2227 chan_info[j + 3].weight_calc_done = true; 2228 } 2229 if ((chan_info[j].chan_freq + 80) == 2230 chan_info[j + 4].chan_freq) { 2231 chan_info[j + 4].weight = 2232 SAP_ACS_WEIGHT_MAX * 16; 2233 chan_info[j + 4].weight_calc_done = true; 2234 } 2235 if ((chan_info[j].chan_freq + 100) == 2236 chan_info[j + 5].chan_freq) { 2237 chan_info[j + 5].weight = 2238 SAP_ACS_WEIGHT_MAX * 16; 2239 chan_info[j + 5].weight_calc_done = true; 2240 } 2241 if ((chan_info[j].chan_freq + 120) == 2242 chan_info[j + 6].chan_freq) { 2243 chan_info[j + 6].weight = 2244 SAP_ACS_WEIGHT_MAX * 16; 2245 chan_info[j + 6].weight_calc_done = true; 2246 } 2247 if ((chan_info[j].chan_freq + 140) == 2248 chan_info[j + 7].chan_freq) { 2249 chan_info[j + 7].weight = 2250 SAP_ACS_WEIGHT_MAX * 16; 2251 chan_info[j + 7].weight_calc_done = true; 2252 } 2253 if ((chan_info[j].chan_freq + 160) == 2254 chan_info[j + 8].chan_freq) { 2255 chan_info[j + 8].weight = 2256 SAP_ACS_WEIGHT_MAX * 16; 2257 chan_info[j + 8].weight_calc_done = true; 2258 } 2259 if ((chan_info[j].chan_freq + 180) == 2260 chan_info[j + 9].chan_freq) { 2261 chan_info[j + 9].weight = 2262 SAP_ACS_WEIGHT_MAX * 16; 2263 chan_info[j + 9].weight_calc_done = true; 2264 } 2265 if ((chan_info[j].chan_freq + 200) == 2266 chan_info[j + 10].chan_freq) { 2267 chan_info[j + 10].weight = 2268 SAP_ACS_WEIGHT_MAX * 16; 2269 chan_info[j + 10].weight_calc_done = true; 2270 } 2271 if ((chan_info[j].chan_freq + 220) == 2272 chan_info[j + 11].chan_freq) { 2273 chan_info[j + 11].weight = 2274 SAP_ACS_WEIGHT_MAX * 16; 2275 chan_info[j + 11].weight_calc_done = true; 2276 } 2277 if ((chan_info[j].chan_freq + 240) == 2278 chan_info[j + 12].chan_freq) { 2279 chan_info[j + 12].weight = 2280 SAP_ACS_WEIGHT_MAX * 16; 2281 chan_info[j + 12].weight_calc_done = true; 2282 } 2283 if ((chan_info[j].chan_freq + 260) == 2284 chan_info[j + 13].chan_freq) { 2285 chan_info[j + 13].weight = 2286 SAP_ACS_WEIGHT_MAX * 16; 2287 chan_info[j + 13].weight_calc_done = true; 2288 } 2289 if ((chan_info[j].chan_freq + 280) == 2290 chan_info[j + 14].chan_freq) { 2291 chan_info[j + 14].weight = 2292 SAP_ACS_WEIGHT_MAX * 16; 2293 chan_info[j + 14].weight_calc_done = true; 2294 } 2295 if ((chan_info[j].chan_freq + 300) == 2296 chan_info[j + 15].chan_freq) { 2297 chan_info[j + 15].weight = 2298 SAP_ACS_WEIGHT_MAX * 16; 2299 chan_info[j + 15].weight_calc_done = true; 2300 } 2301 2302 continue; 2303 } 2304 2305 /* We have 16 channels to calculate cumulative weight */ 2306 combined_weight = chan_info[j].weight + 2307 chan_info[j + 1].weight + 2308 chan_info[j + 2].weight + 2309 chan_info[j + 3].weight + 2310 chan_info[j + 4].weight + 2311 chan_info[j + 5].weight + 2312 chan_info[j + 6].weight + 2313 chan_info[j + 7].weight + 2314 chan_info[j + 8].weight + 2315 chan_info[j + 9].weight + 2316 chan_info[j + 10].weight + 2317 chan_info[j + 11].weight + 2318 chan_info[j + 12].weight + 2319 chan_info[j + 13].weight + 2320 chan_info[j + 14].weight + 2321 chan_info[j + 15].weight; 2322 2323 min_ch_weight = chan_info[j].weight; 2324 minIdx = 0; 2325 has_valid = false; 2326 for (i = 0; i < 16; i++) { 2327 if (min_ch_weight > chan_info[j + i].weight) { 2328 min_ch_weight = chan_info[j + i].weight; 2329 minIdx = i; 2330 } 2331 chan_info[j + i].weight = SAP_ACS_WEIGHT_MAX * 16; 2332 chan_info[j + i].weight_calc_done = true; 2333 if (chan_info[j + i].valid) 2334 has_valid = true; 2335 } 2336 sap_override_6ghz_psc_minidx(mac_ctx, &chan_info[j], 16, 2337 &minIdx); 2338 2339 chan_info[j + minIdx].weight = combined_weight; 2340 if (has_valid) 2341 valid_chans++; 2342 2343 sap_debug("best freq = %d for 320mhz center freq %d combined weight = %d valid %d cnt %d", 2344 chan_info[j + minIdx].chan_freq, 2345 acs_ch_params.mhz_freq_seg1, 2346 combined_weight, 2347 has_valid, valid_chans); 2348 } 2349 2350 if (!valid_chans) { 2351 sap_debug("no valid chan bonding with CH_WIDTH_320MHZ"); 2352 return QDF_STATUS_E_INVAL; 2353 } 2354 2355 sap_sort_chl_weight(ch_info_params); 2356 2357 return QDF_STATUS_SUCCESS; 2358 } 2359 #endif /* WLAN_FEATURE_11BE */ 2360 2361 /** 2362 * sap_allocate_max_weight_40_mhz_24_g() - allocate max weight for 40Mhz 2363 * to all 2.4Ghz channels 2364 * @spect_info_params: Pointer to the tSapChSelSpectInfo structure 2365 * 2366 * Return: none 2367 */ 2368 static void 2369 sap_allocate_max_weight_40_mhz_24_g(struct sap_sel_ch_info *spect_info_params) 2370 { 2371 struct sap_ch_info *spect_info; 2372 uint8_t j; 2373 2374 /* 2375 * Assign max weight for 40Mhz (SAP_ACS_WEIGHT_MAX * 2) to all 2376 * 2.4 Ghz channels 2377 */ 2378 spect_info = spect_info_params->ch_info; 2379 for (j = 0; j < spect_info_params->num_ch; j++) { 2380 if (WLAN_REG_IS_24GHZ_CH_FREQ(spect_info[j].chan_freq)) 2381 spect_info[j].weight = SAP_ACS_WEIGHT_MAX * 2; 2382 } 2383 } 2384 2385 /** 2386 * sap_allocate_max_weight_40_mhz() - allocate max weight for 40Mhz 2387 * to all 5Ghz channels 2388 * @spect_info_params: Pointer to the tSapChSelSpectInfo structure 2389 * 2390 * Return: none 2391 */ 2392 static void 2393 sap_allocate_max_weight_40_mhz(struct sap_sel_ch_info *spect_info_params) 2394 { 2395 struct sap_ch_info *spect_info; 2396 uint8_t j; 2397 2398 /* 2399 * Assign max weight for 40Mhz (SAP_ACS_WEIGHT_MAX * 2) to all 2400 * 5 Ghz channels 2401 */ 2402 spect_info = spect_info_params->ch_info; 2403 for (j = 0; j < spect_info_params->num_ch; j++) { 2404 if (WLAN_REG_IS_5GHZ_CH_FREQ(spect_info[j].chan_freq) || 2405 WLAN_REG_IS_6GHZ_CHAN_FREQ(spect_info[j].chan_freq)) 2406 spect_info[j].weight = SAP_ACS_WEIGHT_MAX * 2; 2407 } 2408 } 2409 2410 /** 2411 * sap_sort_chl_weight_ht40_24_g() - To sort channel with the least weight 2412 * @mac_ctx: Pointer to mac_ctx 2413 * @ch_info_params: Pointer to the sap_sel_ch_info structure 2414 * @domain: Regulatory domain 2415 * 2416 * Function to sort the channels with the least weight first for HT40 channels 2417 * 2418 * Return: none 2419 */ 2420 static void sap_sort_chl_weight_ht40_24_g( 2421 struct mac_context *mac_ctx, 2422 struct sap_sel_ch_info *ch_info_params, 2423 v_REGDOMAIN_t domain) 2424 { 2425 uint8_t i, j; 2426 struct sap_ch_info *chan_info; 2427 uint32_t tmp_weight1, tmp_weight2; 2428 uint32_t ht40plus2gendch = 0; 2429 uint32_t channel; 2430 uint32_t chan_freq; 2431 2432 chan_info = ch_info_params->ch_info; 2433 /* 2434 * for each HT40 channel, calculate the combined weight of the 2435 * two 20MHz weight 2436 */ 2437 for (i = 0; i < ARRAY_SIZE(acs_ht40_channels24_g); i++) { 2438 for (j = 0; j < ch_info_params->num_ch; j++) { 2439 channel = wlan_reg_freq_to_chan(mac_ctx->pdev, 2440 chan_info[j].chan_freq); 2441 if (channel == acs_ht40_channels24_g[i].chStartNum) 2442 break; 2443 } 2444 if (j == ch_info_params->num_ch) 2445 continue; 2446 2447 if (!((chan_info[j].chan_freq + 20) == 2448 chan_info[j + 4].chan_freq)) { 2449 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 2; 2450 continue; 2451 } 2452 /* 2453 * check if there is another channel combination possibility 2454 * e.g., {1, 5} & {5, 9} 2455 */ 2456 if ((chan_info[j + 4].chan_freq + 20) == 2457 chan_info[j + 8].chan_freq) { 2458 /* need to compare two channel pairs */ 2459 tmp_weight1 = chan_info[j].weight + 2460 chan_info[j + 4].weight; 2461 tmp_weight2 = chan_info[j + 4].weight + 2462 chan_info[j + 8].weight; 2463 if (tmp_weight1 <= tmp_weight2) { 2464 if (chan_info[j].weight <= 2465 chan_info[j + 4].weight) { 2466 chan_info[j].weight = 2467 tmp_weight1; 2468 chan_info[j + 4].weight = 2469 SAP_ACS_WEIGHT_MAX * 2; 2470 chan_info[j + 8].weight = 2471 SAP_ACS_WEIGHT_MAX * 2; 2472 } else { 2473 chan_info[j + 4].weight = 2474 tmp_weight1; 2475 /* for secondary channel selection */ 2476 chan_info[j].weight = 2477 SAP_ACS_WEIGHT_MAX * 2 2478 - 1; 2479 chan_info[j + 8].weight = 2480 SAP_ACS_WEIGHT_MAX * 2; 2481 } 2482 } else { 2483 if (chan_info[j + 4].weight <= 2484 chan_info[j + 8].weight) { 2485 chan_info[j + 4].weight = 2486 tmp_weight2; 2487 chan_info[j].weight = 2488 SAP_ACS_WEIGHT_MAX * 2; 2489 /* for secondary channel selection */ 2490 chan_info[j + 8].weight = 2491 SAP_ACS_WEIGHT_MAX * 2 2492 - 1; 2493 } else { 2494 chan_info[j + 8].weight = 2495 tmp_weight2; 2496 chan_info[j].weight = 2497 SAP_ACS_WEIGHT_MAX * 2; 2498 chan_info[j + 4].weight = 2499 SAP_ACS_WEIGHT_MAX * 2; 2500 } 2501 } 2502 } else { 2503 tmp_weight1 = chan_info[j].weight_copy + 2504 chan_info[j + 4].weight_copy; 2505 if (chan_info[j].weight_copy <= 2506 chan_info[j + 4].weight_copy) { 2507 chan_info[j].weight = tmp_weight1; 2508 chan_info[j + 4].weight = 2509 SAP_ACS_WEIGHT_MAX * 2; 2510 } else { 2511 chan_info[j + 4].weight = tmp_weight1; 2512 chan_info[j].weight = 2513 SAP_ACS_WEIGHT_MAX * 2; 2514 } 2515 } 2516 } 2517 /* 2518 * Every channel should be checked. Add the check for the omissive 2519 * channel. Mark the channel whose combination can't satisfy 40MHZ 2520 * as max value, so that it will be sorted to the bottom. 2521 */ 2522 if (REGDOMAIN_FCC == domain) 2523 ht40plus2gendch = HT40PLUS_2G_FCC_CH_END; 2524 else 2525 ht40plus2gendch = HT40PLUS_2G_EURJAP_CH_END; 2526 for (i = HT40MINUS_2G_CH_START; i <= ht40plus2gendch; i++) { 2527 chan_freq = wlan_reg_legacy_chan_to_freq(mac_ctx->pdev, i); 2528 for (j = 0; j < ch_info_params->num_ch; j++) { 2529 if (chan_info[j].chan_freq == chan_freq && 2530 ((chan_info[j].chan_freq + 20) != 2531 chan_info[j + 4].chan_freq) && 2532 ((chan_info[j].chan_freq - 20) != 2533 chan_info[j - 4].chan_freq)) 2534 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 2; 2535 } 2536 } 2537 for (i = ht40plus2gendch + 1; i <= HT40MINUS_2G_CH_END; i++) { 2538 chan_freq = wlan_reg_legacy_chan_to_freq(mac_ctx->pdev, i); 2539 for (j = 0; j < ch_info_params->num_ch; j++) { 2540 if (chan_info[j].chan_freq == chan_freq && 2541 (chan_info[j].chan_freq - 20) != 2542 chan_info[j - 4].chan_freq) 2543 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 2; 2544 } 2545 } 2546 2547 chan_info = ch_info_params->ch_info; 2548 for (j = 0; j < (ch_info_params->num_ch); j++) { 2549 QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_TRACE, 2550 "%s: freq = %d weight = %d rssi = %d bss count = %d", 2551 __func__, chan_info->chan_freq, chan_info->weight, 2552 chan_info->rssi_agr, chan_info->bss_count); 2553 2554 chan_info++; 2555 } 2556 2557 sap_sort_chl_weight(ch_info_params); 2558 } 2559 2560 /** 2561 * sap_sort_chl_weight_40_mhz() - To sort 5 GHz channel in 40 MHz bandwidth 2562 * @mac_ctx: mac context handle 2563 * @sap_ctx: pointer to SAP context 2564 * @ch_info_params: pointer to the tSapChSelSpectInfo structure 2565 * 2566 * Return: QDF STATUS 2567 */ 2568 static QDF_STATUS 2569 sap_sort_chl_weight_40_mhz(struct mac_context *mac_ctx, 2570 struct sap_context *sap_ctx, 2571 struct sap_sel_ch_info *ch_info_params) 2572 { 2573 uint8_t i, j; 2574 struct sap_ch_info *chan_info; 2575 uint8_t minIdx; 2576 struct ch_params acs_ch_params = {0}; 2577 int8_t center_freq_diff; 2578 uint32_t combined_weight; 2579 uint32_t min_ch_weight; 2580 uint32_t valid_chans = 0; 2581 bool has_valid; 2582 2583 chan_info = ch_info_params->ch_info; 2584 2585 for (j = 0; j < ch_info_params->num_ch; j++) { 2586 2587 if (WLAN_REG_IS_24GHZ_CH_FREQ(chan_info[j].chan_freq)) 2588 continue; 2589 2590 if (chan_info[j].weight_calc_done) 2591 continue; 2592 2593 acs_ch_params.ch_width = CH_WIDTH_40MHZ; 2594 2595 wlan_reg_set_channel_params_for_pwrmode(mac_ctx->pdev, 2596 chan_info[j].chan_freq, 2597 0, &acs_ch_params, 2598 REG_CURRENT_PWR_MODE); 2599 2600 /* Check if the freq supports 40 Mhz */ 2601 if (acs_ch_params.ch_width != CH_WIDTH_40MHZ) { 2602 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 2; 2603 chan_info[j].weight_calc_done = true; 2604 continue; 2605 } 2606 2607 center_freq_diff = acs_ch_params.mhz_freq_seg0 - 2608 chan_info[j].chan_freq; 2609 2610 /* This channel frequency does not have all channels */ 2611 if (center_freq_diff != 10) { 2612 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 2; 2613 chan_info[j].weight_calc_done = true; 2614 continue; 2615 } 2616 2617 /* no other freq left for 40 Mhz operation in spectrum */ 2618 if (j + 1 > ch_info_params->num_ch) 2619 continue; 2620 2621 /* Check whether all frequencies are present for 40 Mhz */ 2622 2623 if (!((chan_info[j].chan_freq + 20) == 2624 chan_info[j + 1].chan_freq)) { 2625 /* 2626 * some channels does not exist in pSectInfo array, 2627 * skip this channel and those in the same 40 width 2628 */ 2629 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 2; 2630 chan_info[j].weight_calc_done = true; 2631 2632 if ((chan_info[j].chan_freq + 20) == 2633 chan_info[j + 1].chan_freq) { 2634 chan_info[j + 1].weight = 2635 SAP_ACS_WEIGHT_MAX * 2; 2636 chan_info[j + 1].weight_calc_done = true; 2637 } 2638 2639 continue; 2640 } 2641 2642 /* We have 2 channels to calculate cumulative weight */ 2643 2644 combined_weight = chan_info[j].weight + 2645 chan_info[j + 1].weight; 2646 2647 min_ch_weight = chan_info[j].weight; 2648 minIdx = 0; 2649 has_valid = false; 2650 2651 for (i = 0; i < 2; i++) { 2652 if (min_ch_weight > chan_info[j + i].weight) { 2653 min_ch_weight = chan_info[j + i].weight; 2654 minIdx = i; 2655 } 2656 chan_info[j + i].weight = SAP_ACS_WEIGHT_MAX * 2; 2657 chan_info[j + i].weight_calc_done = true; 2658 if (chan_info[j + i].valid) 2659 has_valid = true; 2660 } 2661 sap_override_6ghz_psc_minidx(mac_ctx, &chan_info[j], 2, 2662 &minIdx); 2663 2664 chan_info[j + minIdx].weight = combined_weight; 2665 if (has_valid) 2666 valid_chans++; 2667 2668 sap_debug("best freq = %d for 40mhz center freq %d combined weight = %d valid %d cnt %d", 2669 chan_info[j + minIdx].chan_freq, 2670 acs_ch_params.mhz_freq_seg0, 2671 combined_weight, has_valid, valid_chans); 2672 } 2673 2674 if (!valid_chans) { 2675 sap_debug("no valid chan bonding with CH_WIDTH_40MHZ"); 2676 return QDF_STATUS_E_INVAL; 2677 } 2678 2679 sap_sort_chl_weight(ch_info_params); 2680 2681 return QDF_STATUS_SUCCESS; 2682 } 2683 2684 /** 2685 * sap_restore_chan_weight() - Restore every channel weight to original 2686 * @spect_info: pointer to the tSapChSelSpectInfo structure 2687 * 2688 * Return: None 2689 */ 2690 static void sap_restore_chan_weight(struct sap_sel_ch_info *spect_info) 2691 { 2692 uint32_t i; 2693 struct sap_ch_info *spect_ch = spect_info->ch_info; 2694 2695 for (i = 0; i < spect_info->num_ch; i++) { 2696 spect_ch->weight = spect_ch->weight_copy; 2697 spect_ch->weight_calc_done = false; 2698 spect_ch++; 2699 } 2700 } 2701 2702 /** 2703 * sap_sort_chl_weight_all() - Function to sort the channels with the least 2704 * weight first 2705 * @mac_ctx: Pointer to mac_ctx structure 2706 * @sap_ctx: Pointer to sap_context structure 2707 * @ch_info_params: Pointer to the sap_sel_ch_info structure 2708 * @operating_band: Operating Band 2709 * @domain: Regulatory domain 2710 * @bw: Bandwidth 2711 * 2712 * Return: NULL 2713 */ 2714 static void sap_sort_chl_weight_all(struct mac_context *mac_ctx, 2715 struct sap_context *sap_ctx, 2716 struct sap_sel_ch_info *ch_info_params, 2717 uint32_t operating_band, 2718 v_REGDOMAIN_t domain, 2719 enum phy_ch_width *bw) 2720 { 2721 QDF_STATUS status = QDF_STATUS_SUCCESS; 2722 enum phy_ch_width ch_width = *bw; 2723 2724 next_bw: 2725 switch (ch_width) { 2726 case CH_WIDTH_40MHZ: 2727 /* 2728 * Assign max weight to all 5Ghz channels when operating band 2729 * is 11g and to all 2.4Ghz channels when operating band is 11a 2730 * or 11abg to avoid selection in ACS algorithm for starting SAP 2731 */ 2732 if (eCSR_DOT11_MODE_11g == operating_band) { 2733 sap_allocate_max_weight_40_mhz(ch_info_params); 2734 sap_sort_chl_weight_ht40_24_g( 2735 mac_ctx, 2736 ch_info_params, 2737 domain); 2738 } else { 2739 sap_allocate_max_weight_40_mhz_24_g(ch_info_params); 2740 status = sap_sort_chl_weight_40_mhz(mac_ctx, 2741 sap_ctx, 2742 ch_info_params); 2743 } 2744 break; 2745 case CH_WIDTH_80MHZ: 2746 case CH_WIDTH_80P80MHZ: 2747 status = sap_sort_chl_weight_80_mhz(mac_ctx, 2748 sap_ctx, 2749 ch_info_params); 2750 break; 2751 case CH_WIDTH_160MHZ: 2752 status = sap_sort_chl_weight_160_mhz(mac_ctx, 2753 sap_ctx, 2754 ch_info_params); 2755 break; 2756 #if defined(WLAN_FEATURE_11BE) 2757 case CH_WIDTH_320MHZ: 2758 status = sap_sort_chl_weight_320_mhz(mac_ctx, 2759 sap_ctx, 2760 ch_info_params); 2761 break; 2762 #endif 2763 case CH_WIDTH_20MHZ: 2764 default: 2765 /* Sorting the channels as per weights as 20MHz channels */ 2766 sap_sort_chl_weight(ch_info_params); 2767 status = QDF_STATUS_SUCCESS; 2768 } 2769 2770 if (status != QDF_STATUS_SUCCESS) { 2771 ch_width = wlan_reg_get_next_lower_bandwidth(ch_width); 2772 sap_restore_chan_weight(ch_info_params); 2773 goto next_bw; 2774 } 2775 2776 if (ch_width != *bw) { 2777 sap_info("channel width change from %d to %d", *bw, ch_width); 2778 *bw = ch_width; 2779 } 2780 } 2781 2782 /** 2783 * sap_is_ch_non_overlap() - returns true if non-overlapping channel 2784 * @sap_ctx: Sap context 2785 * @ch: channel number 2786 * 2787 * Returns: true if non-overlapping (1, 6, 11) channel, false otherwise 2788 */ 2789 static bool sap_is_ch_non_overlap(struct sap_context *sap_ctx, uint16_t ch) 2790 { 2791 if (sap_ctx->enableOverLapCh) 2792 return true; 2793 2794 if ((ch == CHANNEL_1) || (ch == CHANNEL_6) || (ch == CHANNEL_11)) 2795 return true; 2796 2797 return false; 2798 } 2799 2800 static enum phy_ch_width 2801 sap_acs_next_lower_bandwidth(enum phy_ch_width ch_width) 2802 { 2803 if (ch_width <= CH_WIDTH_20MHZ || 2804 ch_width == CH_WIDTH_5MHZ || 2805 ch_width == CH_WIDTH_10MHZ || 2806 ch_width >= CH_WIDTH_INVALID) 2807 return CH_WIDTH_INVALID; 2808 2809 return wlan_reg_get_next_lower_bandwidth(ch_width); 2810 } 2811 2812 void sap_sort_channel_list(struct mac_context *mac_ctx, uint8_t vdev_id, 2813 qdf_list_t *ch_list, struct sap_sel_ch_info *ch_info, 2814 v_REGDOMAIN_t *domain, uint32_t *operating_band) 2815 { 2816 uint8_t country[CDS_COUNTRY_CODE_LEN + 1]; 2817 struct sap_context *sap_ctx; 2818 enum phy_ch_width cur_bw; 2819 v_REGDOMAIN_t reg_domain; 2820 uint32_t op_band; 2821 2822 sap_ctx = mac_ctx->sap.sapCtxList[vdev_id].sap_context; 2823 cur_bw = sap_ctx->acs_cfg->ch_width; 2824 2825 /* Initialize the structure pointed by spect_info */ 2826 if (!sap_chan_sel_init(mac_ctx, ch_info, sap_ctx, false)) { 2827 sap_err("vdev %d ch select initialization failed", vdev_id); 2828 return; 2829 } 2830 2831 /* Compute the weight of the entire spectrum in the operating band */ 2832 sap_compute_spect_weight(ch_info, mac_ctx, ch_list, sap_ctx); 2833 2834 #ifdef FEATURE_AP_MCC_CH_AVOIDANCE 2835 /* process avoid channel IE to collect all channels to avoid */ 2836 sap_process_avoid_ie(mac_ctx, sap_ctx, ch_list, ch_info); 2837 #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ 2838 2839 wlan_reg_read_current_country(mac_ctx->psoc, country); 2840 wlan_reg_get_domain_from_country_code(®_domain, country, 2841 SOURCE_DRIVER); 2842 2843 SET_ACS_BAND(op_band, sap_ctx); 2844 2845 /* Sort the ch lst as per the computed weights, lesser weight first. */ 2846 sap_sort_chl_weight_all(mac_ctx, sap_ctx, ch_info, op_band, 2847 reg_domain, &cur_bw); 2848 sap_ctx->acs_cfg->ch_width = cur_bw; 2849 2850 if (domain) 2851 *domain = reg_domain; 2852 if (operating_band) 2853 *operating_band = op_band; 2854 } 2855 2856 uint32_t sap_select_channel(mac_handle_t mac_handle, 2857 struct sap_context *sap_ctx, 2858 qdf_list_t *scan_list) 2859 { 2860 /* DFS param object holding all the data req by the algo */ 2861 struct sap_sel_ch_info spect_info_obj = { NULL, 0 }; 2862 struct sap_sel_ch_info *spect_info = &spect_info_obj; 2863 uint8_t best_ch_num = SAP_CHANNEL_NOT_SELECTED; 2864 uint32_t best_ch_weight = SAP_ACS_WEIGHT_MAX; 2865 uint32_t ht40plus2gendch = 0; 2866 v_REGDOMAIN_t domain; 2867 uint8_t count; 2868 uint32_t operating_band = 0; 2869 struct mac_context *mac_ctx; 2870 uint32_t best_chan_freq = 0; 2871 2872 mac_ctx = MAC_CONTEXT(mac_handle); 2873 2874 sap_sort_channel_list(mac_ctx, sap_ctx->vdev_id, scan_list, 2875 spect_info, &domain, &operating_band); 2876 2877 /*Loop till get the best channel in the given range */ 2878 for (count = 0; count < spect_info->num_ch; count++) { 2879 if (!spect_info->ch_info[count].valid) 2880 continue; 2881 2882 best_chan_freq = spect_info->ch_info[count].chan_freq; 2883 /* check if best_ch_num is in preferred channel list */ 2884 best_chan_freq = 2885 sap_select_preferred_channel_from_channel_list( 2886 best_chan_freq, sap_ctx, spect_info); 2887 /* if not in preferred ch lst, go to nxt best ch */ 2888 if (best_chan_freq == SAP_CHANNEL_NOT_SELECTED) 2889 continue; 2890 2891 #ifdef FEATURE_AP_MCC_CH_AVOIDANCE 2892 /* 2893 * Weight of the channels(device's AP is operating) 2894 * increased to MAX+1 so that they will be chosen only 2895 * when there is no other best channel to choose 2896 */ 2897 if (!WLAN_REG_IS_6GHZ_CHAN_FREQ(best_chan_freq) && 2898 sap_check_in_avoid_ch_list(sap_ctx, 2899 wlan_reg_freq_to_chan(mac_ctx->pdev, best_chan_freq))) { 2900 best_chan_freq = SAP_CHANNEL_NOT_SELECTED; 2901 continue; 2902 } 2903 #endif 2904 2905 /* Give preference to Non-overlap channels */ 2906 if (WLAN_REG_IS_24GHZ_CH_FREQ(best_chan_freq) && 2907 !sap_is_ch_non_overlap(sap_ctx, 2908 wlan_reg_freq_to_chan(mac_ctx->pdev, best_chan_freq))) { 2909 sap_debug("freq %d is overlapping, skipped", 2910 best_chan_freq); 2911 continue; 2912 } 2913 2914 best_ch_weight = spect_info->ch_info[count].weight; 2915 sap_debug("Freq = %d selected as best frequency weight = %d", 2916 best_chan_freq, best_ch_weight); 2917 2918 break; 2919 } 2920 2921 /* 2922 * in case the best channel selected is not in PCL and there is another 2923 * channel which has same weightage and is in PCL, choose the one in 2924 * PCL 2925 */ 2926 if (!ch_in_pcl(sap_ctx, best_chan_freq)) { 2927 uint32_t cal_chan_freq, cal_chan_weight; 2928 2929 enum phy_ch_width pref_bw = sap_ctx->acs_cfg->ch_width; 2930 next_bw: 2931 sap_debug("check bw %d", pref_bw); 2932 for (count = 0; count < spect_info->num_ch; count++) { 2933 struct ch_params ch_params = {0}; 2934 2935 if (!spect_info->ch_info[count].valid) 2936 continue; 2937 2938 cal_chan_freq = spect_info->ch_info[count].chan_freq; 2939 cal_chan_weight = spect_info->ch_info[count].weight; 2940 /* skip pcl channel whose weight is bigger than best */ 2941 if (!ch_in_pcl(sap_ctx, cal_chan_freq) || 2942 (cal_chan_weight > best_ch_weight)) 2943 continue; 2944 2945 if (best_chan_freq == cal_chan_freq) 2946 continue; 2947 2948 if (sap_select_preferred_channel_from_channel_list( 2949 cal_chan_freq, sap_ctx, 2950 spect_info) 2951 == SAP_CHANNEL_NOT_SELECTED) 2952 continue; 2953 ch_params.ch_width = pref_bw; 2954 sap_acs_set_puncture_support(sap_ctx, &ch_params); 2955 wlan_reg_set_channel_params_for_pwrmode( 2956 mac_ctx->pdev, cal_chan_freq, 0, &ch_params, 2957 REG_CURRENT_PWR_MODE); 2958 if (ch_params.ch_width != pref_bw) 2959 continue; 2960 best_chan_freq = cal_chan_freq; 2961 sap_ctx->acs_cfg->ch_width = pref_bw; 2962 sap_debug("Changed best freq to %d Preferred freq bw %d", 2963 best_chan_freq, pref_bw); 2964 break; 2965 } 2966 if (count == spect_info->num_ch) { 2967 pref_bw = sap_acs_next_lower_bandwidth(pref_bw); 2968 if (pref_bw != CH_WIDTH_INVALID) 2969 goto next_bw; 2970 } 2971 } 2972 2973 sap_ctx->acs_cfg->pri_ch_freq = best_chan_freq; 2974 2975 /* Below code is for 2.4Ghz freq, so freq to channel is safe here */ 2976 2977 /* determine secondary channel for 2.4G channel 5, 6, 7 in HT40 */ 2978 if ((operating_band != eCSR_DOT11_MODE_11g) || 2979 (sap_ctx->acs_cfg->ch_width != CH_WIDTH_40MHZ)) 2980 goto sap_ch_sel_end; 2981 2982 best_ch_num = wlan_reg_freq_to_chan(mac_ctx->pdev, best_chan_freq); 2983 2984 if (REGDOMAIN_FCC == domain) 2985 ht40plus2gendch = HT40PLUS_2G_FCC_CH_END; 2986 else 2987 ht40plus2gendch = HT40PLUS_2G_EURJAP_CH_END; 2988 if ((best_ch_num >= HT40MINUS_2G_CH_START) && 2989 (best_ch_num <= ht40plus2gendch)) { 2990 int weight_below, weight_above, i; 2991 struct sap_ch_info *pspect_info; 2992 2993 weight_below = weight_above = SAP_ACS_WEIGHT_MAX; 2994 pspect_info = spect_info->ch_info; 2995 for (i = 0; i < spect_info->num_ch; i++) { 2996 if (pspect_info[i].chan_freq == (best_chan_freq - 20)) 2997 weight_below = pspect_info[i].weight; 2998 if (pspect_info[i].chan_freq == (best_ch_num + 20)) 2999 weight_above = pspect_info[i].weight; 3000 } 3001 3002 if (weight_below < weight_above) 3003 sap_ctx->acs_cfg->ht_sec_ch_freq = 3004 sap_ctx->acs_cfg->pri_ch_freq - 20; 3005 else 3006 sap_ctx->acs_cfg->ht_sec_ch_freq = 3007 sap_ctx->acs_cfg->pri_ch_freq + 20; 3008 } else if (best_ch_num >= 1 && best_ch_num <= 4) { 3009 sap_ctx->acs_cfg->ht_sec_ch_freq = 3010 sap_ctx->acs_cfg->pri_ch_freq + 20; 3011 } else if (best_ch_num >= ht40plus2gendch && best_ch_num <= 3012 HT40MINUS_2G_CH_END) { 3013 sap_ctx->acs_cfg->ht_sec_ch_freq = 3014 sap_ctx->acs_cfg->pri_ch_freq - 20; 3015 } else if (best_ch_num == 14) { 3016 sap_ctx->acs_cfg->ht_sec_ch_freq = 0; 3017 } 3018 sap_ctx->sec_ch_freq = sap_ctx->acs_cfg->ht_sec_ch_freq; 3019 3020 sap_ch_sel_end: 3021 /* Free all the allocated memory */ 3022 sap_chan_sel_exit(spect_info); 3023 3024 return best_chan_freq; 3025 } 3026 3027 #ifdef CONFIG_AFC_SUPPORT 3028 /** 3029 * sap_max_weight_invalidate_2ghz_channels() - Invalidate 2 GHz channel and set 3030 * max channel weight 3031 * @spect_info: pointer to array of channel spectrum info 3032 * 3033 * Return: None 3034 */ 3035 static void 3036 sap_max_weight_invalidate_2ghz_channels(struct sap_sel_ch_info *spect_info) 3037 { 3038 uint32_t i; 3039 struct sap_ch_info *spect_ch; 3040 3041 spect_ch = spect_info->ch_info; 3042 for (i = 0; i < spect_info->num_ch; i++) { 3043 if (WLAN_REG_IS_24GHZ_CH_FREQ(spect_ch[i].chan_freq)) { 3044 spect_ch[i].weight = SAP_ACS_WEIGHT_MAX; 3045 spect_ch[i].valid = false; 3046 } 3047 } 3048 } 3049 3050 /** 3051 * sap_compute_spect_max_power_weight() - Compute channel weight use max power 3052 * factor 3053 * @spect_info: pointer to SAP channel select structure of spectrum info 3054 * @mac: mac context 3055 * @sap_ctx: pointer to SAP context 3056 * 3057 * Return: None 3058 */ 3059 static void 3060 sap_compute_spect_max_power_weight(struct sap_sel_ch_info *spect_info, 3061 struct mac_context *mac, 3062 struct sap_context *sap_ctx) 3063 { 3064 uint32_t i; 3065 struct sap_ch_info *spect_ch = spect_info->ch_info; 3066 3067 for (i = 0; i < spect_info->num_ch; i++) { 3068 if (spect_ch[i].weight == SAP_ACS_WEIGHT_MAX) { 3069 spect_ch[i].weight_copy = spect_ch[i].weight; 3070 continue; 3071 } 3072 spect_ch[i].weight = SAPDFS_NORMALISE_1000 * 3073 sap_weight_channel_reg_max_power(sap_ctx, 3074 spect_ch[i].chan_freq); 3075 3076 sap_normalize_channel_weight_with_factors(mac, &spect_ch[i]); 3077 3078 if (spect_ch[i].weight > SAP_ACS_WEIGHT_MAX) 3079 spect_ch[i].weight = SAP_ACS_WEIGHT_MAX; 3080 spect_ch[i].weight_copy = spect_ch[i].weight; 3081 3082 sap_debug("freq = %d, weight = %d", 3083 spect_ch[i].chan_freq, spect_ch[i].weight); 3084 } 3085 } 3086 3087 /** 3088 * sap_afc_dcs_target_chan() - Select best channel frequency from sorted list 3089 * @mac_ctx: pointer to mac context 3090 * @sap_ctx: pointer to SAP context 3091 * @spect_info: pointer to SAP channel select structure of spectrum info 3092 * @cur_freq: SAP current home channel frequency 3093 * @cur_bw: SAP current channel bandwidth 3094 * @pref_bw: SAP target channel bandwidth can switch to 3095 * 3096 * Return: Best home channel frequency, if no available channel return 0. 3097 */ 3098 static qdf_freq_t 3099 sap_afc_dcs_target_chan(struct mac_context *mac_ctx, 3100 struct sap_context *sap_ctx, 3101 struct sap_sel_ch_info *spect_info, 3102 qdf_freq_t cur_freq, 3103 enum phy_ch_width cur_bw, 3104 enum phy_ch_width pref_bw) 3105 { 3106 uint32_t i, best_weight; 3107 qdf_freq_t best_chan_freq; 3108 struct sap_ch_info *spect_ch = spect_info->ch_info; 3109 3110 best_weight = spect_ch[0].weight; 3111 best_chan_freq = spect_ch[0].chan_freq; 3112 3113 /* 3114 * If current channel is already best channel and no bandwidth 3115 * change, return the current channel so no channel switch happen. 3116 */ 3117 if (cur_bw == pref_bw) { 3118 for (i = 1; i < spect_info->num_ch; i++) { 3119 if (!spect_ch[i].valid) 3120 continue; 3121 if (spect_ch[i].weight <= best_weight) { 3122 sap_debug("best freq = %d, weight = %d", 3123 spect_ch[i].chan_freq, 3124 spect_ch[i].weight); 3125 if (spect_ch[i].chan_freq == cur_freq) 3126 return cur_freq; 3127 } 3128 } 3129 } 3130 3131 return best_chan_freq; 3132 } 3133 3134 #ifdef WLAN_FEATURE_AFC_DCS_SKIP_ACS_RANGE 3135 /** 3136 * is_sap_afc_dcs_skip_acs() - API to get whether to skip ACS range 3137 * when doing automatically channel selection for AFC DCS. 3138 * @sap_ctx: SAP context pointer 3139 * 3140 * Return: True if skip ACS range and can select channel out of it. 3141 */ 3142 static bool is_sap_afc_dcs_skip_acs(struct sap_context *sap_ctx) 3143 { 3144 struct sap_acs_cfg *acs_cfg; 3145 uint32_t i; 3146 3147 if (!sap_ctx || !sap_ctx->acs_cfg) 3148 return false; 3149 3150 acs_cfg = sap_ctx->acs_cfg; 3151 for (i = 0; i < acs_cfg->ch_list_count; i++) { 3152 if (WLAN_REG_IS_6GHZ_CHAN_FREQ(acs_cfg->freq_list[i])) 3153 return false; 3154 } 3155 return true; 3156 } 3157 #else 3158 static bool is_sap_afc_dcs_skip_acs(struct sap_context *sap_ctx) 3159 { 3160 return false; 3161 } 3162 #endif 3163 3164 qdf_freq_t sap_afc_dcs_sel_chan(struct sap_context *sap_ctx, 3165 qdf_freq_t cur_freq, 3166 enum phy_ch_width cur_bw, 3167 enum phy_ch_width *pref_bw) 3168 { 3169 struct mac_context *mac_ctx; 3170 mac_handle_t mac_handle; 3171 struct sap_sel_ch_info spect_info_obj = {NULL, 0}; 3172 struct sap_sel_ch_info *spect_info = &spect_info_obj; 3173 qdf_freq_t target_freq; 3174 3175 if (!sap_ctx || !pref_bw) 3176 return SAP_CHANNEL_NOT_SELECTED; 3177 3178 if (!sap_ctx->acs_cfg || !sap_ctx->acs_cfg->acs_mode) { 3179 sap_debug("SAP session id %d acs not enable", 3180 sap_ctx->sessionId); 3181 return SAP_CHANNEL_NOT_SELECTED; 3182 } 3183 3184 mac_handle = cds_get_context(QDF_MODULE_ID_SME); 3185 mac_ctx = MAC_CONTEXT(mac_handle); 3186 if (!mac_ctx) 3187 return SAP_CHANNEL_NOT_SELECTED; 3188 3189 /* 3190 * If AFC response received after SAP started, SP channels are 3191 * not included in current ACS range, ignore ACS range check 3192 * in this scenario so that SAP can move to new SP channel. 3193 */ 3194 sap_chan_sel_init(mac_ctx, spect_info, sap_ctx, 3195 is_sap_afc_dcs_skip_acs(sap_ctx)); 3196 3197 sap_max_weight_invalidate_2ghz_channels(spect_info); 3198 3199 sap_compute_spect_max_power_weight(spect_info, mac_ctx, sap_ctx); 3200 3201 sap_sort_chl_weight_all(mac_ctx, sap_ctx, spect_info, 3202 eCSR_DOT11_MODE_11a, REGDOMAIN_FCC, pref_bw); 3203 3204 target_freq = sap_afc_dcs_target_chan(mac_ctx, 3205 sap_ctx, 3206 spect_info, 3207 cur_freq, 3208 cur_bw, 3209 *pref_bw); 3210 sap_chan_sel_exit(spect_info); 3211 return target_freq; 3212 } 3213 #endif 3214