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