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