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