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