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