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