1 /* 2 * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-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 * 22 * This file lim_process_beacon_frame.cc contains the code 23 * for processing Received Beacon Frame. 24 * Author: Chandra Modumudi 25 * Date: 03/01/02 26 * History:- 27 * Date Modified by Modification Information 28 * -------------------------------------------------------------------- 29 * 30 */ 31 32 #include "wni_cfg.h" 33 #include "ani_global.h" 34 #include "sch_api.h" 35 #include "utils_api.h" 36 #include "lim_types.h" 37 #include "lim_utils.h" 38 #include "lim_assoc_utils.h" 39 #include "lim_prop_exts_utils.h" 40 #include "lim_ser_des_utils.h" 41 #include "wlan_mlo_t2lm.h" 42 #include "wlan_mlo_mgr_roam.h" 43 #include "lim_mlo.h" 44 #include "wlan_mlo_mgr_sta.h" 45 #include "wlan_cm_api.h" 46 #include "wlan_mlme_api.h" 47 #include "wlan_objmgr_vdev_obj.h" 48 #include "wlan_reg_services_api.h" 49 #ifdef WLAN_FEATURE_11BE_MLO 50 #include <cds_ieee80211_common.h> 51 #endif 52 #include "wlan_t2lm_api.h" 53 54 #ifdef WLAN_FEATURE_11BE_MLO 55 56 void lim_process_bcn_prb_rsp_t2lm(struct mac_context *mac_ctx, 57 struct pe_session *session, 58 tpSirProbeRespBeacon bcn_ptr) 59 { 60 struct wlan_objmgr_vdev *vdev; 61 struct wlan_t2lm_context *t2lm_ctx; 62 63 if (!session || !bcn_ptr || !mac_ctx) { 64 pe_err("invalid input parameters"); 65 return; 66 } 67 68 vdev = session->vdev; 69 if (!vdev || !wlan_vdev_mlme_is_mlo_vdev(vdev)) 70 return; 71 72 if (!wlan_cm_is_vdev_connected(vdev)) 73 return; 74 75 if (!mlo_check_if_all_links_up(vdev)) 76 return; 77 78 t2lm_ctx = &vdev->mlo_dev_ctx->t2lm_ctx; 79 80 qdf_mem_copy((uint8_t *)&t2lm_ctx->tsf, (uint8_t *)bcn_ptr->timeStamp, 81 sizeof(uint64_t)); 82 wlan_update_t2lm_mapping(vdev, &bcn_ptr->t2lm_ctx, t2lm_ctx->tsf); 83 } 84 85 void lim_process_beacon_mlo(struct mac_context *mac_ctx, 86 struct pe_session *session, 87 tSchBeaconStruct *bcn_ptr) 88 { 89 struct csa_offload_params csa_param; 90 int i; 91 uint8_t link_id; 92 uint8_t *per_sta_pro; 93 uint32_t per_sta_pro_len; 94 uint8_t *sta_pro; 95 uint32_t sta_pro_len; 96 uint16_t stacontrol; 97 struct ieee80211_channelswitch_ie *csa_ie; 98 struct ieee80211_extendedchannelswitch_ie *xcsa_ie; 99 struct wlan_objmgr_vdev *vdev; 100 struct wlan_objmgr_pdev *pdev; 101 struct wlan_mlo_dev_context *mlo_ctx; 102 uint8_t is_sta_csa_synced; 103 struct mlo_link_info *link_info; 104 uint8_t sta_info_len = 0; 105 106 if (!session || !bcn_ptr || !mac_ctx) { 107 pe_err("invalid input parameters"); 108 return; 109 } 110 vdev = session->vdev; 111 if (!vdev || !wlan_vdev_mlme_is_mlo_vdev(vdev)) 112 return; 113 114 pdev = wlan_vdev_get_pdev(vdev); 115 if (!pdev) { 116 pe_err("null pdev"); 117 return; 118 } 119 mlo_ctx = vdev->mlo_dev_ctx; 120 if (!mlo_ctx) { 121 pe_err("null mlo_dev_ctx"); 122 return; 123 } 124 125 if (bcn_ptr->mlo_ie.mlo_ie.medium_sync_delay_info_present) { 126 wlan_vdev_mlme_cap_clear(vdev, WLAN_VDEV_C_EMLSR_CAP); 127 pe_debug("EMLSR not supported with D2.0 AP"); 128 } 129 130 for (i = 0; i < bcn_ptr->mlo_ie.mlo_ie.num_sta_profile; i++) { 131 csa_ie = NULL; 132 xcsa_ie = NULL; 133 qdf_mem_zero(&csa_param, sizeof(csa_param)); 134 per_sta_pro = bcn_ptr->mlo_ie.mlo_ie.sta_profile[i].data; 135 /* Append one byte to get the element length */ 136 per_sta_pro_len = bcn_ptr->mlo_ie.mlo_ie.sta_profile[i].num_data; 137 stacontrol = *(uint16_t *)(per_sta_pro + sizeof(struct subelem_header)); 138 sta_info_len = *(uint8_t *)(per_sta_pro + 139 sizeof(struct subelem_header) + WLAN_ML_BV_LINFO_PERSTAPROF_STACTRL_SIZE); 140 /* IE ID + LEN + STA control STA info len*/ 141 sta_pro = per_sta_pro + sizeof(struct subelem_header) + 142 WLAN_ML_BV_LINFO_PERSTAPROF_STACTRL_SIZE + sta_info_len; 143 sta_pro_len = per_sta_pro_len - sizeof(struct subelem_header) - 144 WLAN_ML_BV_LINFO_PERSTAPROF_STACTRL_SIZE - sta_info_len; 145 link_id = QDF_GET_BITS( 146 stacontrol, 147 WLAN_ML_BV_LINFO_PERSTAPROF_STACTRL_LINKID_IDX, 148 WLAN_ML_BV_LINFO_PERSTAPROF_STACTRL_LINKID_BITS); 149 150 csa_ie = (struct ieee80211_channelswitch_ie *) 151 wlan_get_ie_ptr_from_eid( 152 DOT11F_EID_CHANSWITCHANN, 153 sta_pro, sta_pro_len); 154 xcsa_ie = (struct ieee80211_extendedchannelswitch_ie *) 155 wlan_get_ie_ptr_from_eid( 156 DOT11F_EID_EXT_CHAN_SWITCH_ANN, 157 sta_pro, sta_pro_len); 158 is_sta_csa_synced = mlo_is_sta_csa_synced(mlo_ctx, link_id); 159 link_info = mlo_mgr_get_ap_link_by_link_id(mlo_ctx, link_id); 160 if (!link_info) { 161 mlo_err("link info null"); 162 return; 163 } 164 165 if (csa_ie) { 166 csa_param.channel = csa_ie->newchannel; 167 csa_param.csa_chan_freq = wlan_reg_legacy_chan_to_freq( 168 pdev, csa_ie->newchannel); 169 csa_param.switch_mode = csa_ie->switchmode; 170 csa_param.ies_present_flag |= MLME_CSA_IE_PRESENT; 171 mlo_sta_handle_csa_standby_link(mlo_ctx, link_id, 172 &csa_param, vdev); 173 174 if (!is_sta_csa_synced) 175 mlo_sta_csa_save_params(mlo_ctx, link_id, 176 &csa_param); 177 } else if (xcsa_ie) { 178 csa_param.channel = xcsa_ie->newchannel; 179 csa_param.switch_mode = xcsa_ie->switchmode; 180 csa_param.new_op_class = xcsa_ie->newClass; 181 if (wlan_reg_is_6ghz_op_class(pdev, xcsa_ie->newClass)) 182 csa_param.csa_chan_freq = 183 wlan_reg_chan_band_to_freq( 184 pdev, xcsa_ie->newchannel, 185 BIT(REG_BAND_6G)); 186 else 187 csa_param.csa_chan_freq = 188 wlan_reg_legacy_chan_to_freq( 189 pdev, xcsa_ie->newchannel); 190 csa_param.ies_present_flag |= MLME_XCSA_IE_PRESENT; 191 mlo_sta_handle_csa_standby_link(mlo_ctx, link_id, 192 &csa_param, vdev); 193 if (!is_sta_csa_synced) 194 mlo_sta_csa_save_params(mlo_ctx, link_id, 195 &csa_param); 196 } 197 } 198 } 199 #endif 200 201 static QDF_STATUS 202 lim_validate_rsn_ie(const uint8_t *ie_ptr, uint16_t ie_len) 203 { 204 QDF_STATUS status; 205 const uint8_t *rsn_ie; 206 struct wlan_crypto_params crypto_params; 207 208 rsn_ie = wlan_get_ie_ptr_from_eid(WLAN_ELEMID_RSN, ie_ptr, ie_len); 209 if (!rsn_ie) 210 return QDF_STATUS_SUCCESS; 211 212 qdf_mem_zero(&crypto_params, sizeof(struct wlan_crypto_params)); 213 status = wlan_crypto_rsnie_check(&crypto_params, rsn_ie); 214 if (status != QDF_STATUS_SUCCESS) { 215 pe_debug_rl("RSN IE check failed %d", status); 216 return QDF_STATUS_E_INVAL; 217 } 218 219 return QDF_STATUS_SUCCESS; 220 } 221 222 #ifdef WLAN_FEATURE_11BE 223 /** 224 * lim_get_update_eht_bw_puncture_allow() - whether bw and puncture can be 225 * sent to target directly 226 * @session: pe session 227 * @ori_bw: bandwdith from beacon 228 * @new_bw: bandwidth intersection between reference AP and STA 229 * @update_allow: return true if bw and puncture can be updated directly 230 * 231 * Return: QDF_STATUS 232 */ 233 static QDF_STATUS 234 lim_get_update_eht_bw_puncture_allow(struct pe_session *session, 235 enum phy_ch_width ori_bw, 236 enum phy_ch_width *new_bw, 237 bool *update_allow) 238 { 239 enum phy_ch_width ch_width; 240 struct wlan_objmgr_psoc *psoc; 241 enum wlan_phymode phy_mode; 242 QDF_STATUS status = QDF_STATUS_SUCCESS; 243 244 *update_allow = false; 245 246 psoc = wlan_vdev_get_psoc(session->vdev); 247 if (!psoc) { 248 pe_err("psoc object invalid"); 249 return QDF_STATUS_E_INVAL; 250 } 251 status = mlme_get_peer_phymode(psoc, session->bssId, &phy_mode); 252 if (QDF_IS_STATUS_ERROR(status)) { 253 pe_err("failed to get phy_mode %d mac: " QDF_MAC_ADDR_FMT, 254 status, QDF_MAC_ADDR_REF(session->bssId)); 255 return QDF_STATUS_E_INVAL; 256 } 257 ch_width = wlan_mlme_get_ch_width_from_phymode(phy_mode); 258 259 if (ori_bw <= ch_width) { 260 *new_bw = ori_bw; 261 *update_allow = true; 262 return QDF_STATUS_SUCCESS; 263 } 264 265 if ((ori_bw == CH_WIDTH_320MHZ) && 266 !session->eht_config.support_320mhz_6ghz) { 267 if (ch_width == CH_WIDTH_160MHZ) { 268 *new_bw = CH_WIDTH_160MHZ; 269 *update_allow = true; 270 return QDF_STATUS_SUCCESS; 271 } 272 } 273 274 return QDF_STATUS_SUCCESS; 275 } 276 277 void lim_process_beacon_eht_op(struct pe_session *session, 278 struct sSirProbeRespBeacon *bcn_ptr) 279 { 280 uint16_t ori_punc = 0; 281 enum phy_ch_width ori_bw = CH_WIDTH_INVALID; 282 uint8_t cb_mode; 283 enum phy_ch_width new_bw; 284 bool update_allow; 285 QDF_STATUS status; 286 struct mac_context *mac_ctx; 287 struct wlan_objmgr_vdev *vdev; 288 struct wlan_channel *des_chan; 289 struct csa_offload_params *csa_param; 290 uint8_t ccfs0; 291 uint8_t ccfs1; 292 tDot11fIEeht_op *eht_op; 293 tDot11fIEhe_op *he_op; 294 uint8_t ch_width; 295 uint8_t chan_id; 296 297 if (!bcn_ptr || !session || !session->mac_ctx || !session->vdev) { 298 pe_err("invalid input parameters"); 299 return; 300 } 301 302 eht_op = &bcn_ptr->eht_op; 303 he_op = &bcn_ptr->he_op; 304 mac_ctx = session->mac_ctx; 305 vdev = session->vdev; 306 307 chan_id = wlan_reg_freq_to_chan(wlan_vdev_get_pdev(vdev), 308 bcn_ptr->chan_freq); 309 310 cb_mode = lim_get_cb_mode_for_freq(mac_ctx, session, 311 session->curr_op_freq); 312 if (cb_mode == WNI_CFG_CHANNEL_BONDING_MODE_DISABLE) { 313 /* 314 * if channel bonding is disabled from INI do not 315 * update the chan width 316 */ 317 pe_debug_rl("chan banding is disabled skip bw update"); 318 319 return; 320 } 321 /* handle beacon IE for 11be non-mlo case */ 322 if (eht_op->disabled_sub_chan_bitmap_present) { 323 ori_punc = QDF_GET_BITS( 324 eht_op->disabled_sub_chan_bitmap[0][0], 0, 8); 325 ori_punc |= QDF_GET_BITS( 326 eht_op->disabled_sub_chan_bitmap[0][1], 0, 8) << 8; 327 } 328 if (eht_op->eht_op_information_present) { 329 ori_bw = wlan_mlme_convert_eht_op_bw_to_phy_ch_width( 330 eht_op->channel_width); 331 ccfs0 = eht_op->ccfs0; 332 ccfs1 = eht_op->ccfs1; 333 } else if (he_op->vht_oper_present) { 334 ch_width = he_op->vht_oper.info.chan_width; 335 ccfs0 = he_op->vht_oper.info.center_freq_seg0; 336 ccfs1 = he_op->vht_oper.info.center_freq_seg1; 337 ori_bw = wlan_mlme_convert_vht_op_bw_to_phy_ch_width(ch_width, 338 chan_id, 339 ccfs0, 340 ccfs1); 341 } else if (he_op->oper_info_6g_present) { 342 ch_width = he_op->oper_info_6g.info.ch_width; 343 ccfs0 = he_op->oper_info_6g.info.center_freq_seg0; 344 ccfs1 = he_op->oper_info_6g.info.center_freq_seg1; 345 ori_bw = wlan_mlme_convert_he_6ghz_op_bw_to_phy_ch_width(ch_width, 346 chan_id, 347 ccfs0, 348 ccfs1); 349 } else if (bcn_ptr->VHTOperation.present) { 350 ch_width = bcn_ptr->VHTOperation.chanWidth; 351 ccfs0 = bcn_ptr->VHTOperation.chan_center_freq_seg0; 352 ccfs1 = bcn_ptr->VHTOperation.chan_center_freq_seg1; 353 ori_bw = wlan_mlme_convert_vht_op_bw_to_phy_ch_width(ch_width, 354 chan_id, 355 ccfs0, 356 ccfs1); 357 } else { 358 pe_err("Invalid operation"); 359 return; 360 } 361 362 status = lim_get_update_eht_bw_puncture_allow(session, ori_bw, 363 &new_bw, 364 &update_allow); 365 if (QDF_IS_STATUS_ERROR(status)) 366 return; 367 368 if (update_allow) { 369 wlan_cm_sta_update_bw_puncture(vdev, session->bssId, 370 ori_punc, ori_bw, 371 ccfs0, 372 ccfs1, 373 new_bw); 374 } else { 375 csa_param = qdf_mem_malloc(sizeof(*csa_param)); 376 if (!csa_param) { 377 pe_err("csa_param allocation fails"); 378 return; 379 } 380 des_chan = wlan_vdev_mlme_get_des_chan(vdev); 381 csa_param->channel = des_chan->ch_ieee; 382 csa_param->csa_chan_freq = des_chan->ch_freq; 383 csa_param->new_ch_width = ori_bw; 384 csa_param->new_punct_bitmap = ori_punc; 385 csa_param->new_ch_freq_seg1 = ccfs0; 386 csa_param->new_ch_freq_seg2 = ccfs1; 387 qdf_copy_macaddr(&csa_param->bssid, 388 (struct qdf_mac_addr *)session->bssId); 389 lim_handle_sta_csa_param(session->mac_ctx, csa_param); 390 } 391 } 392 393 void lim_process_beacon_eht(struct mac_context *mac_ctx, 394 struct pe_session *session, 395 tSchBeaconStruct *bcn_ptr) 396 { 397 struct wlan_objmgr_vdev *vdev; 398 struct wlan_channel *des_chan; 399 400 if (!session || !bcn_ptr || !mac_ctx) { 401 pe_err("invalid input parameters"); 402 return; 403 } 404 vdev = session->vdev; 405 if (!vdev || wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE || 406 !qdf_is_macaddr_equal((struct qdf_mac_addr *)session->bssId, 407 (struct qdf_mac_addr *)bcn_ptr->bssid)) 408 return; 409 des_chan = wlan_vdev_mlme_get_des_chan(vdev); 410 if (!des_chan || !IS_WLAN_PHYMODE_EHT(des_chan->ch_phymode)) 411 return; 412 413 if (wlan_cm_is_vdev_connected(vdev)) 414 lim_process_beacon_eht_op(session, bcn_ptr); 415 416 if (mlo_is_mld_sta(vdev)) 417 /* handle beacon IE for 802.11be mlo case */ 418 lim_process_beacon_mlo(mac_ctx, session, bcn_ptr); 419 } 420 421 void 422 lim_process_ml_reconfig(struct mac_context *mac_ctx, 423 struct pe_session *session, 424 uint8_t *rx_pkt_info) 425 { 426 uint8_t *frame; 427 uint16_t frame_len; 428 429 if (!session->vdev) 430 return; 431 432 frame = WMA_GET_RX_MPDU_DATA(rx_pkt_info); 433 frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); 434 if (frame_len < SIR_MAC_B_PR_SSID_OFFSET) 435 return; 436 437 mlo_process_ml_reconfig_ie(session->vdev, NULL, 438 frame + SIR_MAC_B_PR_SSID_OFFSET, 439 frame_len - SIR_MAC_B_PR_SSID_OFFSET, NULL); 440 } 441 #endif 442 443 /** 444 * lim_process_beacon_frame() - to process beacon frames 445 * @mac_ctx: Pointer to Global MAC structure 446 * @rx_pkt_info: A pointer to RX packet info structure 447 * @session: A pointer to session 448 * 449 * This function is called by limProcessMessageQueue() upon Beacon 450 * frame reception. 451 * Note: 452 * 1. Beacons received in 'normal' state in IBSS are handled by 453 * Beacon Processing module. 454 * 455 * Return: none 456 */ 457 458 void 459 lim_process_beacon_frame(struct mac_context *mac_ctx, uint8_t *rx_pkt_info, 460 struct pe_session *session) 461 { 462 tpSirMacMgmtHdr mac_hdr; 463 tSchBeaconStruct *bcn_ptr; 464 uint8_t *frame; 465 const uint8_t *owe_transition_ie; 466 uint16_t frame_len; 467 uint8_t bpcc; 468 bool cu_flag = true; 469 QDF_STATUS status; 470 471 /* 472 * here is it required to increment session specific heartBeat 473 * beacon counter 474 */ 475 mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); 476 frame = WMA_GET_RX_MPDU_DATA(rx_pkt_info); 477 frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); 478 479 if (frame_len < SIR_MAC_B_PR_SSID_OFFSET) { 480 pe_debug_rl("payload invalid len %d", frame_len); 481 return; 482 } 483 if (lim_validate_rsn_ie(frame + SIR_MAC_B_PR_SSID_OFFSET, 484 frame_len - SIR_MAC_B_PR_SSID_OFFSET) != 485 QDF_STATUS_SUCCESS) 486 return; 487 /* Expect Beacon in any state as Scan is independent of LIM state */ 488 bcn_ptr = qdf_mem_malloc(sizeof(*bcn_ptr)); 489 if (!bcn_ptr) 490 return; 491 492 /* Parse received Beacon */ 493 if (sir_convert_beacon_frame2_struct(mac_ctx, 494 rx_pkt_info, bcn_ptr) != 495 QDF_STATUS_SUCCESS) { 496 /* 497 * Received wrongly formatted/invalid Beacon. 498 * Ignore it and move on. 499 */ 500 pe_warn("Received invalid Beacon in state: %X", 501 session->limMlmState); 502 lim_print_mlm_state(mac_ctx, LOGW, 503 session->limMlmState); 504 qdf_mem_free(bcn_ptr); 505 return; 506 } 507 508 if (mlo_is_mld_sta(session->vdev)) { 509 cu_flag = false; 510 status = lim_get_bpcc_from_mlo_ie(bcn_ptr, &bpcc); 511 if (QDF_IS_STATUS_SUCCESS(status)) 512 cu_flag = lim_check_cu_happens(session->vdev, bpcc); 513 lim_process_ml_reconfig(mac_ctx, session, rx_pkt_info); 514 } 515 516 lim_process_bcn_prb_rsp_t2lm(mac_ctx, session, bcn_ptr); 517 if (QDF_IS_STATUS_SUCCESS(lim_check_for_ml_probe_req(session))) 518 goto end; 519 520 /* 521 * during scanning, when any session is active, and 522 * beacon/Pr belongs to one of the session, fill up the 523 * following, TBD - HB counter 524 */ 525 if (sir_compare_mac_addr(session->bssId, 526 bcn_ptr->bssid)) { 527 qdf_mem_copy((uint8_t *)&session->lastBeaconTimeStamp, 528 (uint8_t *) bcn_ptr->timeStamp, 529 sizeof(uint64_t)); 530 session->currentBssBeaconCnt++; 531 } 532 MTRACE(mac_trace(mac_ctx, 533 TRACE_CODE_RX_MGMT_TSF, 0, bcn_ptr->timeStamp[0])); 534 MTRACE(mac_trace(mac_ctx, TRACE_CODE_RX_MGMT_TSF, 0, 535 bcn_ptr->timeStamp[1])); 536 537 if (session->limMlmState == 538 eLIM_MLM_WT_JOIN_BEACON_STATE) { 539 owe_transition_ie = wlan_get_vendor_ie_ptr_from_oui( 540 OWE_TRANSITION_OUI_TYPE, 541 OWE_TRANSITION_OUI_SIZE, 542 frame + SIR_MAC_B_PR_SSID_OFFSET, 543 frame_len - SIR_MAC_B_PR_SSID_OFFSET); 544 if (session->connected_akm == ANI_AKM_TYPE_OWE && 545 owe_transition_ie) { 546 pe_debug("vdev:%d Drop OWE rx beacon. Wait for probe for join success", 547 session->vdev_id); 548 qdf_mem_free(bcn_ptr); 549 return; 550 } 551 552 if (session->beacon) { 553 qdf_mem_free(session->beacon); 554 session->beacon = NULL; 555 session->bcnLen = 0; 556 } 557 558 mac_ctx->lim.bss_rssi = 559 (int8_t)WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info); 560 session->bcnLen = WMA_GET_RX_MPDU_LEN(rx_pkt_info); 561 session->beacon = qdf_mem_malloc(session->bcnLen); 562 if (session->beacon) 563 /* 564 * Store the whole Beacon frame. This is sent to 565 * csr/hdd in join cnf response. 566 */ 567 qdf_mem_copy(session->beacon, 568 WMA_GET_RX_MAC_HEADER(rx_pkt_info), 569 session->bcnLen); 570 571 lim_check_and_announce_join_success(mac_ctx, bcn_ptr, 572 mac_hdr, session); 573 } 574 575 if (cu_flag) 576 lim_process_beacon_eht(mac_ctx, session, bcn_ptr); 577 end: 578 qdf_mem_free(bcn_ptr); 579 return; 580 } 581