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