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