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