1 /*
2 * Copyright (c) 2011-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 * This file lim_api.cc contains the functions that are
22 * exported by LIM to other modules.
23 *
24 * Author: Chandra Modumudi
25 * Date: 02/11/02
26 * History:-
27 * Date Modified by Modification Information
28 * --------------------------------------------------------------------
29 *
30 */
31 #include "cds_api.h"
32 #include "wni_cfg.h"
33 #include "wni_api.h"
34 #include "sir_common.h"
35 #include "sir_debug.h"
36
37 #include "sch_api.h"
38 #include "utils_api.h"
39 #include "lim_api.h"
40 #include "lim_global.h"
41 #include "lim_types.h"
42 #include "lim_utils.h"
43 #include "lim_assoc_utils.h"
44 #include "lim_prop_exts_utils.h"
45 #include "lim_ser_des_utils.h"
46 #include "lim_admit_control.h"
47 #include "lim_send_sme_rsp_messages.h"
48 #include "lim_security_utils.h"
49 #include "wmm_apsd.h"
50 #include "lim_trace.h"
51 #include "lim_ft_defs.h"
52 #include "lim_session.h"
53 #include "wma_types.h"
54 #include "wlan_crypto_global_api.h"
55 #include "wlan_crypto_def_i.h"
56
57 #include "rrm_api.h"
58
59 #include <lim_ft.h>
60 #include "qdf_types.h"
61 #include "cds_packet.h"
62 #include "cds_utils.h"
63 #include "sys_startup.h"
64 #include "cds_api.h"
65 #include "wlan_policy_mgr_api.h"
66 #include "nan_datapath.h"
67 #include "wma.h"
68 #include "wlan_mgmt_txrx_utils_api.h"
69 #include "wlan_objmgr_psoc_obj.h"
70 #include "os_if_nan.h"
71 #include <wlan_scan_ucfg_api.h>
72 #include <wlan_scan_public_structs.h>
73 #include <wlan_p2p_ucfg_api.h>
74 #include "wlan_utility.h"
75 #include <wlan_tdls_cfg_api.h>
76 #include "cfg_ucfg_api.h"
77 #include "wlan_mlme_public_struct.h"
78 #include "wlan_mlme_twt_api.h"
79 #include "wlan_scan_utils_api.h"
80 #include <qdf_hang_event_notifier.h>
81 #include <qdf_notifier.h>
82 #include "wlan_pkt_capture_ucfg_api.h"
83 #include <lim_mlo.h>
84 #include "wlan_mlo_mgr_roam.h"
85 #include "utils_mlo.h"
86 #include "wlan_mlo_mgr_sta.h"
87 #include "wlan_mlo_mgr_peer.h"
88 #include <wlan_twt_api.h>
89 #include "wlan_tdls_api.h"
90 #include "wlan_mlo_mgr_link_switch.h"
91 #include "wlan_cm_api.h"
92 #include "wlan_mlme_api.h"
93
94 struct pe_hang_event_fixed_param {
95 uint16_t tlv_header;
96 uint8_t vdev_id;
97 uint8_t limmlmstate;
98 uint8_t limprevmlmstate;
99 uint8_t limsmestate;
100 uint8_t limprevsmestate;
101 } qdf_packed;
102
__lim_init_bss_vars(struct mac_context * mac)103 static void __lim_init_bss_vars(struct mac_context *mac)
104 {
105 qdf_mem_zero((void *)mac->lim.gpSession,
106 sizeof(*mac->lim.gpSession) * mac->lim.maxBssId);
107 }
108
__lim_init_stats_vars(struct mac_context * mac)109 static void __lim_init_stats_vars(struct mac_context *mac)
110 {
111 /* / Variable to keep track of number of currently associated STAs */
112 mac->lim.gLimNumOfAniSTAs = 0; /* count of ANI peers */
113
114 qdf_mem_zero(mac->lim.gLimHeartBeatApMac[0],
115 sizeof(tSirMacAddr));
116 qdf_mem_zero(mac->lim.gLimHeartBeatApMac[1],
117 sizeof(tSirMacAddr));
118 mac->lim.gLimHeartBeatApMacIndex = 0;
119 }
120
__lim_init_states(struct mac_context * mac)121 static void __lim_init_states(struct mac_context *mac)
122 {
123 /* Counts Heartbeat failures */
124 mac->lim.gLimHBfailureCntInLinkEstState = 0;
125 mac->lim.gLimProbeFailureAfterHBfailedCnt = 0;
126 mac->lim.gLimHBfailureCntInOtherStates = 0;
127 mac->lim.gLimRspReqd = 0;
128 mac->lim.gLimPrevSmeState = eLIM_SME_OFFLINE_STATE;
129
130 /* / MLM State visible across all Sirius modules */
131 MTRACE(mac_trace
132 (mac, TRACE_CODE_MLM_STATE, NO_SESSION, eLIM_MLM_IDLE_STATE));
133 mac->lim.gLimMlmState = eLIM_MLM_IDLE_STATE;
134
135 /* / Previous MLM State */
136 mac->lim.gLimPrevMlmState = eLIM_MLM_OFFLINE_STATE;
137
138 /**
139 * Initialize state to eLIM_SME_OFFLINE_STATE
140 */
141 mac->lim.gLimSmeState = eLIM_SME_OFFLINE_STATE;
142
143 /**
144 * By default assume 'unknown' role. This will be updated
145 * when SME_START_BSS_REQ is received.
146 */
147
148 qdf_mem_zero(&mac->lim.gLimNoShortParams, sizeof(tLimNoShortParams));
149 qdf_mem_zero(&mac->lim.gLimNoShortSlotParams,
150 sizeof(tLimNoShortSlotParams));
151
152 mac->lim.gLimPhyMode = 0;
153 }
154
__lim_init_vars(struct mac_context * mac)155 static void __lim_init_vars(struct mac_context *mac)
156 {
157 /* Place holder for Measurement Req/Rsp/Ind related info */
158
159
160 /* Deferred Queue Parameters */
161 qdf_mem_zero(&mac->lim.gLimDeferredMsgQ, sizeof(tSirAddtsReq));
162
163 /* addts request if any - only one can be outstanding at any time */
164 qdf_mem_zero(&mac->lim.gLimAddtsReq, sizeof(tSirAddtsReq));
165 mac->lim.gLimAddtsSent = 0;
166 mac->lim.gLimAddtsRspTimerCount = 0;
167
168 /* protection related config cache */
169 qdf_mem_zero(&mac->lim.cfgProtection, sizeof(tCfgProtection));
170 mac->lim.gLimProtectionControl = 0;
171 SET_LIM_PROCESS_DEFD_MESGS(mac, true);
172
173 /* WMM Related Flag */
174 mac->lim.gUapsdEnable = 0;
175
176 /* QoS-AC Downgrade: Initially, no AC is admitted */
177 mac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] = 0;
178 mac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] = 0;
179
180 /* dialogue token List head/tail for Action frames request sent. */
181 mac->lim.pDialogueTokenHead = NULL;
182 mac->lim.pDialogueTokenTail = NULL;
183
184 qdf_mem_zero(&mac->lim.tspecInfo,
185 sizeof(tLimTspecInfo) * LIM_NUM_TSPEC_MAX);
186
187 /* admission control policy information */
188 qdf_mem_zero(&mac->lim.admitPolicyInfo, sizeof(tLimAdmitPolicyInfo));
189 }
190
__lim_init_assoc_vars(struct mac_context * mac)191 static void __lim_init_assoc_vars(struct mac_context *mac)
192 {
193 mac->lim.gLimIbssStaLimit = 0;
194 /* Place holder for current authentication request */
195 /* being handled */
196 mac->lim.gpLimMlmAuthReq = NULL;
197
198 /* / MAC level Pre-authentication related globals */
199 mac->lim.gLimPreAuthChannelNumber = 0;
200 mac->lim.gLimPreAuthType = eSIR_OPEN_SYSTEM;
201 qdf_mem_zero(&mac->lim.gLimPreAuthPeerAddr, sizeof(tSirMacAddr));
202 mac->lim.gLimNumPreAuthContexts = 0;
203 qdf_mem_zero(&mac->lim.gLimPreAuthTimerTable, sizeof(tLimPreAuthTable));
204
205 /* Place holder for Pre-authentication node list */
206 mac->lim.pLimPreAuthList = NULL;
207
208 /* One cache for each overlap and associated case. */
209 qdf_mem_zero(mac->lim.protStaOverlapCache,
210 sizeof(tCacheParams) * LIM_PROT_STA_OVERLAP_CACHE_SIZE);
211 qdf_mem_zero(mac->lim.protStaCache,
212 sizeof(tCacheParams) * LIM_PROT_STA_CACHE_SIZE);
213
214 mac->lim.pe_session = NULL;
215 mac->lim.reAssocRetryAttempt = 0;
216
217 }
218
__lim_init_ht_vars(struct mac_context * mac)219 static void __lim_init_ht_vars(struct mac_context *mac)
220 {
221 mac->lim.htCapabilityPresentInBeacon = 0;
222 mac->lim.gHTGreenfield = 0;
223 mac->lim.gHTShortGI40Mhz = 0;
224 mac->lim.gHTShortGI20Mhz = 0;
225 mac->lim.gHTMaxAmsduLength = 0;
226 mac->lim.gHTDsssCckRate40MHzSupport = 0;
227 mac->lim.gHTPSMPSupport = 0;
228 mac->lim.gHTLsigTXOPProtection = 0;
229 mac->lim.gHTMIMOPSState = eSIR_HT_MIMO_PS_STATIC;
230 mac->lim.gHTAMpduDensity = 0;
231
232 mac->lim.gMaxAmsduSizeEnabled = false;
233 mac->lim.gHTMaxRxAMpduFactor = 0;
234 mac->lim.gHTServiceIntervalGranularity = 0;
235 mac->lim.gHTControlledAccessOnly = 0;
236 mac->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE;
237 mac->lim.gHTPCOActive = 0;
238
239 mac->lim.gHTPCOPhase = 0;
240 mac->lim.gHTSecondaryBeacon = 0;
241 mac->lim.gHTDualCTSProtection = 0;
242 mac->lim.gHTSTBCBasicMCS = 0;
243 }
244
__lim_init_config(struct mac_context * mac)245 static QDF_STATUS __lim_init_config(struct mac_context *mac)
246 {
247 struct mlme_ht_capabilities_info *ht_cap_info;
248 #ifdef FEATURE_WLAN_TDLS
249 QDF_STATUS status;
250 uint32_t val1;
251 bool valb;
252 #endif
253
254 /* Read all the CFGs here that were updated before pe_start is called */
255 /* All these CFG READS/WRITES are only allowed in init, at start when there is no session
256 * and they will be used throughout when there is no session
257 */
258 mac->lim.gLimIbssStaLimit = mac->mlme_cfg->sap_cfg.assoc_sta_limit;
259 ht_cap_info = &mac->mlme_cfg->ht_caps.ht_cap_info;
260
261 /* channel bonding mode could be set to anything from 0 to 4(Titan had these */
262 /* modes But for Taurus we have only two modes: enable(>0) or disable(=0) */
263 ht_cap_info->supported_channel_width_set =
264 mac->mlme_cfg->feature_flags.channel_bonding_mode ?
265 WNI_CFG_CHANNEL_BONDING_MODE_ENABLE :
266 WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
267
268 mac->mlme_cfg->ht_caps.info_field_1.recommended_tx_width_set =
269 ht_cap_info->supported_channel_width_set;
270
271 if (!mac->mlme_cfg->timeouts.heart_beat_threshold) {
272 mac->sys.gSysEnableLinkMonitorMode = 0;
273 } else {
274 /* No need to activate the timer during init time. */
275 mac->sys.gSysEnableLinkMonitorMode = 1;
276 }
277
278 /* WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA - not needed */
279
280 /* This was initially done after resume notification from HAL. Now, DAL is
281 started before PE so this can be done here */
282 handle_ht_capabilityand_ht_info(mac, NULL);
283 #ifdef FEATURE_WLAN_TDLS
284 status = cfg_tdls_get_buffer_sta_enable(mac->psoc, &valb);
285 if (QDF_STATUS_SUCCESS != status) {
286 pe_err("cfg get LimTDLSBufStaEnabled failed");
287 return QDF_STATUS_E_FAILURE;
288 }
289 mac->lim.gLimTDLSBufStaEnabled = (uint8_t)valb;
290
291 status = cfg_tdls_get_uapsd_mask(mac->psoc, &val1);
292 if (QDF_STATUS_SUCCESS != status) {
293 pe_err("cfg get LimTDLSUapsdMask failed");
294 return QDF_STATUS_E_FAILURE;
295 }
296 mac->lim.gLimTDLSUapsdMask = (uint8_t)val1;
297
298 status = cfg_tdls_get_off_channel_enable(mac->psoc, &valb);
299 if (QDF_STATUS_SUCCESS != status) {
300 pe_err("cfg get LimTDLSUapsdMask failed");
301 return QDF_STATUS_E_FAILURE;
302 }
303 mac->lim.gLimTDLSOffChannelEnabled = (uint8_t)valb;
304
305 status = cfg_tdls_get_wmm_mode_enable(mac->psoc, &valb);
306 if (QDF_STATUS_SUCCESS != status) {
307 pe_err("cfg get LimTDLSWmmMode failed");
308 return QDF_STATUS_E_FAILURE;
309 }
310 mac->lim.gLimTDLSWmmMode = (uint8_t)valb;
311 #endif
312
313 return QDF_STATUS_SUCCESS;
314 }
315
316 /*
317 lim_start
318 This function is to replace the __lim_process_sme_start_req since there is no
319 eWNI_SME_START_REQ post to PE.
320 */
lim_start(struct mac_context * mac)321 QDF_STATUS lim_start(struct mac_context *mac)
322 {
323 QDF_STATUS retCode = QDF_STATUS_SUCCESS;
324
325 pe_debug("enter");
326
327 if (mac->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) {
328 mac->lim.gLimSmeState = eLIM_SME_IDLE_STATE;
329
330 MTRACE(mac_trace
331 (mac, TRACE_CODE_SME_STATE, NO_SESSION,
332 mac->lim.gLimSmeState));
333
334 /* Initialize MLM state machine */
335 if (QDF_STATUS_SUCCESS != lim_init_mlm(mac)) {
336 pe_err("Init MLM failed");
337 return QDF_STATUS_E_FAILURE;
338 }
339 } else {
340 /**
341 * Should not have received eWNI_SME_START_REQ in states
342 * other than OFFLINE. Return response to host and
343 * log error
344 */
345 pe_warn("Invalid SME state: %X",
346 mac->lim.gLimSmeState);
347 retCode = QDF_STATUS_E_FAILURE;
348 }
349
350 mac->lim.req_id =
351 wlan_scan_register_requester(mac->psoc,
352 "LIM",
353 lim_process_rx_scan_handler,
354 mac);
355 return retCode;
356 }
357
358 /**
359 * lim_initialize()
360 *
361 ***FUNCTION:
362 * This function is called from LIM thread entry function.
363 * LIM related global data structures are initialized in this function.
364 *
365 ***LOGIC:
366 * NA
367 *
368 ***ASSUMPTIONS:
369 * NA
370 *
371 ***NOTE:
372 * NA
373 *
374 * @param mac - Pointer to global MAC structure
375 * @return None
376 */
377
lim_initialize(struct mac_context * mac)378 QDF_STATUS lim_initialize(struct mac_context *mac)
379 {
380 QDF_STATUS status = QDF_STATUS_SUCCESS;
381
382 mac->lim.tdls_frm_session_id = NO_SESSION;
383 mac->lim.deferredMsgCnt = 0;
384 mac->lim.retry_packet_cnt = 0;
385 mac->lim.deauthMsgCnt = 0;
386 mac->lim.disassocMsgCnt = 0;
387
388 __lim_init_assoc_vars(mac);
389 __lim_init_vars(mac);
390 __lim_init_states(mac);
391 __lim_init_stats_vars(mac);
392 __lim_init_bss_vars(mac);
393 __lim_init_ht_vars(mac);
394
395 rrm_initialize(mac);
396
397 if (QDF_IS_STATUS_ERROR(qdf_mutex_create(
398 &mac->lim.lim_frame_register_lock))) {
399 pe_err("lim lock init failed!");
400 return QDF_STATUS_E_FAILURE;
401 }
402
403 qdf_list_create(&mac->lim.gLimMgmtFrameRegistratinQueue, 0);
404
405 /* initialize the TSPEC admission control table. */
406 /* Note that this was initially done after resume notification from HAL. */
407 /* Now, DAL is started before PE so this can be done here */
408 lim_admit_control_init(mac);
409 return status;
410
411 } /*** end lim_initialize() ***/
412
413 /**
414 * lim_cleanup()
415 *
416 ***FUNCTION:
417 * This function is called upon reset or persona change
418 * to cleanup LIM state
419 *
420 ***LOGIC:
421 * NA
422 *
423 ***ASSUMPTIONS:
424 * NA
425 *
426 ***NOTE:
427 * NA
428 *
429 * @param mac - Pointer to Global MAC structure
430 * @return None
431 */
432
lim_cleanup(struct mac_context * mac)433 void lim_cleanup(struct mac_context *mac)
434 {
435 uint8_t i;
436 qdf_list_node_t *lst_node;
437
438 /*
439 * Before destroying the list making sure all the nodes have been
440 * deleted
441 */
442 while (qdf_list_remove_front(
443 &mac->lim.gLimMgmtFrameRegistratinQueue,
444 &lst_node) == QDF_STATUS_SUCCESS) {
445 qdf_mem_free(lst_node);
446 }
447 qdf_list_destroy(&mac->lim.gLimMgmtFrameRegistratinQueue);
448 qdf_mutex_destroy(&mac->lim.lim_frame_register_lock);
449
450 pe_deregister_mgmt_rx_frm_callback(mac);
451
452 /* free up preAuth table */
453 if (mac->lim.gLimPreAuthTimerTable.pTable) {
454 for (i = 0; i < mac->lim.gLimPreAuthTimerTable.numEntry; i++)
455 qdf_mem_free(mac->lim.gLimPreAuthTimerTable.pTable[i]);
456 qdf_mem_free(mac->lim.gLimPreAuthTimerTable.pTable);
457 mac->lim.gLimPreAuthTimerTable.pTable = NULL;
458 mac->lim.gLimPreAuthTimerTable.numEntry = 0;
459 }
460
461 if (mac->lim.pDialogueTokenHead) {
462 lim_delete_dialogue_token_list(mac);
463 }
464
465 if (mac->lim.pDialogueTokenTail) {
466 qdf_mem_free(mac->lim.pDialogueTokenTail);
467 mac->lim.pDialogueTokenTail = NULL;
468 }
469
470 if (mac->lim.gpLimMlmAuthReq) {
471 qdf_mem_free(mac->lim.gpLimMlmAuthReq);
472 mac->lim.gpLimMlmAuthReq = NULL;
473 }
474
475 if (mac->lim.limDisassocDeauthCnfReq.pMlmDisassocReq) {
476 qdf_mem_free(mac->lim.limDisassocDeauthCnfReq.pMlmDisassocReq);
477 mac->lim.limDisassocDeauthCnfReq.pMlmDisassocReq = NULL;
478 }
479
480 if (mac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq) {
481 qdf_mem_free(mac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq);
482 mac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq = NULL;
483 }
484
485 /* Now, finally reset the deferred message queue pointers */
486 lim_reset_deferred_msg_q(mac);
487
488 for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++)
489 rrm_cleanup(mac, i);
490
491 lim_ft_cleanup_all_ft_sessions(mac);
492
493 wlan_scan_unregister_requester(mac->psoc, mac->lim.req_id);
494 } /*** end lim_cleanup() ***/
495
496 #ifdef WLAN_FEATURE_MEMDUMP_ENABLE
497 /**
498 * lim_state_info_dump() - print state information of lim layer
499 * @buf: buffer pointer
500 * @size: size of buffer to be filled
501 *
502 * This function is used to print state information of lim layer
503 *
504 * Return: None
505 */
lim_state_info_dump(char ** buf_ptr,uint16_t * size)506 static void lim_state_info_dump(char **buf_ptr, uint16_t *size)
507 {
508 struct mac_context *mac;
509 uint16_t len = 0;
510 char *buf = *buf_ptr;
511
512 mac = cds_get_context(QDF_MODULE_ID_PE);
513 if (!mac) {
514 return;
515 }
516
517 pe_debug("size of buffer: %d", *size);
518
519 len += qdf_scnprintf(buf + len, *size - len,
520 "\n SmeState: %d", mac->lim.gLimSmeState);
521 len += qdf_scnprintf(buf + len, *size - len,
522 "\n PrevSmeState: %d", mac->lim.gLimPrevSmeState);
523 len += qdf_scnprintf(buf + len, *size - len,
524 "\n MlmState: %d", mac->lim.gLimMlmState);
525 len += qdf_scnprintf(buf + len, *size - len,
526 "\n PrevMlmState: %d", mac->lim.gLimPrevMlmState);
527 len += qdf_scnprintf(buf + len, *size - len,
528 "\n ProcessDefdMsgs: %d", mac->lim.gLimProcessDefdMsgs);
529
530 *size -= len;
531 *buf_ptr += len;
532 }
533
534 /**
535 * lim_register_debug_callback() - registration function for lim layer
536 * to print lim state information
537 *
538 * Return: None
539 */
lim_register_debug_callback(void)540 static void lim_register_debug_callback(void)
541 {
542 qdf_register_debug_callback(QDF_MODULE_ID_PE, &lim_state_info_dump);
543 }
544 #else /* WLAN_FEATURE_MEMDUMP_ENABLE */
lim_register_debug_callback(void)545 static void lim_register_debug_callback(void)
546 {
547 }
548 #endif /* WLAN_FEATURE_MEMDUMP_ENABLE */
549
550 #ifdef WLAN_FEATURE_NAN
lim_nan_register_callbacks(struct mac_context * mac_ctx)551 static void lim_nan_register_callbacks(struct mac_context *mac_ctx)
552 {
553 struct nan_callbacks cb_obj = {0};
554
555 cb_obj.add_ndi_peer = lim_add_ndi_peer_converged;
556 cb_obj.ndp_delete_peers = lim_ndp_delete_peers_converged;
557 cb_obj.delete_peers_by_addr = lim_ndp_delete_peers_by_addr_converged;
558
559 ucfg_nan_register_lim_callbacks(mac_ctx->psoc, &cb_obj);
560 }
561 #else
lim_nan_register_callbacks(struct mac_context * mac_ctx)562 static inline void lim_nan_register_callbacks(struct mac_context *mac_ctx)
563 {
564 }
565 #endif
566
lim_stop_pmfcomeback_timer(struct pe_session * session)567 void lim_stop_pmfcomeback_timer(struct pe_session *session)
568 {
569 if (session->opmode != QDF_STA_MODE)
570 return;
571
572 qdf_mc_timer_stop(&session->pmf_retry_timer);
573 session->pmf_retry_timer_info.retried = false;
574 }
575
576 /*
577 * pe_shutdown_notifier_cb - Shutdown notifier callback
578 * @ctx: Pointer to Global MAC structure
579 *
580 * Return: None
581 */
pe_shutdown_notifier_cb(void * ctx)582 static void pe_shutdown_notifier_cb(void *ctx)
583 {
584 struct mac_context *mac_ctx = (struct mac_context *)ctx;
585 struct pe_session *session;
586 uint8_t i;
587
588 lim_deactivate_timers(mac_ctx);
589 for (i = 0; i < mac_ctx->lim.maxBssId; i++) {
590 session = &mac_ctx->lim.gpSession[i];
591 if (session->valid == true) {
592 if (LIM_IS_AP_ROLE(session))
593 qdf_mc_timer_stop(&session->
594 protection_fields_reset_timer);
595 lim_stop_pmfcomeback_timer(session);
596 }
597 }
598 }
599
is_mgmt_protected(uint32_t vdev_id,const uint8_t * peer_mac_addr)600 bool is_mgmt_protected(uint32_t vdev_id,
601 const uint8_t *peer_mac_addr)
602 {
603 uint16_t aid;
604 tpDphHashNode sta_ds;
605 struct pe_session *session;
606 bool protected = false;
607 struct mac_context *mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
608
609 if (!mac_ctx)
610 return false;
611
612 session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
613 if (!session) {
614 /* couldn't find session */
615 pe_err("Session not found for vdev_id: %d", vdev_id);
616 return false;
617 }
618
619 sta_ds = dph_lookup_hash_entry(mac_ctx, (uint8_t *)peer_mac_addr, &aid,
620 &session->dph.dphHashTable);
621 if (sta_ds) {
622 /* rmfenabled will be set at the time of addbss.
623 * but sometimes EAP auth fails and keys are not
624 * installed then if we send any management frame
625 * like deauth/disassoc with this bit set then
626 * firmware crashes. so check for keys are
627 * installed or not also before setting the bit
628 */
629 if (sta_ds->rmfEnabled && sta_ds->is_key_installed)
630 protected = true;
631 }
632
633 return protected;
634 }
635
p2p_register_callbacks(struct mac_context * mac_ctx)636 static void p2p_register_callbacks(struct mac_context *mac_ctx)
637 {
638 struct p2p_protocol_callbacks p2p_cb = {0};
639
640 p2p_cb.is_mgmt_protected = is_mgmt_protected;
641 ucfg_p2p_register_callbacks(mac_ctx->psoc, &p2p_cb);
642 }
643
644 /*
645 * lim_register_sap_bcn_callback(): Register a callback with scan module for SAP
646 * @mac_ctx: pointer to the global mac context
647 *
648 * Registers the function lim_handle_sap_beacon as callback with the Scan
649 * module to handle beacon frames for SAP sessions
650 *
651 * Return: QDF Status
652 */
lim_register_sap_bcn_callback(struct mac_context * mac_ctx)653 static QDF_STATUS lim_register_sap_bcn_callback(struct mac_context *mac_ctx)
654 {
655 QDF_STATUS status;
656
657 status = ucfg_scan_register_bcn_cb(mac_ctx->psoc,
658 lim_handle_sap_beacon,
659 SCAN_CB_TYPE_UPDATE_BCN);
660 if (!QDF_IS_STATUS_SUCCESS(status)) {
661 pe_err("failed with status code %08d [x%08x]",
662 status, status);
663 }
664
665 return status;
666 }
667
668 /*
669 * lim_unregister_sap_bcn_callback(): Unregister the callback with scan module
670 * @mac_ctx: pointer to the global mac context
671 *
672 * Unregisters the callback registered with the Scan
673 * module to handle beacon frames for SAP sessions
674 *
675 * Return: QDF Status
676 */
lim_unregister_sap_bcn_callback(struct mac_context * mac_ctx)677 static QDF_STATUS lim_unregister_sap_bcn_callback(struct mac_context *mac_ctx)
678 {
679 QDF_STATUS status;
680
681 status = ucfg_scan_register_bcn_cb(mac_ctx->psoc,
682 NULL, SCAN_CB_TYPE_UPDATE_BCN);
683 if (!QDF_IS_STATUS_SUCCESS(status)) {
684 pe_err("failed with status code %08d [x%08x]",
685 status, status);
686 }
687
688 return status;
689 }
690
691 /*
692 * lim_register_scan_mbssid_callback(): Register callback with scan module
693 * @mac_ctx: pointer to the global mac context
694 *
695 * Registers the function lim_register_scan_mbssid_callback as callback
696 * with the Scan module to handle generated frames by MBSSID IE
697 *
698 * Return: QDF Status
699 */
700 static QDF_STATUS
lim_register_scan_mbssid_callback(struct mac_context * mac_ctx)701 lim_register_scan_mbssid_callback(struct mac_context *mac_ctx)
702 {
703 QDF_STATUS status;
704
705 status = wlan_scan_register_mbssid_cb(mac_ctx->psoc,
706 lim_handle_frame_genby_mbssid);
707 if (!QDF_IS_STATUS_SUCCESS(status)) {
708 pe_err("failed with status code %08d [x%08x]",
709 status, status);
710 }
711
712 return status;
713 }
714
715 /*
716 * lim_unregister_scan_mbssid_callback(): Unregister callback with scan module
717 * @mac_ctx: pointer to the global mac context
718 *
719 * Unregisters the callback registered with the Scan module to handle
720 * generated frames by MBSSID IE
721 *
722 * Return: QDF Status
723 */
724 static QDF_STATUS
lim_unregister_scan_mbssid_callback(struct mac_context * mac_ctx)725 lim_unregister_scan_mbssid_callback(struct mac_context *mac_ctx)
726 {
727 QDF_STATUS status;
728
729 status = wlan_scan_register_mbssid_cb(mac_ctx->psoc, NULL);
730 if (!QDF_IS_STATUS_SUCCESS(status)) {
731 pe_err("failed with status code %08d [x%08x]",
732 status, status);
733 }
734
735 return status;
736 }
737
lim_register_policy_mgr_callback(struct wlan_objmgr_psoc * psoc)738 static void lim_register_policy_mgr_callback(struct wlan_objmgr_psoc *psoc)
739 {
740 struct policy_mgr_conc_cbacks conc_cbacks;
741
742 qdf_mem_zero(&conc_cbacks, sizeof(conc_cbacks));
743 conc_cbacks.connection_info_update = lim_send_conc_params_update;
744
745 if (QDF_STATUS_SUCCESS != policy_mgr_register_conc_cb(psoc,
746 &conc_cbacks)) {
747 pe_err("failed to register policy manager callbacks");
748 }
749 }
750
pe_hang_event_notifier_call(struct notifier_block * block,unsigned long state,void * data)751 static int pe_hang_event_notifier_call(struct notifier_block *block,
752 unsigned long state,
753 void *data)
754 {
755 qdf_notif_block *notif_block = qdf_container_of(block, qdf_notif_block,
756 notif_block);
757 struct mac_context *mac;
758 struct pe_session *session;
759 struct qdf_notifer_data *pe_hang_data = data;
760 uint8_t *pe_data;
761 uint8_t i;
762 struct pe_hang_event_fixed_param *cmd;
763 size_t size;
764
765 if (!data)
766 return NOTIFY_STOP_MASK;
767
768 mac = notif_block->priv_data;
769 if (!mac)
770 return NOTIFY_STOP_MASK;
771
772 size = sizeof(*cmd);
773 for (i = 0; i < mac->lim.maxBssId; i++) {
774 session = &mac->lim.gpSession[i];
775 if (!session->valid)
776 continue;
777 if (pe_hang_data->offset + size > QDF_WLAN_HANG_FW_OFFSET)
778 return NOTIFY_STOP_MASK;
779
780 pe_data = (pe_hang_data->hang_data + pe_hang_data->offset);
781 cmd = (struct pe_hang_event_fixed_param *)pe_data;
782 QDF_HANG_EVT_SET_HDR(&cmd->tlv_header, HANG_EVT_TAG_LEGACY_MAC,
783 QDF_HANG_GET_STRUCT_TLVLEN(*cmd));
784 cmd->vdev_id = session->vdev_id;
785 cmd->limmlmstate = session->limMlmState;
786 cmd->limprevmlmstate = session->limPrevMlmState;
787 cmd->limsmestate = session->limSmeState;
788 cmd->limprevsmestate = session->limPrevSmeState;
789 pe_hang_data->offset += size;
790 }
791
792 return NOTIFY_OK;
793 }
794
795 static qdf_notif_block pe_hang_event_notifier = {
796 .notif_block.notifier_call = pe_hang_event_notifier_call,
797 };
798
799 /** -------------------------------------------------------------
800 \fn pe_open
801 \brief will be called in Open sequence from mac_open
802 \param struct mac_context *mac
803 \param tHalOpenParameters *pHalOpenParam
804 \return QDF_STATUS
805 -------------------------------------------------------------*/
806
pe_open(struct mac_context * mac,struct cds_config_info * cds_cfg)807 QDF_STATUS pe_open(struct mac_context *mac, struct cds_config_info *cds_cfg)
808 {
809 QDF_STATUS status = QDF_STATUS_SUCCESS;
810
811 if (QDF_DRIVER_TYPE_MFG == cds_cfg->driver_type)
812 return QDF_STATUS_SUCCESS;
813
814 mac->lim.maxBssId = cds_cfg->max_bssid;
815 mac->lim.maxStation = cds_cfg->max_station;
816 mac->lim.max_sta_of_pe_session =
817 (cds_cfg->max_station > SIR_SAP_MAX_NUM_PEERS) ?
818 SIR_SAP_MAX_NUM_PEERS : cds_cfg->max_station;
819 qdf_spinlock_create(&mac->sys.bbt_mgmt_lock);
820
821 if ((mac->lim.maxBssId == 0) || (mac->lim.maxStation == 0)) {
822 pe_err("max number of Bssid or Stations cannot be zero!");
823 return QDF_STATUS_E_FAILURE;
824 }
825
826 if (!QDF_IS_STATUS_SUCCESS(pe_allocate_dph_node_array_buffer())) {
827 pe_err("g_dph_node_array memory allocate failed!");
828 return QDF_STATUS_E_NOMEM;
829 }
830
831 mac->lim.lim_timers.gpLimCnfWaitTimer =
832 qdf_mem_malloc(sizeof(TX_TIMER) * (mac->lim.maxStation + 1));
833 if (!mac->lim.lim_timers.gpLimCnfWaitTimer) {
834 status = QDF_STATUS_E_NOMEM;
835 goto pe_open_timer_fail;
836 }
837
838 mac->lim.gpSession =
839 qdf_mem_common_alloc(sizeof(struct pe_session) * mac->lim.maxBssId);
840 if (!mac->lim.gpSession) {
841 status = QDF_STATUS_E_NOMEM;
842 goto pe_open_psession_fail;
843 }
844
845 status = lim_initialize(mac);
846 if (QDF_STATUS_SUCCESS != status) {
847 pe_err("lim_initialize failed!");
848 status = QDF_STATUS_E_FAILURE;
849 goto pe_open_lock_fail;
850 }
851
852 /*
853 * pe_open is successful by now, so it is right time to initialize
854 * MTRACE for PE module. if LIM_TRACE_RECORD is not defined in build
855 * file then nothing will be logged for PE module.
856 */
857 #ifdef LIM_TRACE_RECORD
858 MTRACE(lim_trace_init(mac));
859 #endif
860 lim_register_debug_callback();
861 lim_nan_register_callbacks(mac);
862 p2p_register_callbacks(mac);
863 lim_register_scan_mbssid_callback(mac);
864 lim_register_sap_bcn_callback(mac);
865 wlan_reg_register_ctry_change_callback(
866 mac->psoc,
867 lim_update_tx_pwr_on_ctry_change_cb);
868
869 wlan_reg_register_is_chan_connected_callback(mac->psoc,
870 lim_get_connected_chan_for_mode);
871
872 if (mac->mlme_cfg->edca_params.enable_edca_params)
873 lim_register_policy_mgr_callback(mac->psoc);
874
875 if (!QDF_IS_STATUS_SUCCESS(
876 cds_shutdown_notifier_register(pe_shutdown_notifier_cb, mac))) {
877 pe_err("Shutdown notifier register failed");
878 }
879
880 pe_hang_event_notifier.priv_data = mac;
881 qdf_hang_event_register_notifier(&pe_hang_event_notifier);
882
883 return status; /* status here will be QDF_STATUS_SUCCESS */
884
885 pe_open_lock_fail:
886 qdf_mem_common_free(mac->lim.gpSession);
887 mac->lim.gpSession = NULL;
888 pe_open_psession_fail:
889 qdf_mem_free(mac->lim.lim_timers.gpLimCnfWaitTimer);
890 mac->lim.lim_timers.gpLimCnfWaitTimer = NULL;
891 pe_open_timer_fail:
892 pe_free_dph_node_array_buffer();
893
894 return status;
895 }
896
897 /** -------------------------------------------------------------
898 \fn pe_close
899 \brief will be called in close sequence from mac_close
900 \param struct mac_context *mac
901 \return QDF_STATUS
902 -------------------------------------------------------------*/
903
pe_close(struct mac_context * mac)904 QDF_STATUS pe_close(struct mac_context *mac)
905 {
906 uint8_t i;
907
908 if (ANI_DRIVER_TYPE(mac) == QDF_DRIVER_TYPE_MFG)
909 return QDF_STATUS_SUCCESS;
910
911 qdf_hang_event_unregister_notifier(&pe_hang_event_notifier);
912 lim_cleanup_mlm(mac);
913 lim_cleanup(mac);
914 lim_unregister_scan_mbssid_callback(mac);
915 lim_unregister_sap_bcn_callback(mac);
916 wlan_reg_unregister_ctry_change_callback(
917 mac->psoc,
918 lim_update_tx_pwr_on_ctry_change_cb);
919
920 wlan_reg_unregister_is_chan_connected_callback(mac->psoc,
921 lim_get_connected_chan_for_mode);
922
923 if (mac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq) {
924 qdf_mem_free(mac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq);
925 mac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq = NULL;
926 }
927
928 qdf_spinlock_destroy(&mac->sys.bbt_mgmt_lock);
929 for (i = 0; i < mac->lim.maxBssId; i++) {
930 if (mac->lim.gpSession[i].valid == true)
931 pe_delete_session(mac, &mac->lim.gpSession[i]);
932 }
933 qdf_mem_free(mac->lim.lim_timers.gpLimCnfWaitTimer);
934 mac->lim.lim_timers.gpLimCnfWaitTimer = NULL;
935
936 qdf_mem_common_free(mac->lim.gpSession);
937 mac->lim.gpSession = NULL;
938
939 pe_free_dph_node_array_buffer();
940
941 return QDF_STATUS_SUCCESS;
942 }
943
944 /** -------------------------------------------------------------
945 \fn pe_start
946 \brief will be called in start sequence from mac_start
947 \param struct mac_context *mac
948 \return QDF_STATUS_SUCCESS on success, other QDF_STATUS on error
949 -------------------------------------------------------------*/
950
pe_start(struct mac_context * mac)951 QDF_STATUS pe_start(struct mac_context *mac)
952 {
953 QDF_STATUS status = QDF_STATUS_SUCCESS;
954 status = lim_start(mac);
955 if (QDF_STATUS_SUCCESS != status) {
956 pe_err("lim_start failed!");
957 return status;
958 }
959 /* Initialize the configurations needed by PE */
960 if (QDF_STATUS_E_FAILURE == __lim_init_config(mac)) {
961 pe_err("lim init config failed!");
962 /* We need to undo everything in lim_start */
963 lim_cleanup_mlm(mac);
964 return QDF_STATUS_E_FAILURE;
965 }
966
967 return status;
968 }
969
970 /** -------------------------------------------------------------
971 \fn pe_stop
972 \brief will be called in stop sequence from mac_stop
973 \param struct mac_context *mac
974 \return none
975 -------------------------------------------------------------*/
976
pe_stop(struct mac_context * mac)977 void pe_stop(struct mac_context *mac)
978 {
979 pe_debug(" PE STOP: Set LIM state to eLIM_MLM_OFFLINE_STATE");
980 SET_LIM_MLM_STATE(mac, eLIM_MLM_OFFLINE_STATE);
981 return;
982 }
983
pe_free_nested_messages(struct scheduler_msg * msg)984 static void pe_free_nested_messages(struct scheduler_msg *msg)
985 {
986 switch (msg->type) {
987 default:
988 break;
989 }
990 }
991
992 /** -------------------------------------------------------------
993 \fn pe_free_msg
994 \brief Called by CDS scheduler (function cds_sched_flush_mc_mqs)
995 \ to free a given PE message on the TX and MC thread.
996 \ This happens when there are messages pending in the PE
997 \ queue when system is being stopped and reset.
998 \param struct mac_context *mac
999 \param struct scheduler_msg pMsg
1000 \return none
1001 -----------------------------------------------------------------*/
pe_free_msg(struct mac_context * mac,struct scheduler_msg * pMsg)1002 void pe_free_msg(struct mac_context *mac, struct scheduler_msg *pMsg)
1003 {
1004 if (pMsg) {
1005 if (pMsg->bodyptr) {
1006 if (SIR_BB_XPORT_MGMT_MSG == pMsg->type) {
1007 cds_pkt_return_packet((cds_pkt_t *) pMsg->
1008 bodyptr);
1009 } else {
1010 pe_free_nested_messages(pMsg);
1011 qdf_mem_free((void *)pMsg->bodyptr);
1012 }
1013 }
1014 pMsg->bodyptr = 0;
1015 pMsg->bodyval = 0;
1016 pMsg->type = 0;
1017 }
1018 return;
1019 }
1020
lim_post_msg_api(struct mac_context * mac,struct scheduler_msg * msg)1021 QDF_STATUS lim_post_msg_api(struct mac_context *mac, struct scheduler_msg *msg)
1022 {
1023 return scheduler_post_message(QDF_MODULE_ID_PE,
1024 QDF_MODULE_ID_PE,
1025 QDF_MODULE_ID_PE, msg);
1026 }
1027
lim_post_msg_high_priority(struct mac_context * mac,struct scheduler_msg * msg)1028 QDF_STATUS lim_post_msg_high_priority(struct mac_context *mac,
1029 struct scheduler_msg *msg)
1030 {
1031 return scheduler_post_msg_by_priority(QDF_MODULE_ID_PE,
1032 msg, true);
1033 }
1034
pe_mc_process_handler(struct scheduler_msg * msg)1035 QDF_STATUS pe_mc_process_handler(struct scheduler_msg *msg)
1036 {
1037 struct mac_context *mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
1038
1039 if (!mac_ctx)
1040 return QDF_STATUS_E_FAILURE;
1041
1042 if (ANI_DRIVER_TYPE(mac_ctx) == QDF_DRIVER_TYPE_MFG)
1043 return QDF_STATUS_SUCCESS;
1044
1045 lim_message_processor(mac_ctx, msg);
1046
1047 return QDF_STATUS_SUCCESS;
1048 }
1049
1050 /**
1051 * pe_drop_pending_rx_mgmt_frames: To drop pending RX mgmt frames
1052 * @mac_ctx: Pointer to global MAC structure
1053 * @hdr: Management header
1054 * @cds_pkt: Packet
1055 *
1056 * This function is used to drop RX pending mgmt frames if pe mgmt queue
1057 * reaches threshold
1058 *
1059 * Return: QDF_STATUS_SUCCESS on success or QDF_STATUS_E_FAILURE on failure
1060 */
pe_drop_pending_rx_mgmt_frames(struct mac_context * mac_ctx,tpSirMacMgmtHdr hdr,cds_pkt_t * cds_pkt)1061 static QDF_STATUS pe_drop_pending_rx_mgmt_frames(struct mac_context *mac_ctx,
1062 tpSirMacMgmtHdr hdr, cds_pkt_t *cds_pkt)
1063 {
1064 qdf_spin_lock(&mac_ctx->sys.bbt_mgmt_lock);
1065 if (mac_ctx->sys.sys_bbt_pending_mgmt_count >=
1066 MGMT_RX_PACKETS_THRESHOLD) {
1067 qdf_spin_unlock(&mac_ctx->sys.bbt_mgmt_lock);
1068 pe_debug("No.of pending RX management frames reaches to threshold, dropping management frames");
1069 cds_pkt_return_packet(cds_pkt);
1070 cds_pkt = NULL;
1071 mac_ctx->rx_packet_drop_counter++;
1072 return QDF_STATUS_E_FAILURE;
1073 } else if (mac_ctx->sys.sys_bbt_pending_mgmt_count >
1074 (MGMT_RX_PACKETS_THRESHOLD / 2)) {
1075 /* drop all probereq, proberesp and beacons */
1076 if (hdr->fc.subType == SIR_MAC_MGMT_BEACON ||
1077 hdr->fc.subType == SIR_MAC_MGMT_PROBE_REQ ||
1078 hdr->fc.subType == SIR_MAC_MGMT_PROBE_RSP) {
1079 qdf_spin_unlock(&mac_ctx->sys.bbt_mgmt_lock);
1080 if (!(mac_ctx->rx_packet_drop_counter % 100))
1081 pe_debug("No.of pending RX mgmt frames reaches 1/2 thresh, dropping frame subtype: %d rx_packet_drop_counter: %d",
1082 hdr->fc.subType,
1083 mac_ctx->rx_packet_drop_counter);
1084 mac_ctx->rx_packet_drop_counter++;
1085 cds_pkt_return_packet(cds_pkt);
1086 cds_pkt = NULL;
1087 return QDF_STATUS_E_FAILURE;
1088 }
1089 }
1090 mac_ctx->sys.sys_bbt_pending_mgmt_count++;
1091 qdf_spin_unlock(&mac_ctx->sys.bbt_mgmt_lock);
1092 if (mac_ctx->sys.sys_bbt_pending_mgmt_count ==
1093 (MGMT_RX_PACKETS_THRESHOLD / 4)) {
1094 if (!(mac_ctx->rx_packet_drop_counter % 100))
1095 pe_debug("No.of pending RX management frames reaches to 1/4th of threshold, rx_packet_drop_counter: %d",
1096 mac_ctx->rx_packet_drop_counter);
1097 mac_ctx->rx_packet_drop_counter++;
1098 }
1099 return QDF_STATUS_SUCCESS;
1100 }
1101
1102 /**
1103 * pe_is_ext_scan_bcn_probe_rsp - Check if the beacon or probe response
1104 * is from Ext or EPNO scan
1105 *
1106 * @hdr: pointer to the 802.11 header of the frame
1107 * @rx_pkt_info: pointer to the rx packet meta
1108 *
1109 * Checks if the beacon or probe response is from Ext Scan or EPNO scan
1110 *
1111 * Return: true or false
1112 */
1113 #ifdef FEATURE_WLAN_EXTSCAN
pe_is_ext_scan_bcn_probe_rsp(tpSirMacMgmtHdr hdr,uint8_t * rx_pkt_info)1114 static inline bool pe_is_ext_scan_bcn_probe_rsp(tpSirMacMgmtHdr hdr,
1115 uint8_t *rx_pkt_info)
1116 {
1117 if ((hdr->fc.subType == SIR_MAC_MGMT_BEACON ||
1118 hdr->fc.subType == SIR_MAC_MGMT_PROBE_RSP) &&
1119 (WMA_IS_EXTSCAN_SCAN_SRC(rx_pkt_info) ||
1120 WMA_IS_EPNO_SCAN_SRC(rx_pkt_info)))
1121 return true;
1122
1123 return false;
1124 }
1125 #else
pe_is_ext_scan_bcn_probe_rsp(tpSirMacMgmtHdr hdr,uint8_t * rx_pkt_info)1126 static inline bool pe_is_ext_scan_bcn_probe_rsp(tpSirMacMgmtHdr hdr,
1127 uint8_t *rx_pkt_info)
1128 {
1129 return false;
1130 }
1131 #endif
1132
1133 /**
1134 * pe_filter_drop_bcn_probe_frame - Apply filter on the received frame
1135 *
1136 * @mac_ctx: pointer to the global mac context
1137 * @hdr: pointer to the 802.11 header of the frame
1138 * @rx_pkt_info: pointer to the rx packet meta
1139 *
1140 * Applies the filter from global mac context on the received beacon/
1141 * probe response frame before posting it to the PE queue
1142 *
1143 * Return: true if frame is allowed, false if frame is to be dropped.
1144 */
pe_filter_bcn_probe_frame(struct mac_context * mac_ctx,tpSirMacMgmtHdr hdr,uint8_t * rx_pkt_info)1145 static bool pe_filter_bcn_probe_frame(struct mac_context *mac_ctx,
1146 tpSirMacMgmtHdr hdr,
1147 uint8_t *rx_pkt_info)
1148 {
1149 uint8_t session_id;
1150 struct mgmt_beacon_probe_filter *filter;
1151
1152 if (pe_is_ext_scan_bcn_probe_rsp(hdr, rx_pkt_info))
1153 return true;
1154
1155 filter = &mac_ctx->bcn_filter;
1156
1157 /*
1158 * If any STA session exists and beacon source matches any of the
1159 * STA BSSIDs, allow the frame
1160 */
1161 if (filter->num_sta_sessions) {
1162 for (session_id = 0; session_id < WLAN_MAX_VDEVS;
1163 session_id++) {
1164 if (sir_compare_mac_addr(filter->sta_bssid[session_id],
1165 hdr->bssId)) {
1166 return true;
1167 }
1168 }
1169 }
1170
1171 return false;
1172 }
1173
pe_handle_probe_req_frames(struct mac_context * mac_ctx,cds_pkt_t * pkt)1174 static QDF_STATUS pe_handle_probe_req_frames(struct mac_context *mac_ctx,
1175 cds_pkt_t *pkt)
1176 {
1177 QDF_STATUS status;
1178 struct scheduler_msg msg = {0};
1179 uint32_t scan_queue_size = 0;
1180
1181 /* Check if the probe request frame can be posted in the scan queue */
1182 status = scheduler_get_queue_size(QDF_MODULE_ID_SCAN, &scan_queue_size);
1183 if (!QDF_IS_STATUS_SUCCESS(status) ||
1184 scan_queue_size > MAX_BCN_PROBE_IN_SCAN_QUEUE) {
1185 pe_debug_rl("Dropping probe req frame, queue size %d",
1186 scan_queue_size);
1187 return QDF_STATUS_E_FAILURE;
1188 }
1189
1190 /* Forward to MAC via mesg = SIR_BB_XPORT_MGMT_MSG */
1191 msg.type = SIR_BB_XPORT_MGMT_MSG;
1192 msg.bodyptr = pkt;
1193 msg.bodyval = 0;
1194 msg.callback = pe_mc_process_handler;
1195
1196 status = scheduler_post_message(QDF_MODULE_ID_PE,
1197 QDF_MODULE_ID_PE,
1198 QDF_MODULE_ID_SCAN, &msg);
1199
1200 return status;
1201 }
1202
1203 /* --------------------------------------------------------------------------- */
1204 /**
1205 * pe_handle_mgmt_frame() - Process the Management frames from TXRX
1206 * @psoc: psoc context
1207 * @peer: peer
1208 * @buf: buffer
1209 * @mgmt_rx_params; rx event params
1210 * @frm_type: frame type
1211 *
1212 * This function handles the mgmt rx frame from mgmt txrx component and forms
1213 * a cds packet and schedule it in controller thread for further processing.
1214 *
1215 * Return: QDF_STATUS_SUCCESS - in case of success
1216 */
pe_handle_mgmt_frame(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_peer * peer,qdf_nbuf_t buf,struct mgmt_rx_event_params * mgmt_rx_params,enum mgmt_frame_type frm_type)1217 static QDF_STATUS pe_handle_mgmt_frame(struct wlan_objmgr_psoc *psoc,
1218 struct wlan_objmgr_peer *peer, qdf_nbuf_t buf,
1219 struct mgmt_rx_event_params *mgmt_rx_params,
1220 enum mgmt_frame_type frm_type)
1221 {
1222 struct mac_context *mac;
1223 tpSirMacMgmtHdr mHdr;
1224 struct scheduler_msg msg = {0};
1225 cds_pkt_t *pVosPkt;
1226 QDF_STATUS qdf_status;
1227 uint8_t *pRxPacketInfo;
1228 int ret;
1229
1230 /* skip offload packets */
1231 if ((ucfg_pkt_capture_get_mode(psoc) != PACKET_CAPTURE_MODE_DISABLE) &&
1232 mgmt_rx_params->status & WMI_RX_OFFLOAD_MON_MODE) {
1233 qdf_nbuf_free(buf);
1234 return QDF_STATUS_SUCCESS;
1235 }
1236
1237 mac = cds_get_context(QDF_MODULE_ID_PE);
1238 if (!mac) {
1239 /* cannot log a failure without a valid mac */
1240 qdf_nbuf_free(buf);
1241 return QDF_STATUS_E_FAILURE;
1242 }
1243
1244 if (mac->usr_cfg_disable_rsp_tx) {
1245 pe_debug("Drop Rx pkt with user config");
1246 qdf_nbuf_free(buf);
1247 return QDF_STATUS_SUCCESS;
1248 }
1249 pVosPkt = qdf_mem_malloc_atomic(sizeof(*pVosPkt));
1250 if (!pVosPkt) {
1251 qdf_nbuf_free(buf);
1252 return QDF_STATUS_E_NOMEM;
1253 }
1254
1255 ret = wma_form_rx_packet(buf, mgmt_rx_params, pVosPkt);
1256 if (ret) {
1257 pe_debug_rl("Failed to fill cds packet from event buffer");
1258 return QDF_STATUS_E_FAILURE;
1259 }
1260
1261 qdf_status =
1262 wma_ds_peek_rx_packet_info(pVosPkt, (void *)&pRxPacketInfo);
1263
1264 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1265 cds_pkt_return_packet(pVosPkt);
1266 pVosPkt = NULL;
1267 return QDF_STATUS_E_FAILURE;
1268 }
1269
1270 /*
1271 * The MPDU header is now present at a certain "offset" in
1272 * the BD and is specified in the BD itself
1273 */
1274
1275 mHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
1276
1277 /*
1278 * Filter the beacon/probe response frames before posting it
1279 * on the PE queue
1280 */
1281 if ((mHdr->fc.subType == SIR_MAC_MGMT_BEACON ||
1282 mHdr->fc.subType == SIR_MAC_MGMT_PROBE_RSP) &&
1283 !pe_filter_bcn_probe_frame(mac, mHdr, pRxPacketInfo)) {
1284 cds_pkt_return_packet(pVosPkt);
1285 pVosPkt = NULL;
1286 return QDF_STATUS_SUCCESS;
1287 }
1288
1289 /*
1290 * Post Probe Req frames to Scan queue and return
1291 */
1292 if (mHdr->fc.subType == SIR_MAC_MGMT_PROBE_REQ) {
1293 qdf_status = pe_handle_probe_req_frames(mac, pVosPkt);
1294 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
1295 cds_pkt_return_packet(pVosPkt);
1296 pVosPkt = NULL;
1297 }
1298 return qdf_status;
1299 }
1300
1301 if (QDF_STATUS_SUCCESS !=
1302 pe_drop_pending_rx_mgmt_frames(mac, mHdr, pVosPkt))
1303 return QDF_STATUS_E_FAILURE;
1304
1305 /* Forward to MAC via mesg = SIR_BB_XPORT_MGMT_MSG */
1306 msg.type = SIR_BB_XPORT_MGMT_MSG;
1307 msg.bodyptr = pVosPkt;
1308 msg.bodyval = 0;
1309
1310 if (QDF_STATUS_SUCCESS != sys_bbt_process_message_core(mac,
1311 &msg,
1312 mHdr->fc.type,
1313 mHdr->fc.subType)) {
1314 cds_pkt_return_packet(pVosPkt);
1315 pVosPkt = NULL;
1316 /*
1317 * Decrement sys_bbt_pending_mgmt_count if packet
1318 * is dropped before posting to LIM
1319 */
1320 lim_decrement_pending_mgmt_count(mac);
1321 return QDF_STATUS_E_FAILURE;
1322 }
1323
1324 return QDF_STATUS_SUCCESS;
1325 }
1326
pe_register_mgmt_rx_frm_callback(struct mac_context * mac_ctx)1327 void pe_register_mgmt_rx_frm_callback(struct mac_context *mac_ctx)
1328 {
1329 QDF_STATUS status;
1330 struct mgmt_txrx_mgmt_frame_cb_info frm_cb_info;
1331
1332 frm_cb_info.frm_type = MGMT_FRAME_TYPE_ALL;
1333 frm_cb_info.mgmt_rx_cb = pe_handle_mgmt_frame;
1334
1335 status = wlan_mgmt_txrx_register_rx_cb(mac_ctx->psoc,
1336 WLAN_UMAC_COMP_MLME, &frm_cb_info, 1);
1337 if (status != QDF_STATUS_SUCCESS)
1338 pe_err("Registering the PE Handle with MGMT TXRX layer has failed");
1339
1340 wma_register_mgmt_frm_client();
1341 }
1342
pe_deregister_mgmt_rx_frm_callback(struct mac_context * mac_ctx)1343 void pe_deregister_mgmt_rx_frm_callback(struct mac_context *mac_ctx)
1344 {
1345 QDF_STATUS status;
1346 struct mgmt_txrx_mgmt_frame_cb_info frm_cb_info;
1347
1348 frm_cb_info.frm_type = MGMT_FRAME_TYPE_ALL;
1349 frm_cb_info.mgmt_rx_cb = pe_handle_mgmt_frame;
1350
1351 status = wlan_mgmt_txrx_deregister_rx_cb(mac_ctx->psoc,
1352 WLAN_UMAC_COMP_MLME, &frm_cb_info, 1);
1353 if (status != QDF_STATUS_SUCCESS)
1354 pe_err("Deregistering the PE Handle with MGMT TXRX layer has failed");
1355
1356 wma_de_register_mgmt_frm_client();
1357 }
1358
1359
1360 /**
1361 * pe_register_callbacks_with_wma() - register SME and PE callback functions to
1362 * WMA.
1363 * (function documentation in lim_api.h)
1364 */
pe_register_callbacks_with_wma(struct mac_context * mac,struct sme_ready_req * ready_req)1365 void pe_register_callbacks_with_wma(struct mac_context *mac,
1366 struct sme_ready_req *ready_req)
1367 {
1368 QDF_STATUS status;
1369
1370 status = wma_register_roaming_callbacks(
1371 ready_req->csr_roam_auth_event_handle_cb,
1372 ready_req->pe_roam_synch_cb,
1373 ready_req->pe_disconnect_cb,
1374 ready_req->pe_roam_set_ie_cb);
1375 if (status != QDF_STATUS_SUCCESS)
1376 pe_err("Registering roaming callbacks with WMA failed");
1377 }
1378
1379 void
lim_received_hb_handler(struct mac_context * mac,uint32_t chan_freq,struct pe_session * pe_session)1380 lim_received_hb_handler(struct mac_context *mac, uint32_t chan_freq,
1381 struct pe_session *pe_session)
1382 {
1383 if (chan_freq == 0 || chan_freq == pe_session->curr_op_freq)
1384 pe_session->LimRxedBeaconCntDuringHB++;
1385
1386 pe_session->pmmOffloadInfo.bcnmiss = false;
1387 } /*** lim_init_wds_info_params() ***/
1388
1389 /** -------------------------------------------------------------
1390 \fn lim_update_overlap_sta_param
1391 \brief Updates overlap cache and param data structure
1392 \param struct mac_context * mac
1393 \param tSirMacAddr bssId
1394 \param tpLimProtStaParams pStaParams
1395 \return None
1396 -------------------------------------------------------------*/
1397 void
lim_update_overlap_sta_param(struct mac_context * mac,tSirMacAddr bssId,tpLimProtStaParams pStaParams)1398 lim_update_overlap_sta_param(struct mac_context *mac, tSirMacAddr bssId,
1399 tpLimProtStaParams pStaParams)
1400 {
1401 int i;
1402
1403 if (!pStaParams->numSta) {
1404 qdf_mem_copy(mac->lim.protStaOverlapCache[0].addr,
1405 bssId, sizeof(tSirMacAddr));
1406 mac->lim.protStaOverlapCache[0].active = true;
1407
1408 pStaParams->numSta = 1;
1409
1410 return;
1411 }
1412
1413 for (i = 0; i < LIM_PROT_STA_OVERLAP_CACHE_SIZE; i++) {
1414 if (mac->lim.protStaOverlapCache[i].active) {
1415 if (!qdf_mem_cmp
1416 (mac->lim.protStaOverlapCache[i].addr, bssId,
1417 sizeof(tSirMacAddr))) {
1418 return;
1419 }
1420 } else
1421 break;
1422 }
1423
1424 if (i == LIM_PROT_STA_OVERLAP_CACHE_SIZE) {
1425 pe_debug("Overlap cache is full");
1426 } else {
1427 qdf_mem_copy(mac->lim.protStaOverlapCache[i].addr,
1428 bssId, sizeof(tSirMacAddr));
1429 mac->lim.protStaOverlapCache[i].active = true;
1430
1431 pStaParams->numSta++;
1432 }
1433 }
1434
1435 /**
1436 * lim_enc_type_matched() - matches security type of incoming beracon with
1437 * current
1438 * @mac_ctx Pointer to Global MAC structure
1439 * @bcn Pointer to parsed Beacon structure
1440 * @session PE session entry
1441 *
1442 * This function matches security type of incoming beracon with current
1443 *
1444 * @return true if matched, false otherwise
1445 */
1446 static bool
lim_enc_type_matched(struct mac_context * mac_ctx,tpSchBeaconStruct bcn,struct pe_session * session)1447 lim_enc_type_matched(struct mac_context *mac_ctx,
1448 tpSchBeaconStruct bcn,
1449 struct pe_session *session)
1450 {
1451 if (!bcn || !session)
1452 return false;
1453
1454 /*
1455 * This is handled by sending probe req due to IOT issues so
1456 * return TRUE
1457 */
1458 if ((bcn->capabilityInfo.privacy) !=
1459 SIR_MAC_GET_PRIVACY(session->limCurrentBssCaps)) {
1460 pe_warn("Privacy bit miss match");
1461 return true;
1462 }
1463
1464 /* Open */
1465 if ((bcn->capabilityInfo.privacy == 0) &&
1466 (session->encryptType == eSIR_ED_NONE))
1467 return true;
1468
1469 /* WEP */
1470 if ((bcn->capabilityInfo.privacy == 1) &&
1471 (bcn->wpaPresent == 0) && (bcn->rsnPresent == 0) &&
1472 ((session->encryptType == eSIR_ED_WEP40) ||
1473 (session->encryptType == eSIR_ED_WEP104)
1474 #ifdef FEATURE_WLAN_WAPI
1475 || (session->encryptType == eSIR_ED_WPI)
1476 #endif
1477 ))
1478 return true;
1479
1480 /* WPA OR RSN*/
1481 if ((bcn->capabilityInfo.privacy == 1) &&
1482 ((bcn->wpaPresent == 1) || (bcn->rsnPresent == 1)) &&
1483 ((session->encryptType == eSIR_ED_TKIP) ||
1484 (session->encryptType == eSIR_ED_CCMP) ||
1485 (session->encryptType == eSIR_ED_GCMP) ||
1486 (session->encryptType == eSIR_ED_GCMP_256) ||
1487 (session->encryptType == eSIR_ED_AES_128_CMAC)))
1488 return true;
1489
1490 /*
1491 * For HS2.0, RSN ie is not present
1492 * in beacon. Therefore no need to
1493 * check for security type in case
1494 * OSEN session.
1495 * For WPS registration session no need to detect
1496 * detect security mismatch as it won't match and
1497 * driver may end up sending probe request without
1498 * WPS IE during WPS registration process.
1499 */
1500 if (session->isOSENConnection ||
1501 session->wps_registration)
1502 return true;
1503
1504 pe_debug("AP:: Privacy %d WPA %d RSN %d, SELF:: Privacy %d Enc %d OSEN %d WPS %d",
1505 bcn->capabilityInfo.privacy, bcn->wpaPresent, bcn->rsnPresent,
1506 SIR_MAC_GET_PRIVACY(session->limCurrentBssCaps),
1507 session->encryptType, session->isOSENConnection,
1508 session->wps_registration);
1509
1510 return false;
1511 }
1512
1513 void
lim_detect_change_in_ap_capabilities(struct mac_context * mac,tpSirProbeRespBeacon pBeacon,struct pe_session * pe_session,bool is_bcn)1514 lim_detect_change_in_ap_capabilities(struct mac_context *mac,
1515 tpSirProbeRespBeacon pBeacon,
1516 struct pe_session *pe_session,
1517 bool is_bcn)
1518 {
1519 uint8_t len;
1520 uint32_t new_chan_freq;
1521 QDF_STATUS status = QDF_STATUS_SUCCESS;
1522 bool security_caps_matched = true;
1523 uint16_t ap_cap;
1524
1525 ap_cap = lim_get_u16((uint8_t *) &pBeacon->capabilityInfo);
1526 new_chan_freq = pBeacon->chan_freq;
1527
1528 security_caps_matched = lim_enc_type_matched(mac, pBeacon,
1529 pe_session);
1530 if ((false == pe_session->limSentCapsChangeNtf) &&
1531 (((!lim_is_null_ssid(&pBeacon->ssId)) &&
1532 lim_cmp_ssid(&pBeacon->ssId, pe_session)) ||
1533 ((SIR_MAC_GET_ESS(ap_cap) !=
1534 SIR_MAC_GET_ESS(pe_session->limCurrentBssCaps)) ||
1535 (SIR_MAC_GET_PRIVACY(ap_cap) !=
1536 SIR_MAC_GET_PRIVACY(pe_session->limCurrentBssCaps)) ||
1537 (SIR_MAC_GET_QOS(ap_cap) !=
1538 SIR_MAC_GET_QOS(pe_session->limCurrentBssCaps)) ||
1539 ((new_chan_freq != pe_session->curr_op_freq) &&
1540 (new_chan_freq != 0)) ||
1541 (false == security_caps_matched)
1542 ))) {
1543 if (!pe_session->fWaitForProbeRsp || is_bcn) {
1544 /* If Beacon capabilities is not matching with the current capability,
1545 * then send unicast probe request to AP and take decision after
1546 * receiving probe response */
1547 if (pe_session->fIgnoreCapsChange) {
1548 pe_debug_rl("Ignore the Capability change as probe rsp Capability matched");
1549 return;
1550 }
1551 pe_session->fWaitForProbeRsp = true;
1552 pe_info(QDF_MAC_ADDR_FMT ": capabilities are not matching, sending directed probe request",
1553 QDF_MAC_ADDR_REF(pe_session->bssId));
1554 status =
1555 lim_send_probe_req_mgmt_frame(
1556 mac, &pe_session->ssId,
1557 pe_session->bssId,
1558 pe_session->curr_op_freq,
1559 pe_session->self_mac_addr,
1560 pe_session->dot11mode,
1561 NULL, NULL);
1562
1563 if (QDF_STATUS_SUCCESS != status) {
1564 pe_err("send ProbeReq failed");
1565 pe_session->fWaitForProbeRsp = false;
1566 }
1567 return;
1568 }
1569 /**
1570 * BSS capabilities have changed.
1571 * Inform Roaming.
1572 */
1573 len = sizeof(tSirMacCapabilityInfo) + sizeof(tSirMacAddr) + sizeof(uint8_t) + 3 * sizeof(uint8_t) + /* reserved fields */
1574 pBeacon->ssId.length + 1;
1575
1576 if (new_chan_freq != pe_session->curr_op_freq) {
1577 pe_info(QDF_MAC_ADDR_FMT ": Channel freq Change from %d --> %d Ignoring beacon!",
1578 QDF_MAC_ADDR_REF(pe_session->bssId),
1579 pe_session->curr_op_freq, new_chan_freq);
1580 return;
1581 }
1582
1583 /**
1584 * When Cisco 1262 Enterprise APs are configured with WPA2-PSK with
1585 * AES+TKIP Pairwise ciphers and WEP-40 Group cipher, they do not set
1586 * the privacy bit in Beacons (wpa/rsnie is still present in beacons),
1587 * the privacy bit is set in Probe and association responses.
1588 * Due to this anomaly, we detect a change in
1589 * AP capabilities when we receive a beacon after association and
1590 * disconnect from the AP. The following check makes sure that we can
1591 * connect to such APs
1592 */
1593 else if ((SIR_MAC_GET_PRIVACY(ap_cap) == 0) &&
1594 (pBeacon->rsnPresent || pBeacon->wpaPresent)) {
1595 pe_info_rl(QDF_MAC_ADDR_FMT ": BSS Caps (Privacy) bit 0 in beacon, but WPA or RSN IE present, Ignore Beacon!",
1596 QDF_MAC_ADDR_REF(pe_session->bssId));
1597 return;
1598 }
1599
1600 pe_session->fIgnoreCapsChange = false;
1601 pe_session->fWaitForProbeRsp = false;
1602 pe_session->limSentCapsChangeNtf = true;
1603 pe_info(QDF_MAC_ADDR_FMT ": initiate Disconnect due to cap mismatch!",
1604 QDF_MAC_ADDR_REF(pe_session->bssId));
1605 lim_send_deauth_mgmt_frame(mac, REASON_UNSPEC_FAILURE,
1606 pe_session->bssId, pe_session,
1607 false);
1608 lim_tear_down_link_with_ap(mac, pe_session->peSessionId,
1609 REASON_UNSPEC_FAILURE,
1610 eLIM_HOST_DISASSOC);
1611 } else if (pe_session->fWaitForProbeRsp) {
1612 /* Only for probe response frames and matching capabilities the control
1613 * will come here. If beacon is with broadcast ssid then fWaitForProbeRsp
1614 * will be false, the control will not come here*/
1615
1616 pe_debug(QDF_MAC_ADDR_FMT ": capabilities in probe rsp are matching, so ignoring capability mismatch",
1617 QDF_MAC_ADDR_REF(pe_session->bssId));
1618 pe_session->fIgnoreCapsChange = true;
1619 pe_session->fWaitForProbeRsp = false;
1620 }
1621
1622 } /*** lim_detect_change_in_ap_capabilities() ***/
1623
1624 /* --------------------------------------------------------------------- */
1625 /**
1626 * lim_update_short_slot
1627 *
1628 * FUNCTION:
1629 * Enable/Disable short slot
1630 *
1631 * LOGIC:
1632 *
1633 * ASSUMPTIONS:
1634 *
1635 * NOTE:
1636 *
1637 * @param enable Flag to enable/disable short slot
1638 * @return None
1639 */
1640
lim_update_short_slot(struct mac_context * mac,tpSirProbeRespBeacon pBeacon,tpUpdateBeaconParams pBeaconParams,struct pe_session * pe_session)1641 QDF_STATUS lim_update_short_slot(struct mac_context *mac,
1642 tpSirProbeRespBeacon pBeacon,
1643 tpUpdateBeaconParams pBeaconParams,
1644 struct pe_session *pe_session)
1645 {
1646
1647 uint16_t ap_cap;
1648 uint32_t nShortSlot;
1649 uint32_t phyMode;
1650
1651 /* Check Admin mode first. If it is disabled just return */
1652 if (!mac->mlme_cfg->feature_flags.enable_short_slot_time_11g)
1653 return QDF_STATUS_SUCCESS;
1654
1655 /* Check for 11a mode or 11b mode. In both cases return since slot time is constant and cannot/should not change in beacon */
1656 lim_get_phy_mode(mac, &phyMode, pe_session);
1657 if ((phyMode == WNI_CFG_PHY_MODE_11A)
1658 || (phyMode == WNI_CFG_PHY_MODE_11B))
1659 return QDF_STATUS_SUCCESS;
1660
1661 ap_cap = lim_get_u16((uint8_t *) &pBeacon->capabilityInfo);
1662
1663 /* Earlier implementation: determine the appropriate short slot mode based on AP advertised modes */
1664 /* when erp is present, apply short slot always unless, prot=on && shortSlot=off */
1665 /* if no erp present, use short slot based on current ap caps */
1666
1667 /* Issue with earlier implementation : Cisco 1231 BG has shortSlot = 0, erpIEPresent and useProtection = 0 (Case4); */
1668
1669 /* Resolution : always use the shortSlot setting the capability info to decide slot time. */
1670 /* The difference between the earlier implementation and the new one is only Case4. */
1671 /*
1672 ERP IE Present | useProtection | shortSlot = QC STA Short Slot
1673 Case1 1 1 1 1 //AP should not advertise this combination.
1674 Case2 1 1 0 0
1675 Case3 1 0 1 1
1676 Case4 1 0 0 0
1677 Case5 0 1 1 1
1678 Case6 0 1 0 0
1679 Case7 0 0 1 1
1680 Case8 0 0 0 0
1681 */
1682 nShortSlot = SIR_MAC_GET_SHORT_SLOT_TIME(ap_cap);
1683
1684 if (nShortSlot != pe_session->shortSlotTimeSupported) {
1685 /* Short slot time capability of AP has changed. Adopt to it. */
1686 pe_debug("Shortslot capability of AP changed: %d",
1687 nShortSlot);
1688 ((tpSirMacCapabilityInfo) & pe_session->
1689 limCurrentBssCaps)->shortSlotTime = (uint16_t) nShortSlot;
1690 pe_session->shortSlotTimeSupported = nShortSlot;
1691 pBeaconParams->fShortSlotTime = (uint8_t) nShortSlot;
1692 pBeaconParams->paramChangeBitmap |=
1693 PARAM_SHORT_SLOT_TIME_CHANGED;
1694 }
1695 return QDF_STATUS_SUCCESS;
1696 }
1697
1698
lim_send_heart_beat_timeout_ind(struct mac_context * mac,struct pe_session * pe_session)1699 void lim_send_heart_beat_timeout_ind(struct mac_context *mac,
1700 struct pe_session *pe_session)
1701 {
1702 QDF_STATUS status;
1703 struct scheduler_msg msg = {0};
1704
1705 /* Prepare and post message to LIM Message Queue */
1706 msg.type = (uint16_t) SIR_LIM_HEART_BEAT_TIMEOUT;
1707 msg.bodyptr = pe_session;
1708 msg.bodyval = 0;
1709 pe_err("Heartbeat failure from Fw");
1710
1711 status = lim_post_msg_api(mac, &msg);
1712
1713 if (status != QDF_STATUS_SUCCESS) {
1714 pe_err("posting message: %X to LIM failed, reason: %d",
1715 msg.type, status);
1716 }
1717 }
1718
lim_ps_offload_handle_missed_beacon_ind(struct mac_context * mac,struct scheduler_msg * msg)1719 void lim_ps_offload_handle_missed_beacon_ind(struct mac_context *mac,
1720 struct scheduler_msg *msg)
1721 {
1722 struct missed_beacon_ind *missed_beacon_ind = msg->bodyptr;
1723 struct pe_session *pe_session =
1724 pe_find_session_by_vdev_id(mac, missed_beacon_ind->bss_idx);
1725
1726 if (!pe_session) {
1727 pe_err("session does not exist for vdev_id %d",
1728 missed_beacon_ind->bss_idx);
1729 return;
1730 }
1731
1732 /* Set Beacon Miss in Powersave Offload */
1733 pe_session->pmmOffloadInfo.bcnmiss = true;
1734 pe_err("Received Heart Beat Failure");
1735
1736 /* Do AP probing immediately */
1737 lim_send_heart_beat_timeout_ind(mac, pe_session);
1738 }
1739
lim_is_sb_disconnect_allowed_fl(struct pe_session * session,const char * func,uint32_t line)1740 bool lim_is_sb_disconnect_allowed_fl(struct pe_session *session,
1741 const char *func, uint32_t line)
1742 {
1743 if (session->limMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE &&
1744 session->limSmeState != eLIM_SME_WT_DISASSOC_STATE &&
1745 session->limSmeState != eLIM_SME_WT_DEAUTH_STATE)
1746 return true;
1747
1748 pe_nofl_info("%s:%u: Vdev %d (%d): limMlmState %s(%x) limSmeState %s(%x)",
1749 func, line, session->vdev_id, session->peSessionId,
1750 lim_mlm_state_str(session->limMlmState),
1751 session->limMlmState,
1752 lim_sme_state_str(session->limSmeState),
1753 session->limSmeState);
1754
1755 return false;
1756 }
1757
1758 #ifdef WLAN_SUPPORT_TWT
1759 #ifdef WLAN_TWT_CONV_SUPPORTED
lim_set_twt_peer_capabilities(struct mac_context * mac_ctx,struct qdf_mac_addr * peer_mac,tDot11fIEhe_cap * he_cap,tDot11fIEhe_op * he_op)1760 void lim_set_twt_peer_capabilities(struct mac_context *mac_ctx,
1761 struct qdf_mac_addr *peer_mac,
1762 tDot11fIEhe_cap *he_cap,
1763 tDot11fIEhe_op *he_op)
1764 {
1765 uint8_t caps = 0;
1766
1767 if (he_cap->twt_request)
1768 caps |= WLAN_TWT_CAPA_REQUESTOR;
1769
1770 if (he_cap->twt_responder)
1771 caps |= WLAN_TWT_CAPA_RESPONDER;
1772
1773 if (he_cap->broadcast_twt)
1774 caps |= WLAN_TWT_CAPA_BROADCAST;
1775
1776 if (he_cap->flex_twt_sched)
1777 caps |= WLAN_TWT_CAPA_FLEXIBLE;
1778
1779 if (he_op->twt_required)
1780 caps |= WLAN_TWT_CAPA_REQUIRED;
1781
1782 wlan_set_peer_twt_capabilities(mac_ctx->psoc, peer_mac, caps);
1783 }
1784
lim_set_twt_ext_capabilities(struct mac_context * mac_ctx,struct qdf_mac_addr * peer_mac,struct s_ext_cap * ext_cap)1785 void lim_set_twt_ext_capabilities(struct mac_context *mac_ctx,
1786 struct qdf_mac_addr *peer_mac,
1787 struct s_ext_cap *ext_cap)
1788 {
1789 uint8_t caps = 0;
1790
1791 if (ext_cap->twt_requestor_support)
1792 caps |= WLAN_TWT_CAPA_REQUESTOR;
1793
1794 if (ext_cap->twt_responder_support)
1795 caps |= WLAN_TWT_CAPA_RESPONDER;
1796
1797 wlan_set_peer_twt_capabilities(mac_ctx->psoc, peer_mac, caps);
1798 }
1799 #else
lim_set_twt_peer_capabilities(struct mac_context * mac_ctx,struct qdf_mac_addr * peer_mac,tDot11fIEhe_cap * he_cap,tDot11fIEhe_op * he_op)1800 void lim_set_twt_peer_capabilities(struct mac_context *mac_ctx,
1801 struct qdf_mac_addr *peer_mac,
1802 tDot11fIEhe_cap *he_cap,
1803 tDot11fIEhe_op *he_op)
1804 {
1805 uint8_t caps = 0;
1806
1807 if (he_cap->twt_request)
1808 caps |= WLAN_TWT_CAPA_REQUESTOR;
1809
1810 if (he_cap->twt_responder)
1811 caps |= WLAN_TWT_CAPA_RESPONDER;
1812
1813 if (he_cap->broadcast_twt)
1814 caps |= WLAN_TWT_CAPA_BROADCAST;
1815
1816 if (he_cap->flex_twt_sched)
1817 caps |= WLAN_TWT_CAPA_FLEXIBLE;
1818
1819 if (he_op->twt_required)
1820 caps |= WLAN_TWT_CAPA_REQUIRED;
1821
1822 mlme_set_twt_peer_capabilities(mac_ctx->psoc, peer_mac,
1823 caps);
1824 }
1825
lim_set_twt_ext_capabilities(struct mac_context * mac_ctx,struct qdf_mac_addr * peer_mac,struct s_ext_cap * ext_cap)1826 void lim_set_twt_ext_capabilities(struct mac_context *mac_ctx,
1827 struct qdf_mac_addr *peer_mac,
1828 struct s_ext_cap *ext_cap)
1829 {
1830 uint8_t caps = 0;
1831
1832 if (ext_cap->twt_requestor_support)
1833 caps |= WLAN_TWT_CAPA_REQUESTOR;
1834
1835 if (ext_cap->twt_responder_support)
1836 caps |= WLAN_TWT_CAPA_RESPONDER;
1837
1838 mlme_set_twt_peer_capabilities(mac_ctx->psoc, peer_mac, caps);
1839 }
1840 #endif /* WLAN_TWT_CONV_SUPPORTED */
1841 #endif /* WLAN_SUPPORT_TWT */
1842
1843 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
pe_update_crypto_params(struct mac_context * mac_ctx,struct pe_session * ft_session,struct roam_offload_synch_ind * roam_synch)1844 static void pe_update_crypto_params(struct mac_context *mac_ctx,
1845 struct pe_session *ft_session,
1846 struct roam_offload_synch_ind *roam_synch)
1847 {
1848 uint8_t *assoc_ies;
1849 uint32_t assoc_ies_len;
1850 uint8_t ies_offset = WLAN_REASSOC_REQ_IES_OFFSET;
1851 tpSirMacMgmtHdr hdr;
1852 const uint8_t *wpa_ie, *rsn_ie;
1853 uint32_t wpa_oui;
1854 struct wlan_crypto_params *crypto_params;
1855
1856 hdr = (tpSirMacMgmtHdr)((uint8_t *)roam_synch +
1857 roam_synch->reassoc_req_offset);
1858 if (hdr->fc.type == SIR_MAC_MGMT_FRAME &&
1859 hdr->fc.subType == SIR_MAC_MGMT_ASSOC_REQ)
1860 ies_offset = WLAN_ASSOC_REQ_IES_OFFSET;
1861
1862 if (roam_synch->reassoc_req_length <
1863 (sizeof(tSirMacMgmtHdr) + ies_offset)) {
1864 pe_err("invalid reassoc req len %d",
1865 roam_synch->reassoc_req_length);
1866 return;
1867 }
1868
1869 ft_session->limRmfEnabled = false;
1870
1871 assoc_ies = (uint8_t *)roam_synch + roam_synch->reassoc_req_offset +
1872 sizeof(tSirMacMgmtHdr) + ies_offset;
1873 assoc_ies_len = roam_synch->reassoc_req_length -
1874 sizeof(tSirMacMgmtHdr) - ies_offset;
1875
1876 rsn_ie = wlan_get_ie_ptr_from_eid(WLAN_ELEMID_RSN, assoc_ies,
1877 assoc_ies_len);
1878 wpa_oui = WLAN_WPA_SEL(WLAN_WPA_OUI_TYPE);
1879 wpa_ie = wlan_get_vendor_ie_ptr_from_oui((uint8_t *)&wpa_oui,
1880 WLAN_OUI_SIZE, assoc_ies,
1881 assoc_ies_len);
1882 if (!wpa_ie && !rsn_ie) {
1883 pe_nofl_debug("RSN and WPA IE not present");
1884 return;
1885 }
1886
1887 wlan_set_vdev_crypto_prarams_from_ie(ft_session->vdev, assoc_ies,
1888 assoc_ies_len);
1889 ft_session->limRmfEnabled =
1890 lim_get_vdev_rmf_capable(mac_ctx, ft_session);
1891 crypto_params = wlan_crypto_vdev_get_crypto_params(ft_session->vdev);
1892 if (!crypto_params) {
1893 pe_err("crypto params is null");
1894 return;
1895 }
1896
1897 ft_session->connected_akm =
1898 lim_get_connected_akm(ft_session, crypto_params->ucastcipherset,
1899 crypto_params->authmodeset,
1900 crypto_params->key_mgmt);
1901 ft_session->encryptType =
1902 lim_get_encrypt_ed_type(crypto_params->ucastcipherset);
1903 pe_nofl_debug("vdev %d roam auth 0x%x akm 0x%0x rsn_caps 0x%x ucastcipher 0x%x akm %d enc: %d",
1904 ft_session->vdev_id,
1905 crypto_params->authmodeset,
1906 crypto_params->key_mgmt,
1907 crypto_params->rsn_caps,
1908 crypto_params->ucastcipherset,
1909 ft_session->connected_akm,
1910 ft_session->encryptType);
1911 }
1912
1913 /**
1914 * sir_parse_bcn_fixed_fields() - Parse fixed fields in Beacon IE's
1915 *
1916 * @mac_ctx: MAC Context
1917 * @beacon_struct: Beacon/Probe Response structure
1918 * @buf: Fixed Fields buffer
1919 */
sir_parse_bcn_fixed_fields(struct mac_context * mac_ctx,tpSirProbeRespBeacon beacon_struct,uint8_t * buf)1920 static void sir_parse_bcn_fixed_fields(struct mac_context *mac_ctx,
1921 tpSirProbeRespBeacon beacon_struct,
1922 uint8_t *buf)
1923 {
1924 tDot11fFfCapabilities dst;
1925
1926 beacon_struct->timeStamp[0] = lim_get_u32(buf);
1927 beacon_struct->timeStamp[1] = lim_get_u32(buf + 4);
1928 buf += 8;
1929
1930 beacon_struct->beaconInterval = lim_get_u16(buf);
1931 buf += 2;
1932
1933 dot11f_unpack_ff_capabilities(mac_ctx, buf, &dst);
1934
1935 sir_copy_caps_info(mac_ctx, dst, beacon_struct);
1936 }
1937
1938 static QDF_STATUS
lim_roam_gen_mbssid_beacon(struct mac_context * mac,struct roam_offload_synch_ind * roam_ind,tpSirProbeRespBeacon parsed_frm,uint8_t ** ie,uint32_t * ie_len)1939 lim_roam_gen_mbssid_beacon(struct mac_context *mac,
1940 struct roam_offload_synch_ind *roam_ind,
1941 tpSirProbeRespBeacon parsed_frm,
1942 uint8_t **ie, uint32_t *ie_len)
1943 {
1944 qdf_list_t *scan_list;
1945 struct mgmt_rx_event_params rx_param = {0};
1946 uint8_t list_count = 0, i;
1947 QDF_STATUS status = QDF_STATUS_E_FAILURE;
1948 qdf_list_node_t *next_node = NULL, *cur_node = NULL;
1949 struct scan_cache_node *scan_node;
1950 struct scan_cache_entry *scan_entry;
1951 uint8_t *bcn_prb_ptr;
1952 uint32_t nontx_bcn_prbrsp_len = 0, offset, length;
1953 uint8_t *nontx_bcn_prbrsp = NULL;
1954 uint8_t ie_offset;
1955
1956 ie_offset = SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET;
1957 bcn_prb_ptr = (uint8_t *)roam_ind +
1958 roam_ind->beacon_probe_resp_offset;
1959
1960 rx_param.chan_freq = roam_ind->chan_freq;
1961 rx_param.pdev_id = wlan_objmgr_pdev_get_pdev_id(mac->pdev);
1962 rx_param.rssi = roam_ind->rssi;
1963
1964 /* Set all per chain rssi as invalid */
1965 for (i = 0; i < WLAN_MGMT_TXRX_HOST_MAX_ANTENNA; i++)
1966 rx_param.rssi_ctl[i] = WLAN_INVALID_PER_CHAIN_RSSI;
1967
1968 scan_list = util_scan_unpack_beacon_frame(mac->pdev, bcn_prb_ptr,
1969 roam_ind->beacon_probe_resp_length,
1970 MGMT_SUBTYPE_BEACON, &rx_param);
1971 if (!scan_list) {
1972 pe_err("failed to parse");
1973 return QDF_STATUS_E_FAILURE;
1974 }
1975
1976 list_count = qdf_list_size(scan_list);
1977 status = qdf_list_peek_front(scan_list, &cur_node);
1978 if (QDF_IS_STATUS_ERROR(status) || !cur_node) {
1979 pe_debug("list peek front failure. list size %d", list_count);
1980 goto error;
1981 }
1982
1983 for (i = 1; i < list_count; i++) {
1984 scan_node = qdf_container_of(cur_node,
1985 struct scan_cache_node, node);
1986 scan_entry = scan_node->entry;
1987 if (qdf_is_macaddr_equal(&roam_ind->bssid,
1988 &scan_entry->bssid)) {
1989 pe_debug("matched BSSID "QDF_MAC_ADDR_FMT" bcn len %d profiles %d",
1990 QDF_MAC_ADDR_REF(scan_entry->bssid.bytes),
1991 scan_entry->raw_frame.len,
1992 list_count);
1993 nontx_bcn_prbrsp = scan_entry->raw_frame.ptr;
1994 nontx_bcn_prbrsp_len = scan_entry->raw_frame.len;
1995 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE,
1996 QDF_TRACE_LEVEL_DEBUG,
1997 scan_entry->raw_frame.ptr,
1998 nontx_bcn_prbrsp_len);
1999 break;
2000 }
2001 status = qdf_list_peek_next(scan_list, cur_node, &next_node);
2002 if (QDF_IS_STATUS_ERROR(status) || !next_node) {
2003 pe_debug("list remove failure i:%d, lsize:%d",
2004 i, list_count);
2005 goto error;
2006 }
2007 cur_node = next_node;
2008 }
2009
2010 if (!nontx_bcn_prbrsp_len) {
2011 pe_debug("failed to generate/find MBSSID beacon");
2012 goto error;
2013 }
2014
2015 if (roam_ind->is_beacon) {
2016 offset = SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET;
2017 length = nontx_bcn_prbrsp_len - SIR_MAC_HDR_LEN_3A;
2018 if (sir_parse_beacon_ie(mac, parsed_frm,
2019 &nontx_bcn_prbrsp[offset],
2020 length) != QDF_STATUS_SUCCESS ||
2021 !parsed_frm->ssidPresent) {
2022 pe_err("Parse error Beacon, length: %d",
2023 roam_ind->beacon_probe_resp_length);
2024 status = QDF_STATUS_E_FAILURE;
2025 goto error;
2026 }
2027 } else {
2028 offset = SIR_MAC_HDR_LEN_3A;
2029 length = nontx_bcn_prbrsp_len - SIR_MAC_HDR_LEN_3A;
2030 if (sir_convert_probe_frame2_struct(mac,
2031 &nontx_bcn_prbrsp[offset],
2032 length,
2033 parsed_frm) != QDF_STATUS_SUCCESS ||
2034 !parsed_frm->ssidPresent) {
2035 pe_err("Parse error ProbeResponse, length: %d",
2036 roam_ind->beacon_probe_resp_length);
2037 status = QDF_STATUS_E_FAILURE;
2038 goto error;
2039 }
2040 }
2041
2042 *ie_len = nontx_bcn_prbrsp_len - ie_offset;
2043 if (*ie_len) {
2044 *ie = qdf_mem_malloc(*ie_len);
2045 if (!*ie)
2046 return QDF_STATUS_E_NOMEM;
2047 qdf_mem_copy(*ie, nontx_bcn_prbrsp + ie_offset, *ie_len);
2048 pe_debug("beacon/probe Ie length: %d", *ie_len);
2049 }
2050 error:
2051 for (i = 0; i < list_count; i++) {
2052 status = qdf_list_remove_front(scan_list, &next_node);
2053 if (QDF_IS_STATUS_ERROR(status) || !next_node) {
2054 pe_debug("list remove failure i:%d, lsize:%d",
2055 i, list_count);
2056 break;
2057 }
2058 scan_node = qdf_container_of(next_node,
2059 struct scan_cache_node, node);
2060 util_scan_free_cache_entry(scan_node->entry);
2061 qdf_mem_free(scan_node);
2062 }
2063 qdf_mem_free(scan_list);
2064
2065 return status;
2066 }
2067
2068 static QDF_STATUS
lim_roam_gen_beacon_descr(struct mac_context * mac,uint8_t * bcn_prb_ptr,uint16_t bcn_prb_len,bool is_mlo_link,struct roam_offload_synch_ind * roam_ind,tpSirProbeRespBeacon parsed_frm,uint8_t ** ie,uint32_t * ie_len,struct qdf_mac_addr * bssid)2069 lim_roam_gen_beacon_descr(struct mac_context *mac,
2070 uint8_t *bcn_prb_ptr,
2071 uint16_t bcn_prb_len, bool is_mlo_link,
2072 struct roam_offload_synch_ind *roam_ind,
2073 tpSirProbeRespBeacon parsed_frm,
2074 uint8_t **ie, uint32_t *ie_len,
2075 struct qdf_mac_addr *bssid)
2076 {
2077 QDF_STATUS status;
2078 tpSirMacMgmtHdr mac_hdr;
2079 uint8_t ie_offset;
2080 bool is_beacon;
2081
2082 mac_hdr = (tpSirMacMgmtHdr)bcn_prb_ptr;
2083 ie_offset = SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET;
2084
2085 if (qdf_is_macaddr_zero((struct qdf_mac_addr *)mac_hdr->bssId)) {
2086 pe_debug("bssid is 0 in beacon/probe update it with bssId"
2087 QDF_MAC_ADDR_FMT "in sync ind",
2088 QDF_MAC_ADDR_REF(bssid->bytes));
2089 qdf_mem_copy(mac_hdr->bssId, bssid->bytes,
2090 sizeof(tSirMacAddr));
2091 }
2092
2093 is_beacon = is_mlo_link ? roam_ind->is_link_beacon : roam_ind->is_beacon;
2094
2095 if ((!is_multi_link_roam(roam_ind)) &&
2096 (qdf_mem_cmp(bssid->bytes,
2097 &mac_hdr->bssId, QDF_MAC_ADDR_SIZE) != 0)) {
2098 pe_debug("LFR3:MBSSID Beacon/Prb Rsp: %d bssid "
2099 QDF_MAC_ADDR_FMT,
2100 roam_ind->is_beacon,
2101 QDF_MAC_ADDR_REF(mac_hdr->bssId));
2102 /*
2103 * Its a MBSSID non-tx BSS roaming scenario.
2104 * Generate non tx BSS beacon/probe response
2105 */
2106 status = lim_roam_gen_mbssid_beacon(mac,
2107 roam_ind,
2108 parsed_frm,
2109 ie, ie_len);
2110 if (QDF_IS_STATUS_ERROR(status)) {
2111 pe_err("failed to gen mbssid beacon");
2112 return QDF_STATUS_E_FAILURE;
2113 }
2114 } else {
2115 if (is_beacon) {
2116 if (sir_parse_beacon_ie(mac, parsed_frm,
2117 &bcn_prb_ptr[SIR_MAC_HDR_LEN_3A +
2118 SIR_MAC_B_PR_SSID_OFFSET],
2119 bcn_prb_len - SIR_MAC_HDR_LEN_3A) !=
2120 QDF_STATUS_SUCCESS ||
2121 !parsed_frm->ssidPresent) {
2122 pe_err("Parse error Beacon, length: %d",
2123 bcn_prb_len);
2124 return QDF_STATUS_E_FAILURE;
2125 }
2126 } else {
2127 if (sir_convert_probe_frame2_struct(mac,
2128 &bcn_prb_ptr[SIR_MAC_HDR_LEN_3A],
2129 bcn_prb_len -
2130 SIR_MAC_HDR_LEN_3A, parsed_frm) !=
2131 QDF_STATUS_SUCCESS ||
2132 !parsed_frm->ssidPresent) {
2133 pe_err("Parse error ProbeResponse, length: %d",
2134 bcn_prb_len);
2135 return QDF_STATUS_E_FAILURE;
2136 }
2137 }
2138 /* 24 byte MAC header and 12 byte to ssid IE */
2139 if (bcn_prb_len > ie_offset) {
2140 *ie_len = bcn_prb_len - ie_offset;
2141 *ie = qdf_mem_malloc(*ie_len);
2142 if (!*ie)
2143 return QDF_STATUS_E_NOMEM;
2144 qdf_mem_copy(*ie, bcn_prb_ptr + ie_offset, *ie_len);
2145 pe_debug("beacon/probe Ie length: %d", *ie_len);
2146 }
2147 }
2148 /*
2149 * For probe response, unpack core parses beacon interval, capabilities,
2150 * timestamp. For beacon IEs, these fields are not parsed.
2151 */
2152 if (is_beacon)
2153 sir_parse_bcn_fixed_fields(mac, parsed_frm,
2154 &bcn_prb_ptr[SIR_MAC_HDR_LEN_3A]);
2155
2156 return QDF_STATUS_SUCCESS;
2157 }
2158
2159 static QDF_STATUS
lim_roam_fill_bss_descr(struct mac_context * mac,struct roam_offload_synch_ind * roam_synch_ind,struct bss_description * bss_desc_ptr,struct pe_session * session)2160 lim_roam_fill_bss_descr(struct mac_context *mac,
2161 struct roam_offload_synch_ind *roam_synch_ind,
2162 struct bss_description *bss_desc_ptr,
2163 struct pe_session *session)
2164 {
2165 uint32_t ie_len = 0;
2166 tpSirProbeRespBeacon parsed_frm_ptr = NULL;
2167 tpSirMacMgmtHdr mac_hdr;
2168 uint8_t *bcn_proberesp_ptr = NULL;
2169 uint16_t bcn_proberesp_len = 0;
2170 QDF_STATUS status = QDF_STATUS_SUCCESS;
2171 uint8_t *ie = NULL;
2172 struct qdf_mac_addr bssid;
2173 bool is_mlo_link;
2174 uint8_t vdev_id = session->vdev_id;
2175 struct element_info frame;
2176 struct cm_roam_values_copy mdie_cfg = {0};
2177
2178 bcn_proberesp_ptr = (uint8_t *)roam_synch_ind +
2179 roam_synch_ind->beacon_probe_resp_offset;
2180 bcn_proberesp_len = roam_synch_ind->beacon_probe_resp_length;
2181
2182 frame.ptr = NULL;
2183 frame.len = 0;
2184 if (is_multi_link_roam(roam_synch_ind)) {
2185 mlo_get_sta_link_mac_addr(vdev_id, roam_synch_ind, &bssid);
2186 is_mlo_link = wlan_vdev_mlme_get_is_mlo_link(mac->psoc, vdev_id);
2187
2188 status = wlan_scan_get_entry_by_mac_addr(mac->pdev, &bssid,
2189 &frame);
2190 if (QDF_IS_STATUS_ERROR(status) || !frame.len) {
2191 pe_err("Failed to get scan entry for " QDF_MAC_ADDR_FMT,
2192 QDF_MAC_ADDR_REF(bssid.bytes));
2193 return status;
2194 }
2195 bcn_proberesp_ptr = frame.ptr;
2196 bcn_proberesp_len = frame.len;
2197 } else {
2198 bssid = roam_synch_ind->bssid;
2199 is_mlo_link = false;
2200 }
2201
2202 mac_hdr = (tpSirMacMgmtHdr)bcn_proberesp_ptr;
2203 parsed_frm_ptr = qdf_mem_malloc(sizeof(tSirProbeRespBeacon));
2204 if (!parsed_frm_ptr) {
2205 status = QDF_STATUS_E_NOMEM;
2206 goto done;
2207 }
2208
2209 if (bcn_proberesp_len <= SIR_MAC_HDR_LEN_3A) {
2210 pe_err("very few bytes in synchInd %s beacon / probe resp frame! length: %d",
2211 is_mlo_link ? "link" : "", bcn_proberesp_len);
2212 status = QDF_STATUS_E_FAILURE;
2213 goto done;
2214 }
2215
2216 pe_debug("LFR3:Beacon/Prb Rsp: %d bssid " QDF_MAC_ADDR_FMT
2217 " beacon " QDF_MAC_ADDR_FMT,
2218 is_mlo_link ? roam_synch_ind->is_link_beacon :
2219 roam_synch_ind->is_beacon,
2220 QDF_MAC_ADDR_REF(bssid.bytes),
2221 QDF_MAC_ADDR_REF(mac_hdr->bssId));
2222 mgmt_txrx_frame_hex_dump(bcn_proberesp_ptr, bcn_proberesp_len, false);
2223
2224 status = lim_roam_gen_beacon_descr(mac, bcn_proberesp_ptr,
2225 bcn_proberesp_len, is_mlo_link,
2226 roam_synch_ind, parsed_frm_ptr,
2227 &ie, &ie_len,
2228 &bssid);
2229 if (QDF_IS_STATUS_ERROR(status)) {
2230 pe_err("Failed to parse beacon");
2231 status = QDF_STATUS_E_FAILURE;
2232 goto done;
2233 }
2234
2235 /*
2236 * Length of BSS description is without length of
2237 * length itself and length of pointer
2238 * that holds ieFields
2239 *
2240 * struct bss_description
2241 * +--------+---------------------------------+---------------+
2242 * | length | other fields | pointer to IEs|
2243 * +--------+---------------------------------+---------------+
2244 * ^
2245 * ieFields
2246 */
2247 bss_desc_ptr->length = (uint16_t) (offsetof(struct bss_description,
2248 ieFields[0]) -
2249 sizeof(bss_desc_ptr->length) + ie_len);
2250
2251 bss_desc_ptr->fProbeRsp = !(is_mlo_link ?
2252 roam_synch_ind->is_link_beacon :
2253 roam_synch_ind->is_beacon);
2254 bss_desc_ptr->rssi = roam_synch_ind->rssi;
2255 /* Copy Timestamp */
2256 bss_desc_ptr->scansystimensec = qdf_get_monotonic_boottime_ns();
2257
2258 if (is_multi_link_roam(roam_synch_ind)) {
2259 bss_desc_ptr->chan_freq =
2260 mlo_roam_get_chan_freq(vdev_id, roam_synch_ind);
2261 } else if (parsed_frm_ptr->he_op.oper_info_6g_present) {
2262 bss_desc_ptr->chan_freq = wlan_reg_chan_band_to_freq(mac->pdev,
2263 parsed_frm_ptr->he_op.oper_info_6g.info.primary_ch,
2264 BIT(REG_BAND_6G));
2265 } else if (parsed_frm_ptr->dsParamsPresent) {
2266 bss_desc_ptr->chan_freq = parsed_frm_ptr->chan_freq;
2267 } else if (parsed_frm_ptr->HTInfo.present) {
2268 bss_desc_ptr->chan_freq =
2269 wlan_reg_legacy_chan_to_freq(mac->pdev,
2270 parsed_frm_ptr->HTInfo.primaryChannel);
2271 } else {
2272 /*
2273 * If DS Params or HTIE is not present in the probe resp or
2274 * beacon, then use the channel frequency provided by firmware
2275 * to fill the channel in the BSS descriptor.*/
2276 bss_desc_ptr->chan_freq = roam_synch_ind->chan_freq;
2277 }
2278
2279 bss_desc_ptr->nwType = lim_get_nw_type(mac, bss_desc_ptr->chan_freq,
2280 SIR_MAC_MGMT_FRAME,
2281 parsed_frm_ptr);
2282
2283 bss_desc_ptr->sinr = 0;
2284 bss_desc_ptr->beaconInterval = parsed_frm_ptr->beaconInterval;
2285 bss_desc_ptr->timeStamp[0] = parsed_frm_ptr->timeStamp[0];
2286 bss_desc_ptr->timeStamp[1] = parsed_frm_ptr->timeStamp[1];
2287 qdf_mem_copy(&bss_desc_ptr->capabilityInfo,
2288 &bcn_proberesp_ptr[SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_CAPAB_OFFSET], 2);
2289
2290 qdf_mem_copy((uint8_t *) &bss_desc_ptr->bssId,
2291 (uint8_t *)&bssid.bytes,
2292 sizeof(tSirMacAddr));
2293
2294 qdf_mem_copy((uint8_t *)&bss_desc_ptr->seq_ctrl,
2295 (uint8_t *)&mac_hdr->seqControl,
2296 sizeof(tSirMacSeqCtl));
2297
2298 bss_desc_ptr->received_time =
2299 (uint64_t)qdf_mc_timer_get_system_time();
2300 if (parsed_frm_ptr->mdiePresent) {
2301 bss_desc_ptr->mdiePresent = parsed_frm_ptr->mdiePresent;
2302 qdf_mem_copy((uint8_t *)bss_desc_ptr->mdie,
2303 (uint8_t *)parsed_frm_ptr->mdie,
2304 SIR_MDIE_SIZE);
2305
2306 mdie_cfg.bool_value = true;
2307 mdie_cfg.uint_value =
2308 (bss_desc_ptr->mdie[1] << 8) | (bss_desc_ptr->mdie[0]);
2309
2310 wlan_cm_roam_cfg_set_value(mac->psoc, vdev_id,
2311 MOBILITY_DOMAIN, &mdie_cfg);
2312 }
2313 pe_debug("chan: %d rssi: %d ie_len %d mdie_present:%d mdie = %02x %02x %02x",
2314 bss_desc_ptr->chan_freq,
2315 bss_desc_ptr->rssi, ie_len, bss_desc_ptr->mdiePresent,
2316 bss_desc_ptr->mdie[0], bss_desc_ptr->mdie[1], bss_desc_ptr->mdie[2]);
2317
2318 if (ie_len) {
2319 qdf_mem_copy(&bss_desc_ptr->ieFields,
2320 ie, ie_len);
2321 qdf_mem_free(ie);
2322 } else {
2323 pe_err("Beacon/Probe rsp doesn't have any IEs");
2324 status = QDF_STATUS_E_FAILURE;
2325 goto done;
2326 }
2327 done:
2328 qdf_mem_free(frame.ptr);
2329 qdf_mem_free(parsed_frm_ptr);
2330 return status;
2331 }
2332
2333 #if defined(WLAN_FEATURE_FILS_SK)
2334 /**
2335 * lim_copy_and_free_hlp_data_from_session - Copy HLP info
2336 * @session_ptr: PE session
2337 * @roam_sync_ind_ptr: Roam Synch Indication pointer
2338 *
2339 * This API is used to copy the parsed HLP info from PE session
2340 * to roam synch indication data. THe HLP info is expected to be
2341 * parsed/stored in PE session already from assoc IE's received
2342 * from fw as part of Roam Synch Indication.
2343 *
2344 * Return: None
2345 */
2346 static void
lim_copy_and_free_hlp_data_from_session(struct pe_session * session_ptr,struct roam_offload_synch_ind * roam_sync_ind_ptr)2347 lim_copy_and_free_hlp_data_from_session(struct pe_session *session_ptr,
2348 struct roam_offload_synch_ind
2349 *roam_sync_ind_ptr)
2350 {
2351 if (session_ptr->fils_info->hlp_data &&
2352 session_ptr->fils_info->hlp_data_len) {
2353 cds_copy_hlp_info(&session_ptr->fils_info->dst_mac,
2354 &session_ptr->fils_info->src_mac,
2355 session_ptr->fils_info->hlp_data_len,
2356 session_ptr->fils_info->hlp_data,
2357 &roam_sync_ind_ptr->dst_mac,
2358 &roam_sync_ind_ptr->src_mac,
2359 &roam_sync_ind_ptr->hlp_data_len,
2360 roam_sync_ind_ptr->hlp_data);
2361
2362 qdf_mem_free(session_ptr->fils_info->hlp_data);
2363 session_ptr->fils_info->hlp_data = NULL;
2364 session_ptr->fils_info->hlp_data_len = 0;
2365 }
2366 }
2367 #else
2368 static inline void
lim_copy_and_free_hlp_data_from_session(struct pe_session * session_ptr,struct roam_offload_synch_ind * roam_sync_ind_ptr)2369 lim_copy_and_free_hlp_data_from_session(struct pe_session *session_ptr,
2370 struct roam_offload_synch_ind
2371 *roam_sync_ind_ptr)
2372 {}
2373 #endif
2374
2375 static
lim_process_rmf_disconnect_frame(struct mac_context * mac,struct pe_session * session,uint8_t * deauth_disassoc_frame,uint16_t deauth_disassoc_frame_len,uint16_t * extracted_length)2376 uint8_t *lim_process_rmf_disconnect_frame(struct mac_context *mac,
2377 struct pe_session *session,
2378 uint8_t *deauth_disassoc_frame,
2379 uint16_t deauth_disassoc_frame_len,
2380 uint16_t *extracted_length)
2381 {
2382 struct wlan_frame_hdr *mac_hdr;
2383 uint8_t mic_len, hdr_len, pdev_id;
2384 uint8_t *orig_ptr, *efrm;
2385 int32_t mgmtcipherset;
2386 uint32_t mmie_len;
2387 QDF_STATUS status;
2388
2389 mac_hdr = (struct wlan_frame_hdr *)deauth_disassoc_frame;
2390 orig_ptr = (uint8_t *)mac_hdr;
2391
2392 if (mac_hdr->i_fc[1] & IEEE80211_FC1_WEP) {
2393 if (QDF_IS_ADDR_BROADCAST(mac_hdr->i_addr1) ||
2394 IEEE80211_IS_MULTICAST(mac_hdr->i_addr1)) {
2395 pe_err("Encrypted BC/MC frame dropping the frame");
2396 *extracted_length = 0;
2397 return NULL;
2398 }
2399
2400 pdev_id = wlan_objmgr_pdev_get_pdev_id(mac->pdev);
2401 status = mlme_get_peer_mic_len(mac->psoc, pdev_id,
2402 mac_hdr->i_addr2, &mic_len,
2403 &hdr_len);
2404 if (QDF_IS_STATUS_ERROR(status)) {
2405 pe_err("Failed to get mic hdr and length");
2406 *extracted_length = 0;
2407 return NULL;
2408 }
2409
2410 if (deauth_disassoc_frame_len <
2411 (sizeof(*mac_hdr) + hdr_len + mic_len)) {
2412 pe_err("Frame len less than expected %d",
2413 deauth_disassoc_frame_len);
2414 *extracted_length = 0;
2415 return NULL;
2416 }
2417
2418 /*
2419 * Strip the privacy headers and trailer
2420 * for the received deauth/disassoc frame
2421 */
2422 qdf_mem_move(orig_ptr + hdr_len, mac_hdr,
2423 sizeof(*mac_hdr));
2424 *extracted_length = deauth_disassoc_frame_len -
2425 (hdr_len + mic_len);
2426 return orig_ptr + hdr_len;
2427 }
2428
2429 if (!(QDF_IS_ADDR_BROADCAST(mac_hdr->i_addr1) ||
2430 IEEE80211_IS_MULTICAST(mac_hdr->i_addr1))) {
2431 pe_err("Rx unprotected unicast mgmt frame");
2432 *extracted_length = 0;
2433 return NULL;
2434 }
2435
2436 mgmtcipherset = wlan_crypto_get_param(session->vdev,
2437 WLAN_CRYPTO_PARAM_MGMT_CIPHER);
2438 if (mgmtcipherset < 0) {
2439 pe_err("Invalid mgmt cipher");
2440 *extracted_length = 0;
2441 return NULL;
2442 }
2443
2444 mmie_len = (mgmtcipherset & (1 << WLAN_CRYPTO_CIPHER_AES_CMAC) ?
2445 cds_get_mmie_size() : cds_get_gmac_mmie_size());
2446
2447 efrm = orig_ptr + deauth_disassoc_frame_len;
2448 if (!mac->pmf_offload &&
2449 !wlan_crypto_is_mmie_valid(session->vdev, orig_ptr, efrm)) {
2450 pe_err("Invalid MMIE");
2451 *extracted_length = 0;
2452 return NULL;
2453 }
2454
2455 *extracted_length = deauth_disassoc_frame_len - mmie_len;
2456
2457 return deauth_disassoc_frame;
2458 }
2459
2460 QDF_STATUS
pe_disconnect_callback(struct mac_context * mac,uint8_t vdev_id,uint8_t * deauth_disassoc_frame,uint16_t deauth_disassoc_frame_len,uint16_t reason_code)2461 pe_disconnect_callback(struct mac_context *mac, uint8_t vdev_id,
2462 uint8_t *deauth_disassoc_frame,
2463 uint16_t deauth_disassoc_frame_len,
2464 uint16_t reason_code)
2465 {
2466 struct pe_session *session;
2467 uint8_t *extracted_frm = NULL;
2468 uint16_t extracted_frm_len;
2469 bool is_pmf_connection;
2470
2471 session = pe_find_session_by_vdev_id(mac, vdev_id);
2472 if (!session) {
2473 pe_err("LFR3: Vdev %d doesn't exist", vdev_id);
2474 return QDF_STATUS_E_FAILURE;
2475 }
2476
2477 if (!lim_is_sb_disconnect_allowed(session))
2478 return QDF_STATUS_SUCCESS;
2479
2480 if (!deauth_disassoc_frame ||
2481 deauth_disassoc_frame_len <
2482 (sizeof(struct wlan_frame_hdr) + sizeof(reason_code))) {
2483 pe_err_rl("Discard invalid disconnect evt. frame len:%d",
2484 deauth_disassoc_frame_len);
2485 goto end;
2486 }
2487
2488 /*
2489 * Use vdev pmf status instead of peer pmf capability as
2490 * the firmware might roam to new AP in powersave case and
2491 * roam synch can come before emergency deauth event.
2492 * In that case, get peer will fail and reason code received
2493 * from the WMI_ROAM_EVENTID will be sent to upper layers.
2494 */
2495 is_pmf_connection = lim_get_vdev_rmf_capable(mac, session);
2496 if (is_pmf_connection) {
2497 extracted_frm = lim_process_rmf_disconnect_frame(
2498 mac, session,
2499 deauth_disassoc_frame,
2500 deauth_disassoc_frame_len,
2501 &extracted_frm_len);
2502 if (!extracted_frm) {
2503 pe_err("PMF frame validation failed");
2504 goto end;
2505 }
2506 } else {
2507 extracted_frm = deauth_disassoc_frame;
2508 extracted_frm_len = deauth_disassoc_frame_len;
2509 }
2510
2511 lim_extract_ies_from_deauth_disassoc(session, extracted_frm,
2512 extracted_frm_len);
2513
2514 reason_code = sir_read_u16(extracted_frm +
2515 sizeof(struct wlan_frame_hdr));
2516 end:
2517 lim_tear_down_link_with_ap(mac, session->peSessionId,
2518 reason_code,
2519 eLIM_PEER_ENTITY_DEAUTH);
2520
2521 return QDF_STATUS_SUCCESS;
2522 }
2523
2524 #ifdef WLAN_FEATURE_FILS_SK
2525 static void
lim_fill_fils_ft(struct pe_session * src_session,struct pe_session * dst_session)2526 lim_fill_fils_ft(struct pe_session *src_session,
2527 struct pe_session *dst_session)
2528 {
2529 if (src_session->fils_info &&
2530 src_session->fils_info->fils_ft_len) {
2531 dst_session->fils_info->fils_ft_len =
2532 src_session->fils_info->fils_ft_len;
2533 qdf_mem_copy(dst_session->fils_info->fils_ft,
2534 src_session->fils_info->fils_ft,
2535 src_session->fils_info->fils_ft_len);
2536 }
2537 }
2538 #else
2539 static inline void
lim_fill_fils_ft(struct pe_session * src_session,struct pe_session * dst_session)2540 lim_fill_fils_ft(struct pe_session *src_session,
2541 struct pe_session *dst_session)
2542 {}
2543 #endif
2544
2545 #ifdef WLAN_SUPPORT_TWT
2546 void
lim_fill_roamed_peer_twt_caps(struct mac_context * mac_ctx,uint8_t vdev_id,struct roam_offload_synch_ind * roam_synch)2547 lim_fill_roamed_peer_twt_caps(struct mac_context *mac_ctx,
2548 uint8_t vdev_id,
2549 struct roam_offload_synch_ind *roam_synch)
2550 {
2551 uint8_t *reassoc_body;
2552 uint16_t len;
2553 uint32_t status;
2554 tDot11fReAssocResponse *reassoc_rsp;
2555 struct pe_session *pe_session;
2556 struct qdf_mac_addr mac_addr;
2557
2558 pe_session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
2559 if (!pe_session) {
2560 pe_err("session not found for given vdev_id %d", vdev_id);
2561 return;
2562 }
2563
2564 reassoc_rsp = qdf_mem_malloc(sizeof(*reassoc_rsp));
2565 if (!reassoc_rsp)
2566 return;
2567
2568 len = roam_synch->reassoc_resp_length - sizeof(tSirMacMgmtHdr);
2569 reassoc_body = (uint8_t *)roam_synch + sizeof(tSirMacMgmtHdr) +
2570 roam_synch->reassoc_resp_offset;
2571
2572 status = dot11f_unpack_re_assoc_response(mac_ctx, reassoc_body, len,
2573 reassoc_rsp, false);
2574 if (DOT11F_FAILED(status)) {
2575 pe_err("Failed to parse a Re-association Rsp (0x%08x, %d bytes):",
2576 status, len);
2577 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_INFO,
2578 reassoc_body, len);
2579 qdf_mem_free(reassoc_rsp);
2580 return;
2581 } else if (DOT11F_WARNED(status)) {
2582 pe_debug("Warnings while unpacking a Re-association Rsp (0x%08x, %d bytes):",
2583 status, len);
2584 }
2585
2586 if (lim_is_session_he_capable(pe_session)) {
2587 if (is_multi_link_roam(roam_synch))
2588 mlo_get_sta_link_mac_addr(vdev_id, roam_synch,
2589 &mac_addr);
2590 else
2591 qdf_copy_macaddr(&mac_addr, &roam_synch->bssid);
2592 lim_set_twt_peer_capabilities(mac_ctx,
2593 &mac_addr,
2594 &reassoc_rsp->he_cap,
2595 &reassoc_rsp->he_op);
2596 }
2597 qdf_mem_free(reassoc_rsp);
2598 }
2599 #endif
2600
2601 /**
2602 * lim_check_ft_initial_im_association() - To check FT initial mobility(im)
2603 * association
2604 * @roam_synch: A pointer to roam sync ind structure
2605 * @session_entry: pe session
2606 *
2607 * This function is to check ft_initial_im_association.
2608 *
2609 * Return: None
2610 */
2611 void
lim_check_ft_initial_im_association(struct roam_offload_synch_ind * roam_synch,struct pe_session * session_entry)2612 lim_check_ft_initial_im_association(struct roam_offload_synch_ind *roam_synch,
2613 struct pe_session *session_entry)
2614 {
2615 tpSirMacMgmtHdr hdr;
2616 uint8_t *assoc_req_ptr;
2617
2618 assoc_req_ptr = (uint8_t *) roam_synch + roam_synch->reassoc_req_offset;
2619 hdr = (tpSirMacMgmtHdr) assoc_req_ptr;
2620
2621 if (hdr->fc.type == SIR_MAC_MGMT_FRAME &&
2622 hdr->fc.subType == SIR_MAC_MGMT_ASSOC_REQ) {
2623 roam_synch->is_assoc = true;
2624 if (session_entry->is11Rconnection) {
2625 pe_debug("Frame subtype: %d and connection is %d",
2626 hdr->fc.subType,
2627 session_entry->is11Rconnection);
2628 roam_synch->is_ft_im_roam = true;
2629 }
2630 }
2631 }
2632
2633 #ifdef WLAN_FEATURE_11BE_MLO
2634 static void
lim_mlo_roam_copy_partner_info_to_session(struct pe_session * session,struct roam_offload_synch_ind * sync_ind)2635 lim_mlo_roam_copy_partner_info_to_session(struct pe_session *session,
2636 struct roam_offload_synch_ind *sync_ind)
2637 {
2638 mlo_roam_copy_partner_info(&session->ml_partner_info,
2639 sync_ind, sync_ind->roamed_vdev_id, false);
2640 }
2641
2642 static QDF_STATUS
lim_gen_link_specific_assoc_rsp(struct mac_context * mac_ctx,struct pe_session * session_entry,uint8_t * reassoc_rsp,uint32_t reassoc_rsp_len)2643 lim_gen_link_specific_assoc_rsp(struct mac_context *mac_ctx,
2644 struct pe_session *session_entry,
2645 uint8_t *reassoc_rsp,
2646 uint32_t reassoc_rsp_len)
2647 {
2648 struct element_info link_reassoc_rsp;
2649 struct qdf_mac_addr sta_link_addr;
2650 struct mlo_partner_info *ml_partner_info;
2651 QDF_STATUS status = QDF_STATUS_SUCCESS;
2652 uint8_t idx = 0, num_partner_links, link_id, link_vdev_id;
2653
2654 link_reassoc_rsp.ptr = qdf_mem_malloc(reassoc_rsp_len);
2655 if (!link_reassoc_rsp.ptr)
2656 return QDF_STATUS_E_NOMEM;
2657
2658 qdf_mem_copy(&sta_link_addr, session_entry->self_mac_addr,
2659 QDF_MAC_ADDR_SIZE);
2660
2661 link_reassoc_rsp.len = reassoc_rsp_len;
2662
2663 ml_partner_info = &session_entry->ml_partner_info;
2664 num_partner_links = ml_partner_info->num_partner_links;
2665 for (idx = 0; idx < num_partner_links; idx++) {
2666 link_vdev_id = ml_partner_info->partner_link_info[idx].vdev_id;
2667 if (link_vdev_id == WLAN_INVALID_VDEV_ID)
2668 continue;
2669
2670 if (link_vdev_id != session_entry->vdev_id)
2671 continue;
2672
2673 link_id = ml_partner_info->partner_link_info[idx].link_id;
2674 status = util_gen_link_assoc_rsp(
2675 reassoc_rsp + WLAN_MAC_HDR_LEN_3A,
2676 reassoc_rsp_len - WLAN_MAC_HDR_LEN_3A,
2677 true, link_id, sta_link_addr,
2678 link_reassoc_rsp.ptr, reassoc_rsp_len,
2679 (qdf_size_t *)&link_reassoc_rsp.len);
2680 if (QDF_IS_STATUS_ERROR(status)) {
2681 pe_err("MLO ROAM: link_id:%d vdev:%d Reassoc generation failed %d",
2682 link_id, link_vdev_id, status);
2683 goto end;
2684 }
2685
2686 lim_process_assoc_rsp_frame(mac_ctx, link_reassoc_rsp.ptr,
2687 link_reassoc_rsp.len - WLAN_MAC_HDR_LEN_3A,
2688 LIM_REASSOC, session_entry);
2689 }
2690 end:
2691 qdf_mem_free(link_reassoc_rsp.ptr);
2692 link_reassoc_rsp.len = 0;
2693 return status;
2694 }
2695
2696 #else
2697 static inline void
lim_mlo_roam_copy_partner_info_to_session(struct pe_session * session,struct roam_offload_synch_ind * sync_ind)2698 lim_mlo_roam_copy_partner_info_to_session(struct pe_session *session,
2699 struct roam_offload_synch_ind *sync_ind)
2700 {}
2701
2702 static QDF_STATUS
lim_gen_link_specific_assoc_rsp(struct mac_context * mac_ctx,struct pe_session * session_entry,uint8_t * reassoc_rsp,uint32_t reassoc_rsp_len)2703 lim_gen_link_specific_assoc_rsp(struct mac_context *mac_ctx,
2704 struct pe_session *session_entry,
2705 uint8_t *reassoc_rsp,
2706 uint32_t reassoc_rsp_len)
2707 {
2708 return QDF_STATUS_E_NOSUPPORT;
2709 }
2710 #endif
2711
2712 #ifdef WLAN_FEATURE_11AX
pe_roam_fill_obss_scan_param(struct pe_session * src_session,struct pe_session * dst_session)2713 static void pe_roam_fill_obss_scan_param(struct pe_session *src_session,
2714 struct pe_session *dst_session)
2715 {
2716 dst_session->obss_color_collision_dec_evt =
2717 src_session->obss_color_collision_dec_evt;
2718 dst_session->he_op.bss_color = src_session->he_op.bss_color;
2719 }
2720 #else
pe_roam_fill_obss_scan_param(struct pe_session * src_session,struct pe_session * dst_session)2721 static inline void pe_roam_fill_obss_scan_param(struct pe_session *src_session,
2722 struct pe_session *dst_session)
2723 {
2724 }
2725 #endif
2726
2727 #ifdef WLAN_FEATURE_SR
lim_handle_sr_cap(struct wlan_objmgr_vdev * vdev,enum sr_osif_reason_code reason)2728 void lim_handle_sr_cap(struct wlan_objmgr_vdev *vdev,
2729 enum sr_osif_reason_code reason)
2730 {
2731 int32_t non_srg_pd_threshold = 0;
2732 int32_t srg_pd_threshold = 0;
2733 uint8_t non_srg_pd_offset = 0;
2734 uint8_t srg_max_pd_offset = 0;
2735 uint8_t srg_min_pd_offset = 0;
2736 uint8_t sr_ctrl, sr_enable_modes;
2737 bool is_pd_threshold_present = false;
2738 struct wlan_objmgr_pdev *pdev;
2739 enum sr_status_of_roamed_ap sr_status;
2740 enum sr_osif_operation sr_op;
2741 enum QDF_OPMODE opmode;
2742 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
2743
2744 if (!mac) {
2745 pe_err("mac ctx is null");
2746 return;
2747 }
2748 pdev = wlan_vdev_get_pdev(vdev);
2749 if (!pdev) {
2750 pe_err("invalid pdev");
2751 return;
2752 }
2753
2754 opmode = wlan_vdev_mlme_get_opmode(vdev);
2755 /* If SR is disabled in INI for the session-operating mode
2756 * Then return.
2757 */
2758 wlan_mlme_get_sr_enable_modes(mac->psoc, &sr_enable_modes);
2759 if (!(sr_enable_modes & (1 << opmode))) {
2760 pe_debug("SR is disabled in INI for mode: %d", opmode);
2761 return;
2762 }
2763 if (!wlan_vdev_mlme_get_he_spr_enabled(vdev)) {
2764 pe_debug("SR is not enabled");
2765 return;
2766 }
2767 non_srg_pd_offset = wlan_vdev_mlme_get_non_srg_pd_offset(vdev);
2768 wlan_vdev_mlme_get_srg_pd_offset(vdev, &srg_max_pd_offset,
2769 &srg_min_pd_offset);
2770 wlan_vdev_mlme_get_current_non_srg_pd_threshold(vdev,
2771 &non_srg_pd_threshold);
2772 wlan_vdev_mlme_get_current_srg_pd_threshold(vdev,
2773 &srg_pd_threshold);
2774
2775 sr_ctrl = wlan_vdev_mlme_get_sr_ctrl(vdev);
2776 if ((sr_ctrl & NON_SRG_PD_SR_DISALLOWED) &&
2777 (!(sr_ctrl & SRG_INFO_PRESENT))) {
2778 sr_status = SR_DISALLOW;
2779 } else {
2780 if ((!(sr_ctrl & NON_SRG_PD_SR_DISALLOWED) &&
2781 (non_srg_pd_threshold > non_srg_pd_offset +
2782 SR_PD_THRESHOLD_MIN)) ||
2783 ((sr_ctrl & SRG_INFO_PRESENT) &&
2784 ((srg_pd_threshold > srg_max_pd_offset +
2785 SR_PD_THRESHOLD_MIN) ||
2786 (srg_pd_threshold < srg_min_pd_offset +
2787 SR_PD_THRESHOLD_MIN))))
2788 sr_status = SR_THRESHOLD_NOT_IN_RANGE;
2789 else
2790 sr_status = SR_THRESHOLD_IN_RANGE;
2791 }
2792 pe_debug("sr status %d reason %d existing thresholds srg: %d non-srg: %d New: sr offset srg: max %d min %d non-srg: %d",
2793 sr_status, reason, srg_pd_threshold, non_srg_pd_threshold,
2794 srg_max_pd_offset, srg_min_pd_offset, non_srg_pd_offset);
2795 switch (sr_status) {
2796 case SR_DISALLOW:
2797 /** clear thresholds set by previous AP **/
2798 wlan_vdev_mlme_set_current_non_srg_pd_threshold(vdev, 0);
2799 wlan_vdev_mlme_set_current_srg_pd_threshold(vdev, 0);
2800 wlan_spatial_reuse_osif_event(vdev,
2801 SR_OPERATION_SUSPEND,
2802 reason);
2803 /*
2804 * If SR is disabled due to beacon update,
2805 * notify the firmware to disable SR
2806 */
2807 if (reason == SR_REASON_CODE_BCN_IE_CHANGE)
2808 wlan_sr_setup_req(vdev, pdev, false, 0, 0);
2809 break;
2810 case SR_THRESHOLD_NOT_IN_RANGE:
2811 wlan_vdev_mlme_get_pd_threshold_present(
2812 vdev, &is_pd_threshold_present);
2813 /*
2814 * if userspace gives pd threshold then check if its within
2815 * range of roamed AP's min and max thresholds, if not in
2816 * range disable and let userspace decide to re-enable.
2817 * if userspace dosesnt give PD threshold then always enable
2818 * SRG based on AP's recommendation of thresholds.
2819 */
2820 if (is_pd_threshold_present) {
2821 wlan_vdev_mlme_set_current_non_srg_pd_threshold(vdev,
2822 0);
2823 wlan_vdev_mlme_set_current_srg_pd_threshold(vdev, 0);
2824 wlan_spatial_reuse_osif_event(vdev,
2825 SR_OPERATION_SUSPEND,
2826 reason);
2827 } else {
2828 sr_op = (reason == SR_REASON_CODE_ROAMING) ?
2829 SR_OPERATION_RESUME :
2830 SR_OPERATION_UPDATE_PARAMS;
2831 wlan_sr_setup_req(
2832 vdev, pdev, true,
2833 srg_max_pd_offset + SR_PD_THRESHOLD_MIN,
2834 non_srg_pd_threshold + SR_PD_THRESHOLD_MIN);
2835 wlan_spatial_reuse_osif_event(vdev, sr_op, reason);
2836 }
2837 break;
2838 case SR_THRESHOLD_IN_RANGE:
2839 /* Send enable command to fw, as fw disables SR on roaming */
2840 wlan_sr_setup_req(vdev, pdev, true, srg_pd_threshold,
2841 non_srg_pd_threshold);
2842 break;
2843 }
2844 }
2845 #endif
2846
2847 QDF_STATUS
pe_roam_synch_callback(struct mac_context * mac_ctx,uint8_t vdev_id,struct roam_offload_synch_ind * roam_sync_ind_ptr,uint16_t ie_len,enum sir_roam_op_code reason)2848 pe_roam_synch_callback(struct mac_context *mac_ctx,
2849 uint8_t vdev_id,
2850 struct roam_offload_synch_ind *roam_sync_ind_ptr,
2851 uint16_t ie_len,
2852 enum sir_roam_op_code reason)
2853 {
2854 struct pe_session *session_ptr;
2855 struct pe_session *ft_session_ptr;
2856 uint8_t session_id;
2857 uint8_t *reassoc_resp;
2858 tpDphHashNode curr_sta_ds = NULL, sta_ds = NULL;
2859 uint16_t aid;
2860 struct bss_params *add_bss_params;
2861 QDF_STATUS status = QDF_STATUS_E_FAILURE;
2862 struct bss_description *bss_desc = NULL;
2863 uint16_t ric_tspec_len;
2864 struct qdf_mac_addr bssid;
2865 uint8_t *oui_ie_ptr;
2866 uint16_t oui_ie_len;
2867
2868 if (!roam_sync_ind_ptr) {
2869 pe_err("LFR3:roam_sync_ind_ptr is NULL");
2870 return status;
2871 }
2872 session_ptr = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
2873 if (!session_ptr) {
2874 pe_err("LFR3:Unable to find session");
2875 return status;
2876 }
2877
2878 if (!LIM_IS_STA_ROLE(session_ptr)) {
2879 pe_err("LFR3:session is not in STA mode");
2880 return status;
2881 }
2882
2883 if (is_multi_link_roam(roam_sync_ind_ptr))
2884 mlo_get_sta_link_mac_addr(vdev_id, roam_sync_ind_ptr, &bssid);
2885 else
2886 bssid = roam_sync_ind_ptr->bssid;
2887
2888 pe_debug("LFR3: PE callback reason: %d", reason);
2889 switch (reason) {
2890 case SIR_ROAMING_ABORT:
2891 /*
2892 * If there was a disassoc or deauth that was received
2893 * during roaming and it was not honored, then we have
2894 * to internally initiate a disconnect because with
2895 * ROAM_ABORT we come back to original AP.
2896 */
2897 if (session_ptr->recvd_deauth_while_roaming)
2898 lim_perform_deauth(mac_ctx, session_ptr,
2899 session_ptr->deauth_disassoc_rc,
2900 session_ptr->bssId, 0);
2901 if (session_ptr->recvd_disassoc_while_roaming) {
2902 lim_disassoc_tdls_peers(mac_ctx, session_ptr,
2903 session_ptr->bssId);
2904 lim_perform_disassoc(mac_ctx, 0,
2905 session_ptr->deauth_disassoc_rc,
2906 session_ptr, session_ptr->bssId);
2907 }
2908 return QDF_STATUS_SUCCESS;
2909 case SIR_ROAM_SYNCH_PROPAGATION:
2910 break;
2911 default:
2912 return status;
2913 }
2914
2915 pe_debug("LFR3:Received ROAM SYNCH IND bssid "QDF_MAC_ADDR_FMT" auth: %d vdevId: %d",
2916 QDF_MAC_ADDR_REF(roam_sync_ind_ptr->bssid.bytes),
2917 roam_sync_ind_ptr->auth_status,
2918 vdev_id);
2919
2920 /*
2921 * If deauth from AP already in progress, ignore Roam Synch Indication
2922 * from firmware.
2923 */
2924 if (session_ptr->limSmeState != eLIM_SME_LINK_EST_STATE) {
2925 pe_err("LFR3: Not in Link est state");
2926 return status;
2927 }
2928
2929 bss_desc = qdf_mem_malloc(sizeof(struct bss_description) + ie_len);
2930 if (!bss_desc) {
2931 QDF_ASSERT(bss_desc);
2932 status = -QDF_STATUS_E_NOMEM;
2933 return status;
2934 }
2935
2936 status = lim_roam_fill_bss_descr(mac_ctx, roam_sync_ind_ptr,
2937 bss_desc, session_ptr);
2938 if (!QDF_IS_STATUS_SUCCESS(status)) {
2939 pe_err("LFR3:Failed to fill Bss Descr");
2940 qdf_mem_free(bss_desc);
2941 return status;
2942 }
2943 status = QDF_STATUS_E_FAILURE;
2944 ft_session_ptr = pe_create_session(mac_ctx, bss_desc->bssId,
2945 &session_id,
2946 mac_ctx->lim.max_sta_of_pe_session,
2947 session_ptr->bssType,
2948 session_ptr->vdev_id);
2949 if (!ft_session_ptr) {
2950 pe_err("LFR3:Cannot create PE Session bssid: "QDF_MAC_ADDR_FMT,
2951 QDF_MAC_ADDR_REF(bss_desc->bssId));
2952 qdf_mem_free(bss_desc);
2953 return status;
2954 }
2955 /* Update the beacon/probe filter in mac_ctx */
2956 lim_set_bcn_probe_filter(mac_ctx, ft_session_ptr, 0);
2957 sir_copy_mac_addr(ft_session_ptr->limReAssocbssId, bss_desc->bssId);
2958 session_ptr->bRoamSynchInProgress = true;
2959 ft_session_ptr->bRoamSynchInProgress = true;
2960 ft_session_ptr->limSystemRole = eLIM_STA_ROLE;
2961 sir_copy_mac_addr(session_ptr->limReAssocbssId, bss_desc->bssId);
2962 ft_session_ptr->csaOffloadEnable = session_ptr->csaOffloadEnable;
2963
2964 /* Next routine will update nss and vdev_nss with AP's capabilities */
2965 status = lim_fill_ft_session(mac_ctx, bss_desc, ft_session_ptr,
2966 session_ptr, roam_sync_ind_ptr->phy_mode);
2967 if (QDF_IS_STATUS_ERROR(status)) {
2968 pe_err("Failed to fill ft session for vdev id %d",
2969 ft_session_ptr->vdev_id);
2970 qdf_mem_free(bss_desc);
2971 goto roam_sync_fail;
2972 }
2973
2974 roam_sync_ind_ptr->ssid.length =
2975 qdf_min((qdf_size_t)ft_session_ptr->ssId.length,
2976 sizeof(roam_sync_ind_ptr->ssid.ssid));
2977 qdf_mem_copy(roam_sync_ind_ptr->ssid.ssid, ft_session_ptr->ssId.ssId,
2978 roam_sync_ind_ptr->ssid.length);
2979 pe_update_crypto_params(mac_ctx, ft_session_ptr, roam_sync_ind_ptr);
2980
2981 /* Reset the SPMK global cache */
2982 wlan_mlme_set_sae_single_pmk_bss_cap(mac_ctx->psoc, vdev_id, false);
2983
2984 /* Next routine may update nss based on dot11Mode */
2985
2986 lim_ft_prepare_add_bss_req(mac_ctx, ft_session_ptr, bss_desc);
2987 lim_set_tpc_power(mac_ctx, ft_session_ptr, bss_desc);
2988
2989 if (session_ptr->is11Rconnection)
2990 lim_fill_fils_ft(session_ptr, ft_session_ptr);
2991
2992 roam_sync_ind_ptr->add_bss_params =
2993 (struct bss_params *) ft_session_ptr->ftPEContext.pAddBssReq;
2994 add_bss_params = ft_session_ptr->ftPEContext.pAddBssReq;
2995 lim_delete_tdls_peers(mac_ctx, session_ptr);
2996 /*
2997 * After deleting the TDLS peers notify the Firmware about TDLS STA
2998 * disconnection due to roaming
2999 */
3000 wlan_tdls_notify_sta_disconnect(vdev_id, true,
3001 false, session_ptr->vdev);
3002
3003 sta_ds = dph_lookup_hash_entry(mac_ctx, session_ptr->bssId, &aid,
3004 &session_ptr->dph.dphHashTable);
3005 if (!sta_ds && !is_multi_link_roam(roam_sync_ind_ptr)) {
3006 pe_err("LFR3:failed to lookup hash entry");
3007 ft_session_ptr->bRoamSynchInProgress = false;
3008 qdf_mem_free(bss_desc);
3009 goto roam_sync_fail;
3010 }
3011
3012 /* update OBSS scan param */
3013 pe_roam_fill_obss_scan_param(session_ptr, ft_session_ptr);
3014
3015 curr_sta_ds = dph_add_hash_entry(mac_ctx,
3016 bssid.bytes,
3017 DPH_STA_HASH_INDEX_PEER,
3018 &ft_session_ptr->dph.dphHashTable);
3019 if (!curr_sta_ds) {
3020 pe_err("LFR3:failed to add hash entry for "QDF_MAC_ADDR_FMT,
3021 QDF_MAC_ADDR_REF(add_bss_params->staContext.staMac));
3022 ft_session_ptr->bRoamSynchInProgress = false;
3023 qdf_mem_free(bss_desc);
3024 goto roam_sync_fail;
3025 }
3026
3027 if (roam_sync_ind_ptr->auth_status == ROAM_AUTH_STATUS_AUTHENTICATED)
3028 curr_sta_ds->is_key_installed = true;
3029
3030 lim_mlo_roam_copy_partner_info_to_session(ft_session_ptr,
3031 roam_sync_ind_ptr);
3032
3033 reassoc_resp = (uint8_t *)roam_sync_ind_ptr +
3034 roam_sync_ind_ptr->reassoc_resp_offset;
3035 mgmt_txrx_frame_hex_dump(reassoc_resp,
3036 roam_sync_ind_ptr->reassoc_resp_length, false);
3037 if (wlan_vdev_mlme_get_is_mlo_link(mac_ctx->psoc, vdev_id)) {
3038 status = lim_gen_link_specific_assoc_rsp(mac_ctx,
3039 ft_session_ptr,
3040 reassoc_resp,
3041 roam_sync_ind_ptr->reassoc_resp_length);
3042 if (ft_session_ptr->is_unexpected_peer_error)
3043 status = QDF_STATUS_E_FAILURE;
3044
3045 if (QDF_IS_STATUS_ERROR(status)) {
3046 qdf_mem_free(bss_desc);
3047 goto roam_sync_fail;
3048 }
3049 } else {
3050 lim_process_assoc_rsp_frame(mac_ctx, reassoc_resp,
3051 roam_sync_ind_ptr->reassoc_resp_length - SIR_MAC_HDR_LEN_3A,
3052 LIM_REASSOC, ft_session_ptr);
3053 if (ft_session_ptr->is_unexpected_peer_error) {
3054 status = QDF_STATUS_E_FAILURE;
3055 qdf_mem_free(bss_desc);
3056 goto roam_sync_fail;
3057 }
3058 }
3059
3060 oui_ie_ptr = (uint8_t *)&bss_desc->ieFields[0];
3061 oui_ie_len = wlan_get_ielen_from_bss_description(bss_desc);
3062 lim_enable_cts_to_self_for_exempted_iot_ap(mac_ctx,
3063 ft_session_ptr,
3064 oui_ie_ptr, oui_ie_len);
3065 qdf_mem_free(bss_desc);
3066 oui_ie_len = 0;
3067 oui_ie_ptr = NULL;
3068
3069 lim_check_ft_initial_im_association(roam_sync_ind_ptr, ft_session_ptr);
3070
3071 lim_copy_and_free_hlp_data_from_session(ft_session_ptr,
3072 roam_sync_ind_ptr);
3073 roam_sync_ind_ptr->aid = ft_session_ptr->limAID;
3074 curr_sta_ds->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE;
3075 curr_sta_ds->nss = ft_session_ptr->nss;
3076 roam_sync_ind_ptr->nss = ft_session_ptr->nss;
3077 ft_session_ptr->limMlmState = eLIM_MLM_LINK_ESTABLISHED_STATE;
3078 ft_session_ptr->limPrevMlmState = ft_session_ptr->limMlmState;
3079 lim_init_tdls_data(mac_ctx, ft_session_ptr);
3080 ric_tspec_len = ft_session_ptr->RICDataLen;
3081 pe_debug("LFR3: Session RicLength: %d", ft_session_ptr->RICDataLen);
3082 lim_handle_sr_cap(ft_session_ptr->vdev, SR_REASON_CODE_ROAMING);
3083 #ifdef FEATURE_WLAN_ESE
3084 ric_tspec_len += ft_session_ptr->tspecLen;
3085 pe_debug("LFR3: tspecLen: %d", ft_session_ptr->tspecLen);
3086 #endif
3087 if (ric_tspec_len) {
3088 roam_sync_ind_ptr->ric_tspec_data =
3089 qdf_mem_malloc(ric_tspec_len);
3090 if (!roam_sync_ind_ptr->ric_tspec_data) {
3091 ft_session_ptr->bRoamSynchInProgress = false;
3092 status = QDF_STATUS_E_NOMEM;
3093 goto roam_sync_fail;
3094 }
3095
3096 if (ft_session_ptr->ricData) {
3097 roam_sync_ind_ptr->ric_data_len =
3098 ft_session_ptr->RICDataLen;
3099 qdf_mem_copy(roam_sync_ind_ptr->ric_tspec_data,
3100 ft_session_ptr->ricData,
3101 roam_sync_ind_ptr->ric_data_len);
3102 qdf_mem_free(ft_session_ptr->ricData);
3103 ft_session_ptr->ricData = NULL;
3104 ft_session_ptr->RICDataLen = 0;
3105 }
3106 #ifdef FEATURE_WLAN_ESE
3107 if (ft_session_ptr->tspecIes) {
3108 roam_sync_ind_ptr->tspec_len = ft_session_ptr->tspecLen;
3109 qdf_mem_copy(roam_sync_ind_ptr->ric_tspec_data +
3110 roam_sync_ind_ptr->ric_data_len,
3111 ft_session_ptr->tspecIes,
3112 roam_sync_ind_ptr->tspec_len);
3113 qdf_mem_free(ft_session_ptr->tspecIes);
3114 ft_session_ptr->tspecIes = NULL;
3115 ft_session_ptr->tspecLen = 0;
3116 }
3117 #endif
3118 }
3119 roam_sync_ind_ptr->chan_width = ft_session_ptr->ch_width;
3120 roam_sync_ind_ptr->max_rate_flags =
3121 lim_get_max_rate_flags(mac_ctx, curr_sta_ds);
3122 ft_session_ptr->limSmeState = eLIM_SME_LINK_EST_STATE;
3123 ft_session_ptr->limPrevSmeState = ft_session_ptr->limSmeState;
3124 ft_session_ptr->bRoamSynchInProgress = false;
3125
3126 /* Cleanup the old session */
3127 session_ptr->limSmeState = eLIM_SME_IDLE_STATE;
3128
3129 /*
3130 * Delete the ml_peer only if DUT is roamed to a non-11BE candidate.
3131 * ml_peer is already cleaned up in wma_delete_all_peers() at the
3132 * beginning of roam_sync handling for 11BE candidates.
3133 */
3134 if (sta_ds) {
3135 if (!wlan_vdev_mlme_is_mlo_vdev(session_ptr->vdev)) {
3136 lim_mlo_notify_peer_disconn(session_ptr, sta_ds);
3137 lim_mlo_roam_delete_link_peer(session_ptr, sta_ds);
3138 }
3139 lim_cleanup_rx_path(mac_ctx, sta_ds, session_ptr, false);
3140 lim_delete_dph_hash_entry(mac_ctx, sta_ds->staAddr, aid,
3141 session_ptr);
3142 }
3143
3144 pe_delete_session(mac_ctx, session_ptr);
3145
3146 return QDF_STATUS_SUCCESS;
3147
3148 roam_sync_fail:
3149 pe_err("Roam sync failure status %d session vdev %d", status,
3150 session_ptr->vdev_id);
3151 /*
3152 * Cleanup the new session upon roam sync failure.
3153 * Retain the old session for graceful HO failure handling.
3154 */
3155 if (curr_sta_ds) {
3156 lim_cleanup_rx_path(mac_ctx, curr_sta_ds, ft_session_ptr,
3157 false);
3158 lim_delete_dph_hash_entry(mac_ctx, curr_sta_ds->staAddr,
3159 curr_sta_ds->assocId, ft_session_ptr);
3160 }
3161 pe_delete_session(mac_ctx, ft_session_ptr);
3162 return status;
3163 }
3164
3165 QDF_STATUS
pe_set_ie_for_roam_invoke(struct mac_context * mac_ctx,uint8_t vdev_id,uint16_t dot11_mode,enum QDF_OPMODE opmode)3166 pe_set_ie_for_roam_invoke(struct mac_context *mac_ctx, uint8_t vdev_id,
3167 uint16_t dot11_mode, enum QDF_OPMODE opmode)
3168 {
3169 QDF_STATUS status;
3170
3171 if (!mac_ctx)
3172 return QDF_STATUS_E_FAILURE;
3173
3174 status = lim_send_ies_per_band(mac_ctx, vdev_id, dot11_mode, opmode);
3175 return status;
3176 }
3177
3178 #endif
3179
lim_is_beacon_miss_scenario(struct mac_context * mac,uint8_t * pRxPacketInfo)3180 static bool lim_is_beacon_miss_scenario(struct mac_context *mac,
3181 uint8_t *pRxPacketInfo)
3182 {
3183 tpSirMacMgmtHdr pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
3184 uint8_t sessionId;
3185 struct pe_session *pe_session =
3186 pe_find_session_by_bssid(mac, pHdr->bssId, &sessionId);
3187
3188 if (pe_session && pe_session->pmmOffloadInfo.bcnmiss)
3189 return true;
3190 return false;
3191 }
3192
3193 /** -----------------------------------------------------------------
3194 \brief lim_is_pkt_candidate_for_drop() - decides whether to drop the frame or not
3195
3196 This function is called before enqueuing the frame to PE queue for further processing.
3197 This prevents unnecessary frames getting into PE Queue and drops them right away.
3198 Frames will be dropped in the following scenarios:
3199
3200 - In Scan State, drop the frames which are not marked as scan frames
3201 - In non-Scan state, drop the frames which are marked as scan frames.
3202
3203 \param mac - global mac structure
3204 \return - none
3205 \sa
3206 ----------------------------------------------------------------- */
3207
lim_is_pkt_candidate_for_drop(struct mac_context * mac,uint8_t * pRxPacketInfo,uint32_t subType)3208 tMgmtFrmDropReason lim_is_pkt_candidate_for_drop(struct mac_context *mac,
3209 uint8_t *pRxPacketInfo,
3210 uint32_t subType)
3211 {
3212 uint32_t framelen;
3213 uint8_t *pBody;
3214 tSirMacCapabilityInfo capabilityInfo;
3215 tpSirMacMgmtHdr pHdr = NULL;
3216 struct wlan_objmgr_vdev *vdev;
3217
3218 /*
3219 *
3220 * In scan mode, drop only Beacon/Probe Response which are NOT marked as scan-frames.
3221 * In non-scan mode, drop only Beacon/Probe Response which are marked as scan frames.
3222 * Allow other mgmt frames, they must be from our own AP, as we don't allow
3223 * other than beacons or probe responses in scan state.
3224 */
3225 if ((subType == SIR_MAC_MGMT_BEACON) ||
3226 (subType == SIR_MAC_MGMT_PROBE_RSP)) {
3227 if (lim_is_beacon_miss_scenario(mac, pRxPacketInfo)) {
3228 MTRACE(mac_trace(mac, TRACE_CODE_INFO_LOG, 0,
3229 eLOG_NODROP_MISSED_BEACON_SCENARIO));
3230 return eMGMT_DROP_NO_DROP;
3231 }
3232
3233 framelen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
3234 pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
3235 /* drop the frame if length is less than 12 */
3236 if (framelen < LIM_MIN_BCN_PR_LENGTH)
3237 return eMGMT_DROP_INVALID_SIZE;
3238
3239 *((uint16_t *) &capabilityInfo) =
3240 sir_read_u16(pBody + LIM_BCN_PR_CAPABILITY_OFFSET);
3241
3242 /* Note sure if this is sufficient, basically this condition allows all probe responses and
3243 * beacons from an infrastructure network
3244 */
3245 if (!capabilityInfo.ibss)
3246 return eMGMT_DROP_NO_DROP;
3247
3248 /* Drop INFRA Beacons and Probe Responses in IBSS Mode */
3249 /* This can be enhanced to even check the SSID before deciding to enqueue the frame. */
3250 if (capabilityInfo.ess)
3251 return eMGMT_DROP_INFRA_BCN_IN_IBSS;
3252
3253 } else if (subType == SIR_MAC_MGMT_AUTH) {
3254 uint16_t curr_seq_num = 0;
3255 struct tLimPreAuthNode *auth_node;
3256
3257 pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
3258 vdev = wlan_objmgr_get_vdev_by_macaddr_from_pdev(mac->pdev,
3259 pHdr->da,
3260 WLAN_LEGACY_MAC_ID);
3261 if (!vdev)
3262 return eMGMT_DROP_NO_DROP;
3263 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
3264
3265 curr_seq_num = ((pHdr->seqControl.seqNumHi << 4) |
3266 (pHdr->seqControl.seqNumLo));
3267 auth_node = lim_search_pre_auth_list(mac, pHdr->sa);
3268 if (auth_node && pHdr->fc.retry &&
3269 (auth_node->seq_num == curr_seq_num)) {
3270 pe_err_rl("auth frame, seq num: %d is already processed, drop it",
3271 curr_seq_num);
3272 return eMGMT_DROP_DUPLICATE_AUTH_FRAME;
3273 }
3274 } else if ((subType == SIR_MAC_MGMT_ASSOC_REQ) ||
3275 (subType == SIR_MAC_MGMT_DISASSOC) ||
3276 (subType == SIR_MAC_MGMT_DEAUTH)) {
3277 struct peer_mlme_priv_obj *peer_priv;
3278 struct wlan_objmgr_peer *peer;
3279 qdf_time_t *timestamp;
3280
3281 pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
3282 vdev = wlan_objmgr_get_vdev_by_macaddr_from_pdev(mac->pdev,
3283 pHdr->da,
3284 WLAN_LEGACY_MAC_ID);
3285 if (!vdev)
3286 return eMGMT_DROP_SPURIOUS_FRAME;
3287
3288 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE &&
3289 wlan_cm_is_vdev_roam_started(vdev) &&
3290 (subType == SIR_MAC_MGMT_DISASSOC ||
3291 subType == SIR_MAC_MGMT_DEAUTH)) {
3292 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
3293 return eMGMT_DROP_DEAUTH_DURING_ROAM_STARTED;
3294 }
3295 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
3296
3297 peer = wlan_objmgr_get_peer_by_mac(mac->psoc,
3298 pHdr->sa,
3299 WLAN_LEGACY_MAC_ID);
3300 if (!peer) {
3301 if (subType == SIR_MAC_MGMT_ASSOC_REQ)
3302 return eMGMT_DROP_NO_DROP;
3303 return eMGMT_DROP_SPURIOUS_FRAME;
3304 }
3305
3306 peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
3307 WLAN_UMAC_COMP_MLME);
3308 if (!peer_priv) {
3309 wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_MAC_ID);
3310 if (subType == SIR_MAC_MGMT_ASSOC_REQ)
3311 return eMGMT_DROP_NO_DROP;
3312 return eMGMT_DROP_SPURIOUS_FRAME;
3313 }
3314
3315 if (subType == SIR_MAC_MGMT_ASSOC_REQ)
3316 timestamp =
3317 &peer_priv->last_assoc_received_time;
3318 else
3319 timestamp =
3320 &peer_priv->last_disassoc_deauth_received_time;
3321
3322 if (*timestamp > 0 &&
3323 qdf_system_time_before(qdf_get_system_timestamp(),
3324 *timestamp +
3325 LIM_DOS_PROTECTION_TIME)) {
3326 pe_debug_rl(FL("Dropping subtype 0x%x frame. %s %d ms %s %d ms"),
3327 subType, "It is received after",
3328 (int)(qdf_get_system_timestamp() - *timestamp),
3329 "of last frame. Allow it only after",
3330 LIM_DOS_PROTECTION_TIME);
3331 wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_MAC_ID);
3332 return eMGMT_DROP_EXCESSIVE_MGMT_FRAME;
3333 }
3334
3335 *timestamp = qdf_get_system_timestamp();
3336 wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_MAC_ID);
3337
3338 }
3339
3340 return eMGMT_DROP_NO_DROP;
3341 }
3342
lim_update_lost_link_info(struct mac_context * mac,struct pe_session * session,int32_t rssi)3343 void lim_update_lost_link_info(struct mac_context *mac, struct pe_session *session,
3344 int32_t rssi)
3345 {
3346 struct sir_lost_link_info *lost_link_info;
3347 struct scheduler_msg mmh_msg = {0};
3348
3349 if ((!mac) || (!session)) {
3350 pe_err("parameter NULL");
3351 return;
3352 }
3353 if (!LIM_IS_STA_ROLE(session))
3354 return;
3355
3356 lost_link_info = qdf_mem_malloc(sizeof(*lost_link_info));
3357 if (!lost_link_info)
3358 return;
3359
3360 lost_link_info->vdev_id = session->smeSessionId;
3361 lost_link_info->rssi = rssi;
3362 mmh_msg.type = eWNI_SME_LOST_LINK_INFO_IND;
3363 mmh_msg.bodyptr = lost_link_info;
3364 mmh_msg.bodyval = 0;
3365 pe_debug("post eWNI_SME_LOST_LINK_INFO_IND, bss_idx: %d rssi: %d",
3366 lost_link_info->vdev_id, lost_link_info->rssi);
3367
3368 lim_sys_process_mmh_msg_api(mac, &mmh_msg);
3369 }
3370
3371 /**
3372 * lim_mon_init_session() - create PE session for monitor mode operation
3373 * @mac_ptr: mac pointer
3374 * @msg: Pointer to struct sir_create_session type.
3375 *
3376 * Return: NONE
3377 */
lim_mon_init_session(struct mac_context * mac_ptr,struct sir_create_session * msg)3378 void lim_mon_init_session(struct mac_context *mac_ptr,
3379 struct sir_create_session *msg)
3380 {
3381 struct pe_session *psession_entry;
3382 uint8_t session_id;
3383
3384 psession_entry = pe_create_session(mac_ptr, msg->bss_id.bytes,
3385 &session_id,
3386 mac_ptr->lim.max_sta_of_pe_session,
3387 eSIR_MONITOR_MODE,
3388 msg->vdev_id);
3389 if (!psession_entry) {
3390 pe_err("Monitor mode: Session Can not be created bssid: "
3391 QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(msg->bss_id.bytes));
3392 return;
3393 }
3394 psession_entry->vhtCapability = 1;
3395 }
3396
lim_mon_deinit_session(struct mac_context * mac_ptr,struct sir_delete_session * msg)3397 void lim_mon_deinit_session(struct mac_context *mac_ptr,
3398 struct sir_delete_session *msg)
3399 {
3400 struct pe_session *session;
3401
3402 session = pe_find_session_by_vdev_id(mac_ptr, msg->vdev_id);
3403
3404 if (session && session->bssType == eSIR_MONITOR_MODE)
3405 pe_delete_session(mac_ptr, session);
3406 }
3407
3408 /**
3409 * lim_update_ext_cap_ie() - Update Extended capabilities IE(if present)
3410 * with capabilities of Fine Time measurements(FTM) if set in driver
3411 *
3412 * @mac_ctx: Pointer to Global MAC structure
3413 * @ie_data: Default Scan IE data
3414 * @local_ie_buf: Local Scan IE data
3415 * @local_ie_len: Pointer to length of @ie_data
3416 * @session: Pointer to pe session
3417 *
3418 * Return: QDF_STATUS
3419 */
lim_update_ext_cap_ie(struct mac_context * mac_ctx,uint8_t * ie_data,uint8_t * local_ie_buf,uint16_t * local_ie_len,struct pe_session * session)3420 QDF_STATUS lim_update_ext_cap_ie(struct mac_context *mac_ctx, uint8_t *ie_data,
3421 uint8_t *local_ie_buf, uint16_t *local_ie_len,
3422 struct pe_session *session)
3423 {
3424 uint32_t dot11mode;
3425 bool vht_enabled = false;
3426 tDot11fIEExtCap default_scan_ext_cap = {0}, driver_ext_cap = {0};
3427 QDF_STATUS status;
3428
3429 status = lim_strip_extcap_update_struct(mac_ctx, ie_data,
3430 local_ie_len, &default_scan_ext_cap);
3431 if (QDF_STATUS_SUCCESS != status) {
3432 pe_err("Strip ext cap fails %d", status);
3433 return QDF_STATUS_E_FAILURE;
3434 }
3435
3436 if ((*local_ie_len) > (MAX_DEFAULT_SCAN_IE_LEN - EXT_CAP_IE_HDR_LEN)) {
3437 pe_err("Invalid Scan IE length");
3438 return QDF_STATUS_E_FAILURE;
3439 }
3440 /* copy ie prior to ext cap to local buffer */
3441 qdf_mem_copy(local_ie_buf, ie_data, (*local_ie_len));
3442
3443 /* from here ext cap ie starts, set EID */
3444 local_ie_buf[*local_ie_len] = DOT11F_EID_EXTCAP;
3445
3446 dot11mode = mac_ctx->mlme_cfg->dot11_mode.dot11_mode;
3447 if (IS_DOT11_MODE_VHT(dot11mode))
3448 vht_enabled = true;
3449
3450 status = populate_dot11f_ext_cap(mac_ctx, vht_enabled,
3451 &driver_ext_cap, NULL);
3452 if (QDF_STATUS_SUCCESS != status) {
3453 pe_err("Failed %d to create ext cap IE. Use default value instead",
3454 status);
3455 local_ie_buf[*local_ie_len + 1] = DOT11F_IE_EXTCAP_MAX_LEN;
3456
3457 if ((*local_ie_len) > (MAX_DEFAULT_SCAN_IE_LEN -
3458 (DOT11F_IE_EXTCAP_MAX_LEN + EXT_CAP_IE_HDR_LEN))) {
3459 pe_err("Invalid Scan IE length");
3460 return QDF_STATUS_E_FAILURE;
3461 }
3462 (*local_ie_len) += EXT_CAP_IE_HDR_LEN;
3463 qdf_mem_copy(local_ie_buf + (*local_ie_len),
3464 default_scan_ext_cap.bytes,
3465 DOT11F_IE_EXTCAP_MAX_LEN);
3466 (*local_ie_len) += DOT11F_IE_EXTCAP_MAX_LEN;
3467 return QDF_STATUS_SUCCESS;
3468 }
3469 lim_merge_extcap_struct(&driver_ext_cap, &default_scan_ext_cap, true);
3470
3471 if (session)
3472 populate_dot11f_twt_extended_caps(mac_ctx, session,
3473 &driver_ext_cap);
3474 else
3475 pe_debug("Session NULL, cannot set TWT caps");
3476
3477 local_ie_buf[*local_ie_len + 1] = driver_ext_cap.num_bytes;
3478
3479 if ((*local_ie_len) > (MAX_DEFAULT_SCAN_IE_LEN -
3480 (EXT_CAP_IE_HDR_LEN + driver_ext_cap.num_bytes))) {
3481 pe_err("Invalid Scan IE length");
3482 return QDF_STATUS_E_FAILURE;
3483 }
3484 (*local_ie_len) += EXT_CAP_IE_HDR_LEN;
3485 qdf_mem_copy(local_ie_buf + (*local_ie_len),
3486 driver_ext_cap.bytes, driver_ext_cap.num_bytes);
3487 (*local_ie_len) += driver_ext_cap.num_bytes;
3488 return QDF_STATUS_SUCCESS;
3489 }
3490
3491 #define LIM_RSN_OUI_SIZE 4
3492
3493 struct rsn_oui_akm_type_map {
3494 enum ani_akm_type akm_type;
3495 uint8_t rsn_oui[LIM_RSN_OUI_SIZE];
3496 };
3497
3498 static const struct rsn_oui_akm_type_map rsn_oui_akm_type_mapping_table[] = {
3499 {ANI_AKM_TYPE_RSN, {0x00, 0x0F, 0xAC, 0x01} },
3500 {ANI_AKM_TYPE_RSN_PSK, {0x00, 0x0F, 0xAC, 0x02} },
3501 {ANI_AKM_TYPE_FT_RSN, {0x00, 0x0F, 0xAC, 0x03} },
3502 {ANI_AKM_TYPE_FT_RSN_PSK, {0x00, 0x0F, 0xAC, 0x04} },
3503 {ANI_AKM_TYPE_RSN_8021X_SHA256, {0x00, 0x0F, 0xAC, 0x05} },
3504 {ANI_AKM_TYPE_RSN_PSK_SHA256, {0x00, 0x0F, 0xAC, 0x06} },
3505 #ifdef WLAN_FEATURE_SAE
3506 {ANI_AKM_TYPE_SAE, {0x00, 0x0F, 0xAC, 0x08} },
3507 {ANI_AKM_TYPE_FT_SAE, {0x00, 0x0F, 0xAC, 0x09} },
3508 #endif
3509 {ANI_AKM_TYPE_SUITEB_EAP_SHA256, {0x00, 0x0F, 0xAC, 0x0B} },
3510 {ANI_AKM_TYPE_SUITEB_EAP_SHA384, {0x00, 0x0F, 0xAC, 0x0C} },
3511 {ANI_AKM_TYPE_FT_SUITEB_EAP_SHA384, {0x00, 0x0F, 0xAC, 0x0D} },
3512 {ANI_AKM_TYPE_FILS_SHA256, {0x00, 0x0F, 0xAC, 0x0E} },
3513 {ANI_AKM_TYPE_FILS_SHA384, {0x00, 0x0F, 0xAC, 0x0F} },
3514 {ANI_AKM_TYPE_FT_FILS_SHA256, {0x00, 0x0F, 0xAC, 0x10} },
3515 {ANI_AKM_TYPE_FT_FILS_SHA384, {0x00, 0x0F, 0xAC, 0x11} },
3516 {ANI_AKM_TYPE_OWE, {0x00, 0x0F, 0xAC, 0x12} },
3517 #ifdef FEATURE_WLAN_ESE
3518 {ANI_AKM_TYPE_CCKM, {0x00, 0x40, 0x96, 0x00} },
3519 #endif
3520 {ANI_AKM_TYPE_OSEN, {0x50, 0x6F, 0x9A, 0x01} },
3521 {ANI_AKM_TYPE_DPP_RSN, {0x50, 0x6F, 0x9A, 0x02} },
3522 {ANI_AKM_TYPE_WPA, {0x00, 0x50, 0xF2, 0x01} },
3523 {ANI_AKM_TYPE_WPA_PSK, {0x00, 0x50, 0xF2, 0x02} },
3524 {ANI_AKM_TYPE_SAE_EXT_KEY, {0x00, 0x0F, 0xAC, 0x18} },
3525 {ANI_AKM_TYPE_FT_SAE_EXT_KEY, {0x00, 0x0F, 0xAC, 0x19} },
3526 /* Add akm type above here */
3527 {ANI_AKM_TYPE_UNKNOWN, {0} },
3528 };
3529
lim_translate_rsn_oui_to_akm_type(uint8_t auth_suite[4])3530 enum ani_akm_type lim_translate_rsn_oui_to_akm_type(uint8_t auth_suite[4])
3531 {
3532 const struct rsn_oui_akm_type_map *map;
3533 enum ani_akm_type akm_type;
3534
3535 map = rsn_oui_akm_type_mapping_table;
3536 while (true) {
3537 akm_type = map->akm_type;
3538 if ((akm_type == ANI_AKM_TYPE_UNKNOWN) ||
3539 (qdf_mem_cmp(auth_suite, map->rsn_oui, 4) == 0))
3540 break;
3541 map++;
3542 }
3543
3544 pe_debug("akm_type: %d", akm_type);
3545
3546 return akm_type;
3547 }
3548
3549 #if defined(WLAN_FEATURE_ROAM_OFFLOAD) && defined(WLAN_FEATURE_11BE_MLO)
3550 QDF_STATUS
lim_cm_fill_link_session(struct mac_context * mac_ctx,uint8_t vdev_id,struct pe_session * pe_session,struct roam_offload_synch_ind * sync_ind,uint16_t ie_len)3551 lim_cm_fill_link_session(struct mac_context *mac_ctx,
3552 uint8_t vdev_id,
3553 struct pe_session *pe_session,
3554 struct roam_offload_synch_ind *sync_ind,
3555 uint16_t ie_len)
3556 {
3557 struct wlan_objmgr_vdev *vdev;
3558 struct wlan_objmgr_vdev *assoc_vdev;
3559 QDF_STATUS status = QDF_STATUS_SUCCESS;
3560 struct bss_description *bss_desc = NULL;
3561 uint32_t bss_len;
3562 struct join_req *pe_join_req;
3563
3564 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc,
3565 vdev_id,
3566 WLAN_LEGACY_MAC_ID);
3567 if (!vdev) {
3568 pe_err("Vdev is NULL");
3569 return QDF_STATUS_E_NULL_VALUE;
3570 }
3571
3572 bss_len = (uint16_t)(offsetof(struct bss_description,
3573 ieFields[0]) + ie_len);
3574
3575 assoc_vdev = wlan_mlo_get_assoc_link_vdev(vdev);
3576
3577 if (!assoc_vdev) {
3578 pe_err("Assoc vdev is NULL");
3579 status = QDF_STATUS_E_FAILURE;
3580 goto end;
3581 }
3582
3583 status = wlan_vdev_mlme_get_ssid(assoc_vdev,
3584 pe_session->ssId.ssId,
3585 &pe_session->ssId.length);
3586
3587 if (QDF_IS_STATUS_ERROR(status)) {
3588 pe_err("Failed to get ssid vdev id %d",
3589 vdev_id);
3590 status = QDF_STATUS_E_FAILURE;
3591 goto end;
3592 }
3593
3594 pe_session->lim_join_req =
3595 qdf_mem_malloc(sizeof(*pe_session->lim_join_req) + bss_len);
3596 if (!pe_session->lim_join_req) {
3597 status = QDF_STATUS_E_NOMEM;
3598 goto end;
3599 }
3600
3601 pe_join_req = pe_session->lim_join_req;
3602
3603 mlo_roam_copy_partner_info(&pe_join_req->partner_info,
3604 sync_ind, vdev_id, false);
3605
3606 bss_desc = &pe_session->lim_join_req->bssDescription;
3607
3608 status = lim_roam_fill_bss_descr(mac_ctx, sync_ind, bss_desc,
3609 pe_session);
3610 if (!QDF_IS_STATUS_SUCCESS(status)) {
3611 pe_err("LFR3:Failed to fill Bss Descr");
3612 goto end;
3613 }
3614
3615 status = lim_fill_pe_session(mac_ctx, pe_session, bss_desc);
3616 if (QDF_IS_STATUS_ERROR(status)) {
3617 pe_err("Failed to fill pe session vdev id %d",
3618 pe_session->vdev_id);
3619 goto end;
3620 }
3621
3622 if (pe_session->limSmeState == eLIM_SME_WT_JOIN_STATE) {
3623 pe_session->limSmeState = eLIM_SME_LINK_EST_STATE;
3624 pe_session->limMlmState = eLIM_MLM_WT_REASSOC_RSP_STATE;
3625 }
3626 end:
3627 if (QDF_IS_STATUS_ERROR(status)) {
3628 qdf_mem_free(pe_session->lim_join_req);
3629 pe_session->lim_join_req = NULL;
3630 }
3631 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
3632
3633 return status;
3634 }
3635
3636 struct pe_session *
lim_cm_roam_create_session(struct mac_context * mac_ctx,uint8_t vdev_id,struct roam_offload_synch_ind * sync_ind)3637 lim_cm_roam_create_session(struct mac_context *mac_ctx,
3638 uint8_t vdev_id,
3639 struct roam_offload_synch_ind *sync_ind)
3640 {
3641 struct pe_session *pe_session = NULL;
3642 struct qdf_mac_addr link_mac_addr;
3643 bool is_link_vdev = false;
3644 QDF_STATUS status = QDF_STATUS_E_FAILURE;
3645 uint8_t session_id;
3646
3647 is_link_vdev = wlan_vdev_mlme_get_is_mlo_link(mac_ctx->psoc, vdev_id);
3648 status = mlo_get_sta_link_mac_addr(vdev_id, sync_ind,
3649 &link_mac_addr);
3650
3651 if (QDF_IS_STATUS_ERROR(status))
3652 return NULL;
3653
3654 /* In case of legacy to mlo roaming, create pe session */
3655 if (!pe_session && is_link_vdev) {
3656 pe_session = pe_create_session(mac_ctx, &link_mac_addr.bytes[0],
3657 &session_id,
3658 mac_ctx->lim.max_sta_of_pe_session,
3659 eSIR_INFRASTRUCTURE_MODE,
3660 vdev_id);
3661 if (!pe_session) {
3662 pe_err("vdev_id %d : pe session create failed BSSID"
3663 QDF_MAC_ADDR_FMT, vdev_id,
3664 QDF_MAC_ADDR_REF(link_mac_addr.bytes));
3665 return NULL;
3666 }
3667 }
3668
3669 return pe_session;
3670 }
3671
3672 QDF_STATUS
lim_create_and_fill_link_session(struct mac_context * mac_ctx,uint8_t vdev_id,struct roam_offload_synch_ind * sync_ind,uint16_t ie_len)3673 lim_create_and_fill_link_session(struct mac_context *mac_ctx,
3674 uint8_t vdev_id,
3675 struct roam_offload_synch_ind *sync_ind,
3676 uint16_t ie_len)
3677 {
3678 struct pe_session *pe_session;
3679 QDF_STATUS status;
3680
3681 if (!mac_ctx)
3682 return QDF_STATUS_E_INVAL;
3683
3684 pe_session = lim_cm_roam_create_session(mac_ctx, vdev_id, sync_ind);
3685 if (!pe_session)
3686 goto fail;
3687
3688 status = lim_cm_fill_link_session(mac_ctx, vdev_id,
3689 pe_session, sync_ind, ie_len);
3690 if (QDF_IS_STATUS_ERROR(status))
3691 goto fail;
3692
3693 return QDF_STATUS_SUCCESS;
3694
3695 fail:
3696 if (pe_session)
3697 pe_delete_session(mac_ctx, pe_session);
3698
3699 pe_err("MLO ROAM: Link session creation failed");
3700 return QDF_STATUS_E_FAILURE;
3701 }
3702
lim_roam_mlo_create_peer(struct mac_context * mac,struct roam_offload_synch_ind * sync_ind,uint8_t vdev_id,uint8_t * peer_mac)3703 QDF_STATUS lim_roam_mlo_create_peer(struct mac_context *mac,
3704 struct roam_offload_synch_ind *sync_ind,
3705 uint8_t vdev_id, uint8_t *peer_mac)
3706 {
3707 struct wlan_objmgr_vdev *vdev;
3708 struct wlan_objmgr_peer *link_peer = NULL;
3709 uint8_t link_id;
3710 struct mlo_partner_info partner_info;
3711 struct qdf_mac_addr link_addr;
3712 QDF_STATUS status = QDF_STATUS_SUCCESS;
3713
3714 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc,
3715 vdev_id,
3716 WLAN_LEGACY_MAC_ID);
3717 if (!vdev)
3718 return QDF_STATUS_E_INVAL;
3719
3720 if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
3721 goto end;
3722
3723 link_id = mlo_roam_get_link_id(vdev_id, sync_ind);
3724 /* currently only 2 link MLO supported */
3725 partner_info.num_partner_links = 1;
3726 status = mlo_get_sta_link_mac_addr(vdev_id, sync_ind, &link_addr);
3727 if (QDF_IS_STATUS_ERROR(status)) {
3728 pe_err("Link mac address not found");
3729 goto end;
3730 }
3731
3732 qdf_mem_copy(partner_info.partner_link_info[0].link_addr.bytes,
3733 link_addr.bytes, QDF_MAC_ADDR_SIZE);
3734 partner_info.partner_link_info[0].link_id = link_id;
3735 pe_debug("link_addr " QDF_MAC_ADDR_FMT,
3736 QDF_MAC_ADDR_REF(
3737 partner_info.partner_link_info[0].link_addr.bytes));
3738
3739 /* Get the bss peer obj */
3740 link_peer = wlan_objmgr_get_peer_by_mac(mac->psoc, peer_mac,
3741 WLAN_LEGACY_MAC_ID);
3742 if (!link_peer) {
3743 status = QDF_STATUS_E_INVAL;
3744 goto end;
3745 }
3746
3747 status = wlan_mlo_peer_create(vdev, link_peer, &partner_info, NULL, 0);
3748 if (QDF_IS_STATUS_ERROR(status))
3749 pe_err("MLO peer creation failed");
3750
3751 wlan_objmgr_peer_release_ref(link_peer, WLAN_LEGACY_MAC_ID);
3752
3753 end:
3754 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
3755
3756 return status;
3757 }
3758
3759 void
lim_mlo_roam_delete_link_peer(struct pe_session * pe_session,tpDphHashNode sta_ds)3760 lim_mlo_roam_delete_link_peer(struct pe_session *pe_session,
3761 tpDphHashNode sta_ds)
3762 {
3763 struct wlan_objmgr_peer *peer = NULL;
3764 struct mac_context *mac;
3765
3766 mac = cds_get_context(QDF_MODULE_ID_PE);
3767 if (!mac) {
3768 pe_err("mac ctx is null");
3769 return;
3770 }
3771 if (!pe_session) {
3772 pe_err("pe session is null");
3773 return;
3774 }
3775 if (!sta_ds) {
3776 pe_err("sta ds is null");
3777 return;
3778 }
3779
3780 peer = wlan_objmgr_get_peer_by_mac(mac->psoc,
3781 sta_ds->staAddr,
3782 WLAN_LEGACY_MAC_ID);
3783 if (!peer) {
3784 mlo_err("Peer is null");
3785 return;
3786 }
3787
3788 wlan_mlo_link_peer_delete(peer);
3789
3790 wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_MAC_ID);
3791 }
3792 #endif
3793
lim_update_omn_ie_ch_width(struct wlan_objmgr_vdev * vdev,enum phy_ch_width ch_width)3794 void lim_update_omn_ie_ch_width(struct wlan_objmgr_vdev *vdev,
3795 enum phy_ch_width ch_width)
3796 {
3797 struct mlme_legacy_priv *mlme_priv;
3798
3799 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
3800 if (!mlme_priv) {
3801 mlme_legacy_err("vdev legacy private object is NULL");
3802 return;
3803 }
3804
3805 mlme_priv->connect_info.assoc_chan_info.omn_ie_ch_width = ch_width;
3806 }
3807
3808 #ifdef WLAN_FEATURE_11BE_MLO
3809 static bool
lim_match_link_info(uint8_t req_link_id,struct qdf_mac_addr * link_addr,struct mlo_partner_info * partner_info)3810 lim_match_link_info(uint8_t req_link_id,
3811 struct qdf_mac_addr *link_addr,
3812 struct mlo_partner_info *partner_info)
3813 {
3814 uint8_t i;
3815
3816 for (i = 0; i < partner_info->num_partner_links; i++) {
3817 if (partner_info->partner_link_info[i].link_id == req_link_id &&
3818 (qdf_is_macaddr_equal(link_addr,
3819 &partner_info->partner_link_info[i].link_addr)))
3820 return true;
3821 }
3822
3823 return false;
3824 }
3825
3826 QDF_STATUS
lim_add_bcn_probe(struct wlan_objmgr_vdev * vdev,uint8_t * bcn_probe,uint32_t len,qdf_freq_t freq,int32_t rssi)3827 lim_add_bcn_probe(struct wlan_objmgr_vdev *vdev, uint8_t *bcn_probe,
3828 uint32_t len, qdf_freq_t freq, int32_t rssi)
3829 {
3830 qdf_nbuf_t buf;
3831 struct wlan_objmgr_pdev *pdev;
3832 uint8_t *data, i, vdev_id;
3833 struct mgmt_rx_event_params rx_param = {0};
3834 struct wlan_frame_hdr *hdr;
3835 enum mgmt_frame_type frm_type = MGMT_BEACON;
3836 QDF_STATUS status = QDF_STATUS_SUCCESS;
3837
3838 vdev_id = wlan_vdev_get_id(vdev);
3839 if (!bcn_probe || !len || (len < sizeof(*hdr)) ||
3840 len > MAX_MGMT_MPDU_LEN) {
3841 pe_err("bcn_probe is null or invalid len %d",
3842 len);
3843 return QDF_STATUS_E_FAILURE;
3844 }
3845
3846 pdev = wlan_vdev_get_pdev(vdev);
3847 if (!pdev) {
3848 pe_err("Failed to find pdev");
3849 return QDF_STATUS_E_FAILURE;
3850 }
3851
3852 hdr = (struct wlan_frame_hdr *)bcn_probe;
3853 if ((hdr->i_fc[0] & QDF_IEEE80211_FC0_SUBTYPE_MASK) ==
3854 MGMT_SUBTYPE_PROBE_RESP)
3855 frm_type = MGMT_PROBE_RESP;
3856
3857 rx_param.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
3858 rx_param.chan_freq = freq;
3859 rx_param.rssi = rssi;
3860
3861 /* Set all per chain rssi as invalid */
3862 for (i = 0; i < WLAN_MGMT_TXRX_HOST_MAX_ANTENNA; i++)
3863 rx_param.rssi_ctl[i] = WLAN_INVALID_PER_CHAIN_RSSI;
3864
3865 buf = qdf_nbuf_alloc(NULL, qdf_roundup(len, 4), 0, 4, false);
3866 if (!buf)
3867 return QDF_STATUS_E_FAILURE;
3868
3869 qdf_nbuf_put_tail(buf, len);
3870 qdf_nbuf_set_protocol(buf, ETH_P_CONTROL);
3871
3872 data = qdf_nbuf_data(buf);
3873 qdf_mem_copy(data, bcn_probe, len);
3874
3875 pe_debug("MLO: add prb rsp to scan db");
3876 /* buf will be freed by scan module in error or success case */
3877 status = wlan_scan_process_bcn_probe_rx_sync(wlan_pdev_get_psoc(pdev), buf,
3878 &rx_param, frm_type);
3879
3880 return status;
3881 }
3882
3883 #ifdef WLAN_FEATURE_11BE_MLO
3884 static QDF_STATUS
lim_validate_probe_rsp_link_info(struct pe_session * session_entry,uint8_t * probe_rsp,uint32_t probe_rsp_len)3885 lim_validate_probe_rsp_link_info(struct pe_session *session_entry,
3886 uint8_t *probe_rsp,
3887 uint32_t probe_rsp_len)
3888 {
3889 QDF_STATUS status = QDF_STATUS_SUCCESS;
3890 uint8_t *ml_ie = NULL;
3891 qdf_size_t ml_ie_total_len;
3892 struct mlo_partner_info partner_info;
3893 uint8_t i;
3894 struct mlo_partner_info ml_partner_info;
3895
3896 status = util_find_mlie(probe_rsp + WLAN_PROBE_RESP_IES_OFFSET,
3897 probe_rsp_len - WLAN_PROBE_RESP_IES_OFFSET,
3898 &ml_ie, &ml_ie_total_len);
3899 if (QDF_IS_STATUS_ERROR(status)) {
3900 pe_err("Mlo ie not found in Probe response");
3901 return status;
3902 }
3903 status = util_get_bvmlie_persta_partner_info(ml_ie,
3904 ml_ie_total_len,
3905 &partner_info);
3906
3907 if (QDF_IS_STATUS_ERROR(status)) {
3908 pe_err("Per STA profile parsing failed");
3909 return status;
3910 }
3911
3912 ml_partner_info = session_entry->lim_join_req->partner_info;
3913 for (i = 0; i < ml_partner_info.num_partner_links; i++) {
3914 if (!lim_match_link_info(ml_partner_info.partner_link_info[i].link_id,
3915 &ml_partner_info.partner_link_info[i].link_addr,
3916 &partner_info)) {
3917 pe_err("Atleast one Per-STA profile is missing in the ML-probe response");
3918 return QDF_STATUS_E_PROTO;
3919 }
3920 }
3921
3922 return status;
3923 }
3924
3925 static void
lim_clear_ml_partner_info(struct pe_session * session_entry)3926 lim_clear_ml_partner_info(struct pe_session *session_entry)
3927 {
3928 uint8_t idx;
3929 struct mlo_partner_info *partner_info = NULL;
3930
3931 if (!session_entry || !session_entry->lim_join_req)
3932 return;
3933
3934 partner_info = &session_entry->lim_join_req->partner_info;
3935 if (!partner_info) {
3936 pe_err("Partner link info not present");
3937 return;
3938 }
3939 pe_debug_rl("Clear Partner Link/s information");
3940 for (idx = 0; idx < partner_info->num_partner_links; idx++) {
3941 mlo_mgr_clear_ap_link_info(session_entry->vdev,
3942 partner_info->partner_link_info[idx].link_addr.bytes);
3943
3944 partner_info->partner_link_info[idx].link_id = 0;
3945 qdf_zero_macaddr(
3946 &partner_info->partner_link_info[idx].link_addr);
3947 }
3948 partner_info->num_partner_links = 0;
3949 }
3950
3951 static QDF_STATUS
lim_check_scan_db_for_join_req_partner_info(struct pe_session * session_entry,struct mac_context * mac_ctx)3952 lim_check_scan_db_for_join_req_partner_info(struct pe_session *session_entry,
3953 struct mac_context *mac_ctx)
3954 {
3955 struct join_req *lim_join_req;
3956 struct wlan_objmgr_pdev *pdev;
3957 struct mlo_partner_info *partner_info;
3958 struct mlo_link_info *link_info;
3959 struct scan_cache_entry *partner_entry;
3960 uint8_t i;
3961
3962 if (!session_entry) {
3963 pe_err("session entry is NULL");
3964 return QDF_STATUS_E_NULL_VALUE;
3965 }
3966
3967 if (!mac_ctx) {
3968 pe_err("mac context is NULL");
3969 return QDF_STATUS_E_NULL_VALUE;
3970 }
3971
3972 lim_join_req = session_entry->lim_join_req;
3973 if (!lim_join_req) {
3974 pe_err("join req is NULL");
3975 return QDF_STATUS_E_NULL_VALUE;
3976 }
3977
3978 pdev = mac_ctx->pdev;
3979 if (!pdev) {
3980 pe_err("pdev is NULL");
3981 return QDF_STATUS_E_NULL_VALUE;
3982 }
3983
3984 partner_info = &lim_join_req->partner_info;
3985 for (i = 0; i < partner_info->num_partner_links; i++) {
3986 link_info = &partner_info->partner_link_info[i];
3987 partner_entry =
3988 wlan_scan_get_entry_by_bssid(pdev,
3989 &link_info->link_addr);
3990 if (!partner_entry) {
3991 pe_err("Scan entry is not found for partner link %d "
3992 QDF_MAC_ADDR_FMT,
3993 link_info->link_id,
3994 QDF_MAC_ADDR_REF(link_info->link_addr.bytes));
3995 return QDF_STATUS_E_FAILURE;
3996 }
3997 util_scan_free_cache_entry(partner_entry);
3998 }
3999
4000 return QDF_STATUS_SUCCESS;
4001 }
4002
lim_update_mlo_mgr_info(struct mac_context * mac_ctx,struct wlan_objmgr_vdev * vdev,struct qdf_mac_addr * link_addr,uint8_t link_id,uint16_t freq)4003 QDF_STATUS lim_update_mlo_mgr_info(struct mac_context *mac_ctx,
4004 struct wlan_objmgr_vdev *vdev,
4005 struct qdf_mac_addr *link_addr,
4006 uint8_t link_id, uint16_t freq)
4007 {
4008 struct wlan_objmgr_pdev *pdev;
4009 struct scan_cache_entry *cache_entry;
4010 struct wlan_channel channel;
4011 bool is_security_allowed;
4012
4013 pdev = mac_ctx->pdev;
4014 if (!pdev) {
4015 pe_err("pdev is NULL");
4016 return QDF_STATUS_E_NULL_VALUE;
4017 }
4018
4019 cache_entry = wlan_scan_get_scan_entry_by_mac_freq(pdev, link_addr,
4020 freq);
4021 if (!cache_entry)
4022 return QDF_STATUS_E_FAILURE;
4023
4024 /**
4025 * Reject all the partner link if any partner link doesn’t pass the
4026 * security check and proceed connection with single link.
4027 */
4028 is_security_allowed =
4029 wlan_cm_is_eht_allowed_for_current_security(
4030 wlan_pdev_get_psoc(mac_ctx->pdev),
4031 cache_entry, true);
4032
4033 if (!is_security_allowed) {
4034 mlme_debug("current security is not valid for partner link link_addr:" QDF_MAC_ADDR_FMT,
4035 QDF_MAC_ADDR_REF(link_addr->bytes));
4036 util_scan_free_cache_entry(cache_entry);
4037 return QDF_STATUS_E_FAILURE;
4038 }
4039
4040 channel.ch_freq = cache_entry->channel.chan_freq;
4041 channel.ch_ieee = wlan_reg_freq_to_chan(pdev, channel.ch_freq);
4042 channel.ch_phymode = cache_entry->phy_mode;
4043 channel.ch_cfreq1 = cache_entry->channel.cfreq0;
4044 channel.ch_cfreq2 = cache_entry->channel.cfreq1;
4045 channel.ch_width =
4046 wlan_mlme_get_ch_width_from_phymode(cache_entry->phy_mode);
4047
4048 /*
4049 * Supplicant needs non zero center_freq1 in case of 20 MHz connection
4050 * also as a response of get_channel request. In case of 20 MHz channel
4051 * width central frequency is same as channel frequency
4052 */
4053 if (channel.ch_width == CH_WIDTH_20MHZ)
4054 channel.ch_cfreq1 = channel.ch_freq;
4055
4056 util_scan_free_cache_entry(cache_entry);
4057
4058 mlo_mgr_update_ap_channel_info(vdev, link_id, (uint8_t *)link_addr,
4059 channel);
4060
4061 return QDF_STATUS_SUCCESS;
4062 }
4063 #else
4064 static inline void
lim_clear_ml_partner_info(struct pe_session * session_entry)4065 lim_clear_ml_partner_info(struct pe_session *session_entry)
4066 {
4067 }
4068
4069 static QDF_STATUS
lim_check_db_for_join_req_partner_info(struct pe_session * session_entry,struct mac_context * mac_ctx)4070 lim_check_db_for_join_req_partner_info(struct pe_session *session_entry,
4071 struct mac_context *mac_ctx)
4072 {
4073
4074 return QDF_STATUS_E_FAILURE;
4075 }
4076 #endif
4077
lim_check_for_ml_probe_req(struct pe_session * session)4078 QDF_STATUS lim_check_for_ml_probe_req(struct pe_session *session)
4079 {
4080 if (!session || !session->lim_join_req)
4081 return QDF_STATUS_E_NULL_VALUE;
4082
4083 if (session->lim_join_req->is_ml_probe_req_sent)
4084 return QDF_STATUS_SUCCESS;
4085
4086 return QDF_STATUS_E_FAILURE;
4087 }
4088
lim_check_partner_link_for_cmn_akm(struct pe_session * session)4089 static QDF_STATUS lim_check_partner_link_for_cmn_akm(struct pe_session *session)
4090 {
4091 struct scan_filter *filter;
4092 qdf_list_t *scan_list = NULL;
4093 struct wlan_objmgr_pdev *pdev;
4094 uint8_t idx;
4095 struct mlo_link_info *link_info;
4096 struct scan_cache_entry *cur_entry;
4097 struct scan_cache_node *link_node;
4098 struct mlo_partner_info *partner_info;
4099 qdf_list_node_t *cur_node = NULL, *next_node = NULL;
4100 QDF_STATUS status = QDF_STATUS_SUCCESS;
4101
4102 pdev = wlan_vdev_get_pdev(session->vdev);
4103 if (!pdev) {
4104 pe_err("PDEV NULL");
4105 return QDF_STATUS_E_NULL_VALUE;
4106 }
4107
4108 cur_entry =
4109 wlan_cm_get_curr_candidate_entry(session->vdev, session->cm_id);
4110 if (!cur_entry) {
4111 pe_err("Current candidate NULL");
4112 return QDF_STATUS_E_NULL_VALUE;
4113 }
4114
4115 filter = qdf_mem_malloc(sizeof(*filter));
4116 if (!filter) {
4117 status = QDF_STATUS_E_NOMEM;
4118 goto mem_free;
4119 }
4120
4121 partner_info = &session->lim_join_req->partner_info;
4122 for (idx = 0; idx < partner_info->num_partner_links; idx++) {
4123 link_info = &partner_info->partner_link_info[idx];
4124 qdf_copy_macaddr(&filter->bssid_list[idx],
4125 &link_info->link_addr);
4126 filter->num_of_bssid++;
4127
4128 filter->chan_freq_list[idx] = link_info->chan_freq;
4129 filter->num_of_channels++;
4130 }
4131
4132 /* If no.of. scan entries fetched not equal to no.of partner links
4133 * then fail as common AKM is not determined.
4134 */
4135 scan_list = wlan_scan_get_result(pdev, filter);
4136 qdf_mem_free(filter);
4137 if (!scan_list ||
4138 (qdf_list_size(scan_list) != partner_info->num_partner_links)) {
4139 status = QDF_STATUS_E_INVAL;
4140 goto mem_free;
4141 }
4142
4143 qdf_list_peek_front(scan_list, &cur_node);
4144 while (cur_node) {
4145 qdf_list_peek_next(scan_list, cur_node, &next_node);
4146 link_node = qdf_container_of(cur_node, struct scan_cache_node,
4147 node);
4148
4149 if (!wlan_scan_entries_contain_cmn_akm(cur_entry,
4150 link_node->entry)) {
4151 status = QDF_STATUS_E_FAILURE;
4152 break;
4153 }
4154
4155 cur_node = next_node;
4156 next_node = NULL;
4157 }
4158
4159 mem_free:
4160 if (scan_list)
4161 wlan_scan_purge_results(scan_list);
4162 util_scan_free_cache_entry(cur_entry);
4163 return status;
4164 }
4165
lim_gen_link_specific_probe_rsp(struct mac_context * mac_ctx,struct pe_session * session_entry,tpSirProbeRespBeacon rcvd_probe_resp,uint8_t * probe_rsp,uint32_t probe_rsp_len,int32_t rssi)4166 QDF_STATUS lim_gen_link_specific_probe_rsp(struct mac_context *mac_ctx,
4167 struct pe_session *session_entry,
4168 tpSirProbeRespBeacon rcvd_probe_resp,
4169 uint8_t *probe_rsp,
4170 uint32_t probe_rsp_len, int32_t rssi)
4171 {
4172 struct element_info link_probe_rsp = {0};
4173 struct qdf_mac_addr sta_link_addr;
4174 QDF_STATUS status = QDF_STATUS_E_FAILURE;
4175 struct mlo_link_info *link_info = NULL;
4176 struct mlo_partner_info *partner_info;
4177 uint8_t chan;
4178 uint8_t op_class;
4179 uint16_t chan_freq, gen_frame_len;
4180 uint8_t idx;
4181 uint8_t req_link_id;
4182
4183 if (!session_entry)
4184 return QDF_STATUS_E_NULL_VALUE;
4185
4186 if (!session_entry->lim_join_req)
4187 return status;
4188
4189 partner_info = &session_entry->lim_join_req->partner_info;
4190 if (!partner_info->num_partner_links) {
4191 pe_debug("No partner link info since supports 1 link only");
4192 return status;
4193 }
4194
4195 if (session_entry->lim_join_req->is_ml_probe_req_sent &&
4196 rcvd_probe_resp->mlo_ie.mlo_ie_present) {
4197 session_entry->lim_join_req->is_ml_probe_req_sent = false;
4198
4199 partner_info = &session_entry->lim_join_req->partner_info;
4200 if (!partner_info->num_partner_links) {
4201 pe_err("STA doesn't have any partner link information");
4202 return QDF_STATUS_E_FAILURE;
4203 }
4204
4205 status = lim_validate_probe_rsp_link_info(session_entry,
4206 probe_rsp,
4207 probe_rsp_len);
4208 if (QDF_IS_STATUS_ERROR(status)) {
4209 if(QDF_IS_STATUS_ERROR(
4210 lim_check_scan_db_for_join_req_partner_info(
4211 session_entry,
4212 mac_ctx)))
4213 lim_clear_ml_partner_info(session_entry);
4214 return status;
4215 }
4216
4217 /*
4218 * When an MLO probe response is received from a link,
4219 * the other link might be superior in features compared to the
4220 * link that sent ML probe rsp and the per-STA profile
4221 * info may carry corresponding IEs. These IEs are extracted
4222 * and added to IE list of link probe response while generating
4223 * it. So, the new link probe response generated might be of
4224 * more size than the original link probe rsp. Allocate buffer
4225 * for the scan entry to accommodate all of the IEs got
4226 * generated as part of link probe rsp generation. Allocate
4227 * MAX_MGMT_MPDU_LEN bytes for IEs as the max frame size that
4228 * can be received from AP is MAX_MGMT_MPDU_LEN bytes.
4229 */
4230 gen_frame_len = MAX_MGMT_MPDU_LEN;
4231
4232 link_probe_rsp.ptr = qdf_mem_malloc(gen_frame_len);
4233 if (!link_probe_rsp.ptr) {
4234 if(QDF_IS_STATUS_ERROR(
4235 lim_check_scan_db_for_join_req_partner_info(
4236 session_entry,
4237 mac_ctx)))
4238 lim_clear_ml_partner_info(session_entry);
4239 return QDF_STATUS_E_NOMEM;
4240 }
4241
4242 link_probe_rsp.len = gen_frame_len;
4243 qdf_mem_copy(&sta_link_addr, session_entry->self_mac_addr,
4244 QDF_MAC_ADDR_SIZE);
4245
4246 for (idx = 0; idx < partner_info->num_partner_links; idx++) {
4247 req_link_id =
4248 partner_info->partner_link_info[idx].link_id;
4249 status = util_gen_link_probe_rsp(probe_rsp,
4250 probe_rsp_len, req_link_id,
4251 sta_link_addr, link_probe_rsp.ptr,
4252 gen_frame_len,
4253 (qdf_size_t *)&link_probe_rsp.len);
4254
4255 if (QDF_IS_STATUS_ERROR(status)) {
4256 pe_err("MLO: Link %d probe resp gen failed %d",
4257 req_link_id, status);
4258 status =
4259 lim_check_scan_db_for_join_req_partner_info(
4260 session_entry, mac_ctx);
4261 if (QDF_IS_STATUS_ERROR(status))
4262 lim_clear_ml_partner_info(session_entry);
4263
4264 goto end;
4265 }
4266
4267 pe_debug("MLO:link probe rsp size:%u orig probe rsp:%u",
4268 link_probe_rsp.len, probe_rsp_len);
4269
4270 link_info = &partner_info->partner_link_info[idx];
4271 wlan_get_chan_by_bssid_from_rnr(session_entry->vdev,
4272 session_entry->cm_id,
4273 &link_info->link_addr,
4274 &chan, &op_class);
4275 if (!chan)
4276 wlan_get_chan_by_link_id_from_rnr(
4277 session_entry->vdev,
4278 session_entry->cm_id,
4279 link_info->link_id,
4280 &chan, &op_class);
4281 if (!chan) {
4282 pe_err("Invalid link id %d link mac: " QDF_MAC_ADDR_FMT,
4283 link_info->link_id,
4284 QDF_MAC_ADDR_REF(link_info->link_addr.bytes));
4285 status =
4286 lim_check_scan_db_for_join_req_partner_info(
4287 session_entry, mac_ctx);
4288 if (QDF_IS_STATUS_ERROR(status))
4289 lim_clear_ml_partner_info(session_entry);
4290
4291 status = QDF_STATUS_E_FAILURE;
4292 goto end;
4293 }
4294 chan_freq =
4295 wlan_reg_chan_opclass_to_freq(chan, op_class,
4296 true);
4297
4298 status = lim_add_bcn_probe(session_entry->vdev,
4299 link_probe_rsp.ptr,
4300 link_probe_rsp.len,
4301 chan_freq, rssi);
4302 if (QDF_IS_STATUS_ERROR(status)) {
4303 pe_err("failed to add bcn probe %d", status);
4304 status =
4305 lim_check_scan_db_for_join_req_partner_info(
4306 session_entry, mac_ctx);
4307 if (QDF_IS_STATUS_ERROR(status))
4308 lim_clear_ml_partner_info(session_entry);
4309
4310 goto end;
4311 }
4312
4313 status = lim_update_mlo_mgr_info(mac_ctx,
4314 session_entry->vdev,
4315 &link_info->link_addr,
4316 link_info->link_id,
4317 link_info->chan_freq);
4318 if (QDF_IS_STATUS_ERROR(status)) {
4319 pe_err("failed to update mlo_mgr %d", status);
4320 lim_clear_ml_partner_info(session_entry);
4321
4322 goto end;
4323 }
4324 }
4325 /*
4326 * If the partner link's AKM not matching current candidate
4327 * remove the partner links for this association.
4328 */
4329 status = lim_check_partner_link_for_cmn_akm(session_entry);
4330 if (QDF_IS_STATUS_ERROR(status)) {
4331 pe_debug("Non overlapping partner link AKM %d",
4332 status);
4333 lim_clear_ml_partner_info(session_entry);
4334 goto end;
4335 }
4336 } else if (session_entry->lim_join_req->is_ml_probe_req_sent &&
4337 !rcvd_probe_resp->mlo_ie.mlo_ie_present) {
4338 status =
4339 lim_check_scan_db_for_join_req_partner_info(
4340 session_entry, mac_ctx);
4341 if (QDF_IS_STATUS_ERROR(status))
4342 lim_clear_ml_partner_info(session_entry);
4343
4344 return QDF_STATUS_E_FAILURE;
4345 } else {
4346 return status;
4347 }
4348 end:
4349 if (link_probe_rsp.ptr)
4350 qdf_mem_free(link_probe_rsp.ptr);
4351 link_probe_rsp.ptr = NULL;
4352 link_probe_rsp.len = 0;
4353 return status;
4354 }
4355
4356 QDF_STATUS
lim_process_cu_for_probe_rsp(struct mac_context * mac_ctx,struct pe_session * session,uint8_t * probe_rsp,uint32_t probe_rsp_len)4357 lim_process_cu_for_probe_rsp(struct mac_context *mac_ctx,
4358 struct pe_session *session,
4359 uint8_t *probe_rsp,
4360 uint32_t probe_rsp_len)
4361 {
4362 struct element_info link_probe_rsp;
4363 struct qdf_mac_addr sta_link_addr;
4364 struct wlan_objmgr_vdev *vdev;
4365 struct wlan_objmgr_vdev *partner_vdev;
4366 uint8_t *ml_ie = NULL;
4367 qdf_size_t ml_ie_total_len = 0;
4368 struct mlo_partner_info partner_info;
4369 uint8_t i, link_id, vdev_id;
4370 uint8_t bpcc, aui;
4371 bool cu_flag = false;
4372 const uint8_t *rnr;
4373 bool msd_cap_found = false;
4374 QDF_STATUS status = QDF_STATUS_E_INVAL;
4375
4376 vdev = session->vdev;
4377 if (!vdev || !wlan_vdev_mlme_is_mlo_vdev(vdev))
4378 return status;
4379
4380 rnr = wlan_get_ie_ptr_from_eid(WLAN_ELEMID_REDUCED_NEIGHBOR_REPORT,
4381 probe_rsp + WLAN_PROBE_RESP_IES_OFFSET,
4382 probe_rsp_len - WLAN_PROBE_RESP_IES_OFFSET);
4383 if (!rnr)
4384 return status;
4385
4386 status = util_find_mlie(probe_rsp + WLAN_PROBE_RESP_IES_OFFSET,
4387 probe_rsp_len - WLAN_PROBE_RESP_IES_OFFSET,
4388 &ml_ie, &ml_ie_total_len);
4389 if (QDF_IS_STATUS_ERROR(status)) {
4390 pe_err("Mlo ie not found in Probe response");
4391 return status;
4392 }
4393
4394 util_get_bvmlie_msd_cap(ml_ie, ml_ie_total_len, &msd_cap_found,
4395 NULL);
4396 if (msd_cap_found) {
4397 wlan_vdev_mlme_cap_clear(vdev, WLAN_VDEV_C_EMLSR_CAP);
4398 pe_debug("EMLSR not supported with D2.0 AP");
4399 }
4400
4401 status = util_get_bvmlie_persta_partner_info(ml_ie,
4402 ml_ie_total_len,
4403 &partner_info);
4404 if (QDF_IS_STATUS_ERROR(status)) {
4405 pe_err("Per STA profile parsing failed");
4406 return status;
4407 }
4408
4409 link_probe_rsp.ptr = qdf_mem_malloc(probe_rsp_len);
4410 if (!link_probe_rsp.ptr)
4411 return QDF_STATUS_E_NOMEM;
4412
4413 for (i = 0; i < partner_info.num_partner_links; i++) {
4414 link_id = partner_info.partner_link_info[i].link_id;
4415 partner_vdev = mlo_get_vdev_by_link_id(vdev, link_id,
4416 WLAN_LEGACY_MAC_ID);
4417 if (!partner_vdev) {
4418 pe_debug("No partner vdev for link id %d", link_id);
4419 continue;
4420 }
4421
4422 status = lim_cu_info_from_rnr_per_link_id(rnr, link_id,
4423 &bpcc, &aui);
4424 if (QDF_IS_STATUS_ERROR(status)) {
4425 pe_debug("no cu info in rnr for link id %d", link_id);
4426 goto ref_rel;
4427 }
4428
4429 cu_flag = lim_check_cu_happens(partner_vdev, bpcc);
4430 if (!cu_flag)
4431 goto ref_rel;
4432
4433 vdev_id = wlan_vdev_get_id(partner_vdev);
4434 session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
4435 if (!session) {
4436 pe_debug("session is null for vdev id %d", vdev_id);
4437 goto ref_rel;
4438 }
4439
4440 qdf_mem_copy(&sta_link_addr, session->self_mac_addr,
4441 QDF_MAC_ADDR_SIZE);
4442
4443 link_probe_rsp.len = probe_rsp_len;
4444 /* Todo:
4445 * it needs to use link_id as parameter to generate
4446 * specific probe rsp frame when api util_gen_link_probe_rsp
4447 * updated.
4448 */
4449 status =
4450 util_gen_link_probe_rsp(probe_rsp, probe_rsp_len, link_id,
4451 sta_link_addr, link_probe_rsp.ptr,
4452 probe_rsp_len,
4453 (qdf_size_t *)&link_probe_rsp.len);
4454 if (QDF_IS_STATUS_ERROR(status)) {
4455 pe_err("MLO: Link probe response generation failed %d",
4456 status);
4457 goto ref_rel;
4458 }
4459
4460 lim_process_gen_probe_rsp_frame(mac_ctx, session,
4461 link_probe_rsp.ptr,
4462 link_probe_rsp.len);
4463
4464 ref_rel:
4465 wlan_objmgr_vdev_release_ref(partner_vdev, WLAN_LEGACY_MAC_ID);
4466 }
4467
4468 qdf_mem_free(link_probe_rsp.ptr);
4469 link_probe_rsp.ptr = NULL;
4470 link_probe_rsp.len = 0;
4471 return status;
4472 }
4473 #endif
4474
4475 #ifdef WLAN_FEATURE_SR
4476 static
lim_store_array_to_bit_map(uint64_t * val,uint8_t array[8])4477 void lim_store_array_to_bit_map(uint64_t *val, uint8_t array[8])
4478 {
4479 uint32_t bit_map_0 = 0;
4480 uint32_t bit_map_1 = 0;
4481
4482 QDF_SET_BITS(bit_map_0, 0, SR_PADDING_BYTE, array[0]);
4483 QDF_SET_BITS(bit_map_0, 8, SR_PADDING_BYTE, array[1]);
4484 QDF_SET_BITS(bit_map_0, 16, SR_PADDING_BYTE, array[2]);
4485 QDF_SET_BITS(bit_map_0, 24, SR_PADDING_BYTE, array[3]);
4486 QDF_SET_BITS(bit_map_1, 0, SR_PADDING_BYTE, array[4]);
4487 QDF_SET_BITS(bit_map_1, 8, SR_PADDING_BYTE, array[5]);
4488 QDF_SET_BITS(bit_map_1, 16, SR_PADDING_BYTE, array[6]);
4489 QDF_SET_BITS(bit_map_1, 24, SR_PADDING_BYTE, array[7]);
4490 *val = (uint64_t) bit_map_0 |
4491 (((uint64_t)bit_map_1) << 32);
4492 }
4493
lim_update_vdev_sr_elements(struct pe_session * session_entry,tpDphHashNode sta_ds)4494 void lim_update_vdev_sr_elements(struct pe_session *session_entry,
4495 tpDphHashNode sta_ds)
4496 {
4497 uint8_t sr_ctrl;
4498 uint8_t non_srg_max_pd_offset, srg_min_pd_offset, srg_max_pd_offset;
4499 uint64_t srg_color_bit_map = 0;
4500 uint64_t srg_partial_bssid_bit_map = 0;
4501 tDot11fIEspatial_reuse *srp_ie = &sta_ds->parsed_ies.srp_ie;
4502
4503 sr_ctrl = srp_ie->sr_value15_allow << 4 |
4504 srp_ie->srg_info_present << 3 |
4505 srp_ie->non_srg_offset_present << 2 |
4506 srp_ie->non_srg_pd_sr_disallow << 1 |
4507 srp_ie->psr_disallow;
4508 non_srg_max_pd_offset =
4509 srp_ie->non_srg_offset.info.non_srg_pd_max_offset;
4510 srg_min_pd_offset = srp_ie->srg_info.info.srg_pd_min_offset;
4511 srg_max_pd_offset = srp_ie->srg_info.info.srg_pd_max_offset;
4512 lim_store_array_to_bit_map(&srg_color_bit_map,
4513 srp_ie->srg_info.info.srg_color);
4514 lim_store_array_to_bit_map(&srg_partial_bssid_bit_map,
4515 srp_ie->srg_info.info.srg_partial_bssid);
4516 pe_debug("Spatial Reuse Control field: %x Non-SRG Max PD Offset: %x SRG range %d - %d srg_color_bit_map:%llu srg_partial_bssid_bit_map: %llu",
4517 sr_ctrl, non_srg_max_pd_offset, srg_min_pd_offset,
4518 srg_max_pd_offset, srg_color_bit_map,
4519 srg_partial_bssid_bit_map);
4520 wlan_vdev_mlme_set_srg_partial_bssid_bit_map(session_entry->vdev,
4521 srg_partial_bssid_bit_map);
4522 wlan_vdev_mlme_set_srg_bss_color_bit_map(session_entry->vdev,
4523 srg_color_bit_map);
4524 wlan_vdev_mlme_set_sr_ctrl(session_entry->vdev, sr_ctrl);
4525 wlan_vdev_mlme_set_non_srg_pd_offset(session_entry->vdev,
4526 non_srg_max_pd_offset);
4527 wlan_vdev_mlme_set_srg_pd_offset(session_entry->vdev, srg_max_pd_offset,
4528 srg_min_pd_offset);
4529
4530 }
4531 #endif
4532