1  /*
2   * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3   * Copyright (c) 2021-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 A p i L i n k C n t l . C
23  
24     OVERVIEW:
25  
26     This software unit holds the implementation of the WLAN SAP modules
27     Link Control functions.
28  
29     The functions externalized by this module are to be called ONLY by other
30     WLAN modules (HDD)
31  
32     DEPENDENCIES:
33  
34     Are listed for each API below.
35     ===========================================================================*/
36  
37  /*----------------------------------------------------------------------------
38   * Include Files
39   * -------------------------------------------------------------------------*/
40  #include "qdf_trace.h"
41  /* Pick up the CSR callback definition */
42  #include "csr_api.h"
43  #include "ani_global.h"
44  #include "csr_inside_api.h"
45  #include "sme_api.h"
46  /* SAP Internal API header file */
47  #include "sap_internal.h"
48  #include "wlan_policy_mgr_api.h"
49  #include "wma.h"
50  #include <wlan_objmgr_vdev_obj.h>
51  #include <wlan_objmgr_pdev_obj.h>
52  #include "wlan_reg_services_api.h"
53  #include <wlan_scan_api.h>
54  #include <wlan_scan_utils_api.h>
55  #include "wlan_pre_cac_api.h"
56  #include <wlan_cfg80211_scan.h>
57  #include <wlan_hdd_hostapd.h>
58  
59  /* IF MGR API header file */
60  #include "wlan_if_mgr_ucfg_api.h"
61  
62  /*----------------------------------------------------------------------------
63   * Preprocessor Definitions and Constants
64   * -------------------------------------------------------------------------*/
65  #define SAP_DEBUG
66  
67  /*----------------------------------------------------------------------------
68   * Type Declarations
69   * -------------------------------------------------------------------------*/
70  
71  /*----------------------------------------------------------------------------
72   * Global Data Definitions
73   * -------------------------------------------------------------------------*/
74  
75  /*----------------------------------------------------------------------------
76   * Static Variable Definitions
77   * -------------------------------------------------------------------------*/
78  
79  /*----------------------------------------------------------------------------
80   * Static Function Declarations and Definitions
81   * -------------------------------------------------------------------------*/
82  
83  /*----------------------------------------------------------------------------
84   * Externalized Function Definitions
85   * -------------------------------------------------------------------------*/
86  
87  /*----------------------------------------------------------------------------
88   * Function Declarations and Documentation
89   * -------------------------------------------------------------------------*/
90  
91  #if defined(WLAN_FEATURE_11BE)
sap_acs_cfg_is_chwidth_320mhz(uint16_t width)92  static inline bool sap_acs_cfg_is_chwidth_320mhz(uint16_t width)
93  {
94  	return width == CH_WIDTH_320MHZ;
95  }
96  #else
sap_acs_cfg_is_chwidth_320mhz(uint16_t width)97  static inline bool sap_acs_cfg_is_chwidth_320mhz(uint16_t width)
98  {
99  	return false;
100  }
101  #endif
102  
103  #ifdef WLAN_FEATURE_11BE
sap_acs_set_puncture_bitmap(struct sap_context * sap_ctx,struct ch_params * ch_params)104  static void sap_acs_set_puncture_bitmap(struct sap_context *sap_ctx,
105  					struct ch_params *ch_params)
106  {
107  	sap_debug("ccfs0 %d ch_width %d, punct 0x%x",
108  		  ch_params->center_freq_seg0,
109  		  ch_params->ch_width,
110  		  ch_params->reg_punc_bitmap);
111  	sap_ctx->acs_cfg->acs_puncture_bitmap = ch_params->reg_punc_bitmap;
112  }
113  #else
sap_acs_set_puncture_bitmap(struct sap_context * sap_ctx,struct ch_params * ch_params)114  static void sap_acs_set_puncture_bitmap(struct sap_context *sap_ctx,
115  					struct ch_params *ch_params)
116  {
117  }
118  #endif /* WLAN_FEATURE_11BE */
119  
120  /**
121   * sap_config_acs_result : Generate ACS result params based on ch constraints
122   * @sap_ctx: pointer to SAP context data struct
123   * @mac_handle: Opaque handle to the global MAC context
124   * @sec_ch_freq: Secondary channel frequency
125   *
126   * This function calculates the ACS result params: ht sec channel, vht channel
127   * information and channel bonding based on selected ACS channel.
128   *
129   * Return: None
130   */
131  
sap_config_acs_result(mac_handle_t mac_handle,struct sap_context * sap_ctx,uint32_t sec_ch_freq)132  void sap_config_acs_result(mac_handle_t mac_handle,
133  			   struct sap_context *sap_ctx,
134  			   uint32_t sec_ch_freq)
135  {
136  	struct ch_params ch_params = {0};
137  	struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
138  	enum phy_ch_width new_ch_width;
139  
140  	ch_params.ch_width = sap_ctx->acs_cfg->ch_width;
141  	if (sap_phymode_is_eht(sap_ctx->phyMode))
142  		wlan_reg_set_create_punc_bitmap(&ch_params, true);
143  
144  	new_ch_width =
145  		wlan_sap_get_concurrent_bw(mac_ctx->pdev, mac_ctx->psoc,
146  					   sap_ctx->acs_cfg->pri_ch_freq,
147  					   ch_params.ch_width);
148  	sap_debug("new_ch_width:%d", new_ch_width);
149  	ch_params.ch_width = new_ch_width;
150  
151  	wlan_reg_set_channel_params_for_pwrmode(
152  			mac_ctx->pdev, sap_ctx->acs_cfg->pri_ch_freq,
153  			sec_ch_freq, &ch_params, REG_CURRENT_PWR_MODE);
154  	sap_ctx->acs_cfg->ch_width = ch_params.ch_width;
155  	if (sap_ctx->acs_cfg->ch_width > CH_WIDTH_40MHZ ||
156  	    WLAN_REG_IS_6GHZ_CHAN_FREQ(sap_ctx->acs_cfg->pri_ch_freq))
157  		sap_ctx->acs_cfg->vht_seg0_center_ch_freq =
158  						ch_params.mhz_freq_seg0;
159  	else
160  		sap_ctx->acs_cfg->vht_seg0_center_ch_freq = 0;
161  
162  	if (sap_ctx->acs_cfg->ch_width == CH_WIDTH_80P80MHZ ||
163  	   (sap_ctx->acs_cfg->ch_width == CH_WIDTH_160MHZ) ||
164  	   sap_acs_cfg_is_chwidth_320mhz(sap_ctx->acs_cfg->ch_width))
165  		sap_ctx->acs_cfg->vht_seg1_center_ch_freq =
166  						ch_params.mhz_freq_seg1;
167  	else
168  		sap_ctx->acs_cfg->vht_seg1_center_ch_freq = 0;
169  
170  	if (ch_params.sec_ch_offset == PHY_DOUBLE_CHANNEL_HIGH_PRIMARY)
171  		sap_ctx->acs_cfg->ht_sec_ch_freq =
172  				sap_ctx->acs_cfg->pri_ch_freq - 20;
173  	else if (ch_params.sec_ch_offset == PHY_DOUBLE_CHANNEL_LOW_PRIMARY)
174  		sap_ctx->acs_cfg->ht_sec_ch_freq =
175  				sap_ctx->acs_cfg->pri_ch_freq + 20;
176  	else
177  		sap_ctx->acs_cfg->ht_sec_ch_freq = 0;
178  
179  	sap_acs_set_puncture_bitmap(sap_ctx, &ch_params);
180  }
181  
182  /**
183   * sap_hdd_signal_event_handler() - routine to inform hostapd via callback
184   * @ctx: pointer to sap context which was passed to callback
185   *
186   * this routine will be registered as callback to sme_close_session, so upon
187   * closure of sap session it notifies the hostapd
188   *
189   * Return: QDF_STATUS
190   */
sap_hdd_signal_event_handler(void * ctx)191  static QDF_STATUS sap_hdd_signal_event_handler(void *ctx)
192  {
193  	struct sap_context *sap_ctx = ctx;
194  	QDF_STATUS status;
195  
196  	if (!sap_ctx) {
197  		sap_err("sap context is not valid");
198  		return QDF_STATUS_E_FAILURE;
199  	}
200  	status = sap_signal_hdd_event(sap_ctx, NULL,
201  			sap_ctx->sap_state,
202  			(void *) sap_ctx->sap_status);
203  	return status;
204  }
205  
206  /**
207   * acs_scan_done_status_str() - parse scan status to string
208   * @status: scan status
209   *
210   * This function parse scan status to string
211   *
212   * Return: status string
213   *
214   */
acs_scan_done_status_str(eCsrScanStatus status)215  static const char *acs_scan_done_status_str(eCsrScanStatus status)
216  {
217  	switch (status) {
218  	case eCSR_SCAN_SUCCESS:
219  		return "Success";
220  	case eCSR_SCAN_FAILURE:
221  		return "Failure";
222  	case eCSR_SCAN_ABORT:
223  		return "Abort";
224  	case eCSR_SCAN_FOUND_PEER:
225  		return "Found peer";
226  	default:
227  		return "Unknown";
228  	}
229  }
230  
231  #ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
wlansap_send_acs_success_event(struct sap_context * sap_ctx,uint32_t scan_id)232  static void wlansap_send_acs_success_event(struct sap_context *sap_ctx,
233  					   uint32_t scan_id)
234  {
235  	if (scan_id) {
236  		sap_debug("Sending ACS Scan skip event");
237  		sap_signal_hdd_event(sap_ctx, NULL,
238  				     eSAP_ACS_SCAN_SUCCESS_EVENT,
239  				     (void *)eSAP_STATUS_SUCCESS);
240  	} else {
241  		sap_debug("ACS scanid: %d (skipped ACS SCAN)", scan_id);
242  	}
243  }
244  #else
wlansap_send_acs_success_event(struct sap_context * sap_ctx,uint32_t scan_id)245  static inline void wlansap_send_acs_success_event(struct sap_context *sap_ctx,
246  						  uint32_t scan_id)
247  {
248  }
249  #endif
250  
251  static uint32_t
wlansap_calculate_chan_from_scan_result(mac_handle_t mac_handle,struct sap_context * sap_ctx,uint32_t scan_id)252  wlansap_calculate_chan_from_scan_result(mac_handle_t mac_handle,
253  					struct sap_context *sap_ctx,
254  					uint32_t scan_id)
255  {
256  	struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
257  	qdf_list_t *list = NULL;
258  	struct scan_filter *filter;
259  	uint32_t oper_channel = SAP_CHANNEL_NOT_SELECTED;
260  
261  	filter = qdf_mem_malloc(sizeof(*filter));
262  
263  	if (filter) {
264  		if (sap_ctx->partial_acs_scan)
265  			filter->age_threshold =
266  					sap_ctx->acs_cfg->last_scan_ageout_time;
267  		else
268  			filter->age_threshold = qdf_get_time_of_the_day_ms() -
269  						sap_ctx->acs_req_timestamp;
270  	}
271  
272  	list = wlan_scan_get_result(mac_ctx->pdev, filter);
273  
274  	if (filter)
275  		qdf_mem_free(filter);
276  
277  	if (list)
278  		sap_debug("num_entries %d", qdf_list_size(list));
279  
280  	wlansap_send_acs_success_event(sap_ctx, scan_id);
281  
282  	oper_channel = sap_select_channel(mac_handle, sap_ctx, list);
283  	wlan_scan_purge_results(list);
284  
285  	return oper_channel;
286  }
287  
288  static void
wlansap_filter_unsafe_ch(struct wlan_objmgr_psoc * psoc,struct sap_context * sap_ctx)289  wlansap_filter_unsafe_ch(struct wlan_objmgr_psoc *psoc,
290  			 struct sap_context *sap_ctx)
291  {
292  	uint16_t i;
293  	uint16_t num_safe_ch = 0;
294  	uint32_t freq;
295  
296  	/*
297  	 * There are two channel list, one acs cfg channel list, and one
298  	 * sap_ctx->freq_list, the unsafe channels for acs cfg is updated here
299  	 * and the sap_ctx->freq list would be handled in sap_chan_sel_init
300  	 * which would consider more params other than unsafe channels.
301  	 * So the two lists now would be in sync. But in case the ACS weight
302  	 * calculation does not get through due to no scan result or no chan
303  	 * selected, or any other reason, the default channel is chosen which
304  	 * would contain the channels in acs cfg. Now since the scan takes time
305  	 * there could be channels present in acs cfg that could become unsafe
306  	 * in the mean time, so it is better to filter out those channels from
307  	 * the acs channel list before choosing one of them as a default channel
308  	 */
309  	for (i = 0; i < sap_ctx->acs_cfg->ch_list_count; i++) {
310  		freq = sap_ctx->acs_cfg->freq_list[i];
311  		if (!policy_mgr_is_sap_freq_allowed(psoc,
312  				wlan_vdev_mlme_get_opmode(sap_ctx->vdev),
313  				freq)) {
314  			sap_debug("remove freq %d from acs list", freq);
315  			continue;
316  		}
317  		/* Add only allowed channels to the acs cfg ch list */
318  		sap_ctx->acs_cfg->freq_list[num_safe_ch++] =
319  						sap_ctx->acs_cfg->freq_list[i];
320  	}
321  
322  	sap_debug("Updated ACS ch list len %d", num_safe_ch);
323  	sap_ctx->acs_cfg->ch_list_count = num_safe_ch;
324  }
325  
326  static void
wlan_sap_filter_non_preferred_channels(struct wlan_objmgr_pdev * pdev,struct sap_context * sap_ctx)327  wlan_sap_filter_non_preferred_channels(struct wlan_objmgr_pdev *pdev,
328  				       struct sap_context *sap_ctx)
329  {
330  	uint16_t i;
331  	uint16_t num_ch = 0;
332  	bool preferred_freq_found = false;
333  
334  	for (i = 0; i < sap_ctx->acs_cfg->ch_list_count; i++) {
335  		if (sap_ctx->acs_cfg->freq_list[i] == 2467 ||
336  		    sap_ctx->acs_cfg->freq_list[i] == 2472 ||
337  		    sap_ctx->acs_cfg->freq_list[i] == 2477) {
338  			sap_debug("Skip freq %d if preferred freq present",
339  				  sap_ctx->acs_cfg->freq_list[i]);
340  			continue;
341  		}
342  		sap_ctx->acs_cfg->freq_list[num_ch++] =
343  						sap_ctx->acs_cfg->freq_list[i];
344  		preferred_freq_found = true;
345  	}
346  
347  	if (!preferred_freq_found) {
348  		sap_debug("No preferred freq, list unchanged");
349  		return;
350  	}
351  	sap_debug("preferred frequencies found updated ACS ch list len %d",
352  		  num_ch);
353  	sap_ctx->acs_cfg->ch_list_count = num_ch;
354  }
355  
wlansap_pre_start_bss_acs_scan_callback(mac_handle_t mac_handle,struct sap_context * sap_ctx,uint8_t sessionid,uint32_t scanid,eCsrScanStatus scan_status)356  QDF_STATUS wlansap_pre_start_bss_acs_scan_callback(mac_handle_t mac_handle,
357  						   struct sap_context *sap_ctx,
358  						   uint8_t sessionid,
359  						   uint32_t scanid,
360  						   eCsrScanStatus scan_status)
361  {
362  	uint32_t oper_channel = SAP_CHANNEL_NOT_SELECTED;
363  	struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
364  
365  	host_log_acs_scan_done(acs_scan_done_status_str(scan_status),
366  			  sessionid, scanid);
367  
368  	if (sap_ctx->optimize_acs_chan_selected) {
369  		sap_debug("SAP channel selected using first clean channel, ignore scan complete event");
370  		return QDF_STATUS_SUCCESS;
371  	}
372  
373  	/* This has to be done before the ACS selects default channel */
374  	wlansap_filter_unsafe_ch(mac_ctx->psoc, sap_ctx);
375  
376  	wlan_sap_filter_non_preferred_channels(mac_ctx->pdev, sap_ctx);
377  	if (!sap_ctx->acs_cfg->ch_list_count) {
378  		oper_channel =
379  			sap_select_default_oper_chan(mac_ctx,
380  						     sap_ctx->acs_cfg);
381  		sap_ctx->chan_freq = oper_channel;
382  		sap_ctx->acs_cfg->pri_ch_freq = oper_channel;
383  		sap_config_acs_result(mac_handle, sap_ctx,
384  				      sap_ctx->acs_cfg->ht_sec_ch_freq);
385  		sap_ctx->sap_state = eSAP_ACS_CHANNEL_SELECTED;
386  		sap_ctx->sap_status = eSAP_STATUS_SUCCESS;
387  		goto close_session;
388  	}
389  	if (eCSR_SCAN_SUCCESS != scan_status) {
390  		sap_err("CSR scan_status = eCSR_SCAN_ABORT/FAILURE (%d), choose default channel",
391  			scan_status);
392  		oper_channel =
393  			sap_select_default_oper_chan(mac_ctx,
394  						     sap_ctx->acs_cfg);
395  		wlansap_set_acs_ch_freq(sap_ctx, oper_channel);
396  		sap_ctx->acs_cfg->pri_ch_freq = oper_channel;
397  		sap_config_acs_result(mac_handle, sap_ctx,
398  				      sap_ctx->acs_cfg->ht_sec_ch_freq);
399  		sap_ctx->sap_state = eSAP_ACS_CHANNEL_SELECTED;
400  		sap_ctx->sap_status = eSAP_STATUS_SUCCESS;
401  		goto close_session;
402  	}
403  	sap_debug("CSR scan_status = eCSR_SCAN_SUCCESS (%d)", scan_status);
404  
405  	oper_channel = wlansap_calculate_chan_from_scan_result(mac_handle,
406  							       sap_ctx, scanid);
407  
408  	if (oper_channel == SAP_CHANNEL_NOT_SELECTED) {
409  		sap_info("No suitable channel, so select default channel");
410  		oper_channel = sap_select_default_oper_chan(mac_ctx,
411  							    sap_ctx->acs_cfg);
412  	}
413  
414  	wlansap_set_acs_ch_freq(sap_ctx, oper_channel);
415  	sap_ctx->acs_cfg->pri_ch_freq = oper_channel;
416  	sap_config_acs_result(mac_handle, sap_ctx,
417  			      sap_ctx->acs_cfg->ht_sec_ch_freq);
418  
419  	wlansap_dump_acs_ch_freq(sap_ctx);
420  
421  	sap_ctx->sap_state = eSAP_ACS_CHANNEL_SELECTED;
422  	sap_ctx->sap_status = eSAP_STATUS_SUCCESS;
423  close_session:
424  #ifdef SOFTAP_CHANNEL_RANGE
425  	if (sap_ctx->freq_list) {
426  		/*
427  		* Always free up the memory for
428  		* channel selection whatever
429  		* the result
430  		*/
431  		qdf_mem_free(sap_ctx->freq_list);
432  		sap_ctx->freq_list = NULL;
433  		sap_ctx->num_of_channel = 0;
434  	}
435  #endif
436  	sap_hdd_signal_event_handler(sap_ctx);
437  
438  	return QDF_STATUS_SUCCESS;
439  }
440  
441  /**
442   * wlansap_roam_process_ch_change_success() - handles the case for
443   * eCSR_ROAM_RESULT_CHANNEL_CHANGE_SUCCESS in function wlansap_roam_callback()
444   *
445   * @mac_ctx:        mac global context
446   * @sap_ctx:        sap context
447   * @csr_roam_info:  raom info struct
448   * @ret_status:     update return status
449   *
450   * Return: void
451   */
452  static void
wlansap_roam_process_ch_change_success(struct mac_context * mac_ctx,struct sap_context * sap_ctx,struct csr_roam_info * csr_roam_info,QDF_STATUS * ret_status)453  wlansap_roam_process_ch_change_success(struct mac_context *mac_ctx,
454  				      struct sap_context *sap_ctx,
455  				      struct csr_roam_info *csr_roam_info,
456  				      QDF_STATUS *ret_status)
457  {
458  	struct sap_sm_event sap_event;
459  	QDF_STATUS qdf_status;
460  	bool is_ch_dfs = false;
461  	uint32_t target_chan_freq;
462  	eSapDfsCACState_t cac_state = eSAP_DFS_DO_NOT_SKIP_CAC;
463  
464  	/*
465  	 * Channel change is successful. If the new channel is a DFS channel,
466  	 * then we will to perform channel availability check for 60 seconds
467  	 */
468  	sap_nofl_debug("sap_fsm: vdev %d: sapdfs: SAP CSA: freq %d state %d evt freq %d",
469  		       sap_ctx->vdev_id,
470  		       mac_ctx->sap.SapDfsInfo.target_chan_freq,
471  		       sap_ctx->fsm_state,
472  		       csr_roam_info->channelChangeRespEvent->new_op_freq);
473  	target_chan_freq = mac_ctx->sap.SapDfsInfo.target_chan_freq;
474  	/* If SAP is not in starting or started state don't proceed further */
475  	if (sap_ctx->fsm_state == SAP_INIT ||
476  	    sap_ctx->fsm_state == SAP_STOPPING) {
477  		sap_info("sap_fsm: vdev %d: sapdfs: state %d, not starting SAP after channel change",
478  			 sap_ctx->vdev_id, sap_ctx->fsm_state);
479  		return;
480  	}
481  
482  	if (sap_ctx->ch_params.ch_width == CH_WIDTH_160MHZ) {
483  		struct ch_params ch_params = {0};
484  
485  		wlan_reg_set_create_punc_bitmap(&ch_params, true);
486  		ch_params.ch_width = sap_ctx->ch_params.ch_width;
487  		if (wlan_reg_get_5g_bonded_channel_state_for_pwrmode(mac_ctx->pdev,
488  								     target_chan_freq,
489  								     &ch_params,
490  								     REG_CURRENT_PWR_MODE) ==
491  		    CHANNEL_STATE_DFS)
492  			is_ch_dfs = true;
493  	} else if (sap_ctx->ch_params.ch_width == CH_WIDTH_80P80MHZ) {
494  		if (wlan_reg_get_channel_state_for_pwrmode(
495  						mac_ctx->pdev,
496  						target_chan_freq,
497  						REG_CURRENT_PWR_MODE) ==
498  		    CHANNEL_STATE_DFS ||
499  		    wlan_reg_get_channel_state_for_pwrmode(
500  					mac_ctx->pdev,
501  					sap_ctx->ch_params.mhz_freq_seg1,
502  					REG_CURRENT_PWR_MODE) ==
503  				CHANNEL_STATE_DFS)
504  			is_ch_dfs = true;
505  	} else {
506  		/* Indoor channels are also marked DFS, therefore
507  		 * check if the channel has REGULATORY_CHAN_RADAR
508  		 * channel flag to identify if the channel is DFS
509  		 */
510  		if (wlan_reg_is_dfs_for_freq(mac_ctx->pdev, target_chan_freq))
511  			is_ch_dfs = true;
512  	}
513  	if (WLAN_REG_IS_6GHZ_CHAN_FREQ(sap_ctx->chan_freq))
514  		is_ch_dfs = false;
515  
516  	sap_ctx->fsm_state = SAP_STARTING;
517  	sap_debug("sap_fsm: vdev %d: => SAP_STARTING", sap_ctx->vdev_id);
518  	sap_ctx->chan_freq = target_chan_freq;
519  	/* check if currently selected channel is a DFS channel */
520  	if (is_ch_dfs && wlan_pre_cac_complete_get(sap_ctx->vdev)) {
521  		sap_ctx->sap_radar_found_status = false;
522  		sap_event.event = eSAP_MAC_START_BSS_SUCCESS;
523  		sap_event.params = csr_roam_info;
524  		sap_event.u1 = eCSR_ROAM_INFRA_IND;
525  		sap_event.u2 = eCSR_ROAM_RESULT_INFRA_STARTED;
526  	} else if (is_ch_dfs) {
527  		if (sap_plus_sap_cac_skip(mac_ctx, sap_ctx,
528  					  sap_ctx->chan_freq))
529  			cac_state = eSAP_DFS_SKIP_CAC;
530  		if ((false == mac_ctx->sap.SapDfsInfo.ignore_cac) &&
531  		    (cac_state == eSAP_DFS_DO_NOT_SKIP_CAC) &&
532  		    policy_mgr_get_dfs_master_dynamic_enabled(
533  					mac_ctx->psoc,
534  					sap_ctx->sessionId)) {
535  			/* DFS Channel */
536  			sap_event.event = eSAP_DFS_CHANNEL_CAC_START;
537  			sap_event.params = csr_roam_info;
538  			sap_event.u1 = 0;
539  			sap_event.u2 = 0;
540  		} else {
541  			sap_ctx->sap_radar_found_status = false;
542  			sap_event.event = eSAP_MAC_START_BSS_SUCCESS;
543  			sap_event.params = csr_roam_info;
544  			sap_event.u1 = eCSR_ROAM_INFRA_IND;
545  			sap_event.u2 = eCSR_ROAM_RESULT_INFRA_STARTED;
546  		}
547  	} else {
548  		/* non-DFS channel */
549  		sap_ctx->sap_radar_found_status = false;
550  		sap_event.event = eSAP_MAC_START_BSS_SUCCESS;
551  		sap_event.params = csr_roam_info;
552  		sap_event.u1 = eCSR_ROAM_INFRA_IND;
553  		sap_event.u2 = eCSR_ROAM_RESULT_INFRA_STARTED;
554  	}
555  
556  	/* Handle the event */
557  	qdf_status = sap_fsm(sap_ctx, &sap_event);
558  	if (!QDF_IS_STATUS_SUCCESS(qdf_status))
559  		*ret_status = QDF_STATUS_E_FAILURE;
560  }
561  
562  /**
563   * wlansap_roam_process_dfs_chansw_update() - handles the case for
564   * eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS in wlansap_roam_callback()
565   *
566   * @mac_handle:    opaque handle to the global MAC context
567   * @sap_ctx:       sap context
568   * @ret_status:    update return status
569   *
570   * Return: void
571   */
572  static void
wlansap_roam_process_dfs_chansw_update(mac_handle_t mac_handle,struct sap_context * sap_ctx,QDF_STATUS * ret_status)573  wlansap_roam_process_dfs_chansw_update(mac_handle_t mac_handle,
574  				       struct sap_context *sap_ctx,
575  				       QDF_STATUS *ret_status)
576  {
577  	uint8_t intf;
578  	QDF_STATUS qdf_status;
579  	struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
580  	uint8_t dfs_beacon_start_req = 0;
581  	bool sap_scc_dfs;
582  
583  	if (mac_ctx->mlme_cfg->dfs_cfg.dfs_disable_channel_switch) {
584  		sap_err("sapdfs: DFS channel switch disabled");
585  		/*
586  		 * Send a beacon start request to PE. CSA IE required flag from
587  		 * beacon template will be cleared by now. A new beacon template
588  		 * with no CSA IE will be sent to firmware.
589  		 */
590  		dfs_beacon_start_req = true;
591  		wlan_pre_cac_complete_set(sap_ctx->vdev, false);
592  		*ret_status = sme_roam_start_beacon_req(mac_handle,
593  							sap_ctx->bssid,
594  							dfs_beacon_start_req);
595  		return;
596  	}
597  	/*
598  	 * Irrespective of whether the channel switch IE was sent out
599  	 * successfully or not, SAP should still vacate the channel immediately
600  	 */
601  	if (sap_ctx->fsm_state != SAP_STARTED) {
602  		/* Further actions to be taken here */
603  		sap_warn("eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND received in (%d) state",
604  			  sap_ctx->fsm_state);
605  		return;
606  	}
607  	sap_ctx->is_chan_change_inprogress = true;
608  	/*
609  	 * The associated stations have been informed to move to a different
610  	 * channel. However, the AP may not always select the advertised channel
611  	 * for operation if the radar is seen. In that case, the stations will
612  	 * experience link-loss and return back through scanning if they wish to
613  	 */
614  
615  	/*
616  	 * Send channel change request. From spec it is required that the AP
617  	 * should continue to operate in the same mode as it is operating
618  	 * currently. For e.g. 20/40/80 MHz operation
619  	 */
620  	if (mac_ctx->sap.SapDfsInfo.target_chan_freq) {
621  		if (sap_phymode_is_eht(sap_ctx->phyMode))
622  			wlan_reg_set_create_punc_bitmap(&sap_ctx->ch_params,
623  							true);
624  		wlan_reg_set_channel_params_for_pwrmode(mac_ctx->pdev,
625  				mac_ctx->sap.SapDfsInfo.target_chan_freq,
626  				0, &sap_ctx->ch_params, REG_CURRENT_PWR_MODE);
627  	}
628  
629  	/*
630  	 * Fetch the number of SAP interfaces. If the number of sap Interface
631  	 * more than one then we will make is_sap_ready_for_chnl_chng to true
632  	 * for that sapctx. If there is only one SAP interface then process
633  	 * immediately. If Dual BAND SAP OR SBS in different mac, is enabled
634  	 * then also process immediately, as in this case the both SAP will be
635  	 * in different band and channel change on one SAP doesn't mean channel
636  	 * change on other interface.
637  	 *
638  	 * For example,
639  	 * Let's say SAP(2G) + SAP(5G-DFS) is initial connection which triggered
640  	 * DualBand HW mode and if SAP(5G-DFS) is moving to some channel then
641  	 * SAP(2G) doesn't need to move.
642  	 *
643  	 * If both SAPs are not doing SCC DFS then each of them can change the
644  	 * channel independently. Channel change of one SAP became dependent
645  	 * second SAP's channel change due to some previous platform's single
646  	 * radio limitation.
647  	 *
648  	 * For DCS case, SAP will do channel switch one by one.
649  	 *
650  	 */
651  	sap_scc_dfs = sap_is_conc_sap_doing_scc_dfs(mac_handle, sap_ctx);
652  	if (sap_get_total_number_sap_intf(mac_handle) <= 1 ||
653  	    policy_mgr_is_current_hwmode_dbs(mac_ctx->psoc) ||
654  	    policy_mgr_is_current_hwmode_sbs(mac_ctx->psoc) ||
655  	    sap_ctx->csa_reason == CSA_REASON_DCS ||
656  	    !sap_scc_dfs) {
657  		/*
658  		 * Most likely, radar has been detected and SAP wants to
659  		 * change the channel
660  		 */
661  		qdf_status = wlansap_channel_change_request(sap_ctx,
662  			mac_ctx->sap.SapDfsInfo.target_chan_freq);
663  		if (!QDF_IS_STATUS_SUCCESS(qdf_status))
664  			*ret_status = QDF_STATUS_E_FAILURE;
665  		return;
666  	}
667  
668  	sap_ctx->is_sap_ready_for_chnl_chng = true;
669  	/*
670  	 * now check if the con-current sap interface is ready
671  	 * for channel change. If yes then we issue channel change for
672  	 * both the SAPs. If no then simply return success & we will
673  	 * issue channel change when second AP's 5 CSA beacon Tx is
674  	 * completed.
675  	 *
676  	 * This check is added to take care of following scenario:
677  	 * if SAP1 + SAP2 is doing DFS SCC and radar is detected on that channel
678  	 * then SAP1 sends 5 beacons with CSA/ECSA IE and wait for SAP2 to
679  	 * finish sending 5 beacons. if SAP1 changes channel before SAP2 finish
680  	 * sending beacons then it ends up in
681  	 * (SAP1 new channel + SAP2 old channel) MCC with DFS scenario
682  	 * which causes some of the stability issues in old platforms.
683  	 */
684  	if (false ==
685  	    is_concurrent_sap_ready_for_channel_change(mac_handle, sap_ctx)) {
686  		sap_debug("sapdfs: sapctx[%pK] ready but not concurrent sap",
687  			  sap_ctx);
688  		*ret_status = QDF_STATUS_SUCCESS;
689  		return;
690  	}
691  
692  	/* Issue channel change req for each sapctx */
693  	for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) {
694  		struct sap_context *sap_context;
695  
696  		if (!((QDF_SAP_MODE == mac_ctx->sap.sapCtxList[intf].sapPersona ||
697  		       QDF_P2P_GO_MODE == mac_ctx->sap.sapCtxList[intf].sapPersona)
698  		    && (mac_ctx->sap.sapCtxList[intf].sap_context)))
699  			continue;
700  		sap_context = mac_ctx->sap.sapCtxList[intf].sap_context;
701  		sap_debug("sapdfs:issue chnl change for sapctx[%pK]",
702  			  sap_context);
703  		/*
704  		 * Most likely, radar has been detected and SAP wants to
705  		 * change the channel
706  		 */
707  		qdf_status = wlansap_channel_change_request(sap_context,
708  				mac_ctx->sap.SapDfsInfo.target_chan_freq);
709  		if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
710  			sap_err("post chnl chng req failed, sap[%pK]", sap_ctx);
711  			*ret_status = QDF_STATUS_E_FAILURE;
712  		} else {
713  			sap_context->is_sap_ready_for_chnl_chng = false;
714  		}
715  	}
716  	return;
717  }
718  
719  /**
720   * wlansap_roam_process_dfs_radar_found() - handles the case for
721   * eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND in wlansap_roam_callback()
722   *
723   * @mac_ctx:       mac global context
724   * @sap_ctx:       sap context
725   * @ret_status:    update return status
726   *
727   * Return: result of operation
728   */
729  static void
wlansap_roam_process_dfs_radar_found(struct mac_context * mac_ctx,struct sap_context * sap_ctx,QDF_STATUS * ret_status)730  wlansap_roam_process_dfs_radar_found(struct mac_context *mac_ctx,
731  				     struct sap_context *sap_ctx,
732  				     QDF_STATUS *ret_status)
733  {
734  	QDF_STATUS qdf_status;
735  	struct sap_sm_event sap_event;
736  
737  	if (sap_is_dfs_cac_wait_state(sap_ctx)) {
738  		if (mac_ctx->mlme_cfg->dfs_cfg.dfs_disable_channel_switch) {
739  			sap_err("sapdfs: DFS channel switch disabled");
740  			return;
741  		}
742  		if (!sap_ctx->sap_radar_found_status) {
743  			sap_err("sapdfs: sap_radar_found_status is false");
744  			return;
745  		}
746  
747  		sap_debug("sapdfs:Posting event eSAP_DFS_CHANNEL_CAC_RADAR_FOUND");
748  		/*
749  		 * If Radar is found, while in DFS CAC WAIT State then post stop
750  		 * and destroy the CAC timer and post a
751  		 * eSAP_DFS_CHANNEL_CAC_RADAR_FOUND  to sapFsm.
752  		 */
753  		if (!sap_ctx->dfs_cac_offload) {
754  			qdf_mc_timer_stop(&mac_ctx->
755  					sap.SapDfsInfo.sap_dfs_cac_timer);
756  			qdf_mc_timer_destroy(&mac_ctx->
757  					sap.SapDfsInfo.sap_dfs_cac_timer);
758  		}
759  		mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running = false;
760  		mac_ctx->sap.SapDfsInfo.vdev_id = WLAN_INVALID_VDEV_ID;
761  
762  		/*
763  		 * User space is already indicated the CAC start and if
764  		 * CAC end on this channel is not indicated, the user
765  		 * space will be in some undefined state (e.g., UI frozen)
766  		 */
767  		qdf_status = sap_signal_hdd_event(sap_ctx, NULL,
768  				eSAP_DFS_CAC_INTERRUPTED,
769  				(void *) eSAP_STATUS_SUCCESS);
770  		if (QDF_STATUS_SUCCESS != qdf_status) {
771  			sap_err("Failed to send CAC end");
772  			/* Want to still proceed and try to switch channel.
773  			 * Lets try not to be on the DFS channel
774  			 */
775  		}
776  
777  		sap_event.event = eSAP_DFS_CHANNEL_CAC_RADAR_FOUND;
778  		sap_event.params = 0;
779  		sap_event.u1 = 0;
780  		sap_event.u2 = 0;
781  		qdf_status = sap_fsm(sap_ctx, &sap_event);
782  		if (!QDF_IS_STATUS_SUCCESS(qdf_status))
783  			*ret_status = QDF_STATUS_E_FAILURE;
784  		return;
785  	}
786  	if (sap_ctx->fsm_state == SAP_STARTED) {
787  		sap_debug("sapdfs:Posting event eSAP_DFS_CHNL_SWITCH_ANNOUNCEMENT_START");
788  
789  		/*
790  		 * Radar found on the operating channel in STARTED state,
791  		 * new operating channel has already been selected. Send
792  		 * request to SME-->PE for sending CSA IE
793  		 */
794  		sap_event.event = eSAP_DFS_CHNL_SWITCH_ANNOUNCEMENT_START;
795  		sap_event.params = 0;
796  		sap_event.u1 = 0;
797  		sap_event.u2 = 0;
798  		qdf_status = sap_fsm(sap_ctx, &sap_event);
799  		if (!QDF_IS_STATUS_SUCCESS(qdf_status))
800  			*ret_status = QDF_STATUS_E_FAILURE;
801  		return;
802  	}
803  	/* Further actions to be taken here */
804  	sap_err("eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND received in (%d) state",
805  		 sap_ctx->fsm_state);
806  
807  	return;
808  }
809  
810  /**
811   * wlansap_roam_process_infra_assoc_ind() - handles the case for
812   * eCSR_ROAM_RESULT_INFRA_ASSOCIATION_IND in wlansap_roam_callback()
813   *
814   * @sap_ctx:       sap context
815   * @roam_result:   roam result
816   * @csr_roam_info: roam info struct
817   * @ret_status:    update return status
818   *
819   * Return: result of operation
820   */
821  static void
wlansap_roam_process_infra_assoc_ind(struct sap_context * sap_ctx,eCsrRoamResult roam_result,struct csr_roam_info * csr_roam_info,QDF_STATUS * ret_status)822  wlansap_roam_process_infra_assoc_ind(struct sap_context *sap_ctx,
823  				     eCsrRoamResult roam_result,
824  				     struct csr_roam_info *csr_roam_info,
825  				     QDF_STATUS *ret_status)
826  {
827  	QDF_STATUS qdf_status;
828  
829  	sap_debug("CSR roam_result = eCSR_ROAM_RESULT_INFRA_ASSOCIATION_IND (%d)",
830  		  roam_result);
831  	sap_ctx->nStaWPARSnReqIeLength = csr_roam_info->rsnIELen;
832  	if (sap_ctx->nStaWPARSnReqIeLength)
833  		qdf_mem_copy(sap_ctx->pStaWpaRsnReqIE, csr_roam_info->prsnIE,
834  			     sap_ctx->nStaWPARSnReqIeLength);
835  	/* MAC filtering */
836  	qdf_status = sap_is_peer_mac_allowed(sap_ctx,
837  				     (uint8_t *) csr_roam_info->peerMac.bytes);
838  
839  	if (QDF_STATUS_SUCCESS == qdf_status) {
840  		qdf_status = sap_signal_hdd_event(sap_ctx,
841  				csr_roam_info, eSAP_STA_ASSOC_IND,
842  				(void *) eSAP_STATUS_SUCCESS);
843  		if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
844  			sap_err("CSR roam_result = (%d) MAC ("QDF_MAC_ADDR_FMT") fail",
845  				  roam_result, QDF_MAC_ADDR_REF(
846  					csr_roam_info->peerMac.bytes));
847  		*ret_status = QDF_STATUS_E_FAILURE;
848  		}
849  	} else {
850  		sap_warn("CSR roam_result = (%d) MAC ("QDF_MAC_ADDR_FMT") not allowed",
851  			  roam_result,
852  			  QDF_MAC_ADDR_REF(csr_roam_info->peerMac.bytes));
853  		*ret_status = QDF_STATUS_E_FAILURE;
854  	}
855  	return;
856  }
857  
wlansap_update_vendor_acs_chan(struct mac_context * mac_ctx,struct sap_context * sap_ctx)858  static void wlansap_update_vendor_acs_chan(struct mac_context *mac_ctx,
859  				struct sap_context *sap_ctx)
860  {
861  	int intf;
862  
863  	if (!mac_ctx) {
864  		sap_err("Invalid MAC context");
865  		return;
866  	}
867  
868  	mac_ctx->sap.SapDfsInfo.target_chan_freq =
869  				wlan_reg_legacy_chan_to_freq(
870  						mac_ctx->pdev,
871  						sap_ctx->dfs_vendor_channel);
872  
873  	mac_ctx->sap.SapDfsInfo.new_chanWidth =
874  				sap_ctx->dfs_vendor_chan_bw;
875  	mac_ctx->sap.SapDfsInfo.new_ch_params.ch_width =
876  				sap_ctx->dfs_vendor_chan_bw;
877  
878  	if (mac_ctx->sap.SapDfsInfo.target_chan_freq != 0) {
879  		sap_cac_reset_notify(MAC_HANDLE(mac_ctx));
880  		return;
881  	}
882  	/* App failed to provide new channel, try random channel algo */
883  	sap_warn("Failed to get channel from userspace");
884  
885  	/* Issue stopbss for each sapctx */
886  	for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) {
887  		struct sap_context *sap_context;
888  
889  		if (((QDF_SAP_MODE ==
890  		    mac_ctx->sap.sapCtxList[intf].sapPersona) ||
891  		    (QDF_P2P_GO_MODE ==
892  		    mac_ctx->sap.sapCtxList[intf].sapPersona)) &&
893  		    mac_ctx->sap.sapCtxList[intf].sap_context !=
894  		    NULL) {
895  			sap_context =
896  			    mac_ctx->sap.sapCtxList[intf].sap_context;
897  			sap_err("sapdfs: no available channel for sapctx[%pK], StopBss",
898  				 sap_context);
899  			wlansap_stop_bss(sap_context);
900  		}
901  	}
902  }
903  
904  #ifdef WLAN_FEATURE_P2P_P2P_STA
905  /**
906   * sap_check_and_process_forcescc_for_go_plus_go() - find if other p2p
907   * go is there and needs to be moved to current p2p go's channel.
908   *
909   * @cur_sap_ctx: current sap context
910   *
911   * Return: None
912   */
913  static void
sap_check_and_process_forcescc_for_go_plus_go(struct sap_context * cur_sap_ctx)914  sap_check_and_process_forcescc_for_go_plus_go(
915  					struct sap_context *cur_sap_ctx)
916  {
917  	struct sap_context *sap_ctx;
918  	struct mac_context *mac_ctx;
919  	uint8_t i;
920  
921  	mac_ctx = sap_get_mac_context();
922  	if (!mac_ctx) {
923  		sap_err("Invalid MAC context");
924  		return;
925  	}
926  
927  	for (i = 0; i < SAP_MAX_NUM_SESSION; i++) {
928  		sap_ctx = mac_ctx->sap.sapCtxList[i].sap_context;
929  		if (sap_ctx &&
930  		    QDF_P2P_GO_MODE == mac_ctx->sap.sapCtxList[i].sapPersona &&
931  		    sap_ctx->is_forcescc_restart_required &&
932  		    cur_sap_ctx->sessionId != sap_ctx->sessionId) {
933  			sap_debug("update chan_freq %d of sessionId %d with chan_freq %d",
934  				  sap_ctx->chan_freq, sap_ctx->sessionId,
935  				  cur_sap_ctx->chan_freq);
936  			policy_mgr_process_forcescc_for_go(
937  				mac_ctx->psoc, sap_ctx->sessionId,
938  				cur_sap_ctx->chan_freq,
939  				cur_sap_ctx->ch_params.ch_width,
940  				PM_P2P_GO_MODE);
941  			sap_ctx->is_forcescc_restart_required = false;
942  			break;
943  		}
944  	}
945  }
946  
947  /**
948   * sap_check_and_process_go_force_scc() - find if other p2p go/cli/sta
949   *                                        is there and needs force scc.
950   * @sap_ctx: current sap context
951   *
952   * Return: None
953   */
954  static void
sap_check_and_process_go_force_scc(struct sap_context * sap_ctx)955  sap_check_and_process_go_force_scc(struct sap_context *sap_ctx)
956  {
957  	struct mac_context *mac_ctx;
958  	uint32_t con_freq;
959  	enum phy_ch_width ch_width;
960  	enum policy_mgr_con_mode existing_vdev_mode = PM_MAX_NUM_OF_MODE;
961  
962  	mac_ctx = sap_get_mac_context();
963  	if (!mac_ctx) {
964  		sap_err("Invalid MAC context");
965  		return;
966  	}
967  	if (sap_ctx->vdev->vdev_mlme.vdev_opmode ==
968  	    QDF_P2P_GO_MODE &&
969  	    wlan_vdev_get_peer_count(sap_ctx->vdev) == 2 &&
970  	    policy_mgr_mode_specific_connection_count(
971  		    mac_ctx->psoc, PM_P2P_GO_MODE, NULL) > 1) {
972  		sap_check_and_process_forcescc_for_go_plus_go(sap_ctx);
973  		return;
974  	}
975  	policy_mgr_fetch_existing_con_info(mac_ctx->psoc, sap_ctx->sessionId,
976  					   sap_ctx->chan_freq,
977  					   &existing_vdev_mode,
978  					   &con_freq, &ch_width);
979  
980  	if (sap_ctx->vdev->vdev_mlme.vdev_opmode == QDF_P2P_GO_MODE &&
981  	    policy_mgr_go_scc_enforced(mac_ctx->psoc) &&
982  	    !policy_mgr_is_go_scc_strict(mac_ctx->psoc) &&
983  	    wlan_vdev_get_peer_count(sap_ctx->vdev) == 2 &&
984  	    (existing_vdev_mode == PM_P2P_CLIENT_MODE ||
985  	    existing_vdev_mode == PM_STA_MODE)){
986  		policy_mgr_process_forcescc_for_go(mac_ctx->psoc,
987  						   sap_ctx->sessionId,
988  						   con_freq, ch_width,
989  						   existing_vdev_mode);
990  	}
991  }
992  #else
993  static inline void
sap_check_and_process_forcescc_for_go_plus_go(struct sap_context * cur_sap_ctx)994  sap_check_and_process_forcescc_for_go_plus_go(
995  					struct sap_context *cur_sap_ctx)
996  {}
997  static inline void
sap_check_and_process_go_force_scc(struct sap_context * sap_ctx)998  sap_check_and_process_go_force_scc(struct sap_context *sap_ctx)
999  {}
1000  #endif
1001  
1002  /**
1003   * sap_is_csa_restart_state() - check if sap is in csa restart state
1004   * @psoc: PSOC object
1005   * @sap_ctx: sap context to check
1006   *
1007   * Return: true if sap is in csa restart state
1008   */
sap_is_csa_restart_state(struct wlan_objmgr_psoc * psoc,struct sap_context * sap_ctx)1009  static bool sap_is_csa_restart_state(struct wlan_objmgr_psoc *psoc,
1010  				     struct sap_context *sap_ctx)
1011  {
1012  	struct wlan_objmgr_vdev *vdev;
1013  	QDF_STATUS status;
1014  
1015  	if (!psoc || !sap_ctx) {
1016  		sap_err("Invalid params");
1017  		return false;
1018  	}
1019  
1020  	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
1021  						    sap_ctx->sessionId,
1022  						    WLAN_DFS_ID);
1023  	if (!vdev) {
1024  		sap_err("vdev is NULL for vdev_id: %u", sap_ctx->sessionId);
1025  		return false;
1026  	}
1027  
1028  	status = wlan_vdev_mlme_is_csa_restart(vdev);
1029  	wlan_objmgr_vdev_release_ref(vdev, WLAN_DFS_ID);
1030  
1031  	return QDF_IS_STATUS_SUCCESS(status);
1032  }
1033  
1034  #ifdef PRE_CAC_SUPPORT
wlan_sap_pre_cac_radar_ind(struct sap_context * sap_ctx,struct mac_context * mac_ctx)1035  static void wlan_sap_pre_cac_radar_ind(struct sap_context *sap_ctx,
1036  				       struct mac_context *mac_ctx)
1037  {
1038  	qdf_mc_timer_t *dfs_timer = &mac_ctx->sap.SapDfsInfo.sap_dfs_cac_timer;
1039  
1040  	sap_debug("sapdfs: Radar detect on pre cac:%d", sap_ctx->sessionId);
1041  	if (!sap_ctx->dfs_cac_offload) {
1042  		qdf_mc_timer_stop(dfs_timer);
1043  		qdf_mc_timer_destroy(dfs_timer);
1044  	}
1045  	mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running = false;
1046  	mac_ctx->sap.SapDfsInfo.vdev_id = WLAN_INVALID_VDEV_ID;
1047  
1048  	wlan_pre_cac_handle_radar_ind(sap_ctx->vdev);
1049  }
1050  #else
1051  static inline void
wlan_sap_pre_cac_radar_ind(struct sap_context * sap_ctx,struct mac_context * mac_ctx)1052  wlan_sap_pre_cac_radar_ind(struct sap_context *sap_ctx,
1053  			   struct mac_context *mac_ctx)
1054  {
1055  }
1056  #endif
1057  
wlansap_roam_callback(void * ctx,struct csr_roam_info * csr_roam_info,eRoamCmdStatus roam_status,eCsrRoamResult roam_result)1058  QDF_STATUS wlansap_roam_callback(void *ctx,
1059  				 struct csr_roam_info *csr_roam_info,
1060  				 eRoamCmdStatus roam_status,
1061  				 eCsrRoamResult roam_result)
1062  {
1063  	/* sap_ctx value */
1064  	struct sap_context *sap_ctx = ctx;
1065  	/* State machine event */
1066  	struct sap_sm_event sap_event;
1067  	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
1068  	QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
1069  	mac_handle_t mac_handle;
1070  	struct mac_context *mac_ctx;
1071  	uint8_t intf;
1072  
1073  	if (QDF_IS_STATUS_ERROR(wlansap_context_get(sap_ctx)))
1074  		return QDF_STATUS_E_FAILURE;
1075  
1076  	mac_ctx = sap_get_mac_context();
1077  	if (!mac_ctx) {
1078  		sap_err("Invalid MAC context");
1079  		wlansap_context_put(sap_ctx);
1080  		return QDF_STATUS_E_NOMEM;
1081  	}
1082  	sap_debug("CSR roam_status = %s(%d), roam_result = %s(%d)",
1083  		  get_e_roam_cmd_status_str(roam_status), roam_status,
1084  		  get_e_csr_roam_result_str(roam_result), roam_result);
1085  
1086  	mac_handle = MAC_HANDLE(mac_ctx);
1087  
1088  	switch (roam_status) {
1089  	case eCSR_ROAM_INFRA_IND:
1090  		if (roam_result == eCSR_ROAM_RESULT_INFRA_START_FAILED) {
1091  			/* Fill in the event structure */
1092  			sap_event.event = eSAP_MAC_START_FAILS;
1093  			sap_event.params = csr_roam_info;
1094  			sap_event.u1 = roam_status;
1095  			sap_event.u2 = roam_result;
1096  			/* Handle event */
1097  			qdf_status = sap_fsm(sap_ctx, &sap_event);
1098  			if (!QDF_IS_STATUS_SUCCESS(qdf_status))
1099  				qdf_ret_status = QDF_STATUS_E_FAILURE;
1100  		}
1101  		break;
1102  	case eCSR_ROAM_LOSTLINK:
1103  		break;
1104  	case eCSR_ROAM_MIC_ERROR_IND:
1105  		break;
1106  	case eCSR_ROAM_SET_KEY_COMPLETE:
1107  		if (roam_result == eCSR_ROAM_RESULT_FAILURE)
1108  			sap_signal_hdd_event(sap_ctx, csr_roam_info,
1109  					     eSAP_STA_SET_KEY_EVENT,
1110  					     (void *) eSAP_STATUS_FAILURE);
1111  		break;
1112  	case eCSR_ROAM_WPS_PBC_PROBE_REQ_IND:
1113  		break;
1114  	case eCSR_ROAM_DISCONNECT_ALL_P2P_CLIENTS:
1115  		sap_signal_hdd_event(sap_ctx, csr_roam_info,
1116  				     eSAP_DISCONNECT_ALL_P2P_CLIENT,
1117  				     (void *) eSAP_STATUS_SUCCESS);
1118  		break;
1119  	case eCSR_ROAM_SEND_P2P_STOP_BSS:
1120  		sap_debug("Received stopbss");
1121  		sap_signal_hdd_event(sap_ctx, csr_roam_info,
1122  				     eSAP_MAC_TRIG_STOP_BSS_EVENT,
1123  				     (void *) eSAP_STATUS_SUCCESS);
1124  		break;
1125  	case eCSR_ROAM_CHANNEL_COMPLETE_IND:
1126  		sap_debug("Received new channel from app");
1127  		wlansap_update_vendor_acs_chan(mac_ctx, sap_ctx);
1128  		break;
1129  
1130  	case eCSR_ROAM_DFS_RADAR_IND:
1131  		sap_debug("Rcvd Radar Indication on sap ch freq %d, session %d",
1132  			  sap_ctx->chan_freq, sap_ctx->sessionId);
1133  
1134  		if (!policy_mgr_get_dfs_master_dynamic_enabled(
1135  				mac_ctx->psoc, sap_ctx->sessionId)) {
1136  			sap_debug("Ignore the Radar indication");
1137  			goto EXIT;
1138  		}
1139  
1140  		if (sap_ctx->fsm_state != SAP_STARTED &&
1141  		    !sap_is_dfs_cac_wait_state(sap_ctx)) {
1142  			sap_debug("Ignore Radar event in sap state %d cac wait state %d",
1143  				  sap_ctx->fsm_state,
1144  				  sap_is_dfs_cac_wait_state(sap_ctx));
1145  			goto EXIT;
1146  		}
1147  
1148  		if (sap_ctx->fsm_state == SAP_STARTED &&
1149  		    sap_is_csa_restart_state(mac_ctx->psoc, sap_ctx)) {
1150  			sap_debug("Ignore Radar event in csa restart state");
1151  			goto EXIT;
1152  		}
1153  
1154  		if (!sap_chan_bond_dfs_sub_chan(
1155  				sap_ctx, sap_ctx->chan_freq,
1156  				PHY_CHANNEL_BONDING_STATE_MAX)) {
1157  			sap_debug("Ignore Radar event for sap ch freq: %d",
1158  				  sap_ctx->chan_freq);
1159  			goto EXIT;
1160  		}
1161  
1162  		if (wlan_pre_cac_get_status(mac_ctx->psoc)) {
1163  			wlan_sap_pre_cac_radar_ind(sap_ctx, mac_ctx);
1164  			break;
1165  		}
1166  
1167  		sap_debug("sapdfs: Indicate eSAP_DFS_RADAR_DETECT to HDD");
1168  		sap_signal_hdd_event(sap_ctx, NULL, eSAP_DFS_RADAR_DETECT,
1169  				     (void *) eSAP_STATUS_SUCCESS);
1170  		mac_ctx->sap.SapDfsInfo.target_chan_freq =
1171  			sap_indicate_radar(sap_ctx);
1172  
1173  		/* if there is an assigned next channel hopping */
1174  		if (0 < mac_ctx->sap.SapDfsInfo.user_provided_target_chan_freq) {
1175  			mac_ctx->sap.SapDfsInfo.target_chan_freq =
1176  			   mac_ctx->sap.SapDfsInfo.user_provided_target_chan_freq;
1177  			mac_ctx->sap.SapDfsInfo.user_provided_target_chan_freq =
1178  			   0;
1179  		}
1180  		/* if external acs enabled */
1181  		if (sap_ctx->vendor_acs_dfs_lte_enabled &&
1182  		    !mac_ctx->sap.SapDfsInfo.target_chan_freq) {
1183  			/* Return from here, processing will be done later */
1184  			goto EXIT;
1185  		}
1186  		if (mac_ctx->sap.SapDfsInfo.target_chan_freq != 0) {
1187  			sap_cac_reset_notify(mac_handle);
1188  			break;
1189  		}
1190  		/* Issue stopbss for each sapctx */
1191  		for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) {
1192  			struct sap_context *sap_context;
1193  
1194  			if (((QDF_SAP_MODE ==
1195  			    mac_ctx->sap.sapCtxList[intf].sapPersona) ||
1196  			    (QDF_P2P_GO_MODE ==
1197  			    mac_ctx->sap.sapCtxList[intf].sapPersona)) &&
1198  			    mac_ctx->sap.sapCtxList[intf].sap_context !=
1199  			    NULL) {
1200  				sap_context =
1201  				    mac_ctx->sap.sapCtxList[intf].sap_context;
1202  				if (!wlan_reg_is_passive_or_disable_for_pwrmode(
1203  						mac_ctx->pdev,
1204  						sap_context->chan_freq,
1205  						REG_CURRENT_PWR_MODE))
1206  					continue;
1207  				sap_debug("Vdev %d no channel available , stop bss",
1208  					  sap_context->sessionId);
1209  				sap_signal_hdd_event(sap_context, NULL,
1210  					eSAP_STOP_BSS_DUE_TO_NO_CHNL,
1211  					(void *) eSAP_STATUS_SUCCESS);
1212  			}
1213  		}
1214  		break;
1215  	case eCSR_ROAM_DFS_CHAN_SW_NOTIFY:
1216  		sap_debug("Received Chan Sw Update Notification");
1217  		break;
1218  	case eCSR_ROAM_SET_CHANNEL_RSP:
1219  		sap_debug("Received set channel response");
1220  		ucfg_if_mgr_deliver_event(sap_ctx->vdev,
1221  					  WLAN_IF_MGR_EV_AP_CSA_COMPLETE,
1222  					  NULL);
1223  		break;
1224  	case eCSR_ROAM_CAC_COMPLETE_IND:
1225  		sap_debug("Received cac complete indication");
1226  		break;
1227  	case eCSR_ROAM_EXT_CHG_CHNL_IND:
1228  		sap_debug("Received set channel Indication");
1229  		break;
1230  	case eCSR_ROAM_CHANNEL_INFO_EVENT_IND:
1231  		wlansap_process_chan_info_event(sap_ctx, csr_roam_info);
1232  		break;
1233  	default:
1234  		break;
1235  	}
1236  
1237  	switch (roam_result) {
1238  	case eCSR_ROAM_RESULT_INFRA_ASSOCIATION_IND:
1239  		if (csr_roam_info)
1240  			wlansap_roam_process_infra_assoc_ind(sap_ctx,
1241  						roam_result,
1242  						csr_roam_info, &qdf_ret_status);
1243  		break;
1244  	case eCSR_ROAM_RESULT_INFRA_ASSOCIATION_CNF:
1245  		if (!csr_roam_info) {
1246  			sap_err("csr_roam_info is NULL");
1247  			qdf_ret_status = QDF_STATUS_E_NULL_VALUE;
1248  			break;
1249  		}
1250  		sap_ctx->nStaWPARSnReqIeLength = csr_roam_info->rsnIELen;
1251  		if (sap_ctx->nStaWPARSnReqIeLength)
1252  			qdf_mem_copy(sap_ctx->pStaWpaRsnReqIE,
1253  				     csr_roam_info->prsnIE,
1254  				     sap_ctx->nStaWPARSnReqIeLength);
1255  
1256  		/* Fill in the event structure */
1257  		qdf_status = sap_signal_hdd_event(sap_ctx, csr_roam_info,
1258  					eSAP_STA_ASSOC_EVENT,
1259  					(void *) eSAP_STATUS_SUCCESS);
1260  		if (!QDF_IS_STATUS_SUCCESS(qdf_status))
1261  			qdf_ret_status = QDF_STATUS_E_FAILURE;
1262  		break;
1263  	case eCSR_ROAM_RESULT_DEAUTH_IND:
1264  	case eCSR_ROAM_RESULT_DISASSOC_IND:
1265  		/* Fill in the event structure */
1266  		qdf_status = sap_signal_hdd_event(sap_ctx, csr_roam_info,
1267  					eSAP_STA_DISASSOC_EVENT,
1268  					(void *) eSAP_STATUS_SUCCESS);
1269  		if (!QDF_IS_STATUS_SUCCESS(qdf_status))
1270  			qdf_ret_status = QDF_STATUS_E_FAILURE;
1271  		break;
1272  	case eCSR_ROAM_RESULT_MIC_ERROR_GROUP:
1273  		/*
1274  		 * Fill in the event structure
1275  		 * TODO: support for group key MIC failure event to be handled
1276  		 */
1277  		qdf_status = sap_signal_hdd_event(sap_ctx, csr_roam_info,
1278  						eSAP_STA_MIC_FAILURE_EVENT,
1279  						(void *) NULL);
1280  		if (!QDF_IS_STATUS_SUCCESS(qdf_status))
1281  			qdf_ret_status = QDF_STATUS_E_FAILURE;
1282  		break;
1283  	case eCSR_ROAM_RESULT_MIC_ERROR_UNICAST:
1284  		/*
1285  		 * Fill in the event structure
1286  		 * TODO: support for unicast key MIC failure event to be handled
1287  		 */
1288  		qdf_status =
1289  			sap_signal_hdd_event(sap_ctx, csr_roam_info,
1290  					  eSAP_STA_MIC_FAILURE_EVENT,
1291  					  (void *) NULL);
1292  		if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1293  			qdf_ret_status = QDF_STATUS_E_FAILURE;
1294  		}
1295  		break;
1296  	case eCSR_ROAM_RESULT_AUTHENTICATED:
1297  		/* Fill in the event structure */
1298  		sap_signal_hdd_event(sap_ctx, csr_roam_info,
1299  				  eSAP_STA_SET_KEY_EVENT,
1300  				  (void *) eSAP_STATUS_SUCCESS);
1301  		if (!QDF_IS_STATUS_SUCCESS(qdf_status))
1302  			qdf_ret_status = QDF_STATUS_E_FAILURE;
1303  		break;
1304  	case eCSR_ROAM_RESULT_INFRA_STARTED:
1305  		if (!csr_roam_info) {
1306  			sap_err("csr_roam_info is NULL");
1307  			qdf_ret_status = QDF_STATUS_E_NULL_VALUE;
1308  			break;
1309  		}
1310  		/*
1311  		 * In the current implementation, hostapd is not aware that
1312  		 * drive will support DFS. Hence, driver should inform
1313  		 * eSAP_MAC_START_BSS_SUCCESS to upper layers and then perform
1314  		 * CAC underneath
1315  		 */
1316  		sap_event.event = eSAP_MAC_START_BSS_SUCCESS;
1317  		sap_event.params = csr_roam_info;
1318  		sap_ctx->sap_sta_id = csr_roam_info->staId;
1319  		sap_event.u1 = roam_status;
1320  		sap_event.u2 = roam_result;
1321  		qdf_status = sap_fsm(sap_ctx, &sap_event);
1322  		if (!QDF_IS_STATUS_SUCCESS(qdf_status))
1323  			qdf_ret_status = QDF_STATUS_E_FAILURE;
1324  		break;
1325  	case eCSR_ROAM_RESULT_INFRA_STOPPED:
1326  		/* Fill in the event structure */
1327  		sap_event.event = eSAP_MAC_READY_FOR_CONNECTIONS;
1328  		sap_event.params = csr_roam_info;
1329  		sap_event.u1 = roam_status;
1330  		sap_event.u2 = roam_result;
1331  		/* Handle event */
1332  		qdf_status = sap_fsm(sap_ctx, &sap_event);
1333  		if (!QDF_IS_STATUS_SUCCESS(qdf_status))
1334  			qdf_ret_status = QDF_STATUS_E_FAILURE;
1335  		break;
1336  	case eCSR_ROAM_RESULT_WPS_PBC_PROBE_REQ_IND:
1337  		/*
1338  		 * Fill in the event structure
1339  		 * TODO: support for group key MIC failure event to be handled
1340  		 */
1341  		qdf_status = sap_signal_hdd_event(sap_ctx, csr_roam_info,
1342  						eSAP_WPS_PBC_PROBE_REQ_EVENT,
1343  						(void *) NULL);
1344  		if (!QDF_IS_STATUS_SUCCESS(qdf_status))
1345  			qdf_ret_status = QDF_STATUS_E_FAILURE;
1346  		break;
1347  	case eCSR_ROAM_RESULT_FORCED:
1348  		/*
1349  		 * This event can be used to inform hdd about user triggered
1350  		 * disassoc event
1351  		 * Fill in the event structure
1352  		 */
1353  		sap_signal_hdd_event(sap_ctx, csr_roam_info,
1354  				     eSAP_STA_DISASSOC_EVENT,
1355  				     (void *) eSAP_STATUS_SUCCESS);
1356  		break;
1357  	case eCSR_ROAM_RESULT_NONE:
1358  		/*
1359  		 * This event can be used to inform hdd about user triggered
1360  		 * disassoc event
1361  		 * Fill in the event structure
1362  		 */
1363  		if (roam_status == eCSR_ROAM_SET_KEY_COMPLETE) {
1364  			sap_signal_hdd_event(sap_ctx, csr_roam_info,
1365  					     eSAP_STA_SET_KEY_EVENT,
1366  					     (void *) eSAP_STATUS_SUCCESS);
1367  		/*
1368  		 * After set key if this is the first peer connecting to new GO
1369  		 * then check for peer count (which is self peer + peer count)
1370  		 * and take decision for GO+GO, STA+GO and CLI+GO force SCC
1371  		 */
1372  			sap_check_and_process_go_force_scc(sap_ctx);
1373  		}
1374  		break;
1375  	case eCSR_ROAM_RESULT_MAX_ASSOC_EXCEEDED:
1376  		/* Fill in the event structure */
1377  		qdf_status = sap_signal_hdd_event(sap_ctx, csr_roam_info,
1378  						  eSAP_MAX_ASSOC_EXCEEDED,
1379  						  NULL);
1380  		if (!QDF_IS_STATUS_SUCCESS(qdf_status))
1381  			qdf_ret_status = QDF_STATUS_E_FAILURE;
1382  
1383  		break;
1384  	case eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND:
1385  		if (!policy_mgr_get_dfs_master_dynamic_enabled(
1386  				mac_ctx->psoc, sap_ctx->sessionId))
1387  			break;
1388  		wlansap_roam_process_dfs_radar_found(mac_ctx, sap_ctx,
1389  						&qdf_ret_status);
1390  		break;
1391  	case eCSR_ROAM_RESULT_CSA_RESTART_RSP:
1392  		qdf_ret_status = wlansap_dfs_send_csa_ie_request(sap_ctx);
1393  
1394  		if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status))
1395  			sap_debug("CSR roam_result = eCSR_ROAM_RESULT_CSA_RESTART_RSP %d",
1396  				  roam_result);
1397  		break;
1398  	case eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS:
1399  		wlansap_roam_process_dfs_chansw_update(mac_handle, sap_ctx,
1400  						       &qdf_ret_status);
1401  		break;
1402  	case eCSR_ROAM_RESULT_CAC_END_IND:
1403  		sap_dfs_cac_timer_callback(mac_handle);
1404  		break;
1405  	case eCSR_ROAM_RESULT_CHANNEL_CHANGE_SUCCESS:
1406  		wlansap_roam_process_ch_change_success(mac_ctx, sap_ctx,
1407  						csr_roam_info, &qdf_ret_status);
1408  
1409  		if (QDF_IS_STATUS_ERROR(qdf_ret_status))
1410  			qdf_ret_status =
1411  				sap_signal_hdd_event(sap_ctx, csr_roam_info,
1412  						     eSAP_CHANNEL_CHANGE_RESP,
1413  						   (void *)eSAP_STATUS_FAILURE);
1414  		else
1415  			qdf_ret_status =
1416  				sap_signal_hdd_event(sap_ctx, csr_roam_info,
1417  						     eSAP_CHANNEL_CHANGE_RESP,
1418  						   (void *)eSAP_STATUS_SUCCESS);
1419  		break;
1420  	case eCSR_ROAM_RESULT_CHANNEL_CHANGE_FAILURE:
1421  		qdf_ret_status =
1422  			sap_signal_hdd_event(sap_ctx, csr_roam_info,
1423  					     eSAP_CHANNEL_CHANGE_RESP,
1424  					     (void *)eSAP_STATUS_FAILURE);
1425  		break;
1426  	case eCSR_ROAM_EXT_CHG_CHNL_UPDATE_IND:
1427  		qdf_status = sap_signal_hdd_event(sap_ctx, csr_roam_info,
1428  				   eSAP_ECSA_CHANGE_CHAN_IND, NULL);
1429  		if (!QDF_IS_STATUS_SUCCESS(qdf_status))
1430  			qdf_ret_status = QDF_STATUS_E_FAILURE;
1431  		break;
1432  	default:
1433  		sap_err("CSR roam_result = %s (%d) not handled",
1434  			 get_e_csr_roam_result_str(roam_result),
1435  			 roam_result);
1436  		break;
1437  	}
1438  EXIT:
1439  	wlansap_context_put(sap_ctx);
1440  	return qdf_ret_status;
1441  }
1442  
sap_scan_event_callback(struct wlan_objmgr_vdev * vdev,struct scan_event * event,void * arg)1443  void sap_scan_event_callback(struct wlan_objmgr_vdev *vdev,
1444  			struct scan_event *event, void *arg)
1445  {
1446  	uint32_t scan_id;
1447  	uint8_t session_id;
1448  	bool success = false;
1449  	eCsrScanStatus scan_status = eCSR_SCAN_FAILURE;
1450  	mac_handle_t mac_handle;
1451  	QDF_STATUS status;
1452  
1453  	/*
1454  	 * It may happen that the SAP was deleted before the scan
1455  	 * cb was called. Here the sap context which was passed as an
1456  	 * arg to the ACS cb is used after free then, and there is no way
1457  	 * currently to validate the pointer. Now try get vdev ref before
1458  	 * the weight calculation algo kicks in, and return if the
1459  	 * reference cannot be taken to avoid use after free for SAP-context
1460  	 */
1461  	status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_LEGACY_SAP_ID);
1462  	if (QDF_IS_STATUS_ERROR(status)) {
1463  		sap_err("Hotspot fail, vdev ref get error");
1464  		return;
1465  	}
1466  	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SAP_ID);
1467  
1468  	session_id = wlan_vdev_get_id(vdev);
1469  	scan_id = event->scan_id;
1470  	mac_handle = cds_get_context(QDF_MODULE_ID_SME);
1471  	if (!mac_handle)
1472  		return;
1473  
1474  	qdf_mtrace(QDF_MODULE_ID_SCAN, QDF_MODULE_ID_SAP, event->type,
1475  		   event->vdev_id, event->scan_id);
1476  
1477  	if (!util_is_scan_completed(event, &success))
1478  		return;
1479  
1480  	if (success)
1481  		scan_status = eCSR_SCAN_SUCCESS;
1482  
1483  	wlansap_pre_start_bss_acs_scan_callback(mac_handle,
1484  						arg, session_id,
1485  						scan_id, scan_status);
1486  }
1487  
1488  #ifdef WLAN_FEATURE_SAP_ACS_OPTIMIZE
1489  #define WLAN_INVALID_PDEV_ID 0xFFFFFFFF
1490  /**
1491   * sap_mark_freq_as_clean(): This API marks a channel is clean which means
1492   * we didn't see any AP's on this channel
1493   * @clean_channel_array: array of chan enum containing that chan free or not
1494   * @freq: freq for which flag needs to be updated
1495   *
1496   * Return: void
1497   */
1498  static
sap_mark_freq_as_clean(bool * clean_channel_array,qdf_freq_t freq)1499  void sap_mark_freq_as_clean(bool *clean_channel_array,
1500  			    qdf_freq_t freq)
1501  {
1502  	uint32_t ch_index;
1503  	ch_index = wlan_reg_get_chan_enum_for_freq(freq);
1504  	if (ch_index >= INVALID_CHANNEL)
1505  		return;
1506  	clean_channel_array[ch_index] = true;
1507  }
1508  
1509  /**
1510   * sap_is_prev_n_freqs_free(): previous frequencies free or not based on channel
1511   * width
1512   * @clean_channel_array: array of chan enum containing that chan free or not
1513   * @curr_index: Chan enum of current scanned channel
1514   * @prev_n_freq_count: no. of freq  to be monitored based on BW
1515   * @range: Bonded channel freq range
1516   *
1517   *Return: true if previous channels free else false
1518   */
1519  static
sap_is_prev_n_freqs_free(bool * clean_channel_array,uint32_t curr_index,uint32_t prev_n_freq_count,const struct bonded_channel_freq * range)1520  bool sap_is_prev_n_freqs_free(bool *clean_channel_array, uint32_t curr_index,
1521  			      uint32_t prev_n_freq_count,
1522  			      const struct bonded_channel_freq *range)
1523  {
1524  	uint32_t index;
1525  	uint32_t min_index = wlan_reg_get_chan_enum_for_freq(range->start_freq);
1526  	uint32_t max_index = wlan_reg_get_chan_enum_for_freq(range->end_freq);
1527  	if (max_index >= INVALID_CHANNEL ||
1528  	    min_index >= INVALID_CHANNEL)
1529  		return false;
1530  	if (curr_index > max_index || curr_index < min_index) {
1531  		sap_debug("invalid chan index %d", curr_index);
1532  		return false;
1533  	}
1534  	/*
1535  	 * curr_index will be present in range, so bonded freq
1536  	 * range can be checked to decide curr_index is best
1537  	 * available channel or not.
1538  	 */
1539  	for (index = min_index; index > 0 && index <= max_index;
1540  	     index++) {
1541  		if (!clean_channel_array[index]) {
1542  			sap_debug("chan_index %d not free", index);
1543  			return false;
1544  		}
1545  	}
1546  	if ((index - min_index) < prev_n_freq_count) {
1547  		sap_debug("previous %d are not validated", prev_n_freq_count);
1548  		return false;
1549  	}
1550  
1551  	return true;
1552  }
1553  
1554  /**
1555   * is_freq_allowed_for_sap(): is frequency allowed to start SAP
1556   * @pdev: object manager pdev
1557   * @clean_channel_array: array of chan enum containing that chan free or not
1558   * @freq: Scanned frequency
1559   * @ch_width: phy channel width
1560   * @vdev: object manager vdev
1561   *
1562   * Return: true if frequency is allowed based on BW else false.
1563   */
1564  static
is_freq_allowed_for_sap(struct wlan_objmgr_pdev * pdev,bool * clean_channel_array,qdf_freq_t freq,enum phy_ch_width ch_width,struct wlan_objmgr_vdev * vdev)1565  bool is_freq_allowed_for_sap(struct wlan_objmgr_pdev *pdev,
1566  			     bool *clean_channel_array,
1567  			     qdf_freq_t freq, enum phy_ch_width ch_width,
1568  			     struct wlan_objmgr_vdev *vdev) {
1569  	uint16_t min_bw = 0;
1570  	uint16_t max_bw = 0;
1571  	uint16_t curr_bw;
1572  	struct wlan_objmgr_psoc *psoc;
1573  	QDF_STATUS status;
1574  	const struct bonded_channel_freq *range = NULL;
1575  	uint32_t curr_index = wlan_reg_get_chan_enum_for_freq(freq);
1576  	if (curr_index >= INVALID_CHANNEL)
1577  		return false;
1578  	psoc = wlan_pdev_get_psoc(pdev);
1579  	if (!psoc) {
1580  		sap_err("invalid psoc");
1581  		return false;
1582  	}
1583  	if (wlan_mlme_get_ap_policy(vdev) ==
1584  	    HOST_CONCURRENT_AP_POLICY_UNSPECIFIED) {
1585  		sap_debug("low latency sap is not present");
1586  		return false;
1587  	}
1588  	/*
1589  	 * Don't allow frequency that can be shared with 2 GHz frequency
1590  	 * on same MAC.
1591  	 */
1592  	if (policy_mgr_2_freq_always_on_same_mac
1593  			(psoc, wlan_reg_min_24ghz_chan_freq(), freq)) {
1594  		sap_debug("frequency can be shared by 2G MAC");
1595  		return false;
1596  	}
1597  
1598  	status =
1599  	wlan_reg_get_min_max_bw_for_chan_index(pdev, curr_index, &min_bw,
1600  					       &max_bw);
1601  	if (status != QDF_STATUS_SUCCESS) {
1602  		sap_err("get bw for curr channel failed");
1603  		return false;
1604  	}
1605  	curr_bw = wlan_reg_get_bw_value(ch_width);
1606  	if (curr_bw < min_bw || curr_bw > max_bw) {
1607  		sap_debug("frequency doesn't support configured bw");
1608  		return false;
1609  	}
1610  	range = wlan_reg_get_bonded_chan_entry(freq, ch_width, 0);
1611  	if (!range) {
1612  		sap_debug("Invalid freq range for freq: %d and ch_width: %d",
1613  			  freq, ch_width);
1614  		return false;
1615  	}
1616  	sap_debug("freq range for bw %d is %d-%d", ch_width, range->start_freq,
1617  		  range->end_freq);
1618  
1619  	switch (ch_width) {
1620  	case CH_WIDTH_40MHZ:
1621  		return sap_is_prev_n_freqs_free(clean_channel_array,
1622  						curr_index, 40/20,
1623  						range);
1624  	case CH_WIDTH_80MHZ:
1625  		return sap_is_prev_n_freqs_free(clean_channel_array,
1626  						curr_index, 80/20,
1627  						range);
1628  	case CH_WIDTH_160MHZ:
1629  		return sap_is_prev_n_freqs_free(clean_channel_array,
1630  						curr_index, 160/20,
1631  						range);
1632  	case CH_WIDTH_320MHZ:
1633  		return sap_is_prev_n_freqs_free(clean_channel_array,
1634  						curr_index, 320/20,
1635  						range);
1636  	default:
1637  		return false;
1638  	}
1639  	return false;
1640  }
1641  
wlansap_process_chan_info_event(struct sap_context * sap_ctx,struct csr_roam_info * roam_info)1642  void wlansap_process_chan_info_event(struct sap_context *sap_ctx,
1643  				     struct csr_roam_info *roam_info)
1644  {
1645  	struct mac_context *mac;
1646  	struct scan_filter *filter;
1647  	qdf_list_t *list = NULL;
1648  	enum channel_state state;
1649  
1650  	mac = sap_get_mac_context();
1651  	if (!mac) {
1652  		sap_err("Invalid MAC context");
1653  		return;
1654  	}
1655  
1656  	if (!hdd_sap_is_acs_in_progress(sap_ctx->vdev))
1657  		return;
1658  
1659  	if (SAP_INIT != sap_ctx->fsm_state)
1660  		return;
1661  
1662  	if (WLAN_REG_IS_24GHZ_CH_FREQ(roam_info->chan_info_freq))
1663  		return;
1664  
1665  	state = wlan_reg_get_channel_state_for_pwrmode(
1666  				mac->pdev, roam_info->chan_info_freq,
1667  				REG_CURRENT_PWR_MODE);
1668  	if (state != CHANNEL_STATE_ENABLE)
1669  		return;
1670  
1671  	if (sap_ctx->optimize_acs_chan_selected)
1672  		return;
1673  
1674  	if (!sap_ctx->acs_cfg) {
1675  		sap_debug("acs_cfg is null");
1676  		return;
1677  	}
1678  
1679  	/* If chan_info_freq is not preferred band's freq
1680  	 * do not select it as ACS result.
1681  	 */
1682  	if (sap_ctx->acs_cfg->ch_list_count &&
1683  	    !wlan_reg_is_same_band_freqs(
1684  			sap_ctx->acs_cfg->freq_list[
1685  			sap_ctx->acs_cfg->ch_list_count - 1],
1686  			roam_info->chan_info_freq))
1687  		return;
1688  	/* Confirm the freq is in ACS list. */
1689  	if (!wlansap_is_channel_present_in_acs_list(
1690  			    roam_info->chan_info_freq,
1691  			    sap_ctx->acs_cfg->freq_list,
1692  			    sap_ctx->acs_cfg->ch_list_count))
1693  		return;
1694  	/* For 6 GHz, do not select non PSC channel */
1695  	if (wlan_reg_is_6ghz_chan_freq(
1696  		    roam_info->chan_info_freq) &&
1697  	    !wlan_reg_is_6ghz_psc_chan_freq(
1698  		    roam_info->chan_info_freq))
1699  		return;
1700  
1701  	filter = qdf_mem_malloc(sizeof(*filter));
1702  	if (!filter)
1703  		return;
1704  
1705  	filter->age_threshold = qdf_get_time_of_the_day_ms() -
1706  				sap_ctx->acs_req_timestamp;
1707  	filter->num_of_channels = 1;
1708  	filter->chan_freq_list[0] = roam_info->chan_info_freq;
1709  
1710  	list = ucfg_scan_get_result(mac->pdev, filter);
1711  	qdf_mem_free(filter);
1712  	if (!list)
1713  		return;
1714  
1715  	if (qdf_list_size(list))
1716  		goto exit;
1717  
1718  	if (!policy_mgr_is_sap_freq_allowed(mac->psoc,
1719  				wlan_vdev_mlme_get_opmode(sap_ctx->vdev),
1720  				roam_info->chan_info_freq))
1721  		goto exit;
1722  	if (sap_ctx->acs_cfg->ch_width > CH_WIDTH_20MHZ) {
1723  		sap_mark_freq_as_clean(sap_ctx->clean_channel_array,
1724  				       roam_info->chan_info_freq);
1725  		if (!is_freq_allowed_for_sap(mac->pdev,
1726  					     sap_ctx->clean_channel_array,
1727  					     roam_info->chan_info_freq,
1728  					     sap_ctx->acs_cfg->ch_width,
1729  					     sap_ctx->vdev)) {
1730  			goto exit;
1731  		}
1732  	}
1733  
1734  	sap_debug("ACS Best channel %d as no beacon/probe rsp found\n",
1735  		  roam_info->chan_info_freq);
1736  
1737  	sap_ctx->optimize_acs_chan_selected = true;
1738  
1739  	wlan_abort_scan(mac->pdev, WLAN_INVALID_PDEV_ID,
1740  			sap_ctx->sessionId, INVALID_SCAN_ID, false);
1741  
1742  	wlansap_set_acs_ch_freq(sap_ctx, roam_info->chan_info_freq);
1743  	sap_ctx->acs_cfg->pri_ch_freq = roam_info->chan_info_freq;
1744  	sap_config_acs_result(MAC_HANDLE(mac), sap_ctx,
1745  			      sap_ctx->acs_cfg->ht_sec_ch_freq);
1746  
1747  	wlansap_dump_acs_ch_freq(sap_ctx);
1748  
1749  	sap_ctx->sap_state = eSAP_ACS_CHANNEL_SELECTED;
1750  	sap_ctx->sap_status = eSAP_STATUS_SUCCESS;
1751  
1752  	if (sap_ctx->freq_list) {
1753  		qdf_mem_free(sap_ctx->freq_list);
1754  		sap_ctx->freq_list = NULL;
1755  		sap_ctx->num_of_channel = 0;
1756  	}
1757  
1758  	sap_hdd_signal_event_handler(sap_ctx);
1759  
1760  exit:
1761  	ucfg_scan_purge_results(list);
1762  }
1763  #endif
1764