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_process.cc contains beacon processing 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 35 #include "cfg_ucfg_api.h" 36 #include "lim_api.h" 37 #include "utils_api.h" 38 #include "sch_api.h" 39 40 #include "lim_utils.h" 41 #include "lim_send_messages.h" 42 #include "rrm_api.h" 43 #include "lim_mlo.h" 44 45 #ifdef FEATURE_WLAN_DIAG_SUPPORT 46 #include "host_diag_core_log.h" 47 #endif /* FEATURE_WLAN_DIAG_SUPPORT */ 48 49 #include "wma.h" 50 51 #include "wlan_lmac_if_def.h" 52 #include "wlan_reg_services_api.h" 53 #include "wlan_mlo_mgr_sta.h" 54 #include "wlan_mlme_main.h" 55 #include <wlan_mlo_mgr_link_switch.h> 56 57 static void 58 ap_beacon_process_5_ghz(struct mac_context *mac_ctx, uint8_t *rx_pkt_info, 59 tpSchBeaconStruct bcn_struct, 60 tpUpdateBeaconParams bcn_prm, struct pe_session *session, 61 uint32_t phy_mode) 62 { 63 tpSirMacMgmtHdr mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); 64 65 if (!session->htCapability) 66 return; 67 68 if (bcn_struct->chan_freq != session->curr_op_freq) 69 return; 70 71 /* 11a (non HT) AP overlaps or */ 72 /* HT AP with HT op mode as mixed overlaps. */ 73 /* HT AP with HT op mode as overlap legacy overlaps. */ 74 if (!bcn_struct->HTInfo.present 75 || (eSIR_HT_OP_MODE_MIXED == bcn_struct->HTInfo.opMode) 76 || (eSIR_HT_OP_MODE_OVERLAP_LEGACY == bcn_struct->HTInfo.opMode)) { 77 lim_update_overlap_sta_param(mac_ctx, mac_hdr->bssId, 78 &(session->gLimOverlap11aParams)); 79 80 if (session->gLimOverlap11aParams.numSta 81 && !session->gLimOverlap11aParams.protectionEnabled) { 82 lim_update_11a_protection(mac_ctx, true, true, 83 bcn_prm, session); 84 } 85 return; 86 } 87 /* HT AP with HT20 op mode overlaps. */ 88 if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT != bcn_struct->HTInfo.opMode) 89 return; 90 91 lim_update_overlap_sta_param(mac_ctx, mac_hdr->bssId, 92 &(session->gLimOverlapHt20Params)); 93 94 if (session->gLimOverlapHt20Params.numSta 95 && !session->gLimOverlapHt20Params.protectionEnabled) 96 lim_enable_ht20_protection(mac_ctx, true, true, 97 bcn_prm, session); 98 } 99 100 static void 101 ap_beacon_process_24_ghz(struct mac_context *mac_ctx, uint8_t *rx_pkt_info, 102 tpSchBeaconStruct bcn_struct, 103 tpUpdateBeaconParams bcn_prm, struct pe_session *session, 104 uint32_t phy_mode) 105 { 106 tpSirMacMgmtHdr mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); 107 bool tmp_exp = false; 108 /* We are 11G AP. */ 109 if ((phy_mode == WNI_CFG_PHY_MODE_11G) && 110 (false == session->htCapability)) { 111 if (bcn_struct->chan_freq != session->curr_op_freq) 112 return; 113 114 tmp_exp = (!bcn_struct->erpPresent && 115 !bcn_struct->HTInfo.present) || 116 /* if erp not present then 11B AP overlapping */ 117 (!mac_ctx->mlme_cfg->sta.ignore_peer_erp_info && 118 bcn_struct->erpPresent && 119 (bcn_struct->erpIEInfo.useProtection || 120 bcn_struct->erpIEInfo.nonErpPresent)); 121 if (!tmp_exp) 122 return; 123 #ifdef FEATURE_WLAN_ESE 124 if (wlan_cm_get_ese_assoc(mac_ctx->pdev, session->vdev_id)) 125 pe_info("[INFOLOG]ESE 11g erpPresent=%d useProtection=%d nonErpPresent=%d", 126 bcn_struct->erpPresent, 127 bcn_struct->erpIEInfo.useProtection, 128 bcn_struct->erpIEInfo.nonErpPresent); 129 #endif 130 lim_enable_overlap11g_protection(mac_ctx, bcn_prm, 131 mac_hdr, session); 132 return; 133 } 134 /* handling the case when HT AP has overlapping legacy BSS. */ 135 if (!session->htCapability) 136 return; 137 138 if (bcn_struct->chan_freq != session->curr_op_freq) 139 return; 140 141 tmp_exp = (!bcn_struct->erpPresent && !bcn_struct->HTInfo.present) || 142 /* if erp not present then 11B AP overlapping */ 143 (!mac_ctx->mlme_cfg->sta.ignore_peer_erp_info && 144 bcn_struct->erpPresent && 145 (bcn_struct->erpIEInfo.useProtection || 146 bcn_struct->erpIEInfo.nonErpPresent)); 147 if (tmp_exp) { 148 #ifdef FEATURE_WLAN_ESE 149 if (wlan_cm_get_ese_assoc(mac_ctx->pdev, session->vdev_id)) { 150 pe_info("[INFOLOG]ESE 11g erpPresent=%d useProtection=%d nonErpPresent=%d", 151 bcn_struct->erpPresent, 152 bcn_struct->erpIEInfo.useProtection, 153 bcn_struct->erpIEInfo.nonErpPresent); 154 } 155 #endif 156 lim_enable_overlap11g_protection(mac_ctx, bcn_prm, 157 mac_hdr, session); 158 } 159 /* 11g device overlaps */ 160 tmp_exp = bcn_struct->erpPresent 161 && !(bcn_struct->erpIEInfo.useProtection 162 || bcn_struct->erpIEInfo.nonErpPresent) 163 && !(bcn_struct->HTInfo.present); 164 if (tmp_exp) { 165 lim_update_overlap_sta_param(mac_ctx, mac_hdr->bssId, 166 &(session->gLimOverlap11gParams)); 167 168 if (session->gLimOverlap11gParams.numSta 169 && !session->gLimOverlap11gParams.protectionEnabled) 170 lim_enable_ht_protection_from11g(mac_ctx, true, true, 171 bcn_prm, session); 172 } 173 /* ht device overlaps. 174 * here we will check for HT related devices only which might need 175 * protection. check for 11b and 11g is already done in the previous 176 * blocks. so we will not check for HT operating mode as MIXED. 177 */ 178 if (!bcn_struct->HTInfo.present) 179 return; 180 181 /* 182 * if we are not already in mixed mode or legacy mode as HT operating 183 * mode and received beacon has HT operating mode as legacy then we need 184 * to enable protection from 11g station. we don't need protection from 185 * 11b because if that's needed then our operating mode would have 186 * already been set to legacy in the previous blocks. 187 */ 188 if ((eSIR_HT_OP_MODE_OVERLAP_LEGACY == bcn_struct->HTInfo.opMode) && 189 !mac_ctx->mlme_cfg->sap_protection_cfg.ignore_peer_ht_opmode) { 190 if (eSIR_HT_OP_MODE_OVERLAP_LEGACY == mac_ctx->lim.gHTOperMode 191 || eSIR_HT_OP_MODE_MIXED == mac_ctx->lim.gHTOperMode) 192 return; 193 lim_update_overlap_sta_param(mac_ctx, mac_hdr->bssId, 194 &(session->gLimOverlap11gParams)); 195 if (session->gLimOverlap11gParams.numSta 196 && !session->gLimOverlap11gParams.protectionEnabled) 197 lim_enable_ht_protection_from11g(mac_ctx, true, true, 198 bcn_prm, session); 199 return; 200 } 201 202 if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT == bcn_struct->HTInfo.opMode) { 203 lim_update_overlap_sta_param(mac_ctx, mac_hdr->bssId, 204 &(session->gLimOverlapHt20Params)); 205 if (session->gLimOverlapHt20Params.numSta 206 && !session->gLimOverlapHt20Params.protectionEnabled) 207 lim_enable_ht20_protection(mac_ctx, true, true, 208 bcn_prm, session); 209 } 210 } 211 212 /** 213 * ap_beacon_process() - processes incoming beacons 214 * 215 * @mac_ctx: mac global context 216 * @rx_pkt_info: incoming beacon packet 217 * @bcn_struct: beacon struct 218 * @bcn_prm: beacon params 219 * @session: pe session entry 220 * 221 * Return: void 222 */ 223 static void 224 ap_beacon_process(struct mac_context *mac_ctx, uint8_t *rx_pkt_info, 225 tpSchBeaconStruct bcn_struct, 226 tpUpdateBeaconParams bcn_prm, struct pe_session *session) 227 { 228 uint32_t phy_mode; 229 enum reg_wifi_band rf_band = REG_BAND_UNKNOWN; 230 /* Get RF band from session */ 231 rf_band = session->limRFBand; 232 233 lim_get_phy_mode(mac_ctx, &phy_mode, session); 234 235 if (REG_BAND_5G == rf_band) 236 ap_beacon_process_5_ghz(mac_ctx, rx_pkt_info, bcn_struct, 237 bcn_prm, session, phy_mode); 238 else if (REG_BAND_2G == rf_band) 239 ap_beacon_process_24_ghz(mac_ctx, rx_pkt_info, bcn_struct, 240 bcn_prm, session, phy_mode); 241 } 242 243 /* -------------------------------------------------------------------- */ 244 245 /* 246 * sch_bcn_process_sta() - Process the received beacon frame for sta 247 * @mac_ctx: mac_ctx 248 * @bcn: beacon struct 249 * @rx_pkt_info: received packet info 250 * @session: pe session pointer 251 * @beaconParams: update beacon params 252 * @sendProbeReq: out flag to indicate if probe rsp is to be sent 253 * @pMh: mac header 254 * 255 * Process the received beacon frame for sta 256 * 257 * Return: success of failure of operation 258 */ 259 static bool 260 sch_bcn_process_sta(struct mac_context *mac_ctx, 261 tpSchBeaconStruct bcn, 262 uint8_t *rx_pkt_info, 263 struct pe_session *session, 264 tUpdateBeaconParams *beaconParams, 265 uint8_t *sendProbeReq, tpSirMacMgmtHdr pMh) 266 { 267 uint32_t bi; 268 tpDphHashNode sta = NULL; 269 QDF_STATUS status; 270 271 /* 272 * This handles two cases: 273 * -- Infra STA receiving beacons from AP 274 */ 275 276 /** 277 * This is the Beacon received from the AP we're currently associated 278 * with. Check if there are any changes in AP's capabilities 279 */ 280 if (bcn->chan_freq != session->curr_op_freq) { 281 pe_err("Channel Change freq from %d --> %d - Ignoring beacon!", 282 session->curr_op_freq, bcn->chan_freq); 283 return false; 284 } 285 286 /* 287 * Ignore bcn as channel switch IE present and csa offload is enabled, 288 * as in CSA offload enabled case FW will send Event to switch channel 289 */ 290 if (bcn->channelSwitchPresent && wma_is_csa_offload_enabled()) { 291 pe_err_rl("Ignore bcn as channel switch IE present and csa offload is enabled"); 292 return false; 293 } 294 295 lim_detect_change_in_ap_capabilities(mac_ctx, bcn, session, true); 296 beaconParams->bss_idx = session->vdev_id; 297 qdf_mem_copy((uint8_t *) &session->lastBeaconTimeStamp, 298 (uint8_t *) bcn->timeStamp, sizeof(uint64_t)); 299 session->currentBssBeaconCnt++; 300 if (session->bcon_dtim_period != bcn->tim.dtimPeriod) { 301 session->bcon_dtim_period = bcn->tim.dtimPeriod; 302 lim_send_set_dtim_period(mac_ctx, bcn->tim.dtimPeriod, 303 session); 304 } 305 MTRACE(mac_trace(mac_ctx, TRACE_CODE_RX_MGMT_TSF, 306 session->peSessionId, bcn->timeStamp[0])); 307 MTRACE(mac_trace(mac_ctx, TRACE_CODE_RX_MGMT_TSF, 308 session->peSessionId, bcn->timeStamp[1])); 309 310 /* Read beacon interval session Entry */ 311 bi = session->beaconParams.beaconInterval; 312 if (bi != bcn->beaconInterval) { 313 pe_debug("Beacon interval changed from %d to %d", 314 bcn->beaconInterval, bi); 315 316 bi = bcn->beaconInterval; 317 session->beaconParams.beaconInterval = (uint16_t) bi; 318 beaconParams->paramChangeBitmap |= PARAM_BCN_INTERVAL_CHANGED; 319 beaconParams->beaconInterval = (uint16_t) bi; 320 } 321 322 if (bcn->cfPresent) { 323 if (!cfg_in_range(CFG_CFP_PERIOD, bcn->cfParamSet.cfpPeriod)) { 324 pe_err("Error in setting CFG item CFP Period"); 325 return false; 326 } 327 mac_ctx->mlme_cfg->rates.cfp_period = bcn->cfParamSet.cfpPeriod; 328 } 329 330 /* No need to send DTIM Period and Count to HAL/SMAC */ 331 /* SMAC already parses TIM bit. */ 332 if (bcn->timPresent) { 333 if (cfg_in_range(CFG_DTIM_PERIOD, bcn->tim.dtimPeriod)) 334 mac_ctx->mlme_cfg->sap_cfg.dtim_interval = 335 bcn->tim.dtimPeriod; 336 } 337 338 if (mac_ctx->lim.gLimProtectionControl != 339 MLME_FORCE_POLICY_PROTECTION_DISABLE) 340 lim_decide_sta_protection(mac_ctx, bcn, beaconParams, session); 341 342 if (bcn->erpPresent) { 343 if (bcn->erpIEInfo.barkerPreambleMode) 344 lim_enable_short_preamble(mac_ctx, false, 345 beaconParams, session); 346 else 347 lim_enable_short_preamble(mac_ctx, true, 348 beaconParams, session); 349 } 350 lim_update_short_slot(mac_ctx, bcn, beaconParams, session); 351 352 sta = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER, 353 &session->dph.dphHashTable); 354 if ((bcn->wmeEdcaPresent && session->limWmeEnabled) || 355 (bcn->edcaPresent && session->limQosEnabled)) { 356 if (bcn->edcaParams.qosInfo.count != 357 session->gLimEdcaParamSetCount) { 358 qdf_mem_copy(&sta->qos.peer_edca_params, 359 &bcn->edcaParams, 360 sizeof(bcn->edcaParams)); 361 status = sch_beacon_edca_process(mac_ctx, 362 &bcn->edcaParams, 363 session); 364 if (QDF_IS_STATUS_ERROR(status)) { 365 pe_err("EDCA parameter processing error"); 366 } else if (sta) { 367 /* If needed, downgrade the EDCA parameters */ 368 lim_set_active_edca_params(mac_ctx, 369 session->gLimEdcaParams, session); 370 lim_send_edca_params(mac_ctx, 371 session->gLimEdcaParamsActive, 372 session->vdev_id, false); 373 sch_qos_concurrency_update(); 374 } else { 375 pe_err("Self Entry missing in Hash Table"); 376 } 377 } 378 return true; 379 } 380 381 if ((bcn->qosCapabilityPresent && session->limQosEnabled) 382 && (bcn->qosCapability.qosInfo.count != 383 session->gLimEdcaParamSetCount)) 384 *sendProbeReq = true; 385 386 return true; 387 } 388 389 #ifdef WLAN_FEATURE_11AX_BSS_COLOR 390 static void 391 sch_bcn_update_he_ies(struct mac_context *mac_ctx, tpDphHashNode sta_ds, 392 struct pe_session *session, tpSchBeaconStruct bcn, 393 tpSirMacMgmtHdr mac_hdr) 394 { 395 uint8_t session_bss_col_disabled_flag; 396 bool anything_changed = false; 397 398 if (session->is_session_obss_color_collision_det_enabled) 399 return; 400 401 if (session->he_op.present && bcn->he_op.present) { 402 if (bcn->vendor_he_bss_color_change.present && 403 (session->he_op.bss_color != 404 bcn->vendor_he_bss_color_change.new_color)) { 405 pe_debug("bss color changed from [%d] to [%d]", 406 session->he_op.bss_color, 407 bcn->vendor_he_bss_color_change.new_color); 408 session->he_op.bss_color = 409 bcn->vendor_he_bss_color_change.new_color; 410 anything_changed = true; 411 } 412 session_bss_col_disabled_flag = session->he_op.bss_col_disabled; 413 if (session_bss_col_disabled_flag != 414 bcn->he_op.bss_col_disabled) { 415 pe_debug("color disable flag changed from [%d] to [%d]", 416 session->he_op.bss_col_disabled, 417 bcn->he_op.bss_col_disabled); 418 session->he_op.bss_col_disabled = 419 bcn->he_op.bss_col_disabled; 420 anything_changed = true; 421 } 422 } 423 if (anything_changed) 424 lim_send_he_ie_update(mac_ctx, session); 425 } 426 #else 427 static void 428 sch_bcn_update_he_ies(struct mac_context *mac_ctx, tpDphHashNode sta_ds, 429 struct pe_session *session, tpSchBeaconStruct bcn, 430 tpSirMacMgmtHdr mac_hdr) 431 { 432 return; 433 } 434 #endif 435 436 static void 437 sch_bcn_update_opmode_change(struct mac_context *mac_ctx, tpDphHashNode sta_ds, 438 struct pe_session *session, tpSchBeaconStruct bcn, 439 tpSirMacMgmtHdr mac_hdr) 440 { 441 enum phy_ch_width ch_bw; 442 enum phy_ch_width ch_width = CH_WIDTH_20MHZ; 443 tDot11fIEVHTCaps *vht_caps = NULL; 444 tDot11fIEVHTOperation *vht_op = NULL; 445 uint8_t bcn_vht_chwidth = 0; 446 bool is_40 = false; 447 448 /* 449 * Ignore opmode change during channel change The opmode will be updated 450 * with the beacons on new channel once the AP move to new channel. 451 */ 452 if (session->ch_switch_in_progress) { 453 pe_debug("Ignore opmode change as channel switch is in progress"); 454 return; 455 } 456 if (bcn->eht_op.eht_op_information_present) { 457 pe_debug("Ignore opmode change as there is EHT operation information"); 458 return; 459 } 460 461 if (bcn->VHTCaps.present) { 462 vht_caps = &bcn->VHTCaps; 463 vht_op = &bcn->VHTOperation; 464 } else if (bcn->vendor_vht_ie.VHTCaps.present) { 465 vht_caps = &bcn->vendor_vht_ie.VHTCaps; 466 vht_op = &bcn->vendor_vht_ie.VHTOperation; 467 } 468 if (!session->vhtCapability || 469 !(bcn->OperatingMode.present || 470 (vht_op && vht_op->present && vht_caps))) 471 return; 472 473 is_40 = bcn->HTInfo.present ? 474 bcn->HTInfo.recommendedTxWidthSet : false; 475 476 if (bcn->OperatingMode.present) { 477 lim_update_nss(mac_ctx, sta_ds, bcn->OperatingMode.rxNSS, 478 session); 479 ch_width = bcn->OperatingMode.chanWidth; 480 pe_debug("OMN IE present in bcn/probe rsp, omn_ie_ch_width: %d", 481 ch_width); 482 lim_update_omn_ie_ch_width(session->vdev, ch_width); 483 484 } else { 485 bcn_vht_chwidth = lim_get_vht_ch_width(vht_caps, vht_op, 486 &bcn->HTInfo); 487 ch_width = 488 lim_convert_vht_chwidth_to_phy_chwidth(bcn_vht_chwidth, 489 is_40); 490 } 491 492 lim_update_channel_width(mac_ctx, sta_ds, session, ch_width, &ch_bw); 493 } 494 495 #ifdef WLAN_FEATURE_SR 496 /** 497 * lim_detect_change_in_srp() - Detect change in SRP IE 498 * of the beacon 499 * 500 * @mac_ctx: global mac context 501 * @sta: pointer to sta node 502 * @session: pointer to LIM session 503 * @bcn: beacon from associated AP 504 * 505 * Detect change in SRP IE of the beacon and update the params 506 * accordingly. 507 * 508 * Return: None 509 */ 510 static void lim_detect_change_in_srp(struct mac_context *mac_ctx, 511 tpDphHashNode sta, 512 struct pe_session *session, 513 tpSchBeaconStruct bcn) 514 { 515 tDot11fIEspatial_reuse sr_ie; 516 int32_t ret = 0; 517 518 sr_ie = sta->parsed_ies.srp_ie; 519 if (sr_ie.present || bcn->srp_ie.present) { 520 ret = qdf_mem_cmp(&sr_ie, &bcn->srp_ie, 521 sizeof(tDot11fIEspatial_reuse)); 522 523 if (ret) { 524 /* 525 * If SRP IE has changes, update the new params. 526 */ 527 sta->parsed_ies.srp_ie = bcn->srp_ie; 528 lim_update_vdev_sr_elements(session, sta); 529 530 lim_handle_sr_cap(session->vdev, 531 SR_REASON_CODE_BCN_IE_CHANGE); 532 } 533 } 534 } 535 #else 536 static void lim_detect_change_in_srp(struct mac_context *mac_ctx, 537 tpDphHashNode sta, 538 struct pe_session *session, 539 tpSchBeaconStruct bcn) 540 { 541 } 542 #endif 543 544 static void 545 sch_bcn_process_sta_opmode(struct mac_context *mac_ctx, 546 tpSchBeaconStruct bcn, 547 uint8_t *rx_pkt_info, 548 struct pe_session *session, 549 tUpdateBeaconParams *beaconParams, 550 uint8_t *sendProbeReq, tpSirMacMgmtHdr pMh) 551 { 552 tpDphHashNode sta = NULL; 553 uint16_t aid; 554 555 /* check for VHT capability */ 556 sta = dph_lookup_hash_entry(mac_ctx, pMh->sa, &aid, 557 &session->dph.dphHashTable); 558 if (!sta) 559 return; 560 sch_bcn_update_opmode_change(mac_ctx, sta, session, bcn, pMh); 561 sch_bcn_update_he_ies(mac_ctx, sta, session, bcn, pMh); 562 lim_detect_change_in_srp(mac_ctx, sta, session, bcn); 563 return; 564 } 565 566 /** 567 * get_local_power_constraint_beacon() - extracts local constraint 568 * from beacon 569 * @bcn: beacon structure 570 * @local_constraint: local constraint pointer 571 * @is_power_constraint_abs: is power constraint absolute 572 * 573 * Return: None 574 */ 575 #ifdef FEATURE_WLAN_ESE 576 static void get_local_power_constraint_beacon( 577 tpSchBeaconStruct bcn, 578 int8_t *local_constraint, 579 bool *is_power_constraint_abs) 580 { 581 if (bcn->eseTxPwr.present) { 582 *local_constraint = bcn->eseTxPwr.power_limit; 583 *is_power_constraint_abs = true; 584 } 585 } 586 #else 587 static void get_local_power_constraint_beacon( 588 tpSchBeaconStruct bcn, 589 int8_t *local_constraint, 590 bool *is_power_constraint_abs) 591 { 592 593 } 594 #endif 595 596 static void __sch_beacon_process_for_session(struct mac_context *mac_ctx, 597 tpSchBeaconStruct bcn, 598 uint8_t *rx_pkt_info, 599 struct pe_session *session) 600 { 601 tUpdateBeaconParams beaconParams; 602 uint8_t sendProbeReq = false; 603 tpSirMacMgmtHdr pMh = WMA_GET_RX_MAC_HEADER(rx_pkt_info); 604 int8_t local_constraint = 0; 605 uint32_t chan_freq = 0; 606 struct vdev_mlme_obj *mlme_obj; 607 struct wlan_lmac_if_reg_tx_ops *tx_ops; 608 bool ap_constraint_change = false, tpe_change = false; 609 bool allow_tpc = false; 610 int8_t regMax = 0, maxTxPower = 0; 611 QDF_STATUS status; 612 bool skip_tpe = false, is_sap_go_switched_ch; 613 enum reg_6g_ap_type pwr_type_6g; 614 uint8_t bpcc; 615 bool cu_flag = true; 616 bool is_power_constraint_abs = false; 617 618 if (mlo_is_mld_sta(session->vdev)) { 619 cu_flag = false; 620 status = lim_get_bpcc_from_mlo_ie(bcn, &bpcc); 621 if (QDF_IS_STATUS_SUCCESS(status)) 622 cu_flag = lim_check_cu_happens(session->vdev, bpcc); 623 lim_process_ml_reconfig(mac_ctx, session, rx_pkt_info); 624 } 625 626 if (!cu_flag) 627 return; 628 629 qdf_mem_zero(&beaconParams, sizeof(tUpdateBeaconParams)); 630 beaconParams.paramChangeBitmap = 0; 631 632 if (LIM_IS_STA_ROLE(session)) { 633 is_sap_go_switched_ch = 634 wlan_vdev_mlme_is_sap_go_move_before_sta(session->vdev); 635 if (is_sap_go_switched_ch) 636 policy_mgr_sta_sap_dfs_enforce_scc(mac_ctx->psoc, 637 session->vdev_id); 638 if (false == sch_bcn_process_sta(mac_ctx, bcn, rx_pkt_info, 639 session, &beaconParams, 640 &sendProbeReq, pMh)) 641 return; 642 } 643 644 /* 645 * For vht session, if opermode ie or vht oper IE is present 646 * bandwidth change will be taken care using these vht IEs. 647 */ 648 if (!(session->vhtCapability && (bcn->OperatingMode.present || 649 bcn->VHTOperation.present)) && session->htCapability && 650 bcn->HTInfo.present) 651 lim_update_sta_run_time_ht_switch_chnl_params(mac_ctx, 652 &bcn->HTInfo, session); 653 654 if (LIM_IS_STA_ROLE(session)) 655 sch_bcn_process_sta_opmode(mac_ctx, bcn, rx_pkt_info, session, 656 &beaconParams, &sendProbeReq, pMh); 657 658 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(session->vdev); 659 if (!mlme_obj) { 660 pe_err("vdev component object is NULL"); 661 return; 662 } 663 664 if (!wlan_reg_is_6ghz_chan_freq(bcn->chan_freq)) { 665 skip_tpe = wlan_mlme_skip_tpe(mac_ctx->psoc); 666 } else { 667 if (!bcn->countryInfoParam.countryString[0]) { 668 pe_err("Channel is 6G but country IE not present"); 669 return; 670 } 671 if (bcn->he_op.oper_info_6g_present) { 672 session->ap_defined_power_type_6g = 673 bcn->he_op.oper_info_6g.info.reg_info; 674 if (session->ap_defined_power_type_6g < REG_INDOOR_AP || 675 session->ap_defined_power_type_6g > 676 REG_MAX_SUPP_AP_TYPE) { 677 session->ap_defined_power_type_6g = 678 REG_CURRENT_MAX_AP_TYPE; 679 pe_debug("AP power type is invalid, defaulting to MAX_AP_TYPE"); 680 } 681 } else { 682 pe_debug("AP power type is null, defaulting to MAX_AP_TYPE"); 683 session->ap_defined_power_type_6g = 684 REG_CURRENT_MAX_AP_TYPE; 685 } 686 687 status = wlan_reg_get_best_6g_power_type( 688 mac_ctx->psoc, mac_ctx->pdev, &pwr_type_6g, 689 session->ap_defined_power_type_6g, 690 bcn->chan_freq); 691 if (QDF_IS_STATUS_ERROR(status)) 692 return; 693 694 session->best_6g_power_type = pwr_type_6g; 695 mlme_set_best_6g_power_type(session->vdev, pwr_type_6g); 696 } 697 698 /* 699 * STA LPI + SAP VLP is supported. For this STA should operate in VLP 700 * power level of the SAP. 701 * If STA is operating in VLP power of SAP, do not update STA power. 702 */ 703 if (wlan_reg_is_ext_tpc_supported(mac_ctx->psoc) && 704 !session->sta_follows_sap_power) { 705 tx_ops = wlan_reg_get_tx_ops(mac_ctx->psoc); 706 707 lim_parse_tpe_ie(mac_ctx, session, bcn->transmit_power_env, 708 bcn->num_transmit_power_env, &bcn->he_op, 709 &tpe_change); 710 711 if (mac_ctx->mlme_cfg->sta.allow_tpc_from_ap) { 712 get_local_power_constraint_beacon( 713 bcn, &local_constraint, 714 &is_power_constraint_abs); 715 716 if (mac_ctx->rrm.rrmPEContext.rrmEnable && 717 bcn->powerConstraintPresent) { 718 local_constraint = 719 bcn->localPowerConstraint.localPowerConstraints; 720 is_power_constraint_abs = false; 721 } 722 allow_tpc = true; 723 } 724 725 if (allow_tpc && local_constraint != 726 mlme_obj->reg_tpc_obj.ap_constraint_power) { 727 mlme_obj->reg_tpc_obj.ap_constraint_power = 728 local_constraint; 729 mlme_obj->reg_tpc_obj.is_power_constraint_abs = 730 is_power_constraint_abs; 731 ap_constraint_change = true; 732 } 733 734 if (ap_constraint_change || (tpe_change && !skip_tpe)) { 735 lim_calculate_tpc(mac_ctx, session); 736 737 if (tx_ops->set_tpc_power) 738 tx_ops->set_tpc_power(mac_ctx->psoc, 739 session->vdev_id, 740 &mlme_obj->reg_tpc_obj); 741 } 742 } else if (!session->sta_follows_sap_power) { 743 /* Obtain the Max Tx power for the current regulatory */ 744 regMax = wlan_reg_get_channel_reg_power_for_freq( 745 mac_ctx->pdev, session->curr_op_freq); 746 local_constraint = regMax; 747 748 if (mac_ctx->mlme_cfg->sta.allow_tpc_from_ap) { 749 get_local_power_constraint_beacon( 750 bcn, &local_constraint, 751 &is_power_constraint_abs); 752 753 if (mac_ctx->rrm.rrmPEContext.rrmEnable && 754 bcn->powerConstraintPresent) { 755 local_constraint = regMax; 756 local_constraint -= 757 bcn->localPowerConstraint.localPowerConstraints; 758 is_power_constraint_abs = false; 759 760 } 761 } 762 mlme_obj->reg_tpc_obj.is_power_constraint_abs = 763 is_power_constraint_abs; 764 mlme_obj->reg_tpc_obj.reg_max[0] = regMax; 765 mlme_obj->reg_tpc_obj.ap_constraint_power = local_constraint; 766 mlme_obj->reg_tpc_obj.frequency[0] = session->curr_op_freq; 767 768 maxTxPower = lim_get_max_tx_power(mac_ctx, mlme_obj); 769 770 /* If maxTxPower is increased or decreased */ 771 if (maxTxPower != session->maxTxPower) { 772 pe_debug("New maxTx power %d, old pwr %d", 773 maxTxPower, session->maxTxPower); 774 pe_debug("regMax %d, local %d", regMax, 775 local_constraint); 776 status = lim_send_set_max_tx_power_req(mac_ctx, 777 maxTxPower, 778 session); 779 if (status == QDF_STATUS_SUCCESS) 780 session->maxTxPower = maxTxPower; 781 } 782 } 783 /* Indicate to LIM that Beacon is received */ 784 if (bcn->HTInfo.present) { 785 chan_freq = wlan_reg_legacy_chan_to_freq(mac_ctx->pdev, 786 bcn->HTInfo.primaryChannel); 787 lim_received_hb_handler(mac_ctx, chan_freq, session); 788 } else 789 lim_received_hb_handler(mac_ctx, bcn->chan_freq, session); 790 791 /* 792 * I don't know if any additional IE is required here. Currently, not 793 * include addIE. 794 */ 795 if (sendProbeReq) 796 lim_send_probe_req_mgmt_frame(mac_ctx, &session->ssId, 797 session->bssId, session->curr_op_freq, 798 session->self_mac_addr, session->dot11mode, NULL, NULL); 799 800 if ((false == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running) 801 && beaconParams.paramChangeBitmap) { 802 pe_debug("Beacon for session[%d] got changed param change bitmap: 0x%x", 803 session->peSessionId, beaconParams.paramChangeBitmap); 804 lim_send_beacon_params(mac_ctx, &beaconParams, session); 805 } 806 807 if ((session->opmode == QDF_P2P_CLIENT_MODE) && 808 session->send_p2p_conf_frame) { 809 lim_p2p_oper_chan_change_confirm_action_frame(mac_ctx, 810 session->bssId, 811 session); 812 session->send_p2p_conf_frame = false; 813 } 814 815 lim_process_beacon_eht(mac_ctx, session, bcn); 816 lim_process_bcn_prb_rsp_t2lm(mac_ctx, session, bcn); 817 } 818 819 #ifdef WLAN_FEATURE_11AX_BSS_COLOR 820 static void ap_update_bss_color_info(struct mac_context *mac_ctx, 821 struct pe_session *session, 822 uint8_t bss_color) 823 { 824 if (!session) 825 return; 826 827 if (bss_color < 1 || bss_color > 63) { 828 pe_warn("Invalid BSS color"); 829 return; 830 } 831 832 session->bss_color_info[bss_color - 1].seen_count++; 833 session->bss_color_info[bss_color - 1].timestamp = 834 qdf_get_system_timestamp(); 835 } 836 837 static uint8_t ap_get_new_bss_color(struct mac_context *mac_ctx, struct pe_session *session) 838 { 839 int i; 840 uint8_t new_bss_color; 841 struct bss_color_info color_info; 842 qdf_time_t cur_timestamp; 843 844 if (!session) 845 return 0; 846 847 color_info = session->bss_color_info[0]; 848 new_bss_color = 0; 849 cur_timestamp = qdf_get_system_timestamp(); 850 for (i = 1; i < MAX_BSS_COLOR_VALUE; i++) { 851 if (session->bss_color_info[i].seen_count == 0) { 852 new_bss_color = i + 1; 853 return new_bss_color; 854 } 855 856 if (color_info.seen_count > 857 session->bss_color_info[i].seen_count && 858 (cur_timestamp - session->bss_color_info[i]. 859 timestamp) > TIME_BEACON_NOT_UPDATED) { 860 color_info = session->bss_color_info[i]; 861 new_bss_color = i + 1; 862 } 863 } 864 pe_debug("new bss color: %d", new_bss_color); 865 return new_bss_color; 866 } 867 868 static void sch_check_bss_color_ie(struct mac_context *mac_ctx, 869 struct pe_session *ap_session, 870 tSchBeaconStruct *bcn, 871 tUpdateBeaconParams *bcn_prm) 872 { 873 /* check bss color in the beacon */ 874 if (ap_session->he_op.present && !ap_session->he_op.bss_color) { 875 if (bcn->he_op.present && 876 (bcn->he_op.bss_color == 877 ap_session->he_op.bss_color)) { 878 ap_session->he_op.bss_col_disabled = 1; 879 bcn_prm->paramChangeBitmap |= 880 PARAM_BSS_COLOR_CHANGED; 881 ap_session->he_bss_color_change.countdown = 882 BSS_COLOR_SWITCH_COUNTDOWN; 883 ap_session->he_bss_color_change.new_color = 884 ap_get_new_bss_color(mac_ctx, 885 ap_session); 886 ap_session->he_op.bss_color = ap_session-> 887 he_bss_color_change.new_color; 888 bcn_prm->bss_color = ap_session->he_op.bss_color; 889 bcn_prm->bss_color_disabled = 890 ap_session->he_op.bss_col_disabled; 891 ap_session->bss_color_changing = 1; 892 } else { 893 /* update info for the bss color */ 894 if (bcn->he_op.present) 895 ap_update_bss_color_info(mac_ctx, 896 ap_session, 897 bcn->he_op.bss_color); 898 } 899 } 900 } 901 902 #else 903 static void sch_check_bss_color_ie(struct mac_context *mac_ctx, 904 struct pe_session *ap_session, 905 tSchBeaconStruct *bcn, 906 tUpdateBeaconParams *bcn_prm) 907 { 908 } 909 #endif 910 911 void sch_beacon_process_for_ap(struct mac_context *mac_ctx, 912 uint8_t session_id, 913 uint8_t *rx_pkt_info, 914 tSchBeaconStruct *bcn) 915 { 916 struct pe_session *ap_session; 917 tUpdateBeaconParams bcn_prm; 918 919 if (!bcn || !rx_pkt_info) { 920 pe_debug("bcn %pK or rx_pkt_info %pKis NULL", 921 bcn, rx_pkt_info); 922 return; 923 } 924 925 ap_session = pe_find_session_by_session_id(mac_ctx, session_id); 926 if (!ap_session) 927 return; 928 929 if (!LIM_IS_AP_ROLE(ap_session)) 930 return; 931 932 qdf_mem_zero(&bcn_prm, sizeof(tUpdateBeaconParams)); 933 bcn_prm.paramChangeBitmap = 0; 934 935 bcn_prm.bss_idx = ap_session->vdev_id; 936 937 if (!ap_session->is_session_obss_color_collision_det_enabled) 938 sch_check_bss_color_ie(mac_ctx, ap_session, 939 bcn, &bcn_prm); 940 941 if ((ap_session->gLimProtectionControl != 942 MLME_FORCE_POLICY_PROTECTION_DISABLE) && 943 !ap_session->is_session_obss_offload_enabled) 944 ap_beacon_process(mac_ctx, rx_pkt_info, 945 bcn, &bcn_prm, ap_session); 946 947 if ((false == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running) 948 && bcn_prm.paramChangeBitmap) { 949 /* Update the bcn and apply the new settings to HAL */ 950 sch_set_fixed_beacon_fields(mac_ctx, ap_session); 951 pe_debug("Beacon for PE session[%d] got changed", 952 ap_session->peSessionId); 953 pe_debug("sending beacon param change bitmap: 0x%x", 954 bcn_prm.paramChangeBitmap); 955 lim_send_beacon_params(mac_ctx, &bcn_prm, ap_session); 956 } 957 } 958 959 #ifdef WLAN_BCN_RECV_FEATURE 960 /* 961 * sch_send_beacon_report() - To Fill beacon report for 962 * each beacon coming from connected peer and sends it 963 * to upper layer 964 * @mac_ctx: Mac context 965 * @beacon_struct: Pointing to beacon structure 966 * @session: pointer to the PE session 967 * 968 * Return: None 969 */ 970 static 971 void sch_send_beacon_report(struct mac_context *mac_ctx, 972 struct sSirProbeRespBeacon *beacon_struct, 973 struct pe_session *session) 974 { 975 struct wlan_beacon_report beacon_report; 976 beacon_report_cb sme_bcn_cb; 977 978 sme_bcn_cb = mac_ctx->lim.sme_bcn_rcv_callback; 979 if (!sme_bcn_cb) 980 return; 981 982 if (!LIM_IS_STA_ROLE(session)) 983 return; 984 985 if (sir_compare_mac_addr(session->bssId, beacon_struct->bssid)) { 986 /* Prepare beacon report from incoming beacon */ 987 qdf_mem_copy(beacon_report.bssid.bytes, beacon_struct->bssid, 988 sizeof(tSirMacAddr)); 989 990 qdf_mem_copy(&beacon_report.time_stamp, 991 &beacon_struct->timeStamp, sizeof(qdf_time_t)); 992 beacon_report.beacon_interval = beacon_struct->beaconInterval; 993 beacon_report.frequency = beacon_struct->chan_freq; 994 995 beacon_report.ssid.length = beacon_struct->ssId.length; 996 qdf_mem_copy(&beacon_report.ssid.ssid, 997 &beacon_struct->ssId.ssId, 998 beacon_report.ssid.length); 999 1000 beacon_report.boot_time = 1001 qdf_do_div(qdf_get_monotonic_boottime(), 1002 QDF_MC_TIMER_TO_MS_UNIT); 1003 1004 beacon_report.vdev_id = session->vdev_id; 1005 1006 /* Send report to upper layer */ 1007 sme_bcn_cb(mac_ctx->hdd_handle, &beacon_report); 1008 } 1009 } 1010 1011 #else 1012 static inline 1013 void sch_send_beacon_report(struct mac_context *mac_ctx, 1014 struct sSirProbeRespBeacon *beacon_struct, 1015 struct pe_session *session) 1016 { 1017 } 1018 #endif 1019 1020 /** 1021 * sch_beacon_process() - process the beacon frame 1022 * @mac_ctx: mac global context 1023 * @rx_pkt_info: pointer to buffer descriptor 1024 * @session: pointer to the PE session 1025 * 1026 * Return: None 1027 */ 1028 void 1029 sch_beacon_process(struct mac_context *mac_ctx, uint8_t *rx_pkt_info, 1030 struct pe_session *session) 1031 { 1032 static tSchBeaconStruct bcn; 1033 1034 if (!session) 1035 return; 1036 1037 /* 1038 * Drop the beacon/probe response from current connected AP in 1039 * below cases to avoid responding to the changes in beacon(e.g. doing 1040 * VDEV_RESTART to update to the latest capabilities), 1041 * 1. vdev is not in connected state: vdev might be transitioning 1042 * 2. Link switch is in progress: Current link or one of the partner 1043 * links are getting replaced. 1044 * 1045 * New beacons/probe rsps can be considered once post these operations. 1046 */ 1047 if (LIM_IS_STA_ROLE(session) && 1048 (!wlan_cm_is_vdev_connected(session->vdev) || 1049 mlo_mgr_is_link_switch_in_progress(session->vdev))) { 1050 pe_debug_rl("vdev %d, drop beacon", session->vdev_id); 1051 return; 1052 } 1053 1054 /* Convert the beacon frame into a structure */ 1055 if (sir_convert_beacon_frame2_struct(mac_ctx, (uint8_t *) rx_pkt_info, 1056 &bcn) != QDF_STATUS_SUCCESS) { 1057 pe_err_rl("beacon parsing failed"); 1058 return; 1059 } 1060 1061 session->dtimPeriod = bcn.tim.dtimPeriod; 1062 1063 sch_send_beacon_report(mac_ctx, &bcn, session); 1064 __sch_beacon_process_for_session(mac_ctx, &bcn, rx_pkt_info, session); 1065 } 1066 1067 /** 1068 * sch_beacon_edca_process(): Process the EDCA parameter set in the received 1069 * beacon frame 1070 * 1071 * @mac_ctx: mac global context 1072 * @edca: reference to edca parameters in beacon struct 1073 * @session : pesession entry 1074 * 1075 * @return status of operation 1076 */ 1077 QDF_STATUS 1078 sch_beacon_edca_process(struct mac_context *mac, tSirMacEdcaParamSetIE *edca, 1079 struct pe_session *session) 1080 { 1081 bool follow_ap_edca; 1082 #ifdef FEATURE_WLAN_DIAG_SUPPORT 1083 host_log_qos_edca_pkt_type *log_ptr = NULL; 1084 #endif /* FEATURE_WLAN_DIAG_SUPPORT */ 1085 1086 if (!(mac->mlme_cfg)) { 1087 pe_err("invalid mlme cfg"); 1088 return QDF_STATUS_E_FAILURE; 1089 } 1090 1091 follow_ap_edca = mlme_get_follow_ap_edca_flag(session->vdev); 1092 1093 session->gLimEdcaParamSetCount = edca->qosInfo.count; 1094 session->gLimEdcaParams[QCA_WLAN_AC_BE] = edca->acbe; 1095 session->gLimEdcaParams[QCA_WLAN_AC_BK] = edca->acbk; 1096 session->gLimEdcaParams[QCA_WLAN_AC_VI] = edca->acvi; 1097 session->gLimEdcaParams[QCA_WLAN_AC_VO] = edca->acvo; 1098 1099 if (mac->mlme_cfg->edca_params.enable_edca_params && !follow_ap_edca) { 1100 session->gLimEdcaParams[QCA_WLAN_AC_VO].aci.aifsn = 1101 mac->mlme_cfg->edca_params.edca_ac_vo.vo_aifs; 1102 session->gLimEdcaParams[QCA_WLAN_AC_VI].aci.aifsn = 1103 mac->mlme_cfg->edca_params.edca_ac_vi.vi_aifs; 1104 session->gLimEdcaParams[QCA_WLAN_AC_BK].aci.aifsn = 1105 mac->mlme_cfg->edca_params.edca_ac_bk.bk_aifs; 1106 session->gLimEdcaParams[QCA_WLAN_AC_BE].aci.aifsn = 1107 mac->mlme_cfg->edca_params.edca_ac_be.be_aifs; 1108 1109 session->gLimEdcaParams[QCA_WLAN_AC_VO].cw.min = 1110 mac->mlme_cfg->edca_params.edca_ac_vo.vo_cwmin; 1111 session->gLimEdcaParams[QCA_WLAN_AC_VI].cw.min = 1112 mac->mlme_cfg->edca_params.edca_ac_vi.vi_cwmin; 1113 session->gLimEdcaParams[QCA_WLAN_AC_BK].cw.min = 1114 mac->mlme_cfg->edca_params.edca_ac_bk.bk_cwmin; 1115 session->gLimEdcaParams[QCA_WLAN_AC_BE].cw.min = 1116 mac->mlme_cfg->edca_params.edca_ac_be.be_cwmin; 1117 1118 session->gLimEdcaParams[QCA_WLAN_AC_VO].cw.max = 1119 mac->mlme_cfg->edca_params.edca_ac_vo.vo_cwmax; 1120 session->gLimEdcaParams[QCA_WLAN_AC_VI].cw.max = 1121 mac->mlme_cfg->edca_params.edca_ac_vi.vi_cwmax; 1122 session->gLimEdcaParams[QCA_WLAN_AC_BK].cw.max = 1123 mac->mlme_cfg->edca_params.edca_ac_bk.bk_cwmax; 1124 session->gLimEdcaParams[QCA_WLAN_AC_BE].cw.max = 1125 mac->mlme_cfg->edca_params.edca_ac_be.be_cwmax; 1126 } 1127 #ifdef FEATURE_WLAN_DIAG_SUPPORT 1128 WLAN_HOST_DIAG_LOG_ALLOC(log_ptr, host_log_qos_edca_pkt_type, 1129 LOG_WLAN_QOS_EDCA_C); 1130 if (log_ptr) { 1131 log_ptr->aci_be = session->gLimEdcaParams[QCA_WLAN_AC_BE].aci.aci; 1132 log_ptr->cw_be = 1133 session->gLimEdcaParams[QCA_WLAN_AC_BE].cw.max << 4 1134 | session->gLimEdcaParams[QCA_WLAN_AC_BE].cw.min; 1135 log_ptr->txoplimit_be = 1136 session->gLimEdcaParams[QCA_WLAN_AC_BE].txoplimit; 1137 log_ptr->aci_bk = 1138 session->gLimEdcaParams[QCA_WLAN_AC_BK].aci.aci; 1139 log_ptr->cw_bk = 1140 session->gLimEdcaParams[QCA_WLAN_AC_BK].cw.max << 4 1141 | session->gLimEdcaParams[QCA_WLAN_AC_BK].cw.min; 1142 log_ptr->txoplimit_bk = 1143 session->gLimEdcaParams[QCA_WLAN_AC_BK].txoplimit; 1144 log_ptr->aci_vi = 1145 session->gLimEdcaParams[QCA_WLAN_AC_VI].aci.aci; 1146 log_ptr->cw_vi = 1147 session->gLimEdcaParams[QCA_WLAN_AC_VI].cw.max << 4 1148 | session->gLimEdcaParams[QCA_WLAN_AC_VI].cw.min; 1149 log_ptr->txoplimit_vi = 1150 session->gLimEdcaParams[QCA_WLAN_AC_VI].txoplimit; 1151 log_ptr->aci_vo = 1152 session->gLimEdcaParams[QCA_WLAN_AC_VO].aci.aci; 1153 log_ptr->cw_vo = 1154 session->gLimEdcaParams[QCA_WLAN_AC_VO].cw.max << 4 1155 | session->gLimEdcaParams[QCA_WLAN_AC_VO].cw.min; 1156 log_ptr->txoplimit_vo = 1157 session->gLimEdcaParams[QCA_WLAN_AC_VO].txoplimit; 1158 } 1159 WLAN_HOST_DIAG_LOG_REPORT(log_ptr); 1160 #endif /* FEATURE_WLAN_DIAG_SUPPORT */ 1161 pe_debug("Edca param enabled %d. Updating Local Params to: AC_BE: AIFSN: %d, ACM %d, CWmin %d, CWmax %d, TxOp %d AC_BK: AIFSN: %d, ACM %d, CWmin %d, CWmax %d, TxOp %d AC_VI: AIFSN: %d, ACM %d, CWmin %d, CWmax %d, TxOp %d AC_VO: AIFSN: %d, ACM %d, CWmin %d, CWmax %d, TxOp %d", 1162 mac->mlme_cfg->edca_params.enable_edca_params, 1163 session->gLimEdcaParams[0].aci.aifsn, 1164 session->gLimEdcaParams[0].aci.acm, 1165 session->gLimEdcaParams[0].cw.min, 1166 session->gLimEdcaParams[0].cw.max, 1167 session->gLimEdcaParams[0].txoplimit, 1168 session->gLimEdcaParams[1].aci.aifsn, 1169 session->gLimEdcaParams[1].aci.acm, 1170 session->gLimEdcaParams[1].cw.min, 1171 session->gLimEdcaParams[1].cw.max, 1172 session->gLimEdcaParams[1].txoplimit, 1173 session->gLimEdcaParams[2].aci.aifsn, 1174 session->gLimEdcaParams[2].aci.acm, 1175 session->gLimEdcaParams[2].cw.min, 1176 session->gLimEdcaParams[2].cw.max, 1177 session->gLimEdcaParams[2].txoplimit, 1178 session->gLimEdcaParams[3].aci.aifsn, 1179 session->gLimEdcaParams[3].aci.acm, 1180 session->gLimEdcaParams[3].cw.min, 1181 session->gLimEdcaParams[3].cw.max, 1182 session->gLimEdcaParams[3].txoplimit); 1183 1184 return QDF_STATUS_SUCCESS; 1185 } 1186 1187 void lim_enable_obss_detection_config(struct mac_context *mac_ctx, 1188 struct pe_session *session) 1189 { 1190 QDF_STATUS status = QDF_STATUS_SUCCESS; 1191 1192 if (!session) { 1193 pe_err("Invalid session, protection not enabled"); 1194 return; 1195 } 1196 1197 if (session->gLimProtectionControl == 1198 MLME_FORCE_POLICY_PROTECTION_DISABLE) { 1199 pe_err("protectiond disabled, force policy, session %d", 1200 session->smeSessionId); 1201 return; 1202 } 1203 1204 if (mac_ctx->mlme_cfg->obss_ht40.obss_detection_offload_enabled) { 1205 status = lim_obss_send_detection_cfg(mac_ctx, session, true); 1206 if (QDF_IS_STATUS_ERROR(status)) { 1207 pe_err("vdev %d: offload enable failed, trying legacy", 1208 session->smeSessionId); 1209 session->is_session_obss_offload_enabled = false; 1210 } else { 1211 pe_debug("vdev %d: offload detection enabled", 1212 session->smeSessionId); 1213 session->is_session_obss_offload_enabled = true; 1214 lim_obss_send_detection_cfg(mac_ctx, session, true); 1215 } 1216 } 1217 1218 if (!mac_ctx->mlme_cfg->obss_ht40.obss_detection_offload_enabled || 1219 QDF_IS_STATUS_ERROR(status)) { 1220 status = qdf_mc_timer_start(&session-> 1221 protection_fields_reset_timer, 1222 SCH_PROTECTION_RESET_TIME); 1223 if (QDF_IS_STATUS_ERROR(status)) 1224 pe_err("vdev %d: start timer failed", 1225 session->smeSessionId); 1226 else 1227 pe_debug("vdev %d: legacy detection enabled", 1228 session->smeSessionId); 1229 } 1230 } 1231 1232 QDF_STATUS lim_obss_generate_detection_config(struct mac_context *mac_ctx, 1233 struct pe_session *session, 1234 struct obss_detection_cfg *cfg) 1235 { 1236 uint32_t phy_mode; 1237 enum reg_wifi_band rf_band = REG_BAND_UNKNOWN; 1238 struct obss_detection_cfg *cur_detect; 1239 1240 if (!mac_ctx || !session || !cfg) { 1241 pe_err("Invalid params mac_ctx %pK, session %pK, cfg %pK", 1242 mac_ctx, session, cfg); 1243 return QDF_STATUS_E_INVAL; 1244 } 1245 1246 lim_get_phy_mode(mac_ctx, &phy_mode, session); 1247 rf_band = session->limRFBand; 1248 qdf_mem_zero(cfg, sizeof(*cfg)); 1249 cur_detect = &session->current_obss_detection; 1250 1251 pe_debug("band:%d, phy_mode:%d, ht_cap:%d, ht_oper_mode:%d", 1252 rf_band, phy_mode, session->htCapability, 1253 mac_ctx->lim.gHTOperMode); 1254 pe_debug("assoc_sta: 11b:%d, 11g:%d, 11a:%d, ht20:%d", 1255 session->gLim11bParams.protectionEnabled, 1256 session->gLim11gParams.protectionEnabled, 1257 session->gLim11aParams.protectionEnabled, 1258 session->gLimHt20Params.protectionEnabled); 1259 pe_debug("obss: 11b:%d, 11g:%d, 11a:%d, ht20:%d", 1260 session->gLimOlbcParams.protectionEnabled, 1261 session->gLimOverlap11gParams.protectionEnabled, 1262 session->gLimOverlap11aParams.protectionEnabled, 1263 session->gLimOverlapHt20Params.protectionEnabled); 1264 pe_debug("detect: b_ap:%d, b_s:%d, g:%d, a:%d, htl:%d, htm:%d, ht20:%d", 1265 cur_detect->obss_11b_ap_detect_mode, 1266 cur_detect->obss_11b_sta_detect_mode, 1267 cur_detect->obss_11g_ap_detect_mode, 1268 cur_detect->obss_11a_detect_mode, 1269 cur_detect->obss_ht_legacy_detect_mode, 1270 cur_detect->obss_ht_mixed_detect_mode, 1271 cur_detect->obss_ht_20mhz_detect_mode); 1272 1273 if (rf_band == REG_BAND_2G) { 1274 if ((phy_mode == WNI_CFG_PHY_MODE_11G || 1275 session->htCapability) && 1276 !session->gLim11bParams.protectionEnabled) { 1277 if (!session->gLimOlbcParams.protectionEnabled && 1278 !session->gLimOverlap11gParams.protectionEnabled) { 1279 cfg->obss_11b_ap_detect_mode = 1280 OBSS_OFFLOAD_DETECTION_PRESENT; 1281 cfg->obss_11b_sta_detect_mode = 1282 OBSS_OFFLOAD_DETECTION_PRESENT; 1283 } else { 1284 if (cur_detect->obss_11b_ap_detect_mode == 1285 OBSS_OFFLOAD_DETECTION_PRESENT) 1286 cfg->obss_11b_ap_detect_mode = 1287 OBSS_OFFLOAD_DETECTION_ABSENT; 1288 if (cur_detect->obss_11b_sta_detect_mode == 1289 OBSS_OFFLOAD_DETECTION_PRESENT) 1290 cfg->obss_11b_sta_detect_mode = 1291 OBSS_OFFLOAD_DETECTION_ABSENT; 1292 } 1293 } else if (session->gLim11bParams.protectionEnabled) { 1294 session->gLimOlbcParams.protectionEnabled = false; 1295 } 1296 1297 if (session->htCapability && 1298 session->cfgProtection.overlapFromllg && 1299 !session->gLim11gParams.protectionEnabled) { 1300 if (!session->gLimOverlap11gParams.protectionEnabled) { 1301 cfg->obss_11g_ap_detect_mode = 1302 OBSS_OFFLOAD_DETECTION_PRESENT; 1303 cfg->obss_ht_legacy_detect_mode = 1304 OBSS_OFFLOAD_DETECTION_PRESENT; 1305 cfg->obss_ht_mixed_detect_mode = 1306 OBSS_OFFLOAD_DETECTION_PRESENT; 1307 } else { 1308 if (cur_detect->obss_11g_ap_detect_mode == 1309 OBSS_OFFLOAD_DETECTION_PRESENT) 1310 cfg->obss_11g_ap_detect_mode = 1311 OBSS_OFFLOAD_DETECTION_ABSENT; 1312 if (cur_detect->obss_ht_legacy_detect_mode == 1313 OBSS_OFFLOAD_DETECTION_PRESENT) 1314 cfg->obss_ht_legacy_detect_mode = 1315 OBSS_OFFLOAD_DETECTION_ABSENT; 1316 if (cur_detect->obss_ht_mixed_detect_mode == 1317 OBSS_OFFLOAD_DETECTION_PRESENT) 1318 cfg->obss_ht_mixed_detect_mode = 1319 OBSS_OFFLOAD_DETECTION_ABSENT; 1320 } 1321 } else if (session->gLim11gParams.protectionEnabled) { 1322 session->gLimOverlap11gParams.protectionEnabled = false; 1323 } 1324 1325 /* INI related settings */ 1326 if (mac_ctx->mlme_cfg->sta.ignore_peer_erp_info) 1327 cfg->obss_11b_sta_detect_mode = 1328 OBSS_OFFLOAD_DETECTION_DISABLED; 1329 1330 if (mac_ctx->mlme_cfg->sap_protection_cfg.ignore_peer_ht_opmode) 1331 cfg->obss_ht_legacy_detect_mode = 1332 OBSS_OFFLOAD_DETECTION_DISABLED; 1333 } 1334 1335 if ((rf_band == REG_BAND_5G) && session->htCapability) { 1336 if (!session->gLim11aParams.protectionEnabled) { 1337 if (!session->gLimOverlap11aParams.protectionEnabled) 1338 cfg->obss_11a_detect_mode = 1339 OBSS_OFFLOAD_DETECTION_PRESENT; 1340 else if (cur_detect->obss_11a_detect_mode == 1341 OBSS_OFFLOAD_DETECTION_PRESENT) 1342 cfg->obss_11a_detect_mode = 1343 OBSS_OFFLOAD_DETECTION_ABSENT; 1344 } else { 1345 session->gLimOverlap11aParams.protectionEnabled = false; 1346 } 1347 } 1348 1349 if (((rf_band == REG_BAND_2G) || (rf_band == REG_BAND_5G)) && 1350 session->htCapability) { 1351 1352 if (!session->gLimHt20Params.protectionEnabled) { 1353 if (!session->gLimOverlapHt20Params.protectionEnabled) { 1354 cfg->obss_ht_20mhz_detect_mode = 1355 OBSS_OFFLOAD_DETECTION_PRESENT; 1356 } else if (cur_detect->obss_ht_20mhz_detect_mode == 1357 OBSS_OFFLOAD_DETECTION_PRESENT) { 1358 cfg->obss_ht_20mhz_detect_mode = 1359 OBSS_OFFLOAD_DETECTION_ABSENT; 1360 } 1361 } else { 1362 session->gLimOverlapHt20Params.protectionEnabled = 1363 false; 1364 } 1365 } 1366 1367 pe_debug("b_ap:%d, b_s:%d, g:%d, a:%d, ht_le:%d, ht_m:%d, ht_20:%d", 1368 cfg->obss_11b_ap_detect_mode, 1369 cfg->obss_11b_sta_detect_mode, 1370 cfg->obss_11g_ap_detect_mode, 1371 cfg->obss_11a_detect_mode, 1372 cfg->obss_ht_legacy_detect_mode, 1373 cfg->obss_ht_mixed_detect_mode, 1374 cfg->obss_ht_20mhz_detect_mode); 1375 1376 return QDF_STATUS_SUCCESS; 1377 } 1378 1379 QDF_STATUS lim_obss_send_detection_cfg(struct mac_context *mac_ctx, 1380 struct pe_session *session, bool force) 1381 { 1382 QDF_STATUS status; 1383 struct obss_detection_cfg obss_cfg; 1384 struct wmi_obss_detection_cfg_param *req_param; 1385 1386 if (!session) { 1387 pe_err("Invalid session"); 1388 return QDF_STATUS_E_INVAL; 1389 } 1390 1391 if (!session->is_session_obss_offload_enabled) { 1392 pe_debug("obss offload protectiond disabled, session %d", 1393 session->smeSessionId); 1394 /* Send success */ 1395 return QDF_STATUS_SUCCESS; 1396 } 1397 1398 if (session->gLimProtectionControl == 1399 MLME_FORCE_POLICY_PROTECTION_DISABLE) { 1400 pe_debug("protectiond disabled, force from policy, session %d", 1401 session->smeSessionId); 1402 /* Send success */ 1403 return QDF_STATUS_SUCCESS; 1404 } 1405 1406 status = lim_obss_generate_detection_config(mac_ctx, 1407 session, 1408 &obss_cfg); 1409 if (QDF_IS_STATUS_ERROR(status)) { 1410 pe_err("Failed to generate obss detection cfg, session %d", 1411 session->smeSessionId); 1412 return status; 1413 } 1414 1415 if (qdf_mem_cmp(&session->obss_offload_cfg, &obss_cfg, sizeof(obss_cfg)) 1416 || force) { 1417 struct scheduler_msg msg = {0}; 1418 req_param = qdf_mem_malloc(sizeof(*req_param)); 1419 if (!req_param) 1420 return QDF_STATUS_E_NOMEM; 1421 qdf_mem_copy(&session->obss_offload_cfg, &obss_cfg, 1422 sizeof(obss_cfg)); 1423 req_param->vdev_id = session->smeSessionId; 1424 req_param->obss_detect_period_ms = OBSS_DETECTION_PERIOD_MS; 1425 req_param->obss_11b_ap_detect_mode = 1426 obss_cfg.obss_11b_ap_detect_mode; 1427 req_param->obss_11b_sta_detect_mode = 1428 obss_cfg.obss_11b_sta_detect_mode; 1429 req_param->obss_11g_ap_detect_mode = 1430 obss_cfg.obss_11g_ap_detect_mode; 1431 req_param->obss_11a_detect_mode = 1432 obss_cfg.obss_11a_detect_mode; 1433 req_param->obss_ht_legacy_detect_mode = 1434 obss_cfg.obss_ht_legacy_detect_mode; 1435 req_param->obss_ht_20mhz_detect_mode = 1436 obss_cfg.obss_ht_20mhz_detect_mode; 1437 req_param->obss_ht_mixed_detect_mode = 1438 obss_cfg.obss_ht_mixed_detect_mode; 1439 1440 msg.type = WMA_OBSS_DETECTION_REQ; 1441 msg.bodyptr = req_param; 1442 msg.reserved = 0; 1443 status = scheduler_post_message(QDF_MODULE_ID_PE, 1444 QDF_MODULE_ID_WMA, 1445 QDF_MODULE_ID_WMA, &msg); 1446 if (QDF_IS_STATUS_ERROR(status)) { 1447 qdf_mem_free(req_param); 1448 return status; 1449 } 1450 } else { 1451 pe_debug("Skipping WMA_OBSS_DETECTION_REQ, force = %d", force); 1452 } 1453 1454 return status; 1455 } 1456 1457 QDF_STATUS lim_process_obss_detection_ind(struct mac_context *mac_ctx, 1458 struct wmi_obss_detect_info 1459 *obss_detection) 1460 { 1461 QDF_STATUS status; 1462 uint32_t detect_masks; 1463 uint32_t reason; 1464 struct obss_detection_cfg *obss_cfg; 1465 bool enable; 1466 struct pe_session *session; 1467 tUpdateBeaconParams bcn_prm; 1468 enum reg_wifi_band rf_band = REG_BAND_UNKNOWN; 1469 struct obss_detection_cfg *cur_detect; 1470 1471 pe_debug("obss detect ind id %d, reason %d, msk 0x%x, " QDF_MAC_ADDR_FMT, 1472 obss_detection->vdev_id, obss_detection->reason, 1473 obss_detection->matched_detection_masks, 1474 QDF_MAC_ADDR_REF(obss_detection->matched_bssid_addr)); 1475 1476 session = pe_find_session_by_vdev_id(mac_ctx, obss_detection->vdev_id); 1477 if (!session) { 1478 pe_err("Failed to get session for id %d", 1479 obss_detection->vdev_id); 1480 return QDF_STATUS_E_INVAL; 1481 } 1482 1483 if (!LIM_IS_AP_ROLE(session)) { 1484 pe_err("session %d is not AP", obss_detection->vdev_id); 1485 return QDF_STATUS_E_INVAL; 1486 } 1487 1488 if (!session->is_session_obss_offload_enabled) { 1489 pe_err("Offload already disabled for session %d", 1490 obss_detection->vdev_id); 1491 return QDF_STATUS_SUCCESS; 1492 } 1493 1494 reason = obss_detection->reason; 1495 detect_masks = obss_detection->matched_detection_masks; 1496 1497 if (reason == OBSS_OFFLOAD_DETECTION_PRESENT) { 1498 enable = true; 1499 } else if (reason == OBSS_OFFLOAD_DETECTION_ABSENT) { 1500 enable = false; 1501 } else if (reason == OBSS_OFFLOAD_DETECTION_DISABLED) { 1502 /* 1503 * Most common reason for this event-type from firmware 1504 * is insufficient memory. 1505 * Disable offload OBSS detection and enable legacy-way 1506 * of detecting OBSS by parsing beacons. 1507 **/ 1508 session->is_session_obss_offload_enabled = false; 1509 pe_err("FW indicated obss offload disabled"); 1510 pe_err("Enabling host based detection, session %d", 1511 obss_detection->vdev_id); 1512 1513 status = qdf_mc_timer_start(&session-> 1514 protection_fields_reset_timer, 1515 SCH_PROTECTION_RESET_TIME); 1516 if (QDF_IS_STATUS_ERROR(status)) 1517 pe_err("cannot start protection reset timer"); 1518 1519 return QDF_STATUS_SUCCESS; 1520 } else { 1521 pe_err("Invalid reason %d, session %d", 1522 obss_detection->reason, 1523 obss_detection->vdev_id); 1524 return QDF_STATUS_E_INVAL; 1525 } 1526 1527 rf_band = session->limRFBand; 1528 qdf_mem_zero(&bcn_prm, sizeof(bcn_prm)); 1529 obss_cfg = &session->obss_offload_cfg; 1530 cur_detect = &session->current_obss_detection; 1531 1532 if (OBSS_DETECTION_IS_11B_AP(detect_masks)) { 1533 if (reason != obss_cfg->obss_11b_ap_detect_mode || 1534 rf_band != REG_BAND_2G) 1535 goto wrong_detection; 1536 1537 lim_enable11g_protection(mac_ctx, enable, true, 1538 &bcn_prm, session); 1539 cur_detect->obss_11b_ap_detect_mode = reason; 1540 } 1541 if (OBSS_DETECTION_IS_11B_STA(detect_masks)) { 1542 if (reason != obss_cfg->obss_11b_sta_detect_mode || 1543 rf_band != REG_BAND_2G) 1544 goto wrong_detection; 1545 1546 lim_enable11g_protection(mac_ctx, enable, true, 1547 &bcn_prm, session); 1548 cur_detect->obss_11b_sta_detect_mode = reason; 1549 } 1550 if (OBSS_DETECTION_IS_11G_AP(detect_masks)) { 1551 if (reason != obss_cfg->obss_11g_ap_detect_mode || 1552 rf_band != REG_BAND_2G) 1553 goto wrong_detection; 1554 1555 lim_enable_ht_protection_from11g(mac_ctx, enable, true, 1556 &bcn_prm, session); 1557 cur_detect->obss_11g_ap_detect_mode = reason; 1558 } 1559 if (OBSS_DETECTION_IS_11A(detect_masks)) { 1560 if (reason != obss_cfg->obss_11a_detect_mode || 1561 rf_band != REG_BAND_5G) 1562 goto wrong_detection; 1563 1564 lim_update_11a_protection(mac_ctx, enable, true, 1565 &bcn_prm, session); 1566 cur_detect->obss_11a_detect_mode = reason; 1567 } 1568 if (OBSS_DETECTION_IS_HT_LEGACY(detect_masks)) { 1569 /* for 5GHz, we have only 11a detection, which covers legacy */ 1570 if (reason != obss_cfg->obss_ht_legacy_detect_mode || 1571 rf_band != REG_BAND_2G) 1572 goto wrong_detection; 1573 1574 lim_enable_ht_protection_from11g(mac_ctx, enable, true, 1575 &bcn_prm, session); 1576 cur_detect->obss_ht_legacy_detect_mode = reason; 1577 } 1578 if (OBSS_DETECTION_IS_HT_MIXED(detect_masks)) { 1579 /* for 5GHz, we have only 11a detection, which covers ht mix */ 1580 if (reason != obss_cfg->obss_ht_mixed_detect_mode || 1581 rf_band != REG_BAND_2G) 1582 goto wrong_detection; 1583 1584 lim_enable_ht_protection_from11g(mac_ctx, enable, true, 1585 &bcn_prm, session); 1586 cur_detect->obss_ht_mixed_detect_mode = reason; 1587 } 1588 if (OBSS_DETECTION_IS_HT_20MHZ(detect_masks)) { 1589 if (reason != obss_cfg->obss_ht_20mhz_detect_mode) 1590 goto wrong_detection; 1591 1592 lim_enable_ht20_protection(mac_ctx, enable, true, 1593 &bcn_prm, session); 1594 cur_detect->obss_ht_20mhz_detect_mode = reason; 1595 } 1596 1597 if ((false == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running) && 1598 bcn_prm.paramChangeBitmap) { 1599 /* Update the bcn and apply the new settings to HAL */ 1600 sch_set_fixed_beacon_fields(mac_ctx, session); 1601 pe_debug("Beacon for PE session: %d got changed: 0x%x", 1602 session->smeSessionId, bcn_prm.paramChangeBitmap); 1603 if (!QDF_IS_STATUS_SUCCESS(lim_send_beacon_params( 1604 mac_ctx, &bcn_prm, session))) { 1605 pe_err("Failed to send beacon param, session %d", 1606 obss_detection->vdev_id); 1607 return QDF_STATUS_E_FAULT; 1608 } 1609 } 1610 1611 status = lim_obss_send_detection_cfg(mac_ctx, session, true); 1612 if (QDF_IS_STATUS_ERROR(status)) { 1613 pe_err("Failed to send obss detection cfg, session %d", 1614 obss_detection->vdev_id); 1615 return status; 1616 } 1617 1618 return QDF_STATUS_SUCCESS; 1619 1620 wrong_detection: 1621 /* 1622 * We may get this wrong detection before FW can update latest cfg, 1623 * So keeping log level debug 1624 **/ 1625 pe_debug("Wrong detection, session %d", obss_detection->vdev_id); 1626 1627 return QDF_STATUS_E_INVAL; 1628 } 1629