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