xref: /wlan-driver/qcacld-3.0/core/mac/src/pe/lim/lim_process_beacon_frame.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1 /*
2  * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /*
21  *
22  * 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 /*Invalid Recommended Max Simultaneous Links value */
55 #define RESERVED_REC_LINK_VALUE 1
56 
57 #ifdef WLAN_FEATURE_11BE_MLO
58 
lim_process_bcn_prb_rsp_t2lm(struct mac_context * mac_ctx,struct pe_session * session,tpSirProbeRespBeacon bcn_ptr)59 void lim_process_bcn_prb_rsp_t2lm(struct mac_context *mac_ctx,
60 				  struct pe_session *session,
61 				  tpSirProbeRespBeacon bcn_ptr)
62 {
63 	struct wlan_objmgr_vdev *vdev;
64 	struct wlan_t2lm_context *t2lm_ctx;
65 
66 	if (!session || !bcn_ptr || !mac_ctx) {
67 		pe_err("invalid input parameters");
68 		return;
69 	}
70 
71 	if (!wlan_mlme_get_t2lm_negotiation_supported(mac_ctx->psoc)) {
72 		pe_err_rl("T2LM negotiation not supported");
73 		return;
74 	}
75 
76 	vdev = session->vdev;
77 	if (!vdev || !wlan_vdev_mlme_is_mlo_vdev(vdev))
78 		return;
79 
80 	if (!wlan_cm_is_vdev_connected(vdev))
81 		return;
82 
83 	if (!mlo_check_if_all_links_up(vdev))
84 		return;
85 
86 	t2lm_ctx = &vdev->mlo_dev_ctx->t2lm_ctx;
87 
88 	qdf_mem_copy((uint8_t *)&t2lm_ctx->tsf, (uint8_t *)bcn_ptr->timeStamp,
89 		     sizeof(uint64_t));
90 	wlan_update_t2lm_mapping(vdev, &bcn_ptr->t2lm_ctx, t2lm_ctx->tsf);
91 }
92 
valid_max_rec_links(uint8_t value)93 static uint8_t valid_max_rec_links(uint8_t value)
94 {
95 	if (value > RESERVED_REC_LINK_VALUE &&
96 	    value <= WLAN_DEFAULT_REC_LINK_VALUE)
97 		return value;
98 	return WLAN_DEFAULT_REC_LINK_VALUE;
99 }
100 
lim_process_beacon_mlo(struct mac_context * mac_ctx,struct pe_session * session,tSchBeaconStruct * bcn_ptr)101 void lim_process_beacon_mlo(struct mac_context *mac_ctx,
102 			    struct pe_session *session,
103 			    tSchBeaconStruct *bcn_ptr)
104 {
105 	struct csa_offload_params csa_param;
106 	int i;
107 	uint8_t link_id;
108 	uint8_t *per_sta_pro;
109 	uint32_t per_sta_pro_len;
110 	uint8_t *sta_pro;
111 	uint32_t sta_pro_len;
112 	uint16_t stacontrol;
113 	struct ieee80211_channelswitch_ie *csa_ie;
114 	struct ieee80211_extendedchannelswitch_ie *xcsa_ie;
115 	struct wlan_objmgr_vdev *vdev;
116 	struct wlan_objmgr_pdev *pdev;
117 	struct wlan_mlo_dev_context *mlo_ctx;
118 	uint8_t is_sta_csa_synced;
119 	struct mlo_link_info *link_info;
120 	uint8_t sta_info_len = 0;
121 	uint8_t tmp_rec_value;
122 
123 	if (!session || !bcn_ptr || !mac_ctx) {
124 		pe_err("invalid input parameters");
125 		return;
126 	}
127 	vdev = session->vdev;
128 	if (!vdev || !wlan_vdev_mlme_is_mlo_vdev(vdev))
129 		return;
130 
131 	pdev = wlan_vdev_get_pdev(vdev);
132 	if (!pdev) {
133 		pe_err("null pdev");
134 		return;
135 	}
136 	mlo_ctx = vdev->mlo_dev_ctx;
137 	if (!mlo_ctx) {
138 		pe_err("null mlo_dev_ctx");
139 		return;
140 	}
141 
142 	if (bcn_ptr->mlo_ie.mlo_ie.medium_sync_delay_info_present) {
143 		wlan_vdev_mlme_cap_clear(vdev, WLAN_VDEV_C_EMLSR_CAP);
144 		pe_debug("EMLSR not supported with D2.0 AP");
145 	}
146 
147 	/** max num of active links recommended by AP */
148 	tmp_rec_value =
149 	bcn_ptr->mlo_ie.mlo_ie.ext_mld_capab_and_op_info.rec_max_simultaneous_links;
150 	mlo_ctx->mlo_max_recom_simult_links =
151 		valid_max_rec_links(tmp_rec_value);
152 
153 	for (i = 0; i < bcn_ptr->mlo_ie.mlo_ie.num_sta_profile; i++) {
154 		csa_ie = NULL;
155 		xcsa_ie = NULL;
156 		qdf_mem_zero(&csa_param, sizeof(csa_param));
157 		per_sta_pro = bcn_ptr->mlo_ie.mlo_ie.sta_profile[i].data;
158 		/* Append one byte to get the element length  */
159 		per_sta_pro_len = bcn_ptr->mlo_ie.mlo_ie.sta_profile[i].num_data;
160 		stacontrol = *(uint16_t *)(per_sta_pro + sizeof(struct subelem_header));
161 		sta_info_len = *(uint8_t *)(per_sta_pro +
162 				sizeof(struct subelem_header) + WLAN_ML_BV_LINFO_PERSTAPROF_STACTRL_SIZE);
163 		/* IE ID + LEN + STA control STA info len*/
164 		sta_pro = per_sta_pro + sizeof(struct subelem_header) +
165 			WLAN_ML_BV_LINFO_PERSTAPROF_STACTRL_SIZE + sta_info_len;
166 		sta_pro_len = per_sta_pro_len - sizeof(struct subelem_header) -
167 				WLAN_ML_BV_LINFO_PERSTAPROF_STACTRL_SIZE - sta_info_len;
168 		link_id = QDF_GET_BITS(
169 			    stacontrol,
170 			    WLAN_ML_BV_LINFO_PERSTAPROF_STACTRL_LINKID_IDX,
171 			    WLAN_ML_BV_LINFO_PERSTAPROF_STACTRL_LINKID_BITS);
172 
173 		csa_ie = (struct ieee80211_channelswitch_ie *)
174 				wlan_get_ie_ptr_from_eid(
175 					DOT11F_EID_CHANSWITCHANN,
176 					sta_pro, sta_pro_len);
177 		xcsa_ie = (struct ieee80211_extendedchannelswitch_ie *)
178 				wlan_get_ie_ptr_from_eid(
179 					DOT11F_EID_EXT_CHAN_SWITCH_ANN,
180 					sta_pro, sta_pro_len);
181 		is_sta_csa_synced = mlo_is_sta_csa_synced(mlo_ctx, link_id);
182 		link_info = mlo_mgr_get_ap_link_by_link_id(mlo_ctx, link_id);
183 		if (!link_info) {
184 			mlo_err("link info null");
185 			return;
186 		}
187 
188 		if (csa_ie) {
189 			csa_param.channel = csa_ie->newchannel;
190 			csa_param.csa_chan_freq = wlan_reg_legacy_chan_to_freq(
191 						pdev, csa_ie->newchannel);
192 			csa_param.switch_mode = csa_ie->switchmode;
193 			csa_param.ies_present_flag |= MLME_CSA_IE_PRESENT;
194 			mlo_sta_handle_csa_standby_link(mlo_ctx, link_id,
195 							&csa_param, vdev);
196 
197 			if (!is_sta_csa_synced)
198 				mlo_sta_csa_save_params(mlo_ctx, link_id,
199 							&csa_param);
200 		} else if (xcsa_ie) {
201 			csa_param.channel = xcsa_ie->newchannel;
202 			csa_param.switch_mode = xcsa_ie->switchmode;
203 			csa_param.new_op_class = xcsa_ie->newClass;
204 			if (wlan_reg_is_6ghz_op_class(pdev, xcsa_ie->newClass))
205 				csa_param.csa_chan_freq =
206 					wlan_reg_chan_band_to_freq(
207 						pdev, xcsa_ie->newchannel,
208 						BIT(REG_BAND_6G));
209 			else
210 				csa_param.csa_chan_freq =
211 					wlan_reg_legacy_chan_to_freq(
212 						pdev, xcsa_ie->newchannel);
213 			csa_param.ies_present_flag |= MLME_XCSA_IE_PRESENT;
214 			mlo_sta_handle_csa_standby_link(mlo_ctx, link_id,
215 							&csa_param, vdev);
216 			if (!is_sta_csa_synced)
217 				mlo_sta_csa_save_params(mlo_ctx, link_id,
218 							&csa_param);
219 		}
220 	}
221 }
222 #endif
223 
224 static QDF_STATUS
lim_validate_rsn_ie(const uint8_t * ie_ptr,uint16_t ie_len)225 lim_validate_rsn_ie(const uint8_t *ie_ptr, uint16_t ie_len)
226 {
227 	QDF_STATUS status;
228 	const uint8_t *rsn_ie;
229 	struct wlan_crypto_params crypto_params;
230 
231 	rsn_ie = wlan_get_ie_ptr_from_eid(WLAN_ELEMID_RSN, ie_ptr, ie_len);
232 	if (!rsn_ie)
233 		return QDF_STATUS_SUCCESS;
234 
235 	qdf_mem_zero(&crypto_params, sizeof(struct wlan_crypto_params));
236 	status = wlan_crypto_rsnie_check(&crypto_params, rsn_ie);
237 	if (status != QDF_STATUS_SUCCESS) {
238 		pe_debug_rl("RSN IE check failed %d", status);
239 		return QDF_STATUS_E_INVAL;
240 	}
241 
242 	return QDF_STATUS_SUCCESS;
243 }
244 
245 #ifdef WLAN_FEATURE_11BE
246 /**
247  * lim_get_update_eht_bw_puncture_allow() - whether bw and puncture can be
248  *                                          sent to target directly
249  * @session: pe session
250  * @ori_bw: bandwdith from beacon
251  * @new_bw: bandwidth intersection between reference AP and STA
252  * @update_allow: return true if bw and puncture can be updated directly
253  *
254  * Return: QDF_STATUS
255  */
256 static QDF_STATUS
lim_get_update_eht_bw_puncture_allow(struct pe_session * session,enum phy_ch_width ori_bw,enum phy_ch_width * new_bw,bool * update_allow)257 lim_get_update_eht_bw_puncture_allow(struct pe_session *session,
258 				     enum phy_ch_width ori_bw,
259 				     enum phy_ch_width *new_bw,
260 				     bool *update_allow)
261 {
262 	enum phy_ch_width ch_width;
263 	struct wlan_objmgr_psoc *psoc;
264 	enum wlan_phymode phy_mode;
265 	QDF_STATUS status = QDF_STATUS_SUCCESS;
266 
267 	*update_allow = false;
268 
269 	psoc = wlan_vdev_get_psoc(session->vdev);
270 	if (!psoc) {
271 		pe_err("psoc object invalid");
272 		return QDF_STATUS_E_INVAL;
273 	}
274 	status = mlme_get_peer_phymode(psoc, session->bssId, &phy_mode);
275 	if (QDF_IS_STATUS_ERROR(status)) {
276 		pe_err("failed to get phy_mode %d mac: " QDF_MAC_ADDR_FMT,
277 		       status, QDF_MAC_ADDR_REF(session->bssId));
278 		return QDF_STATUS_E_INVAL;
279 	}
280 	ch_width = wlan_mlme_get_ch_width_from_phymode(phy_mode);
281 
282 	if (ori_bw <= ch_width) {
283 		*new_bw = ori_bw;
284 		*update_allow = true;
285 		return QDF_STATUS_SUCCESS;
286 	}
287 
288 	if ((ori_bw == CH_WIDTH_320MHZ) &&
289 	    !session->eht_config.support_320mhz_6ghz) {
290 		if (ch_width == CH_WIDTH_160MHZ) {
291 			*new_bw = CH_WIDTH_160MHZ;
292 			*update_allow = true;
293 			return QDF_STATUS_SUCCESS;
294 		}
295 	}
296 
297 	return QDF_STATUS_SUCCESS;
298 }
299 
lim_process_beacon_eht_op(struct pe_session * session,struct sSirProbeRespBeacon * bcn_ptr)300 void lim_process_beacon_eht_op(struct pe_session *session,
301 			       struct sSirProbeRespBeacon *bcn_ptr)
302 {
303 	uint16_t ori_punc = 0;
304 	enum phy_ch_width ori_bw = CH_WIDTH_INVALID;
305 	enum phy_ch_width ori_bw_no_punct = CH_WIDTH_INVALID;
306 	uint8_t cb_mode;
307 	enum phy_ch_width new_bw;
308 	bool update_allow;
309 	QDF_STATUS status;
310 	struct mac_context *mac_ctx;
311 	struct wlan_objmgr_vdev *vdev;
312 	struct wlan_channel *des_chan;
313 	struct csa_offload_params *csa_param;
314 	uint8_t             ccfs0;
315 	uint8_t             ccfs1;
316 	tDot11fIEeht_op *eht_op;
317 	tDot11fIEhe_op *he_op;
318 	uint8_t  ch_width;
319 	uint8_t chan_id;
320 	struct wlan_channel bss_chan = {0};
321 	struct wlan_channel *current_chan = NULL;
322 	uint8_t band_mask;
323 	uint32_t ch_cfreq2 = 0;
324 
325 	if (!bcn_ptr || !session || !session->mac_ctx || !session->vdev) {
326 		pe_err("invalid input parameters");
327 		return;
328 	}
329 
330 	eht_op = &bcn_ptr->eht_op;
331 	he_op = &bcn_ptr->he_op;
332 	mac_ctx = session->mac_ctx;
333 	vdev = session->vdev;
334 
335 	chan_id = wlan_reg_freq_to_chan(wlan_vdev_get_pdev(vdev),
336 					bcn_ptr->chan_freq);
337 
338 	cb_mode = lim_get_cb_mode_for_freq(mac_ctx, session,
339 					   session->curr_op_freq);
340 	if (cb_mode == WNI_CFG_CHANNEL_BONDING_MODE_DISABLE) {
341 		/*
342 		 * if channel bonding is disabled from INI do not
343 		 * update the chan width
344 		 */
345 		pe_debug_rl("chan banding is disabled skip bw update");
346 
347 		return;
348 	}
349 	/* handle beacon IE for 11be non-mlo case */
350 	if (eht_op->eht_op_information_present) {
351 		ori_bw = wlan_mlme_convert_eht_op_bw_to_phy_ch_width(
352 						eht_op->channel_width);
353 		ccfs0 = eht_op->ccfs0;
354 		ccfs1 = eht_op->ccfs1;
355 		if (eht_op->disabled_sub_chan_bitmap_present) {
356 			ori_punc = QDF_GET_BITS(eht_op->disabled_sub_chan_bitmap[0][0], 0, 8);
357 			ori_punc |= QDF_GET_BITS(eht_op->disabled_sub_chan_bitmap[0][1], 0, 8) << 8;
358 
359 			if (!wlan_mlme_get_eht_disable_punct_in_us_lpi(mac_ctx->psoc))
360 				goto update_bw;
361 
362 			bss_chan.ch_freq = bcn_ptr->chan_freq;
363 			bss_chan.puncture_bitmap = ori_punc;
364 			bss_chan.ch_width = ori_bw;
365 			bss_chan.ch_phymode = WLAN_PHYMODE_11BEA_EHT160;
366 
367 			if (ori_bw == CH_WIDTH_320MHZ &&
368 			    WLAN_REG_IS_6GHZ_CHAN_FREQ(bcn_ptr->chan_freq)) {
369 				band_mask = BIT(REG_BAND_6G);
370 				ch_cfreq2 = wlan_reg_chan_band_to_freq(mac_ctx->pdev,
371 								       ccfs1,
372 								       band_mask);
373 				bss_chan.ch_cfreq2 = ch_cfreq2;
374 			}
375 
376 			status = wlan_mlme_get_bw_no_punct(mac_ctx->psoc,
377 							   vdev,
378 							   &bss_chan,
379 							   &ori_bw_no_punct);
380 			current_chan = wlan_vdev_mlme_get_bss_chan(vdev);
381 			if (QDF_IS_STATUS_SUCCESS(status)) {
382 				if (ori_bw_no_punct != current_chan->ch_width) {
383 					status = wlan_mlme_send_ch_width_update_with_notify(mac_ctx->psoc,
384 											    vdev,
385 											    session->vdev_id,
386 											    ori_bw_no_punct);
387 				}
388 				return;
389 			}
390 		}
391 	} else if (he_op->oper_info_6g_present) {
392 		ch_width = he_op->oper_info_6g.info.ch_width;
393 		ccfs0 = he_op->oper_info_6g.info.center_freq_seg0;
394 		ccfs1 = he_op->oper_info_6g.info.center_freq_seg1;
395 		ori_bw = wlan_mlme_convert_he_6ghz_op_bw_to_phy_ch_width(ch_width,
396 									 chan_id,
397 									 ccfs0,
398 									 ccfs1);
399 	} else {
400 		return;
401 	}
402 
403 update_bw:
404 	status = lim_get_update_eht_bw_puncture_allow(session, ori_bw,
405 						      &new_bw,
406 						      &update_allow);
407 	if (QDF_IS_STATUS_ERROR(status))
408 		return;
409 
410 	if (update_allow) {
411 		wlan_cm_sta_update_bw_puncture(vdev, session->bssId,
412 					       ori_punc, ori_bw,
413 					       ccfs0,
414 					       ccfs1,
415 					       new_bw);
416 	} else {
417 		csa_param = qdf_mem_malloc(sizeof(*csa_param));
418 		if (!csa_param) {
419 			pe_err("csa_param allocation fails");
420 			return;
421 		}
422 		des_chan = wlan_vdev_mlme_get_des_chan(vdev);
423 		csa_param->channel = des_chan->ch_ieee;
424 		csa_param->csa_chan_freq = des_chan->ch_freq;
425 		csa_param->new_ch_width = ori_bw;
426 		csa_param->new_punct_bitmap = ori_punc;
427 		csa_param->new_ch_freq_seg1 = ccfs0;
428 		csa_param->new_ch_freq_seg2 = ccfs1;
429 		qdf_copy_macaddr(&csa_param->bssid,
430 				 (struct qdf_mac_addr *)session->bssId);
431 		lim_handle_sta_csa_param(session->mac_ctx, csa_param, false);
432 	}
433 }
434 
lim_process_beacon_eht(struct mac_context * mac_ctx,struct pe_session * session,tSchBeaconStruct * bcn_ptr)435 void lim_process_beacon_eht(struct mac_context *mac_ctx,
436 			    struct pe_session *session,
437 			    tSchBeaconStruct *bcn_ptr)
438 {
439 	struct wlan_objmgr_vdev *vdev;
440 	struct wlan_channel *des_chan;
441 
442 	if (!session || !bcn_ptr || !mac_ctx) {
443 		pe_err("invalid input parameters");
444 		return;
445 	}
446 	vdev = session->vdev;
447 	if (!vdev || wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE ||
448 	    !qdf_is_macaddr_equal((struct qdf_mac_addr *)session->bssId,
449 				  (struct qdf_mac_addr *)bcn_ptr->bssid))
450 		return;
451 	des_chan = wlan_vdev_mlme_get_des_chan(vdev);
452 	if (!des_chan || !IS_WLAN_PHYMODE_EHT(des_chan->ch_phymode))
453 		return;
454 
455 	if (wlan_cm_is_vdev_connected(vdev))
456 		lim_process_beacon_eht_op(session, bcn_ptr);
457 
458 	if (mlo_is_mld_sta(vdev))
459 		/* handle beacon IE for 802.11be mlo case */
460 		lim_process_beacon_mlo(mac_ctx, session, bcn_ptr);
461 }
462 
463 void
lim_process_ml_reconfig(struct mac_context * mac_ctx,struct pe_session * session,uint8_t * rx_pkt_info)464 lim_process_ml_reconfig(struct mac_context *mac_ctx,
465 			struct pe_session *session,
466 			uint8_t *rx_pkt_info)
467 {
468 	uint8_t *frame;
469 	uint16_t frame_len;
470 
471 	if (!session->vdev)
472 		return;
473 
474 	frame = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
475 	frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
476 	if (frame_len < SIR_MAC_B_PR_SSID_OFFSET)
477 		return;
478 
479 	mlo_process_ml_reconfig_ie(session->vdev, NULL,
480 				   frame + SIR_MAC_B_PR_SSID_OFFSET,
481 				   frame_len - SIR_MAC_B_PR_SSID_OFFSET, NULL);
482 }
483 #endif
484 
485 /**
486  * lim_process_beacon_frame() - to process beacon frames
487  * @mac_ctx: Pointer to Global MAC structure
488  * @rx_pkt_info: A pointer to RX packet info structure
489  * @session: A pointer to session
490  *
491  * This function is called by limProcessMessageQueue() upon Beacon
492  * frame reception.
493  * Note:
494  * 1. Beacons received in 'normal' state in IBSS are handled by
495  *    Beacon Processing module.
496  *
497  * Return: none
498  */
499 
500 void
lim_process_beacon_frame(struct mac_context * mac_ctx,uint8_t * rx_pkt_info,struct pe_session * session)501 lim_process_beacon_frame(struct mac_context *mac_ctx, uint8_t *rx_pkt_info,
502 			 struct pe_session *session)
503 {
504 	tpSirMacMgmtHdr mac_hdr;
505 	tSchBeaconStruct *bcn_ptr;
506 	uint8_t *frame;
507 	const uint8_t *owe_transition_ie;
508 	uint16_t frame_len;
509 	uint8_t bpcc;
510 	bool cu_flag = true;
511 	QDF_STATUS status;
512 
513 	/*
514 	 * here is it required to increment session specific heartBeat
515 	 * beacon counter
516 	 */
517 	mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
518 	frame = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
519 	frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
520 
521 	if (frame_len < SIR_MAC_B_PR_SSID_OFFSET) {
522 		pe_debug_rl("payload invalid len %d", frame_len);
523 		return;
524 	}
525 	if (lim_validate_rsn_ie(frame + SIR_MAC_B_PR_SSID_OFFSET,
526 				frame_len - SIR_MAC_B_PR_SSID_OFFSET) !=
527 			QDF_STATUS_SUCCESS)
528 		return;
529 	/* Expect Beacon in any state as Scan is independent of LIM state */
530 	bcn_ptr = qdf_mem_malloc(sizeof(*bcn_ptr));
531 	if (!bcn_ptr)
532 		return;
533 
534 	/* Parse received Beacon */
535 	if (sir_convert_beacon_frame2_struct(mac_ctx,
536 			rx_pkt_info, bcn_ptr) !=
537 			QDF_STATUS_SUCCESS) {
538 		/*
539 		 * Received wrongly formatted/invalid Beacon.
540 		 * Ignore it and move on.
541 		 */
542 		pe_warn("Received invalid Beacon in state: %X",
543 			session->limMlmState);
544 		lim_print_mlm_state(mac_ctx, LOGW,
545 			session->limMlmState);
546 		qdf_mem_free(bcn_ptr);
547 		return;
548 	}
549 
550 	if (mlo_is_mld_sta(session->vdev)) {
551 		cu_flag = false;
552 		status = lim_get_bpcc_from_mlo_ie(bcn_ptr, &bpcc);
553 		if (QDF_IS_STATUS_SUCCESS(status))
554 			cu_flag = lim_check_cu_happens(session->vdev, bpcc);
555 		lim_process_ml_reconfig(mac_ctx, session, rx_pkt_info);
556 	}
557 
558 	lim_process_bcn_prb_rsp_t2lm(mac_ctx, session, bcn_ptr);
559 	if (QDF_IS_STATUS_SUCCESS(lim_check_for_ml_probe_req(session)))
560 		goto end;
561 
562 	/*
563 	 * during scanning, when any session is active, and
564 	 * beacon/Pr belongs to one of the session, fill up the
565 	 * following, TBD - HB counter
566 	 */
567 	if (sir_compare_mac_addr(session->bssId,
568 				bcn_ptr->bssid)) {
569 		qdf_mem_copy((uint8_t *)&session->lastBeaconTimeStamp,
570 			(uint8_t *) bcn_ptr->timeStamp,
571 			sizeof(uint64_t));
572 		session->currentBssBeaconCnt++;
573 	}
574 	MTRACE(mac_trace(mac_ctx,
575 		TRACE_CODE_RX_MGMT_TSF, 0, bcn_ptr->timeStamp[0]));
576 	MTRACE(mac_trace(mac_ctx, TRACE_CODE_RX_MGMT_TSF, 0,
577 		bcn_ptr->timeStamp[1]));
578 
579 	if (session->limMlmState ==
580 			eLIM_MLM_WT_JOIN_BEACON_STATE) {
581 		owe_transition_ie = wlan_get_vendor_ie_ptr_from_oui(
582 					OWE_TRANSITION_OUI_TYPE,
583 					OWE_TRANSITION_OUI_SIZE,
584 					frame + SIR_MAC_B_PR_SSID_OFFSET,
585 					frame_len - SIR_MAC_B_PR_SSID_OFFSET);
586 		if (session->connected_akm == ANI_AKM_TYPE_OWE &&
587 		    owe_transition_ie) {
588 			pe_debug("vdev:%d Drop OWE rx beacon. Wait for probe for join success",
589 				 session->vdev_id);
590 			qdf_mem_free(bcn_ptr);
591 			return;
592 		}
593 
594 		if (session->beacon) {
595 			qdf_mem_free(session->beacon);
596 			session->beacon = NULL;
597 			session->bcnLen = 0;
598 		}
599 
600 		mac_ctx->lim.bss_rssi =
601 			(int8_t)WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info);
602 		session->bcnLen = WMA_GET_RX_MPDU_LEN(rx_pkt_info);
603 		session->beacon = qdf_mem_malloc(session->bcnLen);
604 		if (session->beacon)
605 			/*
606 			 * Store the whole Beacon frame. This is sent to
607 			 * csr/hdd in join cnf response.
608 			 */
609 			qdf_mem_copy(session->beacon,
610 				WMA_GET_RX_MAC_HEADER(rx_pkt_info),
611 				session->bcnLen);
612 		mgmt_txrx_frame_hex_dump((uint8_t *)mac_hdr,
613 					 WMA_GET_RX_MPDU_LEN(rx_pkt_info),
614 					 false);
615 		lim_check_and_announce_join_success(mac_ctx, bcn_ptr,
616 				mac_hdr, session);
617 	}
618 
619 	if (cu_flag)
620 		lim_process_beacon_eht(mac_ctx, session, bcn_ptr);
621 end:
622 	qdf_mem_free(bcn_ptr);
623 	return;
624 }
625