1 /* 2 * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2023 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 pe_debug("OMN IE is present in the beacon, update NSS/Ch width"); 478 lim_update_nss(mac_ctx, sta_ds, bcn->OperatingMode.rxNSS, 479 session); 480 ch_width = bcn->OperatingMode.chanWidth; 481 } else { 482 bcn_vht_chwidth = lim_get_vht_ch_width(vht_caps, vht_op, 483 &bcn->HTInfo); 484 ch_width = 485 lim_convert_vht_chwidth_to_phy_chwidth(bcn_vht_chwidth, 486 is_40); 487 } 488 lim_update_channel_width(mac_ctx, sta_ds, session, ch_width, &ch_bw); 489 } 490 491 #ifdef WLAN_FEATURE_SR 492 /** 493 * lim_detect_change_in_srp() - Detect change in SRP IE 494 * of the beacon 495 * 496 * @mac_ctx: global mac context 497 * @sta: pointer to sta node 498 * @session: pointer to LIM session 499 * @bcn: beacon from associated AP 500 * 501 * Detect change in SRP IE of the beacon and update the params 502 * accordingly. 503 * 504 * Return: None 505 */ 506 static void lim_detect_change_in_srp(struct mac_context *mac_ctx, 507 tpDphHashNode sta, 508 struct pe_session *session, 509 tpSchBeaconStruct bcn) 510 { 511 tDot11fIEspatial_reuse sr_ie; 512 int32_t ret = 0; 513 514 sr_ie = sta->parsed_ies.srp_ie; 515 if (sr_ie.present || bcn->srp_ie.present) { 516 ret = qdf_mem_cmp(&sr_ie, &bcn->srp_ie, 517 sizeof(tDot11fIEspatial_reuse)); 518 519 if (ret) { 520 /* 521 * If SRP IE has changes, update the new params. 522 */ 523 sta->parsed_ies.srp_ie = bcn->srp_ie; 524 lim_update_vdev_sr_elements(session, sta); 525 526 lim_handle_sr_cap(session->vdev, 527 SR_REASON_CODE_BCN_IE_CHANGE); 528 } 529 } 530 } 531 #else 532 static void lim_detect_change_in_srp(struct mac_context *mac_ctx, 533 tpDphHashNode sta, 534 struct pe_session *session, 535 tpSchBeaconStruct bcn) 536 { 537 } 538 #endif 539 540 static void 541 sch_bcn_process_sta_opmode(struct mac_context *mac_ctx, 542 tpSchBeaconStruct bcn, 543 uint8_t *rx_pkt_info, 544 struct pe_session *session, 545 tUpdateBeaconParams *beaconParams, 546 uint8_t *sendProbeReq, tpSirMacMgmtHdr pMh) 547 { 548 tpDphHashNode sta = NULL; 549 uint16_t aid; 550 551 /* check for VHT capability */ 552 sta = dph_lookup_hash_entry(mac_ctx, pMh->sa, &aid, 553 &session->dph.dphHashTable); 554 if (!sta) 555 return; 556 sch_bcn_update_opmode_change(mac_ctx, sta, session, bcn, pMh); 557 sch_bcn_update_he_ies(mac_ctx, sta, session, bcn, pMh); 558 lim_detect_change_in_srp(mac_ctx, sta, session, bcn); 559 return; 560 } 561 562 /** 563 * get_local_power_constraint_beacon() - extracts local constraint 564 * from beacon 565 * @bcn: beacon structure 566 * @local_constraint: local constraint pointer 567 * @is_power_constraint_abs: is power constraint absolute 568 * 569 * Return: None 570 */ 571 #ifdef FEATURE_WLAN_ESE 572 static void get_local_power_constraint_beacon( 573 tpSchBeaconStruct bcn, 574 int8_t *local_constraint, 575 bool *is_power_constraint_abs) 576 { 577 if (bcn->eseTxPwr.present) { 578 *local_constraint = bcn->eseTxPwr.power_limit; 579 *is_power_constraint_abs = true; 580 } 581 } 582 #else 583 static void get_local_power_constraint_beacon( 584 tpSchBeaconStruct bcn, 585 int8_t *local_constraint, 586 bool *is_power_constraint_abs) 587 { 588 589 } 590 #endif 591 592 static void __sch_beacon_process_for_session(struct mac_context *mac_ctx, 593 tpSchBeaconStruct bcn, 594 uint8_t *rx_pkt_info, 595 struct pe_session *session) 596 { 597 tUpdateBeaconParams beaconParams; 598 uint8_t sendProbeReq = false; 599 tpSirMacMgmtHdr pMh = WMA_GET_RX_MAC_HEADER(rx_pkt_info); 600 int8_t local_constraint = 0; 601 uint32_t chan_freq = 0; 602 struct vdev_mlme_obj *mlme_obj; 603 struct wlan_lmac_if_reg_tx_ops *tx_ops; 604 bool ap_constraint_change = false, tpe_change = false; 605 int8_t regMax = 0, maxTxPower = 0; 606 QDF_STATUS status; 607 bool skip_tpe = false, is_sap_go_switched_ch; 608 enum reg_6g_ap_type pwr_type_6g; 609 uint8_t bpcc; 610 bool cu_flag = true; 611 bool is_power_constraint_abs = false; 612 613 if (mlo_is_mld_sta(session->vdev)) { 614 cu_flag = false; 615 status = lim_get_bpcc_from_mlo_ie(bcn, &bpcc); 616 if (QDF_IS_STATUS_SUCCESS(status)) 617 cu_flag = lim_check_cu_happens(session->vdev, bpcc); 618 lim_process_ml_reconfig(mac_ctx, session, rx_pkt_info); 619 } 620 621 if (!cu_flag) 622 return; 623 624 qdf_mem_zero(&beaconParams, sizeof(tUpdateBeaconParams)); 625 beaconParams.paramChangeBitmap = 0; 626 627 if (LIM_IS_STA_ROLE(session)) { 628 is_sap_go_switched_ch = 629 wlan_vdev_mlme_is_sap_go_move_before_sta(session->vdev); 630 if (is_sap_go_switched_ch) 631 policy_mgr_sta_sap_dfs_enforce_scc(mac_ctx->psoc, 632 session->vdev_id); 633 if (false == sch_bcn_process_sta(mac_ctx, bcn, rx_pkt_info, 634 session, &beaconParams, 635 &sendProbeReq, pMh)) 636 return; 637 } 638 639 /* 640 * For vht session, if opermode ie or vht oper IE is present 641 * bandwidth change will be taken care using these vht IEs. 642 */ 643 if (!(session->vhtCapability && (bcn->OperatingMode.present || 644 bcn->VHTOperation.present)) && session->htCapability && 645 bcn->HTInfo.present) 646 lim_update_sta_run_time_ht_switch_chnl_params(mac_ctx, 647 &bcn->HTInfo, session); 648 649 if (LIM_IS_STA_ROLE(session)) 650 sch_bcn_process_sta_opmode(mac_ctx, bcn, rx_pkt_info, session, 651 &beaconParams, &sendProbeReq, pMh); 652 653 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(session->vdev); 654 if (!mlme_obj) { 655 pe_err("vdev component object is NULL"); 656 return; 657 } 658 659 if (!wlan_reg_is_6ghz_chan_freq(bcn->chan_freq)) { 660 skip_tpe = wlan_mlme_skip_tpe(mac_ctx->psoc); 661 } else { 662 if (!bcn->countryInfoParam.countryString[0]) { 663 pe_err("Channel is 6G but country IE not present"); 664 return; 665 } 666 if (bcn->he_op.oper_info_6g_present) { 667 session->ap_defined_power_type_6g = 668 bcn->he_op.oper_info_6g.info.reg_info; 669 if (session->ap_defined_power_type_6g < REG_INDOOR_AP || 670 session->ap_defined_power_type_6g > 671 REG_MAX_SUPP_AP_TYPE) { 672 session->ap_defined_power_type_6g = 673 REG_CURRENT_MAX_AP_TYPE; 674 pe_debug("AP power type is invalid, defaulting to MAX_AP_TYPE"); 675 } 676 } else { 677 pe_debug("AP power type is null, defaulting to MAX_AP_TYPE"); 678 session->ap_defined_power_type_6g = 679 REG_CURRENT_MAX_AP_TYPE; 680 } 681 682 status = wlan_reg_get_best_6g_power_type( 683 mac_ctx->psoc, mac_ctx->pdev, &pwr_type_6g, 684 session->ap_defined_power_type_6g, 685 bcn->chan_freq); 686 if (QDF_IS_STATUS_ERROR(status)) 687 return; 688 689 session->best_6g_power_type = pwr_type_6g; 690 mlme_set_best_6g_power_type(session->vdev, pwr_type_6g); 691 } 692 693 /* 694 * STA LPI + SAP VLP is supported. For this STA should operate in VLP 695 * power level of the SAP. 696 * If STA is operating in VLP power of SAP, do not update STA power. 697 */ 698 if (wlan_reg_is_ext_tpc_supported(mac_ctx->psoc) && 699 !session->sta_follows_sap_power) { 700 tx_ops = wlan_reg_get_tx_ops(mac_ctx->psoc); 701 702 lim_parse_tpe_ie(mac_ctx, session, bcn->transmit_power_env, 703 bcn->num_transmit_power_env, &bcn->he_op, 704 &tpe_change); 705 706 if (mac_ctx->mlme_cfg->sta.allow_tpc_from_ap) { 707 get_local_power_constraint_beacon( 708 bcn, &local_constraint, 709 &is_power_constraint_abs); 710 711 if (mac_ctx->rrm.rrmPEContext.rrmEnable && 712 bcn->powerConstraintPresent) { 713 local_constraint = 714 bcn->localPowerConstraint.localPowerConstraints; 715 is_power_constraint_abs = false; 716 } 717 } 718 719 if (local_constraint != 720 mlme_obj->reg_tpc_obj.ap_constraint_power) { 721 mlme_obj->reg_tpc_obj.ap_constraint_power = 722 local_constraint; 723 mlme_obj->reg_tpc_obj.is_power_constraint_abs = 724 is_power_constraint_abs; 725 ap_constraint_change = true; 726 } 727 728 if ((ap_constraint_change && local_constraint) || 729 (tpe_change && !skip_tpe)) { 730 lim_calculate_tpc(mac_ctx, session); 731 732 if (tx_ops->set_tpc_power) 733 tx_ops->set_tpc_power(mac_ctx->psoc, 734 session->vdev_id, 735 &mlme_obj->reg_tpc_obj); 736 } 737 } else if (!session->sta_follows_sap_power) { 738 /* Obtain the Max Tx power for the current regulatory */ 739 regMax = wlan_reg_get_channel_reg_power_for_freq( 740 mac_ctx->pdev, session->curr_op_freq); 741 local_constraint = regMax; 742 743 if (mac_ctx->mlme_cfg->sta.allow_tpc_from_ap) { 744 get_local_power_constraint_beacon( 745 bcn, &local_constraint, 746 &is_power_constraint_abs); 747 748 if (mac_ctx->rrm.rrmPEContext.rrmEnable && 749 bcn->powerConstraintPresent) { 750 local_constraint = regMax; 751 local_constraint -= 752 bcn->localPowerConstraint.localPowerConstraints; 753 is_power_constraint_abs = false; 754 755 } 756 } 757 mlme_obj->reg_tpc_obj.is_power_constraint_abs = 758 is_power_constraint_abs; 759 mlme_obj->reg_tpc_obj.reg_max[0] = regMax; 760 mlme_obj->reg_tpc_obj.ap_constraint_power = local_constraint; 761 mlme_obj->reg_tpc_obj.frequency[0] = session->curr_op_freq; 762 763 maxTxPower = lim_get_max_tx_power(mac_ctx, mlme_obj); 764 765 /* If maxTxPower is increased or decreased */ 766 if (maxTxPower != session->maxTxPower) { 767 pe_debug("New maxTx power %d, old pwr %d", 768 maxTxPower, session->maxTxPower); 769 pe_debug("regMax %d, local %d", regMax, 770 local_constraint); 771 status = lim_send_set_max_tx_power_req(mac_ctx, 772 maxTxPower, 773 session); 774 if (status == QDF_STATUS_SUCCESS) 775 session->maxTxPower = maxTxPower; 776 } 777 } 778 /* Indicate to LIM that Beacon is received */ 779 if (bcn->HTInfo.present) { 780 chan_freq = wlan_reg_legacy_chan_to_freq(mac_ctx->pdev, 781 bcn->HTInfo.primaryChannel); 782 lim_received_hb_handler(mac_ctx, chan_freq, session); 783 } else 784 lim_received_hb_handler(mac_ctx, bcn->chan_freq, session); 785 786 /* 787 * I don't know if any additional IE is required here. Currently, not 788 * include addIE. 789 */ 790 if (sendProbeReq) 791 lim_send_probe_req_mgmt_frame(mac_ctx, &session->ssId, 792 session->bssId, session->curr_op_freq, 793 session->self_mac_addr, session->dot11mode, NULL, NULL); 794 795 if ((false == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running) 796 && beaconParams.paramChangeBitmap) { 797 pe_debug("Beacon for session[%d] got changed param change bitmap: 0x%x", 798 session->peSessionId, beaconParams.paramChangeBitmap); 799 lim_send_beacon_params(mac_ctx, &beaconParams, session); 800 } 801 802 if ((session->opmode == QDF_P2P_CLIENT_MODE) && 803 session->send_p2p_conf_frame) { 804 lim_p2p_oper_chan_change_confirm_action_frame(mac_ctx, 805 session->bssId, 806 session); 807 session->send_p2p_conf_frame = false; 808 } 809 810 lim_process_beacon_eht(mac_ctx, session, bcn); 811 lim_process_bcn_prb_rsp_t2lm(mac_ctx, session, bcn); 812 } 813 814 #ifdef WLAN_FEATURE_11AX_BSS_COLOR 815 static void ap_update_bss_color_info(struct mac_context *mac_ctx, 816 struct pe_session *session, 817 uint8_t bss_color) 818 { 819 if (!session) 820 return; 821 822 if (bss_color < 1 || bss_color > 63) { 823 pe_warn("Invalid BSS color"); 824 return; 825 } 826 827 session->bss_color_info[bss_color - 1].seen_count++; 828 session->bss_color_info[bss_color - 1].timestamp = 829 qdf_get_system_timestamp(); 830 } 831 832 static uint8_t ap_get_new_bss_color(struct mac_context *mac_ctx, struct pe_session *session) 833 { 834 int i; 835 uint8_t new_bss_color; 836 struct bss_color_info color_info; 837 qdf_time_t cur_timestamp; 838 839 if (!session) 840 return 0; 841 842 color_info = session->bss_color_info[0]; 843 new_bss_color = 0; 844 cur_timestamp = qdf_get_system_timestamp(); 845 for (i = 1; i < MAX_BSS_COLOR_VALUE; i++) { 846 if (session->bss_color_info[i].seen_count == 0) { 847 new_bss_color = i + 1; 848 return new_bss_color; 849 } 850 851 if (color_info.seen_count > 852 session->bss_color_info[i].seen_count && 853 (cur_timestamp - session->bss_color_info[i]. 854 timestamp) > TIME_BEACON_NOT_UPDATED) { 855 color_info = session->bss_color_info[i]; 856 new_bss_color = i + 1; 857 } 858 } 859 pe_debug("new bss color: %d", new_bss_color); 860 return new_bss_color; 861 } 862 863 static void sch_check_bss_color_ie(struct mac_context *mac_ctx, 864 struct pe_session *ap_session, 865 tSchBeaconStruct *bcn, 866 tUpdateBeaconParams *bcn_prm) 867 { 868 /* check bss color in the beacon */ 869 if (ap_session->he_op.present && !ap_session->he_op.bss_color) { 870 if (bcn->he_op.present && 871 (bcn->he_op.bss_color == 872 ap_session->he_op.bss_color)) { 873 ap_session->he_op.bss_col_disabled = 1; 874 bcn_prm->paramChangeBitmap |= 875 PARAM_BSS_COLOR_CHANGED; 876 ap_session->he_bss_color_change.countdown = 877 BSS_COLOR_SWITCH_COUNTDOWN; 878 ap_session->he_bss_color_change.new_color = 879 ap_get_new_bss_color(mac_ctx, 880 ap_session); 881 ap_session->he_op.bss_color = ap_session-> 882 he_bss_color_change.new_color; 883 bcn_prm->bss_color = ap_session->he_op.bss_color; 884 bcn_prm->bss_color_disabled = 885 ap_session->he_op.bss_col_disabled; 886 ap_session->bss_color_changing = 1; 887 } else { 888 /* update info for the bss color */ 889 if (bcn->he_op.present) 890 ap_update_bss_color_info(mac_ctx, 891 ap_session, 892 bcn->he_op.bss_color); 893 } 894 } 895 } 896 897 #else 898 static void sch_check_bss_color_ie(struct mac_context *mac_ctx, 899 struct pe_session *ap_session, 900 tSchBeaconStruct *bcn, 901 tUpdateBeaconParams *bcn_prm) 902 { 903 } 904 #endif 905 906 void sch_beacon_process_for_ap(struct mac_context *mac_ctx, 907 uint8_t session_id, 908 uint8_t *rx_pkt_info, 909 tSchBeaconStruct *bcn) 910 { 911 struct pe_session *ap_session; 912 tUpdateBeaconParams bcn_prm; 913 914 if (!bcn || !rx_pkt_info) { 915 pe_debug("bcn %pK or rx_pkt_info %pKis NULL", 916 bcn, rx_pkt_info); 917 return; 918 } 919 920 ap_session = pe_find_session_by_session_id(mac_ctx, session_id); 921 if (!ap_session) 922 return; 923 924 if (!LIM_IS_AP_ROLE(ap_session)) 925 return; 926 927 qdf_mem_zero(&bcn_prm, sizeof(tUpdateBeaconParams)); 928 bcn_prm.paramChangeBitmap = 0; 929 930 bcn_prm.bss_idx = ap_session->vdev_id; 931 932 if (!ap_session->is_session_obss_color_collision_det_enabled) 933 sch_check_bss_color_ie(mac_ctx, ap_session, 934 bcn, &bcn_prm); 935 936 if ((ap_session->gLimProtectionControl != 937 MLME_FORCE_POLICY_PROTECTION_DISABLE) && 938 !ap_session->is_session_obss_offload_enabled) 939 ap_beacon_process(mac_ctx, rx_pkt_info, 940 bcn, &bcn_prm, ap_session); 941 942 if ((false == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running) 943 && bcn_prm.paramChangeBitmap) { 944 /* Update the bcn and apply the new settings to HAL */ 945 sch_set_fixed_beacon_fields(mac_ctx, ap_session); 946 pe_debug("Beacon for PE session[%d] got changed", 947 ap_session->peSessionId); 948 pe_debug("sending beacon param change bitmap: 0x%x", 949 bcn_prm.paramChangeBitmap); 950 lim_send_beacon_params(mac_ctx, &bcn_prm, ap_session); 951 } 952 } 953 954 #ifdef WLAN_BCN_RECV_FEATURE 955 /* 956 * sch_send_beacon_report() - To Fill beacon report for 957 * each beacon coming from connected peer and sends it 958 * to upper layer 959 * @mac_ctx: Mac context 960 * @beacon_struct: Pointing to beacon structure 961 * @session: pointer to the PE session 962 * 963 * Return: None 964 */ 965 static 966 void sch_send_beacon_report(struct mac_context *mac_ctx, 967 struct sSirProbeRespBeacon *beacon_struct, 968 struct pe_session *session) 969 { 970 struct wlan_beacon_report beacon_report; 971 beacon_report_cb sme_bcn_cb; 972 973 sme_bcn_cb = mac_ctx->lim.sme_bcn_rcv_callback; 974 if (!sme_bcn_cb) 975 return; 976 977 if (!LIM_IS_STA_ROLE(session)) 978 return; 979 980 if (sir_compare_mac_addr(session->bssId, beacon_struct->bssid)) { 981 /* Prepare beacon report from incoming beacon */ 982 qdf_mem_copy(beacon_report.bssid.bytes, beacon_struct->bssid, 983 sizeof(tSirMacAddr)); 984 985 qdf_mem_copy(&beacon_report.time_stamp, 986 &beacon_struct->timeStamp, sizeof(qdf_time_t)); 987 beacon_report.beacon_interval = beacon_struct->beaconInterval; 988 beacon_report.frequency = beacon_struct->chan_freq; 989 990 beacon_report.ssid.length = beacon_struct->ssId.length; 991 qdf_mem_copy(&beacon_report.ssid.ssid, 992 &beacon_struct->ssId.ssId, 993 beacon_report.ssid.length); 994 995 beacon_report.boot_time = 996 qdf_do_div(qdf_get_monotonic_boottime(), 997 QDF_MC_TIMER_TO_MS_UNIT); 998 999 beacon_report.vdev_id = session->vdev_id; 1000 1001 /* Send report to upper layer */ 1002 sme_bcn_cb(mac_ctx->hdd_handle, &beacon_report); 1003 } 1004 } 1005 1006 #else 1007 static inline 1008 void sch_send_beacon_report(struct mac_context *mac_ctx, 1009 struct sSirProbeRespBeacon *beacon_struct, 1010 struct pe_session *session) 1011 { 1012 } 1013 #endif 1014 1015 /** 1016 * sch_beacon_process() - process the beacon frame 1017 * @mac_ctx: mac global context 1018 * @rx_pkt_info: pointer to buffer descriptor 1019 * @session: pointer to the PE session 1020 * 1021 * Return: None 1022 */ 1023 void 1024 sch_beacon_process(struct mac_context *mac_ctx, uint8_t *rx_pkt_info, 1025 struct pe_session *session) 1026 { 1027 static tSchBeaconStruct bcn; 1028 1029 if (!session) 1030 return; 1031 1032 /* 1033 * Drop the beacon/probe response from current connected AP in 1034 * below cases to avoid responding to the changes in beacon(e.g. doing 1035 * VDEV_RESTART to update to the latest capabilities), 1036 * 1. vdev is not in connected state: vdev might be transitioning 1037 * 2. Link switch is in progress: Current link or one of the partner 1038 * links are getting replaced. 1039 * 1040 * New beacons/probe rsps can be considered once post these operations. 1041 */ 1042 if (LIM_IS_STA_ROLE(session) && 1043 (!wlan_cm_is_vdev_connected(session->vdev) || 1044 mlo_mgr_is_link_switch_in_progress(session->vdev))) { 1045 pe_debug_rl("vdev %d, drop beacon", session->vdev_id); 1046 return; 1047 } 1048 1049 /* Convert the beacon frame into a structure */ 1050 if (sir_convert_beacon_frame2_struct(mac_ctx, (uint8_t *) rx_pkt_info, 1051 &bcn) != QDF_STATUS_SUCCESS) { 1052 pe_err_rl("beacon parsing failed"); 1053 return; 1054 } 1055 1056 session->dtimPeriod = bcn.tim.dtimPeriod; 1057 1058 sch_send_beacon_report(mac_ctx, &bcn, session); 1059 __sch_beacon_process_for_session(mac_ctx, &bcn, rx_pkt_info, session); 1060 } 1061 1062 /** 1063 * sch_beacon_edca_process(): Process the EDCA parameter set in the received 1064 * beacon frame 1065 * 1066 * @mac_ctx: mac global context 1067 * @edca: reference to edca parameters in beacon struct 1068 * @session : pesession entry 1069 * 1070 * @return status of operation 1071 */ 1072 QDF_STATUS 1073 sch_beacon_edca_process(struct mac_context *mac, tSirMacEdcaParamSetIE *edca, 1074 struct pe_session *session) 1075 { 1076 bool follow_ap_edca; 1077 #ifdef FEATURE_WLAN_DIAG_SUPPORT 1078 host_log_qos_edca_pkt_type *log_ptr = NULL; 1079 #endif /* FEATURE_WLAN_DIAG_SUPPORT */ 1080 1081 if (!(mac->mlme_cfg)) { 1082 pe_err("invalid mlme cfg"); 1083 return QDF_STATUS_E_FAILURE; 1084 } 1085 1086 follow_ap_edca = mlme_get_follow_ap_edca_flag(session->vdev); 1087 1088 session->gLimEdcaParamSetCount = edca->qosInfo.count; 1089 session->gLimEdcaParams[QCA_WLAN_AC_BE] = edca->acbe; 1090 session->gLimEdcaParams[QCA_WLAN_AC_BK] = edca->acbk; 1091 session->gLimEdcaParams[QCA_WLAN_AC_VI] = edca->acvi; 1092 session->gLimEdcaParams[QCA_WLAN_AC_VO] = edca->acvo; 1093 1094 if (mac->mlme_cfg->edca_params.enable_edca_params && !follow_ap_edca) { 1095 session->gLimEdcaParams[QCA_WLAN_AC_VO].aci.aifsn = 1096 mac->mlme_cfg->edca_params.edca_ac_vo.vo_aifs; 1097 session->gLimEdcaParams[QCA_WLAN_AC_VI].aci.aifsn = 1098 mac->mlme_cfg->edca_params.edca_ac_vi.vi_aifs; 1099 session->gLimEdcaParams[QCA_WLAN_AC_BK].aci.aifsn = 1100 mac->mlme_cfg->edca_params.edca_ac_bk.bk_aifs; 1101 session->gLimEdcaParams[QCA_WLAN_AC_BE].aci.aifsn = 1102 mac->mlme_cfg->edca_params.edca_ac_be.be_aifs; 1103 1104 session->gLimEdcaParams[QCA_WLAN_AC_VO].cw.min = 1105 mac->mlme_cfg->edca_params.edca_ac_vo.vo_cwmin; 1106 session->gLimEdcaParams[QCA_WLAN_AC_VI].cw.min = 1107 mac->mlme_cfg->edca_params.edca_ac_vi.vi_cwmin; 1108 session->gLimEdcaParams[QCA_WLAN_AC_BK].cw.min = 1109 mac->mlme_cfg->edca_params.edca_ac_bk.bk_cwmin; 1110 session->gLimEdcaParams[QCA_WLAN_AC_BE].cw.min = 1111 mac->mlme_cfg->edca_params.edca_ac_be.be_cwmin; 1112 1113 session->gLimEdcaParams[QCA_WLAN_AC_VO].cw.max = 1114 mac->mlme_cfg->edca_params.edca_ac_vo.vo_cwmax; 1115 session->gLimEdcaParams[QCA_WLAN_AC_VI].cw.max = 1116 mac->mlme_cfg->edca_params.edca_ac_vi.vi_cwmax; 1117 session->gLimEdcaParams[QCA_WLAN_AC_BK].cw.max = 1118 mac->mlme_cfg->edca_params.edca_ac_bk.bk_cwmax; 1119 session->gLimEdcaParams[QCA_WLAN_AC_BE].cw.max = 1120 mac->mlme_cfg->edca_params.edca_ac_be.be_cwmax; 1121 } 1122 #ifdef FEATURE_WLAN_DIAG_SUPPORT 1123 WLAN_HOST_DIAG_LOG_ALLOC(log_ptr, host_log_qos_edca_pkt_type, 1124 LOG_WLAN_QOS_EDCA_C); 1125 if (log_ptr) { 1126 log_ptr->aci_be = session->gLimEdcaParams[QCA_WLAN_AC_BE].aci.aci; 1127 log_ptr->cw_be = 1128 session->gLimEdcaParams[QCA_WLAN_AC_BE].cw.max << 4 1129 | session->gLimEdcaParams[QCA_WLAN_AC_BE].cw.min; 1130 log_ptr->txoplimit_be = 1131 session->gLimEdcaParams[QCA_WLAN_AC_BE].txoplimit; 1132 log_ptr->aci_bk = 1133 session->gLimEdcaParams[QCA_WLAN_AC_BK].aci.aci; 1134 log_ptr->cw_bk = 1135 session->gLimEdcaParams[QCA_WLAN_AC_BK].cw.max << 4 1136 | session->gLimEdcaParams[QCA_WLAN_AC_BK].cw.min; 1137 log_ptr->txoplimit_bk = 1138 session->gLimEdcaParams[QCA_WLAN_AC_BK].txoplimit; 1139 log_ptr->aci_vi = 1140 session->gLimEdcaParams[QCA_WLAN_AC_VI].aci.aci; 1141 log_ptr->cw_vi = 1142 session->gLimEdcaParams[QCA_WLAN_AC_VI].cw.max << 4 1143 | session->gLimEdcaParams[QCA_WLAN_AC_VI].cw.min; 1144 log_ptr->txoplimit_vi = 1145 session->gLimEdcaParams[QCA_WLAN_AC_VI].txoplimit; 1146 log_ptr->aci_vo = 1147 session->gLimEdcaParams[QCA_WLAN_AC_VO].aci.aci; 1148 log_ptr->cw_vo = 1149 session->gLimEdcaParams[QCA_WLAN_AC_VO].cw.max << 4 1150 | session->gLimEdcaParams[QCA_WLAN_AC_VO].cw.min; 1151 log_ptr->txoplimit_vo = 1152 session->gLimEdcaParams[QCA_WLAN_AC_VO].txoplimit; 1153 } 1154 WLAN_HOST_DIAG_LOG_REPORT(log_ptr); 1155 #endif /* FEATURE_WLAN_DIAG_SUPPORT */ 1156 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", 1157 mac->mlme_cfg->edca_params.enable_edca_params, 1158 session->gLimEdcaParams[0].aci.aifsn, 1159 session->gLimEdcaParams[0].aci.acm, 1160 session->gLimEdcaParams[0].cw.min, 1161 session->gLimEdcaParams[0].cw.max, 1162 session->gLimEdcaParams[0].txoplimit, 1163 session->gLimEdcaParams[1].aci.aifsn, 1164 session->gLimEdcaParams[1].aci.acm, 1165 session->gLimEdcaParams[1].cw.min, 1166 session->gLimEdcaParams[1].cw.max, 1167 session->gLimEdcaParams[1].txoplimit, 1168 session->gLimEdcaParams[2].aci.aifsn, 1169 session->gLimEdcaParams[2].aci.acm, 1170 session->gLimEdcaParams[2].cw.min, 1171 session->gLimEdcaParams[2].cw.max, 1172 session->gLimEdcaParams[2].txoplimit, 1173 session->gLimEdcaParams[3].aci.aifsn, 1174 session->gLimEdcaParams[3].aci.acm, 1175 session->gLimEdcaParams[3].cw.min, 1176 session->gLimEdcaParams[3].cw.max, 1177 session->gLimEdcaParams[3].txoplimit); 1178 1179 return QDF_STATUS_SUCCESS; 1180 } 1181 1182 void lim_enable_obss_detection_config(struct mac_context *mac_ctx, 1183 struct pe_session *session) 1184 { 1185 QDF_STATUS status = QDF_STATUS_SUCCESS; 1186 1187 if (!session) { 1188 pe_err("Invalid session, protection not enabled"); 1189 return; 1190 } 1191 1192 if (session->gLimProtectionControl == 1193 MLME_FORCE_POLICY_PROTECTION_DISABLE) { 1194 pe_err("protectiond disabled, force policy, session %d", 1195 session->smeSessionId); 1196 return; 1197 } 1198 1199 if (mac_ctx->mlme_cfg->obss_ht40.obss_detection_offload_enabled) { 1200 status = lim_obss_send_detection_cfg(mac_ctx, session, true); 1201 if (QDF_IS_STATUS_ERROR(status)) { 1202 pe_err("vdev %d: offload enable failed, trying legacy", 1203 session->smeSessionId); 1204 session->is_session_obss_offload_enabled = false; 1205 } else { 1206 pe_debug("vdev %d: offload detection enabled", 1207 session->smeSessionId); 1208 session->is_session_obss_offload_enabled = true; 1209 lim_obss_send_detection_cfg(mac_ctx, session, true); 1210 } 1211 } 1212 1213 if (!mac_ctx->mlme_cfg->obss_ht40.obss_detection_offload_enabled || 1214 QDF_IS_STATUS_ERROR(status)) { 1215 status = qdf_mc_timer_start(&session-> 1216 protection_fields_reset_timer, 1217 SCH_PROTECTION_RESET_TIME); 1218 if (QDF_IS_STATUS_ERROR(status)) 1219 pe_err("vdev %d: start timer failed", 1220 session->smeSessionId); 1221 else 1222 pe_debug("vdev %d: legacy detection enabled", 1223 session->smeSessionId); 1224 } 1225 } 1226 1227 QDF_STATUS lim_obss_generate_detection_config(struct mac_context *mac_ctx, 1228 struct pe_session *session, 1229 struct obss_detection_cfg *cfg) 1230 { 1231 uint32_t phy_mode; 1232 enum reg_wifi_band rf_band = REG_BAND_UNKNOWN; 1233 struct obss_detection_cfg *cur_detect; 1234 1235 if (!mac_ctx || !session || !cfg) { 1236 pe_err("Invalid params mac_ctx %pK, session %pK, cfg %pK", 1237 mac_ctx, session, cfg); 1238 return QDF_STATUS_E_INVAL; 1239 } 1240 1241 lim_get_phy_mode(mac_ctx, &phy_mode, session); 1242 rf_band = session->limRFBand; 1243 qdf_mem_zero(cfg, sizeof(*cfg)); 1244 cur_detect = &session->current_obss_detection; 1245 1246 pe_debug("band:%d, phy_mode:%d, ht_cap:%d, ht_oper_mode:%d", 1247 rf_band, phy_mode, session->htCapability, 1248 mac_ctx->lim.gHTOperMode); 1249 pe_debug("assoc_sta: 11b:%d, 11g:%d, 11a:%d, ht20:%d", 1250 session->gLim11bParams.protectionEnabled, 1251 session->gLim11gParams.protectionEnabled, 1252 session->gLim11aParams.protectionEnabled, 1253 session->gLimHt20Params.protectionEnabled); 1254 pe_debug("obss: 11b:%d, 11g:%d, 11a:%d, ht20:%d", 1255 session->gLimOlbcParams.protectionEnabled, 1256 session->gLimOverlap11gParams.protectionEnabled, 1257 session->gLimOverlap11aParams.protectionEnabled, 1258 session->gLimOverlapHt20Params.protectionEnabled); 1259 pe_debug("detect: b_ap:%d, b_s:%d, g:%d, a:%d, htl:%d, htm:%d, ht20:%d", 1260 cur_detect->obss_11b_ap_detect_mode, 1261 cur_detect->obss_11b_sta_detect_mode, 1262 cur_detect->obss_11g_ap_detect_mode, 1263 cur_detect->obss_11a_detect_mode, 1264 cur_detect->obss_ht_legacy_detect_mode, 1265 cur_detect->obss_ht_mixed_detect_mode, 1266 cur_detect->obss_ht_20mhz_detect_mode); 1267 1268 if (rf_band == REG_BAND_2G) { 1269 if ((phy_mode == WNI_CFG_PHY_MODE_11G || 1270 session->htCapability) && 1271 !session->gLim11bParams.protectionEnabled) { 1272 if (!session->gLimOlbcParams.protectionEnabled && 1273 !session->gLimOverlap11gParams.protectionEnabled) { 1274 cfg->obss_11b_ap_detect_mode = 1275 OBSS_OFFLOAD_DETECTION_PRESENT; 1276 cfg->obss_11b_sta_detect_mode = 1277 OBSS_OFFLOAD_DETECTION_PRESENT; 1278 } else { 1279 if (cur_detect->obss_11b_ap_detect_mode == 1280 OBSS_OFFLOAD_DETECTION_PRESENT) 1281 cfg->obss_11b_ap_detect_mode = 1282 OBSS_OFFLOAD_DETECTION_ABSENT; 1283 if (cur_detect->obss_11b_sta_detect_mode == 1284 OBSS_OFFLOAD_DETECTION_PRESENT) 1285 cfg->obss_11b_sta_detect_mode = 1286 OBSS_OFFLOAD_DETECTION_ABSENT; 1287 } 1288 } else if (session->gLim11bParams.protectionEnabled) { 1289 session->gLimOlbcParams.protectionEnabled = false; 1290 } 1291 1292 if (session->htCapability && 1293 session->cfgProtection.overlapFromllg && 1294 !session->gLim11gParams.protectionEnabled) { 1295 if (!session->gLimOverlap11gParams.protectionEnabled) { 1296 cfg->obss_11g_ap_detect_mode = 1297 OBSS_OFFLOAD_DETECTION_PRESENT; 1298 cfg->obss_ht_legacy_detect_mode = 1299 OBSS_OFFLOAD_DETECTION_PRESENT; 1300 cfg->obss_ht_mixed_detect_mode = 1301 OBSS_OFFLOAD_DETECTION_PRESENT; 1302 } else { 1303 if (cur_detect->obss_11g_ap_detect_mode == 1304 OBSS_OFFLOAD_DETECTION_PRESENT) 1305 cfg->obss_11g_ap_detect_mode = 1306 OBSS_OFFLOAD_DETECTION_ABSENT; 1307 if (cur_detect->obss_ht_legacy_detect_mode == 1308 OBSS_OFFLOAD_DETECTION_PRESENT) 1309 cfg->obss_ht_legacy_detect_mode = 1310 OBSS_OFFLOAD_DETECTION_ABSENT; 1311 if (cur_detect->obss_ht_mixed_detect_mode == 1312 OBSS_OFFLOAD_DETECTION_PRESENT) 1313 cfg->obss_ht_mixed_detect_mode = 1314 OBSS_OFFLOAD_DETECTION_ABSENT; 1315 } 1316 } else if (session->gLim11gParams.protectionEnabled) { 1317 session->gLimOverlap11gParams.protectionEnabled = false; 1318 } 1319 1320 /* INI related settings */ 1321 if (mac_ctx->mlme_cfg->sta.ignore_peer_erp_info) 1322 cfg->obss_11b_sta_detect_mode = 1323 OBSS_OFFLOAD_DETECTION_DISABLED; 1324 1325 if (mac_ctx->mlme_cfg->sap_protection_cfg.ignore_peer_ht_opmode) 1326 cfg->obss_ht_legacy_detect_mode = 1327 OBSS_OFFLOAD_DETECTION_DISABLED; 1328 } 1329 1330 if ((rf_band == REG_BAND_5G) && session->htCapability) { 1331 if (!session->gLim11aParams.protectionEnabled) { 1332 if (!session->gLimOverlap11aParams.protectionEnabled) 1333 cfg->obss_11a_detect_mode = 1334 OBSS_OFFLOAD_DETECTION_PRESENT; 1335 else if (cur_detect->obss_11a_detect_mode == 1336 OBSS_OFFLOAD_DETECTION_PRESENT) 1337 cfg->obss_11a_detect_mode = 1338 OBSS_OFFLOAD_DETECTION_ABSENT; 1339 } else { 1340 session->gLimOverlap11aParams.protectionEnabled = false; 1341 } 1342 } 1343 1344 if (((rf_band == REG_BAND_2G) || (rf_band == REG_BAND_5G)) && 1345 session->htCapability) { 1346 1347 if (!session->gLimHt20Params.protectionEnabled) { 1348 if (!session->gLimOverlapHt20Params.protectionEnabled) { 1349 cfg->obss_ht_20mhz_detect_mode = 1350 OBSS_OFFLOAD_DETECTION_PRESENT; 1351 } else if (cur_detect->obss_ht_20mhz_detect_mode == 1352 OBSS_OFFLOAD_DETECTION_PRESENT) { 1353 cfg->obss_ht_20mhz_detect_mode = 1354 OBSS_OFFLOAD_DETECTION_ABSENT; 1355 } 1356 } else { 1357 session->gLimOverlapHt20Params.protectionEnabled = 1358 false; 1359 } 1360 } 1361 1362 pe_debug("b_ap:%d, b_s:%d, g:%d, a:%d, ht_le:%d, ht_m:%d, ht_20:%d", 1363 cfg->obss_11b_ap_detect_mode, 1364 cfg->obss_11b_sta_detect_mode, 1365 cfg->obss_11g_ap_detect_mode, 1366 cfg->obss_11a_detect_mode, 1367 cfg->obss_ht_legacy_detect_mode, 1368 cfg->obss_ht_mixed_detect_mode, 1369 cfg->obss_ht_20mhz_detect_mode); 1370 1371 return QDF_STATUS_SUCCESS; 1372 } 1373 1374 QDF_STATUS lim_obss_send_detection_cfg(struct mac_context *mac_ctx, 1375 struct pe_session *session, bool force) 1376 { 1377 QDF_STATUS status; 1378 struct obss_detection_cfg obss_cfg; 1379 struct wmi_obss_detection_cfg_param *req_param; 1380 1381 if (!session) { 1382 pe_err("Invalid session"); 1383 return QDF_STATUS_E_INVAL; 1384 } 1385 1386 if (!session->is_session_obss_offload_enabled) { 1387 pe_debug("obss offload protectiond disabled, session %d", 1388 session->smeSessionId); 1389 /* Send success */ 1390 return QDF_STATUS_SUCCESS; 1391 } 1392 1393 if (session->gLimProtectionControl == 1394 MLME_FORCE_POLICY_PROTECTION_DISABLE) { 1395 pe_debug("protectiond disabled, force from policy, session %d", 1396 session->smeSessionId); 1397 /* Send success */ 1398 return QDF_STATUS_SUCCESS; 1399 } 1400 1401 status = lim_obss_generate_detection_config(mac_ctx, 1402 session, 1403 &obss_cfg); 1404 if (QDF_IS_STATUS_ERROR(status)) { 1405 pe_err("Failed to generate obss detection cfg, session %d", 1406 session->smeSessionId); 1407 return status; 1408 } 1409 1410 if (qdf_mem_cmp(&session->obss_offload_cfg, &obss_cfg, sizeof(obss_cfg)) 1411 || force) { 1412 struct scheduler_msg msg = {0}; 1413 req_param = qdf_mem_malloc(sizeof(*req_param)); 1414 if (!req_param) 1415 return QDF_STATUS_E_NOMEM; 1416 qdf_mem_copy(&session->obss_offload_cfg, &obss_cfg, 1417 sizeof(obss_cfg)); 1418 req_param->vdev_id = session->smeSessionId; 1419 req_param->obss_detect_period_ms = OBSS_DETECTION_PERIOD_MS; 1420 req_param->obss_11b_ap_detect_mode = 1421 obss_cfg.obss_11b_ap_detect_mode; 1422 req_param->obss_11b_sta_detect_mode = 1423 obss_cfg.obss_11b_sta_detect_mode; 1424 req_param->obss_11g_ap_detect_mode = 1425 obss_cfg.obss_11g_ap_detect_mode; 1426 req_param->obss_11a_detect_mode = 1427 obss_cfg.obss_11a_detect_mode; 1428 req_param->obss_ht_legacy_detect_mode = 1429 obss_cfg.obss_ht_legacy_detect_mode; 1430 req_param->obss_ht_20mhz_detect_mode = 1431 obss_cfg.obss_ht_20mhz_detect_mode; 1432 req_param->obss_ht_mixed_detect_mode = 1433 obss_cfg.obss_ht_mixed_detect_mode; 1434 1435 msg.type = WMA_OBSS_DETECTION_REQ; 1436 msg.bodyptr = req_param; 1437 msg.reserved = 0; 1438 status = scheduler_post_message(QDF_MODULE_ID_PE, 1439 QDF_MODULE_ID_WMA, 1440 QDF_MODULE_ID_WMA, &msg); 1441 if (QDF_IS_STATUS_ERROR(status)) { 1442 qdf_mem_free(req_param); 1443 return status; 1444 } 1445 } else { 1446 pe_debug("Skipping WMA_OBSS_DETECTION_REQ, force = %d", force); 1447 } 1448 1449 return status; 1450 } 1451 1452 QDF_STATUS lim_process_obss_detection_ind(struct mac_context *mac_ctx, 1453 struct wmi_obss_detect_info 1454 *obss_detection) 1455 { 1456 QDF_STATUS status; 1457 uint32_t detect_masks; 1458 uint32_t reason; 1459 struct obss_detection_cfg *obss_cfg; 1460 bool enable; 1461 struct pe_session *session; 1462 tUpdateBeaconParams bcn_prm; 1463 enum reg_wifi_band rf_band = REG_BAND_UNKNOWN; 1464 struct obss_detection_cfg *cur_detect; 1465 1466 pe_debug("obss detect ind id %d, reason %d, msk 0x%x, " QDF_MAC_ADDR_FMT, 1467 obss_detection->vdev_id, obss_detection->reason, 1468 obss_detection->matched_detection_masks, 1469 QDF_MAC_ADDR_REF(obss_detection->matched_bssid_addr)); 1470 1471 session = pe_find_session_by_vdev_id(mac_ctx, obss_detection->vdev_id); 1472 if (!session) { 1473 pe_err("Failed to get session for id %d", 1474 obss_detection->vdev_id); 1475 return QDF_STATUS_E_INVAL; 1476 } 1477 1478 if (!LIM_IS_AP_ROLE(session)) { 1479 pe_err("session %d is not AP", obss_detection->vdev_id); 1480 return QDF_STATUS_E_INVAL; 1481 } 1482 1483 if (!session->is_session_obss_offload_enabled) { 1484 pe_err("Offload already disabled for session %d", 1485 obss_detection->vdev_id); 1486 return QDF_STATUS_SUCCESS; 1487 } 1488 1489 reason = obss_detection->reason; 1490 detect_masks = obss_detection->matched_detection_masks; 1491 1492 if (reason == OBSS_OFFLOAD_DETECTION_PRESENT) { 1493 enable = true; 1494 } else if (reason == OBSS_OFFLOAD_DETECTION_ABSENT) { 1495 enable = false; 1496 } else if (reason == OBSS_OFFLOAD_DETECTION_DISABLED) { 1497 /* 1498 * Most common reason for this event-type from firmware 1499 * is insufficient memory. 1500 * Disable offload OBSS detection and enable legacy-way 1501 * of detecting OBSS by parsing beacons. 1502 **/ 1503 session->is_session_obss_offload_enabled = false; 1504 pe_err("FW indicated obss offload disabled"); 1505 pe_err("Enabling host based detection, session %d", 1506 obss_detection->vdev_id); 1507 1508 status = qdf_mc_timer_start(&session-> 1509 protection_fields_reset_timer, 1510 SCH_PROTECTION_RESET_TIME); 1511 if (QDF_IS_STATUS_ERROR(status)) 1512 pe_err("cannot start protection reset timer"); 1513 1514 return QDF_STATUS_SUCCESS; 1515 } else { 1516 pe_err("Invalid reason %d, session %d", 1517 obss_detection->reason, 1518 obss_detection->vdev_id); 1519 return QDF_STATUS_E_INVAL; 1520 } 1521 1522 rf_band = session->limRFBand; 1523 qdf_mem_zero(&bcn_prm, sizeof(bcn_prm)); 1524 obss_cfg = &session->obss_offload_cfg; 1525 cur_detect = &session->current_obss_detection; 1526 1527 if (OBSS_DETECTION_IS_11B_AP(detect_masks)) { 1528 if (reason != obss_cfg->obss_11b_ap_detect_mode || 1529 rf_band != REG_BAND_2G) 1530 goto wrong_detection; 1531 1532 lim_enable11g_protection(mac_ctx, enable, true, 1533 &bcn_prm, session); 1534 cur_detect->obss_11b_ap_detect_mode = reason; 1535 } 1536 if (OBSS_DETECTION_IS_11B_STA(detect_masks)) { 1537 if (reason != obss_cfg->obss_11b_sta_detect_mode || 1538 rf_band != REG_BAND_2G) 1539 goto wrong_detection; 1540 1541 lim_enable11g_protection(mac_ctx, enable, true, 1542 &bcn_prm, session); 1543 cur_detect->obss_11b_sta_detect_mode = reason; 1544 } 1545 if (OBSS_DETECTION_IS_11G_AP(detect_masks)) { 1546 if (reason != obss_cfg->obss_11g_ap_detect_mode || 1547 rf_band != REG_BAND_2G) 1548 goto wrong_detection; 1549 1550 lim_enable_ht_protection_from11g(mac_ctx, enable, true, 1551 &bcn_prm, session); 1552 cur_detect->obss_11g_ap_detect_mode = reason; 1553 } 1554 if (OBSS_DETECTION_IS_11A(detect_masks)) { 1555 if (reason != obss_cfg->obss_11a_detect_mode || 1556 rf_band != REG_BAND_5G) 1557 goto wrong_detection; 1558 1559 lim_update_11a_protection(mac_ctx, enable, true, 1560 &bcn_prm, session); 1561 cur_detect->obss_11a_detect_mode = reason; 1562 } 1563 if (OBSS_DETECTION_IS_HT_LEGACY(detect_masks)) { 1564 /* for 5GHz, we have only 11a detection, which covers legacy */ 1565 if (reason != obss_cfg->obss_ht_legacy_detect_mode || 1566 rf_band != REG_BAND_2G) 1567 goto wrong_detection; 1568 1569 lim_enable_ht_protection_from11g(mac_ctx, enable, true, 1570 &bcn_prm, session); 1571 cur_detect->obss_ht_legacy_detect_mode = reason; 1572 } 1573 if (OBSS_DETECTION_IS_HT_MIXED(detect_masks)) { 1574 /* for 5GHz, we have only 11a detection, which covers ht mix */ 1575 if (reason != obss_cfg->obss_ht_mixed_detect_mode || 1576 rf_band != REG_BAND_2G) 1577 goto wrong_detection; 1578 1579 lim_enable_ht_protection_from11g(mac_ctx, enable, true, 1580 &bcn_prm, session); 1581 cur_detect->obss_ht_mixed_detect_mode = reason; 1582 } 1583 if (OBSS_DETECTION_IS_HT_20MHZ(detect_masks)) { 1584 if (reason != obss_cfg->obss_ht_20mhz_detect_mode) 1585 goto wrong_detection; 1586 1587 lim_enable_ht20_protection(mac_ctx, enable, true, 1588 &bcn_prm, session); 1589 cur_detect->obss_ht_20mhz_detect_mode = reason; 1590 } 1591 1592 if ((false == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running) && 1593 bcn_prm.paramChangeBitmap) { 1594 /* Update the bcn and apply the new settings to HAL */ 1595 sch_set_fixed_beacon_fields(mac_ctx, session); 1596 pe_debug("Beacon for PE session: %d got changed: 0x%x", 1597 session->smeSessionId, bcn_prm.paramChangeBitmap); 1598 if (!QDF_IS_STATUS_SUCCESS(lim_send_beacon_params( 1599 mac_ctx, &bcn_prm, session))) { 1600 pe_err("Failed to send beacon param, session %d", 1601 obss_detection->vdev_id); 1602 return QDF_STATUS_E_FAULT; 1603 } 1604 } 1605 1606 status = lim_obss_send_detection_cfg(mac_ctx, session, true); 1607 if (QDF_IS_STATUS_ERROR(status)) { 1608 pe_err("Failed to send obss detection cfg, session %d", 1609 obss_detection->vdev_id); 1610 return status; 1611 } 1612 1613 return QDF_STATUS_SUCCESS; 1614 1615 wrong_detection: 1616 /* 1617 * We may get this wrong detection before FW can update latest cfg, 1618 * So keeping log level debug 1619 **/ 1620 pe_debug("Wrong detection, session %d", obss_detection->vdev_id); 1621 1622 return QDF_STATUS_E_INVAL; 1623 } 1624