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