1 /*
2  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /*
21  * This file 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  */
sch_get_csa_ecsa_count_offset(const uint8_t * ie,uint32_t ie_len,uint32_t * csa_count_offset,uint32_t * ecsa_count_offset)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  */
lim_update_link_info(struct mac_context * mac_ctx,struct pe_session * session,tDot11fBeacon1 * bcn_1,tDot11fBeacon2 * bcn_2)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 
lim_upt_mlo_partner_info(struct mac_context * mac,struct pe_session * session,uint8_t * ie,uint32_t ie_len,uint16_t ie_offset)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
lim_update_link_info(struct mac_context * mac_ctx,struct pe_session * session,tDot11fBeacon1 * bcn_1,tDot11fBeacon2 * bcn_2)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 
lim_upt_mlo_partner_info(struct mac_context * mac,struct pe_session * session,uint8_t * ie,uint32_t ie_len,uint16_t ie_offset)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 
sch_get_p2p_ie_offset(uint8_t * pextra_ie,uint32_t extra_ie_len,uint16_t * pie_offset)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
sch_append_addn_ie(struct mac_context * mac_ctx,struct pe_session * session,uint8_t * frm,uint32_t bcn_size_left,uint32_t * num_bytes,uint8_t * addn_ie,uint16_t addn_ielen)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
populate_channel_switch_ann(struct mac_context * mac_ctx,tDot11fBeacon2 * bcn,struct pe_session * pe_session)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 	if (!pe_session->dfsIncludeChanWrapperIe)
474 		return;
475 
476 	populate_dot11f_chan_switch_wrapper(mac_ctx,
477 					    &bcn->ChannelSwitchWrapper,
478 					    pe_session);
479 }
480 
481 /**
482  * sch_get_tim_size() - Get TIM ie size
483  * @max_aid: Max AID value
484  *
485  * Return: TIM ie size
486  */
sch_get_tim_size(uint32_t max_aid)487 static uint16_t sch_get_tim_size(uint32_t max_aid)
488 {
489 	uint16_t tim_size;
490 	uint8_t N2;
491 
492 	/**
493 	 * The TIM ie format:
494 	 * +----------+------+----------+-------------------------------------------------+
495 	 * |Element ID|Length|DTIM Count|DTIM Period|Bitmap Control|Partial Virtual Bitmap|
496 	 * +----------+------+----------+-----------+--------------+----------------------+
497 	 *   1 Byte    1 Byte  1Byte       1 Byte        1 Byte          0~255 Byte
498 	 *
499 	 * According to 80211 Spec, The Partial Virtual Bitmap field consists of octets
500 	 * numbered N1 to N2 of the traffic indication virtual bitmap, where N1 is the
501 	 * largest even number such that bits numbered 1 to (N1 * 8) – 1 in the traffic
502 	 * indication virtual bitmap are all 0, and N2 is the smallest number such that
503 	 * bits numbered (N2 + 1) * 8 to 2007 in the traffic indication virtual bitmap
504 	 * are all 0. In this case, the Bitmap Offset subfield value contains the number
505 	 * N1/2, and the Length field is set to (N2 – N1) + 4. Always start with AID 1 as
506 	 * minimum, N1 = (1 / 8) = 0. TIM size = length + 1Byte Element ID + 1Byte Length.
507 	 * The expression is reduced to (N2 - 0) + 4 + 2 = N2 + 6;
508 	 */
509 	N2 = max_aid / 8;
510 	tim_size = N2 + 6;
511 
512 	return tim_size;
513 }
514 
515 #ifdef SAP_MULTI_LINK_EMULATION
omit_caps_for_2link_sap(tDot11fBeacon2 * bcn_2)516 static void omit_caps_for_2link_sap(tDot11fBeacon2 *bcn_2)
517 {
518 	qdf_mem_zero(&bcn_2->HTCaps, sizeof(bcn_2->HTCaps));
519 	qdf_mem_zero(&bcn_2->EDCAParamSet, sizeof(bcn_2->EDCAParamSet));
520 	qdf_mem_zero(&bcn_2->PowerConstraints, sizeof(bcn_2->PowerConstraints));
521 	qdf_mem_zero(&bcn_2->TPCReport, sizeof(bcn_2->TPCReport));
522 
523 	pe_debug("Removed caps from beacon/probe rsp");
524 }
525 #else
omit_caps_for_2link_sap(tDot11fBeacon2 * bcn_2)526 static inline void omit_caps_for_2link_sap(tDot11fBeacon2 *bcn_2)
527 {
528 }
529 #endif
530 
531 /**
532  * sch_set_fixed_beacon_fields() - sets the fixed params in beacon frame
533  * @mac_ctx:       mac global context
534  * @session:       pe session entry
535  * @band:          out param, band caclculated
536  * @opr_ch:        operating channels
537  *
538  * Return: status of operation
539  */
540 
541 QDF_STATUS
sch_set_fixed_beacon_fields(struct mac_context * mac_ctx,struct pe_session * session)542 sch_set_fixed_beacon_fields(struct mac_context *mac_ctx, struct pe_session *session)
543 {
544 	tpAniBeaconStruct bcn_struct = (tpAniBeaconStruct)
545 						session->pSchBeaconFrameBegin;
546 	tpSirMacMgmtHdr mac;
547 	uint16_t offset, bcn_size_left;
548 	uint8_t *ptr;
549 	tDot11fBeacon1 *bcn_1;
550 	tDot11fBeacon2 *bcn_2;
551 	uint32_t i, n_status, n_bytes;
552 	bool wps_ap_enable = 0;
553 	tDot11fIEWscProbeRes *wsc_prb_res;
554 	uint8_t *extra_ie = NULL;
555 	uint32_t extra_ie_len = 0;
556 	uint16_t extra_ie_offset = 0;
557 	uint16_t p2p_ie_offset = 0;
558 	uint32_t csa_count_offset = 0;
559 	uint32_t ecsa_count_offset = 0;
560 	QDF_STATUS status = QDF_STATUS_SUCCESS;
561 	bool is_vht_enabled = false;
562 	uint16_t addn_ielen = 0;
563 	uint8_t *addn_ie = NULL;
564 	tDot11fIEExtCap extracted_extcap;
565 	bool extcap_present = true, addnie_present = false;
566 	bool is_6ghz_chsw;
567 	uint8_t *eht_op_ie = NULL, eht_op_ie_len = 0;
568 	uint8_t *eht_cap_ie = NULL, eht_cap_ie_len = 0;
569 	bool is_band_2g;
570 	uint16_t ie_buf_size;
571 	uint16_t mlo_ie_len = 0;
572 	uint16_t tim_size;
573 	uint8_t reg_cc[REG_ALPHA2_LEN + 1];
574 	uint16_t tpe_ie_len = 0;
575 	tDot11fIEtransmit_power_env *transmit_power_env = NULL;
576 	uint16_t num_transmit_power_env = 0;
577 
578 	tim_size = sch_get_tim_size(HAL_NUM_STA);
579 
580 	bcn_1 = qdf_mem_malloc(sizeof(tDot11fBeacon1));
581 	if (!bcn_1)
582 		return QDF_STATUS_E_NOMEM;
583 
584 	bcn_2 = qdf_mem_malloc(sizeof(tDot11fBeacon2));
585 	if (!bcn_2) {
586 		qdf_mem_free(bcn_1);
587 		return QDF_STATUS_E_NOMEM;
588 	}
589 
590 	wsc_prb_res = qdf_mem_malloc(sizeof(tDot11fIEWscProbeRes));
591 	if (!wsc_prb_res) {
592 		qdf_mem_free(bcn_1);
593 		qdf_mem_free(bcn_2);
594 		return QDF_STATUS_E_NOMEM;
595 	}
596 	/*
597 	 * First set the fixed fields:
598 	 * set the TFP headers, set the mac header
599 	 */
600 	qdf_mem_zero((uint8_t *) &bcn_struct->macHdr, sizeof(tSirMacMgmtHdr));
601 	mac = (tpSirMacMgmtHdr) &bcn_struct->macHdr;
602 	mac->fc.type = SIR_MAC_MGMT_FRAME;
603 	mac->fc.subType = SIR_MAC_MGMT_BEACON;
604 
605 	for (i = 0; i < 6; i++)
606 		mac->da[i] = 0xff;
607 
608 	qdf_mem_copy(mac->sa, session->self_mac_addr,
609 		     sizeof(session->self_mac_addr));
610 	qdf_mem_copy(mac->bssId, session->bssId, sizeof(session->bssId));
611 
612 	mac->fc.fromDS = 0;
613 	mac->fc.toDS = 0;
614 
615 	/* Skip over the timestamp (it'll be updated later). */
616 	bcn_1->BeaconInterval.interval =
617 		session->beaconParams.beaconInterval;
618 	populate_dot11f_capabilities(mac_ctx, &bcn_1->Capabilities, session);
619 	if (session->ssidHidden) {
620 		bcn_1->SSID.present = 1;
621 		/* rest of the fields are 0 for hidden ssid */
622 		if ((session->ssId.length) &&
623 		    (session->ssidHidden == eHIDDEN_SSID_ZERO_CONTENTS))
624 			bcn_1->SSID.num_ssid = session->ssId.length;
625 	} else {
626 		populate_dot11f_ssid(mac_ctx, &session->ssId, &bcn_1->SSID);
627 	}
628 
629 	populate_dot11f_supp_rates(mac_ctx, POPULATE_DOT11F_RATES_OPERATIONAL,
630 				   &bcn_1->SuppRates, session);
631 	populate_dot11f_ds_params(mac_ctx, &bcn_1->DSParams,
632 				  session->curr_op_freq);
633 
634 	offset = sizeof(tAniBeaconStruct);
635 	ptr = session->pSchBeaconFrameBegin + offset;
636 
637 	if (LIM_IS_AP_ROLE(session)) {
638 		/* Initialize the default IE bitmap to zero */
639 		qdf_mem_zero((uint8_t *) &(session->DefProbeRspIeBitmap),
640 			    (sizeof(uint32_t) * 8));
641 
642 		/* Initialize the default IE bitmap to zero */
643 		qdf_mem_zero((uint8_t *) &(session->probeRespFrame),
644 			    sizeof(session->probeRespFrame));
645 
646 		/*
647 		 * Can be efficiently updated whenever new IE added in Probe
648 		 * response in future
649 		 */
650 		if (lim_update_probe_rsp_template_ie_bitmap_beacon1(mac_ctx,
651 					bcn_1, session) != QDF_STATUS_SUCCESS)
652 			pe_err("Failed to build ProbeRsp template");
653 	}
654 
655 	n_status = dot11f_pack_beacon1(mac_ctx, bcn_1, ptr,
656 				       SIR_MAX_BEACON_SIZE - offset, &n_bytes);
657 	if (DOT11F_FAILED(n_status)) {
658 		pe_err("Failed to packed a tDot11fBeacon1 (0x%08x)",
659 			n_status);
660 		qdf_mem_free(bcn_1);
661 		qdf_mem_free(bcn_2);
662 		qdf_mem_free(wsc_prb_res);
663 		return QDF_STATUS_E_FAILURE;
664 	} else if (DOT11F_WARNED(n_status)) {
665 		pe_warn("Warnings while packing a tDot11fBeacon1(0x%08x)",
666 			n_status);
667 	}
668 	session->schBeaconOffsetBegin = offset + (uint16_t) n_bytes;
669 	/* Initialize the 'new' fields at the end of the beacon */
670 	is_6ghz_chsw =
671 		WLAN_REG_IS_6GHZ_CHAN_FREQ(session->curr_op_freq) ||
672 		WLAN_REG_IS_6GHZ_CHAN_FREQ
673 			(session->gLimChannelSwitch.sw_target_freq);
674 	if (session->limSystemRole == eLIM_AP_ROLE &&
675 	    (session->dfsIncludeChanSwIe == true ||
676 	     session->bw_update_include_ch_sw_ie == true)) {
677 		if (!CHAN_HOP_ALL_BANDS_ENABLE ||
678 		    session->lim_non_ecsa_cap_num == 0 || is_6ghz_chsw) {
679 			tDot11fIEext_chan_switch_ann *ext_csa =
680 						&bcn_2->ext_chan_switch_ann;
681 			populate_dot_11_f_ext_chann_switch_ann(mac_ctx,
682 							       ext_csa,
683 							       session);
684 			if (lim_is_session_eht_capable(session)) {
685 				bcn_2->ChannelSwitchWrapper.present = 1;
686 				populate_dot11f_bw_ind_element(mac_ctx,
687 						session,
688 				&bcn_2->ChannelSwitchWrapper.bw_ind_element);
689 			}
690 		}
691 		if (session->lim_non_ecsa_cap_num &&
692 		    !is_6ghz_chsw)
693 			populate_channel_switch_ann(mac_ctx, bcn_2, session);
694 
695 	}
696 
697 	populate_dot11_supp_operating_classes(mac_ctx,
698 		&bcn_2->SuppOperatingClasses, session);
699 	populate_dot11f_country(mac_ctx, &bcn_2->Country, session);
700 	if (bcn_1->Capabilities.qos)
701 		populate_dot11f_edca_param_set(mac_ctx, &bcn_2->EDCAParamSet,
702 					       session);
703 
704 	if (session->lim11hEnable) {
705 		populate_dot11f_power_constraints(mac_ctx,
706 						  &bcn_2->PowerConstraints);
707 		populate_dot11f_tpc_report(mac_ctx, &bcn_2->TPCReport, session);
708 		/* Need to insert channel switch announcement here */
709 		if ((LIM_IS_AP_ROLE(session) ||
710 		     LIM_IS_P2P_DEVICE_GO(session)) &&
711 		    session->dfsIncludeChanSwIe && !is_6ghz_chsw) {
712 			populate_channel_switch_ann(mac_ctx, bcn_2, session);
713 		}
714 	}
715 
716 	if (bcn_2->ext_chan_switch_ann.present || bcn_2->ChanSwitchAnn.present)
717 		populate_dot11f_max_chan_switch_time(
718 			mac_ctx, &bcn_2->max_chan_switch_time, session);
719 
720 	if (mac_ctx->rrm.rrmConfig.sap_rrm_enabled)
721 		populate_dot11f_rrm_ie(mac_ctx, &bcn_2->RRMEnabledCap,
722 			session);
723 
724 #ifdef FEATURE_AP_MCC_CH_AVOIDANCE
725 	/* populate proprietary IE for MDM device operating in AP-MCC */
726 	populate_dot11f_avoid_channel_ie(mac_ctx, &bcn_2->QComVendorIE,
727 					 session);
728 #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
729 
730 	if (session->dot11mode != MLME_DOT11_MODE_11B)
731 		populate_dot11f_erp_info(mac_ctx, &bcn_2->ERPInfo, session);
732 
733 	populate_dot11f_qcn_ie(mac_ctx, session, &bcn_2->qcn_ie,
734 			       QCN_IE_ATTR_ID_ALL);
735 
736 	if (session->htCapability) {
737 		populate_dot11f_ht_caps(mac_ctx, session, &bcn_2->HTCaps);
738 		populate_dot11f_ht_info(mac_ctx, &bcn_2->HTInfo, session);
739 	}
740 	if (session->vhtCapability) {
741 		populate_dot11f_vht_caps(mac_ctx, session, &bcn_2->VHTCaps);
742 		populate_dot11f_vht_operation(mac_ctx, session,
743 					      &bcn_2->VHTOperation);
744 		is_vht_enabled = true;
745 		/* following is for MU MIMO: we do not support it yet */
746 		/*
747 		populate_dot11f_vht_ext_bss_load( mac_ctx, &bcn2.VHTExtBssLoad);
748 		*/
749 	}
750 
751 	if (session->vhtCapability ||
752 	    wlan_reg_is_6ghz_chan_freq(session->curr_op_freq)) {
753 		transmit_power_env = qdf_mem_malloc(
754 					WLAN_MAX_NUM_TPE_IE *
755 					sizeof(tDot11fIEtransmit_power_env));
756 		if (!transmit_power_env) {
757 			status = QDF_STATUS_E_NOMEM;
758 			goto free_and_exit;
759 		}
760 		populate_dot11f_tx_power_env(mac_ctx,
761 					     transmit_power_env,
762 					     session->ch_width,
763 					     session->curr_op_freq,
764 					     &num_transmit_power_env,
765 					     false);
766 		tpe_ie_len = lim_get_tpe_ie_length(session->ch_width,
767 						   transmit_power_env,
768 						   num_transmit_power_env);
769 	}
770 
771 	if (lim_is_session_he_capable(session)) {
772 		populate_dot11f_he_caps(mac_ctx, session,
773 					&bcn_2->he_cap);
774 		populate_dot11f_he_operation(mac_ctx, session,
775 					&bcn_2->he_op);
776 		populate_dot11f_sr_info(mac_ctx, session,
777 					&bcn_2->spatial_reuse);
778 		populate_dot11f_he_6ghz_cap(mac_ctx, session,
779 					    &bcn_2->he_6ghz_band_cap);
780 		populate_dot11f_he_bss_color_change(mac_ctx, session,
781 					&bcn_2->bss_color_change);
782 	}
783 
784 	if (lim_is_session_eht_capable(session)) {
785 		populate_dot11f_eht_caps(mac_ctx, session, &bcn_2->eht_cap);
786 		populate_dot11f_eht_operation(mac_ctx, session, &bcn_2->eht_op);
787 	}
788 
789 	populate_dot11f_ext_cap(mac_ctx, is_vht_enabled, &bcn_2->ExtCap,
790 				session);
791 
792 	populate_dot11f_ext_supp_rates(mac_ctx,
793 				POPULATE_DOT11F_RATES_OPERATIONAL,
794 				&bcn_2->ExtSuppRates, session);
795 
796 	if (session->pLimStartBssReq) {
797 		populate_dot11f_wpa(mac_ctx, &session->pLimStartBssReq->rsnIE,
798 				    &bcn_2->WPA);
799 		populate_dot11f_rsn_opaque(mac_ctx,
800 					   &session->pLimStartBssReq->rsnIE,
801 					   &bcn_2->RSNOpaque);
802 		populate_dot11f_wapi(mac_ctx, &session->pLimStartBssReq->rsnIE,
803 				     &bcn_2->WAPI);
804 	}
805 
806 	if (session->limWmeEnabled)
807 		populate_dot11f_wmm(mac_ctx, &bcn_2->WMMInfoAp,
808 				&bcn_2->WMMParams, &bcn_2->WMMCaps, session);
809 
810 	if (LIM_IS_AP_ROLE(session)) {
811 		if (session->wps_state != SAP_WPS_DISABLED) {
812 			populate_dot11f_beacon_wpsi_es(mac_ctx,
813 						&bcn_2->WscBeacon, session);
814 		}
815 	} else {
816 		wps_ap_enable = mac_ctx->mlme_cfg->wps_params.enable_wps &
817 					    WNI_CFG_WPS_ENABLE_AP;
818 		if (wps_ap_enable)
819 			populate_dot11f_wsc(mac_ctx, &bcn_2->WscBeacon);
820 
821 		if (mac_ctx->lim.wscIeInfo.wscEnrollmentState ==
822 						eLIM_WSC_ENROLL_BEGIN) {
823 			populate_dot11f_wsc_registrar_info(mac_ctx,
824 						&bcn_2->WscBeacon);
825 			mac_ctx->lim.wscIeInfo.wscEnrollmentState =
826 						eLIM_WSC_ENROLL_IN_PROGRESS;
827 		}
828 
829 		if (mac_ctx->lim.wscIeInfo.wscEnrollmentState ==
830 						eLIM_WSC_ENROLL_END) {
831 			de_populate_dot11f_wsc_registrar_info(mac_ctx,
832 							&bcn_2->WscBeacon);
833 			mac_ctx->lim.wscIeInfo.wscEnrollmentState =
834 							eLIM_WSC_ENROLL_NOOP;
835 		}
836 	}
837 
838 	if (LIM_IS_AP_ROLE(session)) {
839 		if (wlan_vdev_mlme_is_mlo_ap(session->vdev)) {
840 			lim_update_link_info(mac_ctx, session, bcn_1, bcn_2);
841 			mlo_ie_len = lim_send_bcn_frame_mlo(mac_ctx, session);
842 			populate_dot11f_mlo_rnr(
843 				mac_ctx, session,
844 				&bcn_2->reduced_neighbor_report);
845 		} else if (!wlan_reg_is_6ghz_chan_freq(session->curr_op_freq)) {
846 			/*
847 			 * TD: If current AP is MLO, RNR IE is already populated
848 			 *     More effor to populate RNR IE for
849 			 *     MLO SAP + 6G legacy SAP
850 			 */
851 			populate_dot11f_6g_rnr(mac_ctx, session,
852 					       &bcn_2->reduced_neighbor_report);
853 		}
854 		/*
855 		 * Can be efficiently updated whenever new IE added  in Probe
856 		 * response in future
857 		 */
858 		lim_update_probe_rsp_template_ie_bitmap_beacon2(mac_ctx, bcn_2,
859 					&session->DefProbeRspIeBitmap[0],
860 					&session->probeRespFrame);
861 
862 		/* update probe response WPS IE instead of beacon WPS IE */
863 		if (session->wps_state != SAP_WPS_DISABLED) {
864 			if (session->APWPSIEs.SirWPSProbeRspIE.FieldPresent)
865 				populate_dot11f_probe_res_wpsi_es(mac_ctx,
866 							wsc_prb_res, session);
867 			else
868 				wsc_prb_res->present = 0;
869 			if (wsc_prb_res->present) {
870 				set_probe_rsp_ie_bitmap(
871 					&session->DefProbeRspIeBitmap[0],
872 					SIR_MAC_WPA_EID);
873 				qdf_mem_copy((void *)
874 					&session->probeRespFrame.WscProbeRes,
875 					(void *)wsc_prb_res,
876 					sizeof(tDot11fIEWscProbeRes));
877 			}
878 		}
879 	}
880 
881 	addnie_present = (session->add_ie_params.probeRespBCNDataLen != 0);
882 	if (addnie_present) {
883 		/*
884 		 * Strip HE cap/op from additional IE buffer if any, as they
885 		 * should be populated already.
886 		 */
887 		lim_strip_he_ies_from_add_ies(mac_ctx, session);
888 		lim_strip_eht_ies_from_add_ies(mac_ctx, session);
889 		lim_strip_wapi_ies_from_add_ies(mac_ctx, session);
890 
891 		addn_ielen = session->add_ie_params.probeRespBCNDataLen;
892 		addn_ie = qdf_mem_malloc(addn_ielen);
893 		if (!addn_ie) {
894 			status = QDF_STATUS_E_NOMEM;
895 			goto free_and_exit;
896 		}
897 		qdf_mem_copy(addn_ie,
898 			session->add_ie_params.probeRespBCNData_buff,
899 			addn_ielen);
900 
901 		qdf_mem_zero((uint8_t *)&extracted_extcap,
902 			     sizeof(tDot11fIEExtCap));
903 		status = lim_strip_extcap_update_struct(mac_ctx, addn_ie,
904 				&addn_ielen, &extracted_extcap);
905 		if (QDF_STATUS_SUCCESS != status) {
906 			extcap_present = false;
907 			pe_debug("extcap not extracted");
908 		}
909 		/* merge extcap IE */
910 		if (extcap_present) {
911 			lim_merge_extcap_struct(&bcn_2->ExtCap,
912 						&extracted_extcap,
913 						true);
914 			populate_dot11f_bcn_prot_extcaps(mac_ctx, session,
915 							 &bcn_2->ExtCap);
916 		}
917 	}
918 
919 	if (session->vhtCapability && session->gLimOperatingMode.present) {
920 		populate_dot11f_operating_mode(mac_ctx, &bcn_2->OperatingMode,
921 					       session);
922 		lim_strip_ie(mac_ctx, addn_ie, &addn_ielen,
923 			     WLAN_ELEMID_OP_MODE_NOTIFY, ONE_BYTE, NULL, 0,
924 			     NULL, SIR_MAC_VHT_OPMODE_SIZE - 2);
925 	}
926 
927 	omit_caps_for_2link_sap(bcn_2);
928 
929 	n_status = dot11f_pack_beacon2(mac_ctx, bcn_2,
930 				       session->pSchBeaconFrameEnd,
931 				       SIR_MAX_BEACON_SIZE, &n_bytes);
932 	if (DOT11F_FAILED(n_status)) {
933 		pe_err("Failed to packed a tDot11fBeacon2 (0x%08x)",
934 			n_status);
935 		status = QDF_STATUS_E_FAILURE;
936 		goto free_and_exit;
937 	} else if (DOT11F_WARNED(n_status)) {
938 		pe_err("Warnings while packing a tDot11fBeacon2(0x%08x)",
939 			n_status);
940 	}
941 
942 	/* Strip EHT capabilities IE */
943 	if (lim_is_session_eht_capable(session)) {
944 		ie_buf_size = n_bytes;
945 
946 		eht_op_ie = qdf_mem_malloc(WLAN_MAX_IE_LEN + 2);
947 		if (!eht_op_ie) {
948 			pe_err("malloc failed for eht_op_ie");
949 			status = QDF_STATUS_E_FAILURE;
950 			goto free_and_exit;
951 		}
952 
953 		status = lim_strip_eht_op_ie(mac_ctx,
954 					     session->pSchBeaconFrameEnd,
955 					     &ie_buf_size, eht_op_ie);
956 		if (QDF_IS_STATUS_ERROR(status)) {
957 			pe_err("Failed to strip EHT op IE");
958 			qdf_mem_free(eht_op_ie);
959 			status = QDF_STATUS_E_FAILURE;
960 			goto free_and_exit;
961 		}
962 
963 		lim_ieee80211_pack_ehtop(eht_op_ie, bcn_2->eht_op,
964 					 bcn_2->VHTOperation,
965 					 bcn_2->he_op,
966 					 bcn_2->HTInfo);
967 		eht_op_ie_len = eht_op_ie[1] + 2;
968 
969 		/* Copy the EHT operation IE to the end of the frame */
970 		qdf_mem_copy(session->pSchBeaconFrameEnd + ie_buf_size,
971 			     eht_op_ie, eht_op_ie_len);
972 		qdf_mem_free(eht_op_ie);
973 		n_bytes = ie_buf_size + eht_op_ie_len;
974 
975 		ie_buf_size = n_bytes;
976 		eht_cap_ie = qdf_mem_malloc(WLAN_MAX_IE_LEN + 2);
977 		if (!eht_cap_ie) {
978 			pe_err("malloc failed for eht_cap_ie");
979 			status = QDF_STATUS_E_FAILURE;
980 			goto free_and_exit;
981 		}
982 		status = lim_strip_eht_cap_ie(mac_ctx,
983 					      session->pSchBeaconFrameEnd,
984 					      &ie_buf_size, eht_cap_ie);
985 		if (QDF_IS_STATUS_ERROR(status)) {
986 			pe_err("Failed to strip EHT cap IE");
987 			qdf_mem_free(eht_cap_ie);
988 			status = QDF_STATUS_E_FAILURE;
989 			goto free_and_exit;
990 		}
991 
992 		is_band_2g =
993 			WLAN_REG_IS_24GHZ_CH_FREQ(session->curr_op_freq);
994 
995 		lim_ieee80211_pack_ehtcap(eht_cap_ie, bcn_2->eht_cap,
996 					  bcn_2->he_cap, is_band_2g);
997 		eht_cap_ie_len = eht_cap_ie[1] + 2;
998 
999 		/* Copy the EHT cap IE to the end of the frame */
1000 		qdf_mem_copy(session->pSchBeaconFrameEnd + ie_buf_size,
1001 			     eht_cap_ie, eht_cap_ie_len);
1002 
1003 		qdf_mem_free(eht_cap_ie);
1004 		n_bytes = ie_buf_size + eht_cap_ie_len;
1005 	}
1006 
1007 	if (tpe_ie_len) {
1008 		status = lim_fill_complete_tpe_ie(
1009 					session->ch_width, tpe_ie_len,
1010 					transmit_power_env,
1011 					num_transmit_power_env,
1012 					session->pSchBeaconFrameEnd + n_bytes);
1013 		if (QDF_IS_STATUS_ERROR(status)) {
1014 			pe_debug("assemble tpe ie error");
1015 			tpe_ie_len = 0;
1016 		}
1017 		n_bytes += tpe_ie_len;
1018 	}
1019 
1020 	if (mlo_ie_len) {
1021 		status = lim_fill_complete_mlo_ie(session, mlo_ie_len,
1022 					 session->pSchBeaconFrameEnd + n_bytes);
1023 		if (QDF_IS_STATUS_ERROR(status)) {
1024 			pe_debug("assemble ml ie error");
1025 			mlo_ie_len = 0;
1026 		}
1027 		n_bytes += mlo_ie_len;
1028 	}
1029 
1030 	/* Fill the CSA/ECSA count offsets if the IEs are present */
1031 	mac_ctx->sch.ecsa_count_offset = 0;
1032 	mac_ctx->sch.csa_count_offset = 0;
1033 	if (session->dfsIncludeChanSwIe)
1034 		sch_get_csa_ecsa_count_offset(session->pSchBeaconFrameEnd,
1035 					      n_bytes,
1036 					      &csa_count_offset,
1037 					      &ecsa_count_offset);
1038 
1039 	if (csa_count_offset)
1040 		mac_ctx->sch.csa_count_offset =
1041 				session->schBeaconOffsetBegin + tim_size +
1042 				csa_count_offset;
1043 	if (ecsa_count_offset)
1044 		mac_ctx->sch.ecsa_count_offset =
1045 				session->schBeaconOffsetBegin + tim_size +
1046 				ecsa_count_offset;
1047 
1048 	if (wlan_vdev_mlme_is_mlo_ap(session->vdev))
1049 		lim_upt_mlo_partner_info(mac_ctx, session,
1050 					 session->pSchBeaconFrameEnd, n_bytes,
1051 					 session->schBeaconOffsetBegin +
1052 					 tim_size);
1053 
1054 	extra_ie = session->pSchBeaconFrameEnd + n_bytes;
1055 	extra_ie_offset = n_bytes;
1056 
1057 	/*
1058 	 * Max size left to append additional IE.= (MAX beacon size - TIM IE -
1059 	 * beacon fix size (bcn_1 + header) - beacon variable size (bcn_1).
1060 	 */
1061 	bcn_size_left = SIR_MAX_BEACON_SIZE - tim_size -
1062 				session->schBeaconOffsetBegin -
1063 				(uint16_t)n_bytes;
1064 
1065 	/* TODO: Append additional IE here. */
1066 	if (addn_ielen > 0)
1067 		sch_append_addn_ie(mac_ctx, session,
1068 				   session->pSchBeaconFrameEnd + n_bytes,
1069 				   bcn_size_left, &n_bytes,
1070 				   addn_ie, addn_ielen);
1071 
1072 	session->schBeaconOffsetEnd = (uint16_t) n_bytes;
1073 	extra_ie_len = n_bytes - extra_ie_offset;
1074 	/* Get the p2p Ie Offset */
1075 	status = sch_get_p2p_ie_offset(extra_ie, extra_ie_len, &p2p_ie_offset);
1076 	if (QDF_STATUS_SUCCESS == status)
1077 		/* Update the P2P Ie Offset */
1078 		mac_ctx->sch.p2p_ie_offset =
1079 			session->schBeaconOffsetBegin + tim_size +
1080 			extra_ie_offset + p2p_ie_offset;
1081 	else
1082 		mac_ctx->sch.p2p_ie_offset = 0;
1083 
1084 	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 HT %d VHT %d HE %d EHT %d",
1085 		 session->vdev_id, offset, session->schBeaconOffsetBegin,
1086 		 mac_ctx->sch.csa_count_offset, mac_ctx->sch.ecsa_count_offset,
1087 		 bcn_size_left, addn_ielen, session->schBeaconOffsetEnd,
1088 		 bcn_2->HTCaps.present, bcn_2->VHTCaps.present,
1089 		 bcn_2->he_cap.present, bcn_2->eht_cap.present);
1090 	if (mac_ctx->sch.ecsa_count_offset || mac_ctx->sch.csa_count_offset) {
1091 		wlan_reg_read_current_country(mac_ctx->psoc, reg_cc);
1092 		pe_debug("ECSA/CSA : country:%s chan:%d freq %d width:%d reg:%d off:%d count %d mode %d",
1093 			 reg_cc, session->gLimChannelSwitch.primaryChannel,
1094 			 session->gLimChannelSwitch.sw_target_freq,
1095 			 session->gLimChannelSwitch.ch_width,
1096 			 bcn_2->ext_chan_switch_ann.present ?
1097 			 bcn_2->ext_chan_switch_ann.new_reg_class : 0,
1098 			 session->gLimChannelSwitch.sec_ch_offset,
1099 			 session->gLimChannelSwitch.switchCount,
1100 			 session->gLimChannelSwitch.switchMode);
1101 	}
1102 	mac_ctx->sch.beacon_changed = 1;
1103 	status = QDF_STATUS_SUCCESS;
1104 
1105 free_and_exit:
1106 	qdf_mem_free(bcn_1);
1107 	qdf_mem_free(bcn_2);
1108 	qdf_mem_free(wsc_prb_res);
1109 	qdf_mem_free(addn_ie);
1110 	qdf_mem_free(transmit_power_env);
1111 
1112 	return status;
1113 }
1114 
1115 QDF_STATUS
lim_update_probe_rsp_template_ie_bitmap_beacon1(struct mac_context * mac,tDot11fBeacon1 * beacon1,struct pe_session * pe_session)1116 lim_update_probe_rsp_template_ie_bitmap_beacon1(struct mac_context *mac,
1117 						tDot11fBeacon1 *beacon1,
1118 						struct pe_session *pe_session)
1119 {
1120 	uint32_t *DefProbeRspIeBitmap;
1121 	tDot11fProbeResponse *prb_rsp;
1122 
1123 	if (!pe_session) {
1124 		pe_debug("PESession is null!");
1125 		return QDF_STATUS_E_FAILURE;
1126 	}
1127 	DefProbeRspIeBitmap = &pe_session->DefProbeRspIeBitmap[0];
1128 	prb_rsp = &pe_session->probeRespFrame;
1129 	prb_rsp->BeaconInterval = beacon1->BeaconInterval;
1130 	qdf_mem_copy((void *)&prb_rsp->Capabilities,
1131 		     (void *)&beacon1->Capabilities,
1132 		     sizeof(beacon1->Capabilities));
1133 
1134 	/* SSID */
1135 	if (beacon1->SSID.present) {
1136 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, WLAN_ELEMID_SSID);
1137 		/* populating it, because probe response has to go with SSID even in hidden case */
1138 		populate_dot11f_ssid(mac, &pe_session->ssId, &prb_rsp->SSID);
1139 	}
1140 	/* supported rates */
1141 	if (beacon1->SuppRates.present) {
1142 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, WLAN_ELEMID_RATES);
1143 		qdf_mem_copy((void *)&prb_rsp->SuppRates,
1144 			     (void *)&beacon1->SuppRates,
1145 			     sizeof(beacon1->SuppRates));
1146 
1147 	}
1148 	/* DS Parameter set */
1149 	if (beacon1->DSParams.present) {
1150 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1151 					WLAN_ELEMID_DSPARMS);
1152 		qdf_mem_copy((void *)&prb_rsp->DSParams,
1153 			     (void *)&beacon1->DSParams,
1154 			     sizeof(beacon1->DSParams));
1155 
1156 	}
1157 
1158 	return QDF_STATUS_SUCCESS;
1159 }
1160 
lim_update_probe_rsp_template_ie_bitmap_beacon2(struct mac_context * mac,tDot11fBeacon2 * beacon2,uint32_t * DefProbeRspIeBitmap,tDot11fProbeResponse * prb_rsp)1161 void lim_update_probe_rsp_template_ie_bitmap_beacon2(struct mac_context *mac,
1162 						     tDot11fBeacon2 *beacon2,
1163 						     uint32_t *DefProbeRspIeBitmap,
1164 						     tDot11fProbeResponse *prb_rsp)
1165 {
1166 	uint8_t i;
1167 	uint16_t num_tpe = beacon2->num_transmit_power_env;
1168 
1169 	if (beacon2->Country.present) {
1170 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, WLAN_ELEMID_COUNTRY);
1171 		qdf_mem_copy((void *)&prb_rsp->Country,
1172 			     (void *)&beacon2->Country,
1173 			     sizeof(beacon2->Country));
1174 
1175 	}
1176 	/* Power constraint */
1177 	if (beacon2->PowerConstraints.present) {
1178 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1179 					WLAN_ELEMID_PWRCNSTR);
1180 		qdf_mem_copy((void *)&prb_rsp->PowerConstraints,
1181 			     (void *)&beacon2->PowerConstraints,
1182 			     sizeof(beacon2->PowerConstraints));
1183 
1184 	}
1185 	/* Channel Switch Annoouncement WLAN_ELEMID_CHANSWITCHANN */
1186 	if (beacon2->ChanSwitchAnn.present) {
1187 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1188 					WLAN_ELEMID_CHANSWITCHANN);
1189 		qdf_mem_copy((void *)&prb_rsp->ChanSwitchAnn,
1190 			     (void *)&beacon2->ChanSwitchAnn,
1191 			     sizeof(beacon2->ChanSwitchAnn));
1192 
1193 	}
1194 
1195 	/* EXT Channel Switch Announcement CHNL_EXTENDED_SWITCH_ANN_EID*/
1196 	if (beacon2->ext_chan_switch_ann.present) {
1197 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1198 			WLAN_ELEMID_EXTCHANSWITCHANN);
1199 		qdf_mem_copy((void *)&prb_rsp->ext_chan_switch_ann,
1200 			(void *)&beacon2->ext_chan_switch_ann,
1201 			sizeof(beacon2->ext_chan_switch_ann));
1202 	}
1203 
1204 	/* Supported operating class */
1205 	if (beacon2->SuppOperatingClasses.present) {
1206 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1207 					WLAN_ELEMID_SUPP_OP_CLASS);
1208 		qdf_mem_copy((void *)&prb_rsp->SuppOperatingClasses,
1209 				(void *)&beacon2->SuppOperatingClasses,
1210 				sizeof(beacon2->SuppOperatingClasses));
1211 	}
1212 
1213 #ifdef FEATURE_AP_MCC_CH_AVOIDANCE
1214 	if (beacon2->QComVendorIE.present) {
1215 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1216 					SIR_MAC_QCOM_VENDOR_EID);
1217 		qdf_mem_copy((void *)&prb_rsp->QComVendorIE,
1218 			     (void *)&beacon2->QComVendorIE,
1219 			     sizeof(beacon2->QComVendorIE));
1220 	}
1221 #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
1222 
1223 	/* ERP information */
1224 	if (beacon2->ERPInfo.present) {
1225 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, WLAN_ELEMID_ERP);
1226 		qdf_mem_copy((void *)&prb_rsp->ERPInfo,
1227 			     (void *)&beacon2->ERPInfo,
1228 			     sizeof(beacon2->ERPInfo));
1229 
1230 	}
1231 	/* Extended supported rates */
1232 	if (beacon2->ExtSuppRates.present) {
1233 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1234 					WLAN_ELEMID_XRATES);
1235 		qdf_mem_copy((void *)&prb_rsp->ExtSuppRates,
1236 			     (void *)&beacon2->ExtSuppRates,
1237 			     sizeof(beacon2->ExtSuppRates));
1238 
1239 	}
1240 
1241 	/* WPA */
1242 	if (beacon2->WPA.present) {
1243 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_WPA_EID);
1244 		qdf_mem_copy((void *)&prb_rsp->WPA, (void *)&beacon2->WPA,
1245 			     sizeof(beacon2->WPA));
1246 
1247 	}
1248 
1249 	/* RSN */
1250 	if (beacon2->RSNOpaque.present) {
1251 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, WLAN_ELEMID_RSN);
1252 		qdf_mem_copy((void *)&prb_rsp->RSNOpaque,
1253 			     (void *)&beacon2->RSNOpaque,
1254 			     sizeof(beacon2->RSNOpaque));
1255 	}
1256 
1257 	/* WAPI */
1258 	if (beacon2->WAPI.present) {
1259 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, WLAN_ELEMID_WAPI);
1260 		qdf_mem_copy((void *)&prb_rsp->WAPI,
1261 			     (void *)&beacon2->WAPI,
1262 			     sizeof(beacon2->WAPI));
1263 	}
1264 
1265 	/* EDCA Parameter set */
1266 	if (beacon2->EDCAParamSet.present) {
1267 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1268 					WLAN_ELEMID_EDCAPARMS);
1269 		qdf_mem_copy((void *)&prb_rsp->EDCAParamSet,
1270 			     (void *)&beacon2->EDCAParamSet,
1271 			     sizeof(beacon2->EDCAParamSet));
1272 
1273 	}
1274 	/* Vendor specific - currently no vendor specific IEs added */
1275 	/* Requested IEs - currently we are not processing this will be added later */
1276 	/* HT capability IE */
1277 	if (beacon2->HTCaps.present) {
1278 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1279 					WLAN_ELEMID_HTCAP_ANA);
1280 		qdf_mem_copy((void *)&prb_rsp->HTCaps, (void *)&beacon2->HTCaps,
1281 			     sizeof(beacon2->HTCaps));
1282 	}
1283 	/* HT Info IE */
1284 	if (beacon2->HTInfo.present) {
1285 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, WLAN_ELEMID_HTINFO_ANA);
1286 		qdf_mem_copy((void *)&prb_rsp->HTInfo, (void *)&beacon2->HTInfo,
1287 			     sizeof(beacon2->HTInfo));
1288 	}
1289 	if (beacon2->VHTCaps.present) {
1290 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1291 					WLAN_ELEMID_VHTCAP);
1292 		qdf_mem_copy((void *)&prb_rsp->VHTCaps,
1293 			     (void *)&beacon2->VHTCaps,
1294 			     sizeof(beacon2->VHTCaps));
1295 	}
1296 	if (beacon2->VHTOperation.present) {
1297 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1298 					WLAN_ELEMID_VHTOP);
1299 		qdf_mem_copy((void *)&prb_rsp->VHTOperation,
1300 			     (void *)&beacon2->VHTOperation,
1301 			     sizeof(beacon2->VHTOperation));
1302 	}
1303 
1304 	for (i = 0; i < num_tpe; i++) {
1305 		if (beacon2->transmit_power_env[i].present) {
1306 			set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1307 						WLAN_ELEMID_VHT_TX_PWR_ENVLP);
1308 			qdf_mem_copy((void *)&prb_rsp->transmit_power_env[i],
1309 				     (void *)&beacon2->transmit_power_env[i],
1310 				     sizeof(beacon2->transmit_power_env[i]));
1311 		}
1312 	}
1313 	prb_rsp->num_transmit_power_env = num_tpe;
1314 
1315 	if (beacon2->VHTExtBssLoad.present) {
1316 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1317 					WLAN_ELEMID_EXT_BSS_LOAD);
1318 		qdf_mem_copy((void *)&prb_rsp->VHTExtBssLoad,
1319 			     (void *)&beacon2->VHTExtBssLoad,
1320 			     sizeof(beacon2->VHTExtBssLoad));
1321 	}
1322 	/* WMM IE */
1323 	if (beacon2->WMMParams.present) {
1324 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_WPA_EID);
1325 		qdf_mem_copy((void *)&prb_rsp->WMMParams,
1326 			     (void *)&beacon2->WMMParams,
1327 			     sizeof(beacon2->WMMParams));
1328 	}
1329 	/* WMM capability - most of the case won't be present */
1330 	if (beacon2->WMMCaps.present) {
1331 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_WPA_EID);
1332 		qdf_mem_copy((void *)&prb_rsp->WMMCaps,
1333 			     (void *)&beacon2->WMMCaps,
1334 			     sizeof(beacon2->WMMCaps));
1335 	}
1336 
1337 	/* QCN IE - only for ll sap */
1338 	if (beacon2->qcn_ie.present) {
1339 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1340 					WLAN_ELEMID_VENDOR);
1341 		qdf_mem_copy((void *)&prb_rsp->qcn_ie,
1342 			     (void *)&beacon2->qcn_ie,
1343 			     sizeof(beacon2->qcn_ie));
1344 	}
1345 
1346 	/* Extended Capability */
1347 	if (beacon2->ExtCap.present) {
1348 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, DOT11F_EID_EXTCAP);
1349 		qdf_mem_copy((void *)&prb_rsp->ExtCap,
1350 			     (void *)&beacon2->ExtCap,
1351 			     sizeof(beacon2->ExtCap));
1352 	}
1353 
1354 	if (beacon2->he_cap.present) {
1355 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1356 					DOT11F_EID_HE_CAP);
1357 		qdf_mem_copy((void *)&prb_rsp->he_cap,
1358 			     (void *)&beacon2->he_cap,
1359 			     sizeof(beacon2->he_cap));
1360 	}
1361 	if (beacon2->he_op.present) {
1362 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1363 					DOT11F_EID_HE_OP);
1364 		qdf_mem_copy((void *)&prb_rsp->he_op,
1365 			     (void *)&beacon2->he_op,
1366 			     sizeof(beacon2->he_op));
1367 	}
1368 
1369 	if (beacon2->spatial_reuse.present) {
1370 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1371 					DOT11F_EID_SPATIAL_REUSE);
1372 		qdf_mem_copy((void *)&prb_rsp->spatial_reuse,
1373 			     (void *)&beacon2->spatial_reuse,
1374 			     sizeof(beacon2->spatial_reuse));
1375 	}
1376 
1377 	if (beacon2->he_6ghz_band_cap.present) {
1378 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1379 					DOT11F_EID_HE_6GHZ_BAND_CAP);
1380 		qdf_mem_copy((void *)&prb_rsp->he_6ghz_band_cap,
1381 			     (void *)&beacon2->he_6ghz_band_cap,
1382 			     sizeof(beacon2->he_6ghz_band_cap));
1383 	}
1384 
1385 	if (beacon2->eht_cap.present) {
1386 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1387 					DOT11F_EID_EHT_CAP);
1388 		qdf_mem_copy((void *)&prb_rsp->eht_cap,
1389 			     (void *)&beacon2->eht_cap,
1390 			     sizeof(beacon2->eht_cap));
1391 	}
1392 
1393 	if (beacon2->eht_op.present) {
1394 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1395 					DOT11F_EID_EHT_OP);
1396 		qdf_mem_copy((void *)&prb_rsp->eht_op,
1397 			     (void *)&beacon2->eht_op,
1398 			     sizeof(beacon2->eht_op));
1399 	}
1400 
1401 	if (beacon2->mlo_ie.present) {
1402 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1403 					DOT11F_EID_MLO_IE);
1404 		qdf_mem_copy((void *)&prb_rsp->mlo_ie,
1405 			     (void *)&beacon2->mlo_ie,
1406 			     sizeof(beacon2->mlo_ie));
1407 	}
1408 
1409 	if (beacon2->reduced_neighbor_report.present) {
1410 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1411 					DOT11F_EID_REDUCED_NEIGHBOR_REPORT);
1412 		qdf_mem_copy((void *)&prb_rsp->reduced_neighbor_report,
1413 			     (void *)&beacon2->reduced_neighbor_report,
1414 			     sizeof(beacon2->reduced_neighbor_report));
1415 	}
1416 
1417 	if (beacon2->TPCReport.present) {
1418 		set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
1419 					WLAN_ELEMID_TPCREP);
1420 		qdf_mem_copy((void *)&prb_rsp->TPCReport,
1421 			     (void *)&beacon2->TPCReport,
1422 			     sizeof(beacon2->TPCReport));
1423 	}
1424 
1425 }
1426 
set_probe_rsp_ie_bitmap(uint32_t * IeBitmap,uint32_t pos)1427 void set_probe_rsp_ie_bitmap(uint32_t *IeBitmap, uint32_t pos)
1428 {
1429 	uint32_t index, temp;
1430 
1431 	index = pos >> 5;
1432 	if (index >= 8) {
1433 		return;
1434 	}
1435 	temp = IeBitmap[index];
1436 
1437 	temp |= 1 << (pos & 0x1F);
1438 
1439 	IeBitmap[index] = temp;
1440 }
1441 
1442 /**
1443  * write_beacon_to_memory() - send the beacon to the wma
1444  * @mac: pointer to mac structure
1445  * @size: Size of the beacon to write to memory
1446  * @length: Length field of the beacon to write to memory
1447  * @pe_session: pe session
1448  * @reason: beacon update reason
1449  *
1450  * return: success: QDF_STATUS_SUCCESS failure: QDF_STATUS_E_FAILURE
1451  */
write_beacon_to_memory(struct mac_context * mac,uint16_t size,uint16_t length,struct pe_session * pe_session,enum sir_bcn_update_reason reason)1452 static QDF_STATUS write_beacon_to_memory(struct mac_context *mac, uint16_t size,
1453 					 uint16_t length,
1454 					 struct pe_session *pe_session,
1455 					 enum sir_bcn_update_reason reason)
1456 {
1457 	uint16_t i;
1458 	tpAniBeaconStruct pBeacon;
1459 	QDF_STATUS status;
1460 
1461 	/* copy end of beacon only if length > 0 */
1462 	if (length > 0) {
1463 		if (size + pe_session->schBeaconOffsetEnd >
1464 		    SIR_MAX_BEACON_SIZE) {
1465 			pe_err("beacon tmp fail size %d BeaconOffsetEnd %d",
1466 			       size, pe_session->schBeaconOffsetEnd);
1467 			return QDF_STATUS_E_FAILURE;
1468 		}
1469 		for (i = 0; i < pe_session->schBeaconOffsetEnd; i++)
1470 			pe_session->pSchBeaconFrameBegin[size++] =
1471 				pe_session->pSchBeaconFrameEnd[i];
1472 	}
1473 	/* Update the beacon length */
1474 	pBeacon = (tpAniBeaconStruct) pe_session->pSchBeaconFrameBegin;
1475 	/* Do not include the beaconLength indicator itself */
1476 	if (length == 0) {
1477 		pBeacon->beaconLength = 0;
1478 		/* Dont copy entire beacon, Copy length field alone */
1479 		size = 4;
1480 	} else
1481 		pBeacon->beaconLength = (uint32_t) size - sizeof(uint32_t);
1482 
1483 	if (!mac->sch.beacon_changed)
1484 		return QDF_STATUS_E_FAILURE;
1485 
1486 	status = sch_send_beacon_req(mac, pe_session->pSchBeaconFrameBegin,
1487 				     size, pe_session, reason);
1488 	if (QDF_IS_STATUS_ERROR(status))
1489 		pe_err("sch_send_beacon_req() returned an error %d, size %d",
1490 		       status, size);
1491 	mac->sch.beacon_changed = 0;
1492 
1493 	return status;
1494 }
1495 
1496 /**
1497  * sch_generate_tim
1498  *
1499  * FUNCTION:
1500  * Generate TIM
1501  *
1502  * LOGIC:
1503  *
1504  * ASSUMPTIONS:
1505  *
1506  * NOTE:
1507  *
1508  * @param mac pointer to global mac structure
1509  * @param **pPtr pointer to the buffer, where the TIM bit is to be written.
1510  * @param *timLength pointer to limLength, which needs to be returned.
1511  * @return None
1512  */
sch_generate_tim(struct mac_context * mac,uint8_t ** pPtr,uint16_t * timLength,uint8_t dtimPeriod)1513 void sch_generate_tim(struct mac_context *mac, uint8_t **pPtr, uint16_t *timLength,
1514 		      uint8_t dtimPeriod)
1515 {
1516 	uint8_t *ptr = *pPtr;
1517 	uint32_t val = 0;
1518 	uint32_t minAid = 1;    /* Always start with AID 1 as minimum */
1519 	uint32_t maxAid = HAL_NUM_STA;
1520 	/* Generate partial virtual bitmap */
1521 	uint8_t N1 = minAid / 8;
1522 	uint8_t N2 = maxAid / 8;
1523 
1524 	if (N1 & 1)
1525 		N1--;
1526 
1527 	*timLength = N2 - N1 + 4;
1528 	val = dtimPeriod;
1529 
1530 	/*
1531 	 * Write 0xFF to firmware's field to detect firmware's mal-function
1532 	 * early. DTIM count and bitmap control usually cannot be 0xFF, so it
1533 	 * is easy to know that firmware never updated DTIM count/bitmap control
1534 	 * field after host driver downloaded beacon template if end-user complaints
1535 	 * that DTIM count and bitmapControl is 0xFF.
1536 	 */
1537 	*ptr++ = WLAN_ELEMID_TIM;
1538 	*ptr++ = (uint8_t) (*timLength);
1539 	/* location for dtimCount. will be filled in by FW. */
1540 	*ptr++ = 0xFF;
1541 	*ptr++ = (uint8_t) val;
1542 	/* location for bitmap control. will be filled in by FW. */
1543 	*ptr++ = 0xFF;
1544 	ptr += (N2 - N1 + 1);
1545 
1546 	*pPtr = ptr;
1547 }
1548 
sch_process_pre_beacon_ind(struct mac_context * mac,struct scheduler_msg * limMsg,enum sir_bcn_update_reason reason)1549 QDF_STATUS sch_process_pre_beacon_ind(struct mac_context *mac,
1550 				      struct scheduler_msg *limMsg,
1551 				      enum sir_bcn_update_reason reason)
1552 {
1553 	struct beacon_gen_params *pMsg = limMsg->bodyptr;
1554 	uint32_t beaconSize;
1555 	struct pe_session *pe_session;
1556 	uint8_t sessionId;
1557 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
1558 
1559 	pe_session = pe_find_session_by_bssid(mac, pMsg->bssid, &sessionId);
1560 	if (!pe_session) {
1561 		pe_err("session lookup fails");
1562 		goto end;
1563 	}
1564 
1565 	beaconSize = pe_session->schBeaconOffsetBegin;
1566 
1567 	/* If SME is not in normal mode, no need to generate beacon */
1568 	if (pe_session->limSmeState != eLIM_SME_NORMAL_STATE) {
1569 		pe_debug("PreBeaconInd received in invalid state: %d",
1570 			 pe_session->limSmeState);
1571 		goto end;
1572 	}
1573 
1574 	switch (GET_LIM_SYSTEM_ROLE(pe_session)) {
1575 	case eLIM_AP_ROLE: {
1576 		uint8_t *ptr =
1577 			&pe_session->pSchBeaconFrameBegin[pe_session->
1578 							     schBeaconOffsetBegin];
1579 		uint16_t timLength = 0;
1580 
1581 		if (pe_session->statypeForBss == STA_ENTRY_SELF) {
1582 			sch_generate_tim(mac, &ptr, &timLength,
1583 					 pe_session->dtimPeriod);
1584 			beaconSize += 2 + timLength;
1585 			status =
1586 			    write_beacon_to_memory(mac, (uint16_t) beaconSize,
1587 						   (uint16_t) beaconSize,
1588 						   pe_session, reason);
1589 		} else
1590 			pe_err("can not send beacon for PEER session entry");
1591 			}
1592 			break;
1593 
1594 	default:
1595 		pe_err("Error-PE has Receive PreBeconGenIndication when System is in %d role",
1596 		       GET_LIM_SYSTEM_ROLE(pe_session));
1597 	}
1598 
1599 end:
1600 	qdf_mem_free(pMsg);
1601 
1602 	return status;
1603 }
1604