1 /* 2 * Copyright (c) 2011-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 lim_assoc_utils.cc contains the utility functions 22 * LIM uses while processing (Re) Association messages. 23 * Author: Chandra Modumudi 24 * Date: 02/13/02 25 * History:- 26 * Date Modified by Modification Information 27 * -------------------------------------------------------------------- 28 * 05/26/10 js WPA handling in (Re)Assoc frames 29 * 30 */ 31 32 #include "cds_api.h" 33 #include "ani_global.h" 34 #include "wni_api.h" 35 #include "sir_common.h" 36 37 #include "wni_cfg.h" 38 #include "cfg_ucfg_api.h" 39 40 #include "sch_api.h" 41 #include "utils_api.h" 42 #include "lim_utils.h" 43 #include "lim_assoc_utils.h" 44 #include "lim_security_utils.h" 45 #include "lim_ser_des_utils.h" 46 #include "lim_admit_control.h" 47 #include "lim_send_messages.h" 48 #include "lim_ft_defs.h" 49 #include "lim_session.h" 50 #include "lim_process_fils.h" 51 52 #include "qdf_types.h" 53 #include "wma_types.h" 54 #include "lim_types.h" 55 #include "wlan_utility.h" 56 #include "wlan_mlme_api.h" 57 #include "wma.h" 58 #include "../../core/src/vdev_mgr_ops.h" 59 60 #include <cdp_txrx_cfg.h> 61 #include <cdp_txrx_cmn.h> 62 #include <lim_mlo.h> 63 64 /** 65 * lim_cmp_ssid() - utility function to compare SSIDs 66 * @rx_ssid: Received SSID 67 * @session_entry: Session entry 68 * 69 * This function is called in various places within LIM code 70 * to determine whether received SSID is same as SSID in use. 71 * 72 * Return: zero if SSID matched, non-zero otherwise. 73 */ 74 uint32_t lim_cmp_ssid(tSirMacSSid *rx_ssid, struct pe_session *session_entry) 75 { 76 if (session_entry->ssId.length != rx_ssid->length) 77 return 1; 78 79 return qdf_mem_cmp(rx_ssid->ssId, &session_entry->ssId.ssId, 80 session_entry->ssId.length); 81 } 82 83 /** 84 * lim_compare_capabilities() 85 * 86 ***FUNCTION: 87 * This function is called during Association/Reassociation 88 * frame handling to determine whether received capabilities 89 * match with local capabilities or not. 90 * 91 ***LOGIC: 92 * 93 ***ASSUMPTIONS: 94 * NA 95 * 96 ***NOTE: 97 * NA 98 * 99 * @param mac - Pointer to Global MAC structure 100 * @param pAssocReq - Pointer to received Assoc Req frame 101 * @param pLocalCapabs - Pointer to local capabilities 102 * 103 * @return status - true for Capabilitity match else false. 104 */ 105 106 uint8_t 107 lim_compare_capabilities(struct mac_context *mac, 108 tSirAssocReq *pAssocReq, 109 tSirMacCapabilityInfo *pLocalCapabs, 110 struct pe_session *pe_session) 111 { 112 if (LIM_IS_AP_ROLE(pe_session) && 113 (pAssocReq->capabilityInfo.ibss)) { 114 /* Requesting STA asserting IBSS capability. */ 115 pe_debug("Requesting STA asserting IBSS capability"); 116 return false; 117 } 118 /* Compare CF capabilities */ 119 if (pAssocReq->capabilityInfo.cfPollable || 120 pAssocReq->capabilityInfo.cfPollReq) { 121 /* AP does not support PCF functionality */ 122 pe_debug(" AP does not support PCF functionality"); 123 return false; 124 } 125 /* Compare short preamble capability */ 126 if (pAssocReq->capabilityInfo.shortPreamble && 127 (pAssocReq->capabilityInfo.shortPreamble != 128 pLocalCapabs->shortPreamble)) { 129 /* Allowing a STA requesting short preamble while */ 130 /* AP does not support it */ 131 } 132 133 pe_debug("QoS in AssocReq: %d, local capabs qos: %d", 134 pAssocReq->capabilityInfo.qos, pLocalCapabs->qos); 135 136 /* Compare QoS capability */ 137 if (pAssocReq->capabilityInfo.qos && 138 (pAssocReq->capabilityInfo.qos != pLocalCapabs->qos)) 139 pe_debug("Received unmatched QOS but cfg to suppress - continuing"); 140 141 /* 142 * If AP supports shortSlot and if apple user has 143 * enforced association only from shortSlot station, 144 * then AP must reject any station that does not support 145 * shortSlot 146 */ 147 if (LIM_IS_AP_ROLE(pe_session) && 148 (pLocalCapabs->shortSlotTime == 1)) { 149 if (mac->mlme_cfg->feature_flags.accept_short_slot_assoc) { 150 if (pAssocReq->capabilityInfo.shortSlotTime != 151 pLocalCapabs->shortSlotTime) { 152 pe_err("AP rejects association as station doesn't support shortslot time"); 153 return false; 154 } 155 return false; 156 } 157 } 158 159 return true; 160 } /****** end lim_compare_capabilities() ******/ 161 162 /** 163 * lim_check_rx_basic_rates() 164 * 165 ***FUNCTION: 166 * This function is called during Association/Reassociation 167 * frame handling to determine whether received rates in 168 * Assoc/Reassoc request frames include all BSS basic rates 169 * or not. 170 * 171 ***LOGIC: 172 * 173 ***ASSUMPTIONS: 174 * NA 175 * 176 ***NOTE: 177 * NA 178 * 179 * @param rxRateSet - pointer to SSID structure 180 * 181 * @return status - true if ALL BSS basic rates are present in the 182 * received rateset else false. 183 */ 184 185 uint8_t 186 lim_check_rx_basic_rates(struct mac_context *mac, tSirMacRateSet rxRateSet, 187 struct pe_session *pe_session) 188 { 189 tSirMacRateSet *pRateSet, basicRate; 190 uint8_t i, j, k, match; 191 192 pRateSet = qdf_mem_malloc(sizeof(tSirMacRateSet)); 193 if (!pRateSet) 194 return false; 195 196 /* Copy operational rate set from session Entry */ 197 qdf_mem_copy(pRateSet->rate, (pe_session->rateSet.rate), 198 pe_session->rateSet.numRates); 199 200 pRateSet->numRates = pe_session->rateSet.numRates; 201 202 /* Extract BSS basic rateset from operational rateset */ 203 for (i = 0, j = 0; 204 ((i < pRateSet->numRates) && (i < SIR_MAC_MAX_NUMBER_OF_RATES)); 205 i++) { 206 if ((pRateSet->rate[i] & 0x80) == 0x80) { 207 /* msb is set, so this is a basic rate */ 208 basicRate.rate[j++] = pRateSet->rate[i]; 209 } 210 } 211 212 /* 213 * For each BSS basic rate, find if it is present in the 214 * received rateset. 215 */ 216 for (k = 0; k < j; k++) { 217 match = 0; 218 for (i = 0; 219 ((i < rxRateSet.numRates) && 220 (i < SIR_MAC_MAX_NUMBER_OF_RATES)); i++) { 221 if ((rxRateSet.rate[i] | 0x80) == basicRate.rate[k]) 222 match = 1; 223 } 224 225 if (!match) { 226 /* Free up memory allocated for rateset */ 227 qdf_mem_free((uint8_t *) pRateSet); 228 229 return false; 230 } 231 } 232 233 /* Free up memory allocated for rateset */ 234 qdf_mem_free((uint8_t *) pRateSet); 235 236 return true; 237 } /****** end lim_check_rx_basic_rates() ******/ 238 239 /** 240 * lim_check_mcs_set() 241 * 242 ***FUNCTION: 243 * This function is called during Association/Reassociation 244 * frame handling to determine whether received MCS rates in 245 * Assoc/Reassoc request frames includes all Basic MCS Rate Set or not. 246 * 247 ***LOGIC: 248 * 249 ***ASSUMPTIONS: 250 * NA 251 * 252 ***NOTE: 253 * NA 254 * 255 * @param supportedMCSSet - pointer to Supported MCS Rate Set 256 * 257 * @return status - true if ALL MCS Basic Rate Set rates are present in the 258 * received rateset else false. 259 */ 260 261 uint8_t lim_check_mcs_set(struct mac_context *mac, uint8_t *supportedMCSSet) 262 { 263 uint8_t basicMCSSet[SIZE_OF_BASIC_MCS_SET] = { 0 }; 264 qdf_size_t cfg_len = 0; 265 uint8_t i; 266 uint8_t validBytes; 267 uint8_t lastByteMCSMask = 0x1f; 268 269 cfg_len = mac->mlme_cfg->rates.basic_mcs_set.len; 270 if (wlan_mlme_get_cfg_str((uint8_t *)basicMCSSet, 271 &mac->mlme_cfg->rates.basic_mcs_set, 272 &cfg_len) != QDF_STATUS_SUCCESS) { 273 /* / Could not get Basic MCS rateset from CFG. Log error. */ 274 pe_err("could not retrieve Basic MCS rateset"); 275 return false; 276 } 277 278 validBytes = VALID_MCS_SIZE / 8; 279 280 /* check if all the Basic MCS Bits are set in supported MCS bitmap */ 281 for (i = 0; i < validBytes; i++) { 282 if ((basicMCSSet[i] & supportedMCSSet[i]) != basicMCSSet[i]) { 283 pe_warn("One of Basic MCS Set Rates is not supported by the Station"); 284 return false; 285 } 286 } 287 288 /* check the last 5 bits of the valid MCS bitmap */ 289 if (((basicMCSSet[i] & lastByteMCSMask) & 290 (supportedMCSSet[i] & lastByteMCSMask)) != 291 (basicMCSSet[i] & lastByteMCSMask)) { 292 pe_warn("One of Basic MCS Set Rates is not supported by the Station"); 293 return false; 294 } 295 296 return true; 297 } 298 299 #define SECURITY_SUITE_TYPE_MASK 0xFF 300 #define SECURITY_SUITE_TYPE_WEP40 0x1 301 #define SECURITY_SUITE_TYPE_TKIP 0x2 302 #define SECURITY_SUITE_TYPE_CCMP 0x4 303 #define SECURITY_SUITE_TYPE_WEP104 0x4 304 #define SECURITY_SUITE_TYPE_GCMP 0x8 305 #define SECURITY_SUITE_TYPE_GCMP_256 0x9 306 307 /** 308 *lim_del_peer_info() - remove all peer information from host driver and fw 309 * @mac: Pointer to Global MAC structure 310 * @pe_session: Pointer to PE Session entry 311 * 312 * @Return: QDF_STATUS 313 */ 314 315 QDF_STATUS lim_del_peer_info(struct mac_context *mac, 316 struct pe_session *pe_session) 317 { 318 void *soc = cds_get_context(QDF_MODULE_ID_SOC); 319 uint16_t i; 320 uint32_t bitmap = 1 << CDP_PEER_DELETE_NO_SPECIAL; 321 bool peer_unmap_conf_support_enabled; 322 323 peer_unmap_conf_support_enabled = 324 cdp_cfg_get_peer_unmap_conf_support(soc); 325 326 for (i = 0; i < pe_session->dph.dphHashTable.size; i++) { 327 tpDphHashNode sta_ds; 328 329 sta_ds = dph_get_hash_entry(mac, i, 330 &pe_session->dph.dphHashTable); 331 if (!sta_ds) 332 continue; 333 334 cdp_peer_teardown(soc, pe_session->vdev_id, sta_ds->staAddr); 335 if (peer_unmap_conf_support_enabled) 336 cdp_peer_delete_sync(soc, pe_session->vdev_id, 337 sta_ds->staAddr, 338 wma_peer_unmap_conf_cb, 339 bitmap); 340 else 341 cdp_peer_delete(soc, pe_session->vdev_id, 342 sta_ds->staAddr, bitmap); 343 } 344 return QDF_STATUS_SUCCESS; 345 } 346 347 /** 348 * lim_del_sta_all(): Cleanup all peers associated with VDEV 349 * @mac: Pointer to Global MAC structure 350 * @pe_session: Pointer to PE Session entry 351 * 352 * @Return: QDF Status of operation 353 */ 354 355 QDF_STATUS lim_del_sta_all(struct mac_context *mac, 356 struct pe_session *pe_session) 357 { 358 QDF_STATUS status = QDF_STATUS_SUCCESS; 359 struct vdev_mlme_obj *mlme_obj; 360 uint32_t i; 361 tpDphHashNode sta_ds; 362 363 if (!LIM_IS_AP_ROLE(pe_session)) 364 return QDF_STATUS_E_INVAL; 365 366 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(pe_session->vdev); 367 if (!mlme_obj) { 368 pe_err("vdev component object is NULL"); 369 return QDF_STATUS_E_FAILURE; 370 } 371 372 if (wlan_vdev_mlme_is_mlo_ap(pe_session->vdev)) { 373 for (i = 1; i < pe_session->dph.dphHashTable.size; i++) { 374 sta_ds = dph_get_hash_entry( 375 mac, i, 376 &pe_session->dph.dphHashTable); 377 if (!sta_ds) 378 continue; 379 if (lim_is_mlo_conn(pe_session, sta_ds)) 380 lim_mlo_delete_link_peer(pe_session, sta_ds); 381 } 382 } 383 status = vdev_mgr_peer_delete_all_send(mlme_obj); 384 if (status != QDF_STATUS_SUCCESS) { 385 pe_err("failed status = %d", status); 386 return status; 387 } 388 389 status = lim_del_peer_info(mac, pe_session); 390 391 return status; 392 } 393 394 QDF_STATUS 395 lim_cleanup_rx_path(struct mac_context *mac, tpDphHashNode sta, 396 struct pe_session *pe_session, bool delete_peer) 397 { 398 QDF_STATUS retCode = QDF_STATUS_SUCCESS; 399 400 pe_debug("Cleanup Rx Path for AID: %d limSmeState: %d, mlmState: %d, delete_peer %d", 401 sta->assocId, pe_session->limSmeState, 402 sta->mlmStaContext.mlmState, delete_peer); 403 404 pe_session->isCiscoVendorAP = false; 405 406 if (mac->lim.gLimAddtsSent) { 407 MTRACE(mac_trace 408 (mac, TRACE_CODE_TIMER_DEACTIVATE, 409 pe_session->peSessionId, eLIM_ADDTS_RSP_TIMER)); 410 tx_timer_deactivate(&mac->lim.lim_timers.gLimAddtsRspTimer); 411 pe_debug("Reset gLimAddtsSent flag and send addts timeout to SME"); 412 lim_process_sme_addts_rsp_timeout(mac, 413 mac->lim.gLimAddtsRspTimerCount); 414 } 415 416 if (sta->mlmStaContext.mlmState == eLIM_MLM_WT_ASSOC_CNF_STATE) { 417 lim_deactivate_and_change_per_sta_id_timer(mac, eLIM_CNF_WAIT_TIMER, 418 sta->assocId); 419 420 if (!sta->mlmStaContext.updateContext) { 421 /** 422 * There is no context at Polaris to delete. 423 * Release our assigned AID back to the free pool 424 */ 425 if (LIM_IS_AP_ROLE(pe_session)) { 426 lim_del_sta(mac, sta, true, pe_session); 427 return retCode; 428 } 429 lim_delete_dph_hash_entry(mac, sta->staAddr, 430 sta->assocId, pe_session); 431 432 return retCode; 433 } 434 } 435 /* delete all tspecs associated with this sta. */ 436 lim_admit_control_delete_sta(mac, sta->assocId); 437 438 /** 439 * Make STA hash entry invalid at eCPU so that DPH 440 * does not process any more data packets and 441 * releases those BDs 442 */ 443 sta->valid = 0; 444 lim_send_sme_tsm_ie_ind(mac, pe_session, 0, 0, 0); 445 /* Any roaming related changes should be above this line */ 446 if (!delete_peer) 447 return QDF_STATUS_SUCCESS; 448 449 sta->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE; 450 451 if (LIM_IS_STA_ROLE(pe_session)) { 452 MTRACE(mac_trace 453 (mac, TRACE_CODE_MLM_STATE, pe_session->peSessionId, 454 eLIM_MLM_WT_DEL_STA_RSP_STATE)); 455 pe_session->limMlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE; 456 /* Deactivating probe after heart beat timer */ 457 lim_deactivate_and_change_timer(mac, eLIM_JOIN_FAIL_TIMER); 458 } 459 460 /* Do DEL BSS or DEL STA only if ADD BSS was success */ 461 if (!pe_session->add_bss_failed) { 462 if (pe_session->limSmeState == eLIM_SME_JOIN_FAILURE_STATE) { 463 retCode = 464 lim_del_bss(mac, sta, pe_session->vdev_id, 465 pe_session); 466 } else 467 retCode = lim_del_sta(mac, 468 sta, true, pe_session); 469 } 470 471 return retCode; 472 473 } /*** end lim_cleanup_rx_path() ***/ 474 475 /** 476 * lim_send_del_sta_cnf() - Send Del sta confirmation 477 * @mac: Pointer to Global MAC structure 478 * @sta_dsaddr: sta ds address 479 * @staDsAssocId: sta ds association id 480 * @mlmStaContext: MLM station context 481 * @status_code: Status code 482 * @pe_session: Session entry 483 * 484 * This function is called to send appropriate CNF message to SME. 485 * 486 * Return: None 487 */ 488 void 489 lim_send_del_sta_cnf(struct mac_context *mac, struct qdf_mac_addr sta_dsaddr, 490 uint16_t staDsAssocId, 491 struct lim_sta_context mlmStaContext, 492 tSirResultCodes status_code, struct pe_session *pe_session) 493 { 494 tLimMlmDisassocCnf mlmDisassocCnf; 495 tLimMlmDeauthCnf mlmDeauthCnf; 496 tLimMlmPurgeStaInd mlmPurgeStaInd; 497 498 pe_debug("Sessionid: %d staDsAssocId: %d Trigger: %d status_code: %d sta_dsaddr: "QDF_MAC_ADDR_FMT, 499 pe_session->peSessionId, staDsAssocId, 500 mlmStaContext.cleanupTrigger, status_code, 501 QDF_MAC_ADDR_REF(sta_dsaddr.bytes)); 502 503 if (LIM_IS_STA_ROLE(pe_session)) { 504 /* Set BSSID at CFG to null */ 505 tSirMacAddr nullAddr = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 506 507 sir_copy_mac_addr(nullAddr, pe_session->bssId); 508 509 /* Free up buffer allocated for JoinReq held by */ 510 /* MLM state machine */ 511 if (pe_session->pLimMlmJoinReq) { 512 qdf_mem_free(pe_session->pLimMlmJoinReq); 513 pe_session->pLimMlmJoinReq = NULL; 514 } 515 516 pe_session->limAID = 0; 517 } 518 519 if ((mlmStaContext.cleanupTrigger == 520 eLIM_HOST_DISASSOC) || 521 (mlmStaContext.cleanupTrigger == 522 eLIM_LINK_MONITORING_DISASSOC) || 523 (mlmStaContext.cleanupTrigger == 524 eLIM_PROMISCUOUS_MODE_DISASSOC)) { 525 qdf_mem_copy((uint8_t *) &mlmDisassocCnf.peerMacAddr, 526 (uint8_t *) sta_dsaddr.bytes, QDF_MAC_ADDR_SIZE); 527 mlmDisassocCnf.resultCode = status_code; 528 mlmDisassocCnf.disassocTrigger = mlmStaContext.cleanupTrigger; 529 /* Update PE session Id */ 530 mlmDisassocCnf.sessionId = pe_session->peSessionId; 531 532 lim_post_sme_message(mac, 533 LIM_MLM_DISASSOC_CNF, 534 (uint32_t *) &mlmDisassocCnf); 535 } else if ((mlmStaContext.cleanupTrigger == 536 eLIM_HOST_DEAUTH) || 537 (mlmStaContext.cleanupTrigger == 538 eLIM_LINK_MONITORING_DEAUTH)) { 539 qdf_copy_macaddr(&mlmDeauthCnf.peer_macaddr, &sta_dsaddr); 540 mlmDeauthCnf.resultCode = status_code; 541 mlmDeauthCnf.deauthTrigger = mlmStaContext.cleanupTrigger; 542 /* PE session Id */ 543 mlmDeauthCnf.sessionId = pe_session->peSessionId; 544 545 lim_post_sme_message(mac, 546 LIM_MLM_DEAUTH_CNF, 547 (uint32_t *) &mlmDeauthCnf); 548 } else if ((mlmStaContext.cleanupTrigger == 549 eLIM_PEER_ENTITY_DISASSOC) || 550 (mlmStaContext.cleanupTrigger == eLIM_PEER_ENTITY_DEAUTH)) { 551 qdf_mem_copy((uint8_t *) &mlmPurgeStaInd.peerMacAddr, 552 (uint8_t *) sta_dsaddr.bytes, QDF_MAC_ADDR_SIZE); 553 mlmPurgeStaInd.reasonCode = 554 (uint8_t) mlmStaContext.disassocReason; 555 mlmPurgeStaInd.aid = staDsAssocId; 556 mlmPurgeStaInd.purgeTrigger = mlmStaContext.cleanupTrigger; 557 mlmPurgeStaInd.sessionId = pe_session->peSessionId; 558 559 lim_post_sme_message(mac, 560 LIM_MLM_PURGE_STA_IND, 561 (uint32_t *) &mlmPurgeStaInd); 562 } else if (mlmStaContext.cleanupTrigger == eLIM_JOIN_FAILURE) { 563 /* PE setup the peer entry in HW upfront, right after join is completed. */ 564 /* If there is a failure during rest of the assoc sequence, this context needs to be cleaned up. */ 565 uint8_t smesessionId; 566 567 smesessionId = pe_session->smeSessionId; 568 pe_session->limSmeState = eLIM_SME_JOIN_FAILURE_STATE; 569 MTRACE(mac_trace 570 (mac, TRACE_CODE_SME_STATE, pe_session->peSessionId, 571 pe_session->limSmeState)); 572 573 /* if it is a reassoc failure to join new AP */ 574 if ((mlmStaContext.resultCode == 575 eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE) 576 || (mlmStaContext.resultCode == eSIR_SME_FT_REASSOC_FAILURE) 577 || (mlmStaContext.resultCode == 578 eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE)) { 579 pe_debug("Lim Posting eWNI_SME_REASSOC_RSP to SME" 580 "resultCode: %d, status_code: %d," 581 "sessionId: %d", 582 mlmStaContext.resultCode, 583 mlmStaContext.protStatusCode, 584 pe_session->peSessionId); 585 586 lim_send_sme_join_reassoc_rsp(mac, eWNI_SME_REASSOC_RSP, 587 mlmStaContext.resultCode, 588 mlmStaContext.protStatusCode, 589 pe_session, smesessionId); 590 if (mlmStaContext.resultCode != eSIR_SME_SUCCESS) { 591 pe_delete_session(mac, pe_session); 592 pe_session = NULL; 593 } 594 } else { 595 qdf_mem_free(pe_session->lim_join_req); 596 pe_session->lim_join_req = NULL; 597 598 pe_debug("Lim Posting eWNI_SME_JOIN_RSP to SME." 599 "resultCode: %d,status_code: %d," 600 "sessionId: %d", 601 mlmStaContext.resultCode, 602 mlmStaContext.protStatusCode, 603 pe_session->peSessionId); 604 605 lim_send_sme_join_reassoc_rsp(mac, eWNI_SME_JOIN_RSP, 606 mlmStaContext.resultCode, 607 mlmStaContext.protStatusCode, 608 pe_session, smesessionId); 609 610 if (mlmStaContext.resultCode != eSIR_SME_SUCCESS) { 611 pe_delete_session(mac, pe_session); 612 pe_session = NULL; 613 } 614 } 615 616 } else if (mlmStaContext.cleanupTrigger == eLIM_DUPLICATE_ENTRY) { 617 618 qdf_mem_copy((uint8_t *) &mlmDisassocCnf.peerMacAddr, 619 (uint8_t *) sta_dsaddr.bytes, QDF_MAC_ADDR_SIZE); 620 mlmDisassocCnf.resultCode = status_code; 621 mlmDisassocCnf.disassocTrigger = eLIM_DUPLICATE_ENTRY; 622 /* Update PE session Id */ 623 mlmDisassocCnf.sessionId = pe_session->peSessionId; 624 625 lim_post_sme_message(mac, 626 LIM_MLM_DISASSOC_CNF, 627 (uint32_t *) &mlmDisassocCnf); 628 } 629 630 if (pe_session && !LIM_IS_AP_ROLE(pe_session)) { 631 pe_delete_session(mac, pe_session); 632 pe_session = NULL; 633 } 634 } 635 636 /** 637 * lim_reject_association() - function to reject Re/Association Request 638 * 639 * @mac_ctx: pointer to global mac structure 640 * @peer_addr: mac address of the peer 641 * @sub_type: Indicates whether it is Association Request (=0) or 642 * Reassociation Request (=1) frame 643 * @add_pre_auth_context:Indicates whether pre-auth context 644 * to be added for this STA 645 * @auth_type: Indicates auth type to be added 646 * @sta_id: Indicates staId of the STA being rejected 647 * association 648 * @delete_sta: Indicates whether to delete STA context 649 * at Polaris 650 * @result_code: Indicates what reasonCode to be sent in 651 * Re/Assoc response to STA 652 * @session_entry: pointer to PE session 653 * 654 * This function is called whenever Re/Association Request need 655 * to be rejected due to failure in assigning an AID or failure 656 * in adding STA context at Polaris or reject by applications. 657 * Resources allocated if any are freedup and (Re) Association 658 * Response frame is sent to requesting STA. Pre-Auth context 659 * will be added for this STA if it does not exist already 660 * 661 * Return: none 662 */ 663 664 void 665 lim_reject_association(struct mac_context *mac_ctx, tSirMacAddr peer_addr, 666 uint8_t sub_type, uint8_t add_pre_auth_context, 667 tAniAuthType auth_type, uint16_t sta_id, 668 uint8_t delete_sta, enum wlan_status_code result_code, 669 struct pe_session *session_entry) 670 { 671 tpDphHashNode sta_ds; 672 673 pe_debug("Sessionid: %d auth_type: %d sub_type: %d add_pre_auth_context: %d sta_id: %d delete_sta: %d result_code : %d peer_addr: " QDF_MAC_ADDR_FMT, 674 session_entry->peSessionId, auth_type, sub_type, 675 add_pre_auth_context, sta_id, delete_sta, result_code, 676 QDF_MAC_ADDR_REF(peer_addr)); 677 678 if (add_pre_auth_context) { 679 /* Create entry for this STA in pre-auth list */ 680 struct tLimPreAuthNode *auth_node; 681 682 auth_node = lim_acquire_free_pre_auth_node(mac_ctx, 683 &mac_ctx->lim.gLimPreAuthTimerTable); 684 685 if (auth_node) { 686 qdf_mem_copy((uint8_t *) auth_node->peerMacAddr, 687 peer_addr, sizeof(tSirMacAddr)); 688 auth_node->fTimerStarted = 0; 689 auth_node->mlmState = eLIM_MLM_AUTHENTICATED_STATE; 690 auth_node->authType = (tAniAuthType) auth_type; 691 auth_node->timestamp = qdf_mc_timer_get_system_ticks(); 692 lim_add_pre_auth_node(mac_ctx, auth_node); 693 } 694 } 695 696 sta_ds = dph_get_hash_entry(mac_ctx, sta_id, 697 &session_entry->dph.dphHashTable); 698 699 if (delete_sta == false) { 700 lim_send_assoc_rsp_mgmt_frame( 701 mac_ctx, 702 STATUS_AP_UNABLE_TO_HANDLE_NEW_STA, 703 1, peer_addr, sub_type, sta_ds, session_entry, 704 false); 705 pe_debug("Received Re/Assoc req when max associated STAs reached from " QDF_MAC_ADDR_FMT, 706 QDF_MAC_ADDR_REF(peer_addr)); 707 lim_send_sme_max_assoc_exceeded_ntf(mac_ctx, peer_addr, 708 session_entry->smeSessionId); 709 return; 710 } 711 712 if (!sta_ds) { 713 pe_err("No STA context, yet rejecting Association"); 714 return; 715 } 716 717 /* 718 * Polaris has state for this STA. 719 * Trigger cleanup. 720 */ 721 sta_ds->mlmStaContext.cleanupTrigger = eLIM_REASSOC_REJECT; 722 723 /* Receive path cleanup */ 724 lim_cleanup_rx_path(mac_ctx, sta_ds, session_entry, true); 725 726 /* 727 * Send Re/Association Response with 728 * status code to requesting STA. 729 */ 730 lim_send_assoc_rsp_mgmt_frame(mac_ctx, result_code, 0, peer_addr, 731 sub_type, sta_ds, session_entry, false); 732 733 if (session_entry->parsedAssocReq[sta_ds->assocId]) { 734 lim_free_assoc_req_frm_buf( 735 session_entry->parsedAssocReq[sta_ds->assocId]); 736 737 qdf_mem_free(session_entry->parsedAssocReq[sta_ds->assocId]); 738 session_entry->parsedAssocReq[sta_ds->assocId] = NULL; 739 } 740 } 741 742 void lim_free_assoc_req_frm_buf(tpSirAssocReq assoc_req) 743 { 744 if (!assoc_req) 745 return; 746 if (assoc_req->assoc_req_buf) { 747 qdf_nbuf_free(assoc_req->assoc_req_buf); 748 assoc_req->assoc_req_buf = NULL; 749 assoc_req->assocReqFrame = NULL; 750 assoc_req->assocReqFrameLength = 0; 751 } 752 } 753 754 bool lim_alloc_assoc_req_frm_buf(tpSirAssocReq assoc_req, 755 qdf_nbuf_t buf, uint32_t mac_header_len, 756 uint32_t frame_len) 757 { 758 if (!assoc_req) 759 return false; 760 assoc_req->assoc_req_buf = qdf_nbuf_clone(buf); 761 if (!assoc_req->assoc_req_buf) 762 return false; 763 assoc_req->assocReqFrame = qdf_nbuf_data(assoc_req->assoc_req_buf) + 764 mac_header_len; 765 assoc_req->assocReqFrameLength = frame_len; 766 767 return true; 768 } 769 770 /** 771 * lim_decide_ap_protection_on_ht20_delete() - function to update protection 772 * parameters. 773 * @mac_ctx: pointer to global mac structure 774 * @sta_ds: station node 775 * @beacon_params: ap beacon parameters 776 * @session_entry: pe session entry 777 * 778 * protection related function while HT20 station is getting deleted. 779 * 780 * Return: none 781 */ 782 static void 783 lim_decide_ap_protection_on_ht20_delete(struct mac_context *mac_ctx, 784 tpDphHashNode sta_ds, 785 tpUpdateBeaconParams beacon_params, 786 struct pe_session *session_entry) 787 { 788 uint32_t i = 0; 789 790 pe_debug("(%d) A HT 20 STA is disassociated. Addr is "QDF_MAC_ADDR_FMT, 791 session_entry->gLimHt20Params.numSta, 792 QDF_MAC_ADDR_REF(sta_ds->staAddr)); 793 794 if (session_entry->gLimHt20Params.numSta > 0) { 795 for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { 796 if (!session_entry->protStaCache[i].active) 797 continue; 798 799 if (!qdf_mem_cmp(session_entry->protStaCache[i].addr, 800 sta_ds->staAddr, sizeof(tSirMacAddr))) { 801 session_entry->gLimHt20Params.numSta--; 802 session_entry->protStaCache[i].active = 803 false; 804 break; 805 } 806 } 807 } 808 809 if (session_entry->gLimHt20Params.numSta == 0) { 810 /* disable protection */ 811 pe_debug("No 11B STA exists, PESessionID %d", 812 session_entry->peSessionId); 813 lim_enable_ht20_protection(mac_ctx, false, false, beacon_params, 814 session_entry); 815 } 816 } 817 818 /** 819 * lim_decide_ap_protection_on_delete() - update SAP protection on station 820 * deletion. 821 * @mac_ctx: pointer to global mac structure 822 * @sta_ds: station node 823 * @beacon_params: ap beacon parameters 824 * @session_entry: pe session entry 825 * 826 * Decides about protection related settings when a station is getting deleted. 827 * 828 * Return: none 829 */ 830 void 831 lim_decide_ap_protection_on_delete(struct mac_context *mac_ctx, 832 tpDphHashNode sta_ds, 833 tpUpdateBeaconParams beacon_params, 834 struct pe_session *session_entry) 835 { 836 uint32_t phy_mode; 837 tHalBitVal erp_enabled = eHAL_CLEAR; 838 enum reg_wifi_band rf_band = REG_BAND_UNKNOWN; 839 uint32_t i; 840 841 if (!sta_ds) 842 return; 843 844 lim_get_rf_band_new(mac_ctx, &rf_band, session_entry); 845 lim_get_phy_mode(mac_ctx, &phy_mode, session_entry); 846 erp_enabled = sta_ds->erpEnabled; 847 848 if ((REG_BAND_5G == rf_band) && 849 (true == session_entry->htCapability) && 850 (session_entry->beaconParams.llaCoexist) && 851 (false == sta_ds->mlmStaContext.htCapability)) { 852 /* 853 * we are HT. if we are 11A, then protection is not required or 854 * we are HT and 11A station is leaving. 855 * protection consideration required. 856 * HT station leaving ==> this case is commonly handled 857 * between both the bands below. 858 */ 859 pe_debug("(%d) A 11A STA is disassociated. Addr is "QDF_MAC_ADDR_FMT, 860 session_entry->gLim11aParams.numSta, 861 QDF_MAC_ADDR_REF(sta_ds->staAddr)); 862 for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { 863 if (session_entry->protStaCache[i].active && 864 (!qdf_mem_cmp( 865 session_entry->protStaCache[i].addr, 866 sta_ds->staAddr, 867 sizeof(tSirMacAddr)))) { 868 session_entry->protStaCache[i].active = false; 869 break; 870 } 871 } 872 873 if (session_entry->gLim11aParams.numSta == 0) { 874 /* disable protection */ 875 lim_update_11a_protection(mac_ctx, false, false, 876 beacon_params, session_entry); 877 } 878 } 879 880 /* we are HT or 11G and 11B station is getting deleted */ 881 if ((REG_BAND_2G == rf_band) && 882 (phy_mode == WNI_CFG_PHY_MODE_11G || 883 session_entry->htCapability) && 884 (erp_enabled == eHAL_CLEAR)) { 885 pe_debug("(%d) A legacy STA is disassociated. Addr is "QDF_MAC_ADDR_FMT, 886 session_entry->gLim11bParams.numSta, 887 QDF_MAC_ADDR_REF(sta_ds->staAddr)); 888 for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { 889 if (session_entry->protStaCache[i].active && 890 (!qdf_mem_cmp( 891 session_entry->protStaCache[i].addr, 892 sta_ds->staAddr, 893 sizeof(tSirMacAddr)))) { 894 session_entry->gLim11bParams.numSta--; 895 session_entry->protStaCache[i].active = 896 false; 897 break; 898 } 899 } 900 901 if (session_entry->gLim11bParams.numSta == 0) { 902 /* disable protection */ 903 lim_enable11g_protection(mac_ctx, false, false, 904 beacon_params, session_entry); 905 } 906 } 907 908 /* 909 * we are HT AP and non-11B station is leaving. 910 * 11g station is leaving 911 */ 912 if ((REG_BAND_2G == rf_band) && 913 session_entry->htCapability && 914 !sta_ds->mlmStaContext.htCapability) { 915 pe_debug("(%d) A 11g STA is disassociated. Addr is "QDF_MAC_ADDR_FMT, 916 session_entry->gLim11bParams.numSta, 917 QDF_MAC_ADDR_REF(sta_ds->staAddr)); 918 for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { 919 if (session_entry->protStaCache[i].active && 920 (!qdf_mem_cmp( 921 session_entry->protStaCache[i].addr, 922 sta_ds->staAddr, 923 sizeof(tSirMacAddr)))) { 924 session_entry->gLim11gParams.numSta--; 925 session_entry->protStaCache[i].active = false; 926 break; 927 } 928 } 929 930 if (session_entry->gLim11gParams.numSta == 0) { 931 /* disable protection */ 932 lim_enable_ht_protection_from11g(mac_ctx, false, false, 933 beacon_params, 934 session_entry); 935 } 936 } 937 938 if (!((true == session_entry->htCapability) && 939 (true == sta_ds->mlmStaContext.htCapability))) 940 return; 941 942 /* 943 * Applies to 2.4 as well as 5 GHZ. 944 * HT non-GF leaving 945 */ 946 if (!sta_ds->htGreenfield) { 947 pe_debug("(%d) A non-GF STA is disassociated. Addr is "QDF_MAC_ADDR_FMT, 948 session_entry->gLimNonGfParams.numSta, 949 QDF_MAC_ADDR_REF(sta_ds->staAddr)); 950 for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { 951 if (session_entry->protStaCache[i].active && 952 (!qdf_mem_cmp( 953 session_entry->protStaCache[i].addr, 954 sta_ds->staAddr, 955 sizeof(tSirMacAddr)))) { 956 session_entry->protStaCache[i].active = false; 957 break; 958 } 959 } 960 961 if (session_entry->gLimNonGfParams.numSta == 0) { 962 /* disable protection */ 963 lim_enable_ht_non_gf_protection(mac_ctx, false, false, 964 beacon_params, session_entry); 965 } 966 } 967 968 /* 969 * Applies to 2.4 as well as 5 GHZ. 970 * HT 20Mhz station leaving 971 */ 972 if (session_entry->beaconParams.ht20Coexist && 973 (eHT_CHANNEL_WIDTH_20MHZ == 974 sta_ds->htSupportedChannelWidthSet)) { 975 lim_decide_ap_protection_on_ht20_delete(mac_ctx, sta_ds, 976 beacon_params, session_entry); 977 } 978 979 /* 980 * Applies to 2.4 as well as 5 GHZ. 981 * LSIG TXOP not supporting staiton leaving 982 */ 983 if ((false == session_entry->beaconParams. 984 fLsigTXOPProtectionFullSupport) && 985 (false == sta_ds->htLsigTXOPProtection)) { 986 pe_debug("(%d) A HT LSIG not supporting STA is disassociated. Addr is "QDF_MAC_ADDR_FMT, 987 session_entry->gLimLsigTxopParams.numSta, 988 QDF_MAC_ADDR_REF(sta_ds->staAddr)); 989 for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { 990 if (session_entry->protStaCache[i].active && 991 (!qdf_mem_cmp( 992 session_entry->protStaCache[i].addr, 993 sta_ds->staAddr, 994 sizeof(tSirMacAddr)))) { 995 session_entry->protStaCache[i].active = false; 996 break; 997 } 998 } 999 1000 if (session_entry->gLimLsigTxopParams.numSta == 0) { 1001 /* disable protection */ 1002 lim_enable_ht_lsig_txop_protection(mac_ctx, true, 1003 false, beacon_params, session_entry); 1004 } 1005 } 1006 } 1007 1008 /** 1009 * lim_decide_short_preamble() - update short preamble parameters 1010 * @mac_ctx: pointer to global mac structure 1011 * @sta_ds: station node 1012 * @beacon_params: ap beacon parameters 1013 * @session_entry: pe session entry 1014 * 1015 * Decides about any short preamble related change because of new station 1016 * joining. 1017 * 1018 * Return: None 1019 */ 1020 static void lim_decide_short_preamble(struct mac_context *mac_ctx, 1021 tpDphHashNode sta_ds, 1022 tpUpdateBeaconParams beacon_params, 1023 struct pe_session *session_entry) 1024 { 1025 uint32_t i; 1026 1027 if (sta_ds->shortPreambleEnabled == eHAL_CLEAR) { 1028 pe_debug("(%d) A non-short preamble STA is disassociated. Addr is "QDF_MAC_ADDR_FMT, 1029 session_entry->gLimNoShortParams.numNonShortPreambleSta, 1030 QDF_MAC_ADDR_REF(sta_ds->staAddr)); 1031 for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { 1032 if (session_entry->gLimNoShortParams. 1033 staNoShortCache[i].active && 1034 (!qdf_mem_cmp(session_entry-> 1035 gLimNoShortParams. 1036 staNoShortCache[i].addr, 1037 sta_ds->staAddr, 1038 sizeof(tSirMacAddr)))) { 1039 session_entry->gLimNoShortParams. 1040 numNonShortPreambleSta--; 1041 session_entry->gLimNoShortParams. 1042 staNoShortCache[i].active = false; 1043 break; 1044 } 1045 } 1046 1047 if (session_entry->gLimNoShortParams.numNonShortPreambleSta) 1048 return; 1049 1050 /* 1051 * enable short preamble 1052 * reset the cache 1053 */ 1054 qdf_mem_zero((uint8_t *) &session_entry->gLimNoShortParams, 1055 sizeof(tLimNoShortParams)); 1056 if (lim_enable_short_preamble(mac_ctx, true, 1057 beacon_params, session_entry) != QDF_STATUS_SUCCESS) 1058 pe_err("Cannot enable short preamble"); 1059 } 1060 } 1061 1062 /** 1063 * lim_decide_short_slot() - update short slot time related parameters 1064 * @mac_ctx: pointer to global mac structure 1065 * @sta_ds: station node 1066 * @beacon_params: ap beacon parameters 1067 * @session_entry: pe session entry 1068 * 1069 * Decides about any short slot time related change because of station leaving 1070 * the BSS. 1071 * Return: None 1072 */ 1073 static void 1074 lim_decide_short_slot(struct mac_context *mac_ctx, tpDphHashNode sta_ds, 1075 tpUpdateBeaconParams beacon_params, 1076 struct pe_session *session_entry) 1077 { 1078 uint32_t i, val, non_short_slot_sta_count; 1079 1080 if (sta_ds->shortSlotTimeEnabled != eHAL_CLEAR) 1081 return; 1082 1083 pe_debug("(%d) A non-short slottime STA is disassociated. Addr is "QDF_MAC_ADDR_FMT, 1084 mac_ctx->lim.gLimNoShortSlotParams.numNonShortSlotSta, 1085 QDF_MAC_ADDR_REF(sta_ds->staAddr)); 1086 1087 val = mac_ctx->mlme_cfg->feature_flags.enable_short_slot_time_11g; 1088 1089 if (LIM_IS_AP_ROLE(session_entry)) { 1090 non_short_slot_sta_count = 1091 session_entry->gLimNoShortSlotParams.numNonShortSlotSta; 1092 for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { 1093 if (session_entry->gLimNoShortSlotParams. 1094 staNoShortSlotCache[i].active && 1095 (!qdf_mem_cmp(session_entry-> 1096 gLimNoShortSlotParams. 1097 staNoShortSlotCache[i].addr, 1098 sta_ds->staAddr, 1099 sizeof(tSirMacAddr)))) { 1100 non_short_slot_sta_count--; 1101 session_entry->gLimNoShortSlotParams. 1102 staNoShortSlotCache[i].active = false; 1103 break; 1104 } 1105 } 1106 1107 if (non_short_slot_sta_count == 0 && val) { 1108 /* 1109 * enable short slot time 1110 * reset the cache 1111 */ 1112 qdf_mem_zero((uint8_t *) &session_entry-> 1113 gLimNoShortSlotParams, 1114 sizeof(tLimNoShortSlotParams)); 1115 beacon_params->fShortSlotTime = true; 1116 beacon_params->paramChangeBitmap |= 1117 PARAM_SHORT_SLOT_TIME_CHANGED; 1118 session_entry->shortSlotTimeSupported = true; 1119 } 1120 session_entry->gLimNoShortSlotParams.numNonShortSlotSta = 1121 non_short_slot_sta_count; 1122 } else { 1123 non_short_slot_sta_count = 1124 mac_ctx->lim.gLimNoShortSlotParams.numNonShortSlotSta; 1125 for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { 1126 if (mac_ctx->lim.gLimNoShortSlotParams. 1127 staNoShortSlotCache[i].active && 1128 (!qdf_mem_cmp( 1129 mac_ctx->lim.gLimNoShortSlotParams. 1130 staNoShortSlotCache[i].addr, 1131 sta_ds->staAddr, 1132 sizeof(tSirMacAddr)))) { 1133 non_short_slot_sta_count--; 1134 mac_ctx->lim.gLimNoShortSlotParams. 1135 staNoShortSlotCache[i].active = false; 1136 break; 1137 } 1138 } 1139 1140 if (val && !non_short_slot_sta_count) { 1141 /* 1142 * enable short slot time 1143 * reset the cache 1144 */ 1145 qdf_mem_zero( 1146 (uint8_t *) &mac_ctx->lim.gLimNoShortSlotParams, 1147 sizeof(tLimNoShortSlotParams)); 1148 /*in case of AP set SHORT_SLOT_TIME to enable*/ 1149 if (LIM_IS_AP_ROLE(session_entry)) { 1150 beacon_params->fShortSlotTime = true; 1151 beacon_params->paramChangeBitmap |= 1152 PARAM_SHORT_SLOT_TIME_CHANGED; 1153 session_entry->shortSlotTimeSupported = true; 1154 } 1155 } 1156 mac_ctx->lim.gLimNoShortSlotParams.numNonShortSlotSta = 1157 non_short_slot_sta_count; 1158 } 1159 } 1160 1161 static uint8_t lim_get_nss_from_vht_mcs_map(uint16_t mcs_map) 1162 { 1163 uint8_t nss = 0; 1164 uint16_t mcs_mask = 0x3; 1165 1166 for (nss = 0; nss < VHT_MAX_NSS; nss++) { 1167 if ((mcs_map & mcs_mask) == mcs_mask) 1168 return nss; 1169 1170 mcs_mask = (mcs_mask << 2); 1171 } 1172 1173 return nss; 1174 } 1175 1176 static void lim_get_vht_gt80_nss(struct mac_context *mac_ctx, 1177 struct sDphHashNode *sta_ds, 1178 tDot11fIEVHTCaps *vht_caps, 1179 struct pe_session *session) 1180 { 1181 uint8_t nss; 1182 1183 if (!vht_caps->vht_extended_nss_bw_cap) { 1184 sta_ds->vht_160mhz_nss = 0; 1185 sta_ds->vht_80p80mhz_nss = 0; 1186 pe_debug("peer does not support vht extnd nss bw"); 1187 1188 return; 1189 } 1190 1191 nss = lim_get_nss_from_vht_mcs_map(vht_caps->rxMCSMap); 1192 1193 if (!nss) { 1194 pe_debug("Invalid peer VHT MCS map %0X", vht_caps->rxMCSMap); 1195 nss = 1; 1196 } 1197 1198 switch (vht_caps->supportedChannelWidthSet) { 1199 case VHT_CAP_NO_160M_SUPP: 1200 if (vht_caps->extended_nss_bw_supp == 1201 VHT_EXTD_NSS_80_HALF_NSS_160) { 1202 sta_ds->vht_160mhz_nss = nss / 2; 1203 sta_ds->vht_80p80mhz_nss = 0; 1204 } else if (vht_caps->extended_nss_bw_supp == 1205 VHT_EXTD_NSS_80_HALF_NSS_80P80) { 1206 sta_ds->vht_160mhz_nss = nss / 2; 1207 sta_ds->vht_80p80mhz_nss = nss / 2; 1208 } else if (vht_caps->extended_nss_bw_supp == 1209 VHT_EXTD_NSS_80_3QUART_NSS_80P80) { 1210 sta_ds->vht_160mhz_nss = (nss * 3) / 4; 1211 sta_ds->vht_80p80mhz_nss = (nss * 3) / 4; 1212 } else { 1213 sta_ds->vht_160mhz_nss = 0; 1214 sta_ds->vht_80p80mhz_nss = 0; 1215 } 1216 break; 1217 case VHT_CAP_160_SUPP: 1218 sta_ds->vht_160mhz_nss = nss; 1219 if (vht_caps->extended_nss_bw_supp == 1220 VHT_EXTD_NSS_160_HALF_NSS_80P80) { 1221 sta_ds->vht_80p80mhz_nss = nss / 2; 1222 } else if (vht_caps->extended_nss_bw_supp == 1223 VHT_EXTD_NSS_160_3QUART_NSS_80P80) { 1224 sta_ds->vht_80p80mhz_nss = (nss * 3) / 4; 1225 } else if (vht_caps->extended_nss_bw_supp == 1226 VHT_EXTD_NSS_2X_NSS_160_1X_NSS_80P80) { 1227 if (nss > (VHT_MAX_NSS / 2)) { 1228 pe_debug("Invalid extnd nss bw support val"); 1229 sta_ds->vht_80p80mhz_nss = nss / 2; 1230 break; 1231 } 1232 sta_ds->vht_160mhz_nss = nss * 2; 1233 if (session->nss == MAX_VDEV_NSS) 1234 break; 1235 if (!mac_ctx->mlme_cfg->vht_caps.vht_cap_info.enable2x2) 1236 break; 1237 session->nss *= 2; 1238 } else { 1239 sta_ds->vht_80p80mhz_nss = 0; 1240 } 1241 break; 1242 case VHT_CAP_160_AND_80P80_SUPP: 1243 if (vht_caps->extended_nss_bw_supp == 1244 VHT_EXTD_NSS_2X_NSS_80_1X_NSS_80P80) { 1245 if (nss > (VHT_MAX_NSS / 2)) { 1246 pe_debug("Invalid extnd nss bw support val"); 1247 break; 1248 } 1249 if (session->nss == MAX_VDEV_NSS) 1250 break; 1251 if (!mac_ctx->mlme_cfg->vht_caps.vht_cap_info.enable2x2) 1252 break; 1253 session->nss *= 2; 1254 } else { 1255 sta_ds->vht_160mhz_nss = nss; 1256 sta_ds->vht_80p80mhz_nss = nss; 1257 } 1258 break; 1259 default: 1260 sta_ds->vht_160mhz_nss = 0; 1261 sta_ds->vht_80p80mhz_nss = 0; 1262 } 1263 pe_debug("AP Nss config: 160MHz: %d, 80P80MHz %d", 1264 sta_ds->vht_160mhz_nss, sta_ds->vht_80p80mhz_nss); 1265 sta_ds->vht_160mhz_nss = QDF_MIN(sta_ds->vht_160mhz_nss, session->nss); 1266 sta_ds->vht_80p80mhz_nss = QDF_MIN(sta_ds->vht_80p80mhz_nss, 1267 session->nss); 1268 pe_debug("Session Nss config: 160MHz: %d, 80P80MHz %d, session Nss %d", 1269 sta_ds->vht_160mhz_nss, sta_ds->vht_80p80mhz_nss, 1270 session->nss); 1271 } 1272 1273 QDF_STATUS lim_populate_vht_mcs_set(struct mac_context *mac_ctx, 1274 struct supported_rates *rates, 1275 tDot11fIEVHTCaps *peer_vht_caps, 1276 struct pe_session *session_entry, 1277 uint8_t nss, 1278 struct sDphHashNode *sta_ds) 1279 { 1280 uint32_t self_sta_dot11mode = 0; 1281 uint16_t mcs_map_mask = MCSMAPMASK1x1; 1282 uint16_t mcs_map_mask2x2 = 0; 1283 struct mlme_vht_capabilities_info *vht_cap_info; 1284 1285 self_sta_dot11mode = mac_ctx->mlme_cfg->dot11_mode.dot11_mode; 1286 1287 if (!IS_DOT11_MODE_VHT(self_sta_dot11mode)) 1288 return QDF_STATUS_SUCCESS; 1289 1290 if (!peer_vht_caps || !peer_vht_caps->present) 1291 return QDF_STATUS_SUCCESS; 1292 1293 vht_cap_info = &mac_ctx->mlme_cfg->vht_caps.vht_cap_info; 1294 1295 rates->vhtRxMCSMap = (uint16_t)vht_cap_info->rx_mcs_map; 1296 rates->vhtTxMCSMap = (uint16_t)vht_cap_info->tx_mcs_map; 1297 rates->vhtRxHighestDataRate = 1298 (uint16_t)vht_cap_info->rx_supp_data_rate; 1299 rates->vhtTxHighestDataRate = 1300 (uint16_t)vht_cap_info->tx_supp_data_rate; 1301 1302 if (NSS_1x1_MODE == nss) { 1303 rates->vhtRxMCSMap |= VHT_MCS_1x1; 1304 rates->vhtTxMCSMap |= VHT_MCS_1x1; 1305 rates->vhtTxHighestDataRate = 1306 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1; 1307 rates->vhtRxHighestDataRate = 1308 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1; 1309 if (session_entry && !session_entry->ch_width && 1310 !vht_cap_info->enable_vht20_mcs9 && 1311 ((rates->vhtRxMCSMap & VHT_1x1_MCS_MASK) == 1312 VHT_1x1_MCS9_MAP)) { 1313 DISABLE_VHT_MCS_9(rates->vhtRxMCSMap, 1314 NSS_1x1_MODE); 1315 DISABLE_VHT_MCS_9(rates->vhtTxMCSMap, 1316 NSS_1x1_MODE); 1317 } 1318 } else { 1319 if (session_entry && !session_entry->ch_width && 1320 !vht_cap_info->enable_vht20_mcs9 && 1321 ((rates->vhtRxMCSMap & VHT_2x2_MCS_MASK) == 1322 VHT_2x2_MCS9_MAP)) { 1323 DISABLE_VHT_MCS_9(rates->vhtRxMCSMap, 1324 NSS_2x2_MODE); 1325 DISABLE_VHT_MCS_9(rates->vhtTxMCSMap, 1326 NSS_2x2_MODE); 1327 } 1328 } 1329 1330 if (peer_vht_caps->txSupDataRate) 1331 rates->vhtTxHighestDataRate = 1332 QDF_MIN(rates->vhtTxHighestDataRate, 1333 peer_vht_caps->txSupDataRate); 1334 if (peer_vht_caps->rxHighSupDataRate) 1335 rates->vhtRxHighestDataRate = 1336 QDF_MIN(rates->vhtRxHighestDataRate, 1337 peer_vht_caps->rxHighSupDataRate); 1338 1339 if (session_entry && session_entry->nss == NSS_2x2_MODE) 1340 mcs_map_mask2x2 = MCSMAPMASK2x2; 1341 1342 if ((peer_vht_caps->txMCSMap & mcs_map_mask) < 1343 (rates->vhtRxMCSMap & mcs_map_mask)) { 1344 rates->vhtRxMCSMap &= ~(mcs_map_mask); 1345 rates->vhtRxMCSMap |= (peer_vht_caps->txMCSMap & mcs_map_mask); 1346 } 1347 if ((peer_vht_caps->rxMCSMap & mcs_map_mask) < 1348 (rates->vhtTxMCSMap & mcs_map_mask)) { 1349 rates->vhtTxMCSMap &= ~(mcs_map_mask); 1350 rates->vhtTxMCSMap |= (peer_vht_caps->rxMCSMap & mcs_map_mask); 1351 } 1352 1353 if (mcs_map_mask2x2) { 1354 uint16_t peer_mcs_map, self_mcs_map; 1355 1356 peer_mcs_map = peer_vht_caps->txMCSMap & mcs_map_mask2x2; 1357 self_mcs_map = rates->vhtRxMCSMap & mcs_map_mask2x2; 1358 1359 if ((self_mcs_map != mcs_map_mask2x2) && 1360 ((peer_mcs_map == mcs_map_mask2x2) || 1361 (peer_mcs_map < self_mcs_map))) { 1362 rates->vhtRxMCSMap &= ~mcs_map_mask2x2; 1363 rates->vhtRxMCSMap |= peer_mcs_map; 1364 } 1365 1366 peer_mcs_map = (peer_vht_caps->rxMCSMap & mcs_map_mask2x2); 1367 self_mcs_map = (rates->vhtTxMCSMap & mcs_map_mask2x2); 1368 1369 if ((self_mcs_map != mcs_map_mask2x2) && 1370 ((peer_mcs_map == mcs_map_mask2x2) || 1371 (peer_mcs_map < self_mcs_map))) { 1372 rates->vhtTxMCSMap &= ~mcs_map_mask2x2; 1373 rates->vhtTxMCSMap |= peer_mcs_map; 1374 } 1375 } 1376 1377 pe_debug("RxMCSMap %x TxMCSMap %x", rates->vhtRxMCSMap, 1378 rates->vhtTxMCSMap); 1379 1380 if (!session_entry) 1381 return QDF_STATUS_SUCCESS; 1382 1383 session_entry->supported_nss_1x1 = 1384 ((rates->vhtTxMCSMap & VHT_MCS_1x1) == VHT_MCS_1x1) ? 1385 true : false; 1386 1387 if (!sta_ds || CH_WIDTH_80MHZ >= session_entry->ch_width) 1388 return QDF_STATUS_SUCCESS; 1389 1390 sta_ds->vht_extended_nss_bw_cap = 1391 peer_vht_caps->vht_extended_nss_bw_cap; 1392 lim_get_vht_gt80_nss(mac_ctx, sta_ds, peer_vht_caps, session_entry); 1393 1394 return QDF_STATUS_SUCCESS; 1395 } 1396 1397 static void lim_dump_ht_mcs_mask(uint8_t *self_mcs, uint8_t *peer_mcs) 1398 { 1399 uint32_t len = 0; 1400 uint8_t idx; 1401 uint8_t *buff; 1402 uint32_t buff_len; 1403 1404 /* 1405 * Buffer of (SIR_MAC_MAX_SUPPORTED_MCS_SET * 5) + 1 to consider the 4 1406 * char MCS eg 0xff and 1 space after it and 1 to end the string with 1407 * NULL. 1408 */ 1409 buff_len = (SIR_MAC_MAX_SUPPORTED_MCS_SET * 5) + 1; 1410 buff = qdf_mem_malloc(buff_len); 1411 if (!buff) 1412 return; 1413 1414 if (self_mcs) { 1415 for (idx = 0; idx < SIR_MAC_MAX_SUPPORTED_MCS_SET; idx++) 1416 len += qdf_scnprintf(buff + len, buff_len - len, 1417 "0x%x ", self_mcs[idx]); 1418 1419 pe_nofl_debug("SELF HT MCS: %s", buff); 1420 } 1421 1422 if (peer_mcs) { 1423 len = 0; 1424 for (idx = 0; idx < SIR_MAC_MAX_SUPPORTED_MCS_SET; idx++) 1425 len += qdf_scnprintf(buff + len, buff_len - len, 1426 "0x%x ", peer_mcs[idx]); 1427 1428 pe_nofl_debug("PEER HT MCS: %s", buff); 1429 } 1430 1431 qdf_mem_free(buff); 1432 } 1433 1434 QDF_STATUS lim_populate_own_rate_set(struct mac_context *mac_ctx, 1435 struct supported_rates *rates, 1436 uint8_t *supported_mcs_set, 1437 uint8_t basic_only, 1438 struct pe_session *session_entry, 1439 struct sDot11fIEVHTCaps *vht_caps, 1440 struct sDot11fIEhe_cap *he_caps, 1441 struct sDot11fIEeht_cap *eht_caps) 1442 { 1443 tSirMacRateSet temp_rate_set; 1444 tSirMacRateSet temp_rate_set2; 1445 uint32_t i, j, val, min, is_arate; 1446 uint32_t phy_mode = 0; 1447 uint32_t self_sta_dot11mode = 0; 1448 uint8_t a_rate_index = 0; 1449 uint8_t b_rate_index = 0; 1450 qdf_size_t val_len; 1451 1452 is_arate = 0; 1453 1454 self_sta_dot11mode = mac_ctx->mlme_cfg->dot11_mode.dot11_mode; 1455 lim_get_phy_mode(mac_ctx, &phy_mode, session_entry); 1456 1457 /* 1458 * Include 11b rates only when the device configured in 1459 * auto, 11a/b/g or 11b_only 1460 */ 1461 if ((self_sta_dot11mode == MLME_DOT11_MODE_ALL) || 1462 (self_sta_dot11mode == MLME_DOT11_MODE_11A) || 1463 (self_sta_dot11mode == MLME_DOT11_MODE_11AC) || 1464 (self_sta_dot11mode == MLME_DOT11_MODE_11N) || 1465 (self_sta_dot11mode == MLME_DOT11_MODE_11G) || 1466 (self_sta_dot11mode == MLME_DOT11_MODE_11B) || 1467 (self_sta_dot11mode == MLME_DOT11_MODE_11AX)) { 1468 val_len = mac_ctx->mlme_cfg->rates.supported_11b.len; 1469 wlan_mlme_get_cfg_str((uint8_t *)&temp_rate_set.rate, 1470 &mac_ctx->mlme_cfg->rates.supported_11b, 1471 &val_len); 1472 temp_rate_set.numRates = (uint8_t)val_len; 1473 } else { 1474 temp_rate_set.numRates = 0; 1475 } 1476 1477 /* Include 11a rates when the device configured in non-11b mode */ 1478 if (!IS_DOT11_MODE_11B(self_sta_dot11mode)) { 1479 val_len = mac_ctx->mlme_cfg->rates.supported_11a.len; 1480 wlan_mlme_get_cfg_str((uint8_t *)&temp_rate_set2.rate, 1481 &mac_ctx->mlme_cfg->rates.supported_11a, 1482 &val_len); 1483 temp_rate_set2.numRates = (uint8_t)val_len; 1484 } else { 1485 temp_rate_set2.numRates = 0; 1486 } 1487 1488 if ((temp_rate_set.numRates + temp_rate_set2.numRates) > 12) { 1489 pe_err("more than 12 rates in CFG"); 1490 return QDF_STATUS_E_FAILURE; 1491 } 1492 /* copy all rates in temp_rate_set, there are 12 rates max */ 1493 for (i = 0; i < temp_rate_set2.numRates; i++) 1494 temp_rate_set.rate[i + temp_rate_set.numRates] = 1495 temp_rate_set2.rate[i]; 1496 1497 temp_rate_set.numRates += temp_rate_set2.numRates; 1498 1499 /** 1500 * Sort rates in temp_rate_set (they are likely to be already sorted) 1501 * put the result in pSupportedRates 1502 */ 1503 1504 qdf_mem_zero(rates, sizeof(*rates)); 1505 for (i = 0; i < temp_rate_set.numRates; i++) { 1506 min = 0; 1507 val = 0xff; 1508 is_arate = 0; 1509 1510 for (j = 0; (j < temp_rate_set.numRates) && 1511 (j < SIR_MAC_MAX_NUMBER_OF_RATES); j++) { 1512 if ((uint32_t) (temp_rate_set.rate[j] & 0x7f) < 1513 val) { 1514 val = temp_rate_set.rate[j] & 0x7f; 1515 min = j; 1516 } 1517 } 1518 1519 if (sirIsArate(temp_rate_set.rate[min] & 0x7f)) 1520 is_arate = 1; 1521 1522 if (is_arate) 1523 rates->llaRates[a_rate_index++] = 1524 temp_rate_set.rate[min]; 1525 else 1526 rates->llbRates[b_rate_index++] = 1527 temp_rate_set.rate[min]; 1528 temp_rate_set.rate[min] = 0xff; 1529 } 1530 1531 if (IS_DOT11_MODE_HT(self_sta_dot11mode)) { 1532 val_len = SIZE_OF_SUPPORTED_MCS_SET; 1533 if (wlan_mlme_get_cfg_str( 1534 rates->supportedMCSSet, 1535 &mac_ctx->mlme_cfg->rates.supported_mcs_set, 1536 &val_len) != QDF_STATUS_SUCCESS) { 1537 pe_err("could not retrieve supportedMCSSet"); 1538 return QDF_STATUS_E_FAILURE; 1539 } 1540 1541 if (session_entry->nss == NSS_1x1_MODE) 1542 rates->supportedMCSSet[1] = 0; 1543 /* 1544 * if supported MCS Set of the peer is passed in, 1545 * then do the intersection 1546 * else use the MCS set from local CFG. 1547 */ 1548 1549 if (supported_mcs_set) { 1550 for (i = 0; i < SIR_MAC_MAX_SUPPORTED_MCS_SET; i++) 1551 rates->supportedMCSSet[i] &= 1552 supported_mcs_set[i]; 1553 } 1554 1555 lim_dump_ht_mcs_mask(rates->supportedMCSSet, NULL); 1556 } 1557 lim_populate_vht_mcs_set(mac_ctx, rates, vht_caps, session_entry, 1558 session_entry->nss, NULL); 1559 lim_populate_he_mcs_set(mac_ctx, rates, he_caps, 1560 session_entry, session_entry->nss); 1561 lim_populate_eht_mcs_set(mac_ctx, rates, eht_caps, 1562 session_entry, session_entry->nss); 1563 1564 return QDF_STATUS_SUCCESS; 1565 } 1566 1567 #ifdef WLAN_FEATURE_11AX 1568 static bool lim_check_valid_mcs_for_nss(struct pe_session *session, 1569 tDot11fIEhe_cap *he_caps) 1570 { 1571 uint16_t mcs_map; 1572 uint8_t mcs_count = 2, i; 1573 1574 if (!session->he_capable || !he_caps || !he_caps->present) 1575 return true; 1576 1577 mcs_map = he_caps->rx_he_mcs_map_lt_80; 1578 1579 do { 1580 for (i = 0; i < session->nss; i++) { 1581 if (((mcs_map >> (i * 2)) & 0x3) == 0x3) 1582 return false; 1583 } 1584 1585 mcs_map = he_caps->tx_he_mcs_map_lt_80; 1586 mcs_count--; 1587 } while (mcs_count); 1588 1589 if ((session->ch_width == CH_WIDTH_160MHZ || 1590 lim_is_session_chwidth_320mhz(session)) && 1591 !he_caps->chan_width_2) { 1592 pe_err("session BW 160/320 MHz but peer BW less than 160 MHz"); 1593 return false; 1594 } 1595 1596 return true; 1597 1598 } 1599 #else 1600 static bool lim_check_valid_mcs_for_nss(struct pe_session *session, 1601 tDot11fIEhe_cap *he_caps) 1602 { 1603 return true; 1604 } 1605 #endif 1606 1607 /** 1608 * lim_remove_membership_selectors() - remove elements from rate set 1609 * 1610 * @rate_set: pointer to rate set 1611 * 1612 * Removes the BSS membership selector elements from the rate set, and keep 1613 * only the rates 1614 * 1615 * Return: none 1616 */ 1617 static void lim_remove_membership_selectors(tSirMacRateSet *rate_set) 1618 { 1619 int i, selector_count = 0; 1620 1621 for (i = 0; i < rate_set->numRates; i++) { 1622 if ((rate_set->rate[i] == (WLAN_BASIC_RATE_MASK | 1623 WLAN_BSS_MEMBERSHIP_SELECTOR_HT_PHY)) || 1624 (rate_set->rate[i] == (WLAN_BASIC_RATE_MASK | 1625 WLAN_BSS_MEMBERSHIP_SELECTOR_VHT_PHY)) || 1626 (rate_set->rate[i] == (WLAN_BASIC_RATE_MASK | 1627 WLAN_BSS_MEMBERSHIP_SELECTOR_GLK)) || 1628 (rate_set->rate[i] == (WLAN_BASIC_RATE_MASK | 1629 WLAN_BSS_MEMBERSHIP_SELECTOR_EPD)) || 1630 (rate_set->rate[i] == (WLAN_BASIC_RATE_MASK | 1631 WLAN_BSS_MEMBERSHIP_SELECTOR_SAE_H2E)) || 1632 (rate_set->rate[i] == (WLAN_BASIC_RATE_MASK | 1633 WLAN_BSS_MEMBERSHIP_SELECTOR_HE_PHY))) 1634 selector_count++; 1635 1636 if (i + selector_count < rate_set->numRates) 1637 rate_set->rate[i] = rate_set->rate[i + selector_count]; 1638 } 1639 rate_set->numRates -= selector_count; 1640 } 1641 1642 QDF_STATUS lim_populate_peer_rate_set(struct mac_context *mac, 1643 struct supported_rates *pRates, 1644 uint8_t *pSupportedMCSSet, 1645 uint8_t basicOnly, 1646 struct pe_session *pe_session, 1647 tDot11fIEVHTCaps *pVHTCaps, 1648 tDot11fIEhe_cap *he_caps, 1649 tDot11fIEeht_cap *eht_caps, 1650 struct sDphHashNode *sta_ds, 1651 struct bss_description *bss_desc) 1652 { 1653 tSirMacRateSet tempRateSet; 1654 tSirMacRateSet tempRateSet2; 1655 uint32_t i, j, val, min; 1656 qdf_size_t val_len; 1657 uint8_t aRateIndex = 0; 1658 uint8_t bRateIndex = 0; 1659 tDot11fIEhe_cap *peer_he_caps; 1660 tSchBeaconStruct *pBeaconStruct = NULL; 1661 1662 /* copy operational rate set from pe_session */ 1663 if (pe_session->rateSet.numRates <= SIR_MAC_MAX_NUMBER_OF_RATES) { 1664 qdf_mem_copy((uint8_t *) tempRateSet.rate, 1665 (uint8_t *) (pe_session->rateSet.rate), 1666 pe_session->rateSet.numRates); 1667 tempRateSet.numRates = pe_session->rateSet.numRates; 1668 } else { 1669 pe_err("more than SIR_MAC_MAX_NUMBER_OF_RATES rates"); 1670 return QDF_STATUS_E_FAILURE; 1671 } 1672 if ((pe_session->dot11mode == MLME_DOT11_MODE_11G) || 1673 (pe_session->dot11mode == MLME_DOT11_MODE_11A) || 1674 (pe_session->dot11mode == MLME_DOT11_MODE_11AC) || 1675 (pe_session->dot11mode == MLME_DOT11_MODE_11N) || 1676 (pe_session->dot11mode == MLME_DOT11_MODE_11AX)) { 1677 if (pe_session->extRateSet.numRates <= 1678 SIR_MAC_MAX_NUMBER_OF_RATES) { 1679 qdf_mem_copy((uint8_t *) tempRateSet2.rate, 1680 (uint8_t *) (pe_session->extRateSet. 1681 rate), 1682 pe_session->extRateSet.numRates); 1683 tempRateSet2.numRates = 1684 pe_session->extRateSet.numRates; 1685 } else { 1686 pe_err("numRates more than SIR_MAC_MAX_NUM_OF_RATES"); 1687 return QDF_STATUS_E_FAILURE; 1688 } 1689 } else 1690 tempRateSet2.numRates = 0; 1691 1692 lim_remove_membership_selectors(&tempRateSet); 1693 lim_remove_membership_selectors(&tempRateSet2); 1694 1695 if ((tempRateSet.numRates + tempRateSet2.numRates) > 1696 SIR_MAC_MAX_NUMBER_OF_RATES) { 1697 pe_err("rates in CFG are more than SIR_MAC_MAX_NUM_OF_RATES"); 1698 return QDF_STATUS_E_FAILURE; 1699 } 1700 1701 /* copy all rates in tempRateSet, there are 12 rates max */ 1702 for (i = 0; i < tempRateSet2.numRates; i++) 1703 tempRateSet.rate[i + tempRateSet.numRates] = 1704 tempRateSet2.rate[i]; 1705 tempRateSet.numRates += tempRateSet2.numRates; 1706 /** 1707 * Sort rates in tempRateSet (they are likely to be already sorted) 1708 * put the result in pSupportedRates 1709 */ 1710 1711 qdf_mem_zero(pRates, sizeof(*pRates)); 1712 for (i = 0; i < tempRateSet.numRates; i++) { 1713 min = 0; 1714 val = 0xff; 1715 for (j = 0; (j < tempRateSet.numRates) && 1716 (j < SIR_MAC_MAX_NUMBER_OF_RATES); j++) { 1717 if ((uint32_t)(tempRateSet.rate[j] & 0x7f) < 1718 val) { 1719 val = tempRateSet.rate[j] & 0x7f; 1720 min = j; 1721 } 1722 } 1723 /* 1724 * HAL needs to know whether the rate is basic rate or not, 1725 * as it needs to update the response rate table accordingly. 1726 * e.g. if one of the 11a rates is basic rate, then that rate 1727 * can be used for sending control frames. HAL updates the 1728 * response rate table whenever basic rate set is changed. 1729 */ 1730 if (basicOnly && !(tempRateSet.rate[min] & 0x80)) { 1731 pe_debug("Invalid basic rate"); 1732 } else if (sirIsArate(tempRateSet.rate[min] & 0x7f)) { 1733 if (aRateIndex >= SIR_NUM_11A_RATES) { 1734 pe_debug("OOB, aRateIndex: %d", aRateIndex); 1735 } else if (aRateIndex >= 1 && (tempRateSet.rate[min] == 1736 pRates->llaRates[aRateIndex - 1])) { 1737 pe_debug("Duplicate 11a rate: %d", 1738 tempRateSet.rate[min]); 1739 } else { 1740 pRates->llaRates[aRateIndex++] = 1741 tempRateSet.rate[min]; 1742 } 1743 } else if (sirIsBrate(tempRateSet.rate[min] & 0x7f)) { 1744 if (bRateIndex >= SIR_NUM_11B_RATES) { 1745 pe_debug("OOB, bRateIndex: %d", bRateIndex); 1746 } else if (bRateIndex >= 1 && (tempRateSet.rate[min] == 1747 pRates->llbRates[bRateIndex - 1])) { 1748 pe_debug("Duplicate 11b rate: %d", 1749 tempRateSet.rate[min]); 1750 } else { 1751 pRates->llbRates[bRateIndex++] = 1752 tempRateSet.rate[min]; 1753 } 1754 } else { 1755 pe_debug("%d is neither 11a nor 11b rate", 1756 tempRateSet.rate[min]); 1757 } 1758 tempRateSet.rate[min] = 0xff; 1759 } 1760 1761 if (IS_DOT11_MODE_HT(pe_session->dot11mode) && 1762 !lim_is_he_6ghz_band(pe_session)) { 1763 val_len = SIZE_OF_SUPPORTED_MCS_SET; 1764 if (wlan_mlme_get_cfg_str( 1765 pRates->supportedMCSSet, 1766 &mac->mlme_cfg->rates.supported_mcs_set, 1767 &val_len) != QDF_STATUS_SUCCESS) { 1768 pe_err("could not retrieve supportedMCSSet"); 1769 return QDF_STATUS_E_FAILURE; 1770 } 1771 if (pe_session->nss == NSS_1x1_MODE) 1772 pRates->supportedMCSSet[1] = 0; 1773 1774 /* if supported MCS Set of the peer is passed in, then do the 1775 * intersection, else use the MCS set from local CFG. 1776 */ 1777 if (pSupportedMCSSet) { 1778 for (i = 0; i < SIR_MAC_MAX_SUPPORTED_MCS_SET; i++) 1779 pRates->supportedMCSSet[i] &= 1780 pSupportedMCSSet[i]; 1781 } 1782 1783 lim_dump_ht_mcs_mask(NULL, pRates->supportedMCSSet); 1784 1785 if (pRates->supportedMCSSet[0] == 0) { 1786 pe_debug("Incorrect MCS 0 - 7. They must be supported"); 1787 pRates->supportedMCSSet[0] = 0xFF; 1788 } 1789 1790 pe_session->supported_nss_1x1 = 1791 ((pRates->supportedMCSSet[1] != 0) ? false : true); 1792 } 1793 lim_populate_vht_mcs_set(mac, pRates, pVHTCaps, pe_session, 1794 pe_session->nss, sta_ds); 1795 1796 if (lim_check_valid_mcs_for_nss(pe_session, he_caps)) { 1797 peer_he_caps = he_caps; 1798 } else { 1799 if (!bss_desc) { 1800 pe_err("bssDescription is NULL"); 1801 return QDF_STATUS_E_INVAL; 1802 } 1803 pBeaconStruct = qdf_mem_malloc(sizeof(tSchBeaconStruct)); 1804 if (!pBeaconStruct) 1805 return QDF_STATUS_E_NOMEM; 1806 1807 lim_extract_ap_capabilities( 1808 mac, (uint8_t *)bss_desc->ieFields, 1809 lim_get_ielen_from_bss_description(bss_desc), 1810 pBeaconStruct); 1811 peer_he_caps = &pBeaconStruct->he_cap; 1812 } 1813 1814 lim_populate_he_mcs_set(mac, pRates, peer_he_caps, 1815 pe_session, pe_session->nss); 1816 lim_populate_eht_mcs_set(mac, pRates, eht_caps, 1817 pe_session, pe_session->nss); 1818 1819 pe_debug("nss 1x1 %d nss %d", pe_session->supported_nss_1x1, 1820 pe_session->nss); 1821 1822 if (pBeaconStruct) 1823 qdf_mem_free(pBeaconStruct); 1824 1825 return QDF_STATUS_SUCCESS; 1826 } /*** lim_populate_peer_rate_set() ***/ 1827 1828 /** 1829 * lim_populate_matching_rate_set() -process the CFG rate sets and 1830 * the rate sets received in the Assoc request on AP. 1831 * @mac_ctx: pointer to global mac structure 1832 * @sta_ds: station node 1833 * @oper_rate_set: pointer to operating rate set 1834 * @ext_rate_set: pointer to extended rate set 1835 * @supported_mcs_set: pointer to supported rate set 1836 * @session_entry: pointer to pe session entry 1837 * @vht_caps: pointer to vht capabilities 1838 * @he_caps: pointer to he capabilities 1839 * @eht_caps: pointer to eht capabilities 1840 * 1841 * This is called at the time of Association Request 1842 * processing on AP and while adding peer's context 1843 * in IBSS role to process the CFG rate sets and 1844 * the rate sets received in the Assoc request on AP 1845 * 1846 * 1. It makes the intersection between our own rate set 1847 * and extended rate set and the ones received in the 1848 * association request. 1849 * 2. It creates a combined rate set of 12 rates max which 1850 * comprised the basic and extended rates 1851 * 3. It sorts the combined rate Set and copy it in the 1852 * rate array of the pSTA descriptor 1853 * 1854 * The parser has already ensured unicity of the rates in the 1855 * association request structure 1856 * 1857 * Return: QDF_STATUS_SUCCESS on success else QDF_STATUS_E_FAILURE 1858 */ 1859 QDF_STATUS lim_populate_matching_rate_set(struct mac_context *mac_ctx, 1860 tpDphHashNode sta_ds, 1861 tSirMacRateSet *oper_rate_set, 1862 tSirMacRateSet *ext_rate_set, 1863 uint8_t *supported_mcs_set, 1864 struct pe_session *session_entry, 1865 tDot11fIEVHTCaps *vht_caps, 1866 tDot11fIEhe_cap *he_caps, 1867 tDot11fIEeht_cap *eht_caps) 1868 { 1869 tSirMacRateSet temp_rate_set; 1870 tSirMacRateSet temp_rate_set2 = {0}; 1871 uint32_t i, j, val, min, is_arate; 1872 uint32_t phy_mode; 1873 uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET]; 1874 struct supported_rates *rates; 1875 uint8_t a_rate_index = 0; 1876 uint8_t b_rate_index = 0; 1877 qdf_size_t val_len; 1878 1879 is_arate = 0; 1880 1881 lim_get_phy_mode(mac_ctx, &phy_mode, session_entry); 1882 1883 /* copy operational rate set from session_entry */ 1884 qdf_mem_copy((temp_rate_set.rate), (session_entry->rateSet.rate), 1885 session_entry->rateSet.numRates); 1886 temp_rate_set.numRates = (uint8_t) session_entry->rateSet.numRates; 1887 1888 if (phy_mode == WNI_CFG_PHY_MODE_11G) { 1889 qdf_mem_copy((temp_rate_set2.rate), 1890 (session_entry->extRateSet.rate), 1891 session_entry->extRateSet.numRates); 1892 temp_rate_set2.numRates = 1893 (uint8_t) session_entry->extRateSet.numRates; 1894 } 1895 1896 lim_remove_membership_selectors(&temp_rate_set); 1897 lim_remove_membership_selectors(&temp_rate_set2); 1898 1899 /* 1900 * absolute sum of both num_rates should be less than 12. following 1901 * 16-bit sum avoids false condition where 8-bit arithmetic overflow 1902 * might have caused total sum to be less than 12 1903 */ 1904 if (((uint16_t)temp_rate_set.numRates + 1905 (uint16_t)temp_rate_set2.numRates) > SIR_MAC_MAX_NUMBER_OF_RATES) { 1906 pe_err("more than 12 rates in CFG"); 1907 return QDF_STATUS_E_FAILURE; 1908 } 1909 1910 /* 1911 * Handling of the rate set IEs is the following: 1912 * - keep only rates that we support and that the station supports 1913 * - sort and the rates into the pSta->rate array 1914 */ 1915 1916 /* Copy all rates in temp_rate_set, there are 12 rates max */ 1917 for (i = 0; i < temp_rate_set2.numRates; i++) 1918 temp_rate_set.rate[i + temp_rate_set.numRates] = 1919 temp_rate_set2.rate[i]; 1920 1921 temp_rate_set.numRates += temp_rate_set2.numRates; 1922 1923 /* 1924 * Sort rates in temp_rate_set (they are likely to be already sorted) 1925 * put the result in temp_rate_set2 1926 */ 1927 temp_rate_set2.numRates = 0; 1928 1929 for (i = 0; i < temp_rate_set.numRates; i++) { 1930 min = 0; 1931 val = 0xff; 1932 1933 for (j = 0; j < temp_rate_set.numRates; j++) 1934 if ((uint32_t) (temp_rate_set.rate[j] & 0x7f) < val) { 1935 val = temp_rate_set.rate[j] & 0x7f; 1936 min = j; 1937 } 1938 1939 temp_rate_set2.rate[temp_rate_set2.numRates++] = 1940 temp_rate_set.rate[min]; 1941 temp_rate_set.rate[min] = 0xff; 1942 } 1943 1944 /* 1945 * Copy received rates in temp_rate_set, the parser has ensured 1946 * unicity of the rates so there cannot be more than 12 1947 */ 1948 for (i = 0; (i < oper_rate_set->numRates && 1949 i < SIR_MAC_MAX_NUMBER_OF_RATES); i++) 1950 temp_rate_set.rate[i] = oper_rate_set->rate[i]; 1951 1952 temp_rate_set.numRates = oper_rate_set->numRates; 1953 1954 pe_debug("Sum of SUPPORTED and EXTENDED Rate Set (%1d)", 1955 temp_rate_set.numRates + ext_rate_set->numRates); 1956 1957 if (ext_rate_set->numRates && 1958 ((temp_rate_set.numRates + ext_rate_set->numRates) > 12) && 1959 temp_rate_set.numRates < 12) { 1960 int found = 0; 1961 int tail = temp_rate_set.numRates; 1962 1963 for (i = 0; (i < ext_rate_set->numRates && 1964 i < SIR_MAC_MAX_NUMBER_OF_RATES); i++) { 1965 found = 0; 1966 for (j = 0; j < (uint32_t) tail; j++) { 1967 if ((temp_rate_set.rate[j] & 0x7F) == 1968 (ext_rate_set->rate[i] & 0x7F)) { 1969 found = 1; 1970 break; 1971 } 1972 } 1973 1974 if (!found) { 1975 temp_rate_set.rate[temp_rate_set.numRates++] = 1976 ext_rate_set->rate[i]; 1977 if (temp_rate_set.numRates >= 12) 1978 break; 1979 } 1980 } 1981 } else if (ext_rate_set->numRates && 1982 ((temp_rate_set.numRates + ext_rate_set->numRates) <= 12)) { 1983 for (j = 0; ((j < ext_rate_set->numRates) && 1984 (j < SIR_MAC_MAX_NUMBER_OF_RATES) && 1985 ((i + j) < SIR_MAC_MAX_NUMBER_OF_RATES)); j++) 1986 temp_rate_set.rate[i + j] = ext_rate_set->rate[j]; 1987 1988 temp_rate_set.numRates += ext_rate_set->numRates; 1989 } else if (ext_rate_set->numRates) { 1990 pe_debug("Relying only on the SUPPORTED Rate Set IE"); 1991 } 1992 1993 rates = &sta_ds->supportedRates; 1994 qdf_mem_zero(rates, sizeof(*rates)); 1995 for (i = 0; (i < temp_rate_set2.numRates && 1996 i < SIR_MAC_MAX_NUMBER_OF_RATES); i++) { 1997 for (j = 0; (j < temp_rate_set.numRates && 1998 j < SIR_MAC_MAX_NUMBER_OF_RATES); j++) { 1999 if ((temp_rate_set2.rate[i] & 0x7F) != 2000 (temp_rate_set.rate[j] & 0x7F)) 2001 continue; 2002 2003 if (sirIsArate(temp_rate_set2.rate[i] & 0x7f) && 2004 a_rate_index < SIR_NUM_11A_RATES) { 2005 is_arate = 1; 2006 rates->llaRates[a_rate_index++] = 2007 temp_rate_set2.rate[i]; 2008 } else if ((b_rate_index < SIR_NUM_11B_RATES) && 2009 !(sirIsArate(temp_rate_set2.rate[i] & 0x7f))) { 2010 rates->llbRates[b_rate_index++] = 2011 temp_rate_set2.rate[i]; 2012 } 2013 break; 2014 } 2015 } 2016 2017 /* 2018 * Now add the Polaris rates only when Proprietary rates are enabled. 2019 * compute the matching MCS rate set, if peer is 11n capable and self 2020 * mode is 11n 2021 */ 2022 #ifdef FEATURE_WLAN_TDLS 2023 if (sta_ds->mlmStaContext.htCapability) 2024 #else 2025 if (IS_DOT11_MODE_HT(session_entry->dot11mode) && 2026 (sta_ds->mlmStaContext.htCapability)) 2027 #endif 2028 { 2029 val_len = SIZE_OF_SUPPORTED_MCS_SET; 2030 if (wlan_mlme_get_cfg_str( 2031 mcs_set, 2032 &mac_ctx->mlme_cfg->rates.supported_mcs_set, 2033 &val_len) != QDF_STATUS_SUCCESS) { 2034 pe_err("could not retrieve supportedMCSet"); 2035 return QDF_STATUS_E_FAILURE; 2036 } 2037 2038 if (session_entry->nss == NSS_1x1_MODE) 2039 mcs_set[1] = 0; 2040 2041 for (i = 0; i < val_len; i++) 2042 sta_ds->supportedRates.supportedMCSSet[i] = 2043 mcs_set[i] & supported_mcs_set[i]; 2044 2045 lim_dump_ht_mcs_mask(mcs_set, 2046 sta_ds->supportedRates.supportedMCSSet); 2047 } 2048 lim_populate_vht_mcs_set(mac_ctx, &sta_ds->supportedRates, vht_caps, 2049 session_entry, session_entry->nss, sta_ds); 2050 lim_populate_he_mcs_set(mac_ctx, &sta_ds->supportedRates, he_caps, 2051 session_entry, session_entry->nss); 2052 lim_populate_eht_mcs_set(mac_ctx, &sta_ds->supportedRates, eht_caps, 2053 session_entry, session_entry->nss); 2054 /* 2055 * Set the erpEnabled bit if the phy is in G mode and at least 2056 * one A rate is supported 2057 */ 2058 if ((phy_mode == WNI_CFG_PHY_MODE_11G) && is_arate) 2059 sta_ds->erpEnabled = eHAL_SET; 2060 2061 return QDF_STATUS_SUCCESS; 2062 } 2063 2064 /** 2065 * lim_populate_vht_caps() - populates vht capabilities based on input 2066 * capabilities 2067 * @input_caps: input capabilities based on which we format the vht 2068 * capabilities 2069 * 2070 * function to populate the supported vht capabilities. 2071 * 2072 * Return: vht capabilities derived based on input parameters. 2073 */ 2074 static uint32_t lim_populate_vht_caps(tDot11fIEVHTCaps input_caps) 2075 { 2076 uint32_t vht_caps; 2077 2078 vht_caps = ((input_caps.maxMPDULen << SIR_MAC_VHT_CAP_MAX_MPDU_LEN) | 2079 (input_caps.supportedChannelWidthSet << 2080 SIR_MAC_VHT_CAP_SUPP_CH_WIDTH_SET) | 2081 (input_caps.ldpcCodingCap << 2082 SIR_MAC_VHT_CAP_LDPC_CODING_CAP) | 2083 (input_caps.shortGI80MHz << 2084 SIR_MAC_VHT_CAP_SHORTGI_80MHZ) | 2085 (input_caps.shortGI160and80plus80MHz << 2086 SIR_MAC_VHT_CAP_SHORTGI_160_80_80MHZ) | 2087 (input_caps.txSTBC << SIR_MAC_VHT_CAP_TXSTBC) | 2088 (input_caps.rxSTBC << SIR_MAC_VHT_CAP_RXSTBC) | 2089 (input_caps.suBeamFormerCap << 2090 SIR_MAC_VHT_CAP_SU_BEAMFORMER_CAP) | 2091 (input_caps.suBeamformeeCap << 2092 SIR_MAC_VHT_CAP_SU_BEAMFORMEE_CAP) | 2093 (input_caps.csnofBeamformerAntSup << 2094 SIR_MAC_VHT_CAP_CSN_BEAMORMER_ANT_SUP) | 2095 (input_caps.numSoundingDim << 2096 SIR_MAC_VHT_CAP_NUM_SOUNDING_DIM) | 2097 (input_caps.muBeamformerCap << 2098 SIR_MAC_VHT_CAP_NUM_BEAM_FORMER_CAP) | 2099 (input_caps.muBeamformeeCap << 2100 SIR_MAC_VHT_CAP_NUM_BEAM_FORMEE_CAP) | 2101 (input_caps.vhtTXOPPS << 2102 SIR_MAC_VHT_CAP_TXOPPS) | 2103 (input_caps.htcVHTCap << 2104 SIR_MAC_VHT_CAP_HTC_CAP) | 2105 (input_caps.maxAMPDULenExp << 2106 SIR_MAC_VHT_CAP_MAX_AMDU_LEN_EXPO) | 2107 (input_caps.vhtLinkAdaptCap << 2108 SIR_MAC_VHT_CAP_LINK_ADAPT_CAP) | 2109 (input_caps.rxAntPattern << 2110 SIR_MAC_VHT_CAP_RX_ANTENNA_PATTERN) | 2111 (input_caps.txAntPattern << 2112 SIR_MAC_VHT_CAP_TX_ANTENNA_PATTERN) | 2113 (input_caps.extended_nss_bw_supp << 2114 SIR_MAC_VHT_CAP_EXTD_NSS_BW)); 2115 2116 return vht_caps; 2117 } 2118 2119 /** 2120 * lim_update_he_stbc_capable() - Update stbc capable flag based on 2121 * HE capability 2122 * @add_sta_params: add sta related parameters 2123 * 2124 * Update stbc cpable flag based on HE capability 2125 * 2126 * Return: None 2127 */ 2128 #ifdef WLAN_FEATURE_11AX 2129 static void lim_update_he_stbc_capable(tpAddStaParams add_sta_params) 2130 { 2131 if (add_sta_params && 2132 add_sta_params->he_capable && 2133 add_sta_params->stbc_capable) 2134 add_sta_params->stbc_capable = 2135 add_sta_params->he_config.rx_stbc_lt_80mhz; 2136 } 2137 2138 static void lim_update_he_mcs_12_13(tpAddStaParams add_sta_params, 2139 tpDphHashNode sta_ds) 2140 { 2141 pe_debug("he_mcs_12_13_map %0x", sta_ds->he_mcs_12_13_map); 2142 if (sta_ds->he_mcs_12_13_map) 2143 add_sta_params->he_mcs_12_13_map = sta_ds->he_mcs_12_13_map; 2144 } 2145 2146 static bool lim_is_add_sta_params_he_capable(tpAddStaParams add_sta_params) 2147 { 2148 return add_sta_params->he_capable; 2149 } 2150 #else 2151 static void lim_update_he_stbc_capable(tpAddStaParams add_sta_params) 2152 {} 2153 2154 static void lim_update_he_mcs_12_13(tpAddStaParams add_sta_params, 2155 tpDphHashNode sta_ds) 2156 {} 2157 2158 static bool lim_is_add_sta_params_he_capable(tpAddStaParams add_sta_params) 2159 { 2160 return false; 2161 } 2162 #endif 2163 2164 #ifdef FEATURE_WLAN_TDLS 2165 #ifdef WLAN_FEATURE_11BE 2166 static void lim_add_tdls_sta_eht_config(tpAddStaParams add_sta_params, 2167 tpDphHashNode sta_ds) 2168 { 2169 if (add_sta_params->eht_capable) { 2170 pe_debug("Adding tdls eht capabilities"); 2171 qdf_mem_copy(&add_sta_params->eht_config, &sta_ds->eht_config, 2172 sizeof(add_sta_params->eht_config)); 2173 qdf_mem_copy(&add_sta_params->eht_op, &sta_ds->eht_op, 2174 sizeof(add_sta_params->eht_op)); 2175 } 2176 } 2177 #else 2178 static void lim_add_tdls_sta_eht_config(tpAddStaParams add_sta_params, 2179 tpDphHashNode sta_ds) 2180 { 2181 } 2182 2183 #endif 2184 #ifdef WLAN_FEATURE_11AX 2185 static void lim_add_tdls_sta_he_config(tpAddStaParams add_sta_params, 2186 tpDphHashNode sta_ds) 2187 { 2188 pe_debug("Adding tdls he capabilities"); 2189 qdf_mem_copy(&add_sta_params->he_config, &sta_ds->he_config, 2190 sizeof(add_sta_params->he_config)); 2191 } 2192 2193 static void lim_add_tdls_sta_6ghz_he_cap(struct mac_context *mac_ctx, 2194 tpAddStaParams add_sta_params, 2195 tpDphHashNode sta_ds) 2196 { 2197 lim_update_he_6ghz_band_caps(mac_ctx, &sta_ds->he_6g_band_cap, 2198 add_sta_params); 2199 } 2200 2201 #else 2202 static void lim_add_tdls_sta_he_config(tpAddStaParams add_sta_params, 2203 tpDphHashNode sta_ds) 2204 { 2205 } 2206 2207 static void lim_add_tdls_sta_6ghz_he_cap(struct mac_context *mac_ctx, 2208 tpAddStaParams add_sta_params, 2209 tpDphHashNode sta_ds) 2210 { 2211 } 2212 #endif /* WLAN_FEATURE_11AX */ 2213 #endif /* FEATURE_WLAN_TDLS */ 2214 2215 #ifdef WLAN_FEATURE_11BE 2216 static bool lim_is_add_sta_params_eht_capable(tpAddStaParams add_sta_params) 2217 { 2218 return add_sta_params->eht_capable; 2219 } 2220 2221 static bool lim_is_eht_connection_op_info_present(struct pe_session *pe_session, 2222 tpSirAssocRsp assoc_rsp) 2223 { 2224 if (IS_DOT11_MODE_EHT(pe_session->dot11mode) && 2225 assoc_rsp->eht_op.present && 2226 assoc_rsp->eht_op.eht_op_information_present) 2227 return true; 2228 2229 return false; 2230 } 2231 #else 2232 static bool lim_is_add_sta_params_eht_capable(tpAddStaParams add_sta_params) 2233 { 2234 return false; 2235 } 2236 2237 static bool lim_is_eht_connection_op_info_present(struct pe_session *pe_session, 2238 tpSirAssocRsp assoc_rsp) 2239 { 2240 return false; 2241 } 2242 #endif 2243 2244 #ifdef WLAN_SUPPORT_TWT 2245 /** 2246 * lim_update_peer_twt_caps() - Update peer twt caps to add sta params 2247 * @add_sta_params: pointer to add sta params 2248 * @session_entry: pe session entry 2249 * 2250 * Return: None 2251 */ 2252 static void lim_update_peer_twt_caps(tpAddStaParams add_sta_params, 2253 struct pe_session *session_entry) 2254 { 2255 add_sta_params->twt_requestor = session_entry->peer_twt_requestor; 2256 add_sta_params->twt_responder = session_entry->peer_twt_responder; 2257 } 2258 #else 2259 static inline void 2260 lim_update_peer_twt_caps(tpAddStaParams add_sta_params, 2261 struct pe_session *session_entry) 2262 {} 2263 #endif 2264 2265 #ifdef WLAN_FEATURE_SR 2266 /** 2267 * lim_update_srp_ie() - Updates SRP IE to STA node 2268 * @bp_rsp: pointer to probe response / beacon frame 2269 * @sta_ds: STA Node 2270 * 2271 * Return: QDF_STATUS 2272 */ 2273 static QDF_STATUS lim_update_srp_ie(tSirProbeRespBeacon *bp_rsp, 2274 tpDphHashNode sta_ds) 2275 { 2276 QDF_STATUS status = QDF_STATUS_E_NOSUPPORT; 2277 2278 if (bp_rsp->srp_ie.present) { 2279 sta_ds->parsed_ies.srp_ie = bp_rsp->srp_ie; 2280 status = QDF_STATUS_SUCCESS; 2281 } 2282 2283 return status; 2284 } 2285 #else 2286 static QDF_STATUS lim_update_srp_ie(tSirProbeRespBeacon *bp_rsp, 2287 tpDphHashNode sta_ds) 2288 { 2289 return QDF_STATUS_SUCCESS; 2290 } 2291 #endif 2292 2293 /** 2294 * lim_add_sta()- called to add an STA context at hardware 2295 * @mac_ctx: pointer to global mac structure 2296 * @sta_ds: station node 2297 * @update_entry: set to true for updating the entry 2298 * @session_entry: pe session entry 2299 * 2300 * This function is called to add an STA context at hardware 2301 * whenever a STA is (Re) Associated. 2302 * 2303 * Return: QDF_STATUS_SUCCESS on success else QDF_STATUS failure codes 2304 */ 2305 2306 QDF_STATUS 2307 lim_add_sta(struct mac_context *mac_ctx, 2308 tpDphHashNode sta_ds, uint8_t update_entry, struct pe_session *session_entry) 2309 { 2310 tpAddStaParams add_sta_params = NULL; 2311 struct scheduler_msg msg_q = {0}; 2312 QDF_STATUS ret_code = QDF_STATUS_SUCCESS; 2313 tSirMacAddr sta_mac, *sta_Addr; 2314 tpSirAssocReq assoc_req; 2315 uint8_t i, nw_type_11b = 0; 2316 const uint8_t *p2p_ie = NULL; 2317 tDot11fIEVHTCaps vht_caps; 2318 struct mlme_vht_capabilities_info *vht_cap_info; 2319 2320 vht_cap_info = &mac_ctx->mlme_cfg->vht_caps.vht_cap_info; 2321 2322 sir_copy_mac_addr(sta_mac, session_entry->self_mac_addr); 2323 2324 add_sta_params = qdf_mem_malloc(sizeof(tAddStaParams)); 2325 if (!add_sta_params) 2326 return QDF_STATUS_E_NOMEM; 2327 2328 if (LIM_IS_AP_ROLE(session_entry) || LIM_IS_NDI_ROLE(session_entry)) 2329 sta_Addr = &sta_ds->staAddr; 2330 #ifdef FEATURE_WLAN_TDLS 2331 /* SystemRole shouldn't be matter if staType is TDLS peer */ 2332 else if (STA_ENTRY_TDLS_PEER == sta_ds->staType) 2333 sta_Addr = &sta_ds->staAddr; 2334 #endif 2335 else 2336 sta_Addr = &sta_mac; 2337 2338 qdf_mem_copy((uint8_t *) add_sta_params->staMac, 2339 (uint8_t *) *sta_Addr, sizeof(tSirMacAddr)); 2340 qdf_mem_copy((uint8_t *) add_sta_params->bssId, 2341 session_entry->bssId, sizeof(tSirMacAddr)); 2342 qdf_mem_copy(&add_sta_params->capab_info, 2343 &sta_ds->mlmStaContext.capabilityInfo, 2344 sizeof(add_sta_params->capab_info)); 2345 2346 /* Copy legacy rates */ 2347 qdf_mem_copy(&add_sta_params->supportedRates, 2348 &sta_ds->supportedRates, 2349 sizeof(sta_ds->supportedRates)); 2350 2351 add_sta_params->assocId = sta_ds->assocId; 2352 2353 add_sta_params->wmmEnabled = sta_ds->qosMode; 2354 add_sta_params->listenInterval = sta_ds->mlmStaContext.listenInterval; 2355 if (LIM_IS_AP_ROLE(session_entry) && 2356 (sta_ds->mlmStaContext.subType == LIM_REASSOC)) { 2357 /* 2358 * TBD - need to remove this REASSOC check 2359 * after fixinf rmmod issue 2360 */ 2361 add_sta_params->updateSta = sta_ds->mlmStaContext.updateContext; 2362 } 2363 sta_ds->valid = 0; 2364 sta_ds->mlmStaContext.mlmState = eLIM_MLM_WT_ADD_STA_RSP_STATE; 2365 add_sta_params->staType = sta_ds->staType; 2366 2367 add_sta_params->updateSta = update_entry; 2368 2369 add_sta_params->status = QDF_STATUS_SUCCESS; 2370 2371 /* Update VHT/HT Capability */ 2372 if (LIM_IS_AP_ROLE(session_entry)) { 2373 add_sta_params->htCapable = 2374 sta_ds->mlmStaContext.htCapability && 2375 session_entry->htCapability; 2376 add_sta_params->vhtCapable = 2377 sta_ds->mlmStaContext.vhtCapability && 2378 session_entry->vhtCapability; 2379 } 2380 #ifdef FEATURE_WLAN_TDLS 2381 /* SystemRole shouldn't be matter if staType is TDLS peer */ 2382 else if (STA_ENTRY_TDLS_PEER == sta_ds->staType) { 2383 add_sta_params->htCapable = sta_ds->mlmStaContext.htCapability; 2384 add_sta_params->vhtCapable = 2385 sta_ds->mlmStaContext.vhtCapability; 2386 } 2387 #endif 2388 else { 2389 add_sta_params->htCapable = session_entry->htCapability; 2390 add_sta_params->vhtCapable = session_entry->vhtCapability; 2391 } 2392 2393 /* 2394 * If HT client is connected to SAP DUT and self cap is NSS = 2 then 2395 * disable ASYNC DBS scan by sending wmi_vdev_param_smps_intolerant 2396 * to FW, because HT client's can't drop down chain using SMPS frames. 2397 */ 2398 if (!policy_mgr_is_hw_dbs_2x2_capable(mac_ctx->psoc) && 2399 LIM_IS_AP_ROLE(session_entry) && 2400 (STA_ENTRY_PEER == sta_ds->staType) && 2401 !add_sta_params->vhtCapable && 2402 (session_entry->nss == 2)) { 2403 session_entry->ht_client_cnt++; 2404 if (session_entry->ht_client_cnt == 1) { 2405 wma_cli_set_command(session_entry->smeSessionId, 2406 (int)wmi_vdev_param_smps_intolerant, 2407 1, VDEV_CMD); 2408 } 2409 } 2410 2411 lim_update_sta_he_capable(mac_ctx, add_sta_params, sta_ds, 2412 session_entry); 2413 2414 lim_update_sta_eht_capable(mac_ctx, add_sta_params, sta_ds, 2415 session_entry); 2416 2417 lim_update_tdls_sta_eht_capable(mac_ctx, add_sta_params, sta_ds, 2418 session_entry); 2419 2420 lim_update_sta_mlo_info(session_entry, add_sta_params, sta_ds); 2421 2422 add_sta_params->maxAmpduDensity = sta_ds->htAMpduDensity; 2423 add_sta_params->maxAmpduSize = sta_ds->htMaxRxAMpduFactor; 2424 add_sta_params->fShortGI20Mhz = sta_ds->htShortGI20Mhz; 2425 add_sta_params->fShortGI40Mhz = sta_ds->htShortGI40Mhz; 2426 add_sta_params->ch_width = sta_ds->ch_width; 2427 add_sta_params->mimoPS = sta_ds->htMIMOPSState; 2428 2429 if (add_sta_params->vhtCapable) { 2430 if (sta_ds->vhtSupportedChannelWidthSet) 2431 add_sta_params->ch_width = 2432 sta_ds->vhtSupportedChannelWidthSet + 1; 2433 2434 add_sta_params->vhtSupportedRxNss = sta_ds->vhtSupportedRxNss; 2435 if (LIM_IS_AP_ROLE(session_entry) || 2436 LIM_IS_P2P_DEVICE_GO(session_entry)) 2437 add_sta_params->vhtSupportedRxNss = QDF_MIN( 2438 add_sta_params->vhtSupportedRxNss, 2439 session_entry->nss); 2440 add_sta_params->vhtTxBFCapable = 2441 #ifdef FEATURE_WLAN_TDLS 2442 ((STA_ENTRY_PEER == sta_ds->staType) 2443 || (STA_ENTRY_TDLS_PEER == sta_ds->staType)) ? 2444 sta_ds->vhtBeamFormerCapable : 2445 session_entry->vht_config.su_beam_formee; 2446 #else 2447 (STA_ENTRY_PEER == sta_ds->staType) ? 2448 sta_ds->vhtBeamFormerCapable : 2449 session_entry->vht_config.su_beam_formee; 2450 #endif 2451 add_sta_params->enable_su_tx_bformer = 2452 sta_ds->vht_su_bfee_capable; 2453 add_sta_params->vht_mcs_10_11_supp = 2454 sta_ds->vht_mcs_10_11_supp; 2455 } 2456 2457 #ifdef FEATURE_WLAN_TDLS 2458 if ((STA_ENTRY_PEER == sta_ds->staType) || 2459 (STA_ENTRY_TDLS_PEER == sta_ds->staType)) 2460 #else 2461 if (STA_ENTRY_PEER == sta_ds->staType) 2462 #endif 2463 { 2464 /* 2465 * peer STA get the LDPC capability from sta_ds, 2466 * which populated from 2467 * HT/VHT capability 2468 */ 2469 if (add_sta_params->vhtTxBFCapable 2470 && vht_cap_info->disable_ldpc_with_txbf_ap) { 2471 add_sta_params->htLdpcCapable = 0; 2472 add_sta_params->vhtLdpcCapable = 0; 2473 } else { 2474 if (session_entry->txLdpcIniFeatureEnabled & 0x1) 2475 add_sta_params->htLdpcCapable = 2476 sta_ds->htLdpcCapable; 2477 else 2478 add_sta_params->htLdpcCapable = 0; 2479 2480 if (session_entry->txLdpcIniFeatureEnabled & 0x2) 2481 add_sta_params->vhtLdpcCapable = 2482 sta_ds->vhtLdpcCapable; 2483 else 2484 add_sta_params->vhtLdpcCapable = 0; 2485 } 2486 } else if (STA_ENTRY_SELF == sta_ds->staType) { 2487 /* For Self STA get the LDPC capability from config.ini */ 2488 add_sta_params->htLdpcCapable = 2489 (session_entry->txLdpcIniFeatureEnabled & 0x01); 2490 add_sta_params->vhtLdpcCapable = 2491 ((session_entry->txLdpcIniFeatureEnabled >> 1) & 0x01); 2492 } 2493 2494 /* Update PE session ID */ 2495 add_sta_params->sessionId = session_entry->peSessionId; 2496 2497 /* Update SME session ID */ 2498 add_sta_params->smesessionId = session_entry->smeSessionId; 2499 2500 add_sta_params->maxTxPower = session_entry->maxTxPower; 2501 2502 if (session_entry->parsedAssocReq) { 2503 uint16_t aid = sta_ds->assocId; 2504 /* Get a copy of the already parsed Assoc Request */ 2505 assoc_req = 2506 (tpSirAssocReq) session_entry->parsedAssocReq[aid]; 2507 if (assoc_req && assoc_req->addIEPresent 2508 && assoc_req->addIE.length) { 2509 p2p_ie = limGetP2pIEPtr(mac_ctx, 2510 assoc_req->addIE.addIEdata, 2511 assoc_req->addIE.length); 2512 } 2513 2514 add_sta_params->p2pCapableSta = (p2p_ie != NULL); 2515 if (assoc_req && add_sta_params->htCapable) { 2516 qdf_mem_copy(&add_sta_params->ht_caps, 2517 ((uint8_t *) &assoc_req->HTCaps) + 1, 2518 sizeof(add_sta_params->ht_caps)); 2519 } 2520 2521 if (assoc_req && add_sta_params->vhtCapable) { 2522 if (assoc_req->vendor_vht_ie.VHTCaps.present) 2523 vht_caps = assoc_req->vendor_vht_ie.VHTCaps; 2524 else 2525 vht_caps = assoc_req->VHTCaps; 2526 add_sta_params->vht_caps = 2527 lim_populate_vht_caps(vht_caps); 2528 } 2529 2530 lim_add_he_cap(mac_ctx, session_entry, 2531 add_sta_params, assoc_req); 2532 2533 lim_add_eht_cap(mac_ctx, session_entry, add_sta_params, 2534 assoc_req); 2535 2536 } 2537 2538 #ifdef FEATURE_WLAN_TDLS 2539 if (STA_ENTRY_TDLS_PEER == sta_ds->staType) { 2540 add_sta_params->ht_caps = sta_ds->ht_caps; 2541 add_sta_params->vht_caps = sta_ds->vht_caps; 2542 if (add_sta_params->vhtCapable) { 2543 add_sta_params->maxAmpduSize = 2544 SIR_MAC_GET_VHT_MAX_AMPDU_EXPO( 2545 sta_ds->vht_caps); 2546 } 2547 lim_add_tdls_sta_he_config(add_sta_params, sta_ds); 2548 2549 if (lim_is_he_6ghz_band(session_entry)) 2550 lim_add_tdls_sta_6ghz_he_cap(mac_ctx, add_sta_params, 2551 sta_ds); 2552 lim_add_tdls_sta_eht_config(add_sta_params, sta_ds); 2553 } 2554 #endif 2555 2556 #ifdef FEATURE_WLAN_TDLS 2557 if (sta_ds->wmeEnabled && 2558 (LIM_IS_AP_ROLE(session_entry) || 2559 (STA_ENTRY_TDLS_PEER == sta_ds->staType))) 2560 #else 2561 if (sta_ds->wmeEnabled && LIM_IS_AP_ROLE(session_entry)) 2562 #endif 2563 { 2564 add_sta_params->uAPSD = 0; 2565 /* 2566 * update UAPSD and send it to LIM to add STA 2567 * bitmap MSB <- LSB MSB 4 bits are for 2568 * trigger enabled AC setting and LSB 4 bits 2569 * are for delivery enabled AC setting 2570 * 7 6 5 4 3 2 1 0 2571 * BE BK VI VO BE BK VI VO 2572 */ 2573 add_sta_params->uAPSD |= 2574 sta_ds->qos.capability.qosInfo.acvo_uapsd; 2575 add_sta_params->uAPSD |= 2576 (sta_ds->qos.capability.qosInfo.acvi_uapsd << 1); 2577 add_sta_params->uAPSD |= 2578 (sta_ds->qos.capability.qosInfo.acbk_uapsd << 2); 2579 add_sta_params->uAPSD |= 2580 (sta_ds->qos.capability.qosInfo.acbe_uapsd << 3); 2581 /* 2582 * making delivery enabled and 2583 * trigger enabled setting the same. 2584 */ 2585 add_sta_params->uAPSD |= add_sta_params->uAPSD << 4; 2586 2587 add_sta_params->maxSPLen = 2588 sta_ds->qos.capability.qosInfo.maxSpLen; 2589 } 2590 add_sta_params->rmfEnabled = sta_ds->rmfEnabled; 2591 2592 if (!add_sta_params->htLdpcCapable) 2593 add_sta_params->ht_caps &= ~(1 << SIR_MAC_HT_CAP_ADVCODING_S); 2594 if (!add_sta_params->vhtLdpcCapable) 2595 add_sta_params->vht_caps &= 2596 ~(1 << SIR_MAC_VHT_CAP_LDPC_CODING_CAP); 2597 2598 /* 2599 * we need to defer the message until we get the 2600 * response back from HAL. 2601 */ 2602 SET_LIM_PROCESS_DEFD_MESGS(mac_ctx, false); 2603 2604 add_sta_params->nwType = session_entry->nwType; 2605 2606 if (!(add_sta_params->htCapable || add_sta_params->vhtCapable || 2607 lim_is_add_sta_params_he_capable(add_sta_params) || 2608 lim_is_add_sta_params_eht_capable(add_sta_params))) { 2609 nw_type_11b = 1; 2610 for (i = 0; i < SIR_NUM_11A_RATES; i++) { 2611 if (sirIsArate(sta_ds->supportedRates.llaRates[i] & 2612 0x7F)) { 2613 nw_type_11b = 0; 2614 break; 2615 } 2616 } 2617 if (nw_type_11b) 2618 add_sta_params->nwType = eSIR_11B_NW_TYPE; 2619 } 2620 2621 if (add_sta_params->htCapable && session_entry->ht_config.tx_stbc) { 2622 struct sDot11fIEHTCaps *ht_caps = (struct sDot11fIEHTCaps *) 2623 &add_sta_params->ht_caps; 2624 if (ht_caps->rxSTBC) 2625 add_sta_params->stbc_capable = 1; 2626 else 2627 add_sta_params->stbc_capable = 0; 2628 } 2629 2630 if (add_sta_params->vhtCapable && add_sta_params->stbc_capable) { 2631 struct sDot11fIEVHTCaps *vht_caps = (struct sDot11fIEVHTCaps *) 2632 &add_sta_params->vht_caps; 2633 if (vht_caps->rxSTBC) 2634 add_sta_params->stbc_capable = 1; 2635 else 2636 add_sta_params->stbc_capable = 0; 2637 } 2638 2639 if (session_entry->opmode == QDF_SAP_MODE || 2640 session_entry->opmode == QDF_P2P_GO_MODE) { 2641 if (session_entry->parsedAssocReq) { 2642 uint16_t aid = sta_ds->assocId; 2643 /* Get a copy of the already parsed Assoc Request */ 2644 assoc_req = 2645 (tpSirAssocReq) session_entry->parsedAssocReq[aid]; 2646 2647 if (assoc_req) { 2648 add_sta_params->wpa_rsn = assoc_req->rsnPresent; 2649 add_sta_params->wpa_rsn |= 2650 (assoc_req->wpaPresent << 1); 2651 } 2652 } 2653 } 2654 2655 lim_update_he_stbc_capable(add_sta_params); 2656 lim_update_he_mcs_12_13(add_sta_params, sta_ds); 2657 2658 /* Send peer twt req and res bit during peer assoc command */ 2659 lim_update_peer_twt_caps(add_sta_params, session_entry); 2660 2661 msg_q.type = WMA_ADD_STA_REQ; 2662 msg_q.reserved = 0; 2663 msg_q.bodyptr = add_sta_params; 2664 msg_q.bodyval = 0; 2665 2666 pe_debug("vdev %d: " QDF_MAC_ADDR_FMT " opmode %d sta_type %d subtype %d: update %d aid %d wmm %d li %d ht %d vht %d ht client %d", 2667 session_entry->vdev_id, 2668 QDF_MAC_ADDR_REF(add_sta_params->staMac), 2669 session_entry->opmode, sta_ds->staType, 2670 sta_ds->mlmStaContext.subType, add_sta_params->updateSta, 2671 add_sta_params->assocId, add_sta_params->wmmEnabled, 2672 add_sta_params->listenInterval, add_sta_params->htCapable, 2673 add_sta_params->vhtCapable, session_entry->ht_client_cnt); 2674 pe_nofl_debug("max_ampdu: density %d size %d, width %d sgi20 %d sgi40 %d mimops %d txbf %d subfer %d vht_mcs11 %d uapsd %d " 2675 "max splen %d pmf %d ht ldpc %d vht ldpc %d isp2p %d", 2676 add_sta_params->maxAmpduDensity, 2677 add_sta_params->maxAmpduSize, add_sta_params->ch_width, 2678 add_sta_params->fShortGI20Mhz, 2679 add_sta_params->fShortGI40Mhz, 2680 add_sta_params->mimoPS, add_sta_params->vhtTxBFCapable, 2681 add_sta_params->enable_su_tx_bformer, 2682 add_sta_params->vht_mcs_10_11_supp, add_sta_params->uAPSD, 2683 add_sta_params->maxSPLen, add_sta_params->rmfEnabled, 2684 add_sta_params->htLdpcCapable, 2685 add_sta_params->vhtLdpcCapable, 2686 add_sta_params->p2pCapableSta); 2687 2688 MTRACE(mac_trace_msg_tx(mac_ctx, session_entry->peSessionId, 2689 msg_q.type)); 2690 2691 ret_code = wma_post_ctrl_msg(mac_ctx, &msg_q); 2692 if (QDF_STATUS_SUCCESS != ret_code) { 2693 SET_LIM_PROCESS_DEFD_MESGS(mac_ctx, true); 2694 pe_err("ADD_STA_REQ for aId %d failed (reason %X)", 2695 sta_ds->assocId, ret_code); 2696 qdf_mem_free(add_sta_params); 2697 } 2698 2699 return ret_code; 2700 } 2701 2702 /** 2703 * lim_del_sta() 2704 * 2705 ***FUNCTION: 2706 * This function is called to delete an STA context at hardware 2707 * whenever a STA is disassociated 2708 * 2709 ***LOGIC: 2710 * 2711 ***ASSUMPTIONS: 2712 * NA 2713 * 2714 ***NOTE: 2715 * NA 2716 * 2717 * @param mac - Pointer to Global MAC structure 2718 * @param sta - Pointer to the STA datastructure created by 2719 * LIM and maintained by DPH 2720 * @param fRespReqd - flag to indicate whether the delete is synchronous (true) 2721 * or not (false) 2722 * @return retCode - Indicates success or failure return code 2723 */ 2724 2725 QDF_STATUS 2726 lim_del_sta(struct mac_context *mac, 2727 tpDphHashNode sta, bool fRespReqd, struct pe_session *pe_session) 2728 { 2729 tpDeleteStaParams pDelStaParams = NULL; 2730 struct scheduler_msg msgQ = {0}; 2731 QDF_STATUS retCode = QDF_STATUS_SUCCESS; 2732 2733 pDelStaParams = qdf_mem_malloc(sizeof(tDeleteStaParams)); 2734 if (!pDelStaParams) 2735 return QDF_STATUS_E_NOMEM; 2736 2737 /* 2738 * 2G-AS platform: SAP associates with HT (11n)clients as 2x1 in 2G and 2739 * 2X2 in 5G 2740 * Non-2G-AS platform: SAP associates with HT (11n) clients as 2X2 in 2G 2741 * and 5G; and enable async dbs scan when all HT clients are gone 2742 * 5G-AS: Don't care 2743 */ 2744 if (!policy_mgr_is_hw_dbs_2x2_capable(mac->psoc) && 2745 LIM_IS_AP_ROLE(pe_session) && 2746 (sta->staType == STA_ENTRY_PEER) && 2747 !sta->mlmStaContext.vhtCapability && 2748 (pe_session->nss == 2)) { 2749 pe_session->ht_client_cnt--; 2750 if (pe_session->ht_client_cnt == 0) { 2751 pe_debug("clearing SMPS intolrent vdev_param"); 2752 wma_cli_set_command(pe_session->smeSessionId, 2753 (int)wmi_vdev_param_smps_intolerant, 2754 0, VDEV_CMD); 2755 } 2756 } 2757 2758 pDelStaParams->assocId = sta->assocId; 2759 sta->valid = 0; 2760 2761 if (!fRespReqd) 2762 pDelStaParams->respReqd = 0; 2763 else { 2764 if (!(IS_TDLS_PEER(sta->staType))) { 2765 /* when lim_del_sta is called from processSmeAssocCnf 2766 * then mlmState is already set properly. */ 2767 if (eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE != 2768 GET_LIM_STA_CONTEXT_MLM_STATE(sta)) { 2769 MTRACE(mac_trace 2770 (mac, TRACE_CODE_MLM_STATE, 2771 pe_session->peSessionId, 2772 eLIM_MLM_WT_DEL_STA_RSP_STATE)); 2773 SET_LIM_STA_CONTEXT_MLM_STATE(sta, 2774 eLIM_MLM_WT_DEL_STA_RSP_STATE); 2775 } 2776 if (LIM_IS_STA_ROLE(pe_session)) { 2777 MTRACE(mac_trace 2778 (mac, TRACE_CODE_MLM_STATE, 2779 pe_session->peSessionId, 2780 eLIM_MLM_WT_DEL_STA_RSP_STATE)); 2781 2782 pe_session->limMlmState = 2783 eLIM_MLM_WT_DEL_STA_RSP_STATE; 2784 2785 } 2786 } 2787 2788 /* we need to defer the message until we get the 2789 * response back from HAL. */ 2790 SET_LIM_PROCESS_DEFD_MESGS(mac, false); 2791 2792 pDelStaParams->respReqd = 1; 2793 } 2794 2795 /* notify mlo peer to detach reference of the 2796 * link peer before post WMA_DELETE_STA_REQ, which will free 2797 * wlan_objmgr_peer of the link peer 2798 */ 2799 lim_mlo_notify_peer_disconn(pe_session, sta); 2800 lim_mlo_delete_link_peer(pe_session, sta); 2801 /* Update PE session ID */ 2802 pDelStaParams->sessionId = pe_session->peSessionId; 2803 pDelStaParams->smesessionId = pe_session->smeSessionId; 2804 2805 pDelStaParams->staType = sta->staType; 2806 qdf_mem_copy((uint8_t *) pDelStaParams->staMac, 2807 (uint8_t *) sta->staAddr, sizeof(tSirMacAddr)); 2808 2809 pDelStaParams->status = QDF_STATUS_SUCCESS; 2810 msgQ.type = WMA_DELETE_STA_REQ; 2811 msgQ.reserved = 0; 2812 msgQ.bodyptr = pDelStaParams; 2813 msgQ.bodyval = 0; 2814 2815 pe_debug("Sessionid %d :Sending SIR_HAL_DELETE_STA_REQ " 2816 "for mac_addr "QDF_MAC_ADDR_FMT" and AssocID: %d MAC : " 2817 QDF_MAC_ADDR_FMT, pDelStaParams->sessionId, 2818 QDF_MAC_ADDR_REF(pDelStaParams->staMac), 2819 pDelStaParams->assocId, 2820 QDF_MAC_ADDR_REF(sta->staAddr)); 2821 2822 MTRACE(mac_trace_msg_tx(mac, pe_session->peSessionId, msgQ.type)); 2823 retCode = wma_post_ctrl_msg(mac, &msgQ); 2824 if (QDF_STATUS_SUCCESS != retCode) { 2825 if (fRespReqd) 2826 SET_LIM_PROCESS_DEFD_MESGS(mac, true); 2827 pe_err("Posting DELETE_STA_REQ to HAL failed, reason=%X", 2828 retCode); 2829 qdf_mem_free(pDelStaParams); 2830 } 2831 2832 return retCode; 2833 } 2834 2835 /** 2836 * lim_set_mbssid_info() - Save mbssid info 2837 * @pe_session: pe session entry 2838 * 2839 * Return: None 2840 */ 2841 static void lim_set_mbssid_info(struct pe_session *pe_session) 2842 { 2843 struct scan_mbssid_info *mbssid_info; 2844 2845 if (!pe_session->lim_join_req && !pe_session->pLimReAssocReq) 2846 return; 2847 2848 if (pe_session->lim_join_req) 2849 mbssid_info = 2850 &pe_session->lim_join_req->bssDescription.mbssid_info; 2851 else 2852 mbssid_info = 2853 &pe_session->pLimReAssocReq->bssDescription.mbssid_info; 2854 2855 mlme_set_mbssid_info(pe_session->vdev, mbssid_info); 2856 } 2857 2858 /** 2859 * lim_add_sta_self() 2860 * 2861 ***FUNCTION: 2862 * This function is called to add an STA context at hardware 2863 * whenever a STA is (Re) Associated. 2864 * 2865 ***LOGIC: 2866 * 2867 ***ASSUMPTIONS: 2868 * NA 2869 * 2870 ***NOTE: 2871 * NA 2872 * 2873 * @param mac - Pointer to Global MAC structure 2874 * @param sta - Pointer to the STA datastructure created by 2875 * LIM and maintained by DPH 2876 * @return retCode - Indicates success or failure return code 2877 */ 2878 2879 QDF_STATUS 2880 lim_add_sta_self(struct mac_context *mac, uint8_t updateSta, 2881 struct pe_session *pe_session) 2882 { 2883 tpAddStaParams pAddStaParams = NULL; 2884 struct scheduler_msg msgQ = {0}; 2885 QDF_STATUS retCode = QDF_STATUS_SUCCESS; 2886 tSirMacAddr staMac; 2887 uint32_t listenInterval = MLME_CFG_LISTEN_INTERVAL; 2888 /*This self Sta dot 11 mode comes from the cfg and the expectation here is 2889 * that cfg carries the systemwide capability that device under 2890 * consideration can support. This capability gets plumbed into the cfg 2891 * cache at system initialization time via the .dat and .ini file override 2892 * mechanisms and will not change. If it does change, it is the 2893 * responsibility of SME to evict the selfSta and reissue a new AddStaSelf 2894 * command.*/ 2895 uint32_t selfStaDot11Mode = 0; 2896 2897 selfStaDot11Mode = mac->mlme_cfg->dot11_mode.dot11_mode; 2898 2899 sir_copy_mac_addr(staMac, pe_session->self_mac_addr); 2900 pAddStaParams = qdf_mem_malloc(sizeof(tAddStaParams)); 2901 if (!pAddStaParams) 2902 return QDF_STATUS_E_NOMEM; 2903 2904 /* / Add STA context at MAC HW (BMU, RHP & TFP) */ 2905 qdf_mem_copy((uint8_t *) pAddStaParams->staMac, 2906 (uint8_t *) staMac, sizeof(tSirMacAddr)); 2907 2908 qdf_mem_copy((uint8_t *) pAddStaParams->bssId, 2909 pe_session->bssId, sizeof(tSirMacAddr)); 2910 2911 pAddStaParams->assocId = pe_session->limAID; 2912 pAddStaParams->staType = STA_ENTRY_SELF; 2913 pAddStaParams->status = QDF_STATUS_SUCCESS; 2914 2915 /* Update PE session ID */ 2916 pAddStaParams->sessionId = pe_session->peSessionId; 2917 2918 /* Update SME session ID */ 2919 pAddStaParams->smesessionId = pe_session->smeSessionId; 2920 2921 pAddStaParams->maxTxPower = pe_session->maxTxPower; 2922 2923 pAddStaParams->updateSta = updateSta; 2924 2925 lim_set_mbssid_info(pe_session); 2926 2927 lim_populate_own_rate_set(mac, &pAddStaParams->supportedRates, 2928 NULL, false, 2929 pe_session, NULL, NULL, NULL); 2930 if (IS_DOT11_MODE_HT(selfStaDot11Mode)) { 2931 pAddStaParams->htCapable = true; 2932 2933 pAddStaParams->ch_width = 2934 mac->roam.configParam.channelBondingMode5GHz; 2935 pAddStaParams->mimoPS = 2936 lim_get_ht_capability(mac, eHT_MIMO_POWER_SAVE, 2937 pe_session); 2938 pAddStaParams->maxAmpduDensity = 2939 lim_get_ht_capability(mac, eHT_MPDU_DENSITY, 2940 pe_session); 2941 pAddStaParams->maxAmpduSize = 2942 lim_get_ht_capability(mac, eHT_MAX_RX_AMPDU_FACTOR, 2943 pe_session); 2944 pAddStaParams->fShortGI20Mhz = 2945 pe_session->ht_config.short_gi_20_mhz; 2946 pAddStaParams->fShortGI40Mhz = 2947 pe_session->ht_config.short_gi_40_mhz; 2948 } 2949 pAddStaParams->vhtCapable = pe_session->vhtCapability; 2950 if (pAddStaParams->vhtCapable) 2951 pAddStaParams->ch_width = 2952 pe_session->ch_width; 2953 2954 pAddStaParams->vhtTxBFCapable = 2955 pe_session->vht_config.su_beam_formee; 2956 pAddStaParams->enable_su_tx_bformer = 2957 pe_session->vht_config.su_beam_former; 2958 2959 /* In 11ac mode, the hardware is capable of supporting 128K AMPDU size */ 2960 if (pe_session->vhtCapability) 2961 pAddStaParams->maxAmpduSize = 2962 mac->mlme_cfg->vht_caps.vht_cap_info.ampdu_len_exponent; 2963 2964 pAddStaParams->vhtTxMUBformeeCapable = 2965 pe_session->vht_config.mu_beam_formee; 2966 pAddStaParams->enableVhtpAid = pe_session->enableVhtpAid; 2967 pAddStaParams->enableAmpduPs = pe_session->enableAmpduPs; 2968 pAddStaParams->enableHtSmps = (mac->mlme_cfg->ht_caps.enable_smps && 2969 (!pe_session->supported_nss_1x1)); 2970 pAddStaParams->htSmpsconfig = mac->mlme_cfg->ht_caps.smps; 2971 pAddStaParams->send_smps_action = 2972 pe_session->send_smps_action; 2973 2974 /* For Self STA get the LDPC capability from session i.e config.ini */ 2975 pAddStaParams->htLdpcCapable = 2976 (pe_session->txLdpcIniFeatureEnabled & 0x01); 2977 pAddStaParams->vhtLdpcCapable = 2978 ((pe_session->txLdpcIniFeatureEnabled >> 1) & 0x01); 2979 2980 listenInterval = mac->mlme_cfg->sap_cfg.listen_interval; 2981 pAddStaParams->listenInterval = (uint16_t) listenInterval; 2982 2983 if (QDF_P2P_CLIENT_MODE == pe_session->opmode) 2984 pAddStaParams->p2pCapableSta = 1; 2985 2986 if (pe_session->isNonRoamReassoc) { 2987 pAddStaParams->nonRoamReassoc = 1; 2988 pe_session->isNonRoamReassoc = 0; 2989 } 2990 2991 if (IS_DOT11_MODE_HE(selfStaDot11Mode)) 2992 lim_add_self_he_cap(pAddStaParams, pe_session); 2993 2994 if (IS_DOT11_MODE_EHT(selfStaDot11Mode)) 2995 lim_add_self_eht_cap(pAddStaParams, pe_session); 2996 2997 if (lim_is_fils_connection(pe_session)) 2998 pAddStaParams->no_ptk_4_way = true; 2999 3000 msgQ.type = WMA_ADD_STA_REQ; 3001 msgQ.reserved = 0; 3002 msgQ.bodyptr = pAddStaParams; 3003 msgQ.bodyval = 0; 3004 3005 pe_debug(QDF_MAC_ADDR_FMT ": vdev %d Sending WMA_ADD_STA_REQ.LI %d", 3006 QDF_MAC_ADDR_REF(pAddStaParams->staMac), 3007 pe_session->vdev_id, pAddStaParams->listenInterval); 3008 MTRACE(mac_trace_msg_tx(mac, pe_session->peSessionId, msgQ.type)); 3009 3010 retCode = wma_post_ctrl_msg(mac, &msgQ); 3011 if (QDF_STATUS_SUCCESS != retCode) { 3012 pe_err("Posting WMA_ADD_STA_REQ to HAL failed, reason=%X", 3013 retCode); 3014 qdf_mem_free(pAddStaParams); 3015 } 3016 return retCode; 3017 } 3018 3019 /** 3020 * lim_handle_cnf_wait_timeout() 3021 * 3022 ***FUNCTION: 3023 * This function is called by limProcessMessageQueue to handle 3024 * various confirmation failure cases. 3025 * 3026 ***LOGIC: 3027 * 3028 ***ASSUMPTIONS: 3029 * 3030 ***NOTE: 3031 * 3032 * @param mac - Pointer to Global MAC structure 3033 * @param sta - Pointer to a sta descriptor 3034 * @return None 3035 */ 3036 3037 void lim_handle_cnf_wait_timeout(struct mac_context *mac, uint16_t staId) 3038 { 3039 tpDphHashNode sta; 3040 struct pe_session *pe_session = NULL; 3041 3042 pe_session = pe_find_session_by_session_id(mac, 3043 mac->lim.lim_timers.gpLimCnfWaitTimer[staId].sessionId); 3044 if (!pe_session) { 3045 pe_err("Session Does not exist for given sessionID"); 3046 return; 3047 } 3048 sta = dph_get_hash_entry(mac, staId, &pe_session->dph.dphHashTable); 3049 3050 if (!sta) { 3051 pe_err("No STA context in SIR_LIM_CNF_WAIT_TIMEOUT"); 3052 return; 3053 } 3054 3055 switch (sta->mlmStaContext.mlmState) { 3056 case eLIM_MLM_WT_ASSOC_CNF_STATE: 3057 pe_debug("Did not receive Assoc Cnf in eLIM_MLM_WT_ASSOC_CNF_STATE sta Assoc id %d and STA: "QDF_MAC_ADDR_FMT, 3058 sta->assocId, QDF_MAC_ADDR_REF(sta->staAddr)); 3059 3060 if (LIM_IS_AP_ROLE(pe_session)) { 3061 lim_reject_association(mac, sta->staAddr, 3062 sta->mlmStaContext.subType, 3063 true, 3064 sta->mlmStaContext.authType, 3065 sta->assocId, true, 3066 STATUS_UNSPECIFIED_FAILURE, 3067 pe_session); 3068 } 3069 break; 3070 3071 default: 3072 pe_warn("Received CNF_WAIT_TIMEOUT in state %d", 3073 sta->mlmStaContext.mlmState); 3074 } 3075 } 3076 3077 /** 3078 * lim_delete_dph_hash_entry()- function to delete dph hash entry 3079 * @mac_ctx: pointer to global mac structure 3080 * @sta_addr: peer station address 3081 * @sta_id: id assigned to peer station 3082 * @session_entry: pe session entry 3083 * 3084 * This function is called whenever we need to delete 3085 * the dph hash entry 3086 * 3087 * Return: none 3088 */ 3089 3090 void 3091 lim_delete_dph_hash_entry(struct mac_context *mac_ctx, tSirMacAddr sta_addr, 3092 uint16_t sta_id, struct pe_session *session_entry) 3093 { 3094 uint16_t aid; 3095 tpDphHashNode sta_ds; 3096 tUpdateBeaconParams beacon_params; 3097 3098 qdf_mem_zero(&beacon_params, sizeof(tUpdateBeaconParams)); 3099 beacon_params.paramChangeBitmap = 0; 3100 lim_deactivate_and_change_per_sta_id_timer(mac_ctx, eLIM_CNF_WAIT_TIMER, 3101 sta_id); 3102 if (!session_entry) { 3103 pe_err("NULL session_entry"); 3104 return; 3105 } 3106 3107 beacon_params.bss_idx = session_entry->vdev_id; 3108 sta_ds = dph_lookup_hash_entry(mac_ctx, sta_addr, &aid, 3109 &session_entry->dph.dphHashTable); 3110 3111 if (!sta_ds) { 3112 pe_err("sta_ds is NULL"); 3113 return; 3114 } 3115 3116 pe_debug("Deleting DPH Hash entry sta mac " QDF_MAC_ADDR_FMT, 3117 QDF_MAC_ADDR_REF(sta_addr)); 3118 /* 3119 * update the station count and perform associated actions 3120 * do this before deleting the dph hash entry 3121 */ 3122 lim_util_count_sta_del(mac_ctx, sta_ds, session_entry); 3123 3124 if (LIM_IS_AP_ROLE(session_entry)) { 3125 if (LIM_IS_AP_ROLE(session_entry)) { 3126 if (session_entry->gLimProtectionControl != 3127 MLME_FORCE_POLICY_PROTECTION_DISABLE) 3128 lim_decide_ap_protection_on_delete(mac_ctx, 3129 sta_ds, &beacon_params, session_entry); 3130 } 3131 3132 if (sta_ds->non_ecsa_capable) { 3133 if (session_entry->lim_non_ecsa_cap_num == 0) { 3134 pe_debug("NonECSA sta 0, id %d is ecsa", 3135 sta_id); 3136 } else { 3137 session_entry->lim_non_ecsa_cap_num--; 3138 pe_debug("reducing the non ECSA num to %d", 3139 session_entry->lim_non_ecsa_cap_num); 3140 } 3141 } 3142 3143 lim_decide_short_preamble(mac_ctx, sta_ds, &beacon_params, 3144 session_entry); 3145 lim_decide_short_slot(mac_ctx, sta_ds, &beacon_params, 3146 session_entry); 3147 3148 /* Send message to HAL about beacon parameter change. */ 3149 pe_debug("param bitmap: %d", beacon_params.paramChangeBitmap); 3150 if (beacon_params.paramChangeBitmap && 3151 (false == 3152 mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running)) { 3153 sch_set_fixed_beacon_fields(mac_ctx, session_entry); 3154 lim_send_beacon_params(mac_ctx, &beacon_params, 3155 session_entry); 3156 } 3157 3158 lim_obss_send_detection_cfg(mac_ctx, session_entry, false); 3159 3160 if (sta_ds->rmfEnabled) { 3161 pe_debug("delete pmf timer assoc-id:%d sta mac " 3162 QDF_MAC_ADDR_FMT, sta_ds->assocId, 3163 QDF_MAC_ADDR_REF(sta_ds->staAddr)); 3164 tx_timer_delete(&sta_ds->pmfSaQueryTimer); 3165 } 3166 } 3167 3168 if (dph_delete_hash_entry(mac_ctx, sta_addr, sta_id, 3169 &session_entry->dph.dphHashTable) != QDF_STATUS_SUCCESS) 3170 pe_err("error deleting hash entry"); 3171 lim_ap_check_6g_compatible_peer(mac_ctx, session_entry); 3172 } 3173 3174 /** 3175 * lim_check_and_announce_join_success()- function to check if the received 3176 * Beacon/Probe Response is from the BSS that we're attempting to join. 3177 * @mac: pointer to global mac structure 3178 * @beacon_probe_rsp: pointer to reveived beacon/probe response frame 3179 * @header: pointer to received management frame header 3180 * @session_entry: pe session entry 3181 * 3182 * This function is called upon receiving Beacon/Probe Response 3183 * frame in WT_JOIN_BEACON_STATE to check if the received 3184 * Beacon/Probe Response is from the BSS that we're attempting 3185 * to join. 3186 * If the Beacon/Probe Response is indeed from the BSS we're 3187 * attempting to join, join success is sent to SME. 3188 * 3189 * Return: none 3190 */ 3191 3192 void 3193 lim_check_and_announce_join_success(struct mac_context *mac_ctx, 3194 tSirProbeRespBeacon *beacon_probe_rsp, tpSirMacMgmtHdr header, 3195 struct pe_session *session_entry) 3196 { 3197 tSirMacSSid current_ssid; 3198 tLimMlmJoinCnf mlm_join_cnf; 3199 tpDphHashNode sta_ds = NULL; 3200 uint32_t val; 3201 uint32_t *noa_duration_from_beacon = NULL; 3202 uint32_t *noa2_duration_from_beacon = NULL; 3203 uint32_t noa; 3204 uint32_t total_num_noa_desc = 0; 3205 uint16_t aid; 3206 bool check_assoc_disallowed; 3207 3208 qdf_mem_copy(current_ssid.ssId, 3209 session_entry->ssId.ssId, session_entry->ssId.length); 3210 3211 current_ssid.length = (uint8_t) session_entry->ssId.length; 3212 3213 /* 3214 * Check for SSID only in probe response. Beacons may not carry 3215 * SSID information in hidden SSID case 3216 */ 3217 if (((SIR_MAC_MGMT_FRAME == header->fc.type) && 3218 (SIR_MAC_MGMT_PROBE_RSP == header->fc.subType)) && 3219 current_ssid.length && 3220 (qdf_mem_cmp((uint8_t *) &beacon_probe_rsp->ssId, 3221 (uint8_t *) ¤t_ssid, 3222 (uint8_t) (1 + current_ssid.length)))) { 3223 /* 3224 * Received SSID does not match with the one we've. 3225 * Ignore received Beacon frame 3226 */ 3227 pe_debug("SSID received in Beacon does not match"); 3228 return; 3229 } 3230 3231 if (!LIM_IS_STA_ROLE(session_entry)) 3232 return; 3233 3234 if (SIR_MAC_MGMT_BEACON == header->fc.subType && 3235 lim_is_null_ssid(&beacon_probe_rsp->ssId)) { 3236 pe_debug("for hidden ap, waiting probersp to announce join success"); 3237 return; 3238 } 3239 3240 pe_debug("Received Beacon/PR with BSSID:"QDF_MAC_ADDR_FMT" pe session %d vdev %d", 3241 QDF_MAC_ADDR_REF(session_entry->bssId), 3242 session_entry->peSessionId, 3243 session_entry->vdev_id); 3244 3245 /* Deactivate Join Failure timer */ 3246 lim_deactivate_and_change_timer(mac_ctx, eLIM_JOIN_FAIL_TIMER); 3247 /* Deactivate Periodic Join timer */ 3248 lim_deactivate_and_change_timer(mac_ctx, 3249 eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER); 3250 3251 if (QDF_P2P_CLIENT_MODE == session_entry->opmode && 3252 beacon_probe_rsp->P2PProbeRes.NoticeOfAbsence.present) { 3253 3254 noa_duration_from_beacon = (uint32_t *) 3255 (beacon_probe_rsp->P2PProbeRes.NoticeOfAbsence.NoADesc + 1); 3256 3257 if (beacon_probe_rsp->P2PProbeRes.NoticeOfAbsence.num_NoADesc) 3258 total_num_noa_desc = 3259 beacon_probe_rsp->P2PProbeRes.NoticeOfAbsence. 3260 num_NoADesc / SIZE_OF_NOA_DESCRIPTOR; 3261 3262 noa = *noa_duration_from_beacon; 3263 3264 if (total_num_noa_desc > 1) { 3265 noa2_duration_from_beacon = (uint32_t *) 3266 (beacon_probe_rsp->P2PProbeRes.NoticeOfAbsence.NoADesc + 3267 SIZE_OF_NOA_DESCRIPTOR + 1); 3268 noa += *noa2_duration_from_beacon; 3269 } 3270 3271 /* 3272 * If MAX Noa exceeds 3 secs we will consider only 3 secs to 3273 * avoid arbitrary values in noa duration field 3274 */ 3275 noa = noa > MAX_NOA_PERIOD_IN_MICROSECS ? 3276 MAX_NOA_PERIOD_IN_MICROSECS : noa; 3277 noa = noa / 1000; /* Convert to ms */ 3278 3279 session_entry->defaultAuthFailureTimeout = 3280 mac_ctx->mlme_cfg->timeouts.auth_failure_timeout; 3281 val = mac_ctx->mlme_cfg->timeouts.auth_failure_timeout + noa; 3282 if (cfg_in_range(CFG_AUTH_FAILURE_TIMEOUT, val)) 3283 mac_ctx->mlme_cfg->timeouts.auth_failure_timeout = val; 3284 else 3285 mac_ctx->mlme_cfg->timeouts.auth_failure_timeout = 3286 cfg_default(CFG_AUTH_FAILURE_TIMEOUT); 3287 } else { 3288 session_entry->defaultAuthFailureTimeout = 0; 3289 } 3290 3291 wlan_cm_get_check_assoc_disallowed(mac_ctx->psoc, 3292 &check_assoc_disallowed); 3293 3294 /* 3295 * Check if MBO Association disallowed subattr is present and post 3296 * failure status to LIM if present 3297 */ 3298 if (check_assoc_disallowed && beacon_probe_rsp->assoc_disallowed) { 3299 pe_err("Connection fails due to assoc disallowed reason(%d):"QDF_MAC_ADDR_FMT" PESessionID %d", 3300 beacon_probe_rsp->assoc_disallowed_reason, 3301 QDF_MAC_ADDR_REF(session_entry->bssId), 3302 session_entry->peSessionId); 3303 mlm_join_cnf.resultCode = eSIR_SME_ASSOC_REFUSED; 3304 mlm_join_cnf.protStatusCode = STATUS_UNSPECIFIED_FAILURE; 3305 session_entry->limMlmState = eLIM_MLM_IDLE_STATE; 3306 mlm_join_cnf.sessionId = session_entry->peSessionId; 3307 if (session_entry->pLimMlmJoinReq) { 3308 qdf_mem_free(session_entry->pLimMlmJoinReq); 3309 session_entry->pLimMlmJoinReq = NULL; 3310 } 3311 lim_post_sme_message(mac_ctx, LIM_MLM_JOIN_CNF, 3312 (uint32_t *) &mlm_join_cnf); 3313 return; 3314 } 3315 3316 /* Update Beacon Interval at CFG database */ 3317 3318 if (beacon_probe_rsp->HTCaps.present) 3319 lim_update_sta_run_time_ht_capability(mac_ctx, 3320 &beacon_probe_rsp->HTCaps); 3321 if (beacon_probe_rsp->HTInfo.present) 3322 lim_update_sta_run_time_ht_info(mac_ctx, 3323 &beacon_probe_rsp->HTInfo, session_entry); 3324 session_entry->limMlmState = eLIM_MLM_JOINED_STATE; 3325 MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, 3326 session_entry->peSessionId, eLIM_MLM_JOINED_STATE)); 3327 3328 /* 3329 * update the capability info based on recently received beacon/probe 3330 * response frame 3331 */ 3332 session_entry->limCurrentBssCaps = 3333 lim_get_u16((uint8_t *)&beacon_probe_rsp->capabilityInfo); 3334 3335 /* 3336 * Announce join success by sending 3337 * Join confirm to SME. 3338 */ 3339 mlm_join_cnf.resultCode = eSIR_SME_SUCCESS; 3340 mlm_join_cnf.protStatusCode = STATUS_SUCCESS; 3341 /* Update PE sessionId */ 3342 mlm_join_cnf.sessionId = session_entry->peSessionId; 3343 lim_post_sme_message(mac_ctx, LIM_MLM_JOIN_CNF, 3344 (uint32_t *) &mlm_join_cnf); 3345 3346 if (session_entry->vhtCapability && 3347 beacon_probe_rsp->vendor_vht_ie.VHTCaps.present) { 3348 session_entry->is_vendor_specific_vhtcaps = true; 3349 session_entry->vendor_specific_vht_ie_sub_type = 3350 beacon_probe_rsp->vendor_vht_ie.sub_type; 3351 pe_debug("VHT caps are present in vendor specific IE"); 3352 } 3353 3354 /* Update HS 2.0 Information Element */ 3355 if (beacon_probe_rsp->hs20vendor_ie.present) { 3356 pe_debug("HS20 Indication Element Present, rel#:%u, id:%u", 3357 beacon_probe_rsp->hs20vendor_ie.release_num, 3358 beacon_probe_rsp->hs20vendor_ie.hs_id_present); 3359 qdf_mem_copy(&session_entry->hs20vendor_ie, 3360 &beacon_probe_rsp->hs20vendor_ie, 3361 sizeof(tDot11fIEhs20vendor_ie) - 3362 sizeof(beacon_probe_rsp->hs20vendor_ie.hs_id)); 3363 if (beacon_probe_rsp->hs20vendor_ie.hs_id_present) 3364 qdf_mem_copy(&session_entry->hs20vendor_ie.hs_id, 3365 &beacon_probe_rsp->hs20vendor_ie.hs_id, 3366 sizeof(beacon_probe_rsp->hs20vendor_ie.hs_id)); 3367 } 3368 3369 sta_ds = dph_lookup_hash_entry(mac_ctx, session_entry->self_mac_addr, 3370 &aid, 3371 &session_entry->dph.dphHashTable); 3372 3373 if (sta_ds && QDF_IS_STATUS_SUCCESS(lim_update_srp_ie(beacon_probe_rsp, 3374 sta_ds))) { 3375 /* update the SR parameters */ 3376 lim_update_vdev_sr_elements(session_entry, sta_ds); 3377 /* TODO: Need to send SRP IE update event to userspace */ 3378 } 3379 } 3380 3381 /** 3382 * lim_extract_ap_capabilities() 3383 * 3384 ***FUNCTION: 3385 * This function is called to extract all of the AP's capabilities 3386 * from the IEs received from it in Beacon/Probe Response frames 3387 * 3388 ***LOGIC: 3389 * This routine mimics the lim_extract_ap_capability() API. The difference here 3390 * is that this API returns the entire tSirProbeRespBeacon info as is. It is 3391 * left to the caller of this API to use this info as required 3392 * 3393 ***ASSUMPTIONS: 3394 * NA 3395 * 3396 ***NOTE: 3397 * 3398 * @param mac Pointer to Global MAC structure 3399 * @param pIE Pointer to starting IE in Beacon/Probe Response 3400 * @param ieLen Length of all IEs combined 3401 * @param beaconStruct A pointer to tSirProbeRespBeacon that needs to be 3402 * populated 3403 * @return status A status reporting QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE 3404 */ 3405 QDF_STATUS lim_extract_ap_capabilities(struct mac_context *mac, 3406 uint8_t *pIE, 3407 uint16_t ieLen, 3408 tpSirProbeRespBeacon beaconStruct) 3409 { 3410 qdf_mem_zero((uint8_t *) beaconStruct, sizeof(tSirProbeRespBeacon)); 3411 3412 /* Parse the Beacon IE's, Don't try to parse if we dont have anything in IE */ 3413 if (ieLen > 0) { 3414 if (QDF_STATUS_SUCCESS != 3415 sir_parse_beacon_ie(mac, beaconStruct, pIE, 3416 (uint32_t) ieLen)) { 3417 pe_err("APCapExtract: Beacon parsing error!"); 3418 return QDF_STATUS_E_FAILURE; 3419 } 3420 } 3421 3422 return QDF_STATUS_SUCCESS; 3423 } 3424 3425 /** 3426 * lim_del_bss() 3427 * 3428 ***FUNCTION: 3429 * This function is called to delete BSS context at hardware 3430 * whenever a STA is disassociated 3431 * 3432 ***LOGIC: 3433 * 3434 ***ASSUMPTIONS: 3435 * NA 3436 * 3437 ***NOTE: 3438 * NA 3439 * 3440 * @param mac - Pointer to Global MAC structure 3441 * @param sta - Pointer to the STA datastructure created by 3442 * LIM and maintained by DPH 3443 * @return retCode - Indicates success or failure return code 3444 */ 3445 3446 QDF_STATUS 3447 lim_del_bss(struct mac_context *mac, tpDphHashNode sta, uint16_t bss_idx, 3448 struct pe_session *pe_session) 3449 { 3450 struct scheduler_msg msgQ = {0}; 3451 QDF_STATUS retCode = QDF_STATUS_SUCCESS; 3452 3453 /* DPH was storing the AssocID in staID field, */ 3454 /* staID is actually assigned by HAL when AddSTA message is sent. */ 3455 if (sta) { 3456 sta->valid = 0; 3457 sta->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_BSS_RSP_STATE; 3458 } 3459 pe_session->limMlmState = eLIM_MLM_WT_DEL_BSS_RSP_STATE; 3460 MTRACE(mac_trace 3461 (mac, TRACE_CODE_MLM_STATE, pe_session->peSessionId, 3462 eLIM_MLM_WT_DEL_BSS_RSP_STATE)); 3463 3464 if ((pe_session->peSessionId == 3465 mac->lim.lim_timers.gLimJoinFailureTimer.sessionId) 3466 && (true == 3467 tx_timer_running(&mac->lim.lim_timers.gLimJoinFailureTimer))) { 3468 lim_deactivate_and_change_timer(mac, eLIM_JOIN_FAIL_TIMER); 3469 } 3470 3471 /* we need to defer the message until we get the response back from HAL. */ 3472 SET_LIM_PROCESS_DEFD_MESGS(mac, false); 3473 3474 if (pe_session->process_ho_fail) 3475 msgQ.type = WMA_DELETE_BSS_HO_FAIL_REQ; 3476 else 3477 msgQ.type = WMA_DELETE_BSS_REQ; 3478 msgQ.reserved = 0; 3479 msgQ.bodyptr = NULL; 3480 msgQ.bodyval = pe_session->smeSessionId; 3481 3482 pe_debug("Sessionid %d : Sending HAL_DELETE_BSS_REQ BSSID:" QDF_MAC_ADDR_FMT, 3483 pe_session->peSessionId, 3484 QDF_MAC_ADDR_REF(pe_session->bssId)); 3485 MTRACE(mac_trace_msg_tx(mac, pe_session->peSessionId, msgQ.type)); 3486 3487 retCode = wma_post_ctrl_msg(mac, &msgQ); 3488 if (QDF_STATUS_SUCCESS != retCode) { 3489 SET_LIM_PROCESS_DEFD_MESGS(mac, true); 3490 pe_err("Posting DELETE_BSS_REQ to HAL failed, reason=%X", 3491 retCode); 3492 } 3493 3494 return retCode; 3495 } 3496 3497 /** 3498 * lim_update_vhtcaps_assoc_resp : Update VHT caps in assoc response. 3499 * @mac_ctx Pointer to Global MAC structure 3500 * @pAddBssParams: parameters required for add bss params. 3501 * @vht_caps: VHT capabilities. 3502 * @pe_session : session entry. 3503 * 3504 * Return : void 3505 */ 3506 void lim_update_vhtcaps_assoc_resp(struct mac_context *mac_ctx, 3507 struct bss_params *pAddBssParams, 3508 tDot11fIEVHTCaps *vht_caps, 3509 struct pe_session *pe_session) 3510 { 3511 pAddBssParams->staContext.vht_caps = 3512 ((vht_caps->maxMPDULen << 3513 SIR_MAC_VHT_CAP_MAX_MPDU_LEN) | 3514 (vht_caps->supportedChannelWidthSet << 3515 SIR_MAC_VHT_CAP_SUPP_CH_WIDTH_SET) | 3516 (vht_caps->ldpcCodingCap << 3517 SIR_MAC_VHT_CAP_LDPC_CODING_CAP) | 3518 (vht_caps->shortGI80MHz << 3519 SIR_MAC_VHT_CAP_SHORTGI_80MHZ) | 3520 (vht_caps->shortGI160and80plus80MHz << 3521 SIR_MAC_VHT_CAP_SHORTGI_160_80_80MHZ) | 3522 (vht_caps->txSTBC << 3523 SIR_MAC_VHT_CAP_TXSTBC) | 3524 (vht_caps->rxSTBC << 3525 SIR_MAC_VHT_CAP_RXSTBC) | 3526 (vht_caps->suBeamFormerCap << 3527 SIR_MAC_VHT_CAP_SU_BEAMFORMER_CAP) | 3528 (vht_caps->suBeamformeeCap << 3529 SIR_MAC_VHT_CAP_SU_BEAMFORMEE_CAP) | 3530 (vht_caps->csnofBeamformerAntSup << 3531 SIR_MAC_VHT_CAP_CSN_BEAMORMER_ANT_SUP) | 3532 (vht_caps->numSoundingDim << 3533 SIR_MAC_VHT_CAP_NUM_SOUNDING_DIM) | 3534 (vht_caps->muBeamformerCap << 3535 SIR_MAC_VHT_CAP_NUM_BEAM_FORMER_CAP) | 3536 (vht_caps->muBeamformeeCap << 3537 SIR_MAC_VHT_CAP_NUM_BEAM_FORMEE_CAP) | 3538 (vht_caps->vhtTXOPPS << 3539 SIR_MAC_VHT_CAP_TXOPPS) | 3540 (vht_caps->htcVHTCap << 3541 SIR_MAC_VHT_CAP_HTC_CAP) | 3542 (vht_caps->maxAMPDULenExp << 3543 SIR_MAC_VHT_CAP_MAX_AMDU_LEN_EXPO) | 3544 (vht_caps->vhtLinkAdaptCap << 3545 SIR_MAC_VHT_CAP_LINK_ADAPT_CAP) | 3546 (vht_caps->rxAntPattern << 3547 SIR_MAC_VHT_CAP_RX_ANTENNA_PATTERN) | 3548 (vht_caps->txAntPattern << 3549 SIR_MAC_VHT_CAP_TX_ANTENNA_PATTERN) | 3550 (vht_caps->extended_nss_bw_supp << 3551 SIR_MAC_VHT_CAP_EXTD_NSS_BW)); 3552 3553 pAddBssParams->staContext.maxAmpduSize = 3554 SIR_MAC_GET_VHT_MAX_AMPDU_EXPO( 3555 pAddBssParams->staContext.vht_caps); 3556 } 3557 3558 /** 3559 * lim_update_vht_oper_assoc_resp : Update VHT Operations in assoc response. 3560 * @mac_ctx Pointer to Global MAC structure 3561 * @pAddBssParams: parameters required for add bss params. 3562 * @vht_caps: VHT CAP IE to update. 3563 * @vht_oper: VHT Operations to update. 3564 * @ht_info: HT Info IE to update. 3565 * @pe_session : session entry. 3566 * 3567 * Return : void 3568 */ 3569 static void lim_update_vht_oper_assoc_resp(struct mac_context *mac_ctx, 3570 struct bss_params *pAddBssParams, 3571 tDot11fIEVHTCaps *vht_caps, tDot11fIEVHTOperation *vht_oper, 3572 tDot11fIEHTInfo *ht_info, struct pe_session *pe_session) 3573 { 3574 uint8_t ch_width; 3575 3576 ch_width = pAddBssParams->ch_width; 3577 3578 if (vht_oper->chanWidth == WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ && 3579 pe_session->ch_width) 3580 ch_width = 3581 lim_get_vht_ch_width(vht_caps, vht_oper, ht_info) + 1; 3582 3583 if (ch_width > pe_session->ch_width) 3584 ch_width = pe_session->ch_width; 3585 3586 pAddBssParams->ch_width = ch_width; 3587 pAddBssParams->staContext.ch_width = ch_width; 3588 } 3589 3590 #ifdef WLAN_FEATURE_11BE 3591 /** 3592 * lim_update_eht_oper_assoc_resp : Update BW based on EHT operation IE. 3593 * @pe_session : session entry. 3594 * @pAddBssParams: parameters required for add bss params. 3595 * @eht_op: EHT Oper IE to update. 3596 * 3597 * Return : void 3598 */ 3599 static void lim_update_eht_oper_assoc_resp(struct pe_session *pe_session, 3600 struct bss_params *pAddBssParams, 3601 tDot11fIEeht_op *eht_op) 3602 { 3603 enum phy_ch_width ch_width; 3604 3605 ch_width = wlan_mlme_convert_eht_op_bw_to_phy_ch_width( 3606 eht_op->channel_width); 3607 3608 /* Due to puncturing, EHT AP's send seg1 in VHT IE as zero which causes 3609 * downgrade to 80 MHz, check EHT IE and if EHT IE supports 160MHz 3610 * then stick to 160MHz only 3611 */ 3612 3613 if (ch_width > pAddBssParams->ch_width && 3614 ch_width >= pe_session->ch_width) { 3615 pe_debug("eht ch_width %d and ch_width of add bss param %d", 3616 ch_width, pAddBssParams->ch_width); 3617 ch_width = pe_session->ch_width; 3618 } 3619 3620 pAddBssParams->ch_width = ch_width; 3621 pAddBssParams->staContext.ch_width = ch_width; 3622 } 3623 #else 3624 static void lim_update_eht_oper_assoc_resp(struct pe_session *pe_session, 3625 struct bss_params *pAddBssParams, 3626 tDot11fIEeht_op *eht_op) 3627 { 3628 } 3629 #endif 3630 3631 #ifdef WLAN_SUPPORT_TWT 3632 /** 3633 * lim_set_sta_ctx_twt() - Save the TWT settings in STA context 3634 * @sta_ctx: Pointer to Station Context 3635 * @session: Pointer to PE session 3636 * 3637 * Return: None 3638 */ 3639 static void lim_set_sta_ctx_twt(tAddStaParams *sta_ctx, struct pe_session *session) 3640 { 3641 sta_ctx->twt_requestor = session->peer_twt_requestor; 3642 sta_ctx->twt_responder = session->peer_twt_responder; 3643 } 3644 #else 3645 static inline void lim_set_sta_ctx_twt(tAddStaParams *sta_ctx, 3646 struct pe_session *session) 3647 { 3648 } 3649 #endif 3650 3651 void lim_sta_add_bss_update_ht_parameter(uint32_t bss_chan_freq, 3652 tDot11fIEHTCaps* ht_cap, 3653 tDot11fIEHTInfo* ht_inf, 3654 bool chan_width_support, 3655 struct bss_params *add_bss) 3656 { 3657 if (!ht_cap->present) 3658 return; 3659 3660 add_bss->htCapable = ht_cap->present; 3661 3662 if (!ht_inf->present) 3663 return; 3664 3665 if (chan_width_support && ht_cap->supportedChannelWidthSet) 3666 add_bss->ch_width = ht_inf->recommendedTxWidthSet; 3667 else 3668 add_bss->ch_width = CH_WIDTH_20MHZ; 3669 } 3670 3671 QDF_STATUS lim_sta_send_add_bss(struct mac_context *mac, tpSirAssocRsp pAssocRsp, 3672 tpSchBeaconStruct pBeaconStruct, 3673 struct bss_description *bssDescription, 3674 uint8_t updateEntry, struct pe_session *pe_session) 3675 { 3676 struct bss_params *pAddBssParams = NULL; 3677 uint32_t retCode; 3678 tpDphHashNode sta = NULL; 3679 bool chan_width_support = false; 3680 bool is_vht_cap_in_vendor_ie = false; 3681 tDot11fIEVHTCaps *vht_caps = NULL; 3682 tDot11fIEVHTOperation *vht_oper = NULL; 3683 tAddStaParams *sta_context; 3684 uint32_t listen_interval = MLME_CFG_LISTEN_INTERVAL; 3685 struct mlme_vht_capabilities_info *vht_cap_info; 3686 3687 vht_cap_info = &mac->mlme_cfg->vht_caps.vht_cap_info; 3688 3689 /* Package SIR_HAL_ADD_BSS_REQ message parameters */ 3690 pAddBssParams = qdf_mem_malloc(sizeof(struct bss_params)); 3691 if (!pAddBssParams) { 3692 retCode = QDF_STATUS_E_NOMEM; 3693 goto returnFailure; 3694 } 3695 3696 qdf_mem_copy(pAddBssParams->bssId, bssDescription->bssId, 3697 sizeof(tSirMacAddr)); 3698 3699 pAddBssParams->beaconInterval = bssDescription->beaconInterval; 3700 3701 pAddBssParams->dtimPeriod = pBeaconStruct->tim.dtimPeriod; 3702 pAddBssParams->updateBss = updateEntry; 3703 3704 if (IS_DOT11_MODE_11B(pe_session->dot11mode) && 3705 bssDescription->nwType != eSIR_11B_NW_TYPE) { 3706 pAddBssParams->nwType = eSIR_11B_NW_TYPE; 3707 } else { 3708 pAddBssParams->nwType = bssDescription->nwType; 3709 } 3710 3711 pAddBssParams->shortSlotTimeSupported = 3712 (uint8_t) pAssocRsp->capabilityInfo.shortSlotTime; 3713 pAddBssParams->llbCoexist = 3714 (uint8_t) pe_session->beaconParams.llbCoexist; 3715 3716 /* Use the advertised capabilities from the received beacon/PR */ 3717 if (IS_DOT11_MODE_HT(pe_session->dot11mode)) { 3718 chan_width_support = 3719 lim_get_ht_capability(mac, 3720 eHT_SUPPORTED_CHANNEL_WIDTH_SET, 3721 pe_session); 3722 3723 lim_sta_add_bss_update_ht_parameter(bssDescription->chan_freq, 3724 &pAssocRsp->HTCaps, 3725 &pAssocRsp->HTInfo, 3726 chan_width_support, 3727 pAddBssParams); 3728 /** 3729 * in limExtractApCapability function intersection of FW 3730 * advertised channel width and AP advertised channel 3731 * width has been taken into account for calculating 3732 * pe_session->ch_width 3733 */ 3734 if ((chan_width_support && 3735 ((pAssocRsp->HTCaps.present && 3736 pAssocRsp->HTCaps.supportedChannelWidthSet) || 3737 (pBeaconStruct->HTCaps.present && 3738 pBeaconStruct->HTCaps.supportedChannelWidthSet))) || 3739 lim_is_eht_connection_op_info_present(pe_session, 3740 pAssocRsp)) { 3741 pAddBssParams->ch_width = 3742 pe_session->ch_width; 3743 pAddBssParams->staContext.ch_width = 3744 pe_session->ch_width; 3745 } else { 3746 pAddBssParams->ch_width = CH_WIDTH_20MHZ; 3747 pAddBssParams->staContext.ch_width = CH_WIDTH_20MHZ; 3748 if (!vht_cap_info->enable_txbf_20mhz) 3749 pAddBssParams->staContext.vhtTxBFCapable = 0; 3750 } 3751 } 3752 3753 if (pe_session->vhtCapability && (pAssocRsp->VHTCaps.present)) { 3754 pAddBssParams->vhtCapable = pAssocRsp->VHTCaps.present; 3755 vht_caps = &pAssocRsp->VHTCaps; 3756 vht_oper = &pAssocRsp->VHTOperation; 3757 } else if (pe_session->vhtCapability && 3758 pAssocRsp->vendor_vht_ie.VHTCaps.present){ 3759 pAddBssParams->vhtCapable = 3760 pAssocRsp->vendor_vht_ie.VHTCaps.present; 3761 pe_debug("VHT Caps and Operation are present in vendor Specific IE"); 3762 vht_caps = &pAssocRsp->vendor_vht_ie.VHTCaps; 3763 vht_oper = &pAssocRsp->vendor_vht_ie.VHTOperation; 3764 } else { 3765 pAddBssParams->vhtCapable = 0; 3766 } 3767 if (pAddBssParams->vhtCapable) { 3768 if (vht_oper) 3769 lim_update_vht_oper_assoc_resp(mac, pAddBssParams, 3770 vht_caps, vht_oper, 3771 &pAssocRsp->HTInfo, 3772 pe_session); 3773 if (vht_caps) 3774 lim_update_vhtcaps_assoc_resp(mac, pAddBssParams, 3775 vht_caps, pe_session); 3776 } 3777 3778 if (lim_is_session_he_capable(pe_session) && 3779 (pAssocRsp->he_cap.present)) { 3780 lim_add_bss_he_cap(pAddBssParams, pAssocRsp); 3781 lim_add_bss_he_cfg(pAddBssParams, pe_session); 3782 } 3783 3784 if (lim_is_session_eht_capable(pe_session) && 3785 (pAssocRsp->eht_cap.present)) { 3786 lim_add_bss_eht_cap(pAddBssParams, pAssocRsp); 3787 lim_add_bss_eht_cfg(pAddBssParams, pe_session); 3788 } 3789 3790 if (lim_is_session_eht_capable(pe_session) && 3791 pAssocRsp->eht_op.present && 3792 pAssocRsp->eht_op.eht_op_information_present) 3793 lim_update_eht_oper_assoc_resp(pe_session, pAddBssParams, 3794 &pAssocRsp->eht_op); 3795 3796 if (pAssocRsp->bss_max_idle_period.present) { 3797 pAddBssParams->bss_max_idle_period = 3798 pAssocRsp->bss_max_idle_period.max_idle_period; 3799 pe_debug("bss_max_idle_period %d", 3800 pAddBssParams->bss_max_idle_period); 3801 } else { 3802 pAddBssParams->bss_max_idle_period = 0; 3803 } 3804 3805 /* 3806 * Populate the STA-related parameters here 3807 * Note that the STA here refers to the AP 3808 * staType = PEER 3809 */ 3810 sta_context = &pAddBssParams->staContext; 3811 /* Identifying AP as an STA */ 3812 pAddBssParams->staContext.staType = STA_ENTRY_OTHER; 3813 3814 qdf_mem_copy(pAddBssParams->staContext.bssId, 3815 bssDescription->bssId, sizeof(tSirMacAddr)); 3816 3817 listen_interval = mac->mlme_cfg->sap_cfg.listen_interval; 3818 pAddBssParams->staContext.listenInterval = listen_interval; 3819 3820 /* Get STA hash entry from the dph table */ 3821 sta = dph_lookup_hash_entry(mac, pAddBssParams->staContext.bssId, 3822 &pAddBssParams->staContext.assocId, 3823 &pe_session->dph.dphHashTable); 3824 if (!sta) { 3825 pe_err("Couldn't get assoc id for " "MAC ADDR: " 3826 QDF_MAC_ADDR_FMT, 3827 QDF_MAC_ADDR_REF( 3828 pAddBssParams->staContext.staMac)); 3829 qdf_mem_free(pAddBssParams); 3830 return QDF_STATUS_E_FAILURE; 3831 } 3832 3833 /* Update Assoc id from pe_session for STA */ 3834 pAddBssParams->staContext.assocId = pe_session->limAID; 3835 3836 pAddBssParams->staContext.uAPSD = 3837 pe_session->gUapsdPerAcBitmask; 3838 3839 pAddBssParams->staContext.maxSPLen = 0; 3840 pAddBssParams->staContext.updateSta = updateEntry; 3841 3842 if (IS_DOT11_MODE_HT(pe_session->dot11mode) 3843 && pBeaconStruct->HTCaps.present) { 3844 pAddBssParams->staContext.htCapable = 1; 3845 if (pe_session->ht_config.tx_stbc) 3846 pAddBssParams->staContext.stbc_capable = 3847 pAssocRsp->HTCaps.rxSTBC; 3848 3849 if (pe_session->vhtCapability && 3850 (IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps) || 3851 IS_BSS_VHT_CAPABLE(pBeaconStruct-> 3852 vendor_vht_ie.VHTCaps))) { 3853 pAddBssParams->staContext.vhtCapable = 1; 3854 pAddBssParams->staContext.vht_mcs_10_11_supp = 3855 sta->vht_mcs_10_11_supp; 3856 3857 pAddBssParams->staContext.vhtSupportedRxNss = 3858 sta->vhtSupportedRxNss; 3859 if (pAssocRsp->VHTCaps.present) 3860 vht_caps = &pAssocRsp->VHTCaps; 3861 else if (pAssocRsp->vendor_vht_ie.VHTCaps.present) { 3862 vht_caps = &pAssocRsp->vendor_vht_ie.VHTCaps; 3863 pe_debug("VHT Caps are in vendor Specific IE"); 3864 is_vht_cap_in_vendor_ie = true; 3865 } 3866 3867 if ((vht_caps) && (vht_caps->suBeamFormerCap || 3868 vht_caps->muBeamformerCap) && 3869 pe_session->vht_config.su_beam_formee) 3870 sta_context->vhtTxBFCapable = 1; 3871 3872 if ((vht_caps) && vht_caps->muBeamformerCap && 3873 pe_session->vht_config.mu_beam_formee) 3874 sta_context->vhtTxMUBformeeCapable = 1; 3875 3876 if ((vht_caps) && vht_caps->suBeamformeeCap && 3877 pe_session->vht_config.su_beam_former) 3878 sta_context->enable_su_tx_bformer = 1; 3879 3880 if (vht_caps && pAddBssParams->staContext.stbc_capable) 3881 pAddBssParams->staContext.stbc_capable = 3882 vht_caps->rxSTBC; 3883 if (pe_session->ch_width == CH_WIDTH_160MHZ || 3884 pe_session->ch_width == CH_WIDTH_80P80MHZ) { 3885 sta_context->vht_160mhz_nss = 3886 sta->vht_160mhz_nss; 3887 sta_context->vht_80p80mhz_nss = 3888 sta->vht_80p80mhz_nss; 3889 sta_context->vht_extended_nss_bw_cap = 3890 sta->vht_extended_nss_bw_cap; 3891 } else { 3892 sta_context->vht_160mhz_nss = 0; 3893 sta_context->vht_80p80mhz_nss = 0; 3894 sta_context->vht_extended_nss_bw_cap = 0; 3895 } 3896 } 3897 if (lim_is_session_he_capable(pe_session) && 3898 (pAssocRsp->he_cap.present || 3899 pBeaconStruct->he_cap.present)) { 3900 lim_intersect_ap_he_caps(pe_session, 3901 pAddBssParams, 3902 pBeaconStruct, 3903 pAssocRsp, bssDescription); 3904 lim_update_he_stbc_capable(&pAddBssParams->staContext); 3905 lim_update_he_mcs_12_13(&pAddBssParams->staContext, 3906 sta); 3907 } 3908 3909 if (lim_is_session_eht_capable(pe_session) && 3910 (pAssocRsp->eht_cap.present || 3911 pBeaconStruct->eht_cap.present)) { 3912 lim_intersect_ap_eht_caps(pe_session, 3913 pAddBssParams, 3914 pBeaconStruct, 3915 pAssocRsp); 3916 } 3917 3918 pAddBssParams->staContext.mimoPS = 3919 (tSirMacHTMIMOPowerSaveState) 3920 pAssocRsp->HTCaps.mimoPowerSave; 3921 pAddBssParams->staContext.maxAmpduDensity = 3922 pAssocRsp->HTCaps.mpduDensity; 3923 /* 3924 * We will check gShortGI20Mhz and gShortGI40Mhz from 3925 * session entry if they are set then we will use what ever 3926 * Assoc response coming from AP supports. If these 3927 * values are set as 0 in session entry then we will 3928 * hardcode this values to 0. 3929 */ 3930 if (pe_session->ht_config.short_gi_20_mhz) { 3931 pAddBssParams->staContext.fShortGI20Mhz = 3932 (uint8_t)pAssocRsp->HTCaps.shortGI20MHz; 3933 } else { 3934 pAddBssParams->staContext.fShortGI20Mhz = false; 3935 } 3936 3937 if (pe_session->ht_config.short_gi_40_mhz) { 3938 pAddBssParams->staContext.fShortGI40Mhz = 3939 (uint8_t) pAssocRsp->HTCaps.shortGI40MHz; 3940 } else { 3941 pAddBssParams->staContext.fShortGI40Mhz = false; 3942 } 3943 3944 if (!pAddBssParams->staContext.vhtCapable) 3945 /* Use max ampd factor advertised in 3946 * HTCAP for non-vht connection */ 3947 { 3948 pAddBssParams->staContext.maxAmpduSize = 3949 pAssocRsp->HTCaps.maxRxAMPDUFactor; 3950 } else if (pAddBssParams->staContext.maxAmpduSize < 3951 pAssocRsp->HTCaps.maxRxAMPDUFactor) { 3952 pAddBssParams->staContext.maxAmpduSize = 3953 pAssocRsp->HTCaps.maxRxAMPDUFactor; 3954 } 3955 if (pAddBssParams->staContext.vhtTxBFCapable 3956 && vht_cap_info->disable_ldpc_with_txbf_ap) { 3957 pAddBssParams->staContext.htLdpcCapable = 0; 3958 pAddBssParams->staContext.vhtLdpcCapable = 0; 3959 } else { 3960 if (pe_session->txLdpcIniFeatureEnabled & 0x1) 3961 pAddBssParams->staContext.htLdpcCapable = 3962 (uint8_t) pAssocRsp->HTCaps.advCodingCap; 3963 else 3964 pAddBssParams->staContext.htLdpcCapable = 0; 3965 3966 if (pAssocRsp->VHTCaps.present) 3967 vht_caps = &pAssocRsp->VHTCaps; 3968 else if (pAssocRsp->vendor_vht_ie.VHTCaps.present) { 3969 vht_caps = &pAssocRsp->vendor_vht_ie.VHTCaps; 3970 pe_debug("VHT Caps is in vendor Specific IE"); 3971 } 3972 if (vht_caps && 3973 (pe_session->txLdpcIniFeatureEnabled & 0x2)) { 3974 if (!is_vht_cap_in_vendor_ie) 3975 pAddBssParams->staContext.vhtLdpcCapable = 3976 (uint8_t) pAssocRsp->VHTCaps.ldpcCodingCap; 3977 else 3978 pAddBssParams->staContext.vhtLdpcCapable = 3979 (uint8_t) vht_caps->ldpcCodingCap; 3980 } else { 3981 pAddBssParams->staContext.vhtLdpcCapable = 0; 3982 } 3983 } 3984 3985 } 3986 if (lim_is_he_6ghz_band(pe_session)) { 3987 if (lim_is_session_he_capable(pe_session) && 3988 (pAssocRsp->he_cap.present || 3989 pBeaconStruct->he_cap.present)) { 3990 lim_intersect_ap_he_caps(pe_session, 3991 pAddBssParams, 3992 pBeaconStruct, 3993 pAssocRsp, bssDescription); 3994 lim_update_he_stbc_capable(&pAddBssParams->staContext); 3995 lim_update_he_mcs_12_13(&pAddBssParams->staContext, 3996 sta); 3997 if (!lim_is_eht_connection_op_info_present(pe_session, 3998 pAssocRsp)) 3999 lim_update_he_6gop_assoc_resp(pAddBssParams, 4000 &pAssocRsp->he_op, 4001 pe_session); 4002 lim_update_he_6ghz_band_caps(mac, 4003 &pAssocRsp->he_6ghz_band_cap, 4004 &pAddBssParams->staContext); 4005 } 4006 if (lim_is_session_eht_capable(pe_session) && 4007 (pAssocRsp->eht_cap.present || 4008 pBeaconStruct->eht_cap.present)) { 4009 lim_intersect_ap_eht_caps(pe_session, 4010 pAddBssParams, 4011 pBeaconStruct, 4012 pAssocRsp); 4013 } 4014 } 4015 4016 lim_extract_per_link_id(pe_session, pAddBssParams, pAssocRsp); 4017 lim_extract_ml_info(pe_session, pAddBssParams, pAssocRsp); 4018 lim_intersect_ap_emlsr_caps(mac, pe_session, pAddBssParams, pAssocRsp); 4019 lim_extract_msd_caps(mac, pe_session, pAddBssParams, pAssocRsp); 4020 4021 pAddBssParams->staContext.smesessionId = 4022 pe_session->smeSessionId; 4023 pAddBssParams->staContext.wpa_rsn = pBeaconStruct->rsnPresent; 4024 pAddBssParams->staContext.wpa_rsn |= 4025 (pBeaconStruct->wpaPresent << 1); 4026 /* For OSEN Connection AP does not advertise RSN or WPA IE 4027 * so from the IEs we get from supplicant we get this info 4028 * so for FW to transmit EAPOL message 4 we shall set 4029 * wpa_rsn 4030 */ 4031 if ((!pAddBssParams->staContext.wpa_rsn) 4032 && (pe_session->isOSENConnection)) 4033 pAddBssParams->staContext.wpa_rsn = 1; 4034 qdf_mem_copy(&pAddBssParams->staContext.capab_info, 4035 &pAssocRsp->capabilityInfo, 4036 sizeof(pAddBssParams->staContext.capab_info)); 4037 qdf_mem_copy(&pAddBssParams->staContext.ht_caps, 4038 (uint8_t *) &pAssocRsp->HTCaps + sizeof(uint8_t), 4039 sizeof(pAddBssParams->staContext.ht_caps)); 4040 4041 /* If WMM IE or 802.11E IE is present then enable WMM */ 4042 if ((pe_session->limWmeEnabled && pAssocRsp->wmeEdcaPresent) || 4043 (pe_session->limQosEnabled && pAssocRsp->edcaPresent)) 4044 pAddBssParams->staContext.wmmEnabled = 1; 4045 else 4046 pAddBssParams->staContext.wmmEnabled = 0; 4047 4048 /* Update the rates */ 4049 sta = dph_get_hash_entry(mac, DPH_STA_HASH_INDEX_PEER, 4050 &pe_session->dph.dphHashTable); 4051 if (sta) { 4052 qdf_mem_copy(&pAddBssParams->staContext.supportedRates, 4053 &sta->supportedRates, 4054 sizeof(sta->supportedRates)); 4055 } else 4056 pe_err("could not Update the supported rates"); 4057 pAddBssParams->staContext.encryptType = pe_session->encryptType; 4058 4059 pAddBssParams->maxTxPower = pe_session->maxTxPower; 4060 4061 if (QDF_P2P_CLIENT_MODE == pe_session->opmode) 4062 pAddBssParams->staContext.p2pCapableSta = 1; 4063 4064 if (pe_session->limRmfEnabled) { 4065 pAddBssParams->rmfEnabled = 1; 4066 pAddBssParams->staContext.rmfEnabled = 1; 4067 } 4068 4069 /* Set a new state for MLME */ 4070 if (eLIM_MLM_WT_ASSOC_RSP_STATE == pe_session->limMlmState) 4071 pe_session->limMlmState = 4072 eLIM_MLM_WT_ADD_BSS_RSP_ASSOC_STATE; 4073 else 4074 pe_session->limMlmState = 4075 eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE; 4076 MTRACE(mac_trace 4077 (mac, TRACE_CODE_MLM_STATE, pe_session->peSessionId, 4078 pe_session->limMlmState)); 4079 4080 if (!pAddBssParams->staContext.htLdpcCapable) 4081 pAddBssParams->staContext.ht_caps &= 4082 ~(1 << SIR_MAC_HT_CAP_ADVCODING_S); 4083 if (!pAddBssParams->staContext.vhtLdpcCapable) 4084 pAddBssParams->staContext.vht_caps &= 4085 ~(1 << SIR_MAC_VHT_CAP_LDPC_CODING_CAP); 4086 4087 if (pe_session->isNonRoamReassoc) 4088 pAddBssParams->nonRoamReassoc = 1; 4089 4090 pe_debug("update %d MxAmpduDen %d mimoPS %d vht_mcs11 %d shortSlot %d BI %d DTIM %d enc type %d p2p cab STA %d", 4091 updateEntry, 4092 pAddBssParams->staContext.maxAmpduDensity, 4093 pAddBssParams->staContext.mimoPS, 4094 pAddBssParams->staContext.vht_mcs_10_11_supp, 4095 pAddBssParams->shortSlotTimeSupported, 4096 pAddBssParams->beaconInterval, pAddBssParams->dtimPeriod, 4097 pAddBssParams->staContext.encryptType, 4098 pAddBssParams->staContext.p2pCapableSta); 4099 if (cds_is_5_mhz_enabled()) { 4100 pAddBssParams->ch_width = CH_WIDTH_5MHZ; 4101 pAddBssParams->staContext.ch_width = CH_WIDTH_5MHZ; 4102 } else if (cds_is_10_mhz_enabled()) { 4103 pAddBssParams->ch_width = CH_WIDTH_10MHZ; 4104 pAddBssParams->staContext.ch_width = CH_WIDTH_10MHZ; 4105 } 4106 lim_set_sta_ctx_twt(&pAddBssParams->staContext, pe_session); 4107 4108 if (lim_is_fils_connection(pe_session)) 4109 pAddBssParams->no_ptk_4_way = true; 4110 4111 /* we need to defer the message until we get the response back */ 4112 SET_LIM_PROCESS_DEFD_MESGS(mac, false); 4113 4114 retCode = wma_send_peer_assoc_req(pAddBssParams); 4115 if (QDF_IS_STATUS_ERROR(retCode)) { 4116 SET_LIM_PROCESS_DEFD_MESGS(mac, true); 4117 pe_err("wma_send_peer_assoc_req failed=%X", 4118 retCode); 4119 } 4120 qdf_mem_free(pAddBssParams); 4121 4122 returnFailure: 4123 /* Clean-up will be done by the caller... */ 4124 return retCode; 4125 } 4126 4127 QDF_STATUS lim_sta_send_add_bss_pre_assoc(struct mac_context *mac, 4128 struct pe_session *pe_session) 4129 { 4130 struct bss_params *pAddBssParams = NULL; 4131 uint32_t retCode; 4132 tSchBeaconStruct *pBeaconStruct; 4133 bool chan_width_support = false; 4134 tDot11fIEVHTOperation *vht_oper = NULL; 4135 tDot11fIEVHTCaps *vht_caps = NULL; 4136 uint32_t listen_interval = MLME_CFG_LISTEN_INTERVAL; 4137 struct bss_description *bssDescription = NULL; 4138 struct mlme_vht_capabilities_info *vht_cap_info; 4139 4140 if (!pe_session->lim_join_req) { 4141 pe_err("Lim Join request is NULL"); 4142 return QDF_STATUS_E_FAILURE; 4143 } 4144 4145 bssDescription = &pe_session->lim_join_req->bssDescription; 4146 vht_cap_info = &mac->mlme_cfg->vht_caps.vht_cap_info; 4147 4148 pBeaconStruct = qdf_mem_malloc(sizeof(tSchBeaconStruct)); 4149 if (!pBeaconStruct) 4150 return QDF_STATUS_E_NOMEM; 4151 4152 /* Package SIR_HAL_ADD_BSS_REQ message parameters */ 4153 pAddBssParams = qdf_mem_malloc(sizeof(struct bss_params)); 4154 if (!pAddBssParams) { 4155 retCode = QDF_STATUS_E_NOMEM; 4156 goto returnFailure; 4157 } 4158 4159 lim_extract_ap_capabilities(mac, (uint8_t *) bssDescription->ieFields, 4160 lim_get_ielen_from_bss_description(bssDescription), 4161 pBeaconStruct); 4162 4163 if (mac->lim.gLimProtectionControl != 4164 MLME_FORCE_POLICY_PROTECTION_DISABLE) 4165 lim_decide_sta_protection_on_assoc(mac, pBeaconStruct, 4166 pe_session); 4167 qdf_mem_copy(pAddBssParams->bssId, bssDescription->bssId, 4168 sizeof(tSirMacAddr)); 4169 4170 pAddBssParams->beaconInterval = bssDescription->beaconInterval; 4171 4172 pAddBssParams->dtimPeriod = pBeaconStruct->tim.dtimPeriod; 4173 pAddBssParams->updateBss = false; 4174 4175 pAddBssParams->nwType = bssDescription->nwType; 4176 4177 pAddBssParams->shortSlotTimeSupported = 4178 (uint8_t) pBeaconStruct->capabilityInfo.shortSlotTime; 4179 pAddBssParams->llbCoexist = 4180 (uint8_t) pe_session->beaconParams.llbCoexist; 4181 4182 /* Use the advertised capabilities from the received beacon/PR */ 4183 if (IS_DOT11_MODE_HT(pe_session->dot11mode)) { 4184 chan_width_support = 4185 lim_get_ht_capability(mac, 4186 eHT_SUPPORTED_CHANNEL_WIDTH_SET, 4187 pe_session); 4188 lim_sta_add_bss_update_ht_parameter(bssDescription->chan_freq, 4189 &pBeaconStruct->HTCaps, 4190 &pBeaconStruct->HTInfo, 4191 chan_width_support, 4192 pAddBssParams); 4193 } 4194 4195 if (pe_session->vhtCapability && 4196 (IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps) || 4197 IS_BSS_VHT_CAPABLE(pBeaconStruct->vendor_vht_ie.VHTCaps))) { 4198 4199 pAddBssParams->vhtCapable = 1; 4200 if (pBeaconStruct->VHTOperation.present) 4201 vht_oper = &pBeaconStruct->VHTOperation; 4202 else if (pBeaconStruct->vendor_vht_ie.VHTOperation.present) { 4203 vht_oper = &pBeaconStruct->vendor_vht_ie.VHTOperation; 4204 pe_debug("VHT Operation is present in vendor Specific IE"); 4205 } 4206 4207 /* 4208 * in limExtractApCapability function intersection of FW 4209 * advertised channel width and AP advertised channel width has 4210 * been taken into account for calculating 4211 * pe_session->ch_width 4212 */ 4213 pAddBssParams->ch_width = 4214 pe_session->ch_width; 4215 pAddBssParams->staContext.maxAmpduSize = 4216 SIR_MAC_GET_VHT_MAX_AMPDU_EXPO( 4217 pAddBssParams->staContext.vht_caps); 4218 } else { 4219 pAddBssParams->vhtCapable = 0; 4220 } 4221 4222 if (lim_is_session_he_capable(pe_session) && 4223 pBeaconStruct->he_cap.present) { 4224 lim_update_bss_he_capable(mac, pAddBssParams); 4225 lim_add_bss_he_cfg(pAddBssParams, pe_session); 4226 } 4227 4228 if (lim_is_session_eht_capable(pe_session) && 4229 pBeaconStruct->eht_cap.present) { 4230 lim_update_bss_eht_capable(mac, pAddBssParams); 4231 lim_add_bss_eht_cfg(pAddBssParams, pe_session); 4232 } 4233 4234 /* 4235 * Populate the STA-related parameters here 4236 * Note that the STA here refers to the AP 4237 */ 4238 /* Identifying AP as an STA */ 4239 pAddBssParams->staContext.staType = STA_ENTRY_OTHER; 4240 4241 qdf_mem_copy(pAddBssParams->staContext.bssId, 4242 bssDescription->bssId, sizeof(tSirMacAddr)); 4243 4244 listen_interval = mac->mlme_cfg->sap_cfg.listen_interval; 4245 pAddBssParams->staContext.listenInterval = listen_interval; 4246 pAddBssParams->staContext.assocId = 0; 4247 pAddBssParams->staContext.uAPSD = 0; 4248 pAddBssParams->staContext.maxSPLen = 0; 4249 pAddBssParams->staContext.updateSta = false; 4250 4251 if (IS_DOT11_MODE_HT(pe_session->dot11mode) 4252 && (pBeaconStruct->HTCaps.present)) { 4253 pAddBssParams->staContext.htCapable = 1; 4254 if (pe_session->vhtCapability && 4255 (IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps) || 4256 IS_BSS_VHT_CAPABLE( 4257 pBeaconStruct->vendor_vht_ie.VHTCaps))) { 4258 pAddBssParams->staContext.vhtCapable = 1; 4259 if (pBeaconStruct->VHTCaps.present) 4260 vht_caps = &pBeaconStruct->VHTCaps; 4261 else if (pBeaconStruct->vendor_vht_ie.VHTCaps.present) 4262 vht_caps = &pBeaconStruct-> 4263 vendor_vht_ie.VHTCaps; 4264 4265 if ((vht_caps) && (vht_caps->suBeamFormerCap || 4266 vht_caps->muBeamformerCap) && 4267 pe_session->vht_config.su_beam_formee) 4268 pAddBssParams->staContext.vhtTxBFCapable = 1; 4269 4270 if ((vht_caps) && vht_caps->muBeamformerCap && 4271 pe_session->vht_config.mu_beam_formee) 4272 pAddBssParams->staContext.vhtTxMUBformeeCapable 4273 = 1; 4274 4275 if ((vht_caps) && vht_caps->suBeamformeeCap && 4276 pe_session->vht_config.su_beam_former) 4277 pAddBssParams->staContext.enable_su_tx_bformer 4278 = 1; 4279 } 4280 if (lim_is_session_he_capable(pe_session) && 4281 pBeaconStruct->he_cap.present) 4282 lim_intersect_ap_he_caps(pe_session, pAddBssParams, 4283 pBeaconStruct, NULL, 4284 bssDescription); 4285 4286 if (lim_is_session_eht_capable(pe_session) && 4287 pBeaconStruct->eht_cap.present) 4288 lim_intersect_ap_eht_caps(pe_session, pAddBssParams, 4289 pBeaconStruct, NULL); 4290 4291 if (pBeaconStruct->HTCaps.supportedChannelWidthSet && 4292 chan_width_support) { 4293 pAddBssParams->staContext.ch_width = 4294 (uint8_t) pBeaconStruct->HTInfo. 4295 recommendedTxWidthSet; 4296 if ((vht_oper) && 4297 pAddBssParams->staContext.vhtCapable && 4298 vht_oper->chanWidth) 4299 pAddBssParams->staContext.ch_width = 4300 vht_oper->chanWidth + 1; 4301 } else { 4302 pAddBssParams->staContext.ch_width = 4303 CH_WIDTH_20MHZ; 4304 } 4305 pAddBssParams->staContext.mimoPS = 4306 (tSirMacHTMIMOPowerSaveState) pBeaconStruct->HTCaps. 4307 mimoPowerSave; 4308 pAddBssParams->staContext.maxAmpduDensity = 4309 pBeaconStruct->HTCaps.mpduDensity; 4310 /* 4311 * We will check gShortGI20Mhz and gShortGI40Mhz from ini file. 4312 * if they are set then we will use what ever Beacon coming 4313 * from AP supports. If these values are set as 0 in ini file 4314 * then we will hardcode this values to 0. 4315 */ 4316 if (pe_session->ht_config.short_gi_20_mhz) 4317 pAddBssParams->staContext.fShortGI20Mhz = 4318 (uint8_t)pBeaconStruct->HTCaps.shortGI20MHz; 4319 else 4320 pAddBssParams->staContext.fShortGI20Mhz = false; 4321 4322 if (pe_session->ht_config.short_gi_40_mhz) 4323 pAddBssParams->staContext.fShortGI40Mhz = 4324 (uint8_t) pBeaconStruct->HTCaps.shortGI40MHz; 4325 else 4326 pAddBssParams->staContext.fShortGI40Mhz = false; 4327 4328 pAddBssParams->staContext.maxAmpduSize = 4329 pBeaconStruct->HTCaps.maxRxAMPDUFactor; 4330 if (pAddBssParams->staContext.vhtTxBFCapable 4331 && vht_cap_info->disable_ldpc_with_txbf_ap) { 4332 pAddBssParams->staContext.htLdpcCapable = 0; 4333 pAddBssParams->staContext.vhtLdpcCapable = 0; 4334 } else { 4335 if (pe_session->txLdpcIniFeatureEnabled & 0x1) 4336 pAddBssParams->staContext.htLdpcCapable = 4337 (uint8_t) pBeaconStruct->HTCaps. 4338 advCodingCap; 4339 else 4340 pAddBssParams->staContext.htLdpcCapable = 0; 4341 4342 if (pBeaconStruct->VHTCaps.present) 4343 vht_caps = &pBeaconStruct->VHTCaps; 4344 else if (pBeaconStruct->vendor_vht_ie.VHTCaps.present) { 4345 vht_caps = 4346 &pBeaconStruct->vendor_vht_ie.VHTCaps; 4347 } 4348 if (vht_caps && 4349 (pe_session->txLdpcIniFeatureEnabled & 0x2)) 4350 pAddBssParams->staContext.vhtLdpcCapable = 4351 (uint8_t) vht_caps->ldpcCodingCap; 4352 else 4353 pAddBssParams->staContext.vhtLdpcCapable = 0; 4354 } 4355 } 4356 /* 4357 * If WMM IE or 802.11E IE is not present 4358 * and AP is HT AP then enable WMM 4359 */ 4360 if ((pe_session->limWmeEnabled && (pBeaconStruct->wmeEdcaPresent || 4361 pAddBssParams->staContext.htCapable)) || 4362 (pe_session->limQosEnabled && 4363 (pBeaconStruct->edcaPresent || 4364 pAddBssParams->staContext.htCapable))) 4365 pAddBssParams->staContext.wmmEnabled = 1; 4366 else 4367 pAddBssParams->staContext.wmmEnabled = 0; 4368 4369 /* Update the rates */ 4370 lim_populate_peer_rate_set(mac, 4371 &pAddBssParams->staContext. 4372 supportedRates, 4373 pBeaconStruct->HTCaps.supportedMCSSet, 4374 false, pe_session, 4375 &pBeaconStruct->VHTCaps, 4376 &pBeaconStruct->he_cap, 4377 &pBeaconStruct->eht_cap, NULL, 4378 bssDescription); 4379 4380 pAddBssParams->staContext.encryptType = pe_session->encryptType; 4381 4382 pAddBssParams->maxTxPower = pe_session->maxTxPower; 4383 4384 pAddBssParams->staContext.smesessionId = pe_session->smeSessionId; 4385 pAddBssParams->staContext.sessionId = pe_session->peSessionId; 4386 4387 if (pe_session->limRmfEnabled) { 4388 pAddBssParams->rmfEnabled = 1; 4389 pAddBssParams->staContext.rmfEnabled = 1; 4390 } 4391 /* Set a new state for MLME */ 4392 pe_session->limMlmState = eLIM_MLM_WT_ADD_BSS_RSP_PREASSOC_STATE; 4393 4394 MTRACE(mac_trace 4395 (mac, TRACE_CODE_MLM_STATE, pe_session->peSessionId, 4396 pe_session->limMlmState)); 4397 if (cds_is_5_mhz_enabled()) { 4398 pAddBssParams->ch_width = CH_WIDTH_5MHZ; 4399 pAddBssParams->staContext.ch_width = CH_WIDTH_5MHZ; 4400 } else if (cds_is_10_mhz_enabled()) { 4401 pAddBssParams->ch_width = CH_WIDTH_10MHZ; 4402 pAddBssParams->staContext.ch_width = CH_WIDTH_10MHZ; 4403 } 4404 4405 if (lim_is_fils_connection(pe_session)) 4406 pAddBssParams->no_ptk_4_way = true; 4407 4408 retCode = wma_pre_assoc_req(pAddBssParams); 4409 lim_process_sta_add_bss_rsp_pre_assoc(mac, pAddBssParams, 4410 pe_session, retCode); 4411 qdf_mem_free(pAddBssParams); 4412 /* 4413 * Set retCode success as lim_process_sta_add_bss_rsp_pre_assoc take 4414 * care of failure 4415 */ 4416 retCode = QDF_STATUS_SUCCESS; 4417 4418 returnFailure: 4419 /* Clean-up will be done by the caller... */ 4420 qdf_mem_free(pBeaconStruct); 4421 return retCode; 4422 } 4423 4424 /** 4425 * lim_prepare_and_send_del_all_sta_cnf() - prepares and send del all sta cnf 4426 * @mac: mac global context 4427 * @status_code: status code 4428 * @pe_session: session context 4429 * 4430 * deletes DPH entry, changes the MLM mode for station, calls 4431 * lim_send_del_sta_cnf 4432 * 4433 * Return: void 4434 */ 4435 void lim_prepare_and_send_del_all_sta_cnf(struct mac_context *mac, 4436 tSirResultCodes status_code, 4437 struct pe_session *pe_session) 4438 { 4439 tLimMlmDeauthCnf mlm_deauth; 4440 tpDphHashNode sta_ds = NULL; 4441 uint32_t i; 4442 4443 if (!LIM_IS_AP_ROLE(pe_session)) 4444 return; 4445 4446 for (i = 1; i < pe_session->dph.dphHashTable.size; i++) { 4447 sta_ds = dph_get_hash_entry(mac, i, 4448 &pe_session->dph.dphHashTable); 4449 if (!sta_ds) 4450 continue; 4451 4452 lim_delete_dph_hash_entry(mac, sta_ds->staAddr, 4453 sta_ds->assocId, pe_session); 4454 if (lim_is_mlo_conn(pe_session, sta_ds)) 4455 lim_release_mlo_conn_idx(mac, sta_ds->assocId, 4456 pe_session, false); 4457 else 4458 lim_release_peer_idx(mac, sta_ds->assocId, pe_session); 4459 } 4460 4461 qdf_set_macaddr_broadcast(&mlm_deauth.peer_macaddr); 4462 mlm_deauth.resultCode = status_code; 4463 mlm_deauth.deauthTrigger = eLIM_HOST_DEAUTH; 4464 mlm_deauth.sessionId = pe_session->peSessionId; 4465 4466 lim_post_sme_message(mac, LIM_MLM_DEAUTH_CNF, 4467 (uint32_t *)&mlm_deauth); 4468 } 4469 4470 /** 4471 * lim_prepare_and_send_del_sta_cnf() - prepares and send del sta cnf 4472 * 4473 * @mac: mac global context 4474 * @sta: sta dph node 4475 * @status_code: status code 4476 * @pe_session: session context 4477 * 4478 * deletes DPH entry, changes the MLM mode for station, calls 4479 * lim_send_del_sta_cnf 4480 * 4481 * Return: void 4482 */ 4483 void 4484 lim_prepare_and_send_del_sta_cnf(struct mac_context *mac, tpDphHashNode sta, 4485 tSirResultCodes status_code, 4486 struct pe_session *pe_session) 4487 { 4488 uint16_t staDsAssocId = 0; 4489 struct qdf_mac_addr sta_dsaddr; 4490 struct lim_sta_context mlmStaContext; 4491 bool mlo_conn = false; 4492 4493 if (!sta) { 4494 pe_err("sta is NULL"); 4495 return; 4496 } 4497 4498 staDsAssocId = sta->assocId; 4499 qdf_mem_copy((uint8_t *) sta_dsaddr.bytes, 4500 sta->staAddr, QDF_MAC_ADDR_SIZE); 4501 4502 mlmStaContext = sta->mlmStaContext; 4503 4504 if (LIM_IS_AP_ROLE(pe_session)) { 4505 mlo_conn = lim_is_mlo_conn(pe_session, sta); 4506 if (mlo_conn) 4507 lim_release_mlo_conn_idx(mac, sta->assocId, 4508 pe_session, false); 4509 else 4510 lim_release_peer_idx(mac, sta->assocId, pe_session); 4511 } 4512 4513 lim_delete_dph_hash_entry(mac, sta->staAddr, sta->assocId, 4514 pe_session); 4515 4516 if (LIM_IS_STA_ROLE(pe_session)) { 4517 pe_session->limMlmState = eLIM_MLM_IDLE_STATE; 4518 MTRACE(mac_trace(mac, TRACE_CODE_MLM_STATE, 4519 pe_session->peSessionId, 4520 pe_session->limMlmState)); 4521 } 4522 4523 lim_send_del_sta_cnf(mac, sta_dsaddr, staDsAssocId, mlmStaContext, 4524 status_code, pe_session); 4525 } 4526 4527 /** ------------------------------------------------------------- 4528 \fn lim_init_pre_auth_timer_table 4529 \brief Initialize the Pre Auth Tanle and creates the timer for 4530 each node for the timeout value got from cfg. 4531 \param struct mac_context * mac 4532 \param tpLimPreAuthTable pPreAuthTimerTable 4533 \return none 4534 -------------------------------------------------------------*/ 4535 void lim_init_pre_auth_timer_table(struct mac_context *mac, 4536 tpLimPreAuthTable pPreAuthTimerTable) 4537 { 4538 uint32_t cfgValue; 4539 uint32_t authNodeIdx; 4540 4541 tLimPreAuthNode **pAuthNode = pPreAuthTimerTable->pTable; 4542 4543 /* Get AUTH_RSP Timers value */ 4544 cfgValue = SYS_MS_TO_TICKS(mac->mlme_cfg->timeouts.auth_rsp_timeout); 4545 for (authNodeIdx = 0; authNodeIdx < pPreAuthTimerTable->numEntry; 4546 authNodeIdx++) { 4547 if (tx_timer_create(mac, &(pAuthNode[authNodeIdx]->timer), 4548 "AUTH RESPONSE TIMEOUT", 4549 lim_auth_response_timer_handler, authNodeIdx, 4550 cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { 4551 pe_err("Cannot create Auth Rsp timer of Index: %d", 4552 authNodeIdx); 4553 return; 4554 } 4555 pAuthNode[authNodeIdx]->authNodeIdx = (uint8_t) authNodeIdx; 4556 pAuthNode[authNodeIdx]->fFree = 1; 4557 } 4558 } 4559 4560 /** ------------------------------------------------------------- 4561 \fn lim_acquire_free_pre_auth_node 4562 \brief Retrieves a free Pre Auth node from Pre Auth Table. 4563 \param struct mac_context * mac 4564 \param tpLimPreAuthTable pPreAuthTimerTable 4565 \return none 4566 -------------------------------------------------------------*/ 4567 tLimPreAuthNode *lim_acquire_free_pre_auth_node(struct mac_context *mac, 4568 tpLimPreAuthTable pPreAuthTimerTable) 4569 { 4570 uint32_t i; 4571 tLimPreAuthNode **pTempNode = pPreAuthTimerTable->pTable; 4572 4573 for (i = 0; i < pPreAuthTimerTable->numEntry; i++) { 4574 if (pTempNode[i]->fFree == 1) { 4575 pTempNode[i]->fFree = 0; 4576 return pTempNode[i]; 4577 } 4578 } 4579 4580 return NULL; 4581 } 4582 4583 /** ------------------------------------------------------------- 4584 \fn lim_get_pre_auth_node_from_index 4585 \brief Depending on the Index this retrieves the pre auth node. 4586 \param struct mac_context * mac 4587 \param tpLimPreAuthTable pAuthTable 4588 \param uint32_t authNodeIdx 4589 \return none 4590 -------------------------------------------------------------*/ 4591 tLimPreAuthNode *lim_get_pre_auth_node_from_index(struct mac_context *mac, 4592 tpLimPreAuthTable pAuthTable, 4593 uint32_t authNodeIdx) 4594 { 4595 if ((authNodeIdx >= pAuthTable->numEntry) 4596 || (!pAuthTable->pTable)) { 4597 pe_err("Invalid Auth Timer Index: %d NumEntry: %d", 4598 authNodeIdx, pAuthTable->numEntry); 4599 return NULL; 4600 } 4601 4602 return pAuthTable->pTable[authNodeIdx]; 4603 } 4604 4605 /* Util API to check if the channels supported by STA is within range */ 4606 QDF_STATUS lim_is_dot11h_supported_channels_valid(struct mac_context *mac, 4607 tSirAssocReq *assoc) 4608 { 4609 /* 4610 * Allow all the stations to join with us. 4611 * 802.11h-2003 11.6.1 => An AP may use the supported channels list for associated STAs 4612 * as an input into an algorithm used to select a new channel for the BSS. 4613 * The specification of the algorithm is beyond the scope of this amendment. 4614 */ 4615 4616 return QDF_STATUS_SUCCESS; 4617 } 4618 4619 /* Util API to check if the txpower supported by STA is within range */ 4620 QDF_STATUS lim_is_dot11h_power_capabilities_in_range(struct mac_context *mac, 4621 tSirAssocReq *assoc, 4622 struct pe_session *pe_session) 4623 { 4624 int8_t localMaxTxPower; 4625 uint8_t local_pwr_constraint; 4626 4627 localMaxTxPower = wlan_reg_get_channel_reg_power_for_freq( 4628 mac->pdev, pe_session->curr_op_freq); 4629 4630 local_pwr_constraint = mac->mlme_cfg->power.local_power_constraint; 4631 localMaxTxPower -= (int8_t)local_pwr_constraint; 4632 4633 /** 4634 * The min Tx Power of the associating station should not be greater than (regulatory 4635 * max tx power - local power constraint configured on AP). 4636 */ 4637 if (assoc->powerCapability.minTxPower > localMaxTxPower) { 4638 pe_warn("minTxPower (STA): %d, localMaxTxPower (AP): %d", 4639 assoc->powerCapability.minTxPower, localMaxTxPower); 4640 return QDF_STATUS_E_FAILURE; 4641 } 4642 4643 return QDF_STATUS_SUCCESS; 4644 } 4645 4646 void lim_fill_rx_highest_supported_rate(struct mac_context *mac, 4647 uint16_t *rxHighestRate, 4648 uint8_t *pSupportedMCSSet) 4649 { 4650 tSirMacRxHighestSupportRate *pRxHighestRate; 4651 uint8_t *pBuf; 4652 uint16_t rate = 0; 4653 4654 pBuf = pSupportedMCSSet + MCS_RX_HIGHEST_SUPPORTED_RATE_BYTE_OFFSET; 4655 rate = lim_get_u16(pBuf); 4656 4657 pRxHighestRate = (tSirMacRxHighestSupportRate *) &rate; 4658 *rxHighestRate = pRxHighestRate->rate; 4659 4660 return; 4661 } 4662 4663 /** ------------------------------------------------------------- 4664 \fn lim_send_sme_unprotected_mgmt_frame_ind 4665 \brief Forwards the unprotected management frame to SME. 4666 \param struct mac_context * mac 4667 \param frameType - 802.11 frame type 4668 \param frame - frame buffer 4669 \param sessionId - id for the current session 4670 \param pe_session - PE session context 4671 \return none 4672 -------------------------------------------------------------*/ 4673 void lim_send_sme_unprotected_mgmt_frame_ind(struct mac_context *mac, uint8_t frameType, 4674 uint8_t *frame, uint32_t frameLen, 4675 uint16_t sessionId, 4676 struct pe_session *pe_session) 4677 { 4678 struct scheduler_msg mmhMsg = {0}; 4679 tSirSmeUnprotMgmtFrameInd *pSirSmeMgmtFrame = NULL; 4680 uint16_t length; 4681 4682 length = sizeof(tSirSmeUnprotMgmtFrameInd) + frameLen; 4683 4684 pSirSmeMgmtFrame = qdf_mem_malloc(length); 4685 if (!pSirSmeMgmtFrame) 4686 return; 4687 4688 pSirSmeMgmtFrame->sessionId = sessionId; 4689 pSirSmeMgmtFrame->frameType = frameType; 4690 4691 qdf_mem_copy(pSirSmeMgmtFrame->frameBuf, frame, frameLen); 4692 pSirSmeMgmtFrame->frameLen = frameLen; 4693 4694 mmhMsg.type = eWNI_SME_UNPROT_MGMT_FRM_IND; 4695 mmhMsg.bodyptr = pSirSmeMgmtFrame; 4696 mmhMsg.bodyval = 0; 4697 4698 lim_sys_process_mmh_msg_api(mac, &mmhMsg); 4699 return; 4700 } 4701 4702 #ifdef FEATURE_WLAN_ESE 4703 void lim_send_sme_tsm_ie_ind(struct mac_context *mac, 4704 struct pe_session *pe_session, 4705 uint8_t tid, uint8_t state, 4706 uint16_t measurement_interval) 4707 { 4708 struct scheduler_msg msg = {0}; 4709 struct tsm_ie_ind *tsm_ie_ind; 4710 4711 if (!mac || !pe_session) 4712 return; 4713 4714 tsm_ie_ind = qdf_mem_malloc(sizeof(*tsm_ie_ind)); 4715 if (!tsm_ie_ind) 4716 return; 4717 4718 tsm_ie_ind->sessionId = pe_session->smeSessionId; 4719 tsm_ie_ind->tsm_ie.tsid = tid; 4720 tsm_ie_ind->tsm_ie.state = state; 4721 tsm_ie_ind->tsm_ie.msmt_interval = measurement_interval; 4722 4723 msg.type = eWNI_SME_TSM_IE_IND; 4724 msg.bodyptr = tsm_ie_ind; 4725 msg.bodyval = 0; 4726 4727 lim_sys_process_mmh_msg_api(mac, &msg); 4728 } 4729 #endif /* FEATURE_WLAN_ESE */ 4730 4731 void lim_extract_ies_from_deauth_disassoc(struct pe_session *session, 4732 uint8_t *deauth_disassoc_frame, 4733 uint16_t deauth_disassoc_frame_len) 4734 { 4735 uint16_t reason_code, ie_offset; 4736 struct element_info ie; 4737 4738 if (!session) { 4739 pe_err("NULL session"); 4740 return; 4741 } 4742 4743 /* Get the offset of IEs */ 4744 ie_offset = sizeof(struct wlan_frame_hdr) + sizeof(reason_code); 4745 4746 if (!deauth_disassoc_frame || deauth_disassoc_frame_len <= ie_offset) 4747 return; 4748 4749 ie.ptr = deauth_disassoc_frame + ie_offset; 4750 ie.len = deauth_disassoc_frame_len - ie_offset; 4751 4752 mlme_set_peer_disconnect_ies(session->vdev, &ie); 4753 } 4754