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