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_chnl: 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_result: 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_handle: 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 * @channel_id: channel id 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 * @chn_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 * @chn_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 * @chn_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 * @chn_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 * @chn_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 * @center_freq: Central frequency for the given channel. 981 * @channel_id: channel_id 982 * @ch_start: the start of spect ch array 983 * @ch_end: the end of spect ch array 984 * 985 * sap_interference_rssi_count_5G considers the Adjacent channel rssi 986 * and data count(here number of BSS observed) 987 * 988 * Return: NA. 989 */ 990 991 static void sap_interference_rssi_count_5G(struct sap_ch_info *spect_ch, 992 uint16_t chan_width, 993 uint16_t sec_chan_offset, 994 uint32_t ch_freq0, 995 uint32_t ch_freq1, 996 uint32_t op_chan_freq, 997 struct sap_ch_info *ch_start, 998 struct sap_ch_info *ch_end) 999 { 1000 uint16_t num_ch; 1001 int32_t offset = 0; 1002 1003 sap_debug("freq = %d, ch width = %d, ch_freq0 = %d ch_freq1 = %d", 1004 op_chan_freq, chan_width, ch_freq0, ch_freq1); 1005 1006 switch (chan_width) { 1007 case eHT_CHANNEL_WIDTH_40MHZ: 1008 switch (sec_chan_offset) { 1009 /* Above the Primary Channel */ 1010 case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: 1011 sap_update_rssi_bsscount(spect_ch, 1, false, 1012 ch_start, ch_end); 1013 return; 1014 1015 /* Below the Primary channel */ 1016 case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: 1017 sap_update_rssi_bsscount(spect_ch, -1, false, 1018 ch_start, ch_end); 1019 return; 1020 } 1021 return; 1022 case eHT_CHANNEL_WIDTH_80MHZ: 1023 case eHT_CHANNEL_WIDTH_80P80MHZ: 1024 num_ch = 3; 1025 if ((ch_freq0 - op_chan_freq) == 30) { 1026 offset = 1; 1027 } else if ((ch_freq0 - op_chan_freq) == 10) { 1028 offset = -1; 1029 } else if ((ch_freq0 - op_chan_freq) == -10) { 1030 offset = -2; 1031 } else if ((ch_freq0 - op_chan_freq) == -30) { 1032 offset = -3; 1033 } 1034 break; 1035 case eHT_CHANNEL_WIDTH_160MHZ: 1036 num_ch = 7; 1037 if ((ch_freq0 - op_chan_freq) == 70) 1038 offset = 1; 1039 else if ((ch_freq0 - op_chan_freq) == 50) 1040 offset = -1; 1041 else if ((ch_freq0 - op_chan_freq) == 30) 1042 offset = -2; 1043 else if ((ch_freq0 - op_chan_freq) == 10) 1044 offset = -3; 1045 else if ((ch_freq0 - op_chan_freq) == -10) 1046 offset = -4; 1047 else if ((ch_freq0 - op_chan_freq) == -30) 1048 offset = -5; 1049 else if ((ch_freq0 - op_chan_freq) == -50) 1050 offset = -6; 1051 else if ((ch_freq0 - op_chan_freq) == -70) 1052 offset = -7; 1053 break; 1054 default: 1055 return; 1056 } 1057 1058 sap_update_rssi_bsscount_vht_5G(spect_ch, offset, num_ch, ch_start, 1059 ch_end); 1060 } 1061 1062 /** 1063 * sap_interference_rssi_count() - sap_interference_rssi_count 1064 * considers the Adjacent channel rssi 1065 * and data count(here number of BSS observed) 1066 * @spect_ch Channel Information 1067 * @ch_start: the start of spect ch array 1068 * @ch_end: the end of spect ch array 1069 * 1070 * sap_interference_rssi_count considers the Adjacent channel rssi 1071 * and data count(here number of BSS observed) 1072 * 1073 * Return: None. 1074 */ 1075 1076 static void sap_interference_rssi_count(struct sap_ch_info *spect_ch, 1077 struct sap_ch_info *ch_start, 1078 struct sap_ch_info *ch_end, 1079 struct mac_context *mac) 1080 { 1081 if (!spect_ch) { 1082 sap_err("spect_ch is NULL"); 1083 return; 1084 } 1085 1086 switch (wlan_reg_freq_to_chan(mac->pdev, spect_ch->chan_freq)) { 1087 case CHANNEL_1: 1088 sap_update_rssi_bsscount(spect_ch, 1, true, 1089 ch_start, ch_end); 1090 sap_update_rssi_bsscount(spect_ch, 2, true, 1091 ch_start, ch_end); 1092 sap_update_rssi_bsscount(spect_ch, 3, true, 1093 ch_start, ch_end); 1094 sap_update_rssi_bsscount(spect_ch, 4, true, 1095 ch_start, ch_end); 1096 break; 1097 1098 case CHANNEL_2: 1099 sap_update_rssi_bsscount(spect_ch, -1, true, 1100 ch_start, ch_end); 1101 sap_update_rssi_bsscount(spect_ch, 1, true, 1102 ch_start, ch_end); 1103 sap_update_rssi_bsscount(spect_ch, 2, true, 1104 ch_start, ch_end); 1105 sap_update_rssi_bsscount(spect_ch, 3, true, 1106 ch_start, ch_end); 1107 sap_update_rssi_bsscount(spect_ch, 4, true, 1108 ch_start, ch_end); 1109 break; 1110 case CHANNEL_3: 1111 sap_update_rssi_bsscount(spect_ch, -2, true, 1112 ch_start, ch_end); 1113 sap_update_rssi_bsscount(spect_ch, -1, 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, 2, true, 1118 ch_start, ch_end); 1119 sap_update_rssi_bsscount(spect_ch, 3, true, 1120 ch_start, ch_end); 1121 sap_update_rssi_bsscount(spect_ch, 4, true, 1122 ch_start, ch_end); 1123 break; 1124 case CHANNEL_4: 1125 sap_update_rssi_bsscount(spect_ch, -3, true, 1126 ch_start, ch_end); 1127 sap_update_rssi_bsscount(spect_ch, -2, true, 1128 ch_start, ch_end); 1129 sap_update_rssi_bsscount(spect_ch, -1, 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, 2, true, 1134 ch_start, ch_end); 1135 sap_update_rssi_bsscount(spect_ch, 3, true, 1136 ch_start, ch_end); 1137 sap_update_rssi_bsscount(spect_ch, 4, true, 1138 ch_start, ch_end); 1139 break; 1140 1141 case CHANNEL_5: 1142 case CHANNEL_6: 1143 case CHANNEL_7: 1144 case CHANNEL_8: 1145 case CHANNEL_9: 1146 case CHANNEL_10: 1147 sap_update_rssi_bsscount(spect_ch, -4, true, 1148 ch_start, ch_end); 1149 sap_update_rssi_bsscount(spect_ch, -3, true, 1150 ch_start, ch_end); 1151 sap_update_rssi_bsscount(spect_ch, -2, true, 1152 ch_start, ch_end); 1153 sap_update_rssi_bsscount(spect_ch, -1, 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, 2, true, 1158 ch_start, ch_end); 1159 sap_update_rssi_bsscount(spect_ch, 3, true, 1160 ch_start, ch_end); 1161 sap_update_rssi_bsscount(spect_ch, 4, true, 1162 ch_start, ch_end); 1163 break; 1164 1165 case CHANNEL_11: 1166 sap_update_rssi_bsscount(spect_ch, -4, true, 1167 ch_start, ch_end); 1168 sap_update_rssi_bsscount(spect_ch, -3, true, 1169 ch_start, ch_end); 1170 sap_update_rssi_bsscount(spect_ch, -2, true, 1171 ch_start, ch_end); 1172 sap_update_rssi_bsscount(spect_ch, -1, 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, 2, true, 1177 ch_start, ch_end); 1178 sap_update_rssi_bsscount(spect_ch, 3, true, 1179 ch_start, ch_end); 1180 break; 1181 1182 case CHANNEL_12: 1183 sap_update_rssi_bsscount(spect_ch, -4, true, 1184 ch_start, ch_end); 1185 sap_update_rssi_bsscount(spect_ch, -3, true, 1186 ch_start, ch_end); 1187 sap_update_rssi_bsscount(spect_ch, -2, true, 1188 ch_start, ch_end); 1189 sap_update_rssi_bsscount(spect_ch, -1, 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, 2, true, 1194 ch_start, ch_end); 1195 break; 1196 1197 case CHANNEL_13: 1198 sap_update_rssi_bsscount(spect_ch, -4, true, 1199 ch_start, ch_end); 1200 sap_update_rssi_bsscount(spect_ch, -3, true, 1201 ch_start, ch_end); 1202 sap_update_rssi_bsscount(spect_ch, -2, true, 1203 ch_start, ch_end); 1204 sap_update_rssi_bsscount(spect_ch, -1, true, 1205 ch_start, ch_end); 1206 sap_update_rssi_bsscount(spect_ch, 1, true, 1207 ch_start, ch_end); 1208 break; 1209 1210 case CHANNEL_14: 1211 sap_update_rssi_bsscount(spect_ch, -4, true, 1212 ch_start, ch_end); 1213 sap_update_rssi_bsscount(spect_ch, -3, true, 1214 ch_start, ch_end); 1215 sap_update_rssi_bsscount(spect_ch, -2, true, 1216 ch_start, ch_end); 1217 sap_update_rssi_bsscount(spect_ch, -1, true, 1218 ch_start, ch_end); 1219 break; 1220 1221 default: 1222 break; 1223 } 1224 } 1225 1226 /** 1227 * ch_in_pcl() - Is channel in the Preferred Channel List (PCL) 1228 * @sap_ctx: SAP context which contains the current PCL 1229 * @channel: Input channel number to be checked 1230 * 1231 * Check if a channel is in the preferred channel list 1232 * 1233 * Return: 1234 * true: channel is in PCL, 1235 * false: channel is not in PCL 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_compute_spect_weight() - Compute spectrum weight 1477 * @ch_info_params: Pointer to the tSpectInfoParams structure 1478 * @mac: Pointer to mac_context struucture 1479 * @pResult: Pointer to tScanResultHandle 1480 * @sap_ctx: Context of the SAP 1481 * 1482 * Main function for computing the weight of each channel in the 1483 * spectrum based on the RSSI value of the BSSes on the channel 1484 * and number of BSS 1485 */ 1486 static void sap_compute_spect_weight(struct sap_sel_ch_info *ch_info_params, 1487 struct mac_context *mac, 1488 qdf_list_t *scan_list, 1489 struct sap_context *sap_ctx) 1490 { 1491 int8_t rssi = 0; 1492 uint8_t chn_num = 0; 1493 struct sap_ch_info *ch_info = ch_info_params->ch_info; 1494 tSirMacHTChannelWidth ch_width = 0; 1495 uint16_t secondaryChannelOffset; 1496 uint32_t center_freq0, center_freq1, chan_freq; 1497 uint8_t i; 1498 bool found; 1499 struct sap_ch_info *ch_start = ch_info_params->ch_info; 1500 struct sap_ch_info *ch_end = ch_info_params->ch_info + 1501 ch_info_params->num_ch; 1502 qdf_list_node_t *cur_lst = NULL, *next_lst = NULL; 1503 struct scan_cache_node *cur_node = NULL; 1504 uint32_t rssi_bss_weight = 0, chan_status_weight = 0, power_weight = 0; 1505 uint32_t max_valid_weight_6ghz = 0; 1506 1507 sap_debug("Computing spectral weight"); 1508 1509 if (scan_list) 1510 qdf_list_peek_front(scan_list, &cur_lst); 1511 while (cur_lst) { 1512 cur_node = qdf_container_of(cur_lst, struct scan_cache_node, 1513 node); 1514 ch_info = ch_info_params->ch_info; 1515 /* Defining the default values, so that any value will hold the default values */ 1516 1517 secondaryChannelOffset = PHY_SINGLE_CHANNEL_CENTERED; 1518 center_freq0 = 0; 1519 center_freq1 = 0; 1520 1521 chan_freq = 1522 util_scan_entry_channel_frequency(cur_node->entry); 1523 1524 sap_upd_chan_spec_params(cur_node, &ch_width, 1525 &secondaryChannelOffset, 1526 ¢er_freq0, ¢er_freq1); 1527 1528 /* Processing for each tCsrScanResultInfo in the tCsrScanResult DLink list */ 1529 for (chn_num = 0; chn_num < ch_info_params->num_ch; 1530 chn_num++) { 1531 1532 if (chan_freq != ch_info->chan_freq) { 1533 ch_info++; 1534 continue; 1535 } 1536 1537 if (ch_info->rssi_agr < cur_node->entry->rssi_raw) 1538 ch_info->rssi_agr = cur_node->entry->rssi_raw; 1539 1540 ++ch_info->bss_count; 1541 1542 if (WLAN_REG_IS_24GHZ_CH_FREQ(chan_freq)) 1543 sap_interference_rssi_count(ch_info, ch_start, 1544 ch_end, mac); 1545 else 1546 sap_interference_rssi_count_5G( 1547 ch_info, ch_width, secondaryChannelOffset, 1548 center_freq0, center_freq1, chan_freq, 1549 ch_start, ch_end); 1550 1551 ch_info++; 1552 break; 1553 1554 } 1555 1556 qdf_list_peek_next(scan_list, cur_lst, &next_lst); 1557 cur_lst = next_lst; 1558 next_lst = NULL; 1559 } 1560 1561 /* Calculate the weights for all channels in the spectrum ch_info */ 1562 ch_info = ch_info_params->ch_info; 1563 1564 for (chn_num = 0; chn_num < (ch_info_params->num_ch); 1565 chn_num++) { 1566 1567 /* 1568 rssi : Maximum received signal strength among all BSS on that channel 1569 bss_count : Number of BSS on that channel 1570 */ 1571 1572 rssi = (int8_t)ch_info->rssi_agr; 1573 if (ch_in_pcl(sap_ctx, ch_info->chan_freq)) 1574 rssi -= PCL_RSSI_DISCOUNT; 1575 1576 if (rssi < SOFTAP_MIN_RSSI) 1577 rssi = SOFTAP_MIN_RSSI; 1578 1579 if (ch_info->weight == SAP_ACS_WEIGHT_MAX || 1580 ch_info->weight == SAP_ACS_WEIGHT_ADJUSTABLE) { 1581 ch_info->weight_copy = ch_info->weight; 1582 goto debug_info; 1583 } 1584 1585 /* There may be channels in scanlist, which were not sent to 1586 * FW for scanning as part of ACS scan list, but they do have an 1587 * effect on the neighbouring channels, so they help to find a 1588 * suitable channel, but there weight should be max as they were 1589 * and not meant to be included in the ACS scan results. 1590 * So just assign RSSI as -100, bsscount as 0, and weight as max 1591 * to them, so that they always stay low in sorting of best 1592 * channels which were included in ACS scan list 1593 */ 1594 found = false; 1595 for (i = 0; i < sap_ctx->num_of_channel; i++) { 1596 if (ch_info->chan_freq == sap_ctx->freq_list[i]) { 1597 /* Scan channel was included in ACS scan list */ 1598 found = true; 1599 break; 1600 } 1601 } 1602 1603 rssi_bss_weight = 0; 1604 chan_status_weight = 0; 1605 power_weight = 0; 1606 if (found) { 1607 rssi_bss_weight = sapweight_rssi_count( 1608 sap_ctx, 1609 rssi, 1610 ch_info->bss_count); 1611 chan_status_weight = sap_weight_channel_status( 1612 sap_ctx, 1613 sap_get_channel_status( 1614 mac, ch_info->chan_freq)); 1615 power_weight = sap_weight_channel_reg_max_power( 1616 sap_ctx, ch_info->chan_freq); 1617 ch_info->weight = SAPDFS_NORMALISE_1000 * 1618 (rssi_bss_weight + chan_status_weight 1619 + power_weight); 1620 } else { 1621 if (wlansap_is_channel_present_in_acs_list( 1622 ch_info->chan_freq, 1623 sap_ctx->acs_cfg->master_freq_list, 1624 sap_ctx->acs_cfg->master_ch_list_count)) 1625 ch_info->weight = SAP_ACS_WEIGHT_ADJUSTABLE; 1626 else 1627 ch_info->weight = SAP_ACS_WEIGHT_MAX; 1628 ch_info->rssi_agr = SOFTAP_MIN_RSSI; 1629 rssi = SOFTAP_MIN_RSSI; 1630 ch_info->bss_count = SOFTAP_MIN_COUNT; 1631 } 1632 1633 sap_normalize_channel_weight_with_factors(mac, ch_info); 1634 1635 if (ch_info->weight > SAP_ACS_WEIGHT_MAX) 1636 ch_info->weight = SAP_ACS_WEIGHT_MAX; 1637 ch_info->weight_copy = ch_info->weight; 1638 1639 debug_info: 1640 if (wlan_reg_is_6ghz_chan_freq(ch_info->chan_freq) && 1641 ch_info->weight < SAP_ACS_WEIGHT_ADJUSTABLE && 1642 max_valid_weight_6ghz < ch_info->weight) 1643 max_valid_weight_6ghz = ch_info->weight; 1644 1645 sap_debug("freq %d valid %d weight %d(%d,%d,%d) rssi %d bss %d", 1646 ch_info->chan_freq, ch_info->valid, 1647 ch_info->weight, rssi_bss_weight, 1648 chan_status_weight, power_weight, 1649 ch_info->rssi_agr, ch_info->bss_count); 1650 1651 ch_info++; 1652 } 1653 sap_update_6ghz_max_weight(ch_info_params, 1654 max_valid_weight_6ghz); 1655 sap_clear_channel_status(mac); 1656 } 1657 1658 void sap_chan_sel_exit(struct sap_sel_ch_info *ch_info_params) 1659 { 1660 /* Free all the allocated memory */ 1661 qdf_mem_free(ch_info_params->ch_info); 1662 } 1663 1664 /*========================================================================== 1665 FUNCTION sap_sort_chl_weight 1666 1667 DESCRIPTION 1668 Function to sort the channels with the least weight first for 20MHz channels 1669 1670 DEPENDENCIES 1671 NA. 1672 1673 PARAMETERS 1674 1675 IN 1676 ch_info_params : Pointer to the tSapChSelSpectInfo structure 1677 1678 RETURN VALUE 1679 void : NULL 1680 1681 SIDE EFFECTS 1682 ============================================================================*/ 1683 static void sap_sort_chl_weight(struct sap_sel_ch_info *ch_info_params) 1684 { 1685 struct sap_ch_info temp; 1686 1687 struct sap_ch_info *ch_info = NULL; 1688 uint32_t i = 0, j = 0, min_weight_index = 0; 1689 1690 ch_info = ch_info_params->ch_info; 1691 for (i = 0; i < ch_info_params->num_ch; i++) { 1692 min_weight_index = i; 1693 for (j = i + 1; j < ch_info_params->num_ch; j++) { 1694 if (ch_info[j].weight < 1695 ch_info[min_weight_index].weight) { 1696 min_weight_index = j; 1697 } else if (ch_info[j].weight == 1698 ch_info[min_weight_index].weight) { 1699 if (ch_info[j].bss_count < 1700 ch_info[min_weight_index].bss_count) 1701 min_weight_index = j; 1702 } 1703 } 1704 if (min_weight_index != i) { 1705 qdf_mem_copy(&temp, &ch_info[min_weight_index], 1706 sizeof(*ch_info)); 1707 qdf_mem_copy(&ch_info[min_weight_index], &ch_info[i], 1708 sizeof(*ch_info)); 1709 qdf_mem_copy(&ch_info[i], &temp, sizeof(*ch_info)); 1710 } 1711 } 1712 } 1713 1714 /** 1715 * sap_override_6ghz_psc_minidx() - override mindex to 6 GHz PSC channel's idx 1716 * @mac_ctx: pointer to max context 1717 * @spectinfo: Pointer to array of tSach_infoInfo 1718 * @count: number of tSach_infoInfo element to search 1719 * @minidx: index to be overridden 1720 * 1721 * Return: QDF STATUS 1722 */ 1723 static void 1724 sap_override_6ghz_psc_minidx(struct mac_context *mac_ctx, 1725 struct sap_ch_info *spectinfo, 1726 uint8_t count, 1727 uint8_t *minidx) 1728 { 1729 uint8_t i; 1730 1731 if (!mac_ctx->mlme_cfg->acs.acs_prefer_6ghz_psc) 1732 return; 1733 1734 for (i = 0; i < count; i++) { 1735 if (wlan_reg_is_6ghz_chan_freq( 1736 spectinfo[i].chan_freq) && 1737 wlan_reg_is_6ghz_psc_chan_freq( 1738 spectinfo[i].chan_freq)) { 1739 *minidx = i; 1740 return; 1741 } 1742 } 1743 } 1744 1745 /** 1746 * sap_sort_chl_weight_80_mhz() - to sort the channels with the least weight 1747 * @mac_ctx: pointer to max context 1748 * @sap_ctx: Pointer to the struct sap_context *structure 1749 * @ch_info_params: Pointer to the tSapChSelSpectInfo structure 1750 * Function to sort the channels with the least weight first for HT80 channels 1751 * 1752 * Return: QDF STATUS 1753 */ 1754 static QDF_STATUS 1755 sap_sort_chl_weight_80_mhz(struct mac_context *mac_ctx, 1756 struct sap_context *sap_ctx, 1757 struct sap_sel_ch_info *ch_info_params) 1758 { 1759 uint8_t i, j; 1760 struct sap_ch_info *chan_info; 1761 uint8_t minIdx; 1762 struct ch_params acs_ch_params = {0}; 1763 int8_t center_freq_diff; 1764 uint32_t combined_weight; 1765 uint32_t min_ch_weight; 1766 uint32_t valid_chans = 0; 1767 bool has_valid; 1768 1769 chan_info = ch_info_params->ch_info; 1770 1771 for (j = 0; j < ch_info_params->num_ch; j++) { 1772 1773 if (chan_info[j].weight_calc_done) 1774 continue; 1775 1776 acs_ch_params.ch_width = CH_WIDTH_80MHZ; 1777 sap_acs_set_puncture_support(sap_ctx, &acs_ch_params); 1778 1779 wlan_reg_set_channel_params_for_pwrmode(mac_ctx->pdev, 1780 chan_info[j].chan_freq, 1781 0, &acs_ch_params, 1782 REG_CURRENT_PWR_MODE); 1783 1784 /* Check if the freq supports 80 Mhz */ 1785 if (acs_ch_params.ch_width != CH_WIDTH_80MHZ) { 1786 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 4; 1787 chan_info[j].weight_calc_done = true; 1788 continue; 1789 } 1790 1791 center_freq_diff = acs_ch_params.mhz_freq_seg0 - 1792 chan_info[j].chan_freq; 1793 1794 /* This channel frequency does not have all channels */ 1795 if (center_freq_diff != 30) { 1796 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 4; 1797 chan_info[j].weight_calc_done = true; 1798 continue; 1799 } 1800 1801 /* no other freq left for 80 Mhz operation in spectrum */ 1802 if (j + 3 > ch_info_params->num_ch) 1803 continue; 1804 1805 /* Check whether all frequencies are present for 80 Mhz */ 1806 1807 if (!(((chan_info[j].chan_freq + 20) == 1808 chan_info[j + 1].chan_freq) && 1809 ((chan_info[j].chan_freq + 40) == 1810 chan_info[j + 2].chan_freq) && 1811 ((chan_info[j].chan_freq + 60) == 1812 chan_info[j + 3].chan_freq))) { 1813 /* 1814 * some channels does not exist in pSectInfo array, 1815 * skip this channel and those in the same HT80 width 1816 */ 1817 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 4; 1818 chan_info[j].weight_calc_done = true; 1819 if ((chan_info[j].chan_freq + 20) == 1820 chan_info[j + 1].chan_freq) { 1821 chan_info[j + 1].weight = 1822 SAP_ACS_WEIGHT_MAX * 4; 1823 chan_info[j + 1].weight_calc_done = true; 1824 } 1825 if ((chan_info[j].chan_freq + 40) == 1826 chan_info[j + 2].chan_freq) { 1827 chan_info[j + 2].weight = 1828 SAP_ACS_WEIGHT_MAX * 4; 1829 chan_info[j + 2].weight_calc_done = true; 1830 } 1831 if ((chan_info[j].chan_freq + 60) == 1832 chan_info[j + 3].chan_freq) { 1833 chan_info[j + 3].weight = 1834 SAP_ACS_WEIGHT_MAX * 4; 1835 chan_info[j + 3].weight_calc_done = true; 1836 } 1837 1838 continue; 1839 } 1840 1841 /* We have 4 channels to calculate cumulative weight */ 1842 1843 combined_weight = chan_info[j].weight + 1844 chan_info[j + 1].weight + 1845 chan_info[j + 2].weight + 1846 chan_info[j + 3].weight; 1847 1848 min_ch_weight = chan_info[j].weight; 1849 minIdx = 0; 1850 has_valid = false; 1851 1852 for (i = 0; i < 4; i++) { 1853 if (min_ch_weight > chan_info[j + i].weight) { 1854 min_ch_weight = chan_info[j + i].weight; 1855 minIdx = i; 1856 } 1857 chan_info[j + i].weight = SAP_ACS_WEIGHT_MAX * 4; 1858 chan_info[j + i].weight_calc_done = true; 1859 if (chan_info[j + i].valid) 1860 has_valid = true; 1861 } 1862 sap_override_6ghz_psc_minidx(mac_ctx, &chan_info[j], 4, 1863 &minIdx); 1864 1865 chan_info[j + minIdx].weight = combined_weight; 1866 if (has_valid) 1867 valid_chans++; 1868 1869 sap_debug("best freq = %d for 80mhz center freq %d combined weight = %d valid %d cnt %d", 1870 chan_info[j + minIdx].chan_freq, 1871 acs_ch_params.mhz_freq_seg0, 1872 combined_weight, has_valid, valid_chans); 1873 } 1874 1875 if (!valid_chans) { 1876 sap_debug("no valid chan bonding with CH_WIDTH_80MHZ"); 1877 return QDF_STATUS_E_INVAL; 1878 } 1879 1880 sap_sort_chl_weight(ch_info_params); 1881 1882 return QDF_STATUS_SUCCESS; 1883 } 1884 1885 /** 1886 * sap_sort_chl_weight_vht160() - to sort the channels with the least weight 1887 * @mac_ctx: pointer to max context 1888 * @sap_ctx: Pointer to the struct sap_context *structure 1889 * @ch_info_params: Pointer to the tSapChSelSpectInfo structure 1890 * 1891 * Function to sort the channels with the least weight first for VHT160 channels 1892 * 1893 * Return: QDF STATUS 1894 */ 1895 static QDF_STATUS 1896 sap_sort_chl_weight_160_mhz(struct mac_context *mac_ctx, 1897 struct sap_context *sap_ctx, 1898 struct sap_sel_ch_info *ch_info_params) 1899 { 1900 uint8_t i, j; 1901 struct sap_ch_info *chan_info; 1902 uint8_t minIdx; 1903 struct ch_params acs_ch_params = {0}; 1904 int8_t center_freq_diff; 1905 uint32_t combined_weight; 1906 uint32_t min_ch_weight; 1907 uint32_t valid_chans = 0; 1908 bool has_valid; 1909 1910 chan_info = ch_info_params->ch_info; 1911 1912 for (j = 0; j < ch_info_params->num_ch; j++) { 1913 1914 if (chan_info[j].weight_calc_done) 1915 continue; 1916 1917 acs_ch_params.ch_width = CH_WIDTH_160MHZ; 1918 sap_acs_set_puncture_support(sap_ctx, &acs_ch_params); 1919 1920 wlan_reg_set_channel_params_for_pwrmode(mac_ctx->pdev, 1921 chan_info[j].chan_freq, 1922 0, &acs_ch_params, 1923 REG_CURRENT_PWR_MODE); 1924 1925 /* Check if the freq supports 160 Mhz */ 1926 if (acs_ch_params.ch_width != CH_WIDTH_160MHZ) { 1927 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 8; 1928 chan_info[j].weight_calc_done = true; 1929 continue; 1930 } 1931 1932 center_freq_diff = acs_ch_params.mhz_freq_seg1 - 1933 chan_info[j].chan_freq; 1934 1935 /* This channel frequency does not have all channels */ 1936 if (center_freq_diff != 70) { 1937 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 8; 1938 chan_info[j].weight_calc_done = true; 1939 continue; 1940 } 1941 1942 /* no other freq left for 160 Mhz operation in spectrum */ 1943 if (j + 7 > ch_info_params->num_ch) 1944 continue; 1945 1946 /* Check whether all frequencies are present for 160 Mhz */ 1947 1948 if (!(((chan_info[j].chan_freq + 20) == 1949 chan_info[j + 1].chan_freq) && 1950 ((chan_info[j].chan_freq + 40) == 1951 chan_info[j + 2].chan_freq) && 1952 ((chan_info[j].chan_freq + 60) == 1953 chan_info[j + 3].chan_freq) && 1954 ((chan_info[j].chan_freq + 80) == 1955 chan_info[j + 4].chan_freq) && 1956 ((chan_info[j].chan_freq + 100) == 1957 chan_info[j + 5].chan_freq) && 1958 ((chan_info[j].chan_freq + 120) == 1959 chan_info[j + 6].chan_freq) && 1960 ((chan_info[j].chan_freq + 140) == 1961 chan_info[j + 7].chan_freq))) { 1962 /* 1963 * some channels does not exist in pSectInfo array, 1964 * skip this channel and those in the same VHT160 width 1965 */ 1966 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 8; 1967 chan_info[j].weight_calc_done = true; 1968 if ((chan_info[j].chan_freq + 20) == 1969 chan_info[j + 1].chan_freq) { 1970 chan_info[j + 1].weight = 1971 SAP_ACS_WEIGHT_MAX * 8; 1972 chan_info[j + 1].weight_calc_done = true; 1973 } 1974 if ((chan_info[j].chan_freq + 40) == 1975 chan_info[j + 2].chan_freq) { 1976 chan_info[j + 2].weight = 1977 SAP_ACS_WEIGHT_MAX * 8; 1978 chan_info[j + 2].weight_calc_done = true; 1979 } 1980 if ((chan_info[j].chan_freq + 60) == 1981 chan_info[j + 3].chan_freq) { 1982 chan_info[j + 3].weight = 1983 SAP_ACS_WEIGHT_MAX * 8; 1984 chan_info[j + 3].weight_calc_done = true; 1985 } 1986 if ((chan_info[j].chan_freq + 80) == 1987 chan_info[j + 4].chan_freq) { 1988 chan_info[j + 4].weight = 1989 SAP_ACS_WEIGHT_MAX * 8; 1990 chan_info[j + 4].weight_calc_done = true; 1991 } 1992 if ((chan_info[j].chan_freq + 100) == 1993 chan_info[j + 5].chan_freq) { 1994 chan_info[j + 5].weight = 1995 SAP_ACS_WEIGHT_MAX * 8; 1996 chan_info[j + 5].weight_calc_done = true; 1997 } 1998 if ((chan_info[j].chan_freq + 120) == 1999 chan_info[j + 6].chan_freq) { 2000 chan_info[j + 6].weight = 2001 SAP_ACS_WEIGHT_MAX * 8; 2002 chan_info[j + 6].weight_calc_done = true; 2003 } 2004 if ((chan_info[j].chan_freq + 140) == 2005 chan_info[j + 7].chan_freq) { 2006 chan_info[j + 7].weight = 2007 SAP_ACS_WEIGHT_MAX * 8; 2008 chan_info[j + 7].weight_calc_done = true; 2009 } 2010 2011 continue; 2012 } 2013 2014 /* We have 8 channels to calculate cumulative weight */ 2015 2016 combined_weight = chan_info[j].weight + 2017 chan_info[j + 1].weight + 2018 chan_info[j + 2].weight + 2019 chan_info[j + 3].weight + 2020 chan_info[j + 4].weight + 2021 chan_info[j + 5].weight + 2022 chan_info[j + 6].weight + 2023 chan_info[j + 7].weight; 2024 2025 min_ch_weight = chan_info[j].weight; 2026 minIdx = 0; 2027 has_valid = false; 2028 2029 for (i = 0; i < 8; i++) { 2030 if (min_ch_weight > chan_info[j + i].weight) { 2031 min_ch_weight = chan_info[j + i].weight; 2032 minIdx = i; 2033 } 2034 chan_info[j + i].weight = SAP_ACS_WEIGHT_MAX * 8; 2035 chan_info[j + i].weight_calc_done = true; 2036 if (chan_info[j + i].valid) 2037 has_valid = true; 2038 } 2039 sap_override_6ghz_psc_minidx(mac_ctx, &chan_info[j], 8, 2040 &minIdx); 2041 2042 chan_info[j + minIdx].weight = combined_weight; 2043 if (has_valid) 2044 valid_chans++; 2045 2046 sap_debug("best freq = %d for 160mhz center freq %d combined weight = %d valid %d cnt %d", 2047 chan_info[j + minIdx].chan_freq, 2048 acs_ch_params.mhz_freq_seg1, 2049 combined_weight, has_valid, valid_chans); 2050 } 2051 2052 if (!valid_chans) { 2053 sap_debug("no valid chan bonding with CH_WIDTH_160MHZ"); 2054 return QDF_STATUS_E_INVAL; 2055 } 2056 2057 sap_sort_chl_weight(ch_info_params); 2058 2059 return QDF_STATUS_SUCCESS; 2060 } 2061 2062 #if defined(WLAN_FEATURE_11BE) 2063 /** 2064 * sap_sort_chl_weight_320_mhz() - to sort the channels with the least weight 2065 * @mac_ctx: pointer to max context 2066 * @sap_ctx: Pointer to the struct sap_context *structure 2067 * @ch_info_params: Pointer to the tSapChSelSpectInfo structure 2068 * 2069 * Function to sort the channels with the least weight first for 320MHz channels 2070 * 2071 * Return: QDF STATUS 2072 */ 2073 static QDF_STATUS 2074 sap_sort_chl_weight_320_mhz(struct mac_context *mac_ctx, 2075 struct sap_context *sap_ctx, 2076 struct sap_sel_ch_info *ch_info_params) 2077 { 2078 uint8_t i, j; 2079 struct sap_ch_info *chan_info; 2080 uint8_t minIdx; 2081 struct ch_params acs_ch_params = {0}; 2082 uint32_t combined_weight; 2083 uint32_t min_ch_weight; 2084 uint32_t valid_chans = 0; 2085 bool has_valid; 2086 2087 chan_info = ch_info_params->ch_info; 2088 2089 for (j = 0; j < ch_info_params->num_ch; j++) { 2090 if (chan_info[j].weight_calc_done) 2091 continue; 2092 2093 qdf_mem_zero(&acs_ch_params, sizeof(acs_ch_params)); 2094 acs_ch_params.ch_width = CH_WIDTH_320MHZ; 2095 sap_acs_set_puncture_support(sap_ctx, &acs_ch_params); 2096 2097 wlan_reg_set_channel_params_for_pwrmode(mac_ctx->pdev, 2098 chan_info[j].chan_freq, 2099 0, &acs_ch_params, 2100 REG_CURRENT_PWR_MODE); 2101 2102 /* Check if the freq supports 320 Mhz */ 2103 if (acs_ch_params.ch_width != CH_WIDTH_320MHZ) { 2104 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 16; 2105 chan_info[j].weight_calc_done = true; 2106 continue; 2107 } 2108 2109 /* no other freq left for 320 Mhz operation in spectrum */ 2110 if (j + 15 > ch_info_params->num_ch) { 2111 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 16; 2112 chan_info[j].weight_calc_done = true; 2113 continue; 2114 } 2115 2116 /* Check whether all frequencies are present for 160 Mhz */ 2117 2118 if (!(((chan_info[j].chan_freq + 20) == 2119 chan_info[j + 1].chan_freq) && 2120 ((chan_info[j].chan_freq + 40) == 2121 chan_info[j + 2].chan_freq) && 2122 ((chan_info[j].chan_freq + 60) == 2123 chan_info[j + 3].chan_freq) && 2124 ((chan_info[j].chan_freq + 80) == 2125 chan_info[j + 4].chan_freq) && 2126 ((chan_info[j].chan_freq + 100) == 2127 chan_info[j + 5].chan_freq) && 2128 ((chan_info[j].chan_freq + 120) == 2129 chan_info[j + 6].chan_freq) && 2130 ((chan_info[j].chan_freq + 140) == 2131 chan_info[j + 7].chan_freq) && 2132 ((chan_info[j].chan_freq + 160) == 2133 chan_info[j + 8].chan_freq) && 2134 ((chan_info[j].chan_freq + 180) == 2135 chan_info[j + 9].chan_freq) && 2136 ((chan_info[j].chan_freq + 200) == 2137 chan_info[j + 10].chan_freq) && 2138 ((chan_info[j].chan_freq + 220) == 2139 chan_info[j + 11].chan_freq) && 2140 ((chan_info[j].chan_freq + 240) == 2141 chan_info[j + 12].chan_freq) && 2142 ((chan_info[j].chan_freq + 260) == 2143 chan_info[j + 13].chan_freq) && 2144 ((chan_info[j].chan_freq + 280) == 2145 chan_info[j + 14].chan_freq) && 2146 ((chan_info[j].chan_freq + 300) == 2147 chan_info[j + 15].chan_freq))) { 2148 /* 2149 * some channels does not exist in pSectInfo array, 2150 * skip this channel and those in the same ETH320 width 2151 */ 2152 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 16; 2153 chan_info[j].weight_calc_done = true; 2154 if ((chan_info[j].chan_freq + 20) == 2155 chan_info[j + 1].chan_freq) { 2156 chan_info[j + 1].weight = 2157 SAP_ACS_WEIGHT_MAX * 16; 2158 chan_info[j + 1].weight_calc_done = true; 2159 } 2160 if ((chan_info[j].chan_freq + 40) == 2161 chan_info[j + 2].chan_freq) { 2162 chan_info[j + 2].weight = 2163 SAP_ACS_WEIGHT_MAX * 16; 2164 chan_info[j + 2].weight_calc_done = true; 2165 } 2166 if ((chan_info[j].chan_freq + 60) == 2167 chan_info[j + 3].chan_freq) { 2168 chan_info[j + 3].weight = 2169 SAP_ACS_WEIGHT_MAX * 16; 2170 chan_info[j + 3].weight_calc_done = true; 2171 } 2172 if ((chan_info[j].chan_freq + 80) == 2173 chan_info[j + 4].chan_freq) { 2174 chan_info[j + 4].weight = 2175 SAP_ACS_WEIGHT_MAX * 16; 2176 chan_info[j + 4].weight_calc_done = true; 2177 } 2178 if ((chan_info[j].chan_freq + 100) == 2179 chan_info[j + 5].chan_freq) { 2180 chan_info[j + 5].weight = 2181 SAP_ACS_WEIGHT_MAX * 16; 2182 chan_info[j + 5].weight_calc_done = true; 2183 } 2184 if ((chan_info[j].chan_freq + 120) == 2185 chan_info[j + 6].chan_freq) { 2186 chan_info[j + 6].weight = 2187 SAP_ACS_WEIGHT_MAX * 16; 2188 chan_info[j + 6].weight_calc_done = true; 2189 } 2190 if ((chan_info[j].chan_freq + 140) == 2191 chan_info[j + 7].chan_freq) { 2192 chan_info[j + 7].weight = 2193 SAP_ACS_WEIGHT_MAX * 16; 2194 chan_info[j + 7].weight_calc_done = true; 2195 } 2196 if ((chan_info[j].chan_freq + 160) == 2197 chan_info[j + 8].chan_freq) { 2198 chan_info[j + 8].weight = 2199 SAP_ACS_WEIGHT_MAX * 16; 2200 chan_info[j + 8].weight_calc_done = true; 2201 } 2202 if ((chan_info[j].chan_freq + 180) == 2203 chan_info[j + 9].chan_freq) { 2204 chan_info[j + 9].weight = 2205 SAP_ACS_WEIGHT_MAX * 16; 2206 chan_info[j + 9].weight_calc_done = true; 2207 } 2208 if ((chan_info[j].chan_freq + 200) == 2209 chan_info[j + 10].chan_freq) { 2210 chan_info[j + 10].weight = 2211 SAP_ACS_WEIGHT_MAX * 16; 2212 chan_info[j + 10].weight_calc_done = true; 2213 } 2214 if ((chan_info[j].chan_freq + 220) == 2215 chan_info[j + 11].chan_freq) { 2216 chan_info[j + 11].weight = 2217 SAP_ACS_WEIGHT_MAX * 16; 2218 chan_info[j + 11].weight_calc_done = true; 2219 } 2220 if ((chan_info[j].chan_freq + 240) == 2221 chan_info[j + 12].chan_freq) { 2222 chan_info[j + 12].weight = 2223 SAP_ACS_WEIGHT_MAX * 16; 2224 chan_info[j + 12].weight_calc_done = true; 2225 } 2226 if ((chan_info[j].chan_freq + 260) == 2227 chan_info[j + 13].chan_freq) { 2228 chan_info[j + 13].weight = 2229 SAP_ACS_WEIGHT_MAX * 16; 2230 chan_info[j + 13].weight_calc_done = true; 2231 } 2232 if ((chan_info[j].chan_freq + 280) == 2233 chan_info[j + 14].chan_freq) { 2234 chan_info[j + 14].weight = 2235 SAP_ACS_WEIGHT_MAX * 16; 2236 chan_info[j + 14].weight_calc_done = true; 2237 } 2238 if ((chan_info[j].chan_freq + 300) == 2239 chan_info[j + 15].chan_freq) { 2240 chan_info[j + 15].weight = 2241 SAP_ACS_WEIGHT_MAX * 16; 2242 chan_info[j + 15].weight_calc_done = true; 2243 } 2244 2245 continue; 2246 } 2247 2248 /* We have 16 channels to calculate cumulative weight */ 2249 combined_weight = chan_info[j].weight + 2250 chan_info[j + 1].weight + 2251 chan_info[j + 2].weight + 2252 chan_info[j + 3].weight + 2253 chan_info[j + 4].weight + 2254 chan_info[j + 5].weight + 2255 chan_info[j + 6].weight + 2256 chan_info[j + 7].weight + 2257 chan_info[j + 8].weight + 2258 chan_info[j + 9].weight + 2259 chan_info[j + 10].weight + 2260 chan_info[j + 11].weight + 2261 chan_info[j + 12].weight + 2262 chan_info[j + 13].weight + 2263 chan_info[j + 14].weight + 2264 chan_info[j + 15].weight; 2265 2266 min_ch_weight = chan_info[j].weight; 2267 minIdx = 0; 2268 has_valid = false; 2269 for (i = 0; i < 16; i++) { 2270 if (min_ch_weight > chan_info[j + i].weight) { 2271 min_ch_weight = chan_info[j + i].weight; 2272 minIdx = i; 2273 } 2274 chan_info[j + i].weight = SAP_ACS_WEIGHT_MAX * 16; 2275 chan_info[j + i].weight_calc_done = true; 2276 if (chan_info[j + i].valid) 2277 has_valid = true; 2278 } 2279 sap_override_6ghz_psc_minidx(mac_ctx, &chan_info[j], 16, 2280 &minIdx); 2281 2282 chan_info[j + minIdx].weight = combined_weight; 2283 if (has_valid) 2284 valid_chans++; 2285 2286 sap_debug("best freq = %d for 320mhz center freq %d combined weight = %d valid %d cnt %d", 2287 chan_info[j + minIdx].chan_freq, 2288 acs_ch_params.mhz_freq_seg1, 2289 combined_weight, 2290 has_valid, valid_chans); 2291 } 2292 2293 if (!valid_chans) { 2294 sap_debug("no valid chan bonding with CH_WIDTH_320MHZ"); 2295 return QDF_STATUS_E_INVAL; 2296 } 2297 2298 sap_sort_chl_weight(ch_info_params); 2299 2300 return QDF_STATUS_SUCCESS; 2301 } 2302 #endif /* WLAN_FEATURE_11BE */ 2303 2304 /** 2305 * sap_allocate_max_weight_ht40_24_g() - allocate max weight for 40Mhz 2306 * to all 2.4Ghz channels 2307 * @spect_info_params: Pointer to the tSapChSelSpectInfo structure 2308 * 2309 * Return: none 2310 */ 2311 static void 2312 sap_allocate_max_weight_40_mhz_24_g(struct sap_sel_ch_info *spect_info_params) 2313 { 2314 struct sap_ch_info *spect_info; 2315 uint8_t j; 2316 2317 /* 2318 * Assign max weight for 40Mhz (SAP_ACS_WEIGHT_MAX * 2) to all 2319 * 2.4 Ghz channels 2320 */ 2321 spect_info = spect_info_params->ch_info; 2322 for (j = 0; j < spect_info_params->num_ch; j++) { 2323 if (WLAN_REG_IS_24GHZ_CH_FREQ(spect_info[j].chan_freq)) 2324 spect_info[j].weight = SAP_ACS_WEIGHT_MAX * 2; 2325 } 2326 } 2327 2328 /** 2329 * sap_allocate_max_weight_ht40_5_g() - allocate max weight for 40Mhz 2330 * to all 5Ghz channels 2331 * @spect_info_params: Pointer to the tSapChSelSpectInfo structure 2332 * 2333 * Return: none 2334 */ 2335 static void 2336 sap_allocate_max_weight_40_mhz(struct sap_sel_ch_info *spect_info_params) 2337 { 2338 struct sap_ch_info *spect_info; 2339 uint8_t j; 2340 2341 /* 2342 * Assign max weight for 40Mhz (SAP_ACS_WEIGHT_MAX * 2) to all 2343 * 5 Ghz channels 2344 */ 2345 spect_info = spect_info_params->ch_info; 2346 for (j = 0; j < spect_info_params->num_ch; j++) { 2347 if (WLAN_REG_IS_5GHZ_CH_FREQ(spect_info[j].chan_freq) || 2348 WLAN_REG_IS_6GHZ_CHAN_FREQ(spect_info[j].chan_freq)) 2349 spect_info[j].weight = SAP_ACS_WEIGHT_MAX * 2; 2350 } 2351 } 2352 2353 /** 2354 * sap_sort_chl_weight_ht40_24_g() - To sort channel with the least weight 2355 * @mac_ctx: Pointer to mac_ctx 2356 * @ch_info_params: Pointer to the sap_sel_ch_info structure 2357 * @domain: Regulatory domain 2358 * 2359 * Function to sort the channels with the least weight first for HT40 channels 2360 * 2361 * Return: none 2362 */ 2363 static void sap_sort_chl_weight_ht40_24_g( 2364 struct mac_context *mac_ctx, 2365 struct sap_sel_ch_info *ch_info_params, 2366 v_REGDOMAIN_t domain) 2367 { 2368 uint8_t i, j; 2369 struct sap_ch_info *chan_info; 2370 uint32_t tmp_weight1, tmp_weight2; 2371 uint32_t ht40plus2gendch = 0; 2372 uint32_t channel; 2373 uint32_t chan_freq; 2374 2375 chan_info = ch_info_params->ch_info; 2376 /* 2377 * for each HT40 channel, calculate the combined weight of the 2378 * two 20MHz weight 2379 */ 2380 for (i = 0; i < ARRAY_SIZE(acs_ht40_channels24_g); i++) { 2381 for (j = 0; j < ch_info_params->num_ch; j++) { 2382 channel = wlan_reg_freq_to_chan(mac_ctx->pdev, 2383 chan_info[j].chan_freq); 2384 if (channel == acs_ht40_channels24_g[i].chStartNum) 2385 break; 2386 } 2387 if (j == ch_info_params->num_ch) 2388 continue; 2389 2390 if (!((chan_info[j].chan_freq + 20) == 2391 chan_info[j + 4].chan_freq)) { 2392 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 2; 2393 continue; 2394 } 2395 /* 2396 * check if there is another channel combination possibility 2397 * e.g., {1, 5} & {5, 9} 2398 */ 2399 if ((chan_info[j + 4].chan_freq + 20) == 2400 chan_info[j + 8].chan_freq) { 2401 /* need to compare two channel pairs */ 2402 tmp_weight1 = chan_info[j].weight + 2403 chan_info[j + 4].weight; 2404 tmp_weight2 = chan_info[j + 4].weight + 2405 chan_info[j + 8].weight; 2406 if (tmp_weight1 <= tmp_weight2) { 2407 if (chan_info[j].weight <= 2408 chan_info[j + 4].weight) { 2409 chan_info[j].weight = 2410 tmp_weight1; 2411 chan_info[j + 4].weight = 2412 SAP_ACS_WEIGHT_MAX * 2; 2413 chan_info[j + 8].weight = 2414 SAP_ACS_WEIGHT_MAX * 2; 2415 } else { 2416 chan_info[j + 4].weight = 2417 tmp_weight1; 2418 /* for secondary channel selection */ 2419 chan_info[j].weight = 2420 SAP_ACS_WEIGHT_MAX * 2 2421 - 1; 2422 chan_info[j + 8].weight = 2423 SAP_ACS_WEIGHT_MAX * 2; 2424 } 2425 } else { 2426 if (chan_info[j + 4].weight <= 2427 chan_info[j + 8].weight) { 2428 chan_info[j + 4].weight = 2429 tmp_weight2; 2430 chan_info[j].weight = 2431 SAP_ACS_WEIGHT_MAX * 2; 2432 /* for secondary channel selection */ 2433 chan_info[j + 8].weight = 2434 SAP_ACS_WEIGHT_MAX * 2 2435 - 1; 2436 } else { 2437 chan_info[j + 8].weight = 2438 tmp_weight2; 2439 chan_info[j].weight = 2440 SAP_ACS_WEIGHT_MAX * 2; 2441 chan_info[j + 4].weight = 2442 SAP_ACS_WEIGHT_MAX * 2; 2443 } 2444 } 2445 } else { 2446 tmp_weight1 = chan_info[j].weight_copy + 2447 chan_info[j + 4].weight_copy; 2448 if (chan_info[j].weight_copy <= 2449 chan_info[j + 4].weight_copy) { 2450 chan_info[j].weight = tmp_weight1; 2451 chan_info[j + 4].weight = 2452 SAP_ACS_WEIGHT_MAX * 2; 2453 } else { 2454 chan_info[j + 4].weight = tmp_weight1; 2455 chan_info[j].weight = 2456 SAP_ACS_WEIGHT_MAX * 2; 2457 } 2458 } 2459 } 2460 /* 2461 * Every channel should be checked. Add the check for the omissive 2462 * channel. Mark the channel whose combination can't satisfy 40MHZ 2463 * as max value, so that it will be sorted to the bottom. 2464 */ 2465 if (REGDOMAIN_FCC == domain) 2466 ht40plus2gendch = HT40PLUS_2G_FCC_CH_END; 2467 else 2468 ht40plus2gendch = HT40PLUS_2G_EURJAP_CH_END; 2469 for (i = HT40MINUS_2G_CH_START; i <= ht40plus2gendch; i++) { 2470 chan_freq = wlan_reg_legacy_chan_to_freq(mac_ctx->pdev, i); 2471 for (j = 0; j < ch_info_params->num_ch; j++) { 2472 if (chan_info[j].chan_freq == chan_freq && 2473 ((chan_info[j].chan_freq + 20) != 2474 chan_info[j + 4].chan_freq) && 2475 ((chan_info[j].chan_freq - 20) != 2476 chan_info[j - 4].chan_freq)) 2477 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 2; 2478 } 2479 } 2480 for (i = ht40plus2gendch + 1; i <= HT40MINUS_2G_CH_END; i++) { 2481 chan_freq = wlan_reg_legacy_chan_to_freq(mac_ctx->pdev, i); 2482 for (j = 0; j < ch_info_params->num_ch; j++) { 2483 if (chan_info[j].chan_freq == chan_freq && 2484 (chan_info[j].chan_freq - 20) != 2485 chan_info[j - 4].chan_freq) 2486 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 2; 2487 } 2488 } 2489 2490 chan_info = ch_info_params->ch_info; 2491 for (j = 0; j < (ch_info_params->num_ch); j++) { 2492 QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_TRACE, 2493 "%s: freq = %d weight = %d rssi = %d bss count = %d", 2494 __func__, chan_info->chan_freq, chan_info->weight, 2495 chan_info->rssi_agr, chan_info->bss_count); 2496 2497 chan_info++; 2498 } 2499 2500 sap_sort_chl_weight(ch_info_params); 2501 } 2502 2503 /** 2504 * sap_sort_chl_weight_40_mhz() - To sort 5 GHz channel in 40 MHz bandwidth 2505 * @mac_ctx: mac context handle 2506 * @sap_ctx: pointer to SAP context 2507 * @ch_info_params: pointer to the tSapChSelSpectInfo structure 2508 * 2509 * Return: QDF STATUS 2510 */ 2511 static QDF_STATUS 2512 sap_sort_chl_weight_40_mhz(struct mac_context *mac_ctx, 2513 struct sap_context *sap_ctx, 2514 struct sap_sel_ch_info *ch_info_params) 2515 { 2516 uint8_t i, j; 2517 struct sap_ch_info *chan_info; 2518 uint8_t minIdx; 2519 struct ch_params acs_ch_params = {0}; 2520 int8_t center_freq_diff; 2521 uint32_t combined_weight; 2522 uint32_t min_ch_weight; 2523 uint32_t valid_chans = 0; 2524 bool has_valid; 2525 2526 chan_info = ch_info_params->ch_info; 2527 2528 for (j = 0; j < ch_info_params->num_ch; j++) { 2529 2530 if (WLAN_REG_IS_24GHZ_CH_FREQ(chan_info[j].chan_freq)) 2531 continue; 2532 2533 if (chan_info[j].weight_calc_done) 2534 continue; 2535 2536 acs_ch_params.ch_width = CH_WIDTH_40MHZ; 2537 2538 wlan_reg_set_channel_params_for_pwrmode(mac_ctx->pdev, 2539 chan_info[j].chan_freq, 2540 0, &acs_ch_params, 2541 REG_CURRENT_PWR_MODE); 2542 2543 /* Check if the freq supports 40 Mhz */ 2544 if (acs_ch_params.ch_width != CH_WIDTH_40MHZ) { 2545 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 2; 2546 chan_info[j].weight_calc_done = true; 2547 continue; 2548 } 2549 2550 center_freq_diff = acs_ch_params.mhz_freq_seg0 - 2551 chan_info[j].chan_freq; 2552 2553 /* This channel frequency does not have all channels */ 2554 if (center_freq_diff != 10) { 2555 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 2; 2556 chan_info[j].weight_calc_done = true; 2557 continue; 2558 } 2559 2560 /* no other freq left for 40 Mhz operation in spectrum */ 2561 if (j + 1 > ch_info_params->num_ch) 2562 continue; 2563 2564 /* Check whether all frequencies are present for 40 Mhz */ 2565 2566 if (!((chan_info[j].chan_freq + 20) == 2567 chan_info[j + 1].chan_freq)) { 2568 /* 2569 * some channels does not exist in pSectInfo array, 2570 * skip this channel and those in the same 40 width 2571 */ 2572 chan_info[j].weight = SAP_ACS_WEIGHT_MAX * 2; 2573 chan_info[j].weight_calc_done = true; 2574 2575 if ((chan_info[j].chan_freq + 20) == 2576 chan_info[j + 1].chan_freq) { 2577 chan_info[j + 1].weight = 2578 SAP_ACS_WEIGHT_MAX * 2; 2579 chan_info[j + 1].weight_calc_done = true; 2580 } 2581 2582 continue; 2583 } 2584 2585 /* We have 2 channels to calculate cumulative weight */ 2586 2587 combined_weight = chan_info[j].weight + 2588 chan_info[j + 1].weight; 2589 2590 min_ch_weight = chan_info[j].weight; 2591 minIdx = 0; 2592 has_valid = false; 2593 2594 for (i = 0; i < 2; i++) { 2595 if (min_ch_weight > chan_info[j + i].weight) { 2596 min_ch_weight = chan_info[j + i].weight; 2597 minIdx = i; 2598 } 2599 chan_info[j + i].weight = SAP_ACS_WEIGHT_MAX * 2; 2600 chan_info[j + i].weight_calc_done = true; 2601 if (chan_info[j + i].valid) 2602 has_valid = true; 2603 } 2604 sap_override_6ghz_psc_minidx(mac_ctx, &chan_info[j], 2, 2605 &minIdx); 2606 2607 chan_info[j + minIdx].weight = combined_weight; 2608 if (has_valid) 2609 valid_chans++; 2610 2611 sap_debug("best freq = %d for 40mhz center freq %d combined weight = %d valid %d cnt %d", 2612 chan_info[j + minIdx].chan_freq, 2613 acs_ch_params.mhz_freq_seg0, 2614 combined_weight, has_valid, valid_chans); 2615 } 2616 2617 if (!valid_chans) { 2618 sap_debug("no valid chan bonding with CH_WIDTH_40MHZ"); 2619 return QDF_STATUS_E_INVAL; 2620 } 2621 2622 sap_sort_chl_weight(ch_info_params); 2623 2624 return QDF_STATUS_SUCCESS; 2625 } 2626 2627 /** 2628 * sap_restore_chan_weight() - Restore every channel weight to original 2629 * @spect_info: pointer to the tSapChSelSpectInfo structure 2630 * 2631 * Return: None 2632 */ 2633 static void sap_restore_chan_weight(struct sap_sel_ch_info *spect_info) 2634 { 2635 uint32_t i; 2636 struct sap_ch_info *spect_ch = spect_info->ch_info; 2637 2638 for (i = 0; i < spect_info->num_ch; i++) { 2639 spect_ch->weight = spect_ch->weight_copy; 2640 spect_ch->weight_calc_done = false; 2641 spect_ch++; 2642 } 2643 } 2644 2645 /** 2646 * sap_sort_chl_weight_all() - Function to sort the channels with the least 2647 * weight first 2648 * @mac_ctx: Pointer to mac_ctx structure 2649 * @sap_ctx: Pointer to sap_context structure 2650 * @ch_info_params: Pointer to the sap_sel_ch_info structure 2651 * @operating_band: Operating Band 2652 * @domain: Regulatory domain 2653 * @bw: Bandwidth 2654 * 2655 * Return: NULL 2656 */ 2657 static void sap_sort_chl_weight_all(struct mac_context *mac_ctx, 2658 struct sap_context *sap_ctx, 2659 struct sap_sel_ch_info *ch_info_params, 2660 uint32_t operating_band, 2661 v_REGDOMAIN_t domain, 2662 enum phy_ch_width *bw) 2663 { 2664 QDF_STATUS status = QDF_STATUS_SUCCESS; 2665 enum phy_ch_width ch_width = *bw; 2666 2667 next_bw: 2668 switch (ch_width) { 2669 case CH_WIDTH_40MHZ: 2670 /* 2671 * Assign max weight to all 5Ghz channels when operating band 2672 * is 11g and to all 2.4Ghz channels when operating band is 11a 2673 * or 11abg to avoid selection in ACS algorithm for starting SAP 2674 */ 2675 if (eCSR_DOT11_MODE_11g == operating_band) { 2676 sap_allocate_max_weight_40_mhz(ch_info_params); 2677 sap_sort_chl_weight_ht40_24_g( 2678 mac_ctx, 2679 ch_info_params, 2680 domain); 2681 } else { 2682 sap_allocate_max_weight_40_mhz_24_g(ch_info_params); 2683 status = sap_sort_chl_weight_40_mhz(mac_ctx, 2684 sap_ctx, 2685 ch_info_params); 2686 } 2687 break; 2688 case CH_WIDTH_80MHZ: 2689 case CH_WIDTH_80P80MHZ: 2690 status = sap_sort_chl_weight_80_mhz(mac_ctx, 2691 sap_ctx, 2692 ch_info_params); 2693 break; 2694 case CH_WIDTH_160MHZ: 2695 status = sap_sort_chl_weight_160_mhz(mac_ctx, 2696 sap_ctx, 2697 ch_info_params); 2698 break; 2699 #if defined(WLAN_FEATURE_11BE) 2700 case CH_WIDTH_320MHZ: 2701 status = sap_sort_chl_weight_320_mhz(mac_ctx, 2702 sap_ctx, 2703 ch_info_params); 2704 break; 2705 #endif 2706 case CH_WIDTH_20MHZ: 2707 default: 2708 /* Sorting the channels as per weights as 20MHz channels */ 2709 sap_sort_chl_weight(ch_info_params); 2710 status = QDF_STATUS_SUCCESS; 2711 } 2712 2713 if (status != QDF_STATUS_SUCCESS) { 2714 ch_width = wlan_reg_get_next_lower_bandwidth(ch_width); 2715 sap_restore_chan_weight(ch_info_params); 2716 goto next_bw; 2717 } 2718 2719 if (ch_width != *bw) { 2720 sap_info("channel width change from %d to %d", *bw, ch_width); 2721 *bw = ch_width; 2722 } 2723 } 2724 2725 /** 2726 * sap_is_ch_non_overlap() - returns true if non-overlapping channel 2727 * @sap_ctx: Sap context 2728 * @ch: channel number 2729 * 2730 * Returns: true if non-overlapping (1, 6, 11) channel, false otherwise 2731 */ 2732 static bool sap_is_ch_non_overlap(struct sap_context *sap_ctx, uint16_t ch) 2733 { 2734 if (sap_ctx->enableOverLapCh) 2735 return true; 2736 2737 if ((ch == CHANNEL_1) || (ch == CHANNEL_6) || (ch == CHANNEL_11)) 2738 return true; 2739 2740 return false; 2741 } 2742 2743 static enum phy_ch_width 2744 sap_acs_next_lower_bandwidth(enum phy_ch_width ch_width) 2745 { 2746 if (ch_width <= CH_WIDTH_20MHZ || 2747 ch_width == CH_WIDTH_5MHZ || 2748 ch_width == CH_WIDTH_10MHZ || 2749 ch_width >= CH_WIDTH_INVALID) 2750 return CH_WIDTH_INVALID; 2751 2752 return wlan_reg_get_next_lower_bandwidth(ch_width); 2753 } 2754 2755 void sap_sort_channel_list(struct mac_context *mac_ctx, uint8_t vdev_id, 2756 qdf_list_t *ch_list, struct sap_sel_ch_info *ch_info, 2757 v_REGDOMAIN_t *domain, uint32_t *operating_band) 2758 { 2759 uint8_t country[CDS_COUNTRY_CODE_LEN + 1]; 2760 struct sap_context *sap_ctx; 2761 enum phy_ch_width cur_bw; 2762 v_REGDOMAIN_t reg_domain; 2763 uint32_t op_band; 2764 2765 sap_ctx = mac_ctx->sap.sapCtxList[vdev_id].sap_context; 2766 cur_bw = sap_ctx->acs_cfg->ch_width; 2767 2768 /* Initialize the structure pointed by spect_info */ 2769 if (!sap_chan_sel_init(mac_ctx, ch_info, sap_ctx, false)) { 2770 sap_err("vdev %d ch select initialization failed", vdev_id); 2771 return; 2772 } 2773 2774 /* Compute the weight of the entire spectrum in the operating band */ 2775 sap_compute_spect_weight(ch_info, mac_ctx, ch_list, sap_ctx); 2776 2777 #ifdef FEATURE_AP_MCC_CH_AVOIDANCE 2778 /* process avoid channel IE to collect all channels to avoid */ 2779 sap_process_avoid_ie(mac_ctx, sap_ctx, ch_list, ch_info); 2780 #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ 2781 2782 wlan_reg_read_current_country(mac_ctx->psoc, country); 2783 wlan_reg_get_domain_from_country_code(®_domain, country, 2784 SOURCE_DRIVER); 2785 2786 SET_ACS_BAND(op_band, sap_ctx); 2787 2788 /* Sort the ch lst as per the computed weights, lesser weight first. */ 2789 sap_sort_chl_weight_all(mac_ctx, sap_ctx, ch_info, op_band, 2790 reg_domain, &cur_bw); 2791 sap_ctx->acs_cfg->ch_width = cur_bw; 2792 2793 if (domain) 2794 *domain = reg_domain; 2795 if (operating_band) 2796 *operating_band = op_band; 2797 } 2798 2799 uint32_t sap_select_channel(mac_handle_t mac_handle, 2800 struct sap_context *sap_ctx, 2801 qdf_list_t *scan_list) 2802 { 2803 /* DFS param object holding all the data req by the algo */ 2804 struct sap_sel_ch_info spect_info_obj = { NULL, 0 }; 2805 struct sap_sel_ch_info *spect_info = &spect_info_obj; 2806 uint8_t best_ch_num = SAP_CHANNEL_NOT_SELECTED; 2807 uint32_t best_ch_weight = SAP_ACS_WEIGHT_MAX; 2808 uint32_t ht40plus2gendch = 0; 2809 v_REGDOMAIN_t domain; 2810 uint8_t count; 2811 uint32_t operating_band = 0; 2812 struct mac_context *mac_ctx; 2813 uint32_t best_chan_freq = 0; 2814 2815 mac_ctx = MAC_CONTEXT(mac_handle); 2816 2817 sap_sort_channel_list(mac_ctx, sap_ctx->vdev_id, scan_list, 2818 spect_info, &domain, &operating_band); 2819 2820 /*Loop till get the best channel in the given range */ 2821 for (count = 0; count < spect_info->num_ch; count++) { 2822 if (!spect_info->ch_info[count].valid) 2823 continue; 2824 2825 best_chan_freq = spect_info->ch_info[count].chan_freq; 2826 /* check if best_ch_num is in preferred channel list */ 2827 best_chan_freq = 2828 sap_select_preferred_channel_from_channel_list( 2829 best_chan_freq, sap_ctx, spect_info); 2830 /* if not in preferred ch lst, go to nxt best ch */ 2831 if (best_chan_freq == SAP_CHANNEL_NOT_SELECTED) 2832 continue; 2833 2834 #ifdef FEATURE_AP_MCC_CH_AVOIDANCE 2835 /* 2836 * Weight of the channels(device's AP is operating) 2837 * increased to MAX+1 so that they will be chosen only 2838 * when there is no other best channel to choose 2839 */ 2840 if (!WLAN_REG_IS_6GHZ_CHAN_FREQ(best_chan_freq) && 2841 sap_check_in_avoid_ch_list(sap_ctx, 2842 wlan_reg_freq_to_chan(mac_ctx->pdev, best_chan_freq))) { 2843 best_chan_freq = SAP_CHANNEL_NOT_SELECTED; 2844 continue; 2845 } 2846 #endif 2847 2848 /* Give preference to Non-overlap channels */ 2849 if (WLAN_REG_IS_24GHZ_CH_FREQ(best_chan_freq) && 2850 !sap_is_ch_non_overlap(sap_ctx, 2851 wlan_reg_freq_to_chan(mac_ctx->pdev, best_chan_freq))) { 2852 sap_debug("freq %d is overlapping, skipped", 2853 best_chan_freq); 2854 continue; 2855 } 2856 2857 best_ch_weight = spect_info->ch_info[count].weight; 2858 sap_debug("Freq = %d selected as best frequency weight = %d", 2859 best_chan_freq, best_ch_weight); 2860 2861 break; 2862 } 2863 2864 /* 2865 * in case the best channel selected is not in PCL and there is another 2866 * channel which has same weightage and is in PCL, choose the one in 2867 * PCL 2868 */ 2869 if (!ch_in_pcl(sap_ctx, best_chan_freq)) { 2870 uint32_t cal_chan_freq, cal_chan_weight; 2871 2872 enum phy_ch_width pref_bw = sap_ctx->acs_cfg->ch_width; 2873 next_bw: 2874 sap_debug("check bw %d", pref_bw); 2875 for (count = 0; count < spect_info->num_ch; count++) { 2876 struct ch_params ch_params = {0}; 2877 2878 if (!spect_info->ch_info[count].valid) 2879 continue; 2880 2881 cal_chan_freq = spect_info->ch_info[count].chan_freq; 2882 cal_chan_weight = spect_info->ch_info[count].weight; 2883 /* skip pcl channel whose weight is bigger than best */ 2884 if (!ch_in_pcl(sap_ctx, cal_chan_freq) || 2885 (cal_chan_weight > best_ch_weight)) 2886 continue; 2887 2888 if (best_chan_freq == cal_chan_freq) 2889 continue; 2890 2891 if (sap_select_preferred_channel_from_channel_list( 2892 cal_chan_freq, sap_ctx, 2893 spect_info) 2894 == SAP_CHANNEL_NOT_SELECTED) 2895 continue; 2896 ch_params.ch_width = pref_bw; 2897 sap_acs_set_puncture_support(sap_ctx, &ch_params); 2898 wlan_reg_set_channel_params_for_pwrmode( 2899 mac_ctx->pdev, cal_chan_freq, 0, &ch_params, 2900 REG_CURRENT_PWR_MODE); 2901 if (ch_params.ch_width != pref_bw) 2902 continue; 2903 best_chan_freq = cal_chan_freq; 2904 sap_ctx->acs_cfg->ch_width = pref_bw; 2905 sap_debug("Changed best freq to %d Preferred freq bw %d", 2906 best_chan_freq, pref_bw); 2907 break; 2908 } 2909 if (count == spect_info->num_ch) { 2910 pref_bw = sap_acs_next_lower_bandwidth(pref_bw); 2911 if (pref_bw != CH_WIDTH_INVALID) 2912 goto next_bw; 2913 } 2914 } 2915 2916 sap_ctx->acs_cfg->pri_ch_freq = best_chan_freq; 2917 2918 /* Below code is for 2.4Ghz freq, so freq to channel is safe here */ 2919 2920 /* determine secondary channel for 2.4G channel 5, 6, 7 in HT40 */ 2921 if ((operating_band != eCSR_DOT11_MODE_11g) || 2922 (sap_ctx->acs_cfg->ch_width != CH_WIDTH_40MHZ)) 2923 goto sap_ch_sel_end; 2924 2925 best_ch_num = wlan_reg_freq_to_chan(mac_ctx->pdev, best_chan_freq); 2926 2927 if (REGDOMAIN_FCC == domain) 2928 ht40plus2gendch = HT40PLUS_2G_FCC_CH_END; 2929 else 2930 ht40plus2gendch = HT40PLUS_2G_EURJAP_CH_END; 2931 if ((best_ch_num >= HT40MINUS_2G_CH_START) && 2932 (best_ch_num <= ht40plus2gendch)) { 2933 int weight_below, weight_above, i; 2934 struct sap_ch_info *pspect_info; 2935 2936 weight_below = weight_above = SAP_ACS_WEIGHT_MAX; 2937 pspect_info = spect_info->ch_info; 2938 for (i = 0; i < spect_info->num_ch; i++) { 2939 if (pspect_info[i].chan_freq == (best_chan_freq - 20)) 2940 weight_below = pspect_info[i].weight; 2941 if (pspect_info[i].chan_freq == (best_ch_num + 20)) 2942 weight_above = pspect_info[i].weight; 2943 } 2944 2945 if (weight_below < weight_above) 2946 sap_ctx->acs_cfg->ht_sec_ch_freq = 2947 sap_ctx->acs_cfg->pri_ch_freq - 20; 2948 else 2949 sap_ctx->acs_cfg->ht_sec_ch_freq = 2950 sap_ctx->acs_cfg->pri_ch_freq + 20; 2951 } else if (best_ch_num >= 1 && best_ch_num <= 4) { 2952 sap_ctx->acs_cfg->ht_sec_ch_freq = 2953 sap_ctx->acs_cfg->pri_ch_freq + 20; 2954 } else if (best_ch_num >= ht40plus2gendch && best_ch_num <= 2955 HT40MINUS_2G_CH_END) { 2956 sap_ctx->acs_cfg->ht_sec_ch_freq = 2957 sap_ctx->acs_cfg->pri_ch_freq - 20; 2958 } else if (best_ch_num == 14) { 2959 sap_ctx->acs_cfg->ht_sec_ch_freq = 0; 2960 } 2961 sap_ctx->sec_ch_freq = sap_ctx->acs_cfg->ht_sec_ch_freq; 2962 2963 sap_ch_sel_end: 2964 /* Free all the allocated memory */ 2965 sap_chan_sel_exit(spect_info); 2966 2967 return best_chan_freq; 2968 } 2969 2970 #ifdef CONFIG_AFC_SUPPORT 2971 /** 2972 * sap_max_weight_invalidate_2ghz_channels() - Invalidate 2 GHz channel and set 2973 * max channel weight 2974 * @spect_info: pointer to array of channel spectrum info 2975 * 2976 * Return: None 2977 */ 2978 static void 2979 sap_max_weight_invalidate_2ghz_channels(struct sap_sel_ch_info *spect_info) 2980 { 2981 uint32_t i; 2982 struct sap_ch_info *spect_ch; 2983 2984 spect_ch = spect_info->ch_info; 2985 for (i = 0; i < spect_info->num_ch; i++) { 2986 if (WLAN_REG_IS_24GHZ_CH_FREQ(spect_ch[i].chan_freq)) { 2987 spect_ch[i].weight = SAP_ACS_WEIGHT_MAX; 2988 spect_ch[i].valid = false; 2989 } 2990 } 2991 } 2992 2993 /** 2994 * sap_compute_spect_max_power_weight() - Compute channel weight use max power 2995 * factor 2996 * @spect_info: pointer to SAP channel select structure of spectrum info 2997 * @mac: mac context 2998 * @sap_ctx: pointer to SAP context 2999 * 3000 * Return: None 3001 */ 3002 static void 3003 sap_compute_spect_max_power_weight(struct sap_sel_ch_info *spect_info, 3004 struct mac_context *mac, 3005 struct sap_context *sap_ctx) 3006 { 3007 uint32_t i; 3008 struct sap_ch_info *spect_ch = spect_info->ch_info; 3009 3010 for (i = 0; i < spect_info->num_ch; i++) { 3011 if (spect_ch[i].weight == SAP_ACS_WEIGHT_MAX) { 3012 spect_ch[i].weight_copy = spect_ch[i].weight; 3013 continue; 3014 } 3015 spect_ch[i].weight = SAPDFS_NORMALISE_1000 * 3016 sap_weight_channel_reg_max_power(sap_ctx, 3017 spect_ch[i].chan_freq); 3018 3019 sap_normalize_channel_weight_with_factors(mac, &spect_ch[i]); 3020 3021 if (spect_ch[i].weight > SAP_ACS_WEIGHT_MAX) 3022 spect_ch[i].weight = SAP_ACS_WEIGHT_MAX; 3023 spect_ch[i].weight_copy = spect_ch[i].weight; 3024 3025 sap_debug("freq = %d, weight = %d", 3026 spect_ch[i].chan_freq, spect_ch[i].weight); 3027 } 3028 } 3029 3030 /** 3031 * sap_afc_dcs_target_chan() - Select best channel frequency from sorted list 3032 * @mac_ctx: pointer to mac context 3033 * @sap_ctx: pointer to SAP context 3034 * @spect_info: pointer to SAP channel select structure of spectrum info 3035 * @cur_freq: SAP current home channel frequency 3036 * @cur_bw: SAP current channel bandwidth 3037 * @pref_bw: SAP target channel bandwidth can switch to 3038 * 3039 * Return: Best home channel frequency, if no available channel return 0. 3040 */ 3041 static qdf_freq_t 3042 sap_afc_dcs_target_chan(struct mac_context *mac_ctx, 3043 struct sap_context *sap_ctx, 3044 struct sap_sel_ch_info *spect_info, 3045 qdf_freq_t cur_freq, 3046 enum phy_ch_width cur_bw, 3047 enum phy_ch_width pref_bw) 3048 { 3049 uint32_t i, best_weight; 3050 qdf_freq_t best_chan_freq; 3051 struct sap_ch_info *spect_ch = spect_info->ch_info; 3052 3053 best_weight = spect_ch[0].weight; 3054 best_chan_freq = spect_ch[0].chan_freq; 3055 3056 /* 3057 * If current channel is already best channel and no bandwidth 3058 * change, return the current channel so no channel switch happen. 3059 */ 3060 if (cur_bw == pref_bw) { 3061 for (i = 1; i < spect_info->num_ch; i++) { 3062 if (!spect_ch[i].valid) 3063 continue; 3064 if (spect_ch[i].weight <= best_weight) { 3065 sap_debug("best freq = %d, weight = %d", 3066 spect_ch[i].chan_freq, 3067 spect_ch[i].weight); 3068 if (spect_ch[i].chan_freq == cur_freq) 3069 return cur_freq; 3070 } 3071 } 3072 } 3073 3074 return best_chan_freq; 3075 } 3076 3077 #ifdef WLAN_FEATURE_AFC_DCS_SKIP_ACS_RANGE 3078 /** 3079 * is_sap_afc_dcs_skip_acs() - API to get whether to skip ACS range 3080 * when doing automatically channel selection for AFC DCS. 3081 * @sap_ctx: SAP context pointer 3082 * 3083 * Return: True if skip ACS range and can select channel out of it. 3084 */ 3085 static bool is_sap_afc_dcs_skip_acs(struct sap_context *sap_ctx) 3086 { 3087 struct sap_acs_cfg *acs_cfg; 3088 uint32_t i; 3089 3090 if (!sap_ctx || !sap_ctx->acs_cfg) 3091 return false; 3092 3093 acs_cfg = sap_ctx->acs_cfg; 3094 for (i = 0; i < acs_cfg->ch_list_count; i++) { 3095 if (WLAN_REG_IS_6GHZ_CHAN_FREQ(acs_cfg->freq_list[i])) 3096 return false; 3097 } 3098 return true; 3099 } 3100 #else 3101 static bool is_sap_afc_dcs_skip_acs(struct sap_context *sap_ctx) 3102 { 3103 return false; 3104 } 3105 #endif 3106 3107 qdf_freq_t sap_afc_dcs_sel_chan(struct sap_context *sap_ctx, 3108 qdf_freq_t cur_freq, 3109 enum phy_ch_width cur_bw, 3110 enum phy_ch_width *pref_bw) 3111 { 3112 struct mac_context *mac_ctx; 3113 mac_handle_t mac_handle; 3114 struct sap_sel_ch_info spect_info_obj = {NULL, 0}; 3115 struct sap_sel_ch_info *spect_info = &spect_info_obj; 3116 qdf_freq_t target_freq; 3117 3118 if (!sap_ctx || !pref_bw) 3119 return SAP_CHANNEL_NOT_SELECTED; 3120 3121 if (!sap_ctx->acs_cfg || !sap_ctx->acs_cfg->acs_mode) { 3122 sap_debug("SAP session id %d acs not enable", 3123 sap_ctx->sessionId); 3124 return SAP_CHANNEL_NOT_SELECTED; 3125 } 3126 3127 mac_handle = cds_get_context(QDF_MODULE_ID_SME); 3128 mac_ctx = MAC_CONTEXT(mac_handle); 3129 if (!mac_ctx) 3130 return SAP_CHANNEL_NOT_SELECTED; 3131 3132 /* 3133 * If AFC response received after SAP started, SP channels are 3134 * not included in current ACS range, ignore ACS range check 3135 * in this scenario so that SAP can move to new SP channel. 3136 */ 3137 sap_chan_sel_init(mac_ctx, spect_info, sap_ctx, 3138 is_sap_afc_dcs_skip_acs(sap_ctx)); 3139 3140 sap_max_weight_invalidate_2ghz_channels(spect_info); 3141 3142 sap_compute_spect_max_power_weight(spect_info, mac_ctx, sap_ctx); 3143 3144 sap_sort_chl_weight_all(mac_ctx, sap_ctx, spect_info, 3145 eCSR_DOT11_MODE_11a, REGDOMAIN_FCC, pref_bw); 3146 3147 target_freq = sap_afc_dcs_target_chan(mac_ctx, 3148 sap_ctx, 3149 spect_info, 3150 cur_freq, 3151 cur_bw, 3152 *pref_bw); 3153 sap_chan_sel_exit(spect_info); 3154 return target_freq; 3155 } 3156 #endif 3157