xref: /wlan-dirver/qcacld-3.0/core/sap/src/sap_fsm.c (revision 32f63dc370adac4d2694d98ae22869c1330dc253)
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 F s m . C
23 
24    OVERVIEW:
25 
26    This software unit holds the implementation of the WLAN SAP Finite
27    State Machine modules
28 
29    DEPENDENCIES:
30 
31    Are listed for each API below.
32    ===========================================================================*/
33 
34 /*----------------------------------------------------------------------------
35  * Include Files
36  * -------------------------------------------------------------------------*/
37 #include "sap_internal.h"
38 #include <wlan_dfs_tgt_api.h>
39 #include <wlan_dfs_utils_api.h>
40 #include <wlan_dfs_public_struct.h>
41 #include <wlan_reg_services_api.h>
42 /* Pick up the SME API definitions */
43 #include "sme_api.h"
44 /* Pick up the PMC API definitions */
45 #include "cds_utils.h"
46 #include "cds_ieee80211_common_i.h"
47 #include "cds_reg_service.h"
48 #include "qdf_util.h"
49 #include "wlan_policy_mgr_api.h"
50 #include <wlan_objmgr_pdev_obj.h>
51 #include <wlan_objmgr_vdev_obj.h>
52 #include <wlan_utility.h>
53 #include <linux/netdevice.h>
54 #include <net/cfg80211.h>
55 #include <qca_vendor.h>
56 #include <wlan_scan_api.h>
57 #include "wlan_reg_services_api.h"
58 #include "wlan_mlme_ucfg_api.h"
59 #include "wlan_policy_mgr_ucfg.h"
60 #include "cfg_ucfg_api.h"
61 #include "wlan_mlme_vdev_mgr_interface.h"
62 #include "wlan_vdev_mgr_utils_api.h"
63 #include "wlan_pre_cac_api.h"
64 #include <wlan_cmn_ieee80211.h>
65 #include <target_if.h>
66 #include "wlan_ll_sap_api.h"
67 
68 /*----------------------------------------------------------------------------
69  * Preprocessor Definitions and Constants
70  * -------------------------------------------------------------------------*/
71 
72 /*----------------------------------------------------------------------------
73  * Type Declarations
74  * -------------------------------------------------------------------------*/
75 
76 /*----------------------------------------------------------------------------
77  * Global Data Definitions
78  * -------------------------------------------------------------------------*/
79 
80 /*----------------------------------------------------------------------------
81  *  External declarations for global context
82  * -------------------------------------------------------------------------*/
83 /*----------------------------------------------------------------------------
84  * Static Variable Definitions
85  * -------------------------------------------------------------------------*/
86 
87 /*----------------------------------------------------------------------------
88  * Static Function Declarations and Definitions
89  * -------------------------------------------------------------------------*/
90 #ifdef SOFTAP_CHANNEL_RANGE
91 static QDF_STATUS sap_get_freq_list(struct sap_context *sap_ctx,
92 				    uint32_t **freq_list,
93 				    uint8_t *num_ch);
94 #endif
95 
96 /*==========================================================================
97    FUNCTION    sapStopDfsCacTimer
98 
99    DESCRIPTION
100     Function to sttop the DFS CAC timer when SAP is stopped
101    DEPENDENCIES
102     NA.
103 
104    PARAMETERS
105 
106     IN
107     sap_ctx: SAP Context
108    RETURN VALUE
109     DFS Timer start status
110    SIDE EFFECTS
111    ============================================================================*/
112 
113 static int sap_stop_dfs_cac_timer(struct sap_context *sap_ctx);
114 
115 /*==========================================================================
116    FUNCTION    sapStartDfsCacTimer
117 
118    DESCRIPTION
119     Function to start the DFS CAC timer when SAP is started on DFS Channel
120    DEPENDENCIES
121     NA.
122 
123    PARAMETERS
124 
125     IN
126     sap_ctx: SAP Context
127    RETURN VALUE
128     DFS Timer start status
129    SIDE EFFECTS
130    ============================================================================*/
131 
132 static int sap_start_dfs_cac_timer(struct sap_context *sap_ctx);
133 
134 /** sap_hdd_event_to_string() - convert hdd event to string
135  * @event: eSapHddEvent event type
136  *
137  * This function converts eSapHddEvent into string
138  *
139  * Return: string for the @event.
140  */
141 static uint8_t *sap_hdd_event_to_string(eSapHddEvent event)
142 {
143 	switch (event) {
144 	CASE_RETURN_STRING(eSAP_START_BSS_EVENT);
145 	CASE_RETURN_STRING(eSAP_STOP_BSS_EVENT);
146 	CASE_RETURN_STRING(eSAP_STA_ASSOC_IND);
147 	CASE_RETURN_STRING(eSAP_STA_ASSOC_EVENT);
148 	CASE_RETURN_STRING(eSAP_STA_REASSOC_EVENT);
149 	CASE_RETURN_STRING(eSAP_STA_DISASSOC_EVENT);
150 	CASE_RETURN_STRING(eSAP_STA_SET_KEY_EVENT);
151 	CASE_RETURN_STRING(eSAP_STA_MIC_FAILURE_EVENT);
152 	CASE_RETURN_STRING(eSAP_WPS_PBC_PROBE_REQ_EVENT);
153 	CASE_RETURN_STRING(eSAP_DISCONNECT_ALL_P2P_CLIENT);
154 	CASE_RETURN_STRING(eSAP_MAC_TRIG_STOP_BSS_EVENT);
155 	CASE_RETURN_STRING(eSAP_UNKNOWN_STA_JOIN);
156 	CASE_RETURN_STRING(eSAP_MAX_ASSOC_EXCEEDED);
157 	CASE_RETURN_STRING(eSAP_CHANNEL_CHANGE_EVENT);
158 	CASE_RETURN_STRING(eSAP_DFS_CAC_START);
159 	CASE_RETURN_STRING(eSAP_DFS_CAC_INTERRUPTED);
160 	CASE_RETURN_STRING(eSAP_DFS_CAC_END);
161 	CASE_RETURN_STRING(eSAP_DFS_RADAR_DETECT);
162 	CASE_RETURN_STRING(eSAP_DFS_NO_AVAILABLE_CHANNEL);
163 #ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
164 	CASE_RETURN_STRING(eSAP_ACS_SCAN_SUCCESS_EVENT);
165 #endif
166 	CASE_RETURN_STRING(eSAP_ACS_CHANNEL_SELECTED);
167 	CASE_RETURN_STRING(eSAP_ECSA_CHANGE_CHAN_IND);
168 	default:
169 		return "eSAP_HDD_EVENT_UNKNOWN";
170 	}
171 }
172 
173 #ifdef QCA_DFS_BW_PUNCTURE
174 /**
175  * sap_is_chan_change_needed() - Check if SAP channel change needed
176  * @sap_ctx: sap context.
177  *
178  * Even some 20 MHz sub channel disabled for nol, if puncture pattern is valid,
179  * SAP still can keep current channel width and primary channel, don't need
180  * change channel.
181  *
182  * Return: bool, true: channel change needed
183  */
184 static bool
185 sap_is_chan_change_needed(struct sap_context *sap_ctx)
186 {
187 	uint8_t ch_wd;
188 	uint16_t pri_freq_puncture = 0;
189 	struct ch_params *ch_params;
190 	QDF_STATUS status;
191 	struct mac_context *mac_ctx;
192 
193 	mac_ctx = sap_get_mac_context();
194 	if (!mac_ctx) {
195 		sap_err("Invalid MAC context");
196 		return true;
197 	}
198 
199 	ch_params = &mac_ctx->sap.SapDfsInfo.new_ch_params;
200 	if (mac_ctx->sap.SapDfsInfo.orig_chanWidth == 0) {
201 		ch_wd = sap_ctx->ch_width_orig;
202 		mac_ctx->sap.SapDfsInfo.orig_chanWidth = ch_wd;
203 	} else {
204 		ch_wd = mac_ctx->sap.SapDfsInfo.orig_chanWidth;
205 	}
206 
207 	ch_params->ch_width = ch_wd;
208 
209 	if (sap_phymode_is_eht(sap_ctx->phyMode))
210 		wlan_reg_set_create_punc_bitmap(ch_params, true);
211 	wlan_reg_set_channel_params_for_pwrmode(mac_ctx->pdev,
212 						sap_ctx->chan_freq,
213 						0,
214 						ch_params,
215 						REG_CURRENT_PWR_MODE);
216 	if (ch_params->ch_width == sap_ctx->ch_params.ch_width) {
217 		status = wlan_reg_extract_puncture_by_bw(ch_params->ch_width,
218 							 ch_params->reg_punc_bitmap,
219 							 sap_ctx->chan_freq,
220 							 ch_params->mhz_freq_seg1,
221 							 CH_WIDTH_20MHZ,
222 							 &pri_freq_puncture);
223 		if (QDF_IS_STATUS_SUCCESS(status) && !pri_freq_puncture) {
224 			sap_debug("Eht valid puncture : 0x%x, keep freq %d",
225 				  ch_params->reg_punc_bitmap,
226 				  sap_ctx->chan_freq);
227 			mac_ctx->sap.SapDfsInfo.new_chanWidth =
228 						ch_params->ch_width;
229 			return false;
230 		}
231 	}
232 
233 	return true;
234 }
235 #else
236 static inline bool
237 sap_is_chan_change_needed(struct sap_context *sap_ctx)
238 {
239 	return true;
240 }
241 #endif
242 
243 #ifdef DFS_COMPONENT_ENABLE
244 /**
245  * sap_random_channel_sel() - This function randomly pick up an available
246  * channel
247  * @sap_ctx: sap context.
248  *
249  * This function first eliminates invalid channel, then selects random channel
250  * using following algorithm:
251  *
252  * Return: channel frequency picked
253  */
254 static qdf_freq_t sap_random_channel_sel(struct sap_context *sap_ctx)
255 {
256 	uint16_t chan_freq;
257 	uint8_t ch_wd;
258 	struct wlan_objmgr_pdev *pdev = NULL;
259 	struct ch_params *ch_params;
260 	uint32_t hw_mode, flag  = 0;
261 	struct mac_context *mac_ctx;
262 	struct dfs_acs_info acs_info = {0};
263 
264 	mac_ctx = sap_get_mac_context();
265 	if (!mac_ctx) {
266 		sap_err("Invalid MAC context");
267 		return 0;
268 	}
269 
270 	pdev = mac_ctx->pdev;
271 	if (!pdev) {
272 		sap_err("null pdev");
273 		return 0;
274 	}
275 
276 	ch_params = &mac_ctx->sap.SapDfsInfo.new_ch_params;
277 	if (mac_ctx->sap.SapDfsInfo.orig_chanWidth == 0) {
278 		ch_wd = sap_ctx->ch_width_orig;
279 		mac_ctx->sap.SapDfsInfo.orig_chanWidth = ch_wd;
280 	} else {
281 		ch_wd = mac_ctx->sap.SapDfsInfo.orig_chanWidth;
282 	}
283 
284 	ch_params->ch_width = ch_wd;
285 	if (sap_ctx->acs_cfg) {
286 		acs_info.acs_mode = sap_ctx->acs_cfg->acs_mode;
287 		acs_info.chan_freq_list = sap_ctx->acs_cfg->master_freq_list;
288 		acs_info.num_of_channel =
289 					sap_ctx->acs_cfg->master_ch_list_count;
290 	} else {
291 		acs_info.acs_mode = false;
292 	}
293 
294 	if (mac_ctx->mlme_cfg->dfs_cfg.dfs_prefer_non_dfs)
295 		flag |= DFS_RANDOM_CH_FLAG_NO_DFS_CH;
296 	if (mac_ctx->mlme_cfg->dfs_cfg.dfs_disable_japan_w53)
297 		flag |= DFS_RANDOM_CH_FLAG_NO_JAPAN_W53_CH;
298 	if (mac_ctx->sap.SapDfsInfo.sap_operating_chan_preferred_location
299 	    == 1)
300 		flag |= DFS_RANDOM_CH_FLAG_NO_UPEER_5G_CH;
301 	else if (mac_ctx->sap.SapDfsInfo.
302 		 sap_operating_chan_preferred_location == 2)
303 		flag |= DFS_RANDOM_CH_FLAG_NO_LOWER_5G_CH;
304 
305 	/*
306 	 * Dont choose 6ghz channel currently as legacy clients won't be able to
307 	 * scan them. In future create an ini if any customer wants 6ghz freq
308 	 * to be prioritize over 5ghz/2.4ghz.
309 	 * Currently for SAP there is a high chance of 6ghz being selected as
310 	 * an op frequency as PCL will have only 5, 6ghz freq as preferred for
311 	 * standalone SAP, and 6ghz channels being high in number.
312 	 */
313 	flag |= DFS_RANDOM_CH_FLAG_NO_6GHZ_CH;
314 
315 	if (sap_ctx->candidate_freq &&
316 	    sap_ctx->chan_freq != sap_ctx->candidate_freq &&
317 	    !utils_dfs_is_freq_in_nol(pdev, sap_ctx->candidate_freq)) {
318 		chan_freq = sap_ctx->candidate_freq;
319 		if (sap_phymode_is_eht(sap_ctx->phyMode))
320 			wlan_reg_set_create_punc_bitmap(ch_params, true);
321 		wlan_reg_set_channel_params_for_pwrmode(pdev, chan_freq, 0,
322 							ch_params,
323 							REG_CURRENT_PWR_MODE);
324 		sap_debug("random chan select candidate freq=%d", chan_freq);
325 		sap_ctx->candidate_freq = 0;
326 	} else if (QDF_IS_STATUS_ERROR(
327 				utils_dfs_get_vdev_random_channel_for_freq(
328 					pdev, sap_ctx->vdev, flag, ch_params,
329 					&hw_mode, &chan_freq, &acs_info))) {
330 		/* No available channel found */
331 		sap_err("No available channel found!!!");
332 		sap_signal_hdd_event(sap_ctx, NULL,
333 				     eSAP_DFS_NO_AVAILABLE_CHANNEL,
334 				     (void *)eSAP_STATUS_SUCCESS);
335 		return 0;
336 	}
337 
338 	mac_ctx->sap.SapDfsInfo.new_chanWidth = ch_params->ch_width;
339 	sap_ctx->ch_params.ch_width = ch_params->ch_width;
340 	sap_ctx->ch_params.sec_ch_offset = ch_params->sec_ch_offset;
341 	sap_ctx->ch_params.center_freq_seg0 = ch_params->center_freq_seg0;
342 	sap_ctx->ch_params.center_freq_seg1 = ch_params->center_freq_seg1;
343 	return chan_freq;
344 }
345 #else
346 static uint8_t sap_random_channel_sel(struct sap_context *sap_ctx)
347 {
348 	return 0;
349 }
350 #endif
351 
352 /**
353  * sap_is_channel_bonding_etsi_weather_channel() - check weather chan bonding.
354  * @sap_ctx: sap context.
355  * @chan_freq: chan frequency
356  * @ch_params: pointer to ch_params
357  *
358  * Check if given channel and channel params are bonded to weather radar
359  * channel in ETSI domain.
360  *
361  * Return: True if bonded to weather channel in ETSI
362  */
363 static bool
364 sap_is_channel_bonding_etsi_weather_channel(struct sap_context *sap_ctx,
365 					    qdf_freq_t chan_freq,
366 					    struct ch_params *ch_params)
367 {
368 	struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(sap_ctx->vdev);
369 
370 	if (IS_CH_BONDING_WITH_WEATHER_CH(wlan_reg_freq_to_chan(pdev,
371 								chan_freq)) &&
372 	    ch_params->ch_width != CH_WIDTH_20MHZ)
373 		return true;
374 
375 	return false;
376 }
377 
378 /*
379  * sap_get_bonding_channels() - get bonding channels from primary channel.
380  * @sap_ctx: Handle to SAP context.
381  * @chan_freq: Channel frequency to get bonded channels.
382  * @freq_list: Bonded channel frequency list
383  * @size: Max bonded channels
384  * @chanBondState: The channel bonding mode of the passed channel.
385  *
386  * Return: Number of sub channels
387  */
388 static uint8_t sap_get_bonding_channels(struct sap_context *sap_ctx,
389 					qdf_freq_t chan_freq,
390 					qdf_freq_t *freq_list, uint8_t size,
391 					ePhyChanBondState chanBondState)
392 {
393 	uint8_t num_freq;
394 
395 	if (!freq_list)
396 		return 0;
397 
398 	if (size < MAX_BONDED_CHANNELS)
399 		return 0;
400 
401 	switch (chanBondState) {
402 	case PHY_SINGLE_CHANNEL_CENTERED:
403 		num_freq = 1;
404 		freq_list[0] = chan_freq;
405 		break;
406 	case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY:
407 		num_freq = 2;
408 		freq_list[0] = chan_freq - 20;
409 		freq_list[1] = chan_freq;
410 		break;
411 	case PHY_DOUBLE_CHANNEL_LOW_PRIMARY:
412 		num_freq = 2;
413 		freq_list[0] = chan_freq;
414 		freq_list[1] = chan_freq + 20;
415 		break;
416 	case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW:
417 		num_freq = 4;
418 		freq_list[0] = chan_freq;
419 		freq_list[1] = chan_freq + 20;
420 		freq_list[2] = chan_freq + 40;
421 		freq_list[3] = chan_freq + 60;
422 		break;
423 	case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW:
424 		num_freq = 4;
425 		freq_list[0] = chan_freq - 20;
426 		freq_list[1] = chan_freq;
427 		freq_list[2] = chan_freq + 20;
428 		freq_list[3] = chan_freq + 40;
429 		break;
430 	case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH:
431 		num_freq = 4;
432 		freq_list[0] = chan_freq - 40;
433 		freq_list[1] = chan_freq - 20;
434 		freq_list[2] = chan_freq;
435 		freq_list[3] = chan_freq + 20;
436 		break;
437 	case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH:
438 		num_freq = 4;
439 		freq_list[0] = chan_freq - 60;
440 		freq_list[1] = chan_freq - 40;
441 		freq_list[2] = chan_freq - 20;
442 		freq_list[3] = chan_freq;
443 		break;
444 	default:
445 		num_freq = 1;
446 		freq_list[0] = chan_freq;
447 		break;
448 	}
449 
450 	return num_freq;
451 }
452 
453 /**
454  * sap_ch_params_to_bonding_channels() - get bonding channels from channel param
455  * @ch_params: channel params ( bw, pri and sec channel info)
456  * @freq_list: bonded channel frequency list
457  *
458  * Return: Number of sub channel frequencies
459  */
460 static uint8_t sap_ch_params_to_bonding_channels(
461 		struct ch_params *ch_params,
462 		qdf_freq_t *freq_list)
463 {
464 	qdf_freq_t center_freq = ch_params->mhz_freq_seg0;
465 	uint8_t num_freq = 0;
466 
467 	switch (ch_params->ch_width) {
468 	case CH_WIDTH_160MHZ:
469 		num_freq = 8;
470 		center_freq = ch_params->mhz_freq_seg1;
471 		freq_list[0] = center_freq - 70;
472 		freq_list[1] = center_freq - 50;
473 		freq_list[2] = center_freq - 30;
474 		freq_list[3] = center_freq - 10;
475 		freq_list[4] = center_freq + 10;
476 		freq_list[5] = center_freq + 30;
477 		freq_list[6] = center_freq + 50;
478 		freq_list[7] = center_freq + 70;
479 		break;
480 	case CH_WIDTH_80P80MHZ:
481 		num_freq = 8;
482 		freq_list[0] = center_freq - 30;
483 		freq_list[1] = center_freq - 10;
484 		freq_list[2] = center_freq + 10;
485 		freq_list[3] = center_freq + 30;
486 
487 		center_freq = ch_params->mhz_freq_seg1;
488 		freq_list[4] = center_freq - 30;
489 		freq_list[5] = center_freq - 10;
490 		freq_list[6] = center_freq + 10;
491 		freq_list[7] = center_freq + 30;
492 		break;
493 	case CH_WIDTH_80MHZ:
494 		num_freq = 4;
495 		freq_list[0] = center_freq - 30;
496 		freq_list[1] = center_freq - 10;
497 		freq_list[2] = center_freq + 10;
498 		freq_list[3] = center_freq + 30;
499 		break;
500 	case CH_WIDTH_40MHZ:
501 		num_freq = 2;
502 		freq_list[0] = center_freq - 10;
503 		freq_list[1] = center_freq + 10;
504 		break;
505 	default:
506 		num_freq = 1;
507 		freq_list[0] = center_freq;
508 		break;
509 	}
510 
511 	return num_freq;
512 }
513 
514 /**
515  * sap_operating_on_dfs() - check current sap operating on dfs
516  * @mac_ctx: mac ctx
517  * @sap_ctx: SAP context
518  *
519  * Return: true if any sub channel is dfs channel
520  */
521 static
522 bool sap_operating_on_dfs(struct mac_context *mac_ctx,
523 			  struct sap_context *sap_ctx)
524 {
525 	struct wlan_channel *chan;
526 
527 	if (!sap_ctx->vdev) {
528 		sap_debug("vdev invalid");
529 		return false;
530 	}
531 
532 	chan = wlan_vdev_get_active_channel(sap_ctx->vdev);
533 	if (!chan) {
534 		sap_debug("Couldn't get vdev active channel");
535 		return false;
536 	}
537 
538 	if (chan->ch_flagext & (IEEE80211_CHAN_DFS |
539 				IEEE80211_CHAN_DFS_CFREQ2))
540 		return true;
541 
542 	return false;
543 }
544 
545 bool sap_plus_sap_cac_skip(struct mac_context *mac,
546 			   struct sap_context *sap_ctx,
547 			   qdf_freq_t chan_freq)
548 {
549 	uint8_t intf;
550 
551 	for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) {
552 		struct sap_context *sap_context =
553 			mac->sap.sapCtxList[intf].sap_context;
554 
555 		if (!sap_context || sap_context == sap_ctx)
556 			continue;
557 		if (mac->sap.sapCtxList[intf].sapPersona != QDF_SAP_MODE &&
558 		    mac->sap.sapCtxList[intf].sapPersona != QDF_P2P_GO_MODE)
559 			continue;
560 		if (sap_context->isCacEndNotified &&
561 		    sap_context->chan_freq == chan_freq &&
562 		    sap_operating_on_dfs(mac, sap_context)) {
563 			sap_debug("SAP vid %d CAC can skip due to CAC completed on other SAP vid %d",
564 				  sap_ctx->sessionId, sap_context->sessionId);
565 			return true;
566 		}
567 	}
568 
569 	return false;
570 }
571 
572 /**
573  * is_wlansap_cac_required_for_chan() - Is cac required for given channel
574  * @mac_ctx: mac ctx
575  * @sap_ctx: sap context
576  * @chan_freq: given channel
577  * @ch_params: pointer to ch_params
578  *
579  * Return: True if cac is required for given channel
580  */
581 static bool
582 is_wlansap_cac_required_for_chan(struct mac_context *mac_ctx,
583 				 struct sap_context *sap_ctx,
584 				 qdf_freq_t chan_freq,
585 				 struct ch_params *ch_params)
586 {
587 	bool is_ch_dfs = false;
588 	bool cac_required;
589 	uint8_t vdev_id_list[MAX_NUMBER_OF_CONC_CONNECTIONS];
590 	uint32_t freq_list[MAX_NUMBER_OF_CONC_CONNECTIONS];
591 	uint8_t sta_cnt, i;
592 	eSapDfsCACState_t cac_state = eSAP_DFS_DO_NOT_SKIP_CAC;
593 
594 	if (ch_params->ch_width == CH_WIDTH_160MHZ) {
595 		wlan_reg_set_create_punc_bitmap(ch_params, true);
596 		if (wlan_reg_get_5g_bonded_channel_state_for_pwrmode(mac_ctx->pdev,
597 								     chan_freq,
598 								     ch_params,
599 								     REG_CURRENT_PWR_MODE) ==
600 		    CHANNEL_STATE_DFS)
601 			is_ch_dfs = true;
602 	} else if (ch_params->ch_width == CH_WIDTH_80P80MHZ) {
603 		if (wlan_reg_get_channel_state_for_pwrmode(
604 						mac_ctx->pdev,
605 						chan_freq,
606 						REG_CURRENT_PWR_MODE) ==
607 		    CHANNEL_STATE_DFS ||
608 		    wlan_reg_get_channel_state_for_pwrmode(
609 					mac_ctx->pdev,
610 					ch_params->mhz_freq_seg1,
611 					REG_CURRENT_PWR_MODE) ==
612 				CHANNEL_STATE_DFS)
613 			is_ch_dfs = true;
614 	} else {
615 		/* Indoor channels are also marked DFS, therefore
616 		 * check if the channel has REGULATORY_CHAN_RADAR
617 		 * channel flag to identify if the channel is DFS
618 		 */
619 		if (wlan_reg_is_dfs_for_freq(mac_ctx->pdev, chan_freq))
620 			is_ch_dfs = true;
621 	}
622 	if (WLAN_REG_IS_6GHZ_CHAN_FREQ(chan_freq))
623 		is_ch_dfs = false;
624 	if (is_ch_dfs && sap_plus_sap_cac_skip(mac_ctx, sap_ctx, chan_freq))
625 		cac_state = eSAP_DFS_SKIP_CAC;
626 	sap_debug("vdev id %d chan %d is_ch_dfs %d pre_cac_complete %d ignore_cac %d cac_state %d",
627 		  sap_ctx->sessionId, chan_freq, is_ch_dfs,
628 		  wlan_pre_cac_complete_get(sap_ctx->vdev),
629 		  mac_ctx->sap.SapDfsInfo.ignore_cac,
630 		  cac_state);
631 
632 	if (!is_ch_dfs || wlan_pre_cac_complete_get(sap_ctx->vdev) ||
633 	    mac_ctx->sap.SapDfsInfo.ignore_cac ||
634 	    cac_state == eSAP_DFS_SKIP_CAC)
635 		cac_required = false;
636 	else
637 		cac_required = true;
638 
639 	if (cac_required) {
640 		sta_cnt =
641 		  policy_mgr_get_mode_specific_conn_info(mac_ctx->psoc,
642 							 freq_list,
643 							 vdev_id_list,
644 							 PM_STA_MODE);
645 
646 		for (i = 0; i < sta_cnt; i++) {
647 			if (chan_freq == freq_list[i]) {
648 				sap_debug("STA vdev id %d exists, ignore CAC",
649 					  vdev_id_list[i]);
650 				cac_required = false;
651 			}
652 		}
653 	}
654 
655 	return cac_required;
656 }
657 
658 void sap_get_cac_dur_dfs_region(struct sap_context *sap_ctx,
659 				uint32_t *cac_duration_ms,
660 				uint32_t *dfs_region,
661 				qdf_freq_t chan_freq,
662 				struct ch_params *ch_params)
663 {
664 	int i;
665 	qdf_freq_t freq_list[MAX_BONDED_CHANNELS];
666 	uint8_t num_freq;
667 	struct mac_context *mac;
668 	bool cac_required;
669 
670 	*cac_duration_ms = 0;
671 	if (!sap_ctx) {
672 		sap_err("null sap_ctx");
673 		return;
674 	}
675 
676 	mac = sap_get_mac_context();
677 	if (!mac) {
678 		sap_err("Invalid MAC context");
679 		return;
680 	}
681 
682 	wlan_reg_get_dfs_region(mac->pdev, dfs_region);
683 	cac_required = is_wlansap_cac_required_for_chan(mac, sap_ctx,
684 							chan_freq, ch_params);
685 
686 	if (!cac_required) {
687 		sap_debug("cac is not required");
688 		return;
689 	}
690 	*cac_duration_ms = DEFAULT_CAC_TIMEOUT;
691 
692 	if (*dfs_region != DFS_ETSI_REGION) {
693 		sap_debug("sapdfs: default cac duration");
694 		return;
695 	}
696 
697 	if (sap_is_channel_bonding_etsi_weather_channel(sap_ctx, chan_freq,
698 							ch_params)) {
699 		*cac_duration_ms = ETSI_WEATHER_CH_CAC_TIMEOUT;
700 		sap_debug("sapdfs: bonding_etsi_weather_channel");
701 		return;
702 	}
703 
704 	qdf_mem_zero(freq_list, sizeof(freq_list));
705 	num_freq = sap_ch_params_to_bonding_channels(ch_params, freq_list);
706 	for (i = 0; i < num_freq; i++) {
707 		if (IS_ETSI_WEATHER_FREQ(freq_list[i])) {
708 			*cac_duration_ms = ETSI_WEATHER_CH_CAC_TIMEOUT;
709 			sap_debug("sapdfs: ch freq=%d is etsi weather channel",
710 				  freq_list[i]);
711 			return;
712 		}
713 	}
714 
715 }
716 
717 void sap_dfs_set_current_channel(void *ctx)
718 {
719 	struct sap_context *sap_ctx = ctx;
720 	uint8_t vht_seg0 = sap_ctx->ch_params.center_freq_seg0;
721 	uint8_t vht_seg1 = sap_ctx->ch_params.center_freq_seg1;
722 	struct wlan_objmgr_pdev *pdev;
723 	struct mac_context *mac_ctx;
724 	uint32_t use_nol = 0;
725 	int error;
726 	bool is_dfs;
727 
728 	mac_ctx = sap_get_mac_context();
729 	if (!mac_ctx) {
730 		sap_err("Invalid MAC context");
731 		return;
732 	}
733 
734 	pdev = mac_ctx->pdev;
735 	if (!pdev) {
736 		sap_err("null pdev");
737 		return;
738 	}
739 
740 	is_dfs = wlan_mlme_check_chan_param_has_dfs(pdev,
741 						    &sap_ctx->ch_params,
742 						    sap_ctx->chan_freq);
743 
744 	sap_debug("freq=%d, dfs %d seg0=%d, seg1=%d, bw %d",
745 		  sap_ctx->chan_freq, is_dfs, vht_seg0, vht_seg1,
746 		  sap_ctx->ch_params.ch_width);
747 
748 	if (is_dfs) {
749 		if (policy_mgr_concurrent_beaconing_sessions_running(
750 		    mac_ctx->psoc)) {
751 			uint16_t con_ch_freq;
752 			mac_handle_t handle = MAC_HANDLE(mac_ctx);
753 
754 			con_ch_freq =
755 				sme_get_beaconing_concurrent_operation_channel(
756 					handle, sap_ctx->sessionId);
757 			if (!con_ch_freq ||
758 			    !wlan_reg_is_dfs_for_freq(pdev,
759 							con_ch_freq))
760 				tgt_dfs_get_radars(pdev);
761 		} else {
762 			tgt_dfs_get_radars(pdev);
763 		}
764 		tgt_dfs_set_phyerr_filter_offload(pdev);
765 
766 		if (mac_ctx->mlme_cfg->dfs_cfg.dfs_disable_channel_switch)
767 			tgt_dfs_control(pdev, DFS_SET_USENOL, &use_nol,
768 					sizeof(uint32_t), NULL, NULL, &error);
769 	}
770 }
771 
772 #ifdef FEATURE_AP_MCC_CH_AVOIDANCE
773 /**
774  * sap_check_in_avoid_ch_list() - checks if given channel present is channel
775  * avoidance list
776  *
777  * @sap_ctx:        sap context.
778  * @channel:        channel to be checked in sap_ctx's avoid ch list
779  *
780  * sap_ctx contains sap_avoid_ch_info strcut containing the list of channels on
781  * which MDM device's AP with MCC was detected. This function checks if given
782  * channel is present in that list.
783  *
784  * Return: true, if channel was present, false othersie.
785  */
786 bool sap_check_in_avoid_ch_list(struct sap_context *sap_ctx, uint8_t channel)
787 {
788 	uint8_t i = 0;
789 	struct sap_avoid_channels_info *ie_info =
790 		&sap_ctx->sap_detected_avoid_ch_ie;
791 	for (i = 0; i < sizeof(ie_info->channels); i++)
792 		if (ie_info->channels[i] == channel)
793 			return true;
794 	return false;
795 }
796 #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
797 
798 /**
799  * sap_dfs_is_channel_in_nol_list() - given bonded channel is available
800  * @sap_context: Handle to SAP context.
801  * @channel_freq: Channel freq on which availability should be checked.
802  * @chan_bondState: The channel bonding mode of the passed channel.
803  *
804  * This function Checks if a given bonded channel is available or
805  * usable for DFS operation.
806  *
807  * Return: false if channel is available, true if channel is in NOL.
808  */
809 bool
810 sap_dfs_is_channel_in_nol_list(struct sap_context *sap_context,
811 			       qdf_freq_t channel_freq,
812 			       ePhyChanBondState chan_bondState)
813 {
814 	int i;
815 	struct mac_context *mac_ctx;
816 	qdf_freq_t freq_list[MAX_BONDED_CHANNELS];
817 	uint8_t num_ch_freq;
818 	struct wlan_objmgr_pdev *pdev = NULL;
819 	enum channel_state ch_state;
820 	qdf_freq_t ch_freq;
821 
822 	mac_ctx = sap_get_mac_context();
823 	if (!mac_ctx) {
824 		sap_err("Invalid MAC context");
825 		return false;
826 	}
827 
828 	pdev = mac_ctx->pdev;
829 	if (!pdev) {
830 		sap_err("null pdev");
831 		return false;
832 	}
833 
834 	sap_context->ch_params.mhz_freq_seg0 =
835 			wlan_reg_legacy_chan_to_freq(
836 				pdev,
837 				sap_context->ch_params.center_freq_seg0);
838 	sap_context->ch_params.mhz_freq_seg1 =
839 			wlan_reg_legacy_chan_to_freq(
840 				pdev,
841 				sap_context->ch_params.center_freq_seg1);
842 
843 	/* get the bonded channels */
844 	if (channel_freq == sap_context->chan_freq &&
845 	    chan_bondState >= PHY_CHANNEL_BONDING_STATE_MAX)
846 		num_ch_freq = sap_ch_params_to_bonding_channels(
847 					&sap_context->ch_params, freq_list);
848 	else
849 		num_ch_freq = sap_get_bonding_channels(
850 					sap_context, channel_freq,
851 					freq_list, MAX_BONDED_CHANNELS,
852 					chan_bondState);
853 
854 	/* check for NOL, first on will break the loop */
855 	for (i = 0; i < num_ch_freq; i++) {
856 		ch_freq = freq_list[i];
857 
858 		ch_state =
859 			wlan_reg_get_channel_state_from_secondary_list_for_freq(
860 								pdev, ch_freq);
861 		if (CHANNEL_STATE_ENABLE != ch_state &&
862 		    CHANNEL_STATE_DFS != ch_state) {
863 			sap_err_rl("Invalid ch freq = %d, ch state=%d", ch_freq,
864 				   ch_state);
865 			return true;
866 		}
867 	} /* loop for bonded channels */
868 
869 	return false;
870 }
871 
872 bool
873 sap_chan_bond_dfs_sub_chan(struct sap_context *sap_context,
874 			   qdf_freq_t channel_freq,
875 			   ePhyChanBondState bond_state)
876 {
877 	int i;
878 	struct mac_context *mac_ctx;
879 	qdf_freq_t freq_list[MAX_BONDED_CHANNELS];
880 	uint8_t num_freq;
881 	struct wlan_objmgr_pdev *pdev;
882 
883 	mac_ctx = sap_get_mac_context();
884 	if (!mac_ctx) {
885 		sap_err("Invalid MAC context");
886 		return false;
887 	}
888 
889 	pdev = mac_ctx->pdev;
890 	if (!pdev) {
891 		sap_err("null pdev");
892 		return false;
893 	}
894 
895 	if (wlan_reg_chan_has_dfs_attribute_for_freq(pdev, channel_freq))
896 		return true;
897 
898 	/* get the bonded channels */
899 	if (channel_freq == sap_context->chan_freq &&
900 	    bond_state >= PHY_CHANNEL_BONDING_STATE_MAX)
901 		num_freq = sap_ch_params_to_bonding_channels(
902 					&sap_context->ch_params, freq_list);
903 	else
904 		num_freq = sap_get_bonding_channels(
905 					sap_context, channel_freq, freq_list,
906 					MAX_BONDED_CHANNELS, bond_state);
907 
908 	for (i = 0; i < num_freq; i++) {
909 		if (wlan_reg_chan_has_dfs_attribute_for_freq(pdev, freq_list[i])) {
910 			sap_debug("sub ch freq=%d is dfs in %d",
911 				  freq_list[i], channel_freq);
912 			return true;
913 		}
914 	}
915 
916 	return false;
917 }
918 
919 uint32_t sap_select_default_oper_chan(struct mac_context *mac_ctx,
920 				      struct sap_acs_cfg *acs_cfg)
921 {
922 	uint16_t i;
923 	uint32_t freq0 = 0, freq1 = 0, freq2 = 0, default_freq;
924 
925 	if (!acs_cfg)
926 		return 0;
927 
928 	if (!acs_cfg->ch_list_count || !acs_cfg->freq_list) {
929 		if (mac_ctx->mlme_cfg->acs.force_sap_start) {
930 			sap_debug("SAP forced, freq selected %d",
931 				  acs_cfg->master_freq_list[0]);
932 			return acs_cfg->master_freq_list[0];
933 		} else {
934 			sap_debug("No channel left for operation");
935 			return 0;
936 		}
937 	}
938 	/*
939 	 * There could be both 2.4Ghz and 5ghz channels present in the list
940 	 * based upon the Hw mode received from hostapd, it is always better
941 	 * to chose a default 5ghz operating channel than 2.4ghz, as it can
942 	 * provide a better throughput, latency than 2.4ghz. Also 40 Mhz is
943 	 * rare in 2.4ghz band, so 5ghz should be preferred. If we get a 5Ghz
944 	 * chan in the acs cfg ch list , we should go for that first else the
945 	 * default channel can be 2.4ghz.
946 	 * Add check regulatory channel state before select the channel.
947 	 */
948 
949 	for (i = 0; i < acs_cfg->ch_list_count; i++) {
950 		enum channel_state state =
951 			wlan_reg_get_channel_state_for_pwrmode(
952 					mac_ctx->pdev, acs_cfg->freq_list[i],
953 					REG_CURRENT_PWR_MODE);
954 		if (!freq0 && state == CHANNEL_STATE_ENABLE &&
955 		    WLAN_REG_IS_5GHZ_CH_FREQ(acs_cfg->freq_list[i])) {
956 			freq0 = acs_cfg->freq_list[i];
957 			break;
958 		} else if (!freq1 && state == CHANNEL_STATE_DFS &&
959 			   WLAN_REG_IS_5GHZ_CH_FREQ(acs_cfg->freq_list[i])) {
960 			freq1 = acs_cfg->freq_list[i];
961 		} else if (!freq2 && state == CHANNEL_STATE_ENABLE) {
962 			freq2 = acs_cfg->freq_list[i];
963 		}
964 	}
965 	default_freq = freq0;
966 	if (!default_freq)
967 		default_freq = freq1;
968 	if (!default_freq)
969 		default_freq = freq2;
970 	if (!default_freq)
971 		default_freq = acs_cfg->freq_list[0];
972 
973 	sap_debug("default freq %d chosen from %d %d %d %d", default_freq,
974 		  freq0, freq1, freq2, acs_cfg->freq_list[0]);
975 
976 	return default_freq;
977 }
978 
979 static bool is_mcc_preferred(struct sap_context *sap_context,
980 			     uint32_t con_ch_freq)
981 {
982 	/*
983 	 * If SAP ACS channel list is 1-11 and STA is on non-preferred
984 	 * channel i.e. 12, 13, 14 then MCC is unavoidable. This is because
985 	 * if SAP is started on 12,13,14 some clients may not be able to
986 	 * join dependending on their regulatory country.
987 	 */
988 	if ((con_ch_freq >= 2467) && (con_ch_freq <= 2484) &&
989 	    (sap_context->acs_cfg->start_ch_freq >= 2412 &&
990 	     sap_context->acs_cfg->end_ch_freq <= 2462)) {
991 		sap_debug("conc ch freq %d & sap acs ch list is 1-11, prefer mcc",
992 			  con_ch_freq);
993 		return true;
994 	}
995 
996 	return false;
997 }
998 
999 /**
1000  * sap_process_force_scc_with_go_start() - Check GO force SCC or not
1001  * @psoc: psoc object
1002  * @sap_context: sap_context
1003  *
1004  * This function checks the current SAP MCC or not with the GO's home channel.
1005  * If it is, skip the GO's force SCC. The SAP will do force SCC after
1006  * GO's started.
1007  *
1008  * Return: true if skip GO's force SCC
1009  */
1010 static bool
1011 sap_process_force_scc_with_go_start(struct wlan_objmgr_psoc *psoc,
1012 				    struct sap_context *sap_context)
1013 {
1014 	uint8_t existing_vdev_id = WLAN_UMAC_VDEV_ID_MAX;
1015 	enum policy_mgr_con_mode existing_vdev_mode = PM_MAX_NUM_OF_MODE;
1016 	uint32_t con_freq;
1017 	enum phy_ch_width ch_width;
1018 
1019 	if (sap_context->cc_switch_mode ==
1020 			QDF_MCC_TO_SCC_SWITCH_WITH_FAVORITE_CHANNEL)
1021 		return false;
1022 
1023 	existing_vdev_id =
1024 		policy_mgr_fetch_existing_con_info(psoc,
1025 						   sap_context->sessionId,
1026 						   sap_context->chan_freq,
1027 						   &existing_vdev_mode,
1028 						   &con_freq, &ch_width);
1029 	if (existing_vdev_id < WLAN_UMAC_VDEV_ID_MAX &&
1030 	    existing_vdev_mode == PM_SAP_MODE) {
1031 		sap_debug("concurrent sap vdev: %d on freq %d, skip GO force scc",
1032 			  existing_vdev_id, con_freq);
1033 		return true;
1034 	}
1035 
1036 	return false;
1037 }
1038 
1039 #ifdef WLAN_FEATURE_P2P_P2P_STA
1040 /**
1041  * sap_set_forcescc_required() - set force scc flag for provided p2p go vdev
1042  *
1043  * @vdev_id: vdev_id for which flag needs to be set
1044  *
1045  * Return: None
1046  */
1047 static void sap_set_forcescc_required(uint8_t vdev_id)
1048 {
1049 	struct mac_context *mac_ctx;
1050 	struct sap_context *sap_ctx;
1051 	uint8_t i = 0;
1052 
1053 	mac_ctx = sap_get_mac_context();
1054 	if (!mac_ctx) {
1055 		sap_err("Invalid MAC context");
1056 		return;
1057 	}
1058 
1059 	for (i = 0; i < SAP_MAX_NUM_SESSION; i++) {
1060 		sap_ctx = mac_ctx->sap.sapCtxList[i].sap_context;
1061 		if (QDF_P2P_GO_MODE == mac_ctx->sap.sapCtxList[i].sapPersona &&
1062 		    sap_ctx->sessionId == vdev_id) {
1063 			sap_debug("update forcescc restart for vdev %d",
1064 				  vdev_id);
1065 			sap_ctx->is_forcescc_restart_required = true;
1066 		}
1067 	}
1068 }
1069 
1070 /**
1071  * sap_process_liberal_scc_for_go() - based on existing connections this
1072  * function decides current go should start on provided channel or not and
1073  * sets force scc required bit for existing GO.
1074  *
1075  * @sap_context: sap_context
1076  *
1077  * Return: bool
1078  */
1079 static bool sap_process_liberal_scc_for_go(struct sap_context *sap_context)
1080 {
1081 	uint8_t existing_vdev_id = WLAN_UMAC_VDEV_ID_MAX;
1082 	enum policy_mgr_con_mode existing_vdev_mode = PM_MAX_NUM_OF_MODE;
1083 	uint32_t con_freq;
1084 	enum phy_ch_width ch_width;
1085 	struct mac_context *mac_ctx;
1086 	mac_handle_t mac_handle;
1087 
1088 	mac_handle = cds_get_context(QDF_MODULE_ID_SME);
1089 	mac_ctx = MAC_CONTEXT(mac_handle);
1090 	if (!mac_ctx) {
1091 		sap_alert("invalid MAC handle");
1092 		return true;
1093 	}
1094 
1095 	existing_vdev_id =
1096 		policy_mgr_fetch_existing_con_info(
1097 				mac_ctx->psoc,
1098 				sap_context->sessionId,
1099 				sap_context->chan_freq,
1100 				&existing_vdev_mode,
1101 				&con_freq, &ch_width);
1102 
1103 	if (existing_vdev_id <
1104 			WLAN_UMAC_VDEV_ID_MAX &&
1105 			existing_vdev_mode == PM_P2P_GO_MODE) {
1106 		sap_debug("set forcescc flag for go vdev: %d",
1107 			  existing_vdev_id);
1108 		sap_set_forcescc_required(
1109 				existing_vdev_id);
1110 		return true;
1111 	}
1112 	if (existing_vdev_id < WLAN_UMAC_VDEV_ID_MAX &&
1113 	    (existing_vdev_mode == PM_STA_MODE ||
1114 	    existing_vdev_mode == PM_P2P_CLIENT_MODE)) {
1115 		sap_debug("don't override channel, start go on %d",
1116 			  sap_context->chan_freq);
1117 		return true;
1118 	}
1119 
1120 	return false;
1121 }
1122 #else
1123 static bool sap_process_liberal_scc_for_go(struct sap_context *sap_context)
1124 {
1125 	return false;
1126 }
1127 #endif
1128 
1129 QDF_STATUS
1130 sap_validate_chan(struct sap_context *sap_context,
1131 		  bool pre_start_bss,
1132 		  bool check_for_connection_update)
1133 {
1134 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
1135 	struct mac_context *mac_ctx;
1136 	mac_handle_t mac_handle;
1137 	uint32_t con_ch_freq;
1138 	bool sta_sap_scc_on_dfs_chan;
1139 	uint32_t sta_go_bit_mask = QDF_STA_MASK | QDF_P2P_GO_MASK;
1140 	uint32_t sta_sap_bit_mask = QDF_STA_MASK | QDF_SAP_MASK;
1141 	uint32_t concurrent_state;
1142 	bool go_force_scc;
1143 	struct ch_params ch_params = {0};
1144 	bool is_go_scc_strict = false;
1145 	bool start_sap_on_provided_freq = false;
1146 
1147 	mac_handle = cds_get_context(QDF_MODULE_ID_SME);
1148 	mac_ctx = MAC_CONTEXT(mac_handle);
1149 	if (!mac_ctx) {
1150 		/* we have a serious problem */
1151 		sap_alert("invalid MAC handle");
1152 		return QDF_STATUS_E_FAULT;
1153 	}
1154 
1155 	if (!sap_context->chan_freq) {
1156 		sap_err("Invalid channel");
1157 		return QDF_STATUS_E_FAILURE;
1158 	}
1159 
1160 	if (policy_mgr_is_vdev_ll_lt_sap(mac_ctx->psoc, sap_context->vdev_id)) {
1161 		sap_context->chan_freq = wlan_ll_lt_sap_override_freq(
1162 							mac_ctx->psoc,
1163 							sap_context->vdev_id,
1164 							sap_context->chan_freq);
1165 		return QDF_STATUS_SUCCESS;
1166 	}
1167 
1168 	if (sap_context->vdev &&
1169 	    sap_context->vdev->vdev_mlme.vdev_opmode == QDF_P2P_GO_MODE) {
1170 	       /*
1171 		* check whether go_force_scc is enabled or not.
1172 		* If it not enabled then don't any force scc on existing go and
1173 		* new p2p go vdevs.
1174 		* Otherwise, if it is enabled then check whether it's in strict
1175 		* mode or liberal mode.
1176 		* For strict mode, do force scc on newly p2p go to existing vdev
1177 		* channel.
1178 		* For liberal first form new p2p go on requested channel and
1179 		* follow below rules:
1180 		* a.) If Existing vdev mode is P2P GO Once set key is done, do
1181 		* force scc for existing p2p go and move that go to new p2p
1182 		* go's channel.
1183 		*
1184 		* b.) If Existing vdev mode is P2P CLI/STA Once set key is
1185 		* done, do force scc for p2p go and move go to cli/sta channel.
1186 		*/
1187 		go_force_scc = policy_mgr_go_scc_enforced(mac_ctx->psoc);
1188 		sap_debug("go force scc enabled %d", go_force_scc);
1189 
1190 		if (sap_process_force_scc_with_go_start(mac_ctx->psoc,
1191 							sap_context))
1192 			goto validation_done;
1193 
1194 		if (go_force_scc) {
1195 			is_go_scc_strict =
1196 				policy_mgr_is_go_scc_strict(mac_ctx->psoc);
1197 			if (!is_go_scc_strict) {
1198 				sap_debug("liberal mode is enabled");
1199 				start_sap_on_provided_freq =
1200 				sap_process_liberal_scc_for_go(sap_context);
1201 				if (start_sap_on_provided_freq)
1202 					goto validation_done;
1203 			}
1204 		} else {
1205 			goto validation_done;
1206 		}
1207 	}
1208 
1209 	concurrent_state = policy_mgr_get_concurrency_mode(mac_ctx->psoc);
1210 	if (policy_mgr_concurrent_beaconing_sessions_running(mac_ctx->psoc) ||
1211 	    ((concurrent_state & sta_sap_bit_mask) == sta_sap_bit_mask) ||
1212 	    ((concurrent_state & sta_go_bit_mask) == sta_go_bit_mask)) {
1213 #ifdef FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE
1214 		if (wlan_reg_is_dfs_for_freq(mac_ctx->pdev,
1215 					     sap_context->chan_freq)) {
1216 			sap_warn("DFS not supported in STA_AP Mode");
1217 			return QDF_STATUS_E_ABORTED;
1218 		}
1219 #endif
1220 #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
1221 		if (sap_context->cc_switch_mode !=
1222 					QDF_MCC_TO_SCC_SWITCH_DISABLE) {
1223 			con_ch_freq = sme_check_concurrent_channel_overlap(
1224 					mac_handle,
1225 					sap_context->chan_freq,
1226 					sap_context->phyMode,
1227 					sap_context->cc_switch_mode,
1228 					sap_context->sessionId);
1229 			sap_debug("After check overlap: sap freq %d con freq:%d",
1230 				  sap_context->chan_freq, con_ch_freq);
1231 			/*
1232 			 * For non-DBS platform, a 2.4Ghz can become a 5Ghz freq
1233 			 * so lets used max BW in that case, if it remain 2.4Ghz
1234 			 * then BW will be limited to 20 anyway
1235 			 */
1236 			if (WLAN_REG_IS_24GHZ_CH_FREQ(sap_context->chan_freq))
1237 				ch_params.ch_width = CH_WIDTH_MAX;
1238 			else
1239 				ch_params = sap_context->ch_params;
1240 
1241 			if (sap_context->cc_switch_mode !=
1242 		QDF_MCC_TO_SCC_SWITCH_FORCE_PREFERRED_WITHOUT_DISCONNECTION) {
1243 				if (QDF_IS_STATUS_ERROR(
1244 					policy_mgr_valid_sap_conc_channel_check(
1245 						mac_ctx->psoc, &con_ch_freq,
1246 						sap_context->chan_freq,
1247 						sap_context->sessionId,
1248 						&ch_params))) {
1249 					sap_warn("SAP can't start (no MCC)");
1250 					return QDF_STATUS_E_ABORTED;
1251 				}
1252 			}
1253 			/* if CH width didn't change fallback to original */
1254 			if (ch_params.ch_width == CH_WIDTH_MAX)
1255 				ch_params = sap_context->ch_params;
1256 
1257 			sap_debug("After check concurrency: con freq:%d",
1258 				  con_ch_freq);
1259 			sta_sap_scc_on_dfs_chan =
1260 				policy_mgr_is_sta_sap_scc_allowed_on_dfs_chan(
1261 						mac_ctx->psoc);
1262 			if (con_ch_freq &&
1263 			    (policy_mgr_sta_sap_scc_on_lte_coex_chan(
1264 						mac_ctx->psoc) ||
1265 			     policy_mgr_is_safe_channel(
1266 						mac_ctx->psoc, con_ch_freq)) &&
1267 			    (!wlan_mlme_check_chan_param_has_dfs(
1268 					mac_ctx->pdev, &ch_params,
1269 					con_ch_freq) ||
1270 			    sta_sap_scc_on_dfs_chan)) {
1271 				if (is_mcc_preferred(sap_context, con_ch_freq))
1272 					goto validation_done;
1273 
1274 				sap_debug("Override ch freq %d (bw %d) to %d (bw %d) due to CC Intf",
1275 					  sap_context->chan_freq,
1276 					  sap_context->ch_params.ch_width,
1277 					  con_ch_freq, ch_params.ch_width);
1278 				sap_context->chan_freq = con_ch_freq;
1279 				sap_context->ch_params = ch_params;
1280 			}
1281 		}
1282 #endif
1283 	}
1284 validation_done:
1285 	sap_debug("for configured channel, Ch_freq = %d",
1286 		  sap_context->chan_freq);
1287 
1288 	/*
1289 	 * Don't check if the frequency is allowed or not if SAP is started
1290 	 * in fixed channel, or WLAN CH AVOID EXT feature explicit restrict
1291 	 * SAP start on unsafe channel.
1292 	 */
1293 
1294 	if ((sap_context->acs_cfg->acs_mode ||
1295 	     policy_mgr_restrict_sap_on_unsafe_chan(mac_ctx->psoc)) &&
1296 	    !policy_mgr_is_sap_freq_allowed(mac_ctx->psoc,
1297 					    sap_context->chan_freq)) {
1298 		sap_warn("Abort SAP start due to unsafe channel");
1299 		return QDF_STATUS_E_ABORTED;
1300 	}
1301 
1302 	if (check_for_connection_update) {
1303 		/* This wait happens in the hostapd context. The event
1304 		 * is set in the MC thread context.
1305 		 */
1306 		qdf_status =
1307 		policy_mgr_update_and_wait_for_connection_update(
1308 			mac_ctx->psoc, sap_context->sessionId,
1309 			sap_context->chan_freq,
1310 			POLICY_MGR_UPDATE_REASON_START_AP);
1311 		if (QDF_IS_STATUS_ERROR(qdf_status))
1312 			return qdf_status;
1313 	}
1314 
1315 	if (pre_start_bss) {
1316 		sap_info("ACS end due to Ch override. Sel Ch freq = %d",
1317 			  sap_context->chan_freq);
1318 		sap_context->acs_cfg->pri_ch_freq = sap_context->chan_freq;
1319 		sap_context->acs_cfg->ch_width =
1320 					 sap_context->ch_width_orig;
1321 		sap_config_acs_result(mac_handle, sap_context, 0);
1322 		return QDF_STATUS_E_CANCELED;
1323 	}
1324 
1325 	return QDF_STATUS_SUCCESS;
1326 }
1327 
1328 #ifdef WLAN_FEATURE_SAP_ACS_OPTIMIZE
1329 
1330 static void sap_sort_freq_list(struct chan_list *list,
1331 			       uint8_t num_ch)
1332 {
1333 	int i, j, temp;
1334 
1335 	for (i = 0; i < num_ch - 1; i++) {
1336 		for (j = 0 ; j < num_ch - i - 1; j++) {
1337 			if (list->chan[j].freq < list->chan[j + 1].freq) {
1338 				temp = list->chan[j].freq;
1339 				list->chan[j].freq = list->chan[j + 1].freq;
1340 				list->chan[j + 1].freq = temp;
1341 			}
1342 		}
1343 	}
1344 }
1345 
1346 /**
1347  * sap_acs_scan_freq_list_optimize() - optimize the ACS scan freq list based
1348  * on when last scan was performed on particular frequency. If last scan
1349  * performed on particular frequency is less than configured last_scan_ageout
1350  * time, then skip that frequency from ACS scan freq list.
1351  *
1352  * @sap_ctx: sap context
1353  * @list: ACS scan frequency list
1354  * @ch_count: number of frequency in list
1355  *
1356  * Return: None
1357  */
1358 static void sap_acs_scan_freq_list_optimize(struct sap_context *sap_ctx,
1359 					    struct chan_list *list,
1360 					    uint8_t *ch_count)
1361 {
1362 	int loop_count = 0, j = 0;
1363 	uint32_t ts_last_scan;
1364 
1365 	sap_ctx->partial_acs_scan = false;
1366 
1367 	while (loop_count < *ch_count) {
1368 		ts_last_scan = scm_get_last_scan_time_per_channel(
1369 				sap_ctx->vdev, list->chan[loop_count].freq);
1370 
1371 		if (qdf_system_time_before(
1372 		    qdf_get_time_of_the_day_ms(),
1373 		    ts_last_scan + sap_ctx->acs_cfg->last_scan_ageout_time)) {
1374 			sap_info("ACS chan %d skipped from scan as last scan ts %lu\n",
1375 				 list->chan[loop_count].freq,
1376 				 qdf_get_time_of_the_day_ms() - ts_last_scan);
1377 
1378 			for (j = loop_count; j < *ch_count - 1; j++)
1379 				list->chan[j].freq = list->chan[j + 1].freq;
1380 
1381 			(*ch_count)--;
1382 			sap_ctx->partial_acs_scan = true;
1383 			continue;
1384 		}
1385 		loop_count++;
1386 	}
1387 	if (*ch_count == 0)
1388 		sap_info("All ACS freq channels are scanned recently, skip ACS scan\n");
1389 	else
1390 		sap_sort_freq_list(list, *ch_count);
1391 }
1392 #else
1393 static void sap_acs_scan_freq_list_optimize(struct sap_context *sap_ctx,
1394 					    struct chan_list *list,
1395 					    uint8_t *ch_count)
1396 {
1397 }
1398 #endif
1399 
1400 #ifdef WLAN_FEATURE_SAP_ACS_OPTIMIZE
1401 /**
1402  * sap_reset_clean_freq_array() - clear freq array that contains info
1403  * channel is free or not
1404  * @sap_context: sap context
1405  *
1406  * Return: void
1407  */
1408 static
1409 void sap_reset_clean_freq_array(struct sap_context *sap_context)
1410 {
1411 	memset(sap_context->clean_channel_array, 0, NUM_CHANNELS);
1412 }
1413 #else
1414 static inline
1415 void sap_reset_clean_freq_array(struct sap_context *sap_context)
1416 {}
1417 #endif
1418 
1419 /**
1420  * wlansap_set_aux_scan_ctrl_ext_flag() - update aux scan policy
1421  * @req: pointer to scan request
1422  *
1423  * Set aux scan bits in scan_ctrl_ext_flag value depending on scan type
1424  *
1425  * Return: None
1426  */
1427 static void wlansap_set_aux_scan_ctrl_ext_flag(struct scan_start_request *req)
1428 {
1429 	sap_debug("Set Reliable Scan Flag");
1430 	req->scan_req.scan_ctrl_flags_ext |=
1431 			SCAN_FLAG_EXT_AUX_RELIABLE_SCAN;
1432 }
1433 
1434 QDF_STATUS sap_channel_sel(struct sap_context *sap_context)
1435 {
1436 	QDF_STATUS qdf_ret_status;
1437 	struct mac_context *mac_ctx;
1438 	struct scan_start_request *req;
1439 	struct wlan_objmgr_vdev *vdev = NULL;
1440 	uint8_t i, j;
1441 	uint32_t *freq_list = NULL;
1442 	uint8_t num_of_channels = 0;
1443 	mac_handle_t mac_handle;
1444 	uint32_t con_ch_freq;
1445 	uint8_t vdev_id;
1446 	uint32_t scan_id;
1447 	uint32_t default_op_freq;
1448 
1449 	mac_handle = cds_get_context(QDF_MODULE_ID_SME);
1450 	if (!mac_handle)
1451 		return QDF_STATUS_E_FAULT;
1452 
1453 	mac_ctx = MAC_CONTEXT(mac_handle);
1454 	if (!mac_ctx) {
1455 		sap_err("Invalid MAC context");
1456 		return QDF_STATUS_E_FAILURE;
1457 	}
1458 	if (sap_context->fsm_state != SAP_STARTED && sap_context->chan_freq)
1459 		return sap_validate_chan(sap_context, true, false);
1460 
1461 	if (policy_mgr_concurrent_beaconing_sessions_running(mac_ctx->psoc) ||
1462 	    ((sap_context->cc_switch_mode ==
1463 	      QDF_MCC_TO_SCC_SWITCH_FORCE_PREFERRED_WITHOUT_DISCONNECTION) &&
1464 	     (policy_mgr_mode_specific_connection_count(mac_ctx->psoc,
1465 							PM_SAP_MODE, NULL) ||
1466 	     policy_mgr_mode_specific_connection_count(mac_ctx->psoc,
1467 						       PM_P2P_GO_MODE,
1468 						       NULL)))) {
1469 		con_ch_freq = sme_get_beaconing_concurrent_operation_channel(
1470 					mac_handle, sap_context->sessionId);
1471 #ifdef FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE
1472 		if (con_ch_freq)
1473 			sap_context->dfs_ch_disable = true;
1474 #endif
1475 	}
1476 
1477 	if ((policy_mgr_get_concurrency_mode(mac_ctx->psoc) ==
1478 		(QDF_STA_MASK | QDF_SAP_MASK)) ||
1479 		((sap_context->cc_switch_mode ==
1480 		QDF_MCC_TO_SCC_SWITCH_FORCE_PREFERRED_WITHOUT_DISCONNECTION) &&
1481 		(policy_mgr_get_concurrency_mode(mac_ctx->psoc) ==
1482 		(QDF_STA_MASK | QDF_P2P_GO_MASK)))) {
1483 #ifdef FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE
1484 		sap_context->dfs_ch_disable = true;
1485 #endif
1486 	}
1487 #ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
1488 	sap_debug("skip_acs_status = %d",
1489 		  sap_context->acs_cfg->skip_scan_status);
1490 	if (sap_context->acs_cfg->skip_scan_status !=
1491 					eSAP_SKIP_ACS_SCAN) {
1492 #endif
1493 
1494 		if (sap_context->freq_list) {
1495 			qdf_mem_free(sap_context->freq_list);
1496 			sap_context->freq_list = NULL;
1497 			sap_context->num_of_channel = 0;
1498 		}
1499 
1500 		sap_get_freq_list(sap_context, &freq_list, &num_of_channels);
1501 		if (!num_of_channels || !freq_list) {
1502 			sap_err("No freq sutiable for SAP in current list, SAP failed");
1503 			return QDF_STATUS_E_FAILURE;
1504 		}
1505 
1506 		req = qdf_mem_malloc(sizeof(*req));
1507 		if (!req) {
1508 			qdf_mem_free(freq_list);
1509 			return QDF_STATUS_E_NOMEM;
1510 		}
1511 
1512 		vdev_id = sap_context->sessionId;
1513 		vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc,
1514 							    vdev_id,
1515 							    WLAN_LEGACY_SME_ID);
1516 		if (!vdev) {
1517 			sap_err("Invalid vdev objmgr");
1518 			qdf_mem_free(freq_list);
1519 			qdf_mem_free(req);
1520 			return QDF_STATUS_E_INVAL;
1521 		}
1522 
1523 		/* Initiate a SCAN request */
1524 		wlan_scan_init_default_params(vdev, req);
1525 		scan_id = wlan_scan_get_scan_id(mac_ctx->psoc);
1526 		req->scan_req.scan_id = scan_id;
1527 		req->scan_req.vdev_id = vdev_id;
1528 		req->scan_req.scan_f_passive = false;
1529 		req->scan_req.scan_req_id = sap_context->req_id;
1530 		req->scan_req.scan_priority = SCAN_PRIORITY_HIGH;
1531 		req->scan_req.scan_f_bcast_probe = true;
1532 		for (i = 0, j = 0; i < num_of_channels; i++) {
1533 			if (wlan_reg_is_6ghz_chan_freq(freq_list[i]) &&
1534 			    !wlan_reg_is_6ghz_psc_chan_freq(freq_list[i]))
1535 				continue;
1536 			req->scan_req.chan_list.chan[j++].freq = freq_list[i];
1537 		}
1538 		req->scan_req.chan_list.num_chan = j;
1539 		sap_context->freq_list = freq_list;
1540 		sap_context->num_of_channel = num_of_channels;
1541 		sap_context->optimize_acs_chan_selected = false;
1542 		sap_reset_clean_freq_array(sap_context);
1543 		/* Set requestType to Full scan */
1544 
1545 		/*
1546 		 * send partial channels to be scanned in SCAN request if
1547 		 * vendor command included last scan ageout time to be used to
1548 		 * optimize the SAP bring up time
1549 		 */
1550 		if (sap_context->acs_cfg->last_scan_ageout_time)
1551 			sap_acs_scan_freq_list_optimize(
1552 					sap_context, &req->scan_req.chan_list,
1553 					&req->scan_req.chan_list.num_chan);
1554 
1555 		if (!req->scan_req.chan_list.num_chan) {
1556 			sap_info("## SKIPPED ACS SCAN");
1557 			sap_context->acs_cfg->skip_acs_scan = true;
1558 			wlansap_pre_start_bss_acs_scan_callback(
1559 				mac_handle, sap_context, sap_context->sessionId,
1560 				0, eCSR_SCAN_SUCCESS);
1561 			qdf_mem_free(req);
1562 			qdf_ret_status = QDF_STATUS_SUCCESS;
1563 			goto release_vdev_ref;
1564 		}
1565 
1566 		sap_context->acs_req_timestamp = qdf_get_time_of_the_day_ms();
1567 
1568 		if (wlan_scan_get_aux_support(mac_ctx->psoc))
1569 			wlansap_set_aux_scan_ctrl_ext_flag(req);
1570 		qdf_ret_status = wlan_scan_start(req);
1571 		if (qdf_ret_status != QDF_STATUS_SUCCESS) {
1572 			sap_err("scan request  fail %d!!!", qdf_ret_status);
1573 			sap_info("SAP Configuring default ch, Ch_freq=%d",
1574 				  sap_context->chan_freq);
1575 			default_op_freq = sap_select_default_oper_chan(
1576 						mac_ctx, sap_context->acs_cfg);
1577 			wlansap_set_acs_ch_freq(sap_context, default_op_freq);
1578 
1579 			if (sap_context->freq_list) {
1580 				wlansap_set_acs_ch_freq(
1581 					sap_context, sap_context->freq_list[0]);
1582 				qdf_mem_free(sap_context->freq_list);
1583 				sap_context->freq_list = NULL;
1584 				sap_context->num_of_channel = 0;
1585 			}
1586 			/*
1587 			* In case of ACS req before start Bss,
1588 			* return failure so that the calling
1589 			* function can use the default channel.
1590 			*/
1591 			qdf_ret_status = QDF_STATUS_E_FAILURE;
1592 			goto release_vdev_ref;
1593 		} else {
1594 			wlansap_dump_acs_ch_freq(sap_context);
1595 			host_log_acs_scan_start(scan_id, vdev_id);
1596 		}
1597 
1598 #ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
1599 	} else {
1600 		sap_context->acs_cfg->skip_scan_status = eSAP_SKIP_ACS_SCAN;
1601 	}
1602 
1603 	if (sap_context->acs_cfg->skip_scan_status == eSAP_SKIP_ACS_SCAN) {
1604 		sap_err("## SKIPPED ACS SCAN");
1605 		wlansap_pre_start_bss_acs_scan_callback(mac_handle,
1606 				sap_context, sap_context->sessionId, 0,
1607 				eCSR_SCAN_SUCCESS);
1608 	}
1609 #endif
1610 
1611 	wlansap_dump_acs_ch_freq(sap_context);
1612 
1613 	qdf_ret_status = QDF_STATUS_SUCCESS;
1614 
1615 release_vdev_ref:
1616 	if (vdev)
1617 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
1618 	return qdf_ret_status;
1619 }
1620 
1621 /**
1622  * sap_find_valid_concurrent_session() - to find valid concurrent session
1623  * @mac_handle: Opaque handle to the global MAC context
1624  *
1625  * This API will check if any valid concurrent SAP session is present
1626  *
1627  * Return: pointer to sap context of valid concurrent session
1628  */
1629 static struct sap_context *
1630 sap_find_valid_concurrent_session(mac_handle_t mac_handle)
1631 {
1632 	struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
1633 	uint8_t intf = 0;
1634 	struct sap_context *sap_ctx;
1635 
1636 	for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) {
1637 		if (((QDF_SAP_MODE ==
1638 				mac_ctx->sap.sapCtxList[intf].sapPersona) ||
1639 		     (QDF_P2P_GO_MODE ==
1640 				mac_ctx->sap.sapCtxList[intf].sapPersona)) &&
1641 		    mac_ctx->sap.sapCtxList[intf].sap_context) {
1642 			sap_ctx = mac_ctx->sap.sapCtxList[intf].sap_context;
1643 			if (sap_ctx->fsm_state != SAP_INIT)
1644 				return sap_ctx;
1645 		}
1646 	}
1647 
1648 	return NULL;
1649 }
1650 
1651 QDF_STATUS sap_clear_global_dfs_param(mac_handle_t mac_handle,
1652 				      struct sap_context *sap_ctx)
1653 {
1654 	struct sap_context *con_sap_ctx;
1655 
1656 	con_sap_ctx = sap_find_valid_concurrent_session(mac_handle);
1657 	if (con_sap_ctx && WLAN_REG_IS_5GHZ_CH_FREQ(con_sap_ctx->chan_freq)) {
1658 		sap_debug("conc session exists, no need to clear dfs struct");
1659 		return QDF_STATUS_SUCCESS;
1660 	}
1661 	/*
1662 	 * CAC timer will be initiated and started only when SAP starts
1663 	 * on DFS channel and it will be stopped and destroyed
1664 	 * immediately once the radar detected or timedout. So
1665 	 * as per design CAC timer should be destroyed after stop
1666 	 */
1667 	wlansap_cleanup_cac_timer(sap_ctx);
1668 	sap_cac_reset_notify(mac_handle);
1669 
1670 	return QDF_STATUS_SUCCESS;
1671 }
1672 
1673 QDF_STATUS sap_acquire_vdev_ref(struct wlan_objmgr_psoc *psoc,
1674 				struct sap_context *sap_ctx,
1675 				uint8_t session_id)
1676 {
1677 	struct wlan_objmgr_vdev *vdev;
1678 
1679 	if (sap_ctx->vdev) {
1680 		sap_err("Invalid vdev obj in sap context");
1681 		return QDF_STATUS_E_FAULT;
1682 	}
1683 
1684 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, session_id,
1685 						    WLAN_LEGACY_SAP_ID);
1686 	if (!vdev) {
1687 		sap_err("vdev is NULL for vdev_id: %u", session_id);
1688 		return QDF_STATUS_E_FAILURE;
1689 	}
1690 
1691 	sap_ctx->vdev = vdev;
1692 	return QDF_STATUS_SUCCESS;
1693 }
1694 
1695 void sap_release_vdev_ref(struct sap_context *sap_ctx)
1696 {
1697 	struct wlan_objmgr_vdev *vdev;
1698 
1699 	if (!sap_ctx) {
1700 		sap_debug("Invalid SAP pointer");
1701 		return;
1702 	}
1703 
1704 	vdev = sap_ctx->vdev;
1705 	if (vdev) {
1706 		sap_ctx->vdev = NULL;
1707 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SAP_ID);
1708 	}
1709 }
1710 
1711 QDF_STATUS sap_set_session_param(mac_handle_t mac_handle,
1712 				 struct sap_context *sapctx,
1713 				 uint32_t session_id)
1714 {
1715 	struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
1716 	int i;
1717 
1718 	sapctx->sessionId = session_id;
1719 	wlan_pre_cac_set_status(sapctx->vdev, false);
1720 	wlan_pre_cac_complete_set(sapctx->vdev, false);
1721 	wlan_pre_cac_set_freq_before_pre_cac(sapctx->vdev, 0);
1722 
1723 	/* When SSR, SAP will restart, clear the old context,sessionId */
1724 	for (i = 0; i < SAP_MAX_NUM_SESSION; i++) {
1725 		if (mac_ctx->sap.sapCtxList[i].sap_context == sapctx)
1726 			mac_ctx->sap.sapCtxList[i].sap_context = NULL;
1727 	}
1728 
1729 	mac_ctx->sap.sapCtxList[sapctx->sessionId].sap_context = sapctx;
1730 	mac_ctx->sap.sapCtxList[sapctx->sessionId].sapPersona =
1731 			wlan_get_opmode_from_vdev_id(mac_ctx->pdev, session_id);
1732 	sap_debug("Initializing sap_ctx = %pK with session = %d",
1733 		   sapctx, session_id);
1734 
1735 	return QDF_STATUS_SUCCESS;
1736 }
1737 
1738 QDF_STATUS sap_clear_session_param(mac_handle_t mac_handle,
1739 				   struct sap_context *sapctx,
1740 				   uint32_t session_id)
1741 {
1742 	struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
1743 
1744 	if (sapctx->sessionId >= SAP_MAX_NUM_SESSION)
1745 		return QDF_STATUS_E_FAILURE;
1746 
1747 	mac_ctx->sap.sapCtxList[sapctx->sessionId].sap_context = NULL;
1748 	mac_ctx->sap.sapCtxList[sapctx->sessionId].sapPersona =
1749 		QDF_MAX_NO_OF_MODE;
1750 	sap_clear_global_dfs_param(mac_handle, sapctx);
1751 
1752 	sap_err("Set sapCtxList null for session %d", sapctx->sessionId);
1753 	qdf_mem_zero(sapctx, sizeof(*sapctx));
1754 	sapctx->sessionId = WLAN_UMAC_VDEV_ID_MAX;
1755 
1756 	return QDF_STATUS_SUCCESS;
1757 }
1758 
1759 #ifdef WLAN_FEATURE_11AX
1760 static uint16_t he_mcs_12_13_support(void)
1761 {
1762 	struct mac_context *mac_ctx;
1763 
1764 	mac_ctx = sap_get_mac_context();
1765 	if (!mac_ctx) {
1766 		sap_err("Invalid MAC context");
1767 		return 0;
1768 	}
1769 
1770 	return mac_ctx->mlme_cfg->he_caps.he_mcs_12_13_supp_5g;
1771 }
1772 #else
1773 static inline uint16_t he_mcs_12_13_support(void)
1774 {
1775 	return 0;
1776 }
1777 #endif
1778 
1779 static bool is_mcs13_ch_width(enum phy_ch_width ch_width)
1780 {
1781 	if ((ch_width == CH_WIDTH_320MHZ) ||
1782 	    (ch_width == CH_WIDTH_160MHZ) ||
1783 	    (ch_width == CH_WIDTH_80P80MHZ))
1784 		return true;
1785 
1786 	return false;
1787 }
1788 
1789 /**
1790  * sap_update_mcs_rate() - Update SAP MCS rate
1791  * @sap_ctx: pointer to sap Context
1792  * @is_start: Start or stop SAP
1793  *
1794  * Return: QDF_STATUS
1795  */
1796 static QDF_STATUS
1797 sap_update_mcs_rate(struct sap_context *sap_ctx, bool is_start)
1798 {
1799 	uint32_t default_mcs[] = {26, 0x3fff};
1800 	uint32_t fixed_mcs[] = {26, 0x1fff};
1801 	bool disable_mcs13_support = false;
1802 	uint16_t he_mcs_12_13_supp;
1803 	struct mac_context *mac_ctx;
1804 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1805 
1806 	mac_ctx = sap_get_mac_context();
1807 	if (!mac_ctx) {
1808 		sap_err("Invalid MAC context");
1809 		return QDF_STATUS_E_INVAL;
1810 	}
1811 
1812 	he_mcs_12_13_supp = he_mcs_12_13_support();
1813 	disable_mcs13_support = cfg_get(mac_ctx->psoc,
1814 					CFG_DISABLE_MCS13_SUPPORT);
1815 	sap_debug("session id %d, disable mcs13 support %d, he_mcs_12_13 %d, start %d, disabled_mcs13 %d, ch width %d",
1816 		  sap_ctx->sessionId, disable_mcs13_support,
1817 		  he_mcs_12_13_supp,
1818 		  is_start, sap_ctx->disabled_mcs13,
1819 		  sap_ctx->ch_params.ch_width);
1820 
1821 	if (!disable_mcs13_support ||
1822 	    !he_mcs_12_13_supp)
1823 		return status;
1824 
1825 	if (!is_start && !sap_ctx->disabled_mcs13)
1826 		return status;
1827 
1828 	if (!is_mcs13_ch_width(sap_ctx->ch_params.ch_width))
1829 		return status;
1830 
1831 	if (is_start) {
1832 		status = sme_send_unit_test_cmd(sap_ctx->sessionId,
1833 						10, 2, fixed_mcs);
1834 		if (QDF_IS_STATUS_ERROR(status)) {
1835 			sap_err("Set fixed mcs rate failed, session %d",
1836 				sap_ctx->sessionId);
1837 		} else {
1838 			sap_ctx->disabled_mcs13 = true;
1839 		}
1840 	} else {
1841 		status = sme_send_unit_test_cmd(sap_ctx->sessionId,
1842 						10, 2, default_mcs);
1843 		if (QDF_IS_STATUS_ERROR(status)) {
1844 			sap_err("Set default mcs rate failed, session %d",
1845 				sap_ctx->sessionId);
1846 		} else {
1847 			sap_ctx->disabled_mcs13 = false;
1848 		}
1849 	}
1850 
1851 	return status;
1852 }
1853 
1854 /**
1855  * sap_goto_stopping() - Processing of SAP FSM stopping state
1856  * @sap_ctx: pointer to sap Context
1857  *
1858  * Return: QDF_STATUS code associated with performing the operation
1859  */
1860 static QDF_STATUS sap_goto_stopping(struct sap_context *sap_ctx)
1861 {
1862 	QDF_STATUS status;
1863 	struct mac_context *mac_ctx;
1864 
1865 	mac_ctx = sap_get_mac_context();
1866 	if (!mac_ctx) {
1867 		/* we have a serious problem */
1868 		sap_err("Invalid MAC context");
1869 		return QDF_STATUS_E_FAULT;
1870 	}
1871 
1872 	sap_update_mcs_rate(sap_ctx, false);
1873 	qdf_mem_zero(&sap_ctx->sap_bss_cfg, sizeof(sap_ctx->sap_bss_cfg));
1874 
1875 	status = sme_roam_stop_bss(MAC_HANDLE(mac_ctx), sap_ctx->sessionId);
1876 	if (status != QDF_STATUS_SUCCESS) {
1877 		sap_err("Calling sme_roam_stop_bss status = %d", status);
1878 		return QDF_STATUS_E_FAILURE;
1879 	}
1880 
1881 	return QDF_STATUS_SUCCESS;
1882 }
1883 
1884 /**
1885  * sap_goto_init() - Function for setting the SAP FSM to init state
1886  * @sap_ctx: pointer to sap context
1887  *
1888  * Return: QDF_STATUS code associated with performing the operation
1889  */
1890 static QDF_STATUS sap_goto_init(struct sap_context *sap_ctx)
1891 {
1892 	QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
1893 	struct sap_sm_event sap_event;
1894 	/* Processing has to be coded */
1895 
1896 	/*
1897 	 * Clean up stations from TL etc as AP BSS is shut down
1898 	 * then set event
1899 	 */
1900 
1901 	/* hardcoded event */
1902 	sap_event.event = eSAP_MAC_READY_FOR_CONNECTIONS;
1903 	sap_event.params = 0;
1904 	sap_event.u1 = 0;
1905 	sap_event.u2 = 0;
1906 	/* Handle event */
1907 	qdf_status = sap_fsm(sap_ctx, &sap_event);
1908 
1909 	return qdf_status;
1910 }
1911 
1912 #ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
1913 /**
1914  * sap_handle_acs_scan_event() - handle acs scan event for SAP
1915  * @sap_context: ptSapContext
1916  * @sap_event: struct sap_event
1917  * @status: status of acs scan
1918  *
1919  * The function is to handle the eSAP_ACS_SCAN_SUCCESS_EVENT event.
1920  *
1921  * Return: void
1922  */
1923 static void sap_handle_acs_scan_event(struct sap_context *sap_context,
1924 		struct sap_event *sap_event, eSapStatus status)
1925 {
1926 	sap_event->sapHddEventCode = eSAP_ACS_SCAN_SUCCESS_EVENT;
1927 	sap_event->sapevt.sap_acs_scan_comp.status = status;
1928 	sap_event->sapevt.sap_acs_scan_comp.num_of_channels =
1929 			sap_context->num_of_channel;
1930 	sap_event->sapevt.sap_acs_scan_comp.freq_list =
1931 			sap_context->freq_list;
1932 }
1933 #else
1934 static void sap_handle_acs_scan_event(struct sap_context *sap_context,
1935 		struct sap_event *sap_event, eSapStatus status)
1936 {
1937 }
1938 #endif
1939 
1940 #define DH_OUI_TYPE      "\x20"
1941 #define DH_OUI_TYPE_SIZE (1)
1942 /**
1943  * sap_fill_owe_ie_in_assoc_ind() - Fill OWE IE in assoc indication
1944  * Function to fill OWE IE in assoc indication
1945  * @assoc_ind: SAP STA association indication
1946  * @sme_assoc_ind: SME association indication
1947  * @reassoc: True if it is reassoc frame
1948  *
1949  * This function is to get OWE IEs (RSN IE, DH IE etc) from assoc request
1950  * and fill them in association indication.
1951  *
1952  * Return: true for success and false for failure
1953  */
1954 static bool sap_fill_owe_ie_in_assoc_ind(tSap_StationAssocIndication *assoc_ind,
1955 					 struct assoc_ind *sme_assoc_ind,
1956 					 bool reassoc)
1957 {
1958 	uint32_t owe_ie_len, rsn_ie_len, dh_ie_len;
1959 	const uint8_t *rsn_ie, *dh_ie;
1960 	uint8_t *assoc_req_ie;
1961 	uint16_t assoc_req_ie_len;
1962 
1963 	if (reassoc) {
1964 		if (assoc_ind->assocReqLength < WLAN_REASSOC_REQ_IES_OFFSET) {
1965 			sap_err("Invalid reassoc req");
1966 			return false;
1967 		}
1968 
1969 		assoc_req_ie = assoc_ind->assocReqPtr +
1970 			       WLAN_REASSOC_REQ_IES_OFFSET;
1971 		assoc_req_ie_len = assoc_ind->assocReqLength -
1972 				   WLAN_REASSOC_REQ_IES_OFFSET;
1973 	} else {
1974 		if (assoc_ind->assocReqLength < WLAN_ASSOC_REQ_IES_OFFSET) {
1975 			sap_err("Invalid assoc req");
1976 			return false;
1977 		}
1978 
1979 		assoc_req_ie = assoc_ind->assocReqPtr +
1980 			       WLAN_ASSOC_REQ_IES_OFFSET;
1981 		assoc_req_ie_len = assoc_ind->assocReqLength -
1982 				   WLAN_ASSOC_REQ_IES_OFFSET;
1983 	}
1984 	rsn_ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_RSN,
1985 					  assoc_req_ie, assoc_req_ie_len);
1986 	if (!rsn_ie) {
1987 		sap_err("RSN IE is not present");
1988 		return false;
1989 	}
1990 	rsn_ie_len = rsn_ie[1] + 2;
1991 	if (rsn_ie_len < DOT11F_IE_RSN_MIN_LEN ||
1992 	    rsn_ie_len > DOT11F_IE_RSN_MAX_LEN) {
1993 		sap_err("Invalid RSN IE len %d", rsn_ie_len);
1994 		return false;
1995 	}
1996 
1997 	dh_ie = wlan_get_ext_ie_ptr_from_ext_id(DH_OUI_TYPE, DH_OUI_TYPE_SIZE,
1998 						assoc_req_ie, assoc_req_ie_len);
1999 	if (!dh_ie) {
2000 		sap_err("DH IE is not present");
2001 		return false;
2002 	}
2003 	dh_ie_len = dh_ie[1] + 2;
2004 	if (dh_ie_len < DOT11F_IE_DH_PARAMETER_ELEMENT_MIN_LEN ||
2005 	    dh_ie_len > DOT11F_IE_DH_PARAMETER_ELEMENT_MAX_LEN) {
2006 		sap_err("Invalid DH IE len %d", dh_ie_len);
2007 		return false;
2008 	}
2009 
2010 	sap_debug("rsn_ie_len = %d, dh_ie_len = %d", rsn_ie_len, dh_ie_len);
2011 
2012 	owe_ie_len = rsn_ie_len + dh_ie_len;
2013 	assoc_ind->owe_ie = qdf_mem_malloc(owe_ie_len);
2014 	if (!assoc_ind->owe_ie)
2015 		return false;
2016 
2017 	qdf_mem_copy(assoc_ind->owe_ie, rsn_ie, rsn_ie_len);
2018 	qdf_mem_copy(assoc_ind->owe_ie + rsn_ie_len, dh_ie, dh_ie_len);
2019 	assoc_ind->owe_ie_len = owe_ie_len;
2020 
2021 	return true;
2022 }
2023 
2024 /**
2025  * sap_save_owe_pending_assoc_ind() - Save pending assoc indication
2026  * Function to save pending assoc indication in SAP context
2027  * @sap_ctx: SAP context
2028  * @sme_assoc_ind: SME association indication
2029  *
2030  * This function is to save pending assoc indication in linked list
2031  * in SAP context.
2032  *
2033  * Return: true for success and false for failure
2034  */
2035 static bool sap_save_owe_pending_assoc_ind(struct sap_context *sap_ctx,
2036 				       struct assoc_ind *sme_assoc_ind)
2037 {
2038 	struct owe_assoc_ind *assoc_ind;
2039 	QDF_STATUS status;
2040 
2041 	assoc_ind = qdf_mem_malloc(sizeof(*assoc_ind));
2042 	if (!assoc_ind)
2043 		return false;
2044 	assoc_ind->assoc_ind = sme_assoc_ind;
2045 	status = qdf_list_insert_back(&sap_ctx->owe_pending_assoc_ind_list,
2046 				      &assoc_ind->node);
2047 	if (QDF_STATUS_SUCCESS != status) {
2048 		qdf_mem_free(assoc_ind);
2049 		return false;
2050 	}
2051 
2052 	return true;
2053 }
2054 
2055 static bool sap_save_ft_pending_assoc_ind(struct sap_context *sap_ctx,
2056 					  struct assoc_ind *sme_assoc_ind)
2057 {
2058 	struct ft_assoc_ind *assoc_ind;
2059 	QDF_STATUS status;
2060 
2061 	assoc_ind = qdf_mem_malloc(sizeof(*assoc_ind));
2062 	if (!assoc_ind)
2063 		return false;
2064 	assoc_ind->assoc_ind = sme_assoc_ind;
2065 	status = qdf_list_insert_back(&sap_ctx->ft_pending_assoc_ind_list,
2066 				      &assoc_ind->node);
2067 	if (QDF_STATUS_SUCCESS != status) {
2068 		qdf_mem_free(assoc_ind);
2069 		return false;
2070 	}
2071 	qdf_event_set(&sap_ctx->ft_pending_event);
2072 
2073 	return true;
2074 }
2075 
2076 #ifdef FEATURE_RADAR_HISTORY
2077 /* Last cac result */
2078 static struct prev_cac_result prev_cac_history;
2079 
2080 /**
2081  * sap_update_cac_history() - record SAP Radar found result in last
2082  * "active" or CAC period
2083  * @mac_ctx: mac context
2084  * @sap_ctx: sap context
2085  * @event_id: sap event
2086  *
2087  *  The function is to save the dfs channel information
2088  *  If SAP has been "active" or "CAC" on DFS channel for 60s and
2089  *  no found radar event.
2090  *
2091  * Return: void
2092  */
2093 static void
2094 sap_update_cac_history(struct mac_context *mac_ctx,
2095 		       struct sap_context *sap_ctx,
2096 		       eSapHddEvent event_id)
2097 {
2098 	struct prev_cac_result *cac_result = &sap_ctx->cac_result;
2099 
2100 	switch (event_id) {
2101 	case eSAP_START_BSS_EVENT:
2102 	case eSAP_CHANNEL_CHANGE_RESP:
2103 	case eSAP_DFS_CAC_START:
2104 		if (sap_operating_on_dfs(mac_ctx, sap_ctx)) {
2105 			qdf_mem_zero(cac_result,
2106 				     sizeof(struct prev_cac_result));
2107 			if (!sap_ctx->ch_params.mhz_freq_seg0) {
2108 				sap_debug("invalid seq0");
2109 				return;
2110 			}
2111 			cac_result->ap_start_time =
2112 				qdf_get_monotonic_boottime();
2113 			cac_result->cac_ch_param = sap_ctx->ch_params;
2114 			sap_debug("ap start(CAC) (%d, %d) bw %d",
2115 				  cac_result->cac_ch_param.mhz_freq_seg0,
2116 				  cac_result->cac_ch_param.mhz_freq_seg1,
2117 				  cac_result->cac_ch_param.ch_width);
2118 		}
2119 		break;
2120 	case eSAP_DFS_RADAR_DETECT:
2121 		qdf_mem_zero(cac_result,
2122 			     sizeof(struct prev_cac_result));
2123 		break;
2124 	case eSAP_DFS_CAC_END:
2125 	case eSAP_STOP_BSS_EVENT:
2126 		if (cac_result->ap_start_time) {
2127 			uint64_t diff_ms;
2128 
2129 			cac_result->ap_end_time =
2130 				qdf_get_monotonic_boottime();
2131 			diff_ms = qdf_do_div(cac_result->ap_end_time -
2132 				     cac_result->ap_start_time, 1000);
2133 			if (diff_ms < DEFAULT_CAC_TIMEOUT - 5000) {
2134 				if (event_id == eSAP_STOP_BSS_EVENT)
2135 					qdf_mem_zero(
2136 					cac_result,
2137 					sizeof(struct prev_cac_result));
2138 				sap_debug("ap cac dur %llu ms", diff_ms);
2139 				break;
2140 			}
2141 			cac_result->cac_complete = true;
2142 			qdf_mem_copy(&prev_cac_history, cac_result,
2143 				     sizeof(struct prev_cac_result));
2144 			sap_debug("ap cac saved %llu ms %llu (%d, %d) bw %d",
2145 				  diff_ms,
2146 				  cac_result->ap_end_time,
2147 				  cac_result->cac_ch_param.mhz_freq_seg0,
2148 				  cac_result->cac_ch_param.mhz_freq_seg1,
2149 				  cac_result->cac_ch_param.ch_width);
2150 			if (event_id == eSAP_STOP_BSS_EVENT)
2151 				qdf_mem_zero(cac_result,
2152 					     sizeof(struct prev_cac_result));
2153 		}
2154 		break;
2155 	default:
2156 		break;
2157 	}
2158 }
2159 
2160 /**
2161  * find_ch_freq_in_radar_hist() - check channel frequency existing
2162  * in radar history buffer
2163  * @radar_result: radar history buffer
2164  * @count: radar history element number
2165  * @ch_freq: channel frequency
2166  *
2167  * Return: bool
2168  */
2169 static
2170 bool find_ch_freq_in_radar_hist(struct dfs_radar_history *radar_result,
2171 				uint32_t count, uint16_t ch_freq)
2172 {
2173 	while (count) {
2174 		if (radar_result->ch_freq == ch_freq)
2175 			return true;
2176 		radar_result++;
2177 		count--;
2178 	}
2179 
2180 	return false;
2181 }
2182 
2183 /**
2184  * sap_append_cac_history() - Add CAC history to list
2185  * @mac_ctx: pointer to mac context
2186  * @radar_result: radar history buffer
2187  * @idx: current radar history element number
2188  * @max_elems: max elements number of radar history buffer.
2189  *
2190  * This function is to add the CAC history to radar history list.
2191  *
2192  * Return: void
2193  */
2194 static
2195 void sap_append_cac_history(struct mac_context *mac_ctx,
2196 			    struct dfs_radar_history *radar_result,
2197 			    uint32_t *idx, uint32_t max_elems)
2198 {
2199 	struct prev_cac_result *cac_result = &prev_cac_history;
2200 	struct ch_params ch_param = cac_result->cac_ch_param;
2201 	uint32_t count = *idx;
2202 
2203 	if (!cac_result->cac_complete || !cac_result->ap_end_time) {
2204 		sap_debug("cac hist empty");
2205 		return;
2206 	}
2207 
2208 	if (ch_param.ch_width <= CH_WIDTH_20MHZ) {
2209 		if (wlan_reg_is_dfs_for_freq(mac_ctx->pdev,
2210 					     ch_param.mhz_freq_seg0) &&
2211 		    !find_ch_freq_in_radar_hist(radar_result, count,
2212 						ch_param.mhz_freq_seg0) &&
2213 		    *idx < max_elems) {
2214 			radar_result[*idx].ch_freq = ch_param.mhz_freq_seg0;
2215 			radar_result[*idx].time = cac_result->ap_end_time;
2216 			radar_result[*idx].radar_found = false;
2217 			sap_debug("radar hist[%d] freq %d time %llu no radar",
2218 				  *idx, ch_param.mhz_freq_seg0,
2219 				  cac_result->ap_end_time);
2220 			(*idx)++;
2221 		}
2222 	} else {
2223 		uint16_t chan_cfreq;
2224 		enum channel_state state;
2225 		const struct bonded_channel_freq *bonded_chan_ptr = NULL;
2226 
2227 		state = wlan_reg_get_5g_bonded_channel_and_state_for_pwrmode
2228 			(mac_ctx->pdev, ch_param.mhz_freq_seg0,
2229 			 ch_param.ch_width, &bonded_chan_ptr,
2230 			 REG_CURRENT_PWR_MODE, NO_SCHANS_PUNC);
2231 		if (!bonded_chan_ptr || state == CHANNEL_STATE_INVALID) {
2232 			sap_debug("invalid freq %d", ch_param.mhz_freq_seg0);
2233 			return;
2234 		}
2235 
2236 		chan_cfreq = bonded_chan_ptr->start_freq;
2237 		while (chan_cfreq <= bonded_chan_ptr->end_freq) {
2238 			state = wlan_reg_get_channel_state_for_pwrmode(
2239 					mac_ctx->pdev, chan_cfreq,
2240 					REG_CURRENT_PWR_MODE);
2241 			if (state == CHANNEL_STATE_INVALID) {
2242 				sap_debug("invalid ch freq %d",
2243 					  chan_cfreq);
2244 				chan_cfreq = chan_cfreq + 20;
2245 				continue;
2246 			}
2247 			if (wlan_reg_is_dfs_for_freq(mac_ctx->pdev,
2248 						     chan_cfreq) &&
2249 			    !find_ch_freq_in_radar_hist(radar_result, count,
2250 							chan_cfreq) &&
2251 			    *idx < max_elems) {
2252 				radar_result[*idx].ch_freq = chan_cfreq;
2253 				radar_result[*idx].time =
2254 						cac_result->ap_end_time;
2255 				radar_result[*idx].radar_found = false;
2256 				sap_debug("radar hist[%d] freq %d time %llu no radar",
2257 					  *idx, chan_cfreq,
2258 					  cac_result->ap_end_time);
2259 				(*idx)++;
2260 			}
2261 			chan_cfreq = chan_cfreq + 20;
2262 		}
2263 	}
2264 }
2265 
2266 QDF_STATUS
2267 wlansap_query_radar_history(mac_handle_t mac_handle,
2268 			    struct dfs_radar_history **radar_history,
2269 			    uint32_t *count)
2270 {
2271 	struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
2272 	struct dfsreq_nolinfo *nol_info;
2273 	uint32_t i;
2274 	uint32_t hist_count;
2275 	struct dfs_radar_history *radar_result;
2276 
2277 	nol_info = qdf_mem_malloc(sizeof(struct dfsreq_nolinfo));
2278 	if (!nol_info)
2279 		return QDF_STATUS_E_NOMEM;
2280 
2281 	ucfg_dfs_getnol(mac_ctx->pdev, nol_info);
2282 
2283 	hist_count = nol_info->dfs_ch_nchans + MAX_NUM_OF_CAC_HISTORY;
2284 	radar_result = qdf_mem_malloc(sizeof(struct dfs_radar_history) *
2285 					hist_count);
2286 	if (!radar_result) {
2287 		qdf_mem_free(nol_info);
2288 		return QDF_STATUS_E_NOMEM;
2289 	}
2290 
2291 	for (i = 0; i < nol_info->dfs_ch_nchans && i < DFS_CHAN_MAX; i++) {
2292 		radar_result[i].ch_freq = nol_info->dfs_nol[i].nol_freq;
2293 		radar_result[i].time = nol_info->dfs_nol[i].nol_start_us;
2294 		radar_result[i].radar_found = true;
2295 		sap_debug("radar hist[%d] freq %d time %llu radar",
2296 			  i, nol_info->dfs_nol[i].nol_freq,
2297 			  nol_info->dfs_nol[i].nol_start_us);
2298 	}
2299 
2300 	sap_append_cac_history(mac_ctx, radar_result, &i, hist_count);
2301 	sap_debug("hist count %d cur %llu", i, qdf_get_monotonic_boottime());
2302 
2303 	*radar_history = radar_result;
2304 	*count = i;
2305 	qdf_mem_free(nol_info);
2306 
2307 	return QDF_STATUS_SUCCESS;
2308 }
2309 #else
2310 static inline void
2311 sap_update_cac_history(struct mac_context *mac_ctx,
2312 		       struct sap_context *sap_ctx,
2313 		       eSapHddEvent event_id)
2314 {
2315 }
2316 #endif
2317 
2318 #ifdef WLAN_FEATURE_11BE_MLO
2319 static inline
2320 bool sap_check_peer_for_peer_null_mldaddr(struct wlan_objmgr_peer *peer)
2321 {
2322 	if (qdf_is_macaddr_zero((struct qdf_mac_addr *)peer->mldaddr))
2323 		return true;
2324 	else
2325 		return false;
2326 }
2327 #else
2328 static inline
2329 bool sap_check_peer_for_peer_null_mldaddr(struct wlan_objmgr_peer *peer)
2330 {
2331 	return true;
2332 }
2333 #endif
2334 
2335 static
2336 QDF_STATUS sap_populate_peer_assoc_info(struct mac_context *mac_ctx,
2337 					struct csr_roam_info *csr_roaminfo,
2338 					struct sap_event *sap_ap_event)
2339 {
2340 	struct wlan_objmgr_peer *peer;
2341 	tSap_StationAssocReassocCompleteEvent *reassoc_complete;
2342 
2343 	reassoc_complete =
2344 		&sap_ap_event->sapevt.sapStationAssocReassocCompleteEvent;
2345 
2346 	peer = wlan_objmgr_get_peer_by_mac(mac_ctx->psoc,
2347 					   csr_roaminfo->peerMac.bytes,
2348 					   WLAN_LEGACY_MAC_ID);
2349 	if (!peer) {
2350 		sap_err("Peer object not found");
2351 		return QDF_STATUS_E_FAILURE;
2352 	}
2353 
2354 	sap_debug("mlo peer assoc:%d", wlan_peer_mlme_is_assoc_peer(peer));
2355 
2356 	if (sap_check_peer_for_peer_null_mldaddr(peer) ||
2357 	    wlan_peer_mlme_is_assoc_peer(peer)) {
2358 		if (csr_roaminfo->assocReqLength < ASSOC_REQ_IE_OFFSET) {
2359 			sap_err("Invalid assoc request length:%d",
2360 				csr_roaminfo->assocReqLength);
2361 			wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_MAC_ID);
2362 			return QDF_STATUS_E_INVAL;
2363 		}
2364 		reassoc_complete->ies_len = (csr_roaminfo->assocReqLength -
2365 					    ASSOC_REQ_IE_OFFSET);
2366 		reassoc_complete->ies = (csr_roaminfo->assocReqPtr +
2367 					 ASSOC_REQ_IE_OFFSET);
2368 		/* skip current AP address in reassoc frame */
2369 		if (csr_roaminfo->fReassocReq) {
2370 			reassoc_complete->ies_len -= QDF_MAC_ADDR_SIZE;
2371 			reassoc_complete->ies += QDF_MAC_ADDR_SIZE;
2372 		}
2373 	}
2374 
2375 	if (csr_roaminfo->addIELen) {
2376 		if (wlan_get_vendor_ie_ptr_from_oui(
2377 		    SIR_MAC_P2P_OUI, SIR_MAC_P2P_OUI_SIZE,
2378 		    csr_roaminfo->paddIE, csr_roaminfo->addIELen)) {
2379 			reassoc_complete->staType = eSTA_TYPE_P2P_CLI;
2380 		} else {
2381 			reassoc_complete->staType = eSTA_TYPE_INFRA;
2382 		}
2383 	}
2384 
2385 	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_MAC_ID);
2386 
2387 	return QDF_STATUS_SUCCESS;
2388 }
2389 
2390 #ifdef WLAN_FEATURE_11BE_MLO
2391 static void
2392 sap_reassoc_mld_copy(struct csr_roam_info *csr_roaminfo,
2393 		     tSap_StationAssocReassocCompleteEvent *reassoc_complete)
2394 {
2395 	qdf_copy_macaddr(&reassoc_complete->sta_mld,
2396 			 &csr_roaminfo->peer_mld);
2397 	sap_debug("reassoc_complete->staMld: " QDF_MAC_ADDR_FMT,
2398 		  QDF_MAC_ADDR_REF(reassoc_complete->sta_mld.bytes));
2399 }
2400 #else /* WLAN_FEATURE_11BE_MLO */
2401 static inline void
2402 sap_reassoc_mld_copy(struct csr_roam_info *csr_roaminfo,
2403 		     tSap_StationAssocReassocCompleteEvent *reassoc_complete)
2404 {
2405 }
2406 #endif /* WLAN_FEATURE_11BE_MLO */
2407 
2408 /**
2409  * sap_signal_hdd_event() - send event notification
2410  * @sap_ctx: Sap Context
2411  * @csr_roaminfo: Pointer to CSR roam information
2412  * @sap_hddevent: SAP HDD event
2413  * @context: to pass the element for future support
2414  *
2415  * Function for HDD to send the event notification using callback
2416  *
2417  * Return: QDF_STATUS
2418  */
2419 QDF_STATUS sap_signal_hdd_event(struct sap_context *sap_ctx,
2420 		struct csr_roam_info *csr_roaminfo, eSapHddEvent sap_hddevent,
2421 		void *context)
2422 {
2423 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
2424 	struct sap_event *sap_ap_event;
2425 	struct mac_context *mac_ctx;
2426 	struct oem_channel_info *chaninfo;
2427 	tSap_StationAssocIndication *assoc_ind;
2428 	tSap_StartBssCompleteEvent *bss_complete;
2429 	struct sap_ch_selected_s *acs_selected;
2430 	tSap_StationAssocReassocCompleteEvent *reassoc_complete;
2431 	tSap_StationDisassocCompleteEvent *disassoc_comp;
2432 	tSap_StationSetKeyCompleteEvent *key_complete;
2433 	tSap_StationMICFailureEvent *mic_failure;
2434 
2435 	/* Format the Start BSS Complete event to return... */
2436 	if (!sap_ctx->sap_event_cb)
2437 		return QDF_STATUS_E_FAILURE;
2438 
2439 	mac_ctx = sap_get_mac_context();
2440 	if (!mac_ctx) {
2441 		sap_err("Invalid MAC context");
2442 		return QDF_STATUS_E_FAILURE;
2443 	}
2444 
2445 	sap_ap_event = qdf_mem_malloc(sizeof(*sap_ap_event));
2446 	if (!sap_ap_event)
2447 		return QDF_STATUS_E_NOMEM;
2448 
2449 	sap_debug("SAP event callback event = %s",
2450 		  sap_hdd_event_to_string(sap_hddevent));
2451 
2452 	switch (sap_hddevent) {
2453 	case eSAP_STA_ASSOC_IND:
2454 		if (!csr_roaminfo) {
2455 			sap_debug("Invalid CSR Roam Info");
2456 			qdf_mem_free(sap_ap_event);
2457 			return QDF_STATUS_E_INVAL;
2458 		}
2459 		/*  TODO - Indicate the assoc request indication to OS */
2460 		sap_ap_event->sapHddEventCode = eSAP_STA_ASSOC_IND;
2461 		assoc_ind = &sap_ap_event->sapevt.sapAssocIndication;
2462 
2463 		qdf_copy_macaddr(&assoc_ind->staMac, &csr_roaminfo->peerMac);
2464 		assoc_ind->staId = csr_roaminfo->staId;
2465 		assoc_ind->status = 0;
2466 		/* Required for indicating the frames to upper layer */
2467 		assoc_ind->assocReqLength = csr_roaminfo->assocReqLength;
2468 		assoc_ind->assocReqPtr = csr_roaminfo->assocReqPtr;
2469 		assoc_ind->fWmmEnabled = csr_roaminfo->wmmEnabledSta;
2470 		assoc_ind->ecsa_capable = csr_roaminfo->ecsa_capable;
2471 		if (csr_roaminfo->owe_pending_assoc_ind) {
2472 			if (!sap_fill_owe_ie_in_assoc_ind(assoc_ind,
2473 					 csr_roaminfo->owe_pending_assoc_ind,
2474 					 csr_roaminfo->fReassocReq)) {
2475 				sap_err("Failed to fill OWE IE");
2476 				qdf_mem_free(csr_roaminfo->
2477 					     owe_pending_assoc_ind);
2478 				csr_roaminfo->owe_pending_assoc_ind = NULL;
2479 				qdf_mem_free(sap_ap_event);
2480 				return QDF_STATUS_E_INVAL;
2481 			}
2482 			if (!sap_save_owe_pending_assoc_ind(sap_ctx,
2483 					 csr_roaminfo->owe_pending_assoc_ind)) {
2484 				sap_err("Failed to save assoc ind");
2485 				qdf_mem_free(csr_roaminfo->
2486 					     owe_pending_assoc_ind);
2487 				csr_roaminfo->owe_pending_assoc_ind = NULL;
2488 				qdf_mem_free(sap_ap_event);
2489 				return QDF_STATUS_E_INVAL;
2490 			}
2491 			csr_roaminfo->owe_pending_assoc_ind = NULL;
2492 		}
2493 
2494 		if (csr_roaminfo->ft_pending_assoc_ind) {
2495 			if (!sap_save_ft_pending_assoc_ind(sap_ctx,
2496 			    csr_roaminfo->ft_pending_assoc_ind)) {
2497 				sap_err("Failed to save ft assoc ind");
2498 				qdf_mem_free(csr_roaminfo->ft_pending_assoc_ind);
2499 				csr_roaminfo->ft_pending_assoc_ind = NULL;
2500 				qdf_mem_free(sap_ap_event);
2501 				return QDF_STATUS_E_INVAL;
2502 			}
2503 			csr_roaminfo->ft_pending_assoc_ind = NULL;
2504 		}
2505 		break;
2506 	case eSAP_START_BSS_EVENT:
2507 		sap_ap_event->sapHddEventCode = eSAP_START_BSS_EVENT;
2508 		bss_complete = &sap_ap_event->sapevt.sapStartBssCompleteEvent;
2509 
2510 		bss_complete->sessionId = sap_ctx->sessionId;
2511 		if (bss_complete->sessionId == WLAN_UMAC_VDEV_ID_MAX) {
2512 			sap_err("Invalid sessionId");
2513 			qdf_mem_free(sap_ap_event);
2514 			return QDF_STATUS_E_INVAL;
2515 		}
2516 
2517 		bss_complete->status = (eSapStatus) context;
2518 		bss_complete->staId = sap_ctx->sap_sta_id;
2519 
2520 		sap_debug("(eSAP_START_BSS_EVENT): staId = %d",
2521 			  bss_complete->staId);
2522 
2523 		bss_complete->operating_chan_freq = sap_ctx->chan_freq;
2524 		bss_complete->ch_width = sap_ctx->ch_params.ch_width;
2525 		if (QDF_IS_STATUS_SUCCESS(bss_complete->status)) {
2526 			sap_update_cac_history(mac_ctx, sap_ctx,
2527 					       sap_hddevent);
2528 			sap_update_mcs_rate(sap_ctx, true);
2529 		}
2530 		break;
2531 	case eSAP_DFS_CAC_START:
2532 	case eSAP_DFS_CAC_INTERRUPTED:
2533 	case eSAP_DFS_CAC_END:
2534 	case eSAP_DFS_RADAR_DETECT:
2535 	case eSAP_DFS_NO_AVAILABLE_CHANNEL:
2536 		sap_ap_event->sapHddEventCode = sap_hddevent;
2537 		sap_ap_event->sapevt.sapStopBssCompleteEvent.status =
2538 			(eSapStatus) context;
2539 		sap_update_cac_history(mac_ctx, sap_ctx,
2540 				       sap_hddevent);
2541 		break;
2542 	case eSAP_ACS_SCAN_SUCCESS_EVENT:
2543 		sap_handle_acs_scan_event(sap_ctx, sap_ap_event,
2544 					  (eSapStatus)context);
2545 		break;
2546 	case eSAP_ACS_CHANNEL_SELECTED:
2547 		sap_ap_event->sapHddEventCode = sap_hddevent;
2548 		acs_selected = &sap_ap_event->sapevt.sap_ch_selected;
2549 		if (eSAP_STATUS_SUCCESS == (eSapStatus)context) {
2550 			acs_selected->pri_ch_freq =
2551 						sap_ctx->acs_cfg->pri_ch_freq;
2552 			acs_selected->ht_sec_ch_freq =
2553 					sap_ctx->acs_cfg->ht_sec_ch_freq;
2554 			acs_selected->ch_width = sap_ctx->acs_cfg->ch_width;
2555 			acs_selected->vht_seg0_center_ch_freq =
2556 				sap_ctx->acs_cfg->vht_seg0_center_ch_freq;
2557 			acs_selected->vht_seg1_center_ch_freq =
2558 				sap_ctx->acs_cfg->vht_seg1_center_ch_freq;
2559 		} else if (eSAP_STATUS_FAILURE == (eSapStatus)context) {
2560 			acs_selected->pri_ch_freq = 0;
2561 		}
2562 		break;
2563 
2564 	case eSAP_STOP_BSS_EVENT:
2565 		sap_ap_event->sapHddEventCode = eSAP_STOP_BSS_EVENT;
2566 		sap_ap_event->sapevt.sapStopBssCompleteEvent.status =
2567 			(eSapStatus) context;
2568 		break;
2569 
2570 	case eSAP_STA_ASSOC_EVENT:
2571 	case eSAP_STA_REASSOC_EVENT:
2572 
2573 		if (!csr_roaminfo) {
2574 			sap_err("Invalid CSR Roam Info");
2575 			qdf_mem_free(sap_ap_event);
2576 			return QDF_STATUS_E_INVAL;
2577 		}
2578 		if (sap_ctx->fsm_state == SAP_STOPPING) {
2579 			sap_err("SAP is stopping, not able to handle any incoming (re)assoc req");
2580 			qdf_mem_free(sap_ap_event);
2581 			return QDF_STATUS_E_ABORTED;
2582 		}
2583 
2584 		qdf_status = sap_populate_peer_assoc_info(mac_ctx, csr_roaminfo,
2585 							  sap_ap_event);
2586 		if (QDF_IS_STATUS_ERROR(qdf_status)) {
2587 			qdf_mem_free(sap_ap_event);
2588 			return QDF_STATUS_E_INVAL;
2589 		}
2590 
2591 		reassoc_complete =
2592 		    &sap_ap_event->sapevt.sapStationAssocReassocCompleteEvent;
2593 
2594 		if (csr_roaminfo->fReassocReq)
2595 			sap_ap_event->sapHddEventCode = eSAP_STA_REASSOC_EVENT;
2596 		else
2597 			sap_ap_event->sapHddEventCode = eSAP_STA_ASSOC_EVENT;
2598 
2599 		qdf_copy_macaddr(&reassoc_complete->staMac,
2600 				 &csr_roaminfo->peerMac);
2601 		sap_reassoc_mld_copy(csr_roaminfo, reassoc_complete);
2602 		reassoc_complete->staId = csr_roaminfo->staId;
2603 		reassoc_complete->status_code = csr_roaminfo->status_code;
2604 
2605 		/* also fill up the channel info from the csr_roamInfo */
2606 		chaninfo = &reassoc_complete->chan_info;
2607 
2608 		chaninfo->mhz = csr_roaminfo->chan_info.mhz;
2609 		chaninfo->info = csr_roaminfo->chan_info.info;
2610 		chaninfo->band_center_freq1 =
2611 			csr_roaminfo->chan_info.band_center_freq1;
2612 		chaninfo->band_center_freq2 =
2613 			csr_roaminfo->chan_info.band_center_freq2;
2614 		chaninfo->reg_info_1 =
2615 			csr_roaminfo->chan_info.reg_info_1;
2616 		chaninfo->reg_info_2 =
2617 			csr_roaminfo->chan_info.reg_info_2;
2618 		chaninfo->nss = csr_roaminfo->chan_info.nss;
2619 		chaninfo->rate_flags = csr_roaminfo->chan_info.rate_flags;
2620 
2621 		reassoc_complete->wmmEnabled = csr_roaminfo->wmmEnabledSta;
2622 		reassoc_complete->status = (eSapStatus) context;
2623 		reassoc_complete->timingMeasCap = csr_roaminfo->timingMeasCap;
2624 		reassoc_complete->ampdu = csr_roaminfo->ampdu;
2625 		reassoc_complete->sgi_enable = csr_roaminfo->sgi_enable;
2626 		reassoc_complete->tx_stbc = csr_roaminfo->tx_stbc;
2627 		reassoc_complete->rx_stbc = csr_roaminfo->rx_stbc;
2628 		reassoc_complete->ch_width = csr_roaminfo->ch_width;
2629 		reassoc_complete->mode = csr_roaminfo->mode;
2630 		reassoc_complete->max_supp_idx = csr_roaminfo->max_supp_idx;
2631 		reassoc_complete->max_ext_idx = csr_roaminfo->max_ext_idx;
2632 		reassoc_complete->max_mcs_idx = csr_roaminfo->max_mcs_idx;
2633 		reassoc_complete->max_real_mcs_idx =
2634 						csr_roaminfo->max_real_mcs_idx;
2635 		reassoc_complete->rx_mcs_map = csr_roaminfo->rx_mcs_map;
2636 		reassoc_complete->tx_mcs_map = csr_roaminfo->tx_mcs_map;
2637 		reassoc_complete->ecsa_capable = csr_roaminfo->ecsa_capable;
2638 		reassoc_complete->ext_cap = csr_roaminfo->ext_cap;
2639 		reassoc_complete->supported_band = csr_roaminfo->supported_band;
2640 		if (csr_roaminfo->ht_caps.present)
2641 			reassoc_complete->ht_caps = csr_roaminfo->ht_caps;
2642 		if (csr_roaminfo->vht_caps.present)
2643 			reassoc_complete->vht_caps = csr_roaminfo->vht_caps;
2644 		reassoc_complete->he_caps_present =
2645 						csr_roaminfo->he_caps_present;
2646 		reassoc_complete->eht_caps_present =
2647 						csr_roaminfo->eht_caps_present;
2648 		reassoc_complete->capability_info =
2649 						csr_roaminfo->capability_info;
2650 
2651 		break;
2652 
2653 	case eSAP_STA_DISASSOC_EVENT:
2654 		if (!csr_roaminfo) {
2655 			sap_debug("Invalid CSR Roam Info");
2656 			qdf_mem_free(sap_ap_event);
2657 			return QDF_STATUS_E_INVAL;
2658 		}
2659 		sap_ap_event->sapHddEventCode = eSAP_STA_DISASSOC_EVENT;
2660 		disassoc_comp =
2661 			&sap_ap_event->sapevt.sapStationDisassocCompleteEvent;
2662 
2663 		qdf_copy_macaddr(&disassoc_comp->staMac,
2664 				 &csr_roaminfo->peerMac);
2665 		disassoc_comp->staId = csr_roaminfo->staId;
2666 		if (csr_roaminfo->reasonCode == eCSR_ROAM_RESULT_FORCED)
2667 			disassoc_comp->reason = eSAP_USR_INITATED_DISASSOC;
2668 		else
2669 			disassoc_comp->reason = eSAP_MAC_INITATED_DISASSOC;
2670 
2671 		disassoc_comp->status_code = csr_roaminfo->status_code;
2672 		disassoc_comp->status = (eSapStatus) context;
2673 		disassoc_comp->rssi = csr_roaminfo->rssi;
2674 		disassoc_comp->rx_rate = csr_roaminfo->rx_rate;
2675 		disassoc_comp->tx_rate = csr_roaminfo->tx_rate;
2676 		disassoc_comp->rx_mc_bc_cnt = csr_roaminfo->rx_mc_bc_cnt;
2677 		disassoc_comp->rx_retry_cnt = csr_roaminfo->rx_retry_cnt;
2678 		disassoc_comp->reason_code = csr_roaminfo->disassoc_reason;
2679 		break;
2680 
2681 	case eSAP_STA_SET_KEY_EVENT:
2682 
2683 		if (!csr_roaminfo) {
2684 			sap_debug("Invalid CSR Roam Info");
2685 			qdf_mem_free(sap_ap_event);
2686 			return QDF_STATUS_E_INVAL;
2687 		}
2688 		sap_ap_event->sapHddEventCode = eSAP_STA_SET_KEY_EVENT;
2689 		key_complete =
2690 			&sap_ap_event->sapevt.sapStationSetKeyCompleteEvent;
2691 		key_complete->status = (eSapStatus) context;
2692 		qdf_copy_macaddr(&key_complete->peerMacAddr,
2693 				 &csr_roaminfo->peerMac);
2694 		break;
2695 
2696 	case eSAP_STA_MIC_FAILURE_EVENT:
2697 
2698 		if (!csr_roaminfo) {
2699 			sap_debug("Invalid CSR Roam Info");
2700 			qdf_mem_free(sap_ap_event);
2701 			return QDF_STATUS_E_INVAL;
2702 		}
2703 		sap_ap_event->sapHddEventCode = eSAP_STA_MIC_FAILURE_EVENT;
2704 		mic_failure = &sap_ap_event->sapevt.sapStationMICFailureEvent;
2705 
2706 		qdf_mem_copy(&mic_failure->srcMacAddr,
2707 			     csr_roaminfo->u.pMICFailureInfo->srcMacAddr,
2708 			     sizeof(tSirMacAddr));
2709 		qdf_mem_copy(&mic_failure->staMac.bytes,
2710 			     csr_roaminfo->u.pMICFailureInfo->taMacAddr,
2711 			     sizeof(tSirMacAddr));
2712 		qdf_mem_copy(&mic_failure->dstMacAddr.bytes,
2713 			     csr_roaminfo->u.pMICFailureInfo->dstMacAddr,
2714 			     sizeof(tSirMacAddr));
2715 		mic_failure->multicast =
2716 			csr_roaminfo->u.pMICFailureInfo->multicast;
2717 		mic_failure->IV1 = csr_roaminfo->u.pMICFailureInfo->IV1;
2718 		mic_failure->keyId = csr_roaminfo->u.pMICFailureInfo->keyId;
2719 		qdf_mem_copy(mic_failure->TSC,
2720 			     csr_roaminfo->u.pMICFailureInfo->TSC,
2721 			     SIR_CIPHER_SEQ_CTR_SIZE);
2722 		break;
2723 
2724 	case eSAP_WPS_PBC_PROBE_REQ_EVENT:
2725 
2726 		if (!csr_roaminfo) {
2727 			sap_debug("Invalid CSR Roam Info");
2728 			qdf_mem_free(sap_ap_event);
2729 			return QDF_STATUS_E_INVAL;
2730 		}
2731 		sap_ap_event->sapHddEventCode = eSAP_WPS_PBC_PROBE_REQ_EVENT;
2732 
2733 		qdf_mem_copy(&sap_ap_event->sapevt.sapPBCProbeReqEvent.
2734 			     WPSPBCProbeReq, csr_roaminfo->u.pWPSPBCProbeReq,
2735 			     sizeof(tSirWPSPBCProbeReq));
2736 		break;
2737 
2738 	case eSAP_DISCONNECT_ALL_P2P_CLIENT:
2739 		sap_ap_event->sapHddEventCode = eSAP_DISCONNECT_ALL_P2P_CLIENT;
2740 		sap_ap_event->sapevt.sapActionCnf.actionSendSuccess =
2741 			(eSapStatus) context;
2742 		break;
2743 
2744 	case eSAP_MAC_TRIG_STOP_BSS_EVENT:
2745 		sap_ap_event->sapHddEventCode = eSAP_MAC_TRIG_STOP_BSS_EVENT;
2746 		sap_ap_event->sapevt.sapActionCnf.actionSendSuccess =
2747 			(eSapStatus) context;
2748 		break;
2749 
2750 	case eSAP_UNKNOWN_STA_JOIN:
2751 		sap_ap_event->sapHddEventCode = eSAP_UNKNOWN_STA_JOIN;
2752 		qdf_mem_copy((void *)sap_ap_event->sapevt.sapUnknownSTAJoin.
2753 			     macaddr.bytes, (void *) context,
2754 			     QDF_MAC_ADDR_SIZE);
2755 		break;
2756 
2757 	case eSAP_MAX_ASSOC_EXCEEDED:
2758 
2759 		if (!csr_roaminfo) {
2760 			sap_debug("Invalid CSR Roam Info");
2761 			qdf_mem_free(sap_ap_event);
2762 			return QDF_STATUS_E_INVAL;
2763 		}
2764 		sap_ap_event->sapHddEventCode = eSAP_MAX_ASSOC_EXCEEDED;
2765 		qdf_copy_macaddr(&sap_ap_event->sapevt.
2766 				 sapMaxAssocExceeded.macaddr,
2767 				 &csr_roaminfo->peerMac);
2768 		break;
2769 
2770 	case eSAP_CHANNEL_CHANGE_EVENT:
2771 		/*
2772 		 * Reconfig ACS result info. For DFS AP-AP Mode Sec AP ACS
2773 		 * follows pri AP
2774 		 */
2775 		sap_ctx->acs_cfg->pri_ch_freq = sap_ctx->chan_freq;
2776 		sap_ctx->acs_cfg->ch_width =
2777 					sap_ctx->ch_params.ch_width;
2778 		sap_config_acs_result(MAC_HANDLE(mac_ctx), sap_ctx,
2779 				      sap_ctx->sec_ch_freq);
2780 
2781 		sap_ap_event->sapHddEventCode = eSAP_CHANNEL_CHANGE_EVENT;
2782 
2783 		acs_selected = &sap_ap_event->sapevt.sap_ch_selected;
2784 		acs_selected->pri_ch_freq = sap_ctx->chan_freq;
2785 		acs_selected->ht_sec_ch_freq = sap_ctx->sec_ch_freq;
2786 		acs_selected->ch_width =
2787 			sap_ctx->acs_cfg->ch_width;
2788 		acs_selected->vht_seg0_center_ch_freq =
2789 			sap_ctx->acs_cfg->vht_seg0_center_ch_freq;
2790 		acs_selected->vht_seg1_center_ch_freq =
2791 			sap_ctx->acs_cfg->vht_seg1_center_ch_freq;
2792 		break;
2793 
2794 	case eSAP_ECSA_CHANGE_CHAN_IND:
2795 
2796 		if (!csr_roaminfo) {
2797 			sap_debug("Invalid CSR Roam Info");
2798 			qdf_mem_free(sap_ap_event);
2799 			return QDF_STATUS_E_INVAL;
2800 		}
2801 		sap_debug("SAP event callback event = %s",
2802 			  "eSAP_ECSA_CHANGE_CHAN_IND");
2803 		sap_ap_event->sapHddEventCode = eSAP_ECSA_CHANGE_CHAN_IND;
2804 		sap_ap_event->sapevt.sap_chan_cng_ind.new_chan_freq =
2805 					   csr_roaminfo->target_chan_freq;
2806 		break;
2807 	case eSAP_DFS_NEXT_CHANNEL_REQ:
2808 		sap_debug("SAP event callback event = %s",
2809 			  "eSAP_DFS_NEXT_CHANNEL_REQ");
2810 		sap_ap_event->sapHddEventCode = eSAP_DFS_NEXT_CHANNEL_REQ;
2811 		break;
2812 	case eSAP_STOP_BSS_DUE_TO_NO_CHNL:
2813 		sap_ap_event->sapHddEventCode = eSAP_STOP_BSS_DUE_TO_NO_CHNL;
2814 		sap_debug("stopping session_id:%d, bssid:"QDF_MAC_ADDR_FMT", chan_freq:%d",
2815 			   sap_ctx->sessionId,
2816 			   QDF_MAC_ADDR_REF(sap_ctx->self_mac_addr),
2817 			   sap_ctx->chan_freq);
2818 		break;
2819 
2820 	case eSAP_CHANNEL_CHANGE_RESP:
2821 		sap_ap_event->sapHddEventCode = eSAP_CHANNEL_CHANGE_RESP;
2822 		sap_ap_event->sapevt.sap_chan_cng_rsp.ch_change_rsp_status =
2823 					(eSapStatus)context;
2824 		acs_selected =
2825 			&sap_ap_event->sapevt.sap_chan_cng_rsp.sap_ch_selected;
2826 		acs_selected->pri_ch_freq = sap_ctx->chan_freq;
2827 		acs_selected->ht_sec_ch_freq = sap_ctx->sec_ch_freq;
2828 		acs_selected->ch_width =
2829 				sap_ctx->ch_params.ch_width;
2830 		acs_selected->vht_seg0_center_ch_freq =
2831 				sap_ctx->ch_params.mhz_freq_seg0;
2832 		acs_selected->vht_seg1_center_ch_freq =
2833 				sap_ctx->ch_params.mhz_freq_seg1;
2834 		sap_update_cac_history(mac_ctx, sap_ctx,
2835 				       sap_hddevent);
2836 		sap_debug("SAP event callback event = %s",
2837 			  "eSAP_CHANNEL_CHANGE_RESP");
2838 		break;
2839 
2840 	default:
2841 		sap_err("SAP Unknown callback event = %d", sap_hddevent);
2842 		break;
2843 	}
2844 	qdf_status = (*sap_ctx->sap_event_cb)
2845 			(sap_ap_event, sap_ctx->user_context);
2846 
2847 	qdf_mem_free(sap_ap_event);
2848 
2849 	return qdf_status;
2850 }
2851 
2852 bool sap_is_dfs_cac_wait_state(struct sap_context *sap_ctx)
2853 {
2854 	struct wlan_objmgr_vdev *vdev;
2855 	QDF_STATUS status;
2856 	struct mac_context *mac_ctx;
2857 	mac_handle_t mac_handle;
2858 
2859 	if (!sap_ctx) {
2860 		sap_err("Invalid sap context");
2861 		return false;
2862 	}
2863 
2864 	mac_handle = cds_get_context(QDF_MODULE_ID_SME);
2865 	if (!mac_handle)
2866 		return false;
2867 
2868 	mac_ctx = MAC_CONTEXT(mac_handle);
2869 	if (!mac_ctx) {
2870 		sap_err("Invalid MAC context");
2871 		return false;
2872 	}
2873 
2874 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc,
2875 						    sap_ctx->sessionId,
2876 						    WLAN_DFS_ID);
2877 	if (!vdev) {
2878 		sap_err("vdev is NULL for vdev_id: %u", sap_ctx->sessionId);
2879 		return false;
2880 	}
2881 
2882 	status = wlan_vdev_is_dfs_cac_wait(vdev);
2883 	wlan_objmgr_vdev_release_ref(vdev, WLAN_DFS_ID);
2884 
2885 	return QDF_IS_STATUS_SUCCESS(status);
2886 }
2887 
2888 /**
2889  * sap_find_cac_wait_session() - Get context of a SAP session in CAC wait state
2890  * @handle: Global MAC handle
2891  *
2892  * Finds and gets the context of a SAP session in CAC wait state.
2893  *
2894  * Return: Valid SAP context on success, else NULL
2895  */
2896 static struct sap_context *sap_find_cac_wait_session(mac_handle_t handle)
2897 {
2898 	struct mac_context *mac = MAC_CONTEXT(handle);
2899 	uint8_t i = 0;
2900 	struct sap_context *sap_ctx;
2901 
2902 	for (i = 0; i < SAP_MAX_NUM_SESSION; i++) {
2903 		sap_ctx = mac->sap.sapCtxList[i].sap_context;
2904 		if (((QDF_SAP_MODE == mac->sap.sapCtxList[i].sapPersona)
2905 		    ||
2906 		    (QDF_P2P_GO_MODE == mac->sap.sapCtxList[i].sapPersona)) &&
2907 		    (sap_is_dfs_cac_wait_state(sap_ctx))) {
2908 			sap_debug("found SAP in cac wait state");
2909 			return sap_ctx;
2910 		}
2911 		if (sap_ctx) {
2912 			sap_debug("sapdfs: mode:%d intf:%d state:%d",
2913 				  mac->sap.sapCtxList[i].sapPersona, i,
2914 				  sap_ctx->fsm_state);
2915 		}
2916 	}
2917 
2918 	return NULL;
2919 }
2920 
2921 void sap_cac_reset_notify(mac_handle_t mac_handle)
2922 {
2923 	uint8_t intf = 0;
2924 	struct mac_context *mac = MAC_CONTEXT(mac_handle);
2925 
2926 	for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) {
2927 		struct sap_context *sap_context =
2928 			mac->sap.sapCtxList[intf].sap_context;
2929 		if (((QDF_SAP_MODE == mac->sap.sapCtxList[intf].sapPersona)
2930 		    ||
2931 		    (QDF_P2P_GO_MODE == mac->sap.sapCtxList[intf].sapPersona))
2932 		    && mac->sap.sapCtxList[intf].sap_context) {
2933 			sap_context->isCacStartNotified = false;
2934 			sap_context->isCacEndNotified = false;
2935 		}
2936 	}
2937 }
2938 
2939 /**
2940  * sap_cac_start_notify() - Notify CAC start to HDD
2941  * @mac_handle: Opaque handle to the global MAC context
2942  *
2943  * Function will be called to notify eSAP_DFS_CAC_START event to HDD
2944  *
2945  * Return: QDF_STATUS_SUCCESS if the notification was sent, otherwise
2946  *         an appropriate QDF_STATUS error
2947  */
2948 static QDF_STATUS sap_cac_start_notify(mac_handle_t mac_handle)
2949 {
2950 	uint8_t intf = 0;
2951 	struct mac_context *mac = MAC_CONTEXT(mac_handle);
2952 	QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
2953 
2954 	for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) {
2955 		struct sap_context *sap_context =
2956 			mac->sap.sapCtxList[intf].sap_context;
2957 
2958 		if (((QDF_SAP_MODE == mac->sap.sapCtxList[intf].sapPersona)
2959 		    ||
2960 		    (QDF_P2P_GO_MODE == mac->sap.sapCtxList[intf].sapPersona))
2961 		    && mac->sap.sapCtxList[intf].sap_context &&
2962 		    (false == sap_context->isCacStartNotified)) {
2963 			/* Don't start CAC for non-dfs channel, its violation */
2964 			if (!sap_operating_on_dfs(
2965 					mac,
2966 					mac->sap.sapCtxList[intf].sap_context))
2967 				continue;
2968 			sap_debug("sapdfs: Signaling eSAP_DFS_CAC_START to HDD for sapctx[%pK]",
2969 				  sap_context);
2970 
2971 			qdf_status = sap_signal_hdd_event(sap_context, NULL,
2972 							  eSAP_DFS_CAC_START,
2973 							  (void *)
2974 							  eSAP_STATUS_SUCCESS);
2975 			if (QDF_STATUS_SUCCESS != qdf_status) {
2976 				sap_err("Failed setting isCacStartNotified on interface[%d]",
2977 					 intf);
2978 				return qdf_status;
2979 			}
2980 			sap_context->isCacStartNotified = true;
2981 		}
2982 	}
2983 	return qdf_status;
2984 }
2985 
2986 #ifdef PRE_CAC_SUPPORT
2987 /**
2988  * wlansap_pre_cac_end_notify() - Update pre cac end to upper layer
2989  * @sap_context: SAP context
2990  * @mac: Global MAC structure
2991  * @intf: Interface number
2992  *
2993  * Notifies pre cac end to upper layer
2994  *
2995  * Return: None
2996  */
2997 static void wlansap_pre_cac_end_notify(struct sap_context *sap_context,
2998 				       struct mac_context *mac,
2999 				       uint8_t intf)
3000 {
3001 	sap_context->isCacEndNotified = true;
3002 	sap_context->sap_radar_found_status = false;
3003 	sap_context->fsm_state = SAP_STARTED;
3004 	sap_warn("sap_fsm: vdev %d => SAP_STARTED, pre cac end notify on %d",
3005 		 sap_context->vdev_id, intf);
3006 	wlan_pre_cac_handle_cac_end(sap_context->vdev);
3007 }
3008 #endif
3009 
3010 QDF_STATUS sap_cac_end_notify(mac_handle_t mac_handle,
3011 			      struct csr_roam_info *roamInfo)
3012 {
3013 	uint8_t intf;
3014 	struct mac_context *mac = MAC_CONTEXT(mac_handle);
3015 	QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
3016 	bool is_acs;
3017 
3018 	/*
3019 	 * eSAP_DFS_CHANNEL_CAC_END:
3020 	 * CAC Period elapsed and there was no radar
3021 	 * found so, SAP can continue beaconing.
3022 	 * sap_radar_found_status is set to 0
3023 	 */
3024 	for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) {
3025 		struct sap_context *sap_context =
3026 			mac->sap.sapCtxList[intf].sap_context;
3027 
3028 		if (((QDF_SAP_MODE == mac->sap.sapCtxList[intf].sapPersona)
3029 		    ||
3030 		    (QDF_P2P_GO_MODE == mac->sap.sapCtxList[intf].sapPersona))
3031 		    && mac->sap.sapCtxList[intf].sap_context &&
3032 		    (false == sap_context->isCacEndNotified) &&
3033 		    sap_is_dfs_cac_wait_state(sap_context)) {
3034 			sap_context = mac->sap.sapCtxList[intf].sap_context;
3035 			/* Don't check CAC for non-dfs channel */
3036 			if (!sap_operating_on_dfs(
3037 					mac,
3038 					mac->sap.sapCtxList[intf].sap_context))
3039 				continue;
3040 
3041 			/* If this is an end notification of a pre cac, the
3042 			 * SAP must not start beaconing and must delete the
3043 			 * temporary interface created for pre cac and switch
3044 			 * the original SAP to the pre CAC channel.
3045 			 */
3046 			if (wlan_pre_cac_get_status(mac->psoc)) {
3047 				wlansap_pre_cac_end_notify(sap_context,
3048 							   mac, intf);
3049 				/* pre CAC is not allowed with any concurrency.
3050 				 * So, we can break from here.
3051 				 */
3052 				break;
3053 			}
3054 
3055 			qdf_status = sap_signal_hdd_event(sap_context, NULL,
3056 							  eSAP_DFS_CAC_END,
3057 							  (void *)
3058 							  eSAP_STATUS_SUCCESS);
3059 			if (QDF_STATUS_SUCCESS != qdf_status) {
3060 				sap_err("failed setting isCacEndNotified on interface[%d]",
3061 					 intf);
3062 				return qdf_status;
3063 			}
3064 			sap_context->isCacEndNotified = true;
3065 			sap_context->sap_radar_found_status = false;
3066 			sap_debug("sapdfs: Start beacon request on sapctx[%pK]",
3067 				  sap_context);
3068 
3069 			/* Start beaconing on the new channel */
3070 			wlansap_start_beacon_req(sap_context);
3071 
3072 			/* Transition from SAP_STARTING to SAP_STARTED
3073 			 * (both without substates)
3074 			 */
3075 			sap_context->fsm_state = SAP_STARTED;
3076 			sap_debug("sap_fsm: vdev %d: SAP_STARTING => SAP_STARTED, freq %d",
3077 				  sap_context->vdev_id, sap_context->chan_freq);
3078 
3079 			/*Action code for transition */
3080 			qdf_status = sap_signal_hdd_event(sap_context, roamInfo,
3081 							  eSAP_START_BSS_EVENT,
3082 							  (void *)
3083 							  eSAP_STATUS_SUCCESS);
3084 			if (QDF_STATUS_SUCCESS != qdf_status) {
3085 				sap_err("Failed setting isCacEndNotified on interface[%d]",
3086 					 intf);
3087 				return qdf_status;
3088 			}
3089 
3090 			/*
3091 			 * CAC wait prevent SAP restart, check if need
3092 			 * restart SAP after CAC end
3093 			 */
3094 			is_acs = sap_context->acs_cfg &&
3095 				 sap_context->acs_cfg->acs_mode;
3096 			policy_mgr_check_concurrent_intf_and_restart_sap(mac->psoc,
3097 									 is_acs);
3098 		}
3099 	}
3100 
3101 	return qdf_status;
3102 }
3103 
3104 /**
3105  * sap_validate_dfs_nol() - Validate SAP channel with NOL list
3106  * @sap_ctx: SAP context
3107  * @mac_ctx: pointer to mac context
3108  *
3109  * Function will be called to validate SAP channel and bonded sub channels
3110  * included in DFS NOL or not.
3111  *
3112  * Return: QDF_STATUS_SUCCESS for NOT in NOL
3113  */
3114 static QDF_STATUS sap_validate_dfs_nol(struct sap_context *sap_ctx,
3115 				       struct mac_context *mac_ctx)
3116 {
3117 	bool b_leak_chan = false;
3118 	uint16_t temp_freq;
3119 	uint16_t sap_freq;
3120 	enum channel_state ch_state;
3121 	bool is_chan_nol = false;
3122 
3123 	sap_freq = sap_ctx->chan_freq;
3124 	temp_freq = sap_freq;
3125 	utils_dfs_mark_leaking_chan_for_freq(mac_ctx->pdev,
3126 					     sap_ctx->ch_params.ch_width, 1,
3127 					     &temp_freq);
3128 
3129 	/*
3130 	 * if selelcted channel has leakage to channels
3131 	 * in NOL, the temp_freq will be reset
3132 	 */
3133 	b_leak_chan = (temp_freq != sap_freq);
3134 	/*
3135 	 * check if channel is in DFS_NOL or if the channel
3136 	 * has leakage to the channels in NOL
3137 	 */
3138 
3139 	if (sap_phymode_is_eht(sap_ctx->phyMode)) {
3140 		ch_state =
3141 			wlan_reg_get_channel_state_from_secondary_list_for_freq(
3142 						mac_ctx->pdev, sap_freq);
3143 		if (CHANNEL_STATE_ENABLE != ch_state &&
3144 		    CHANNEL_STATE_DFS != ch_state) {
3145 			sap_err_rl("Invalid sap freq = %d, ch state=%d",
3146 				   sap_freq, ch_state);
3147 			is_chan_nol = true;
3148 		}
3149 	} else {
3150 		is_chan_nol = sap_dfs_is_channel_in_nol_list(
3151 					sap_ctx, sap_ctx->chan_freq,
3152 					PHY_CHANNEL_BONDING_STATE_MAX);
3153 	}
3154 
3155 	if (is_chan_nol || b_leak_chan) {
3156 		qdf_freq_t chan_freq;
3157 
3158 		/* find a new available channel */
3159 		chan_freq = sap_random_channel_sel(sap_ctx);
3160 		if (!chan_freq) {
3161 			/* No available channel found */
3162 			sap_err("No available channel found!!!");
3163 			sap_signal_hdd_event(sap_ctx, NULL,
3164 					     eSAP_DFS_NO_AVAILABLE_CHANNEL,
3165 					     (void *)eSAP_STATUS_SUCCESS);
3166 			return QDF_STATUS_E_FAULT;
3167 		}
3168 
3169 		sap_debug("ch_freq %d is in NOL, start bss on new freq %d",
3170 			  sap_ctx->chan_freq, chan_freq);
3171 
3172 		sap_ctx->chan_freq = chan_freq;
3173 		if (sap_phymode_is_eht(sap_ctx->phyMode))
3174 			wlan_reg_set_create_punc_bitmap(&sap_ctx->ch_params,
3175 							true);
3176 		wlan_reg_set_channel_params_for_pwrmode(mac_ctx->pdev,
3177 							sap_ctx->chan_freq,
3178 							sap_ctx->sec_ch_freq,
3179 							&sap_ctx->ch_params,
3180 							REG_CURRENT_PWR_MODE);
3181 	}
3182 
3183 	return QDF_STATUS_SUCCESS;
3184 }
3185 
3186 static void sap_validate_chanmode_and_chwidth(struct mac_context *mac_ctx,
3187 					      struct sap_context *sap_ctx)
3188 {
3189 	uint32_t orig_phymode;
3190 	enum phy_ch_width orig_ch_width;
3191 
3192 	orig_ch_width = sap_ctx->ch_params.ch_width;
3193 	orig_phymode = sap_ctx->phyMode;
3194 
3195 	if (WLAN_REG_IS_5GHZ_CH_FREQ(sap_ctx->chan_freq) &&
3196 	    (sap_ctx->phyMode == eCSR_DOT11_MODE_11g ||
3197 	     sap_ctx->phyMode == eCSR_DOT11_MODE_11g_ONLY)) {
3198 		sap_ctx->phyMode = eCSR_DOT11_MODE_11a;
3199 	} else if (WLAN_REG_IS_24GHZ_CH_FREQ(sap_ctx->chan_freq) &&
3200 		   (sap_ctx->phyMode == eCSR_DOT11_MODE_11a)) {
3201 		sap_ctx->phyMode = eCSR_DOT11_MODE_11g;
3202 	}
3203 
3204 	if (sap_ctx->ch_params.ch_width > CH_WIDTH_20MHZ &&
3205 	    (sap_ctx->phyMode == eCSR_DOT11_MODE_abg ||
3206 	     sap_ctx->phyMode == eCSR_DOT11_MODE_11a ||
3207 	     sap_ctx->phyMode == eCSR_DOT11_MODE_11g ||
3208 	     sap_ctx->phyMode == eCSR_DOT11_MODE_11b)) {
3209 		sap_ctx->ch_params.ch_width = CH_WIDTH_20MHZ;
3210 		wlan_reg_set_channel_params_for_pwrmode(mac_ctx->pdev,
3211 					       sap_ctx->chan_freq,
3212 					       sap_ctx->ch_params.sec_ch_offset,
3213 					       &sap_ctx->ch_params,
3214 					       REG_CURRENT_PWR_MODE);
3215 	} else if (sap_ctx->ch_params.ch_width > CH_WIDTH_40MHZ &&
3216 		   sap_ctx->phyMode == eCSR_DOT11_MODE_11n) {
3217 		sap_ctx->ch_params.ch_width = CH_WIDTH_40MHZ;
3218 		wlan_reg_set_channel_params_for_pwrmode(mac_ctx->pdev,
3219 					       sap_ctx->chan_freq,
3220 					       sap_ctx->ch_params.sec_ch_offset,
3221 					       &sap_ctx->ch_params,
3222 					       REG_CURRENT_PWR_MODE);
3223 	}
3224 
3225 	if (orig_ch_width != sap_ctx->ch_params.ch_width ||
3226 	    orig_phymode != sap_ctx->phyMode)
3227 		sap_info("Freq %d Updated BW %d -> %d , phymode %d -> %d",
3228 			 sap_ctx->chan_freq, orig_ch_width,
3229 			 sap_ctx->ch_params.ch_width,
3230 			 orig_phymode, sap_ctx->phyMode);
3231 }
3232 
3233 static bool
3234 wlansap_is_power_change_required(struct mac_context *mac_ctx,
3235 				 qdf_freq_t sap_freq)
3236 {
3237 	struct wlan_objmgr_vdev *sta_vdev;
3238 	uint8_t sta_vdev_id;
3239 	enum hw_mode_bandwidth ch_wd;
3240 	uint8_t country[CDS_COUNTRY_CODE_LEN + 1];
3241 	enum channel_state state;
3242 	uint32_t ap_pwr_type_6g = 0;
3243 	bool indoor_ch_support = false;
3244 
3245 	if (!mac_ctx || !mac_ctx->psoc || !mac_ctx->pdev)
3246 		return false;
3247 
3248 	if (!policy_mgr_is_sta_present_on_freq(mac_ctx->psoc, &sta_vdev_id,
3249 					       sap_freq, &ch_wd)) {
3250 		return false;
3251 	}
3252 
3253 	sta_vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc,
3254 							sta_vdev_id,
3255 							WLAN_LEGACY_SAP_ID);
3256 	if (!sta_vdev)
3257 		return false;
3258 
3259 	ap_pwr_type_6g = wlan_mlme_get_6g_ap_power_type(sta_vdev);
3260 
3261 	wlan_objmgr_vdev_release_ref(sta_vdev, WLAN_LEGACY_SAP_ID);
3262 
3263 	if (ap_pwr_type_6g == REG_VERY_LOW_POWER_AP)
3264 		return false;
3265 	ucfg_mlme_get_indoor_channel_support(mac_ctx->psoc, &indoor_ch_support);
3266 
3267 	if (ap_pwr_type_6g == REG_INDOOR_AP && indoor_ch_support) {
3268 		sap_debug("STA is connected to Indoor AP and indoor concurrency is supported");
3269 		return false;
3270 	}
3271 
3272 	wlan_reg_read_current_country(mac_ctx->psoc, country);
3273 	if (!wlan_reg_ctry_support_vlp(country)) {
3274 		sap_debug("Device country doesn't support VLP");
3275 		return false;
3276 	}
3277 
3278 	state = wlan_reg_get_channel_state_for_pwrmode(mac_ctx->pdev,
3279 						       sap_freq, REG_AP_VLP);
3280 
3281 	return state & CHANNEL_STATE_ENABLE;
3282 }
3283 
3284 /**
3285  * sap_goto_starting() - Trigger softap start
3286  * @sap_ctx: SAP context
3287  * @sap_event: SAP event buffer
3288  * @mac_ctx: global MAC context
3289  * @mac_handle: Opaque handle to the global MAC context
3290  *
3291  * This function triggers start of softap. Before starting, it can select
3292  * new channel if given channel has leakage or if given channel in DFS_NOL.
3293  *
3294  * Return: QDF_STATUS
3295  */
3296 static QDF_STATUS sap_goto_starting(struct sap_context *sap_ctx,
3297 				    struct sap_sm_event *sap_event,
3298 				    struct mac_context *mac_ctx,
3299 				    mac_handle_t mac_handle)
3300 {
3301 	QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
3302 	struct bss_dot11_config dot11_cfg = {0};
3303 	tSirMacRateSet *opr_rates = &sap_ctx->sap_bss_cfg.operationalRateSet;
3304 	tSirMacRateSet *ext_rates = &sap_ctx->sap_bss_cfg.extendedRateSet;
3305 	uint8_t h2e;
3306 
3307 	/*
3308 	 * check if channel is in DFS_NOL or if the channel
3309 	 * has leakage to the channels in NOL.
3310 	 */
3311 	if (!WLAN_REG_IS_6GHZ_CHAN_FREQ(sap_ctx->chan_freq)) {
3312 		qdf_status = sap_validate_dfs_nol(sap_ctx, mac_ctx);
3313 		if (!QDF_IS_STATUS_SUCCESS(qdf_status))
3314 			return qdf_status;
3315 	} else if (!policy_mgr_get_ap_6ghz_capable(mac_ctx->psoc,
3316 						   sap_ctx->sessionId, NULL)) {
3317 		return QDF_STATUS_E_FAILURE;
3318 	} else if (wlansap_is_power_change_required(mac_ctx,
3319 						    sap_ctx->chan_freq)) {
3320 		wlan_set_tpc_update_required_for_sta(sap_ctx->vdev, true);
3321 	}
3322 
3323 	/*
3324 	 * when AP2 is started while AP1 is performing ACS, we may not
3325 	 * have the AP1 channel yet.So here after the completion of AP2
3326 	 * ACS check if AP1 ACS resulting channel is DFS and if yes
3327 	 * override AP2 ACS scan result with AP1 DFS channel
3328 	 */
3329 	if (policy_mgr_concurrent_beaconing_sessions_running(mac_ctx->psoc)) {
3330 		uint32_t con_ch_freq;
3331 		uint16_t con_ch;
3332 
3333 		con_ch_freq = sme_get_beaconing_concurrent_operation_channel(
3334 				mac_handle, sap_ctx->sessionId);
3335 		con_ch = wlan_reg_freq_to_chan(mac_ctx->pdev, con_ch_freq);
3336 		/* Overwrite second AP's channel with first only when:
3337 		 * 1. If operating mode is single mac
3338 		 * 2. or if 2nd AP is coming up on 5G band channel
3339 		 */
3340 		if ((!policy_mgr_is_hw_dbs_capable(mac_ctx->psoc) ||
3341 		     WLAN_REG_IS_5GHZ_CH_FREQ(sap_ctx->chan_freq)) &&
3342 		     con_ch &&
3343 		     wlan_reg_is_dfs_for_freq(mac_ctx->pdev,
3344 					      con_ch_freq)) {
3345 			sap_ctx->chan_freq = con_ch_freq;
3346 			if (sap_phymode_is_eht(sap_ctx->phyMode))
3347 				wlan_reg_set_create_punc_bitmap(
3348 					&sap_ctx->ch_params, true);
3349 			wlan_reg_set_channel_params_for_pwrmode(
3350 						    mac_ctx->pdev,
3351 						    con_ch_freq, 0,
3352 						    &sap_ctx->ch_params,
3353 						    REG_CURRENT_PWR_MODE);
3354 		}
3355 	}
3356 
3357 	sap_validate_chanmode_and_chwidth(mac_ctx, sap_ctx);
3358 	/* Channel selected. Now can sap_goto_starting */
3359 	sap_ctx->fsm_state = SAP_STARTING;
3360 	sap_debug("sap_fsm: vdev %d: SAP_INIT => SAP_STARTING, phyMode %d bw %d",
3361 		  sap_ctx->vdev_id, sap_ctx->phyMode,
3362 		  sap_ctx->ch_params.ch_width);
3363 	/* Specify the channel */
3364 	sap_get_cac_dur_dfs_region(sap_ctx,
3365 				   &sap_ctx->sap_bss_cfg.cac_duration_ms,
3366 				   &sap_ctx->sap_bss_cfg.dfs_regdomain,
3367 				   sap_ctx->chan_freq,
3368 				   &sap_ctx->ch_params);
3369 	mlme_set_cac_required(sap_ctx->vdev,
3370 			      !!sap_ctx->sap_bss_cfg.cac_duration_ms);
3371 
3372 	sap_ctx->sap_bss_cfg.oper_ch_freq = sap_ctx->chan_freq;
3373 	sap_ctx->sap_bss_cfg.vht_channel_width = sap_ctx->ch_params.ch_width;
3374 	sap_ctx->sap_bss_cfg.center_freq_seg0 =
3375 					sap_ctx->ch_params.center_freq_seg0;
3376 	sap_ctx->sap_bss_cfg.center_freq_seg1 =
3377 					sap_ctx->ch_params.center_freq_seg1;
3378 	sap_ctx->sap_bss_cfg.sec_ch_offset = sap_ctx->ch_params.sec_ch_offset;
3379 
3380 	dot11_cfg.vdev_id = sap_ctx->sessionId;
3381 	dot11_cfg.bss_op_ch_freq = sap_ctx->chan_freq;
3382 	dot11_cfg.phy_mode = sap_ctx->phyMode;
3383 	dot11_cfg.privacy = sap_ctx->sap_bss_cfg.privacy;
3384 
3385 	qdf_mem_copy(dot11_cfg.opr_rates.rate,
3386 		     opr_rates->rate, opr_rates->numRates);
3387 	dot11_cfg.opr_rates.numRates = opr_rates->numRates;
3388 
3389 	qdf_mem_copy(dot11_cfg.ext_rates.rate,
3390 		     ext_rates->rate, ext_rates->numRates);
3391 	dot11_cfg.ext_rates.numRates = ext_rates->numRates;
3392 
3393 	sme_get_network_params(mac_ctx, &dot11_cfg);
3394 
3395 	sap_ctx->sap_bss_cfg.nwType = dot11_cfg.nw_type;
3396 	sap_ctx->sap_bss_cfg.dot11mode = dot11_cfg.dot11_mode;
3397 
3398 	if (dot11_cfg.opr_rates.numRates) {
3399 		qdf_mem_copy(opr_rates->rate,
3400 			     dot11_cfg.opr_rates.rate,
3401 			     dot11_cfg.opr_rates.numRates);
3402 		opr_rates->numRates = dot11_cfg.opr_rates.numRates;
3403 	} else {
3404 		qdf_mem_zero(opr_rates, sizeof(tSirMacRateSet));
3405 	}
3406 
3407 	if (dot11_cfg.ext_rates.numRates) {
3408 		qdf_mem_copy(ext_rates->rate,
3409 			     dot11_cfg.ext_rates.rate,
3410 			     dot11_cfg.ext_rates.numRates);
3411 		ext_rates->numRates = dot11_cfg.ext_rates.numRates;
3412 	} else {
3413 		qdf_mem_zero(ext_rates, sizeof(tSirMacRateSet));
3414 	}
3415 
3416 	if (sap_ctx->require_h2e) {
3417 		h2e = WLAN_BASIC_RATE_MASK |
3418 			WLAN_BSS_MEMBERSHIP_SELECTOR_SAE_H2E;
3419 		if (ext_rates->numRates < SIR_MAC_MAX_NUMBER_OF_RATES) {
3420 			ext_rates->rate[ext_rates->numRates] = h2e;
3421 			ext_rates->numRates++;
3422 			sap_debug("H2E bss membership add to ext support rate");
3423 		} else if (opr_rates->numRates < SIR_MAC_MAX_NUMBER_OF_RATES) {
3424 			opr_rates->rate[opr_rates->numRates] = h2e;
3425 			opr_rates->numRates++;
3426 			sap_debug("H2E bss membership add to support rate");
3427 		} else {
3428 			sap_err("rates full, can not add H2E bss membership");
3429 		}
3430 	}
3431 	sap_dfs_set_current_channel(sap_ctx);
3432 	/* Reset radar found flag before start sap, the flag will
3433 	 * be set when radar found in CAC wait.
3434 	 */
3435 	sap_ctx->sap_radar_found_status = false;
3436 
3437 	sap_debug("session: %d", sap_ctx->sessionId);
3438 
3439 	qdf_status = sme_start_bss(mac_handle, sap_ctx->sessionId,
3440 				   &sap_ctx->sap_bss_cfg);
3441 	if (!QDF_IS_STATUS_SUCCESS(qdf_status))
3442 		sap_err("Failed to issue sme_roam_connect");
3443 
3444 	return qdf_status;
3445 }
3446 
3447 /**
3448  * sap_fsm_cac_start() - start cac wait timer
3449  * @sap_ctx: SAP context
3450  * @mac_ctx: global MAC context
3451  * @mac_handle: Opaque handle to the global MAC context
3452  *
3453  * Return: QDF_STATUS
3454  */
3455 static QDF_STATUS sap_fsm_cac_start(struct sap_context *sap_ctx,
3456 				    struct mac_context *mac_ctx,
3457 				    mac_handle_t mac_handle)
3458 {
3459 	if (!mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running) {
3460 		sap_debug("sapdfs: starting dfs cac timer on sapctx[%pK]",
3461 			  sap_ctx);
3462 		sap_start_dfs_cac_timer(sap_ctx);
3463 	}
3464 
3465 	return sap_cac_start_notify(mac_handle);
3466 }
3467 
3468 /**
3469  * sap_fsm_state_init() - utility function called from sap fsm
3470  * @sap_ctx: SAP context
3471  * @sap_event: SAP event buffer
3472  * @mac_ctx: global MAC context
3473  * @mac_handle: Opaque handle to the global MAC context
3474  *
3475  * This function is called for state transition from "SAP_INIT"
3476  *
3477  * Return: QDF_STATUS
3478  */
3479 static QDF_STATUS sap_fsm_state_init(struct sap_context *sap_ctx,
3480 				     struct sap_sm_event *sap_event,
3481 				     struct mac_context *mac_ctx,
3482 				     mac_handle_t mac_handle)
3483 {
3484 	uint32_t msg = sap_event->event;
3485 	QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
3486 
3487 	if (msg == eSAP_HDD_START_INFRA_BSS) {
3488 		/* init dfs channel nol */
3489 		sap_init_dfs_channel_nol_list(sap_ctx);
3490 
3491 		/*
3492 		 * Perform sme_ScanRequest. This scan request is post start bss
3493 		 * request so, set the third to false.
3494 		 */
3495 		qdf_status = sap_validate_chan(sap_ctx, false, true);
3496 		if (QDF_IS_STATUS_ERROR(qdf_status)) {
3497 			sap_err("vdev %d: channel is not valid!",
3498 				sap_ctx->vdev_id);
3499 			goto exit;
3500 		}
3501 
3502 		qdf_status = sap_goto_starting(sap_ctx, sap_event,
3503 					       mac_ctx, mac_handle);
3504 		if (QDF_IS_STATUS_ERROR(qdf_status))
3505 			sap_err("vdev %d: sap_goto_starting failed",
3506 				sap_ctx->vdev_id);
3507 	} else {
3508 		sap_err("sap_fsm: vdev %d: SAP_INIT, invalid event %d",
3509 			sap_ctx->vdev_id, msg);
3510 	}
3511 
3512 exit:
3513 	return qdf_status;
3514 }
3515 
3516 /**
3517  * sap_fsm_handle_radar_during_cac() - uhandle radar event during cac
3518  * @sap_ctx: SAP context
3519  * @mac_ctx: global MAC context
3520  *
3521  * Return: QDF_STATUS
3522  */
3523 static QDF_STATUS sap_fsm_handle_radar_during_cac(struct sap_context *sap_ctx,
3524 						  struct mac_context *mac_ctx)
3525 {
3526 	uint8_t intf;
3527 
3528 	if (mac_ctx->sap.SapDfsInfo.target_chan_freq) {
3529 		if (sap_phymode_is_eht(sap_ctx->phyMode))
3530 			wlan_reg_set_create_punc_bitmap(&sap_ctx->ch_params,
3531 							true);
3532 		wlan_reg_set_channel_params_for_pwrmode(mac_ctx->pdev,
3533 				    mac_ctx->sap.SapDfsInfo.target_chan_freq, 0,
3534 				    &sap_ctx->ch_params, REG_CURRENT_PWR_MODE);
3535 	} else {
3536 		sap_err("Invalid target channel freq %d",
3537 			 mac_ctx->sap.SapDfsInfo.target_chan_freq);
3538 		return QDF_STATUS_E_FAILURE;
3539 	}
3540 
3541 	for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) {
3542 		struct sap_context *t_sap_ctx;
3543 
3544 		t_sap_ctx = mac_ctx->sap.sapCtxList[intf].sap_context;
3545 		if (((QDF_SAP_MODE ==
3546 		      mac_ctx->sap.sapCtxList[intf].sapPersona) ||
3547 		     (QDF_P2P_GO_MODE ==
3548 		      mac_ctx->sap.sapCtxList[intf].sapPersona)) &&
3549 		    t_sap_ctx && t_sap_ctx->fsm_state != SAP_INIT) {
3550 			if (!sap_operating_on_dfs(mac_ctx, t_sap_ctx))
3551 				continue;
3552 			t_sap_ctx->is_chan_change_inprogress = true;
3553 			/*
3554 			 * eSAP_DFS_CHANNEL_CAC_RADAR_FOUND:
3555 			 * A Radar is found on current DFS Channel
3556 			 * while in CAC WAIT period So, do a channel
3557 			 * switch to randomly selected	target channel.
3558 			 * Send the Channel change message to SME/PE.
3559 			 * sap_radar_found_status is set to 1
3560 			 */
3561 			wlansap_channel_change_request(t_sap_ctx,
3562 				mac_ctx->sap.SapDfsInfo.target_chan_freq);
3563 		}
3564 	}
3565 
3566 	return QDF_STATUS_SUCCESS;
3567 }
3568 
3569 /**
3570  * sap_fsm_handle_start_failure() - handle sap start failure
3571  * @sap_ctx: SAP context
3572  * @msg: event msg
3573  * @mac_handle: Opaque handle to the global MAC context
3574  *
3575  * Return: QDF_STATUS
3576  */
3577 static QDF_STATUS sap_fsm_handle_start_failure(struct sap_context *sap_ctx,
3578 					       uint32_t msg,
3579 					       mac_handle_t mac_handle)
3580 {
3581 	QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
3582 
3583 	if (msg == eSAP_HDD_STOP_INFRA_BSS) {
3584 		/*
3585 		 * Stop the CAC timer only in following conditions
3586 		 * single AP: if there is a single AP then stop timer
3587 		 * multiple APs: incase of multiple APs, make sure that
3588 		 * all APs are down.
3589 		 */
3590 		if (!sap_find_valid_concurrent_session(mac_handle)) {
3591 			sap_debug("sapdfs: no sessions are valid, stopping timer");
3592 			sap_stop_dfs_cac_timer(sap_ctx);
3593 		}
3594 		/* Transition from SAP_STARTING to SAP_STOPPING */
3595 		sap_ctx->fsm_state = SAP_STOPPING;
3596 		sap_debug("sap_fsm: vdev %d: SAP_STARTING => SAP_STOPPING, start is in progress",
3597 			  sap_ctx->vdev_id);
3598 		qdf_status = sap_goto_stopping(sap_ctx);
3599 	} else {
3600 		/*
3601 		 * Transition from SAP_STARTING to SAP_INIT
3602 		 * (both without substates)
3603 		 */
3604 		sap_ctx->fsm_state = SAP_INIT;
3605 		sap_debug("sap_fsm: vdev %d: SAP_STARTING => SAP_INIT",
3606 			  sap_ctx->vdev_id);
3607 		qdf_status = sap_signal_hdd_event(sap_ctx, NULL,
3608 						  eSAP_START_BSS_EVENT,
3609 						  (void *)
3610 						  eSAP_STATUS_FAILURE);
3611 		qdf_status = sap_goto_init(sap_ctx);
3612 	}
3613 
3614 	return qdf_status;
3615 }
3616 
3617 /**
3618  * sap_propagate_cac_events() - Indicate CAC START/END event
3619  * @sap_ctx: SAP context
3620  *
3621  * This function is to indicate CAC START/END event if CAC process
3622  * is skipped.
3623  *
3624  * Return: void
3625  */
3626 static void sap_propagate_cac_events(struct sap_context *sap_ctx)
3627 {
3628 	QDF_STATUS qdf_status;
3629 
3630 	qdf_status = sap_signal_hdd_event(sap_ctx, NULL,
3631 					  eSAP_DFS_CAC_START,
3632 					  (void *)
3633 					  eSAP_STATUS_SUCCESS);
3634 	if (qdf_status != QDF_STATUS_SUCCESS) {
3635 		sap_err("Failed to indicate CAC START vdev %d",
3636 			sap_ctx->sessionId);
3637 		return;
3638 	}
3639 
3640 	qdf_status = sap_signal_hdd_event(sap_ctx, NULL,
3641 					  eSAP_DFS_CAC_END,
3642 					  (void *)
3643 					  eSAP_STATUS_SUCCESS);
3644 	if (qdf_status != QDF_STATUS_SUCCESS) {
3645 		sap_debug("Failed to indicate CAC End vdev %d",
3646 			  sap_ctx->sessionId);
3647 	}
3648 }
3649 
3650 static void sap_check_and_update_vdev_ch_params(struct sap_context *sap_ctx)
3651 {
3652 	struct wlan_channel *chan;
3653 	enum phy_ch_width orig_ch_width;
3654 
3655 	chan = wlan_vdev_get_active_channel(sap_ctx->vdev);
3656 	if (!chan) {
3657 		sap_debug("Couldn't get vdev active channel");
3658 		return;
3659 	}
3660 	if (sap_ctx->ch_params.ch_width == chan->ch_width)
3661 		return;
3662 
3663 	orig_ch_width = sap_ctx->ch_params.ch_width;
3664 
3665 	sap_ctx->ch_params.ch_width = chan->ch_width;
3666 	sap_ctx->ch_params.center_freq_seg0 = chan->ch_freq_seg1;
3667 	sap_ctx->ch_params.center_freq_seg1 = chan->ch_freq_seg2;
3668 	sap_ctx->ch_params.mhz_freq_seg0 = chan->ch_cfreq1;
3669 	sap_ctx->ch_params.mhz_freq_seg1 = chan->ch_cfreq2;
3670 
3671 	if (WLAN_REG_IS_24GHZ_CH_FREQ(sap_ctx->chan_freq) &&
3672 	    (chan->ch_width == CH_WIDTH_40MHZ)) {
3673 		if (sap_ctx->chan_freq < chan->ch_freq_seg1)
3674 			sap_ctx->ch_params.sec_ch_offset = LOW_PRIMARY_CH;
3675 		else
3676 			sap_ctx->ch_params.sec_ch_offset = HIGH_PRIMARY_CH;
3677 	}
3678 	sap_debug("updated BW %d -> %d", orig_ch_width,
3679 		  sap_ctx->ch_params.ch_width);
3680 }
3681 
3682 static qdf_freq_t sap_get_safe_channel_freq(struct sap_context *sap_ctx)
3683 {
3684 	qdf_freq_t freq;
3685 
3686 	freq = wlan_pre_cac_get_freq_before_pre_cac(sap_ctx->vdev);
3687 	if (!freq)
3688 		freq = wlansap_get_safe_channel_from_pcl_and_acs_range(
3689 								sap_ctx,
3690 								NULL);
3691 
3692 	sap_debug("new selected freq %d as target chan as current freq unsafe %d",
3693 		  freq, sap_ctx->chan_freq);
3694 
3695 	return freq;
3696 }
3697 
3698 /**
3699  * sap_fsm_send_csa_restart_req() - send csa start event
3700  * @mac_ctx: mac ctx
3701  * @sap_ctx: SAP context
3702  *
3703  * Return: QDF_STATUS
3704  */
3705 static inline QDF_STATUS
3706 sap_fsm_send_csa_restart_req(struct mac_context *mac_ctx,
3707 			     struct sap_context *sap_ctx)
3708 {
3709 	QDF_STATUS status;
3710 
3711 	status = policy_mgr_check_and_set_hw_mode_for_channel_switch(
3712 				mac_ctx->psoc, sap_ctx->sessionId,
3713 				mac_ctx->sap.SapDfsInfo.target_chan_freq,
3714 				POLICY_MGR_UPDATE_REASON_CHANNEL_SWITCH_SAP);
3715 
3716 	/*
3717 	 * If hw_mode_status is QDF_STATUS_E_FAILURE, mean HW
3718 	 * mode change was required but driver failed to set HW
3719 	 * mode so ignore CSA for the channel.
3720 	 */
3721 	if (status == QDF_STATUS_E_FAILURE) {
3722 		sap_err("HW change required but failed to set hw mode");
3723 		return status;
3724 	}
3725 
3726 	/*
3727 	 * If hw_mode_status is QDF_STATUS_SUCCESS mean HW mode
3728 	 * change was required and was successfully requested so
3729 	 * the channel switch will continue after HW mode change
3730 	 * completion.
3731 	 */
3732 	if (QDF_IS_STATUS_SUCCESS(status)) {
3733 		sap_info("Channel change will continue after HW mode change");
3734 		return QDF_STATUS_SUCCESS;
3735 	}
3736 
3737 	return sme_csa_restart(mac_ctx, sap_ctx->sessionId);
3738 }
3739 
3740 /**
3741  * sap_fsm_validate_and_change_channel() - handle channel Avoid event event
3742  *                                         or channel list update during cac
3743  * @mac_ctx: global MAC context
3744  * @sap_ctx: SAP context
3745  *
3746  * Return: QDF_STATUS
3747  */
3748 static void sap_fsm_validate_and_change_channel(struct mac_context *mac_ctx,
3749 						struct sap_context *sap_ctx)
3750 {
3751 	qdf_freq_t target_chan_freq;
3752 	struct ch_params ch_params = {0};
3753 	QDF_STATUS status;
3754 	enum phy_ch_width target_bw = sap_ctx->ch_params.ch_width;
3755 
3756 	if (((!sap_ctx->acs_cfg || !sap_ctx->acs_cfg->acs_mode) &&
3757 	     (!policy_mgr_restrict_sap_on_unsafe_chan(mac_ctx->psoc) ||
3758 	      target_psoc_get_sap_coex_fixed_chan_cap(
3759 		      wlan_psoc_get_tgt_if_handle(mac_ctx->psoc)))) ||
3760 	    (policy_mgr_is_sap_freq_allowed(mac_ctx->psoc, sap_ctx->chan_freq) &&
3761 	     !wlan_reg_is_disable_for_pwrmode(mac_ctx->pdev, sap_ctx->chan_freq,
3762 					      REG_CURRENT_PWR_MODE)))
3763 		return;
3764 
3765 	/*
3766 	 * The selected channel is not safe channel. Hence,
3767 	 * change the sap channel to a safe channel.
3768 	 */
3769 	target_chan_freq = sap_get_safe_channel_freq(sap_ctx);
3770 	ch_params.ch_width = target_bw;
3771 	target_bw = wlansap_get_csa_chanwidth_from_phymode(
3772 			sap_ctx, target_chan_freq, &ch_params);
3773 	sap_debug("sap vdev %d change to safe ch freq %d bw %d from unsafe %d",
3774 		  sap_ctx->sessionId, target_chan_freq, target_bw,
3775 		  sap_ctx->chan_freq);
3776 	status = wlansap_set_channel_change_with_csa(
3777 			sap_ctx, target_chan_freq, target_bw, false);
3778 	if (QDF_IS_STATUS_ERROR(status))
3779 		sap_err("SAP set channel failed for freq: %d, bw: %d",
3780 			target_chan_freq, target_bw);
3781 }
3782 
3783 /**
3784  * sap_fsm_state_starting() - utility function called from sap fsm
3785  * @sap_ctx: SAP context
3786  * @sap_event: SAP event buffer
3787  * @mac_ctx: global MAC context
3788  * @mac_handle: Opaque handle to the global MAC context
3789  *
3790  * This function is called for state transition from "SAP_STARTING"
3791  *
3792  * Return: QDF_STATUS
3793  */
3794 static QDF_STATUS sap_fsm_state_starting(struct sap_context *sap_ctx,
3795 					 struct sap_sm_event *sap_event,
3796 					 struct mac_context *mac_ctx,
3797 					 mac_handle_t mac_handle)
3798 {
3799 	uint32_t msg = sap_event->event;
3800 	struct csr_roam_info *roam_info =
3801 		(struct csr_roam_info *) (sap_event->params);
3802 	tSapDfsInfo *sap_dfs_info;
3803 	QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
3804 	uint8_t is_dfs = false;
3805 	uint32_t sap_chan_freq;
3806 	uint32_t ch_cfreq1 = 0;
3807 	enum reg_wifi_band band;
3808 	eSapDfsCACState_t cac_state = eSAP_DFS_DO_NOT_SKIP_CAC;
3809 
3810 	if (msg == eSAP_MAC_START_BSS_SUCCESS) {
3811 		/*
3812 		 * Update sap_ctx->ch_params from vdev to make up with any BW
3813 		 * change in lower layer
3814 		 */
3815 		sap_check_and_update_vdev_ch_params(sap_ctx);
3816 
3817 		/*
3818 		 * Transition from SAP_STARTING to SAP_STARTED
3819 		 * (both without substates)
3820 		 */
3821 		sap_ctx->fsm_state = SAP_STARTED;
3822 		sap_debug("sap_fsm: vdev %d: SAP_STARTING => SAP_STARTED, freq %d ch_width %d",
3823 			  sap_ctx->vdev_id, sap_ctx->chan_freq,
3824 			  sap_ctx->ch_params.ch_width);
3825 
3826 		if (sap_ctx->is_chan_change_inprogress) {
3827 			/* SAP channel change request processing is completed */
3828 			qdf_status = sap_signal_hdd_event(sap_ctx, roam_info,
3829 						eSAP_CHANNEL_CHANGE_EVENT,
3830 						(void *)eSAP_STATUS_SUCCESS);
3831 			sap_ctx->is_chan_change_inprogress = false;
3832 		} else {
3833 			sap_debug("vdev %d notify hostapd about chan freq selection: %d",
3834 				  sap_ctx->vdev_id, sap_ctx->chan_freq);
3835 			qdf_status =
3836 				sap_signal_hdd_event(sap_ctx, roam_info,
3837 						     eSAP_CHANNEL_CHANGE_EVENT,
3838 						     (void *)eSAP_STATUS_SUCCESS);
3839 			/* Action code for transition */
3840 			qdf_status = sap_signal_hdd_event(sap_ctx, roam_info,
3841 					eSAP_START_BSS_EVENT,
3842 					(void *) eSAP_STATUS_SUCCESS);
3843 		}
3844 		sap_chan_freq = sap_ctx->chan_freq;
3845 		band = wlan_reg_freq_to_band(sap_ctx->chan_freq);
3846 		if (sap_ctx->ch_params.center_freq_seg1)
3847 			ch_cfreq1 = wlan_reg_chan_band_to_freq(
3848 					mac_ctx->pdev,
3849 					sap_ctx->ch_params.center_freq_seg1,
3850 					BIT(band));
3851 
3852 		/*
3853 		 * The upper layers have been informed that AP is up and
3854 		 * running, however, the AP is still not beaconing, until
3855 		 * CAC is done if the operating channel is DFS
3856 		 */
3857 		if (sap_ctx->ch_params.ch_width == CH_WIDTH_160MHZ) {
3858 			struct ch_params ch_params = {0};
3859 
3860 			wlan_reg_set_create_punc_bitmap(&ch_params, true);
3861 			ch_params.ch_width = CH_WIDTH_160MHZ;
3862 			is_dfs =
3863 			wlan_reg_get_5g_bonded_channel_state_for_pwrmode(mac_ctx->pdev,
3864 									 sap_chan_freq,
3865 									 &ch_params,
3866 									 REG_CURRENT_PWR_MODE) ==
3867 			CHANNEL_STATE_DFS;
3868 		} else if (sap_ctx->ch_params.ch_width == CH_WIDTH_80P80MHZ) {
3869 			if (wlan_reg_get_channel_state_for_pwrmode(
3870 							mac_ctx->pdev,
3871 							sap_chan_freq,
3872 							REG_CURRENT_PWR_MODE) ==
3873 			    CHANNEL_STATE_DFS ||
3874 			    wlan_reg_get_channel_state_for_pwrmode(
3875 							mac_ctx->pdev,
3876 							ch_cfreq1,
3877 							REG_CURRENT_PWR_MODE) ==
3878 					CHANNEL_STATE_DFS)
3879 				is_dfs = true;
3880 		} else {
3881 			/* Indoor channels are also marked DFS, therefore
3882 			 * check if the channel has REGULATORY_CHAN_RADAR
3883 			 * channel flag to identify if the channel is DFS
3884 			 */
3885 			if (wlan_reg_is_dfs_for_freq(mac_ctx->pdev,
3886 						     sap_chan_freq))
3887 				is_dfs = true;
3888 		}
3889 		if (WLAN_REG_IS_6GHZ_CHAN_FREQ(sap_ctx->chan_freq))
3890 			is_dfs = false;
3891 
3892 		sap_debug("vdev %d freq %d, is_dfs %d", sap_ctx->vdev_id,
3893 			  sap_ctx->chan_freq, is_dfs);
3894 		if (is_dfs) {
3895 			sap_dfs_info = &mac_ctx->sap.SapDfsInfo;
3896 			if (sap_plus_sap_cac_skip(mac_ctx, sap_ctx,
3897 						  sap_chan_freq))
3898 				cac_state = eSAP_DFS_SKIP_CAC;
3899 			if ((false == sap_dfs_info->ignore_cac) &&
3900 			    (cac_state == eSAP_DFS_DO_NOT_SKIP_CAC) &&
3901 			    !wlan_pre_cac_complete_get(sap_ctx->vdev) &&
3902 			    policy_mgr_get_dfs_master_dynamic_enabled(
3903 					mac_ctx->psoc,
3904 					sap_ctx->sessionId)) {
3905 				sap_ctx->fsm_state = SAP_STARTING;
3906 				sap_debug("sap_fsm: vdev %d: SAP_STARTED => SAP_STARTING to start cac timer",
3907 					  sap_ctx->vdev_id);
3908 				qdf_status = sap_fsm_cac_start(sap_ctx, mac_ctx,
3909 							       mac_handle);
3910 			} else {
3911 				sap_debug("vdev %d skip cac timer",
3912 					  sap_ctx->vdev_id);
3913 				sap_ctx->sap_radar_found_status = false;
3914 				/*
3915 				 * If hostapd starts AP on dfs channel,
3916 				 * hostapd will wait for CAC START/CAC END
3917 				 * event and finish AP start process.
3918 				 * If we skip CAC timer, we will need to
3919 				 * indicate the CAC event even though driver
3920 				 * doesn't perform CAC.
3921 				 */
3922 				sap_propagate_cac_events(sap_ctx);
3923 
3924 				wlansap_start_beacon_req(sap_ctx);
3925 			}
3926 		}
3927 		/*
3928 		 * During CSA, it might be possible that ch avoidance event to
3929 		 * avoid the sap frequency is received. So, check after CSA,
3930 		 * whether sap frequency is safe if not restart sap to a safe
3931 		 * channel.
3932 		 */
3933 		sap_fsm_validate_and_change_channel(mac_ctx, sap_ctx);
3934 	} else if (msg == eSAP_MAC_START_FAILS ||
3935 		 msg == eSAP_HDD_STOP_INFRA_BSS) {
3936 			qdf_status = sap_fsm_handle_start_failure(sap_ctx, msg,
3937 								  mac_handle);
3938 	} else if (msg == eSAP_OPERATING_CHANNEL_CHANGED) {
3939 		/* The operating channel has changed, update hostapd */
3940 		sap_ctx->chan_freq = mac_ctx->sap.SapDfsInfo.target_chan_freq;
3941 
3942 		sap_ctx->fsm_state = SAP_STARTED;
3943 		sap_debug("sap_fsm: vdev %d: SAP_STARTING => SAP_STARTED",
3944 			  sap_ctx->vdev_id);
3945 
3946 		/* Indicate change in the state to upper layers */
3947 		qdf_status = sap_signal_hdd_event(sap_ctx, roam_info,
3948 				  eSAP_START_BSS_EVENT,
3949 				  (void *)eSAP_STATUS_SUCCESS);
3950 	} else if (msg == eSAP_DFS_CHANNEL_CAC_RADAR_FOUND) {
3951 		qdf_status = sap_fsm_handle_radar_during_cac(sap_ctx, mac_ctx);
3952 	} else if (msg == eSAP_DFS_CHANNEL_CAC_END) {
3953 		if (sap_ctx->vdev &&
3954 		    wlan_util_vdev_mgr_get_cac_timeout_for_vdev(sap_ctx->vdev)) {
3955 			qdf_status = sap_cac_end_notify(mac_handle, roam_info);
3956 		} else {
3957 			sap_debug("vdev %d cac duration is zero",
3958 				  sap_ctx->vdev_id);
3959 			qdf_status = QDF_STATUS_SUCCESS;
3960 		}
3961 	} else if (msg == eSAP_DFS_CHANNEL_CAC_START) {
3962 		if (sap_ctx->is_chan_change_inprogress) {
3963 			sap_signal_hdd_event(sap_ctx,
3964 					     NULL,
3965 					     eSAP_CHANNEL_CHANGE_EVENT,
3966 					     (void *)eSAP_STATUS_SUCCESS);
3967 			sap_ctx->is_chan_change_inprogress = false;
3968 		}
3969 		qdf_status = sap_fsm_cac_start(sap_ctx, mac_ctx, mac_handle);
3970 	} else {
3971 		sap_err("sap_fsm: vdev %d: SAP_STARTING, invalid event %d",
3972 			sap_ctx->vdev_id, msg);
3973 	}
3974 
3975 	return qdf_status;
3976 }
3977 
3978 /**
3979  * sap_fsm_state_started() - utility function called from sap fsm
3980  * @sap_ctx: SAP context
3981  * @sap_event: SAP event buffer
3982  * @mac_ctx: global MAC context
3983  *
3984  * This function is called for state transition from "SAP_STARTED"
3985  *
3986  * Return: QDF_STATUS
3987  */
3988 static QDF_STATUS sap_fsm_state_started(struct sap_context *sap_ctx,
3989 					struct sap_sm_event *sap_event,
3990 					struct mac_context *mac_ctx)
3991 {
3992 	uint32_t msg = sap_event->event;
3993 	QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
3994 
3995 	if (msg == eSAP_HDD_STOP_INFRA_BSS) {
3996 		/*
3997 		 * Transition from SAP_STARTED to SAP_STOPPING
3998 		 * (both without substates)
3999 		 */
4000 		sap_ctx->fsm_state = SAP_STOPPING;
4001 		sap_debug("sap_fsm: vdev %d: SAP_STARTED => SAP_STOPPING",
4002 			  sap_ctx->vdev_id);
4003 		qdf_status = sap_goto_stopping(sap_ctx);
4004 	} else if (eSAP_DFS_CHNL_SWITCH_ANNOUNCEMENT_START == msg) {
4005 		uint8_t intf;
4006 		if (!mac_ctx->sap.SapDfsInfo.target_chan_freq) {
4007 			sap_err("Invalid target channel freq %d",
4008 				mac_ctx->sap.SapDfsInfo.target_chan_freq);
4009 			return qdf_status;
4010 		}
4011 
4012 		/*
4013 		 * Radar is seen on the current operating channel
4014 		 * send CSA IE for all associated stations
4015 		 * Request for CSA IE transmission
4016 		 */
4017 		for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) {
4018 			struct sap_context *temp_sap_ctx;
4019 
4020 			if (((QDF_SAP_MODE ==
4021 				mac_ctx->sap.sapCtxList[intf].sapPersona) ||
4022 			    (QDF_P2P_GO_MODE ==
4023 				mac_ctx->sap.sapCtxList[intf].sapPersona)) &&
4024 			    mac_ctx->sap.sapCtxList[intf].sap_context) {
4025 				temp_sap_ctx =
4026 				    mac_ctx->sap.sapCtxList[intf].sap_context;
4027 				/*
4028 				 * Radar won't come on non-dfs channel, so
4029 				 * no need to move them
4030 				 */
4031 				if (!sap_operating_on_dfs(
4032 						mac_ctx, temp_sap_ctx)) {
4033 					sap_debug("vdev %d freq %d (state %d) is not DFS or disabled so continue",
4034 						  temp_sap_ctx->sessionId,
4035 						  temp_sap_ctx->chan_freq,
4036 						  wlan_reg_get_channel_state_for_pwrmode(
4037 						  mac_ctx->pdev,
4038 						  temp_sap_ctx->chan_freq,
4039 						  REG_CURRENT_PWR_MODE));
4040 					continue;
4041 				}
4042 				sap_debug("vdev %d switch freq %d -> %d",
4043 					  temp_sap_ctx->sessionId,
4044 					  temp_sap_ctx->chan_freq,
4045 					  mac_ctx->sap.SapDfsInfo.target_chan_freq);
4046 				qdf_status =
4047 				   sap_fsm_send_csa_restart_req(mac_ctx,
4048 								temp_sap_ctx);
4049 			}
4050 		}
4051 	} else {
4052 		sap_err("sap_fsm: vdev %d: SAP_STARTED, invalid event %d",
4053 			sap_ctx->vdev_id, msg);
4054 	}
4055 
4056 	return qdf_status;
4057 }
4058 
4059 /**
4060  * sap_fsm_state_stopping() - utility function called from sap fsm
4061  * @sap_ctx: SAP context
4062  * @sap_event: SAP event buffer
4063  * @mac_ctx: global MAC context
4064  * @mac_handle: Opaque handle to the global MAC context
4065  *
4066  * This function is called for state transition from "SAP_STOPPING"
4067  *
4068  * Return: QDF_STATUS
4069  */
4070 static QDF_STATUS
4071 sap_fsm_state_stopping(struct sap_context *sap_ctx,
4072 		       struct sap_sm_event *sap_event,
4073 		       struct mac_context *mac_ctx,
4074 		       mac_handle_t mac_handle)
4075 {
4076 	uint32_t msg = sap_event->event;
4077 	QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
4078 
4079 	if (msg == eSAP_MAC_READY_FOR_CONNECTIONS) {
4080 		/*
4081 		 * Transition from SAP_STOPPING to SAP_INIT
4082 		 * (both without substates)
4083 		 */
4084 		sap_ctx->fsm_state = SAP_INIT;
4085 		sap_debug("sap_fsm: vdev %d: SAP_STOPPING => SAP_INIT",
4086 			  sap_ctx->vdev_id);
4087 
4088 		/* Close the SME session */
4089 		qdf_status = sap_signal_hdd_event(sap_ctx, NULL,
4090 					eSAP_STOP_BSS_EVENT,
4091 					(void *)eSAP_STATUS_SUCCESS);
4092 	} else if (msg == eSAP_HDD_STOP_INFRA_BSS) {
4093 		/*
4094 		 * In case the SAP is already in stopping case and
4095 		 * we get a STOP request, return success.
4096 		 */
4097 		sap_debug("vdev %d SAP already in Stopping state",
4098 			  sap_ctx->vdev_id);
4099 		qdf_status = QDF_STATUS_SUCCESS;
4100 	} else {
4101 		sap_err("sap_fsm: vdev %d: SAP_STOPPING, invalid event %d",
4102 			sap_ctx->vdev_id, msg);
4103 	}
4104 
4105 	return qdf_status;
4106 }
4107 
4108 /**
4109  * sap_fsm() - SAP statem machine entry function
4110  * @sap_ctx: SAP context
4111  * @sap_event: SAP event
4112  *
4113  * SAP state machine entry function
4114  *
4115  * Return: QDF_STATUS
4116  */
4117 QDF_STATUS sap_fsm(struct sap_context *sap_ctx, struct sap_sm_event *sap_event)
4118 {
4119 	/*
4120 	 * Retrieve the phy link state machine structure
4121 	 * from the sap_ctx value
4122 	 * state var that keeps track of state machine
4123 	 */
4124 	enum sap_fsm_state state_var = sap_ctx->fsm_state;
4125 	uint32_t msg = sap_event->event; /* State machine input event message */
4126 	QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
4127 	struct mac_context *mac_ctx;
4128 	mac_handle_t mac_handle;
4129 
4130 	mac_ctx = sap_get_mac_context();
4131 	if (!mac_ctx) {
4132 		sap_err("Invalid MAC context");
4133 		return QDF_STATUS_E_FAILURE;
4134 	}
4135 	mac_handle = MAC_HANDLE(mac_ctx);
4136 
4137 	sap_debug("vdev %d: state %d event %d", sap_ctx->vdev_id, state_var,
4138 		  msg);
4139 
4140 	switch (state_var) {
4141 	case SAP_INIT:
4142 		qdf_status = sap_fsm_state_init(sap_ctx, sap_event,
4143 						mac_ctx, mac_handle);
4144 		break;
4145 
4146 	case SAP_STARTING:
4147 		qdf_status = sap_fsm_state_starting(sap_ctx, sap_event,
4148 						    mac_ctx, mac_handle);
4149 		break;
4150 
4151 	case SAP_STARTED:
4152 		qdf_status = sap_fsm_state_started(sap_ctx, sap_event,
4153 						   mac_ctx);
4154 		break;
4155 
4156 	case SAP_STOPPING:
4157 		qdf_status = sap_fsm_state_stopping(sap_ctx, sap_event,
4158 						    mac_ctx, mac_handle);
4159 		break;
4160 	}
4161 	return qdf_status;
4162 }
4163 
4164 void sap_sort_mac_list(struct qdf_mac_addr *macList, uint16_t size)
4165 {
4166 	uint16_t outer, inner;
4167 	struct qdf_mac_addr temp;
4168 	int32_t nRes = -1;
4169 
4170 	if ((!macList) || (size > MAX_ACL_MAC_ADDRESS)) {
4171 		sap_err("either buffer is NULL or size = %d is more", size);
4172 		return;
4173 	}
4174 
4175 	for (outer = 0; outer < size; outer++) {
4176 		for (inner = 0; inner < size - 1; inner++) {
4177 			nRes =
4178 				qdf_mem_cmp((macList + inner)->bytes,
4179 						 (macList + inner + 1)->bytes,
4180 						 QDF_MAC_ADDR_SIZE);
4181 			if (nRes > 0) {
4182 				qdf_mem_copy(temp.bytes,
4183 					     (macList + inner + 1)->bytes,
4184 					     QDF_MAC_ADDR_SIZE);
4185 				qdf_mem_copy((macList + inner + 1)->bytes,
4186 					     (macList + inner)->bytes,
4187 					     QDF_MAC_ADDR_SIZE);
4188 				qdf_mem_copy((macList + inner)->bytes,
4189 					     temp.bytes, QDF_MAC_ADDR_SIZE);
4190 			}
4191 		}
4192 	}
4193 }
4194 
4195 bool
4196 sap_search_mac_list(struct qdf_mac_addr *macList,
4197 		    uint16_t num_mac, uint8_t *peerMac,
4198 		    uint16_t *index)
4199 {
4200 	int32_t nRes = -1, nStart = 0, nEnd, nMiddle;
4201 
4202 	nEnd = num_mac - 1;
4203 
4204 	if ((!macList) || (num_mac > MAX_ACL_MAC_ADDRESS)) {
4205 		sap_err("either buffer is NULL or size = %d is more", num_mac);
4206 		return false;
4207 	}
4208 
4209 	while (nStart <= nEnd) {
4210 		nMiddle = (nStart + nEnd) / 2;
4211 		nRes =
4212 			qdf_mem_cmp(&macList[nMiddle], peerMac,
4213 					 QDF_MAC_ADDR_SIZE);
4214 
4215 		if (0 == nRes) {
4216 			sap_debug("search SUCC");
4217 			/* "index equals NULL" means the caller does not need the */
4218 			/* index value of the peerMac being searched */
4219 			if (index) {
4220 				*index = (uint16_t)nMiddle;
4221 				sap_debug("index %d", *index);
4222 			}
4223 			return true;
4224 		}
4225 		if (nRes < 0)
4226 			nStart = nMiddle + 1;
4227 		else
4228 			nEnd = nMiddle - 1;
4229 	}
4230 
4231 	sap_debug("search not succ");
4232 	return false;
4233 }
4234 
4235 void sap_add_mac_to_acl(struct qdf_mac_addr *macList,
4236 			uint16_t *size, uint8_t *peerMac)
4237 {
4238 	int32_t nRes = -1;
4239 	int i;
4240 
4241 	sap_debug("add acl entered");
4242 
4243 	if (!macList || *size > MAX_ACL_MAC_ADDRESS) {
4244 		sap_debug("either buffer is NULL or size = %d is incorrect",
4245 			  *size);
4246 		return;
4247 	}
4248 
4249 	for (i = ((*size) - 1); i >= 0; i--) {
4250 		nRes =
4251 			qdf_mem_cmp(&macList[i], peerMac, QDF_MAC_ADDR_SIZE);
4252 		if (nRes > 0) {
4253 			/* Move alphabetically greater mac addresses one index down to allow for insertion
4254 			   of new mac in sorted order */
4255 			qdf_mem_copy((macList + i + 1)->bytes,
4256 				     (macList + i)->bytes, QDF_MAC_ADDR_SIZE);
4257 		} else {
4258 			break;
4259 		}
4260 	}
4261 	/* This should also take care of if the element is the first to be added in the list */
4262 	qdf_mem_copy((macList + i + 1)->bytes, peerMac, QDF_MAC_ADDR_SIZE);
4263 	/* increment the list size */
4264 	(*size)++;
4265 }
4266 
4267 void sap_remove_mac_from_acl(struct qdf_mac_addr *macList,
4268 			     uint16_t *size, uint16_t index)
4269 {
4270 	int i;
4271 
4272 	sap_debug("remove acl entered");
4273 	/*
4274 	 * Return if the list passed is empty. Ideally this should never happen
4275 	 * since this funcn is always called after sap_search_mac_list to get
4276 	 * the index of the mac addr to be removed and this will only get
4277 	 * called if the search is successful. Still no harm in having the check
4278 	 */
4279 	if ((!macList) || (*size == 0) ||
4280 					(*size > MAX_ACL_MAC_ADDRESS)) {
4281 		sap_err("either buffer is NULL or size %d is incorrect",
4282 			 *size);
4283 		return;
4284 	}
4285 	for (i = index; i < ((*size) - 1); i++) {
4286 		/* Move mac addresses starting from "index" passed one index up to delete the void
4287 		   created by deletion of a mac address in ACL */
4288 		qdf_mem_copy((macList + i)->bytes, (macList + i + 1)->bytes,
4289 			     QDF_MAC_ADDR_SIZE);
4290 	}
4291 	/* The last space should be made empty since all mac addresses moved one step up */
4292 	qdf_mem_zero((macList + (*size) - 1)->bytes, QDF_MAC_ADDR_SIZE);
4293 	/* reduce the list size by 1 */
4294 	(*size)--;
4295 }
4296 
4297 void sap_print_acl(struct qdf_mac_addr *macList, uint16_t size)
4298 {
4299 	uint16_t i;
4300 	uint8_t *macArray;
4301 
4302 	sap_debug("print acl entered");
4303 
4304 	if ((!macList) || (size == 0) || (size > MAX_ACL_MAC_ADDRESS)) {
4305 		sap_err("Either buffer is NULL or size %d is incorrect", size);
4306 		return;
4307 	}
4308 
4309 	for (i = 0; i < size; i++) {
4310 		macArray = (macList + i)->bytes;
4311 		sap_debug("** ACL entry %i - " QDF_MAC_ADDR_FMT, i,
4312 			  QDF_MAC_ADDR_REF(macArray));
4313 	}
4314 	return;
4315 }
4316 
4317 QDF_STATUS sap_is_peer_mac_allowed(struct sap_context *sap_ctx,
4318 				   uint8_t *peerMac)
4319 {
4320 	if (eSAP_ALLOW_ALL == sap_ctx->eSapMacAddrAclMode)
4321 		return QDF_STATUS_SUCCESS;
4322 
4323 	if (sap_search_mac_list
4324 		    (sap_ctx->acceptMacList, sap_ctx->nAcceptMac, peerMac, NULL))
4325 		return QDF_STATUS_SUCCESS;
4326 
4327 	if (sap_search_mac_list
4328 		    (sap_ctx->denyMacList, sap_ctx->nDenyMac, peerMac, NULL)) {
4329 		sap_err("Peer " QDF_MAC_ADDR_FMT " in deny list",
4330 			 QDF_MAC_ADDR_REF(peerMac));
4331 		return QDF_STATUS_E_FAILURE;
4332 	}
4333 	/* A new station CAN associate, unless in deny list. Less stringent mode */
4334 	if (eSAP_ACCEPT_UNLESS_DENIED == sap_ctx->eSapMacAddrAclMode)
4335 		return QDF_STATUS_SUCCESS;
4336 
4337 	/* A new station CANNOT associate, unless in accept list. More stringent mode */
4338 	if (eSAP_DENY_UNLESS_ACCEPTED == sap_ctx->eSapMacAddrAclMode) {
4339 		sap_debug("Peer " QDF_MAC_ADDR_FMT
4340 			  " denied, Mac filter mode is eSAP_DENY_UNLESS_ACCEPTED",
4341 			  QDF_MAC_ADDR_REF(peerMac));
4342 		return QDF_STATUS_E_FAILURE;
4343 	}
4344 
4345 	/* The new STA is neither in accept list nor in deny list. In this case, deny the association
4346 	 * but send a wifi event notification indicating the mac address being denied
4347 	 */
4348 	if (eSAP_SUPPORT_ACCEPT_AND_DENY == sap_ctx->eSapMacAddrAclMode) {
4349 		sap_signal_hdd_event(sap_ctx, NULL, eSAP_UNKNOWN_STA_JOIN,
4350 				     (void *) peerMac);
4351 		sap_debug("Peer " QDF_MAC_ADDR_FMT
4352 			  " denied, Mac filter mode is eSAP_SUPPORT_ACCEPT_AND_DENY",
4353 			  QDF_MAC_ADDR_REF(peerMac));
4354 		return QDF_STATUS_E_FAILURE;
4355 	}
4356 	return QDF_STATUS_SUCCESS;
4357 }
4358 
4359 void sap_dump_acs_channel(struct sap_acs_cfg *acs_cfg)
4360 {
4361 	uint32_t buf_len = 0, len = 0, i;
4362 	uint8_t *chan_buff = NULL;
4363 
4364 	/*
4365 	 * Buffer of (num channel * 5) + 1  to consider the 4 char freq
4366 	 * and 1 space after it for each channel and 1 to end the string
4367 	 * with NULL.
4368 	 */
4369 	buf_len = (acs_cfg->ch_list_count * 5) + 1;
4370 	chan_buff = qdf_mem_malloc(buf_len);
4371 	if (!chan_buff)
4372 		return;
4373 
4374 	for (i = 0; i < acs_cfg->ch_list_count; i++)
4375 		len += qdf_scnprintf(chan_buff + len, buf_len - len,
4376 				     " %d", acs_cfg->freq_list[i]);
4377 
4378 	sap_nofl_debug("ACS freq list[%d]:%s",
4379 		       acs_cfg->ch_list_count, chan_buff);
4380 	qdf_mem_free(chan_buff);
4381 }
4382 
4383 #ifdef SOFTAP_CHANNEL_RANGE
4384 /**
4385  * sap_get_freq_list() - get the list of channel frequency
4386  * @sap_ctx: sap context
4387  * @freq_list: pointer to channel list array
4388  * @num_ch: pointer to number of channels.
4389  *
4390  * This function populates the list of channel frequency for scanning.
4391  *
4392  * Return: QDF_STATUS
4393  */
4394 static QDF_STATUS sap_get_freq_list(struct sap_context *sap_ctx,
4395 				    uint32_t **freq_list,
4396 				    uint8_t *num_ch)
4397 {
4398 	uint8_t loop_count;
4399 	uint32_t *list;
4400 	uint8_t ch_count;
4401 	uint8_t dfs_master_enable;
4402 	uint32_t start_ch_freq, band_start_ch;
4403 	uint32_t end_ch_freq, band_end_ch;
4404 	uint32_t en_lte_coex;
4405 	struct mac_context *mac_ctx;
4406 	uint16_t ch_width;
4407 	uint8_t normalize_factor = 100;
4408 	uint32_t chan_freq;
4409 	struct acs_weight *weight_list;
4410 	struct acs_weight_range *range_list;
4411 	bool freq_present_in_list = false;
4412 	uint8_t i;
4413 	bool srd_chan_enabled;
4414 	enum QDF_OPMODE vdev_opmode;
4415 
4416 	mac_ctx = sap_get_mac_context();
4417 	if (!mac_ctx) {
4418 		sap_err("Invalid MAC context");
4419 		*num_ch = 0;
4420 		*freq_list = NULL;
4421 		return QDF_STATUS_E_FAULT;
4422 	}
4423 
4424 	weight_list = mac_ctx->mlme_cfg->acs.normalize_weight_chan;
4425 	range_list = mac_ctx->mlme_cfg->acs.normalize_weight_range;
4426 
4427 	dfs_master_enable = mac_ctx->mlme_cfg->dfs_cfg.dfs_master_capable;
4428 	if (sap_ctx->dfs_mode == ACS_DFS_MODE_DISABLE)
4429 		dfs_master_enable = false;
4430 
4431 	start_ch_freq = sap_ctx->acs_cfg->start_ch_freq;
4432 	end_ch_freq = sap_ctx->acs_cfg->end_ch_freq;
4433 	ch_width = sap_ctx->acs_cfg->ch_width;
4434 
4435 	sap_debug("startChannel %d, EndChannel %d, ch_width %d, HW:%d",
4436 		  start_ch_freq, end_ch_freq, ch_width,
4437 		  sap_ctx->acs_cfg->hw_mode);
4438 
4439 	wlansap_extend_to_acs_range(MAC_HANDLE(mac_ctx),
4440 				    &start_ch_freq, &end_ch_freq,
4441 				    &band_start_ch, &band_end_ch);
4442 
4443 	sap_debug("expanded startChannel %d,EndChannel %d band_start_ch %d, band_end_ch %d",
4444 		  start_ch_freq, end_ch_freq, band_start_ch, band_end_ch);
4445 
4446 	en_lte_coex = mac_ctx->mlme_cfg->sap_cfg.enable_lte_coex;
4447 
4448 	/* Check if LTE coex is enabled and 2.4GHz is selected */
4449 	if (en_lte_coex && (band_start_ch == CHAN_ENUM_2412) &&
4450 	    (band_end_ch == CHAN_ENUM_2484)) {
4451 		/* Set 2.4GHz upper limit to channel 9 for LTE COEX */
4452 		band_end_ch = CHAN_ENUM_2452;
4453 	}
4454 
4455 	/* Allocate the max number of channel supported */
4456 	list = qdf_mem_malloc((NUM_CHANNELS) * sizeof(uint32_t));
4457 	if (!list) {
4458 		*num_ch = 0;
4459 		*freq_list = NULL;
4460 		return QDF_STATUS_E_NOMEM;
4461 	}
4462 
4463 	/* Search for the Active channels in the given range */
4464 	ch_count = 0;
4465 	for (loop_count = band_start_ch; loop_count <= band_end_ch;
4466 	     loop_count++) {
4467 		chan_freq = WLAN_REG_CH_TO_FREQ(loop_count);
4468 
4469 		/* go to next channel if rf_channel is out of range */
4470 		if (start_ch_freq > WLAN_REG_CH_TO_FREQ(loop_count) ||
4471 		    end_ch_freq < WLAN_REG_CH_TO_FREQ(loop_count))
4472 			continue;
4473 		/*
4474 		 * go to next channel if none of these condition pass
4475 		 * - DFS scan enabled and chan not in CHANNEL_STATE_DISABLE
4476 		 * - DFS scan disable but chan in CHANNEL_STATE_ENABLE
4477 		 */
4478 		if (!(((true == mac_ctx->scan.fEnableDFSChnlScan) &&
4479 		      wlan_reg_get_channel_state_from_secondary_list_for_freq(
4480 			mac_ctx->pdev, WLAN_REG_CH_TO_FREQ(loop_count)))
4481 		      ||
4482 		    ((false == mac_ctx->scan.fEnableDFSChnlScan) &&
4483 		     (CHANNEL_STATE_ENABLE ==
4484 		      wlan_reg_get_channel_state_from_secondary_list_for_freq(
4485 			mac_ctx->pdev, WLAN_REG_CH_TO_FREQ(loop_count)))
4486 		     )))
4487 			continue;
4488 
4489 		/* check if the channel is in NOL denylist */
4490 		if (!WLAN_REG_IS_6GHZ_CHAN_FREQ(WLAN_REG_CH_TO_FREQ(
4491 					loop_count))) {
4492 			if (sap_dfs_is_channel_in_nol_list(
4493 					sap_ctx,
4494 					chan_freq,
4495 					PHY_SINGLE_CHANNEL_CENTERED)) {
4496 				sap_debug("Ch freq %d in NOL list", chan_freq);
4497 				continue;
4498 			}
4499 		}
4500 		/* Skip DSRC channels */
4501 		if (wlan_reg_is_dsrc_freq(WLAN_REG_CH_TO_FREQ(loop_count)))
4502 			continue;
4503 
4504 		/*
4505 		 * Skip the channels which are not in ACS config from user
4506 		 * space
4507 		 */
4508 		if (!wlansap_is_channel_present_in_acs_list(
4509 					chan_freq,
4510 					sap_ctx->acs_cfg->freq_list,
4511 					sap_ctx->acs_cfg->ch_list_count))
4512 			continue;
4513 		/* Dont scan DFS channels in case of MCC disallowed
4514 		 * As it can result in SAP starting on DFS channel
4515 		 * resulting  MCC on DFS channel
4516 		 */
4517 		if (wlan_reg_is_dfs_in_secondary_list_for_freq(
4518 					mac_ctx->pdev,
4519 					WLAN_REG_CH_TO_FREQ(loop_count))) {
4520 			if (!dfs_master_enable)
4521 				continue;
4522 			if (wlansap_dcs_is_wlan_interference_mitigation_enabled(
4523 								sap_ctx))
4524 				sap_debug("dfs chan_freq %d added when dcs enabled",
4525 					  WLAN_REG_CH_TO_FREQ(loop_count));
4526 			else if (policy_mgr_disallow_mcc(
4527 					mac_ctx->psoc,
4528 					WLAN_REG_CH_TO_FREQ(loop_count)))
4529 				continue;
4530 			normalize_factor =
4531 				MLME_GET_DFS_CHAN_WEIGHT(
4532 				mac_ctx->mlme_cfg->acs.np_chan_weightage);
4533 			freq_present_in_list = true;
4534 		}
4535 
4536 		vdev_opmode = wlan_vdev_mlme_get_opmode(sap_ctx->vdev);
4537 		wlan_mlme_get_srd_master_mode_for_vdev(mac_ctx->psoc,
4538 						       vdev_opmode,
4539 						       &srd_chan_enabled);
4540 
4541 		if (!srd_chan_enabled &&
4542 		    wlan_reg_is_etsi_srd_chan_for_freq(
4543 					mac_ctx->pdev,
4544 					WLAN_REG_CH_TO_FREQ(loop_count))) {
4545 			sap_debug("vdev opmode %d not allowed on SRD freq %d",
4546 				  vdev_opmode, WLAN_REG_CH_TO_FREQ(loop_count));
4547 			continue;
4548 		}
4549 
4550 		/* Check if the freq is present in range list */
4551 		for (i = 0; i < mac_ctx->mlme_cfg->acs.num_weight_range; i++) {
4552 			if (chan_freq >= range_list[i].start_freq &&
4553 			    chan_freq <= range_list[i].end_freq) {
4554 				normalize_factor =
4555 					range_list[i].normalize_weight;
4556 				sap_debug("Range list, freq %d normalize weight factor %d",
4557 					  chan_freq, normalize_factor);
4558 				freq_present_in_list = true;
4559 			}
4560 		}
4561 
4562 		for (i = 0;
4563 		     i < mac_ctx->mlme_cfg->acs.normalize_weight_num_chan;
4564 		     i++) {
4565 			if (chan_freq == weight_list[i].chan_freq) {
4566 				normalize_factor =
4567 					weight_list[i].normalize_weight;
4568 				sap_debug("freq %d normalize weight factor %d",
4569 					  chan_freq, normalize_factor);
4570 				freq_present_in_list = true;
4571 			}
4572 		}
4573 
4574 		/* This would mean that the user does not want this freq */
4575 		if (freq_present_in_list && !normalize_factor) {
4576 			sap_debug("chan_freq %d ecluded normalize weight 0",
4577 				  chan_freq);
4578 			freq_present_in_list = false;
4579 			continue;
4580 		}
4581 #ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
4582 		if (sap_ctx->acs_cfg->skip_scan_status ==
4583 			eSAP_DO_PAR_ACS_SCAN) {
4584 			uint32_t ch_freq;
4585 
4586 			ch_freq = WLAN_REG_CH_TO_FREQ(loop_count);
4587 			if ((ch_freq >=
4588 				sap_ctx->acs_cfg->skip_scan_range1_stch &&
4589 			      ch_freq <=
4590 				sap_ctx->acs_cfg->skip_scan_range1_endch) ||
4591 			     (ch_freq >=
4592 				sap_ctx->acs_cfg->skip_scan_range2_stch &&
4593 			      ch_freq <=
4594 				sap_ctx->acs_cfg->skip_scan_range2_endch)) {
4595 				list[ch_count] =
4596 					WLAN_REG_CH_TO_FREQ(loop_count);
4597 				ch_count++;
4598 				sap_debug("%d %d added to ACS ch range",
4599 					  ch_count, ch_freq);
4600 			} else {
4601 				sap_debug("%d %d skipped from ACS ch range",
4602 					  ch_count, ch_freq);
4603 			}
4604 		} else {
4605 			list[ch_count] = WLAN_REG_CH_TO_FREQ(loop_count);
4606 			ch_count++;
4607 			sap_debug("%d added to ACS ch range", ch_count);
4608 		}
4609 #else
4610 		list[ch_count] = WLAN_REG_CH_TO_FREQ(loop_count);
4611 		ch_count++;
4612 #endif
4613 	}
4614 	if (!ch_count) {
4615 		sap_info("No active channels present for the current region");
4616 		/*
4617 		 * LTE COEX: channel range outside the restricted 2.4GHz
4618 		 * band limits
4619 		 */
4620 		if (en_lte_coex &&
4621 		    start_ch_freq > WLAN_REG_CH_TO_FREQ(band_end_ch))
4622 			sap_info("SAP can't be started as due to LTE COEX");
4623 	}
4624 
4625 	/* return the channel list and number of channels to scan */
4626 	*num_ch = ch_count;
4627 	if (ch_count != 0) {
4628 		*freq_list = list;
4629 	} else {
4630 		*freq_list = NULL;
4631 		qdf_mem_free(list);
4632 		return QDF_STATUS_SUCCESS;
4633 	}
4634 
4635 	for (loop_count = 0; loop_count < ch_count; loop_count++) {
4636 		sap_ctx->acs_cfg->freq_list[loop_count] = list[loop_count];
4637 	}
4638 	sap_ctx->acs_cfg->ch_list_count = ch_count;
4639 	sap_dump_acs_channel(sap_ctx->acs_cfg);
4640 
4641 	return QDF_STATUS_SUCCESS;
4642 }
4643 #endif
4644 
4645 #ifdef DFS_COMPONENT_ENABLE
4646 qdf_freq_t sap_indicate_radar(struct sap_context *sap_ctx)
4647 {
4648 	qdf_freq_t chan_freq = 0;
4649 	struct mac_context *mac;
4650 
4651 	if (!sap_ctx) {
4652 		sap_err("null sap_ctx");
4653 		return 0;
4654 	}
4655 
4656 	mac = sap_get_mac_context();
4657 	if (!mac) {
4658 		sap_err("Invalid MAC context");
4659 		return 0;
4660 	}
4661 
4662 	/*
4663 	 * SAP needs to generate Channel Switch IE
4664 	 * if the radar is found in the STARTED state
4665 	 */
4666 	if (sap_ctx->fsm_state == SAP_STARTED)
4667 		mac->sap.SapDfsInfo.csaIERequired = true;
4668 
4669 	if (mac->mlme_cfg->dfs_cfg.dfs_disable_channel_switch) {
4670 		mac->sap.SapDfsInfo.new_chanWidth =
4671 					sap_ctx->ch_params.ch_width;
4672 		sap_debug("DFS channel switch disabled, CSA to same ch %d wd %d",
4673 			  sap_ctx->chan_freq, sap_ctx->ch_params.ch_width);
4674 		return sap_ctx->chan_freq;
4675 	}
4676 
4677 	/* set the Radar Found flag in SapDfsInfo */
4678 	sap_ctx->sap_radar_found_status = true;
4679 
4680 	chan_freq = wlan_pre_cac_get_freq_before_pre_cac(sap_ctx->vdev);
4681 	if (chan_freq) {
4682 		sap_info("sapdfs: set chan freq before pre cac %d as target chan",
4683 			 chan_freq);
4684 		return chan_freq;
4685 	}
4686 
4687 	if (sap_ctx->vendor_acs_dfs_lte_enabled && (QDF_STATUS_SUCCESS ==
4688 	    sap_signal_hdd_event(sap_ctx, NULL, eSAP_DFS_NEXT_CHANNEL_REQ,
4689 	    (void *) eSAP_STATUS_SUCCESS)))
4690 		return 0;
4691 
4692 	if (!sap_is_chan_change_needed(sap_ctx))
4693 		return sap_ctx->chan_freq;
4694 
4695 	chan_freq = sap_random_channel_sel(sap_ctx);
4696 	if (!chan_freq)
4697 		sap_signal_hdd_event(sap_ctx, NULL,
4698 		eSAP_DFS_NO_AVAILABLE_CHANNEL, (void *) eSAP_STATUS_SUCCESS);
4699 
4700 	sap_warn("sapdfs: New selected target freq is [%d]", chan_freq);
4701 
4702 	return chan_freq;
4703 }
4704 #endif
4705 
4706 /*
4707  * CAC timer callback function.
4708  * Post eSAP_DFS_CHANNEL_CAC_END event to sap_fsm().
4709  */
4710 void sap_dfs_cac_timer_callback(void *data)
4711 {
4712 	struct sap_context *sap_ctx;
4713 	struct sap_sm_event sap_event;
4714 	mac_handle_t mac_handle = data;
4715 	struct mac_context *mac;
4716 
4717 	if (!mac_handle) {
4718 		sap_err("Invalid mac_handle");
4719 		return;
4720 	}
4721 	mac = MAC_CONTEXT(mac_handle);
4722 	sap_ctx = sap_find_cac_wait_session(mac_handle);
4723 	if (!sap_ctx) {
4724 		sap_err("no SAP contexts in wait state");
4725 		return;
4726 	}
4727 
4728 	if (mac->sap.SapDfsInfo.vdev_id != sap_ctx->vdev_id) {
4729 		sap_err("vdev mismatch sap_ctx->vdev_id %d mac->sap.SapDfsInfo.vdev_id %d",
4730 			sap_ctx->vdev_id, mac->sap.SapDfsInfo.vdev_id);
4731 		return;
4732 	}
4733 
4734 	/*
4735 	 * SAP may not be in CAC wait state, when the timer runs out.
4736 	 * if following flag is set, then timer is in initialized state,
4737 	 * destroy timer here.
4738 	 */
4739 	if (mac->sap.SapDfsInfo.is_dfs_cac_timer_running == true) {
4740 		if (!sap_ctx->dfs_cac_offload)
4741 			qdf_mc_timer_destroy(
4742 				&mac->sap.SapDfsInfo.sap_dfs_cac_timer);
4743 		mac->sap.SapDfsInfo.is_dfs_cac_timer_running = false;
4744 		mac->sap.SapDfsInfo.vdev_id = WLAN_INVALID_VDEV_ID;
4745 	}
4746 
4747 	/*
4748 	 * CAC Complete, post eSAP_DFS_CHANNEL_CAC_END to sap_fsm
4749 	 */
4750 	sap_debug("sapdfs: Sending eSAP_DFS_CHANNEL_CAC_END for target_chan_freq = %d on sapctx[%pK]",
4751 		  sap_ctx->chan_freq, sap_ctx);
4752 
4753 	sap_event.event = eSAP_DFS_CHANNEL_CAC_END;
4754 	sap_event.params = 0;
4755 	sap_event.u1 = 0;
4756 	sap_event.u2 = 0;
4757 
4758 	sap_fsm(sap_ctx, &sap_event);
4759 }
4760 
4761 /*
4762  * Function to stop the DFS CAC Timer
4763  */
4764 static int sap_stop_dfs_cac_timer(struct sap_context *sap_ctx)
4765 {
4766 	struct mac_context *mac;
4767 
4768 	if (!sap_ctx)
4769 		return 0;
4770 
4771 	mac = sap_get_mac_context();
4772 	if (!mac) {
4773 		sap_err("Invalid MAC context");
4774 		return 0;
4775 	}
4776 
4777 	if (mac->sap.SapDfsInfo.vdev_id != sap_ctx->vdev_id) {
4778 		sap_err("Invalid vdev Id sap_ctx_vdev_id %d mac_ctx vdev id %d",
4779 			sap_ctx->vdev_id, mac->sap.SapDfsInfo.vdev_id);
4780 		return 0;
4781 	}
4782 
4783 	if (sap_ctx->dfs_cac_offload) {
4784 		mac->sap.SapDfsInfo.is_dfs_cac_timer_running = 0;
4785 		mac->sap.SapDfsInfo.vdev_id = WLAN_INVALID_VDEV_ID;
4786 		return 0;
4787 	}
4788 
4789 	if (QDF_TIMER_STATE_RUNNING !=
4790 	    qdf_mc_timer_get_current_state(&mac->sap.SapDfsInfo.
4791 					   sap_dfs_cac_timer)) {
4792 		return 0;
4793 	}
4794 
4795 	qdf_mc_timer_stop(&mac->sap.SapDfsInfo.sap_dfs_cac_timer);
4796 	mac->sap.SapDfsInfo.is_dfs_cac_timer_running = 0;
4797 	mac->sap.SapDfsInfo.vdev_id = WLAN_INVALID_VDEV_ID;
4798 	qdf_mc_timer_destroy(&mac->sap.SapDfsInfo.sap_dfs_cac_timer);
4799 
4800 	return 0;
4801 }
4802 
4803 /*
4804  * Function to start the DFS CAC Timer
4805  * when SAP is started on a DFS channel
4806  */
4807 static int sap_start_dfs_cac_timer(struct sap_context *sap_ctx)
4808 {
4809 	QDF_STATUS status;
4810 	uint32_t cac_dur;
4811 	struct mac_context *mac;
4812 	enum dfs_reg dfs_region;
4813 
4814 	if (!sap_ctx) {
4815 		sap_err("null sap_ctx");
4816 		return 0;
4817 	}
4818 
4819 	mac = sap_get_mac_context();
4820 	if (!mac) {
4821 		sap_err("Invalid MAC context");
4822 		return 0;
4823 	}
4824 	/* start time only when is_dfs_cac_timer_running is not running */
4825 	if (mac->sap.SapDfsInfo.is_dfs_cac_timer_running) {
4826 		sap_err("Invalid state is_dfs_cac_timer_running");
4827 		return 0;
4828 	}
4829 
4830 	if (sap_ctx->dfs_cac_offload) {
4831 		sap_debug("cac timer offloaded to firmware");
4832 		mac->sap.SapDfsInfo.is_dfs_cac_timer_running = true;
4833 		mac->sap.SapDfsInfo.vdev_id = sap_ctx->vdev_id;
4834 		return 1;
4835 	}
4836 
4837 	sap_get_cac_dur_dfs_region(sap_ctx, &cac_dur, &dfs_region,
4838 				   sap_ctx->chan_freq, &sap_ctx->ch_params);
4839 	if (0 == cac_dur)
4840 		return 0;
4841 
4842 #ifdef QCA_WIFI_EMULATION
4843 	cac_dur = cac_dur / 100;
4844 #endif
4845 	sap_debug("sapdfs: SAP_DFS_CHANNEL_CAC_START on CH freq %d, CAC_DUR-%d sec",
4846 		  sap_ctx->chan_freq, cac_dur / 1000);
4847 
4848 	qdf_mc_timer_init(&mac->sap.SapDfsInfo.sap_dfs_cac_timer,
4849 			  QDF_TIMER_TYPE_SW,
4850 			  sap_dfs_cac_timer_callback, MAC_HANDLE(mac));
4851 
4852 	/* Start the CAC timer */
4853 	status = qdf_mc_timer_start(&mac->sap.SapDfsInfo.sap_dfs_cac_timer,
4854 			cac_dur);
4855 	if (QDF_IS_STATUS_ERROR(status)) {
4856 		sap_err("failed to start cac timer");
4857 		goto destroy_timer;
4858 	}
4859 
4860 	mac->sap.SapDfsInfo.is_dfs_cac_timer_running = true;
4861 	mac->sap.SapDfsInfo.vdev_id = sap_ctx->vdev_id;
4862 
4863 	return 0;
4864 
4865 destroy_timer:
4866 	mac->sap.SapDfsInfo.is_dfs_cac_timer_running = false;
4867 	mac->sap.SapDfsInfo.vdev_id = WLAN_INVALID_VDEV_ID;
4868 	qdf_mc_timer_destroy(&mac->sap.SapDfsInfo.sap_dfs_cac_timer);
4869 
4870 	return 1;
4871 }
4872 
4873 /*
4874  * This function initializes the NOL list
4875  * parameters required to track the radar
4876  * found DFS channels in the current Reg. Domain .
4877  */
4878 QDF_STATUS sap_init_dfs_channel_nol_list(struct sap_context *sap_ctx)
4879 {
4880 	struct mac_context *mac;
4881 
4882 	if (!sap_ctx) {
4883 		sap_err("Invalid SAP context");
4884 		return QDF_STATUS_E_FAULT;
4885 	}
4886 
4887 	mac = sap_get_mac_context();
4888 	if (!mac) {
4889 		sap_err("Invalid MAC context");
4890 		return QDF_STATUS_E_FAULT;
4891 	}
4892 
4893 	utils_dfs_init_nol(mac->pdev);
4894 
4895 	return QDF_STATUS_SUCCESS;
4896 }
4897 
4898 /**
4899  * sap_is_active() - Check SAP active or not by sap_context object
4900  * @sap_ctx: Pointer to the SAP context
4901  *
4902  * Return: true if SAP is active
4903  */
4904 static bool sap_is_active(struct sap_context *sap_ctx)
4905 {
4906 	return sap_ctx->fsm_state != SAP_INIT;
4907 }
4908 
4909 /*
4910  * This function will calculate how many interfaces
4911  * have sap persona and returns total number of sap persona.
4912  */
4913 uint8_t sap_get_total_number_sap_intf(mac_handle_t mac_handle)
4914 {
4915 	struct mac_context *mac = MAC_CONTEXT(mac_handle);
4916 	uint8_t intf = 0;
4917 	uint8_t intf_count = 0;
4918 	struct sap_context *sap_context;
4919 
4920 	for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) {
4921 		if (((QDF_SAP_MODE == mac->sap.sapCtxList[intf].sapPersona)
4922 		    ||
4923 		    (QDF_P2P_GO_MODE == mac->sap.sapCtxList[intf].sapPersona))
4924 		    && mac->sap.sapCtxList[intf].sap_context) {
4925 			sap_context =
4926 				mac->sap.sapCtxList[intf].sap_context;
4927 			if (!sap_is_active(sap_context))
4928 				continue;
4929 			intf_count++;
4930 		}
4931 	}
4932 	return intf_count;
4933 }
4934 
4935 /**
4936  * is_concurrent_sap_ready_for_channel_change() - to check all saps are ready
4937  *						  for channel change
4938  * @mac_handle: Opaque handle to the global MAC context
4939  * @sap_ctx: sap context for which this function has been called
4940  *
4941  * This function will find the concurrent sap context apart from
4942  * passed sap context and return its channel change ready status
4943  *
4944  *
4945  * Return: true if other SAP personas are ready to channel switch else false
4946  */
4947 bool is_concurrent_sap_ready_for_channel_change(mac_handle_t mac_handle,
4948 						struct sap_context *sap_ctx)
4949 {
4950 	struct mac_context *mac = MAC_CONTEXT(mac_handle);
4951 	struct sap_context *sap_context;
4952 	uint8_t intf = 0;
4953 
4954 	for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) {
4955 		if (((QDF_SAP_MODE == mac->sap.sapCtxList[intf].sapPersona)
4956 		    ||
4957 		    (QDF_P2P_GO_MODE == mac->sap.sapCtxList[intf].sapPersona))
4958 		    && mac->sap.sapCtxList[intf].sap_context) {
4959 			sap_context =
4960 				mac->sap.sapCtxList[intf].sap_context;
4961 			if (!sap_is_active(sap_context))
4962 				continue;
4963 			if (sap_context == sap_ctx) {
4964 				sap_err("sapCtx matched [%pK]", sap_ctx);
4965 				continue;
4966 			} else {
4967 				sap_err("concurrent sapCtx[%pK] didn't matche with [%pK]",
4968 					 sap_context, sap_ctx);
4969 				return sap_context->is_sap_ready_for_chnl_chng;
4970 			}
4971 		}
4972 	}
4973 	return false;
4974 }
4975 
4976 /**
4977  * sap_is_conc_sap_doing_scc_dfs() - check if conc SAPs are doing SCC DFS
4978  * @mac_handle: Opaque handle to the global MAC context
4979  * @given_sapctx: current SAP persona's channel
4980  *
4981  * If provided SAP's channel is DFS then Loop through each SAP or GO persona and
4982  * check if other beaconing entity's channel is same DFS channel. If they are
4983  * same then concurrent sap is doing SCC DFS.
4984  *
4985  * Return: true if two or more beaconing entities doing SCC DFS else false
4986  */
4987 bool sap_is_conc_sap_doing_scc_dfs(mac_handle_t mac_handle,
4988 				   struct sap_context *given_sapctx)
4989 {
4990 	struct mac_context *mac = MAC_CONTEXT(mac_handle);
4991 	struct sap_context *sap_ctx;
4992 	uint8_t intf = 0, scc_dfs_counter = 0;
4993 	qdf_freq_t ch_freq;
4994 
4995 	ch_freq = given_sapctx->chan_freq;
4996 	/*
4997 	 * current SAP persona's channel itself is not DFS, so no need to check
4998 	 * what other persona's channel is
4999 	 */
5000 	if (!wlan_reg_is_dfs_for_freq(mac->pdev,
5001 				      ch_freq)) {
5002 		sap_debug("skip this loop as provided channel is non-dfs");
5003 		return false;
5004 	}
5005 
5006 	for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) {
5007 		if ((QDF_SAP_MODE != mac->sap.sapCtxList[intf].sapPersona) &&
5008 		    (QDF_P2P_GO_MODE != mac->sap.sapCtxList[intf].sapPersona))
5009 			continue;
5010 		if (!mac->sap.sapCtxList[intf].sap_context)
5011 			continue;
5012 		sap_ctx = mac->sap.sapCtxList[intf].sap_context;
5013 		if (!sap_is_active(sap_ctx))
5014 			continue;
5015 		/* if same SAP contexts then skip to next context */
5016 		if (sap_ctx == given_sapctx)
5017 			continue;
5018 		if (given_sapctx->chan_freq == sap_ctx->chan_freq)
5019 			scc_dfs_counter++;
5020 	}
5021 
5022 	/* Found atleast two of the beaconing entities doing SCC DFS */
5023 	if (scc_dfs_counter)
5024 		return true;
5025 
5026 	return false;
5027 }
5028 
5029 /**
5030  * sap_build_start_bss_config() - Fill the start bss request for SAP
5031  * @sap_bss_cfg: start bss config
5032  * @config: sap config
5033  *
5034  * This function fills the start bss request for SAP
5035  *
5036  * Return: None
5037  */
5038 void
5039 sap_build_start_bss_config(struct start_bss_config *sap_bss_cfg,
5040 			   struct sap_config *config)
5041 {
5042 	qdf_mem_zero(&sap_bss_cfg->ssId.ssId, sizeof(sap_bss_cfg->ssId.ssId));
5043 	sap_bss_cfg->ssId.length = config->SSIDinfo.ssid.length;
5044 	qdf_mem_copy(&sap_bss_cfg->ssId.ssId, config->SSIDinfo.ssid.ssId,
5045 		     config->SSIDinfo.ssid.length);
5046 
5047 	if (config->authType == eSAP_SHARED_KEY)
5048 		sap_bss_cfg->authType = eSIR_SHARED_KEY;
5049 	else if (config->authType == eSAP_OPEN_SYSTEM)
5050 		sap_bss_cfg->authType = eSIR_OPEN_SYSTEM;
5051 	else
5052 		sap_bss_cfg->authType = eSIR_AUTO_SWITCH;
5053 
5054 	sap_bss_cfg->beaconInterval = (uint16_t)config->beacon_int;
5055 	sap_bss_cfg->privacy = config->privacy;
5056 	sap_bss_cfg->ssidHidden = config->SSIDinfo.ssidHidden;
5057 	sap_bss_cfg->dtimPeriod = config->dtim_period;
5058 	sap_bss_cfg->wps_state = config->wps_state;
5059 	sap_bss_cfg->beacon_tx_rate = config->beacon_tx_rate;
5060 
5061 	/* RSNIE */
5062 	sap_bss_cfg->rsnIE.length = config->RSNWPAReqIELength;
5063 	if (config->RSNWPAReqIELength)
5064 		qdf_mem_copy(sap_bss_cfg->rsnIE.rsnIEdata,
5065 			     config->RSNWPAReqIE, config->RSNWPAReqIELength);
5066 
5067 	/* Probe response IE */
5068 	if (config->probeRespIEsBufferLen > 0 &&
5069 	    config->pProbeRespIEsBuffer) {
5070 		sap_bss_cfg->add_ie_params.probeRespDataLen =
5071 						config->probeRespIEsBufferLen;
5072 		sap_bss_cfg->add_ie_params.probeRespData_buff =
5073 						config->pProbeRespIEsBuffer;
5074 	} else {
5075 		sap_bss_cfg->add_ie_params.probeRespDataLen = 0;
5076 		sap_bss_cfg->add_ie_params.probeRespData_buff = NULL;
5077 	}
5078 
5079 	/*assoc resp IE */
5080 	if (config->assocRespIEsLen > 0 && config->pAssocRespIEsBuffer) {
5081 		sap_bss_cfg->add_ie_params.assocRespDataLen =
5082 						config->assocRespIEsLen;
5083 		sap_bss_cfg->add_ie_params.assocRespData_buff =
5084 						config->pAssocRespIEsBuffer;
5085 	} else {
5086 		sap_bss_cfg->add_ie_params.assocRespDataLen = 0;
5087 		sap_bss_cfg->add_ie_params.assocRespData_buff = NULL;
5088 	}
5089 
5090 	if (config->probeRespBcnIEsLen > 0 &&
5091 	    config->pProbeRespBcnIEsBuffer) {
5092 		sap_bss_cfg->add_ie_params.probeRespBCNDataLen =
5093 						config->probeRespBcnIEsLen;
5094 		sap_bss_cfg->add_ie_params.probeRespBCNData_buff =
5095 						config->pProbeRespBcnIEsBuffer;
5096 	} else {
5097 		sap_bss_cfg->add_ie_params.probeRespBCNDataLen = 0;
5098 		sap_bss_cfg->add_ie_params.probeRespBCNData_buff = NULL;
5099 	}
5100 
5101 	if (config->supported_rates.numRates) {
5102 		qdf_mem_copy(sap_bss_cfg->operationalRateSet.rate,
5103 			     config->supported_rates.rate,
5104 			     config->supported_rates.numRates);
5105 		sap_bss_cfg->operationalRateSet.numRates =
5106 					config->supported_rates.numRates;
5107 	}
5108 
5109 	if (config->extended_rates.numRates) {
5110 		qdf_mem_copy(sap_bss_cfg->extendedRateSet.rate,
5111 			     config->extended_rates.rate,
5112 			     config->extended_rates.numRates);
5113 		sap_bss_cfg->extendedRateSet.numRates =
5114 				config->extended_rates.numRates;
5115 	}
5116 
5117 	return;
5118 }
5119