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