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