xref: /wlan-dirver/qcacld-3.0/core/mac/src/pe/sch/sch_beacon_gen.c (revision d1eb296939c4184ce7e8a921bf6ffe874f574400)
1 /*
2  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2022 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 sch_beacon_gen.cc contains beacon generation related
22  * functions
23  *
24  * Author:      Sandesh Goel
25  * Date:        02/25/02
26  * History:-
27  * Date            Modified by    Modification Information
28  * --------------------------------------------------------------------
29  *
30  */
31 
32 #include "cds_api.h"
33 #include "wni_cfg.h"
34 #include "ani_global.h"
35 #include "sir_mac_prot_def.h"
36 
37 #include "lim_utils.h"
38 #include "lim_api.h"
39 
40 #include "wma_if.h"
41 #include "sch_api.h"
42 
43 #include "parser_api.h"
44 #include "wlan_utility.h"
45 #include "lim_mlo.h"
46 
47 /* Offset of Channel Switch count field in CSA/ECSA IE */
48 #define SCH_CSA_SWITCH_COUNT_OFFSET 2
49 #define SCH_ECSA_SWITCH_COUNT_OFFSET 3
50 
51 const uint8_t p2p_oui[] = { 0x50, 0x6F, 0x9A, 0x9 };
52 
53 /**
54  * sch_get_csa_ecsa_count_offset() - get the offset of Switch count field
55  * @ie: pointer to the beginning of IEs in the beacon frame buffer
56  * @ie_len: length of the IEs in the buffer
57  * @csa_count_offset: pointer to the csa_count_offset variable in the caller
58  * @ecsa_count_offset: pointer to the ecsa_count_offset variable in the caller
59  *
60  * Gets the offset of the switch count field in the CSA/ECSA IEs from the start
61  * of the IEs buffer.
62  *
63  * Return: None
64  */
65 static void sch_get_csa_ecsa_count_offset(const uint8_t *ie, uint32_t ie_len,
66 					  uint32_t *csa_count_offset,
67 					  uint32_t *ecsa_count_offset)
68 {
69 	const uint8_t *ptr = ie;
70 	uint8_t elem_id;
71 	uint16_t elem_len;
72 	uint32_t offset = 0;
73 
74 	/* IE is not present */
75 	if (!ie_len)
76 		return;
77 
78 	while (ie_len >= 2) {
79 		elem_id = ptr[0];
80 		elem_len = ptr[1];
81 		ie_len -= 2;
82 		offset += 2;
83 
84 		if (elem_id == DOT11F_EID_CHANSWITCHANN &&
85 		    elem_len == 3)
86 			*csa_count_offset = offset +
87 					SCH_CSA_SWITCH_COUNT_OFFSET;
88 
89 		if (elem_id == DOT11F_EID_EXT_CHAN_SWITCH_ANN &&
90 		    elem_len == 4)
91 			*ecsa_count_offset = offset +
92 					SCH_ECSA_SWITCH_COUNT_OFFSET;
93 
94 		if (ie_len < elem_len)
95 			return;
96 
97 		ie_len -= elem_len;
98 		offset += elem_len;
99 		ptr += (elem_len + 2);
100 	}
101 }
102 
103 #ifdef WLAN_FEATURE_11BE_MLO
104 /**
105  * lim_update_link_info() - update mlo_link_info
106  * @mac_ctx: mac context
107  * @session: pe session
108  * @bcn_1: pointer to tDot11fBeacon1
109  * @bcn_2: pointer to tDot11fBeacon2
110  *
111  * Return: void
112  */
113 static void lim_update_link_info(struct mac_context *mac_ctx,
114 				 struct pe_session *session,
115 				 tDot11fBeacon1 *bcn_1,
116 				 tDot11fBeacon2 *bcn_2)
117 {
118 	struct mlo_link_ie *link_ie = &session->mlo_link_info.link_ie;
119 	uint16_t offset;
120 	uint8_t *ptr;
121 	uint32_t n_bytes;
122 
123 	session->mlo_link_info.upt_bcn_mlo_ie = false;
124 	session->mlo_link_info.bss_param_change = false;
125 
126 	if (qdf_mem_cmp(&link_ie->link_ds, &bcn_1->DSParams,
127 			sizeof(bcn_1->DSParams))) {
128 		qdf_mem_copy(&link_ie->link_ds, &bcn_1->DSParams,
129 			     sizeof(bcn_1->DSParams));
130 		session->mlo_link_info.bss_param_change = true;
131 		pe_debug("vdev id %d DSParams changed, critical update",
132 			 wlan_vdev_get_id(session->vdev));
133 	}
134 
135 	qdf_mem_copy(&link_ie->link_wmm_params, &bcn_2->WMMParams,
136 		     sizeof(bcn_2->WMMParams));
137 
138 	qdf_mem_copy(&link_ie->link_wmm_caps, &bcn_2->WMMCaps,
139 		     sizeof(bcn_2->WMMCaps));
140 
141 	if (qdf_mem_cmp(&link_ie->link_edca, &bcn_2->EDCAParamSet,
142 			sizeof(bcn_2->EDCAParamSet))) {
143 		qdf_mem_copy(&link_ie->link_edca, &bcn_2->EDCAParamSet,
144 			     sizeof(bcn_2->EDCAParamSet));
145 		session->mlo_link_info.bss_param_change = true;
146 		pe_debug("vdev id %d EDCAParamSet changed, critical update",
147 			 wlan_vdev_get_id(session->vdev));
148 	}
149 
150 	if (qdf_mem_cmp(&link_ie->link_csa, &bcn_2->ChanSwitchAnn,
151 			sizeof(bcn_2->ChanSwitchAnn))) {
152 		session->mlo_link_info.upt_bcn_mlo_ie = true;
153 		qdf_mem_copy(&link_ie->link_csa, &bcn_2->ChanSwitchAnn,
154 			     sizeof(bcn_2->ChanSwitchAnn));
155 		session->mlo_link_info.bss_param_change = true;
156 		pe_debug("vdev id %d csa added, critical update",
157 			 wlan_vdev_get_id(session->vdev));
158 	}
159 
160 	if (qdf_mem_cmp(&link_ie->link_ecsa, &bcn_2->ext_chan_switch_ann,
161 			sizeof(bcn_2->ext_chan_switch_ann))) {
162 		session->mlo_link_info.upt_bcn_mlo_ie = true;
163 		qdf_mem_copy(&link_ie->link_ecsa, &bcn_2->ext_chan_switch_ann,
164 			     sizeof(bcn_2->ext_chan_switch_ann));
165 		session->mlo_link_info.bss_param_change = true;
166 		pe_debug("vdev id %d ecsa added, critical update",
167 			 wlan_vdev_get_id(session->vdev));
168 	}
169 
170 	if (qdf_mem_cmp(&link_ie->link_swt_time, &bcn_2->max_chan_switch_time,
171 			sizeof(bcn_2->max_chan_switch_time))) {
172 		session->mlo_link_info.upt_bcn_mlo_ie = true;
173 		qdf_mem_copy(&link_ie->link_swt_time,
174 			     &bcn_2->max_chan_switch_time,
175 			     sizeof(bcn_2->max_chan_switch_time));
176 		pe_debug("vdev id %d max channel switch time added",
177 			 wlan_vdev_get_id(session->vdev));
178 	}
179 
180 	if (qdf_mem_cmp(&link_ie->link_quiet, &bcn_2->Quiet,
181 			sizeof(bcn_2->Quiet))) {
182 		session->mlo_link_info.upt_bcn_mlo_ie = true;
183 		qdf_mem_copy(&link_ie->link_quiet, &bcn_2->Quiet,
184 			     sizeof(bcn_2->Quiet));
185 		session->mlo_link_info.bss_param_change = true;
186 		pe_debug("vdev id %d quiet added, critical update",
187 			 wlan_vdev_get_id(session->vdev));
188 	}
189 
190 	if (qdf_mem_cmp(&link_ie->link_ht_info, &bcn_2->HTInfo,
191 			sizeof(bcn_2->HTInfo))) {
192 		qdf_mem_copy(&link_ie->link_ht_info, &bcn_2->HTInfo,
193 			     sizeof(bcn_2->HTInfo));
194 		session->mlo_link_info.bss_param_change = true;
195 		pe_debug("vdev id %d HTInfo changed, critical update",
196 			 wlan_vdev_get_id(session->vdev));
197 	}
198 
199 	if (qdf_mem_cmp(&link_ie->link_vht_op, &bcn_2->VHTOperation,
200 			sizeof(bcn_2->VHTOperation))) {
201 		qdf_mem_copy(&link_ie->link_vht_op, &bcn_2->VHTOperation,
202 			     sizeof(bcn_2->VHTOperation));
203 		session->mlo_link_info.bss_param_change = true;
204 		pe_debug("vdev id %d VHTOperation changed, critical update",
205 			 wlan_vdev_get_id(session->vdev));
206 	}
207 
208 	if (qdf_mem_cmp(&link_ie->link_he_op, &bcn_2->he_op,
209 			sizeof(bcn_2->he_op))) {
210 		qdf_mem_copy(&link_ie->link_he_op, &bcn_2->he_op,
211 			     sizeof(bcn_2->he_op));
212 		session->mlo_link_info.bss_param_change = true;
213 		pe_debug("vdev id %d he_op changed, critical update",
214 			 wlan_vdev_get_id(session->vdev));
215 	}
216 
217 	if (qdf_mem_cmp(&link_ie->link_eht_op, &bcn_2->eht_op,
218 			sizeof(bcn_2->eht_op))) {
219 		qdf_mem_copy(&link_ie->link_eht_op, &bcn_2->eht_op,
220 			     sizeof(bcn_2->eht_op));
221 		session->mlo_link_info.bss_param_change = true;
222 		pe_debug("vdev id %d eht_op changed, critical update",
223 			 wlan_vdev_get_id(session->vdev));
224 	}
225 
226 	/*
227 	 * MLOTD
228 	 * If max channel switch time is not exist, calculate one for partner
229 	 * link, if current link enters CAC
230 	 */
231 
232 	if (session->mlo_link_info.bcn_tmpl_exist) {
233 		if (bcn_2->ChanSwitchAnn.present ||
234 		    bcn_2->ext_chan_switch_ann.present ||
235 		    bcn_2->Quiet.present ||
236 		    bcn_2->WiderBWChanSwitchAnn.present ||
237 		    bcn_2->ChannelSwitchWrapper.present ||
238 		    bcn_2->OperatingMode.present ||
239 		    bcn_2->bss_color_change.present)
240 			session->mlo_link_info.bss_param_change = true;
241 		if (session->mlo_link_info.bss_param_change) {
242 			link_ie->bss_param_change_cnt++;
243 			offset = sizeof(tAniBeaconStruct);
244 			bcn_1->Capabilities.criticalUpdateFlag = 1;
245 			ptr = session->pSchBeaconFrameBegin + offset;
246 			dot11f_pack_beacon1(mac_ctx, bcn_1, ptr,
247 					    SIR_MAX_BEACON_SIZE - offset,
248 					    &n_bytes);
249 			bcn_1->Capabilities.criticalUpdateFlag = 0;
250 			mlme_set_notify_co_located_ap_update_rnr(session->vdev,
251 								 true);
252 		}
253 	} else {
254 		//save one time
255 		session->mlo_link_info.bcn_tmpl_exist = true;
256 		session->mlo_link_info.link_ie.bss_param_change_cnt = 0;
257 		qdf_mem_copy(&link_ie->link_cap, &bcn_1->Capabilities,
258 			     sizeof(bcn_1->Capabilities));
259 		qdf_mem_copy(&link_ie->link_qcn_ie, &bcn_2->qcn_ie,
260 			     sizeof(bcn_2->qcn_ie));
261 		qdf_mem_copy(&link_ie->link_ht_cap, &bcn_2->HTCaps,
262 			     sizeof(bcn_2->HTCaps));
263 		qdf_mem_copy(&link_ie->link_ext_cap, &bcn_2->ExtCap,
264 			     sizeof(bcn_2->ExtCap));
265 		qdf_mem_copy(&link_ie->link_vht_cap, &bcn_2->VHTCaps,
266 			     sizeof(bcn_2->VHTCaps));
267 		qdf_mem_copy(&link_ie->link_he_cap, &bcn_2->he_cap,
268 			     sizeof(bcn_2->he_cap));
269 		qdf_mem_copy(&link_ie->link_he_6ghz_band_cap,
270 			     &bcn_2->he_6ghz_band_cap,
271 			     sizeof(bcn_2->he_6ghz_band_cap));
272 		qdf_mem_copy(&link_ie->link_eht_cap, &bcn_2->eht_cap,
273 			     sizeof(bcn_2->eht_cap));
274 	}
275 }
276 
277 static void lim_upt_mlo_partner_info(struct mac_context *mac,
278 				     struct pe_session *session,
279 				     uint8_t *ie, uint32_t ie_len,
280 				     uint16_t ie_offset)
281 {
282 	const uint8_t *mlo_ie;
283 	uint16_t subie_len;
284 	const uint8_t *subie_sta_prof;
285 	uint16_t subie_sta_prof_len;
286 	int link;
287 	struct ml_sch_partner_info *sch_info;
288 	uint16_t per_sta_ofst = mac->sch.sch_mlo_partner.mlo_ie_link_info_ofst;
289 
290 	mlo_ie = wlan_get_ext_ie_ptr_from_ext_id(MLO_IE_OUI_TYPE,
291 						 MLO_IE_OUI_SIZE,
292 						 ie, ie_len);
293 	/* IE is not present */
294 	if (!mlo_ie) {
295 		pe_err("no mlo ie in mlo ap vdev id %d", session->vdev_id);
296 		return;
297 	}
298 	for (link = 0; link < mac->sch.sch_mlo_partner.num_links; link++) {
299 		sch_info = &mac->sch.sch_mlo_partner.partner_info[link];
300 		if (!sch_info->link_info_sta_prof_ofst)
301 			continue;
302 		if (!sch_info->csa_ext_csa_exist) {
303 			per_sta_ofst += 1; /* subelement ID */
304 			subie_len = mlo_ie[per_sta_ofst];
305 			per_sta_ofst += 1; /* length */
306 			per_sta_ofst += subie_len; /* payload of per sta info */
307 			continue;
308 		}
309 		subie_sta_prof = mlo_ie + per_sta_ofst +
310 					sch_info->link_info_sta_prof_ofst;
311 		per_sta_ofst += 1; /* subelement ID */
312 		subie_len = mlo_ie[per_sta_ofst];
313 		per_sta_ofst += 1; /* length */
314 		per_sta_ofst += subie_len; /* payload of per sta info */
315 		subie_sta_prof_len = subie_len + 2 -
316 					sch_info->link_info_sta_prof_ofst;
317 		sch_get_csa_ecsa_count_offset(subie_sta_prof,
318 					      subie_sta_prof_len,
319 					      &sch_info->bcn_csa_cnt_ofst,
320 					      &sch_info->bcn_ext_csa_cnt_ofst);
321 		/* plus offset from IE of sta prof to ie */
322 		if (sch_info->bcn_csa_cnt_ofst)
323 			sch_info->bcn_csa_cnt_ofst += ie_offset +
324 						subie_sta_prof - ie;
325 		if (sch_info->bcn_ext_csa_cnt_ofst)
326 			sch_info->bcn_ext_csa_cnt_ofst += ie_offset +
327 						subie_sta_prof - ie;
328 		pe_debug("vdev %d mlo csa_count_offset %d ecsa_count_offset %d",
329 			 sch_info->vdev_id, sch_info->bcn_csa_cnt_ofst,
330 			 sch_info->bcn_ext_csa_cnt_ofst);
331 	}
332 }
333 #else
334 static void lim_update_link_info(struct mac_context *mac_ctx,
335 				 struct pe_session *session,
336 				 tDot11fBeacon1 *bcn_1,
337 				 tDot11fBeacon2 *bcn_2)
338 {
339 }
340 
341 static void lim_upt_mlo_partner_info(struct mac_context *mac,
342 				     struct pe_session *session,
343 				     uint8_t *ie, uint32_t ie_len,
344 				     uint16_t ie_offset)
345 {
346 }
347 #endif
348 
349 static QDF_STATUS sch_get_p2p_ie_offset(uint8_t *pextra_ie,
350 					uint32_t extra_ie_len,
351 					uint16_t *pie_offset)
352 {
353 	uint8_t elem_id;
354 	uint8_t elem_len;
355 	uint8_t *ie_ptr = pextra_ie;
356 	uint8_t oui_size = sizeof(p2p_oui);
357 	uint32_t p2p_ie_offset = 0;
358 	uint32_t left_len = extra_ie_len;
359 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
360 
361 	*pie_offset = 0;
362 	while (left_len > 2) {
363 		elem_id  = ie_ptr[0];
364 		elem_len = ie_ptr[1];
365 		left_len -= 2;
366 
367 		if (elem_len > left_len)
368 			return status;
369 
370 		if ((elem_id == 0xDD) && (elem_len >= oui_size)) {
371 			if (!qdf_mem_cmp(&ie_ptr[2], &p2p_oui, oui_size)) {
372 				*pie_offset = p2p_ie_offset;
373 				return QDF_STATUS_SUCCESS;
374 			}
375 		}
376 
377 		left_len -= elem_len;
378 		ie_ptr += (elem_len + 2);
379 		p2p_ie_offset += (elem_len + 2);
380 	};
381 
382 	return status;
383 }
384 
385 /**
386  * sch_append_addn_ie() - adds additional IEs to frame
387  * @mac_ctx:       mac global context
388  * @session:       pe session pointer
389  * @frm:           frame where additional IE is to be added
390  * @bcn_size_left: beacon size left
391  * @num_bytes:     final size
392  * @addn_ie:       pointer to additional IE
393  * @addn_ielen:    length of additional IE
394  *
395  * Return: status of operation
396  */
397 static QDF_STATUS
398 sch_append_addn_ie(struct mac_context *mac_ctx, struct pe_session *session,
399 		   uint8_t *frm, uint32_t bcn_size_left,
400 		   uint32_t *num_bytes, uint8_t *addn_ie, uint16_t addn_ielen)
401 {
402 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
403 	uint8_t add_ie[WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN];
404 	uint8_t *p2p_ie = NULL;
405 	uint8_t noa_len = 0;
406 	uint8_t noa_strm[SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN];
407 	uint8_t ext_p2p_ie[DOT11F_IE_P2PBEACON_MAX_LEN + 2];
408 	bool valid_ie;
409 
410 	valid_ie = (addn_ielen <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN &&
411 		    addn_ielen && (addn_ielen <= bcn_size_left));
412 	if (!valid_ie) {
413 		pe_err("addn_ielen %d exceed left %d",
414 		       addn_ielen, bcn_size_left);
415 		return status;
416 	}
417 
418 	qdf_mem_zero(&ext_p2p_ie[0], DOT11F_IE_P2PBEACON_MAX_LEN + 2);
419 	/*
420 	 * P2P IE extracted in wlan_hdd_add_hostapd_conf_vsie may not
421 	 * be at the end of additional IE buffer. The buffer sent to WMA
422 	 * expect P2P IE at the end of beacon buffer and will result in
423 	 * beacon corruption if P2P IE is not at end of beacon buffer.
424 	 */
425 	status = lim_strip_ie(mac_ctx, addn_ie, &addn_ielen, WLAN_ELEMID_VENDOR,
426 			      ONE_BYTE, SIR_MAC_P2P_OUI, SIR_MAC_P2P_OUI_SIZE,
427 			      ext_p2p_ie, DOT11F_IE_P2PBEACON_MAX_LEN);
428 
429 	qdf_mem_copy(&add_ie[0], addn_ie, addn_ielen);
430 
431 	if (status == QDF_STATUS_SUCCESS &&
432 	    ext_p2p_ie[0] == WLAN_ELEMID_VENDOR &&
433 	    !qdf_mem_cmp(&ext_p2p_ie[2], SIR_MAC_P2P_OUI,
434 			 SIR_MAC_P2P_OUI_SIZE)) {
435 		qdf_mem_copy(&add_ie[addn_ielen], ext_p2p_ie,
436 			     ext_p2p_ie[1] + 2);
437 		addn_ielen += ext_p2p_ie[1] + 2;
438 	}
439 
440 	p2p_ie = (uint8_t *)limGetP2pIEPtr(mac_ctx, &add_ie[0], addn_ielen);
441 	if ((p2p_ie) && !mac_ctx->beacon_offload) {
442 		/* get NoA attribute stream P2P IE */
443 		noa_len = lim_get_noa_attr_stream(mac_ctx, noa_strm, session);
444 		if (noa_len) {
445 			if ((noa_len + addn_ielen) <=
446 			    WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN) {
447 				qdf_mem_copy(&add_ie[addn_ielen], noa_strm,
448 					     noa_len);
449 				addn_ielen += noa_len;
450 				p2p_ie[1] += noa_len;
451 			} else {
452 				pe_err("Not able to insert NoA because of length constraint");
453 			}
454 		}
455 	}
456 	if (addn_ielen <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN) {
457 		qdf_mem_copy(frm, &add_ie[0], addn_ielen);
458 		*num_bytes = *num_bytes + addn_ielen;
459 	} else {
460 		pe_warn("Not able to insert because of len constraint %d",
461 			addn_ielen);
462 	}
463 	return status;
464 }
465 
466 static void
467 populate_channel_switch_ann(struct mac_context *mac_ctx,
468 			    tDot11fBeacon2 *bcn,
469 			    struct pe_session *pe_session)
470 {
471 	populate_dot11f_chan_switch_ann(mac_ctx, &bcn->ChanSwitchAnn,
472 					pe_session);
473 	pe_debug("csa: mode:%d chan:%d count:%d",
474 		 bcn->ChanSwitchAnn.switchMode,
475 		 bcn->ChanSwitchAnn.newChannel,
476 		 bcn->ChanSwitchAnn.switchCount);
477 
478 	if (!pe_session->dfsIncludeChanWrapperIe)
479 		return;
480 
481 	populate_dot11f_chan_switch_wrapper(mac_ctx,
482 					    &bcn->ChannelSwitchWrapper,
483 					    pe_session);
484 	pe_debug("wrapper: width:%d f0:%d f1:%d",
485 		 bcn->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newChanWidth,
486 		 bcn->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newCenterChanFreq0,
487 		 bcn->ChannelSwitchWrapper.WiderBWChanSwitchAnn.newCenterChanFreq1);
488 }
489 
490 /**
491  * sch_set_fixed_beacon_fields() - sets the fixed params in beacon frame
492  * @mac_ctx:       mac global context
493  * @session:       pe session entry
494  * @band:          out param, band caclculated
495  * @opr_ch:        operating channels
496  *
497  * Return: status of operation
498  */
499 
500 QDF_STATUS
501 sch_set_fixed_beacon_fields(struct mac_context *mac_ctx, struct pe_session *session)
502 {
503 	tpAniBeaconStruct bcn_struct = (tpAniBeaconStruct)
504 						session->pSchBeaconFrameBegin;
505 	tpSirMacMgmtHdr mac;
506 	uint16_t offset, bcn_size_left;
507 	uint8_t *ptr;
508 	tDot11fBeacon1 *bcn_1;
509 	tDot11fBeacon2 *bcn_2;
510 	uint32_t i, n_status, n_bytes;
511 	bool wps_ap_enable = 0;
512 	tDot11fIEWscProbeRes *wsc_prb_res;
513 	uint8_t *extra_ie = NULL;
514 	uint32_t extra_ie_len = 0;
515 	uint16_t extra_ie_offset = 0;
516 	uint16_t p2p_ie_offset = 0;
517 	uint32_t csa_count_offset = 0;
518 	uint32_t ecsa_count_offset = 0;
519 	QDF_STATUS status = QDF_STATUS_SUCCESS;
520 	bool is_vht_enabled = false;
521 	uint16_t addn_ielen = 0;
522 	uint8_t *addn_ie = NULL;
523 	tDot11fIEExtCap extracted_extcap;
524 	bool extcap_present = true, addnie_present = false;
525 	bool is_6ghz_chsw;
526 	uint8_t *eht_op_ie = NULL, eht_op_ie_len = 0;
527 	uint8_t *eht_cap_ie = NULL, eht_cap_ie_len = 0;
528 	bool is_band_2g;
529 	uint16_t ie_buf_size;
530 	uint16_t mlo_ie_len = 0;
531 
532 	bcn_1 = qdf_mem_malloc(sizeof(tDot11fBeacon1));
533 	if (!bcn_1)
534 		return QDF_STATUS_E_NOMEM;
535 
536 	bcn_2 = qdf_mem_malloc(sizeof(tDot11fBeacon2));
537 	if (!bcn_2) {
538 		qdf_mem_free(bcn_1);
539 		return QDF_STATUS_E_NOMEM;
540 	}
541 
542 	wsc_prb_res = qdf_mem_malloc(sizeof(tDot11fIEWscProbeRes));
543 	if (!wsc_prb_res) {
544 		qdf_mem_free(bcn_1);
545 		qdf_mem_free(bcn_2);
546 		return QDF_STATUS_E_NOMEM;
547 	}
548 	/*
549 	 * First set the fixed fields:
550 	 * set the TFP headers, set the mac header
551 	 */
552 	qdf_mem_zero((uint8_t *) &bcn_struct->macHdr, sizeof(tSirMacMgmtHdr));
553 	mac = (tpSirMacMgmtHdr) &bcn_struct->macHdr;
554 	mac->fc.type = SIR_MAC_MGMT_FRAME;
555 	mac->fc.subType = SIR_MAC_MGMT_BEACON;
556 
557 	for (i = 0; i < 6; i++)
558 		mac->da[i] = 0xff;
559 
560 	qdf_mem_copy(mac->sa, session->self_mac_addr,
561 		     sizeof(session->self_mac_addr));
562 	qdf_mem_copy(mac->bssId, session->bssId, sizeof(session->bssId));
563 
564 	mac->fc.fromDS = 0;
565 	mac->fc.toDS = 0;
566 
567 	/* Skip over the timestamp (it'll be updated later). */
568 	bcn_1->BeaconInterval.interval =
569 		session->beaconParams.beaconInterval;
570 	populate_dot11f_capabilities(mac_ctx, &bcn_1->Capabilities, session);
571 	if (session->ssidHidden) {
572 		bcn_1->SSID.present = 1;
573 		/* rest of the fields are 0 for hidden ssid */
574 		if ((session->ssId.length) &&
575 		    (session->ssidHidden == eHIDDEN_SSID_ZERO_CONTENTS))
576 			bcn_1->SSID.num_ssid = session->ssId.length;
577 	} else {
578 		populate_dot11f_ssid(mac_ctx, &session->ssId, &bcn_1->SSID);
579 	}
580 
581 	populate_dot11f_supp_rates(mac_ctx, POPULATE_DOT11F_RATES_OPERATIONAL,
582 				   &bcn_1->SuppRates, session);
583 	populate_dot11f_ds_params(mac_ctx, &bcn_1->DSParams,
584 				  session->curr_op_freq);
585 
586 	offset = sizeof(tAniBeaconStruct);
587 	ptr = session->pSchBeaconFrameBegin + offset;
588 
589 	if (LIM_IS_AP_ROLE(session)) {
590 		/* Initialize the default IE bitmap to zero */
591 		qdf_mem_zero((uint8_t *) &(session->DefProbeRspIeBitmap),
592 			    (sizeof(uint32_t) * 8));
593 
594 		/* Initialize the default IE bitmap to zero */
595 		qdf_mem_zero((uint8_t *) &(session->probeRespFrame),
596 			    sizeof(session->probeRespFrame));
597 
598 		/*
599 		 * Can be efficiently updated whenever new IE added in Probe
600 		 * response in future
601 		 */
602 		if (lim_update_probe_rsp_template_ie_bitmap_beacon1(mac_ctx,
603 					bcn_1, session) != QDF_STATUS_SUCCESS)
604 			pe_err("Failed to build ProbeRsp template");
605 	}
606 
607 	n_status = dot11f_pack_beacon1(mac_ctx, bcn_1, ptr,
608 				       SIR_MAX_BEACON_SIZE - offset, &n_bytes);
609 	if (DOT11F_FAILED(n_status)) {
610 		pe_err("Failed to packed a tDot11fBeacon1 (0x%08x)",
611 			n_status);
612 		qdf_mem_free(bcn_1);
613 		qdf_mem_free(bcn_2);
614 		qdf_mem_free(wsc_prb_res);
615 		return QDF_STATUS_E_FAILURE;
616 	} else if (DOT11F_WARNED(n_status)) {
617 		pe_warn("Warnings while packing a tDot11fBeacon1(0x%08x)",
618 			n_status);
619 	}
620 	session->schBeaconOffsetBegin = offset + (uint16_t) n_bytes;
621 	/* Initialize the 'new' fields at the end of the beacon */
622 	is_6ghz_chsw =
623 		WLAN_REG_IS_6GHZ_CHAN_FREQ(session->curr_op_freq) ||
624 		WLAN_REG_IS_6GHZ_CHAN_FREQ
625 			(session->gLimChannelSwitch.sw_target_freq);
626 	if (session->limSystemRole == eLIM_AP_ROLE &&
627 	    session->dfsIncludeChanSwIe == true) {
628 		if (!CHAN_HOP_ALL_BANDS_ENABLE ||
629 		    session->lim_non_ecsa_cap_num == 0 || is_6ghz_chsw) {
630 			tDot11fIEext_chan_switch_ann *ext_csa =
631 						&bcn_2->ext_chan_switch_ann;
632 			populate_dot_11_f_ext_chann_switch_ann(mac_ctx,
633 							       ext_csa,
634 							       session);
635 			pe_debug("ecsa: mode:%d reg:%d chan:%d count:%d",
636 				 ext_csa->switch_mode,
637 				 ext_csa->new_reg_class,
638 				 ext_csa->new_channel,
639 				 ext_csa->switch_count);
640 		}
641 
642 		if (session->lim_non_ecsa_cap_num &&
643 		    WLAN_REG_IS_24GHZ_CH_FREQ(session->curr_op_freq) &&
644 		    !is_6ghz_chsw)
645 			populate_channel_switch_ann(mac_ctx, bcn_2, session);
646 	}
647 
648 	populate_dot11_supp_operating_classes(mac_ctx,
649 		&bcn_2->SuppOperatingClasses, session);
650 	populate_dot11f_country(mac_ctx, &bcn_2->Country, session);
651 	if (bcn_1->Capabilities.qos)
652 		populate_dot11f_edca_param_set(mac_ctx, &bcn_2->EDCAParamSet,
653 					       session);
654 
655 	if (session->lim11hEnable) {
656 		populate_dot11f_power_constraints(mac_ctx,
657 						  &bcn_2->PowerConstraints);
658 		populate_dot11f_tpc_report(mac_ctx, &bcn_2->TPCReport, session);
659 		/* Need to insert channel switch announcement here */
660 		if ((LIM_IS_AP_ROLE(session) ||
661 		     LIM_IS_P2P_DEVICE_GO(session)) &&
662 		    session->dfsIncludeChanSwIe && !is_6ghz_chsw) {
663 			populate_channel_switch_ann(mac_ctx, bcn_2, session);
664 		}
665 	}
666 
667 	if (bcn_2->ext_chan_switch_ann.present || bcn_2->ChanSwitchAnn.present)
668 		populate_dot11f_max_chan_switch_time(
669 			mac_ctx, &bcn_2->max_chan_switch_time, session);
670 
671 	if (mac_ctx->rrm.rrmConfig.sap_rrm_enabled)
672 		populate_dot11f_rrm_ie(mac_ctx, &bcn_2->RRMEnabledCap,
673 			session);
674 
675 #ifdef FEATURE_AP_MCC_CH_AVOIDANCE
676 	/* populate proprietary IE for MDM device operating in AP-MCC */
677 	populate_dot11f_avoid_channel_ie(mac_ctx, &bcn_2->QComVendorIE,
678 					 session);
679 #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
680 
681 	if (session->dot11mode != MLME_DOT11_MODE_11B)
682 		populate_dot11f_erp_info(mac_ctx, &bcn_2->ERPInfo, session);
683 
684 	if (session->htCapability) {
685 		populate_dot11f_ht_caps(mac_ctx, session, &bcn_2->HTCaps);
686 		populate_dot11f_ht_info(mac_ctx, &bcn_2->HTInfo, session);
687 	}
688 	if (session->vhtCapability) {
689 		populate_dot11f_vht_caps(mac_ctx, session, &bcn_2->VHTCaps);
690 		populate_dot11f_vht_operation(mac_ctx, session,
691 					      &bcn_2->VHTOperation);
692 		is_vht_enabled = true;
693 		/* following is for MU MIMO: we do not support it yet */
694 		/*
695 		populate_dot11f_vht_ext_bss_load( mac_ctx, &bcn2.VHTExtBssLoad);
696 		*/
697 		populate_dot11f_tx_power_env(mac_ctx,
698 					     &bcn_2->transmit_power_env[0],
699 					     session->ch_width,
700 					     session->curr_op_freq,
701 					     &bcn_2->num_transmit_power_env,
702 					     false);
703 		populate_dot11f_qcn_ie(mac_ctx, session, &bcn_2->qcn_ie,
704 				       QCN_IE_ATTR_ID_ALL);
705 	}
706 
707 	if (wlan_reg_is_6ghz_chan_freq(session->curr_op_freq)) {
708 		populate_dot11f_tx_power_env(mac_ctx,
709 					     &bcn_2->transmit_power_env[0],
710 					     session->ch_width,
711 					     session->curr_op_freq,
712 					     &bcn_2->num_transmit_power_env,
713 					     false);
714 	}
715 
716 	if (lim_is_session_he_capable(session)) {
717 		pe_debug("Populate HE IEs");
718 		populate_dot11f_he_caps(mac_ctx, session,
719 					&bcn_2->he_cap);
720 		populate_dot11f_he_operation(mac_ctx, session,
721 					&bcn_2->he_op);
722 		populate_dot11f_sr_info(mac_ctx, session,
723 					&bcn_2->spatial_reuse);
724 		populate_dot11f_he_6ghz_cap(mac_ctx, session,
725 					    &bcn_2->he_6ghz_band_cap);
726 		populate_dot11f_he_bss_color_change(mac_ctx, session,
727 					&bcn_2->bss_color_change);
728 	}
729 
730 	if (lim_is_session_eht_capable(session)) {
731 		pe_debug("Populate EHT IEs");
732 		populate_dot11f_eht_caps(mac_ctx, session, &bcn_2->eht_cap);
733 		populate_dot11f_eht_operation(mac_ctx, session, &bcn_2->eht_op);
734 	}
735 
736 	populate_dot11f_ext_cap(mac_ctx, is_vht_enabled, &bcn_2->ExtCap,
737 				session);
738 
739 	populate_dot11f_ext_supp_rates(mac_ctx,
740 				POPULATE_DOT11F_RATES_OPERATIONAL,
741 				&bcn_2->ExtSuppRates, session);
742 
743 	if (session->pLimStartBssReq) {
744 		populate_dot11f_wpa(mac_ctx, &session->pLimStartBssReq->rsnIE,
745 				    &bcn_2->WPA);
746 		populate_dot11f_rsn_opaque(mac_ctx,
747 					   &session->pLimStartBssReq->rsnIE,
748 					   &bcn_2->RSNOpaque);
749 		populate_dot11f_wapi(mac_ctx, &session->pLimStartBssReq->rsnIE,
750 				     &bcn_2->WAPI);
751 	}
752 
753 	if (session->limWmeEnabled)
754 		populate_dot11f_wmm(mac_ctx, &bcn_2->WMMInfoAp,
755 				&bcn_2->WMMParams, &bcn_2->WMMCaps, session);
756 
757 	if (LIM_IS_AP_ROLE(session)) {
758 		if (session->wps_state != SAP_WPS_DISABLED) {
759 			populate_dot11f_beacon_wpsi_es(mac_ctx,
760 						&bcn_2->WscBeacon, session);
761 		}
762 	} else {
763 		wps_ap_enable = mac_ctx->mlme_cfg->wps_params.enable_wps &
764 					    WNI_CFG_WPS_ENABLE_AP;
765 		if (wps_ap_enable)
766 			populate_dot11f_wsc(mac_ctx, &bcn_2->WscBeacon);
767 
768 		if (mac_ctx->lim.wscIeInfo.wscEnrollmentState ==
769 						eLIM_WSC_ENROLL_BEGIN) {
770 			populate_dot11f_wsc_registrar_info(mac_ctx,
771 						&bcn_2->WscBeacon);
772 			mac_ctx->lim.wscIeInfo.wscEnrollmentState =
773 						eLIM_WSC_ENROLL_IN_PROGRESS;
774 		}
775 
776 		if (mac_ctx->lim.wscIeInfo.wscEnrollmentState ==
777 						eLIM_WSC_ENROLL_END) {
778 			de_populate_dot11f_wsc_registrar_info(mac_ctx,
779 							&bcn_2->WscBeacon);
780 			mac_ctx->lim.wscIeInfo.wscEnrollmentState =
781 							eLIM_WSC_ENROLL_NOOP;
782 		}
783 	}
784 
785 	if (LIM_IS_AP_ROLE(session)) {
786 		if (wlan_vdev_mlme_is_mlo_ap(session->vdev)) {
787 			lim_update_link_info(mac_ctx, session, bcn_1, bcn_2);
788 			mlo_ie_len = lim_send_bcn_frame_mlo(mac_ctx, session);
789 			populate_dot11f_mlo_rnr(
790 				mac_ctx, session,
791 				&bcn_2->reduced_neighbor_report);
792 		} else if (!wlan_reg_is_6ghz_chan_freq(session->curr_op_freq)) {
793 			/*
794 			 * TD: If current AP is MLO, RNR IE is already populated
795 			 *     More effor to populate RNR IE for
796 			 *     MLO SAP + 6G legacy SAP
797 			 */
798 			populate_dot11f_6g_rnr(mac_ctx, session,
799 					       &bcn_2->reduced_neighbor_report);
800 		}
801 		/*
802 		 * Can be efficiently updated whenever new IE added  in Probe
803 		 * response in future
804 		 */
805 		lim_update_probe_rsp_template_ie_bitmap_beacon2(mac_ctx, bcn_2,
806 					&session->DefProbeRspIeBitmap[0],
807 					&session->probeRespFrame);
808 
809 		/* update probe response WPS IE instead of beacon WPS IE */
810 		if (session->wps_state != SAP_WPS_DISABLED) {
811 			if (session->APWPSIEs.SirWPSProbeRspIE.FieldPresent)
812 				populate_dot11f_probe_res_wpsi_es(mac_ctx,
813 							wsc_prb_res, session);
814 			else
815 				wsc_prb_res->present = 0;
816 			if (wsc_prb_res->present) {
817 				set_probe_rsp_ie_bitmap(
818 					&session->DefProbeRspIeBitmap[0],
819 					SIR_MAC_WPA_EID);
820 				qdf_mem_copy((void *)
821 					&session->probeRespFrame.WscProbeRes,
822 					(void *)wsc_prb_res,
823 					sizeof(tDot11fIEWscProbeRes));
824 			}
825 		}
826 	}
827 
828 	addnie_present = (session->add_ie_params.probeRespBCNDataLen != 0);
829 	if (addnie_present) {
830 		/*
831 		 * Strip HE cap/op from additional IE buffer if any, as they
832 		 * should be populated already.
833 		 */
834 		lim_strip_he_ies_from_add_ies(mac_ctx, session);
835 		lim_strip_eht_ies_from_add_ies(mac_ctx, session);
836 
837 		addn_ielen = session->add_ie_params.probeRespBCNDataLen;
838 		addn_ie = qdf_mem_malloc(addn_ielen);
839 		if (!addn_ie) {
840 			qdf_mem_free(bcn_1);
841 			qdf_mem_free(bcn_2);
842 			qdf_mem_free(wsc_prb_res);
843 			return QDF_STATUS_E_NOMEM;
844 		}
845 		qdf_mem_copy(addn_ie,
846 			session->add_ie_params.probeRespBCNData_buff,
847 			addn_ielen);
848 
849 		qdf_mem_zero((uint8_t *)&extracted_extcap,
850 			     sizeof(tDot11fIEExtCap));
851 		status = lim_strip_extcap_update_struct(mac_ctx, addn_ie,
852 				&addn_ielen, &extracted_extcap);
853 		if (QDF_STATUS_SUCCESS != status) {
854 			extcap_present = false;
855 			pe_debug("extcap not extracted");
856 		}
857 		/* merge extcap IE */
858 		if (extcap_present)
859 			lim_merge_extcap_struct(&bcn_2->ExtCap,
860 						&extracted_extcap,
861 						true);
862 	}
863 
864 	if (session->vhtCapability && session->gLimOperatingMode.present) {
865 		populate_dot11f_operating_mode(mac_ctx, &bcn_2->OperatingMode,
866 					       session);
867 		lim_strip_ie(mac_ctx, addn_ie, &addn_ielen,
868 			     WLAN_ELEMID_OP_MODE_NOTIFY, ONE_BYTE, NULL, 0,
869 			     NULL, SIR_MAC_VHT_OPMODE_SIZE - 2);
870 	}
871 
872 	n_status = dot11f_pack_beacon2(mac_ctx, bcn_2,
873 				       session->pSchBeaconFrameEnd,
874 				       SIR_MAX_BEACON_SIZE, &n_bytes);
875 	if (DOT11F_FAILED(n_status)) {
876 		pe_err("Failed to packed a tDot11fBeacon2 (0x%08x)",
877 			n_status);
878 		status = QDF_STATUS_E_FAILURE;
879 		goto free_and_exit;
880 	} else if (DOT11F_WARNED(n_status)) {
881 		pe_err("Warnings while packing a tDot11fBeacon2(0x%08x)",
882 			n_status);
883 	}
884 
885 	/* Strip EHT capabilities IE */
886 	if (lim_is_session_eht_capable(session)) {
887 		ie_buf_size = n_bytes;
888 
889 		eht_op_ie = qdf_mem_malloc(WLAN_MAX_IE_LEN + 2);
890 		if (!eht_op_ie) {
891 			pe_err("malloc failed for eht_op_ie");
892 			status = QDF_STATUS_E_FAILURE;
893 			goto free_and_exit;
894 		}
895 
896 		status = lim_strip_eht_op_ie(mac_ctx,
897 					     session->pSchBeaconFrameEnd,
898 					     &ie_buf_size, eht_op_ie);
899 		if (QDF_IS_STATUS_ERROR(status)) {
900 			pe_err("Failed to strip EHT op IE");
901 			qdf_mem_free(eht_op_ie);
902 			status = QDF_STATUS_E_FAILURE;
903 			goto free_and_exit;
904 		}
905 
906 		lim_ieee80211_pack_ehtop(eht_op_ie, bcn_2->eht_op,
907 					 bcn_2->VHTOperation,
908 					 bcn_2->he_op,
909 					 bcn_2->HTInfo);
910 		eht_op_ie_len = eht_op_ie[1] + 2;
911 
912 		/* Copy the EHT operation IE to the end of the frame */
913 		qdf_mem_copy(session->pSchBeaconFrameEnd + ie_buf_size,
914 			     eht_op_ie, eht_op_ie_len);
915 		qdf_mem_free(eht_op_ie);
916 		n_bytes = ie_buf_size + eht_op_ie_len;
917 
918 		ie_buf_size = n_bytes;
919 		eht_cap_ie = qdf_mem_malloc(WLAN_MAX_IE_LEN + 2);
920 		if (!eht_cap_ie) {
921 			pe_err("malloc failed for eht_cap_ie");
922 			status = QDF_STATUS_E_FAILURE;
923 			goto free_and_exit;
924 		}
925 		status = lim_strip_eht_cap_ie(mac_ctx,
926 					      session->pSchBeaconFrameEnd,
927 					      &ie_buf_size, eht_cap_ie);
928 		if (QDF_IS_STATUS_ERROR(status)) {
929 			pe_err("Failed to strip EHT cap IE");
930 			qdf_mem_free(eht_cap_ie);
931 			status = QDF_STATUS_E_FAILURE;
932 			goto free_and_exit;
933 		}
934 
935 		is_band_2g =
936 			WLAN_REG_IS_24GHZ_CH_FREQ(session->curr_op_freq);
937 
938 		lim_ieee80211_pack_ehtcap(eht_cap_ie, bcn_2->eht_cap,
939 					  bcn_2->he_cap, is_band_2g);
940 		eht_cap_ie_len = eht_cap_ie[1] + 2;
941 
942 		/* Copy the EHT cap IE to the end of the frame */
943 		qdf_mem_copy(session->pSchBeaconFrameEnd + ie_buf_size,
944 			     eht_cap_ie, eht_cap_ie_len);
945 
946 		qdf_mem_free(eht_cap_ie);
947 		n_bytes = ie_buf_size + eht_cap_ie_len;
948 	}
949 
950 	if (mlo_ie_len) {
951 		status = lim_fill_complete_mlo_ie(session, mlo_ie_len,
952 					 session->pSchBeaconFrameEnd + n_bytes);
953 		if (QDF_IS_STATUS_ERROR(status)) {
954 			pe_debug("assemble ml ie error");
955 			mlo_ie_len = 0;
956 		}
957 		n_bytes += mlo_ie_len;
958 	}
959 
960 	/* Fill the CSA/ECSA count offsets if the IEs are present */
961 	mac_ctx->sch.ecsa_count_offset = 0;
962 	mac_ctx->sch.csa_count_offset = 0;
963 	if (session->dfsIncludeChanSwIe)
964 		sch_get_csa_ecsa_count_offset(session->pSchBeaconFrameEnd,
965 					      n_bytes,
966 					      &csa_count_offset,
967 					      &ecsa_count_offset);
968 
969 	if (csa_count_offset)
970 		mac_ctx->sch.csa_count_offset =
971 				session->schBeaconOffsetBegin + TIM_IE_SIZE +
972 				csa_count_offset;
973 	if (ecsa_count_offset)
974 		mac_ctx->sch.ecsa_count_offset =
975 				session->schBeaconOffsetBegin + TIM_IE_SIZE +
976 				ecsa_count_offset;
977 
978 	if (wlan_vdev_mlme_is_mlo_ap(session->vdev))
979 		lim_upt_mlo_partner_info(mac_ctx, session,
980 					 session->pSchBeaconFrameEnd, n_bytes,
981 					 session->schBeaconOffsetBegin +
982 					 TIM_IE_SIZE);
983 
984 	extra_ie = session->pSchBeaconFrameEnd + n_bytes;
985 	extra_ie_offset = n_bytes;
986 
987 	/*
988 	 * Max size left to append additional IE.= (MAX beacon size - TIM IE -
989 	 * beacon fix size (bcn_1 + header) - beacon variable size (bcn_1).
990 	 */
991 	bcn_size_left = SIR_MAX_BEACON_SIZE - TIM_IE_SIZE -
992 				session->schBeaconOffsetBegin -
993 				(uint16_t)n_bytes;
994 
995 	/* TODO: Append additional IE here. */
996 	if (addn_ielen > 0)
997 		sch_append_addn_ie(mac_ctx, session,
998 				   session->pSchBeaconFrameEnd + n_bytes,
999 				   bcn_size_left, &n_bytes,
1000 				   addn_ie, addn_ielen);
1001 
1002 	session->schBeaconOffsetEnd = (uint16_t) n_bytes;
1003 	extra_ie_len = n_bytes - extra_ie_offset;
1004 	/* Get the p2p Ie Offset */
1005 	status = sch_get_p2p_ie_offset(extra_ie, extra_ie_len, &p2p_ie_offset);
1006 	if (QDF_STATUS_SUCCESS == status)
1007 		/* Update the P2P Ie Offset */
1008 		mac_ctx->sch.p2p_ie_offset =
1009 			session->schBeaconOffsetBegin + TIM_IE_SIZE +
1010 			extra_ie_offset + p2p_ie_offset;
1011 	else
1012 		mac_ctx->sch.p2p_ie_offset = 0;
1013 
1014 	pe_debug("vdev %d: beacon begin offset %d fixed size %d csa_count_offset %d ecsa_count_offset %d max_bcn_size_left %d addn_ielen %d beacon end offset %d",
1015 		 session->vdev_id, offset, session->schBeaconOffsetBegin,
1016 		 mac_ctx->sch.csa_count_offset, mac_ctx->sch.ecsa_count_offset,
1017 		 bcn_size_left, addn_ielen, session->schBeaconOffsetEnd);
1018 	mac_ctx->sch.beacon_changed = 1;
1019 	status = QDF_STATUS_SUCCESS;
1020 
1021 free_and_exit:
1022 	qdf_mem_free(bcn_1);
1023 	qdf_mem_free(bcn_2);
1024 	qdf_mem_free(wsc_prb_res);
1025 	qdf_mem_free(addn_ie);
1026 	return status;
1027 }
1028 
1029 QDF_STATUS
1030 lim_update_probe_rsp_template_ie_bitmap_beacon1(struct mac_context *mac,
1031 						tDot11fBeacon1 *beacon1,
1032 						struct pe_session *pe_session)
1033 {
1034 	uint32_t *DefProbeRspIeBitmap;
1035 	tDot11fProbeResponse *prb_rsp;
1036 
1037 	if (!pe_session) {
1038 		pe_debug("PESession is null!");
1039 		return QDF_STATUS_E_FAILURE;
1040 	}
1041 	DefProbeRspIeBitmap = &pe_session->DefProbeRspIeBitmap[0];
1042 	prb_rsp = &pe_session->probeRespFrame;
1043 	prb_rsp->BeaconInterval = beacon1->BeaconInterval;
1044 	qdf_mem_copy((void *)&prb_rsp->Capabilities,
1045 		     (void *)&beacon1->Capabilities,
1046 		     sizeof(beacon1->Capabilities));
1047 
1048 	/* SSID */
1049 	if (beacon1->SSID.present) {
1050 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, WLAN_ELEMID_SSID);
1051 		/* populating it, because probe response has to go with SSID even in hidden case */
1052 		populate_dot11f_ssid(mac, &pe_session->ssId, &prb_rsp->SSID);
1053 	}
1054 	/* supported rates */
1055 	if (beacon1->SuppRates.present) {
1056 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, WLAN_ELEMID_RATES);
1057 		qdf_mem_copy((void *)&prb_rsp->SuppRates,
1058 			     (void *)&beacon1->SuppRates,
1059 			     sizeof(beacon1->SuppRates));
1060 
1061 	}
1062 	/* DS Parameter set */
1063 	if (beacon1->DSParams.present) {
1064 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1065 					WLAN_ELEMID_DSPARMS);
1066 		qdf_mem_copy((void *)&prb_rsp->DSParams,
1067 			     (void *)&beacon1->DSParams,
1068 			     sizeof(beacon1->DSParams));
1069 
1070 	}
1071 
1072 	return QDF_STATUS_SUCCESS;
1073 }
1074 
1075 void lim_update_probe_rsp_template_ie_bitmap_beacon2(struct mac_context *mac,
1076 						     tDot11fBeacon2 *beacon2,
1077 						     uint32_t *DefProbeRspIeBitmap,
1078 						     tDot11fProbeResponse *prb_rsp)
1079 {
1080 	uint8_t i;
1081 	uint16_t num_tpe = beacon2->num_transmit_power_env;
1082 
1083 	if (beacon2->Country.present) {
1084 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, WLAN_ELEMID_COUNTRY);
1085 		qdf_mem_copy((void *)&prb_rsp->Country,
1086 			     (void *)&beacon2->Country,
1087 			     sizeof(beacon2->Country));
1088 
1089 	}
1090 	/* Power constraint */
1091 	if (beacon2->PowerConstraints.present) {
1092 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1093 					WLAN_ELEMID_PWRCNSTR);
1094 		qdf_mem_copy((void *)&prb_rsp->PowerConstraints,
1095 			     (void *)&beacon2->PowerConstraints,
1096 			     sizeof(beacon2->PowerConstraints));
1097 
1098 	}
1099 	/* Channel Switch Annoouncement WLAN_ELEMID_CHANSWITCHANN */
1100 	if (beacon2->ChanSwitchAnn.present) {
1101 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1102 					WLAN_ELEMID_CHANSWITCHANN);
1103 		qdf_mem_copy((void *)&prb_rsp->ChanSwitchAnn,
1104 			     (void *)&beacon2->ChanSwitchAnn,
1105 			     sizeof(beacon2->ChanSwitchAnn));
1106 
1107 	}
1108 
1109 	/* EXT Channel Switch Announcement CHNL_EXTENDED_SWITCH_ANN_EID*/
1110 	if (beacon2->ext_chan_switch_ann.present) {
1111 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1112 			WLAN_ELEMID_EXTCHANSWITCHANN);
1113 		qdf_mem_copy((void *)&prb_rsp->ext_chan_switch_ann,
1114 			(void *)&beacon2->ext_chan_switch_ann,
1115 			sizeof(beacon2->ext_chan_switch_ann));
1116 	}
1117 
1118 	/* Supported operating class */
1119 	if (beacon2->SuppOperatingClasses.present) {
1120 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1121 					WLAN_ELEMID_SUPP_OP_CLASS);
1122 		qdf_mem_copy((void *)&prb_rsp->SuppOperatingClasses,
1123 				(void *)&beacon2->SuppOperatingClasses,
1124 				sizeof(beacon2->SuppOperatingClasses));
1125 	}
1126 
1127 #ifdef FEATURE_AP_MCC_CH_AVOIDANCE
1128 	if (beacon2->QComVendorIE.present) {
1129 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1130 					SIR_MAC_QCOM_VENDOR_EID);
1131 		qdf_mem_copy((void *)&prb_rsp->QComVendorIE,
1132 			     (void *)&beacon2->QComVendorIE,
1133 			     sizeof(beacon2->QComVendorIE));
1134 	}
1135 #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
1136 
1137 	/* ERP information */
1138 	if (beacon2->ERPInfo.present) {
1139 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, WLAN_ELEMID_ERP);
1140 		qdf_mem_copy((void *)&prb_rsp->ERPInfo,
1141 			     (void *)&beacon2->ERPInfo,
1142 			     sizeof(beacon2->ERPInfo));
1143 
1144 	}
1145 	/* Extended supported rates */
1146 	if (beacon2->ExtSuppRates.present) {
1147 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1148 					WLAN_ELEMID_XRATES);
1149 		qdf_mem_copy((void *)&prb_rsp->ExtSuppRates,
1150 			     (void *)&beacon2->ExtSuppRates,
1151 			     sizeof(beacon2->ExtSuppRates));
1152 
1153 	}
1154 
1155 	/* WPA */
1156 	if (beacon2->WPA.present) {
1157 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_WPA_EID);
1158 		qdf_mem_copy((void *)&prb_rsp->WPA, (void *)&beacon2->WPA,
1159 			     sizeof(beacon2->WPA));
1160 
1161 	}
1162 
1163 	/* RSN */
1164 	if (beacon2->RSNOpaque.present) {
1165 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, WLAN_ELEMID_RSN);
1166 		qdf_mem_copy((void *)&prb_rsp->RSNOpaque,
1167 			     (void *)&beacon2->RSNOpaque,
1168 			     sizeof(beacon2->RSNOpaque));
1169 	}
1170 
1171 	/* WAPI */
1172 	if (beacon2->WAPI.present) {
1173 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, WLAN_ELEMID_WAPI);
1174 		qdf_mem_copy((void *)&prb_rsp->WAPI,
1175 			     (void *)&beacon2->WAPI,
1176 			     sizeof(beacon2->WAPI));
1177 	}
1178 
1179 	/* EDCA Parameter set */
1180 	if (beacon2->EDCAParamSet.present) {
1181 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1182 					WLAN_ELEMID_EDCAPARMS);
1183 		qdf_mem_copy((void *)&prb_rsp->EDCAParamSet,
1184 			     (void *)&beacon2->EDCAParamSet,
1185 			     sizeof(beacon2->EDCAParamSet));
1186 
1187 	}
1188 	/* Vendor specific - currently no vendor specific IEs added */
1189 	/* Requested IEs - currently we are not processing this will be added later */
1190 	/* HT capability IE */
1191 	if (beacon2->HTCaps.present) {
1192 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1193 					WLAN_ELEMID_HTCAP_ANA);
1194 		qdf_mem_copy((void *)&prb_rsp->HTCaps, (void *)&beacon2->HTCaps,
1195 			     sizeof(beacon2->HTCaps));
1196 	}
1197 	/* HT Info IE */
1198 	if (beacon2->HTInfo.present) {
1199 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, WLAN_ELEMID_HTINFO_ANA);
1200 		qdf_mem_copy((void *)&prb_rsp->HTInfo, (void *)&beacon2->HTInfo,
1201 			     sizeof(beacon2->HTInfo));
1202 	}
1203 	if (beacon2->VHTCaps.present) {
1204 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1205 					WLAN_ELEMID_VHTCAP);
1206 		qdf_mem_copy((void *)&prb_rsp->VHTCaps,
1207 			     (void *)&beacon2->VHTCaps,
1208 			     sizeof(beacon2->VHTCaps));
1209 	}
1210 	if (beacon2->VHTOperation.present) {
1211 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1212 					WLAN_ELEMID_VHTOP);
1213 		qdf_mem_copy((void *)&prb_rsp->VHTOperation,
1214 			     (void *)&beacon2->VHTOperation,
1215 			     sizeof(beacon2->VHTOperation));
1216 	}
1217 
1218 	for (i = 0; i < num_tpe; i++) {
1219 		if (beacon2->transmit_power_env[i].present) {
1220 			set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1221 						WLAN_ELEMID_VHT_TX_PWR_ENVLP);
1222 			qdf_mem_copy((void *)&prb_rsp->transmit_power_env[i],
1223 				     (void *)&beacon2->transmit_power_env[i],
1224 				     sizeof(beacon2->transmit_power_env[i]));
1225 		}
1226 	}
1227 	prb_rsp->num_transmit_power_env = num_tpe;
1228 
1229 	if (beacon2->VHTExtBssLoad.present) {
1230 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1231 					WLAN_ELEMID_EXT_BSS_LOAD);
1232 		qdf_mem_copy((void *)&prb_rsp->VHTExtBssLoad,
1233 			     (void *)&beacon2->VHTExtBssLoad,
1234 			     sizeof(beacon2->VHTExtBssLoad));
1235 	}
1236 	/* WMM IE */
1237 	if (beacon2->WMMParams.present) {
1238 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_WPA_EID);
1239 		qdf_mem_copy((void *)&prb_rsp->WMMParams,
1240 			     (void *)&beacon2->WMMParams,
1241 			     sizeof(beacon2->WMMParams));
1242 	}
1243 	/* WMM capability - most of the case won't be present */
1244 	if (beacon2->WMMCaps.present) {
1245 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_WPA_EID);
1246 		qdf_mem_copy((void *)&prb_rsp->WMMCaps,
1247 			     (void *)&beacon2->WMMCaps,
1248 			     sizeof(beacon2->WMMCaps));
1249 	}
1250 
1251 	/* Extended Capability */
1252 	if (beacon2->ExtCap.present) {
1253 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, DOT11F_EID_EXTCAP);
1254 		qdf_mem_copy((void *)&prb_rsp->ExtCap,
1255 			     (void *)&beacon2->ExtCap,
1256 			     sizeof(beacon2->ExtCap));
1257 	}
1258 
1259 	if (beacon2->he_cap.present) {
1260 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1261 					DOT11F_EID_HE_CAP);
1262 		qdf_mem_copy((void *)&prb_rsp->he_cap,
1263 			     (void *)&beacon2->he_cap,
1264 			     sizeof(beacon2->he_cap));
1265 	}
1266 	if (beacon2->he_op.present) {
1267 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1268 					DOT11F_EID_HE_OP);
1269 		qdf_mem_copy((void *)&prb_rsp->he_op,
1270 			     (void *)&beacon2->he_op,
1271 			     sizeof(beacon2->he_op));
1272 	}
1273 
1274 	if (beacon2->spatial_reuse.present) {
1275 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1276 					DOT11F_EID_SPATIAL_REUSE);
1277 		qdf_mem_copy((void *)&prb_rsp->spatial_reuse,
1278 			     (void *)&beacon2->spatial_reuse,
1279 			     sizeof(beacon2->spatial_reuse));
1280 	}
1281 
1282 	if (beacon2->he_6ghz_band_cap.present) {
1283 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1284 					DOT11F_EID_HE_6GHZ_BAND_CAP);
1285 		qdf_mem_copy((void *)&prb_rsp->he_6ghz_band_cap,
1286 			     (void *)&beacon2->he_6ghz_band_cap,
1287 			     sizeof(beacon2->he_6ghz_band_cap));
1288 	}
1289 
1290 	if (beacon2->eht_cap.present) {
1291 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1292 					DOT11F_EID_EHT_CAP);
1293 		qdf_mem_copy((void *)&prb_rsp->eht_cap,
1294 			     (void *)&beacon2->eht_cap,
1295 			     sizeof(beacon2->eht_cap));
1296 	}
1297 
1298 	if (beacon2->eht_op.present) {
1299 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1300 					DOT11F_EID_EHT_OP);
1301 		qdf_mem_copy((void *)&prb_rsp->eht_op,
1302 			     (void *)&beacon2->eht_op,
1303 			     sizeof(beacon2->eht_op));
1304 	}
1305 
1306 	if (beacon2->mlo_ie.present) {
1307 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1308 					DOT11F_EID_MLO_IE);
1309 		qdf_mem_copy((void *)&prb_rsp->mlo_ie,
1310 			     (void *)&beacon2->mlo_ie,
1311 			     sizeof(beacon2->mlo_ie));
1312 	}
1313 
1314 	if (beacon2->reduced_neighbor_report.present) {
1315 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1316 					DOT11F_EID_REDUCED_NEIGHBOR_REPORT);
1317 		qdf_mem_copy((void *)&prb_rsp->reduced_neighbor_report,
1318 			     (void *)&beacon2->reduced_neighbor_report,
1319 			     sizeof(beacon2->reduced_neighbor_report));
1320 	}
1321 
1322 	if (beacon2->TPCReport.present) {
1323 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1324 					WLAN_ELEMID_TPCREP);
1325 		qdf_mem_copy((void *)&prb_rsp->TPCReport,
1326 			     (void *)&beacon2->TPCReport,
1327 			     sizeof(beacon2->TPCReport));
1328 	}
1329 
1330 }
1331 
1332 void set_probe_rsp_ie_bitmap(uint32_t *IeBitmap, uint32_t pos)
1333 {
1334 	uint32_t index, temp;
1335 
1336 	index = pos >> 5;
1337 	if (index >= 8) {
1338 		return;
1339 	}
1340 	temp = IeBitmap[index];
1341 
1342 	temp |= 1 << (pos & 0x1F);
1343 
1344 	IeBitmap[index] = temp;
1345 }
1346 
1347 /**
1348  * write_beacon_to_memory() - send the beacon to the wma
1349  * @mac: pointer to mac structure
1350  * @size: Size of the beacon to write to memory
1351  * @length: Length field of the beacon to write to memory
1352  * @pe_session: pe session
1353  * @reason: beacon update reason
1354  *
1355  * return: success: QDF_STATUS_SUCCESS failure: QDF_STATUS_E_FAILURE
1356  */
1357 static QDF_STATUS write_beacon_to_memory(struct mac_context *mac, uint16_t size,
1358 					 uint16_t length,
1359 					 struct pe_session *pe_session,
1360 					 enum sir_bcn_update_reason reason)
1361 {
1362 	uint16_t i;
1363 	tpAniBeaconStruct pBeacon;
1364 	QDF_STATUS status;
1365 
1366 	/* copy end of beacon only if length > 0 */
1367 	if (length > 0) {
1368 		if (size + pe_session->schBeaconOffsetEnd >
1369 		    SIR_MAX_BEACON_SIZE) {
1370 			pe_err("beacon tmp fail size %d BeaconOffsetEnd %d",
1371 			       size, pe_session->schBeaconOffsetEnd);
1372 			return QDF_STATUS_E_FAILURE;
1373 		}
1374 		for (i = 0; i < pe_session->schBeaconOffsetEnd; i++)
1375 			pe_session->pSchBeaconFrameBegin[size++] =
1376 				pe_session->pSchBeaconFrameEnd[i];
1377 	}
1378 	/* Update the beacon length */
1379 	pBeacon = (tpAniBeaconStruct) pe_session->pSchBeaconFrameBegin;
1380 	/* Do not include the beaconLength indicator itself */
1381 	if (length == 0) {
1382 		pBeacon->beaconLength = 0;
1383 		/* Dont copy entire beacon, Copy length field alone */
1384 		size = 4;
1385 	} else
1386 		pBeacon->beaconLength = (uint32_t) size - sizeof(uint32_t);
1387 
1388 	if (!mac->sch.beacon_changed)
1389 		return QDF_STATUS_E_FAILURE;
1390 
1391 	status = sch_send_beacon_req(mac, pe_session->pSchBeaconFrameBegin,
1392 				     size, pe_session, reason);
1393 	if (QDF_IS_STATUS_ERROR(status))
1394 		pe_err("sch_send_beacon_req() returned an error %d, size %d",
1395 		       status, size);
1396 	mac->sch.beacon_changed = 0;
1397 
1398 	return status;
1399 }
1400 
1401 /**
1402  * sch_generate_tim
1403  *
1404  * FUNCTION:
1405  * Generate TIM
1406  *
1407  * LOGIC:
1408  *
1409  * ASSUMPTIONS:
1410  *
1411  * NOTE:
1412  *
1413  * @param mac pointer to global mac structure
1414  * @param **pPtr pointer to the buffer, where the TIM bit is to be written.
1415  * @param *timLength pointer to limLength, which needs to be returned.
1416  * @return None
1417  */
1418 void sch_generate_tim(struct mac_context *mac, uint8_t **pPtr, uint16_t *timLength,
1419 		      uint8_t dtimPeriod)
1420 {
1421 	uint8_t *ptr = *pPtr;
1422 	uint32_t val = 0;
1423 	uint32_t minAid = 1;    /* Always start with AID 1 as minimum */
1424 	uint32_t maxAid = HAL_NUM_STA;
1425 	/* Generate partial virtual bitmap */
1426 	uint8_t N1 = minAid / 8;
1427 	uint8_t N2 = maxAid / 8;
1428 
1429 	if (N1 & 1)
1430 		N1--;
1431 
1432 	*timLength = N2 - N1 + 4;
1433 	val = dtimPeriod;
1434 
1435 	/*
1436 	 * Write 0xFF to firmware's field to detect firmware's mal-function
1437 	 * early. DTIM count and bitmap control usually cannot be 0xFF, so it
1438 	 * is easy to know that firmware never updated DTIM count/bitmap control
1439 	 * field after host driver downloaded beacon template if end-user complaints
1440 	 * that DTIM count and bitmapControl is 0xFF.
1441 	 */
1442 	*ptr++ = WLAN_ELEMID_TIM;
1443 	*ptr++ = (uint8_t) (*timLength);
1444 	/* location for dtimCount. will be filled in by FW. */
1445 	*ptr++ = 0xFF;
1446 	*ptr++ = (uint8_t) val;
1447 	/* location for bitmap control. will be filled in by FW. */
1448 	*ptr++ = 0xFF;
1449 	ptr += (N2 - N1 + 1);
1450 
1451 	*pPtr = ptr;
1452 }
1453 
1454 QDF_STATUS sch_process_pre_beacon_ind(struct mac_context *mac,
1455 				      struct scheduler_msg *limMsg,
1456 				      enum sir_bcn_update_reason reason)
1457 {
1458 	struct beacon_gen_params *pMsg = limMsg->bodyptr;
1459 	uint32_t beaconSize;
1460 	struct pe_session *pe_session;
1461 	uint8_t sessionId;
1462 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
1463 
1464 	pe_session = pe_find_session_by_bssid(mac, pMsg->bssid, &sessionId);
1465 	if (!pe_session) {
1466 		pe_err("session lookup fails");
1467 		goto end;
1468 	}
1469 
1470 	beaconSize = pe_session->schBeaconOffsetBegin;
1471 
1472 	/* If SME is not in normal mode, no need to generate beacon */
1473 	if (pe_session->limSmeState != eLIM_SME_NORMAL_STATE) {
1474 		pe_debug("PreBeaconInd received in invalid state: %d",
1475 			 pe_session->limSmeState);
1476 		goto end;
1477 	}
1478 
1479 	switch (GET_LIM_SYSTEM_ROLE(pe_session)) {
1480 	case eLIM_AP_ROLE: {
1481 		uint8_t *ptr =
1482 			&pe_session->pSchBeaconFrameBegin[pe_session->
1483 							     schBeaconOffsetBegin];
1484 		uint16_t timLength = 0;
1485 
1486 		if (pe_session->statypeForBss == STA_ENTRY_SELF) {
1487 			sch_generate_tim(mac, &ptr, &timLength,
1488 					 pe_session->dtimPeriod);
1489 			beaconSize += 2 + timLength;
1490 			status =
1491 			    write_beacon_to_memory(mac, (uint16_t) beaconSize,
1492 						   (uint16_t) beaconSize,
1493 						   pe_session, reason);
1494 		} else
1495 			pe_err("can not send beacon for PEER session entry");
1496 			}
1497 			break;
1498 
1499 	default:
1500 		pe_err("Error-PE has Receive PreBeconGenIndication when System is in %d role",
1501 		       GET_LIM_SYSTEM_ROLE(pe_session));
1502 	}
1503 
1504 end:
1505 	qdf_mem_free(pMsg);
1506 
1507 	return status;
1508 }
1509