1 /* 2 * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /* 21 * This file lim_process_sme_req_messages.cc contains the code 22 * for processing SME request messages. 23 * Author: Chandra Modumudi 24 * Date: 02/11/02 25 * History:- 26 * Date Modified by Modification Information 27 * -------------------------------------------------------------------- 28 * 29 */ 30 31 #include "cds_api.h" 32 #include "wni_api.h" 33 #include "wni_cfg.h" 34 #include "sir_api.h" 35 #include "sch_api.h" 36 #include "utils_api.h" 37 #include "lim_types.h" 38 #include "lim_utils.h" 39 #include "lim_assoc_utils.h" 40 #include "lim_security_utils.h" 41 #include "lim_ser_des_utils.h" 42 #include "lim_sme_req_utils.h" 43 #include "lim_admit_control.h" 44 #include "dph_hash_table.h" 45 #include "lim_send_messages.h" 46 #include "lim_api.h" 47 #include "wmm_apsd.h" 48 #include "sir_mac_prot_def.h" 49 #include "rrm_api.h" 50 #include "nan_datapath.h" 51 #include "sap_api.h" 52 #include <lim_ft.h> 53 #include "cds_regdomain.h" 54 #include <wlan_reg_services_api.h> 55 #include "lim_process_fils.h" 56 #include "wlan_utility.h" 57 #include <wlan_crypto_global_api.h> 58 #include "../../core/src/vdev_mgr_ops.h" 59 #include "wma.h" 60 #include <../../core/src/wlan_cm_vdev_api.h> 61 #include "wlan_action_oui_main.h" 62 #include <wlan_cm_api.h> 63 #include <wlan_mlme_api.h> 64 #include <wlan_mlme_ucfg_api.h> 65 #include <wlan_reg_ucfg_api.h> 66 #include "wlan_lmac_if_def.h" 67 #include "wlan_reg_services_api.h" 68 #include <lim_mlo.h> 69 #include <wlan_vdev_mgr_utils_api.h> 70 #include "cfg_ucfg_api.h" 71 #include "wlan_twt_cfg_ext_api.h" 72 #include <spatial_reuse_api.h> 73 #include "wlan_psoc_mlme_api.h" 74 #include "wma_he.h" 75 #include "wlan_mlo_mgr_sta.h" 76 #include "wlan_mlme_main.h" 77 #ifdef WLAN_FEATURE_11BE_MLO 78 #include <wlan_mlo_mgr_peer.h> 79 #endif 80 81 /* SME REQ processing function templates */ 82 static bool __lim_process_sme_sys_ready_ind(struct mac_context *, uint32_t *); 83 static bool __lim_process_sme_start_bss_req(struct mac_context *, 84 struct scheduler_msg *pMsg); 85 static void __lim_process_sme_disassoc_req(struct mac_context *, uint32_t *); 86 static void lim_process_sme_disassoc_cnf(struct mac_context *mac_ctx, 87 struct scheduler_msg *msg); 88 static void lim_process_sme_deauth_req(struct mac_context *mac_ctx, 89 struct scheduler_msg *msg); 90 static void lim_process_sme_disassoc_req(struct mac_context *mac_ctx, 91 struct scheduler_msg *msg); 92 static void __lim_process_sme_disassoc_cnf(struct mac_context *, uint32_t *); 93 static void __lim_process_sme_deauth_req(struct mac_context *, uint32_t *); 94 static bool __lim_process_sme_stop_bss_req(struct mac_context *, 95 struct scheduler_msg *pMsg); 96 static void lim_process_sme_channel_change_request(struct mac_context *mac, 97 uint32_t *pMsg); 98 static void lim_process_sme_start_beacon_req(struct mac_context *mac, uint32_t *pMsg); 99 static void lim_process_sme_dfs_csa_ie_request(struct mac_context *mac, uint32_t *pMsg); 100 static void lim_process_nss_update_request(struct mac_context *mac, uint32_t *pMsg); 101 static void lim_process_set_ie_req(struct mac_context *mac, uint32_t *pMsg); 102 103 static void lim_start_bss_update_add_ie_buffer(struct mac_context *mac, 104 uint8_t **pDstData_buff, 105 uint16_t *pDstDataLen, 106 uint8_t *pSrcData_buff, 107 uint16_t srcDataLen); 108 109 static void lim_update_add_ie_buffer(struct mac_context *mac, 110 uint8_t **pDstData_buff, 111 uint16_t *pDstDataLen, 112 uint8_t *pSrcData_buff, uint16_t srcDataLen); 113 static void lim_process_modify_add_ies(struct mac_context *mac, uint32_t *pMsg); 114 115 static void lim_process_update_add_ies(struct mac_context *mac, uint32_t *pMsg); 116 117 static void lim_process_ext_change_channel(struct mac_context *mac_ctx, 118 uint32_t *msg); 119 120 static void lim_mlo_sap_validate_and_update_ra(struct pe_session *session, 121 struct qdf_mac_addr *peer_addr); 122 /** 123 * enum get_next_lower_bw - Get next higher bandwidth for a given BW. 124 * This enum is used in conjunction with 125 * wlan_reg_set_channel_params_for_pwrmode API to fetch center frequencies 126 * for each BW starting from 20MHz upto Max BSS BW in case of non-PSD power. 127 * 128 */ 129 static const enum phy_ch_width get_next_higher_bw[] = { 130 [CH_WIDTH_20MHZ] = CH_WIDTH_40MHZ, 131 [CH_WIDTH_40MHZ] = CH_WIDTH_80MHZ, 132 [CH_WIDTH_80MHZ] = CH_WIDTH_160MHZ, 133 #if !defined(WLAN_FEATURE_11BE) 134 [CH_WIDTH_160MHZ] = CH_WIDTH_INVALID 135 #else 136 [CH_WIDTH_160MHZ] = CH_WIDTH_320MHZ, 137 [CH_WIDTH_320MHZ] = CH_WIDTH_INVALID 138 #endif 139 }; 140 141 /** 142 * lim_process_set_hw_mode() - Send set HW mode command to WMA 143 * @mac: Globacl MAC pointer 144 * @msg: Message containing the hw mode index 145 * 146 * Send the set HW mode command to WMA 147 * 148 * Return: QDF_STATUS_SUCCESS if message posting is successful 149 */ 150 static QDF_STATUS lim_process_set_hw_mode(struct mac_context *mac, uint32_t *msg) 151 { 152 QDF_STATUS status = QDF_STATUS_SUCCESS; 153 struct scheduler_msg message = {0}; 154 struct policy_mgr_hw_mode *req_msg; 155 uint32_t len; 156 struct s_sir_set_hw_mode *buf; 157 struct scheduler_msg resp_msg = {0}; 158 struct sir_set_hw_mode_resp *param; 159 160 buf = (struct s_sir_set_hw_mode *) msg; 161 if (!buf) { 162 pe_err("Set HW mode param is NULL"); 163 status = QDF_STATUS_E_INVAL; 164 /* To free the active command list */ 165 goto fail; 166 } 167 168 len = sizeof(*req_msg); 169 170 req_msg = qdf_mem_malloc(len); 171 if (!req_msg) { 172 status = QDF_STATUS_E_NOMEM; 173 goto fail; 174 } 175 176 req_msg->hw_mode_index = buf->set_hw.hw_mode_index; 177 req_msg->reason = buf->set_hw.reason; 178 /* Other parameters are not needed for WMA */ 179 180 message.bodyptr = req_msg; 181 message.type = SIR_HAL_PDEV_SET_HW_MODE; 182 183 pe_debug("Posting SIR_HAL_SOC_SET_HW_MOD to WMA"); 184 status = scheduler_post_message(QDF_MODULE_ID_PE, 185 QDF_MODULE_ID_WMA, 186 QDF_MODULE_ID_WMA, &message); 187 if (!QDF_IS_STATUS_SUCCESS(status)) { 188 pe_err("scheduler_post_msg failed!(err=%d)", 189 status); 190 qdf_mem_free(req_msg); 191 goto fail; 192 } 193 return status; 194 fail: 195 param = qdf_mem_malloc(sizeof(*param)); 196 if (!param) 197 return QDF_STATUS_E_FAILURE; 198 param->status = SET_HW_MODE_STATUS_ECANCELED; 199 param->cfgd_hw_mode_index = 0; 200 param->num_vdev_mac_entries = 0; 201 resp_msg.type = eWNI_SME_SET_HW_MODE_RESP; 202 resp_msg.bodyptr = param; 203 resp_msg.bodyval = 0; 204 lim_sys_process_mmh_msg_api(mac, &resp_msg); 205 return status; 206 } 207 208 /** 209 * lim_process_set_dual_mac_cfg_req() - Set dual mac config command to WMA 210 * @mac: Global MAC pointer 211 * @msg: Message containing the dual mac config parameter 212 * 213 * Send the set dual mac config command to WMA 214 * 215 * Return: QDF_STATUS_SUCCESS if message posting is successful 216 */ 217 static QDF_STATUS lim_process_set_dual_mac_cfg_req(struct mac_context *mac, 218 uint32_t *msg) 219 { 220 QDF_STATUS status = QDF_STATUS_SUCCESS; 221 struct scheduler_msg message = {0}; 222 struct policy_mgr_dual_mac_config *req_msg; 223 uint32_t len; 224 struct sir_set_dual_mac_cfg *buf; 225 struct scheduler_msg resp_msg = {0}; 226 struct sir_dual_mac_config_resp *param; 227 228 buf = (struct sir_set_dual_mac_cfg *) msg; 229 if (!buf) { 230 pe_err("Set Dual mac config is NULL"); 231 status = QDF_STATUS_E_INVAL; 232 /* To free the active command list */ 233 goto fail; 234 } 235 236 len = sizeof(*req_msg); 237 238 req_msg = qdf_mem_malloc(len); 239 if (!req_msg) { 240 status = QDF_STATUS_E_NOMEM; 241 goto fail; 242 } 243 244 req_msg->scan_config = buf->set_dual_mac.scan_config; 245 req_msg->fw_mode_config = buf->set_dual_mac.fw_mode_config; 246 /* Other parameters are not needed for WMA */ 247 248 message.bodyptr = req_msg; 249 message.type = SIR_HAL_PDEV_DUAL_MAC_CFG_REQ; 250 251 pe_debug("Post SIR_HAL_PDEV_DUAL_MAC_CFG_REQ to WMA: %x %x", 252 req_msg->scan_config, req_msg->fw_mode_config); 253 status = scheduler_post_message(QDF_MODULE_ID_PE, 254 QDF_MODULE_ID_WMA, 255 QDF_MODULE_ID_WMA, &message); 256 if (!QDF_IS_STATUS_SUCCESS(status)) { 257 pe_err("scheduler_post_msg failed!(err=%d)", 258 status); 259 qdf_mem_free(req_msg); 260 goto fail; 261 } 262 return status; 263 fail: 264 param = qdf_mem_malloc(sizeof(*param)); 265 if (!param) 266 return QDF_STATUS_E_FAILURE; 267 param->status = SET_HW_MODE_STATUS_ECANCELED; 268 resp_msg.type = eWNI_SME_SET_DUAL_MAC_CFG_RESP; 269 resp_msg.bodyptr = param; 270 resp_msg.bodyval = 0; 271 lim_sys_process_mmh_msg_api(mac, &resp_msg); 272 return status; 273 } 274 275 #ifdef FEATURE_WLAN_ESE 276 static inline bool 277 lim_is_ese_enabled(struct mac_context *mac_ctx) 278 { 279 return mac_ctx->mlme_cfg->lfr.ese_enabled; 280 } 281 #else 282 static inline bool 283 lim_is_ese_enabled(struct mac_context *mac_ctx) 284 { 285 return false; 286 } 287 #endif 288 289 /** 290 * lim_process_set_antenna_mode_req() - Set antenna mode command 291 * to WMA 292 * @mac: Global MAC pointer 293 * @msg: Message containing the antenna mode parameter 294 * 295 * Send the set antenna mode command to WMA 296 * 297 * Return: QDF_STATUS_SUCCESS if message posting is successful 298 */ 299 static QDF_STATUS lim_process_set_antenna_mode_req(struct mac_context *mac, 300 uint32_t *msg) 301 { 302 QDF_STATUS status = QDF_STATUS_SUCCESS; 303 struct scheduler_msg message = {0}; 304 struct sir_antenna_mode_param *req_msg; 305 struct sir_set_antenna_mode *buf; 306 struct scheduler_msg resp_msg = {0}; 307 struct sir_antenna_mode_resp *param; 308 309 buf = (struct sir_set_antenna_mode *) msg; 310 if (!buf) { 311 pe_err("Set antenna mode is NULL"); 312 status = QDF_STATUS_E_INVAL; 313 /* To free the active command list */ 314 goto fail; 315 } 316 317 req_msg = qdf_mem_malloc(sizeof(*req_msg)); 318 if (!req_msg) { 319 status = QDF_STATUS_E_NOMEM; 320 goto fail; 321 } 322 323 req_msg->num_rx_chains = buf->set_antenna_mode.num_rx_chains; 324 req_msg->num_tx_chains = buf->set_antenna_mode.num_tx_chains; 325 326 message.bodyptr = req_msg; 327 message.type = SIR_HAL_SOC_ANTENNA_MODE_REQ; 328 329 pe_debug("Post SIR_HAL_SOC_ANTENNA_MODE_REQ to WMA: %d %d", 330 req_msg->num_rx_chains, 331 req_msg->num_tx_chains); 332 status = scheduler_post_message(QDF_MODULE_ID_PE, 333 QDF_MODULE_ID_WMA, 334 QDF_MODULE_ID_WMA, &message); 335 if (!QDF_IS_STATUS_SUCCESS(status)) { 336 pe_err("scheduler_post_msg failed!(err=%d)", 337 status); 338 qdf_mem_free(req_msg); 339 goto fail; 340 } 341 return status; 342 fail: 343 param = qdf_mem_malloc(sizeof(*param)); 344 if (!param) 345 return QDF_STATUS_E_NOMEM; 346 param->status = SET_ANTENNA_MODE_STATUS_ECANCELED; 347 resp_msg.type = eWNI_SME_SET_ANTENNA_MODE_RESP; 348 resp_msg.bodyptr = param; 349 resp_msg.bodyval = 0; 350 lim_sys_process_mmh_msg_api(mac, &resp_msg); 351 return status; 352 } 353 354 /** 355 * __lim_is_sme_assoc_cnf_valid() -- Validate ASSOC_CNF message 356 * @assoc_cnf: Pointer to Received ASSOC_CNF message 357 * 358 * This function is called by __lim_process_sme_assoc_cnf_new() upon 359 * receiving SME_ASSOC_CNF. 360 * 361 * Return: true when received SME_ASSOC_CNF is formatted correctly 362 * false otherwise 363 */ 364 static bool __lim_is_sme_assoc_cnf_valid(struct assoc_cnf *assoc_cnf) 365 { 366 if (qdf_is_macaddr_group(&assoc_cnf->peer_macaddr)) 367 return false; 368 369 return true; 370 } 371 372 /** 373 * __lim_is_deferred_msg_for_radar() - Defers the message if radar is detected 374 * @mac_ctx: Pointer to Global MAC structure 375 * @message: Pointer to message posted from SME to LIM. 376 * 377 * Has role only if 11h is enabled. Not used on STA side. 378 * Defers the message if radar is detected. 379 * 380 * Return: true, if deferred otherwise return false. 381 */ 382 static bool 383 __lim_is_deferred_msg_for_radar(struct mac_context *mac_ctx, 384 struct scheduler_msg *message) 385 { 386 /* 387 * fRadarDetCurOperChan will be set only if we 388 * detect radar in current operating channel and 389 * System Role == AP ROLE 390 * 391 * TODO: Need to take care radar detection. 392 * 393 * if (LIM_IS_RADAR_DETECTED(mac_ctx)) 394 */ 395 if (0) { 396 if (lim_defer_msg(mac_ctx, message) != TX_SUCCESS) { 397 pe_err("Could not defer Msg: %d", message->type); 398 return false; 399 } 400 pe_debug("Defer the message, in learn mode type: %d", 401 message->type); 402 return true; 403 } 404 return false; 405 } 406 407 /** 408 * __lim_process_sme_sys_ready_ind () - Process ready indication from WMA 409 * @mac: Global MAC context 410 * @msg_buf: Message from WMA 411 * 412 * handles the notification from HDD. PE just forwards this message to HAL. 413 * 414 * Return: true-Posting to HAL failed, so PE will consume the buffer. 415 * false-Posting to HAL successful, so HAL will consume the buffer. 416 */ 417 418 static bool __lim_process_sme_sys_ready_ind(struct mac_context *mac, 419 uint32_t *msg_buf) 420 { 421 struct scheduler_msg msg = {0}; 422 struct sme_ready_req *ready_req = (struct sme_ready_req *)msg_buf; 423 424 msg.type = WMA_SYS_READY_IND; 425 msg.reserved = 0; 426 msg.bodyptr = msg_buf; 427 msg.bodyval = 0; 428 429 if (ANI_DRIVER_TYPE(mac) != QDF_DRIVER_TYPE_MFG) { 430 ready_req->pe_roam_synch_cb = pe_roam_synch_callback; 431 ready_req->pe_disconnect_cb = pe_disconnect_callback; 432 ready_req->pe_roam_set_ie_cb = pe_set_ie_for_roam_invoke; 433 pe_register_mgmt_rx_frm_callback(mac); 434 pe_register_callbacks_with_wma(mac, ready_req); 435 mac->lim.sme_msg_callback = ready_req->sme_msg_cb; 436 mac->lim.stop_roaming_callback = ready_req->stop_roaming_cb; 437 } 438 439 pe_debug("sending WMA_SYS_READY_IND msg to HAL"); 440 MTRACE(mac_trace_msg_tx(mac, NO_SESSION, msg.type)); 441 442 if (QDF_STATUS_SUCCESS != wma_post_ctrl_msg(mac, &msg)) { 443 pe_err("wma_post_ctrl_msg failed"); 444 return true; 445 } 446 return false; 447 } 448 449 /** 450 *lim_configure_ap_start_bss_session() - Configure the AP Start BSS in session. 451 *@mac_ctx: Pointer to Global MAC structure 452 *@session: A pointer to session entry 453 *@sme_start_bss_req: Start BSS Request from upper layers. 454 * 455 * This function is used to configure the start bss parameters 456 * in to the session. 457 * 458 * Return: None. 459 */ 460 static void 461 lim_configure_ap_start_bss_session(struct mac_context *mac_ctx, 462 struct pe_session *session, 463 struct start_bss_config *sme_start_bss_req) 464 { 465 bool sap_uapsd; 466 uint16_t ht_cap = cfg_default(CFG_AP_PROTECTION_MODE); 467 468 session->limSystemRole = eLIM_AP_ROLE; 469 session->privacy = sme_start_bss_req->privacy; 470 session->fwdWPSPBCProbeReq = 1; 471 session->authType = sme_start_bss_req->authType; 472 /* Store the DTIM period */ 473 session->dtimPeriod = (uint8_t) sme_start_bss_req->dtimPeriod; 474 475 /* Enable/disable UAPSD */ 476 wlan_mlme_is_sap_uapsd_enabled(mac_ctx->psoc, &sap_uapsd); 477 session->apUapsdEnable = sap_uapsd; 478 479 session->gLimProtectionControl = 480 wlan_mlme_is_ap_prot_enabled(mac_ctx->psoc); 481 482 wlan_mlme_get_ap_protection_mode(mac_ctx->psoc, &ht_cap); 483 qdf_mem_copy((void *)&session->cfgProtection, 484 (void *)&ht_cap, 485 sizeof(uint16_t)); 486 487 wlan_mlme_get_vendor_vht_for_24ghz(mac_ctx->psoc, 488 &session->vendor_vht_sap); 489 if (session->opmode == QDF_P2P_GO_MODE) { 490 session->sap_dot11mc = 1; 491 session->proxyProbeRspEn = 0; 492 } else { 493 session->sap_dot11mc = mac_ctx->mlme_cfg->gen.sap_dot11mc; 494 /* 495 * To detect PBC overlap in SAP WPS mode, 496 * Host handles Probe Requests. 497 */ 498 if (SAP_WPS_DISABLED == sme_start_bss_req->wps_state) 499 session->proxyProbeRspEn = 1; 500 else 501 session->proxyProbeRspEn = 0; 502 } 503 session->ssidHidden = sme_start_bss_req->ssidHidden; 504 session->wps_state = sme_start_bss_req->wps_state; 505 506 lim_get_short_slot_from_phy_mode(mac_ctx, session, session->gLimPhyMode, 507 &session->shortSlotTimeSupported); 508 509 session->beacon_tx_rate = sme_start_bss_req->beacon_tx_rate; 510 511 } 512 513 static void lim_set_privacy(struct mac_context *mac_ctx, 514 int32_t ucast_cipher, 515 int32_t auth_mode, int32_t akm, bool ap_privacy) 516 { 517 bool rsn_enabled, privacy; 518 519 /* set default to open */ 520 mac_ctx->mlme_cfg->wep_params.auth_type = eSIR_OPEN_SYSTEM; 521 if (QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_AUTO) && 522 (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WEP) || 523 QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WEP_40) || 524 QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WEP_104))) 525 mac_ctx->mlme_cfg->wep_params.auth_type = eSIR_AUTO_SWITCH; 526 else if (QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_SHARED)) 527 mac_ctx->mlme_cfg->wep_params.auth_type = eSIR_SHARED_KEY; 528 else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_SAE) || 529 QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE) || 530 QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE_EXT_KEY) || 531 QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_SAE_EXT_KEY)) 532 mac_ctx->mlme_cfg->wep_params.auth_type = eSIR_AUTH_TYPE_SAE; 533 534 if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WEP) || 535 QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WEP_40) || 536 QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WEP_104)) { 537 privacy = true; 538 rsn_enabled = false; 539 } else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_TKIP) || 540 QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_CCM) || 541 QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_OCB) || 542 QDF_HAS_PARAM(ucast_cipher, 543 WLAN_CRYPTO_CIPHER_AES_CCM_256) || 544 QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_GCM) || 545 QDF_HAS_PARAM(ucast_cipher, 546 WLAN_CRYPTO_CIPHER_AES_GCM_256) || 547 QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WAPI_GCM4) || 548 QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WAPI_SMS4)) { 549 privacy = ap_privacy; 550 rsn_enabled = true; 551 } else { 552 rsn_enabled = false; 553 privacy = false; 554 } 555 556 mac_ctx->mlme_cfg->feature_flags.enable_rsn = rsn_enabled; 557 mac_ctx->mlme_cfg->wep_params.is_privacy_enabled = privacy; 558 mac_ctx->mlme_cfg->wep_params.wep_default_key_id = 0; 559 } 560 561 /** 562 * lim_send_start_vdev_req() - send vdev start request 563 *@session: pe session 564 *@mlm_start_req: vdev start req 565 * 566 * Return: QDF_STATUS 567 */ 568 static QDF_STATUS 569 lim_send_start_vdev_req(struct pe_session *session, tLimMlmStartReq *mlm_start_req) 570 { 571 return wlan_vdev_mlme_sm_deliver_evt(session->vdev, 572 WLAN_VDEV_SM_EV_START, 573 sizeof(*mlm_start_req), 574 mlm_start_req); 575 } 576 577 #ifdef WLAN_FEATURE_11BE 578 void lim_strip_eht_ies_from_add_ies(struct mac_context *mac_ctx, 579 struct pe_session *session) 580 { 581 struct add_ie_params *add_ie = &session->add_ie_params; 582 QDF_STATUS status; 583 uint8_t eht_cap_buff[DOT11F_IE_EHT_CAP_MAX_LEN + 2]; 584 uint8_t eht_op_buff[DOT11F_IE_EHT_OP_MAX_LEN + 2]; 585 586 qdf_mem_zero(eht_cap_buff, sizeof(eht_cap_buff)); 587 qdf_mem_zero(eht_op_buff, sizeof(eht_op_buff)); 588 589 status = lim_strip_ie(mac_ctx, add_ie->probeRespBCNData_buff, 590 &add_ie->probeRespBCNDataLen, 591 DOT11F_EID_EHT_CAP, ONE_BYTE, 592 EHT_CAP_OUI_TYPE, (uint8_t)EHT_CAP_OUI_SIZE, 593 eht_cap_buff, DOT11F_IE_EHT_CAP_MAX_LEN); 594 if (status != QDF_STATUS_SUCCESS) 595 pe_debug("Failed to strip EHT cap IE status: %d", status); 596 597 status = lim_strip_ie(mac_ctx, add_ie->probeRespBCNData_buff, 598 &add_ie->probeRespBCNDataLen, 599 DOT11F_EID_EHT_OP, ONE_BYTE, 600 EHT_OP_OUI_TYPE, (uint8_t)EHT_OP_OUI_SIZE, 601 eht_op_buff, DOT11F_IE_EHT_OP_MAX_LEN); 602 if (status != QDF_STATUS_SUCCESS) 603 pe_debug("Failed to strip EHT op IE status: %d", status); 604 } 605 #else 606 void lim_strip_eht_ies_from_add_ies(struct mac_context *mac_ctx, 607 struct pe_session *session) 608 { 609 } 610 #endif 611 612 #ifdef WLAN_FEATURE_11AX 613 void lim_strip_he_ies_from_add_ies(struct mac_context *mac_ctx, 614 struct pe_session *session) 615 { 616 struct add_ie_params *add_ie = &session->add_ie_params; 617 QDF_STATUS status; 618 uint8_t he_cap_buff[DOT11F_IE_HE_CAP_MAX_LEN + 2]; 619 uint8_t he_op_buff[DOT11F_IE_HE_OP_MAX_LEN + 2]; 620 621 qdf_mem_zero(he_cap_buff, sizeof(he_cap_buff)); 622 qdf_mem_zero(he_op_buff, sizeof(he_op_buff)); 623 624 status = lim_strip_ie(mac_ctx, add_ie->probeRespBCNData_buff, 625 &add_ie->probeRespBCNDataLen, 626 DOT11F_EID_HE_CAP, ONE_BYTE, 627 HE_CAP_OUI_TYPE, (uint8_t)HE_CAP_OUI_SIZE, 628 he_cap_buff, DOT11F_IE_HE_CAP_MAX_LEN); 629 if (status != QDF_STATUS_SUCCESS) 630 pe_debug("Failed to strip HE cap IE status: %d", status); 631 632 633 status = lim_strip_ie(mac_ctx, add_ie->probeRespBCNData_buff, 634 &add_ie->probeRespBCNDataLen, 635 DOT11F_EID_HE_OP, ONE_BYTE, 636 HE_OP_OUI_TYPE, (uint8_t)HE_OP_OUI_SIZE, 637 he_op_buff, DOT11F_IE_HE_OP_MAX_LEN); 638 if (status != QDF_STATUS_SUCCESS) 639 pe_debug("Failed to strip HE op IE status: %d", status); 640 } 641 #else 642 void lim_strip_he_ies_from_add_ies(struct mac_context *mac_ctx, 643 struct pe_session *session) 644 { 645 } 646 #endif 647 648 #ifdef FEATURE_WLAN_WAPI 649 650 void lim_strip_wapi_ies_from_add_ies(struct mac_context *mac_ctx, 651 struct pe_session *session) 652 { 653 struct add_ie_params *add_ie = &session->add_ie_params; 654 uint8_t wapiie_buff[DOT11F_IE_WAPIOPAQUE_MAX_LEN + 2]; 655 QDF_STATUS status; 656 657 qdf_mem_zero(wapiie_buff, sizeof(wapiie_buff)); 658 659 status = lim_strip_ie(mac_ctx, add_ie->probeRespBCNData_buff, 660 &add_ie->probeRespBCNDataLen, 661 DOT11F_EID_WAPIOPAQUE, ONE_BYTE, 662 NULL, 0, 663 wapiie_buff, DOT11F_IE_WAPIOPAQUE_MAX_LEN); 664 if (status != QDF_STATUS_SUCCESS) 665 pe_debug("Failed to strip WAPI IE status: %d", status); 666 } 667 #else 668 void lim_strip_wapi_ies_from_add_ies(struct mac_context *mac_ctx, 669 struct pe_session *session) 670 { 671 } 672 #endif 673 /** 674 * lim_set_ldpc_exception() - to set allow any LDPC exception permitted 675 * @mac_ctx: Pointer to mac context 676 * @vdev_mlme: vdev mlme 677 * @ch_freq: Given channel frequency where connection will go 678 * 679 * This API will check if hardware allows LDPC to be enabled for provided 680 * channel and user has enabled the RX LDPC selection 681 * 682 * Return: QDF_STATUS 683 */ 684 static QDF_STATUS lim_set_ldpc_exception(struct mac_context *mac_ctx, 685 struct vdev_mlme_obj *vdev_mlme, 686 uint32_t ch_freq) 687 { 688 struct wlan_vht_config vht_config; 689 struct wlan_ht_config ht_caps; 690 691 vht_config.caps = vdev_mlme->proto.vht_info.caps; 692 ht_caps.caps = vdev_mlme->proto.ht_info.ht_caps; 693 694 if (mac_ctx->mlme_cfg->ht_caps.ht_cap_info.adv_coding_cap && 695 wma_is_rx_ldpc_supported_for_channel(ch_freq)) { 696 ht_caps.ht_caps.adv_coding_cap = 1; 697 vht_config.ldpc_coding = 1; 698 sme_debug("LDPC enable for ch freq[%d]", ch_freq); 699 } else { 700 ht_caps.ht_caps.adv_coding_cap = 0; 701 vht_config.ldpc_coding = 0; 702 sme_debug("LDPC disable for ch freq[%d]", ch_freq); 703 } 704 vdev_mlme->proto.vht_info.caps = vht_config.caps; 705 vdev_mlme->proto.ht_info.ht_caps = ht_caps.caps; 706 707 return QDF_STATUS_SUCCESS; 708 } 709 710 /** 711 * lim_revise_req_vht_cap_per_band: Update vht cap based on band 712 * @session: Session pointer 713 * 714 * Return: None 715 * 716 */ 717 static void lim_revise_req_vht_cap_per_band(struct pe_session *session) 718 { 719 struct wlan_vht_config *vht_config; 720 721 vht_config = &session->vht_config; 722 /* Disable shortgi160 and 80 for 2.4Ghz BSS*/ 723 if (wlan_reg_is_24ghz_ch_freq(session->curr_op_freq)) { 724 vht_config->shortgi80 = 0; 725 vht_config->shortgi160and80plus80 = 0; 726 } 727 } 728 729 static void lim_start_bss_update_ht_vht_caps(struct mac_context *mac_ctx, 730 struct pe_session *session) 731 { 732 struct vdev_mlme_obj *vdev_mlme; 733 struct wlan_vht_config vht_config; 734 uint8_t value = 0; 735 struct wlan_ht_config ht_caps; 736 737 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(session->vdev); 738 if (!vdev_mlme) 739 return; 740 if (!policy_mgr_is_dbs_enable(mac_ctx->psoc)) 741 lim_set_ldpc_exception(mac_ctx, vdev_mlme, 742 session->curr_op_freq); 743 vht_config.caps = vdev_mlme->proto.vht_info.caps; 744 value = mac_ctx->mlme_cfg->vht_caps.vht_cap_info.su_bformee; 745 vht_config.su_beam_formee = 746 value && mac_ctx->mlme_cfg->vht_caps.vht_cap_info.tx_bfee_sap; 747 value = MLME_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED_FW_DEF; 748 vht_config.csnof_beamformer_antSup = value; 749 vht_config.mu_beam_formee = 0; 750 if (session->pLimStartBssReq->vht_channel_width <= CH_WIDTH_80MHZ) { 751 vht_config.shortgi160and80plus80 = 0; 752 vht_config.supported_channel_widthset = 0; 753 } 754 755 session->vht_config = vht_config; 756 757 ht_caps.caps = vdev_mlme->proto.ht_info.ht_caps; 758 session->ht_config = ht_caps.ht_caps; 759 760 lim_revise_req_vht_cap_per_band(session); 761 pe_debug("cur_op_freq %d HT capability 0x%x VHT capability 0x%x bw %d", 762 session->curr_op_freq, ht_caps.caps, vht_config.caps, 763 session->pLimStartBssReq->vht_channel_width); 764 } 765 766 #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH 767 static inline void lim_fill_cc_mode(struct mac_context *mac_ctx, 768 struct pe_session *session) 769 { 770 session->cc_switch_mode = mac_ctx->roam.configParam.cc_switch_mode; 771 } 772 #else 773 static inline void lim_fill_cc_mode(struct mac_context *mac_ctx, 774 struct pe_session *session) 775 { 776 } 777 #endif 778 779 #ifdef WLAN_FEATURE_SON 780 /** 781 * lim_save_max_mcs_idx() - save max mcs index to mlme component 782 * @mac_ctx: Pointer to Global MAC structure 783 * @session: pointer to pe session 784 * 785 * Return: void 786 */ 787 static void 788 lim_save_max_mcs_idx(struct mac_context *mac_ctx, struct pe_session *session) 789 { 790 tDot11fIEVHTCaps vht_cap; 791 tDot11fIEhe_cap he_cap; 792 tDot11fIEHTCaps ht_cap; 793 u_int8_t session_max_mcs_idx = INVALID_MCS_NSS_INDEX; 794 795 if (IS_DOT11_MODE_HE(session->dot11mode)) { 796 qdf_mem_zero(&he_cap, sizeof(tDot11fIEhe_cap)); 797 populate_dot11f_he_caps(mac_ctx, session, &he_cap); 798 session_max_mcs_idx = lim_get_he_max_mcs_idx(session->ch_width, 799 &he_cap); 800 } 801 if (session_max_mcs_idx == INVALID_MCS_NSS_INDEX && 802 IS_DOT11_MODE_VHT(session->dot11mode)) { 803 qdf_mem_zero(&vht_cap, sizeof(tDot11fIEVHTCaps)); 804 populate_dot11f_vht_caps(mac_ctx, session, &vht_cap); 805 session_max_mcs_idx = lim_get_vht_max_mcs_idx(&vht_cap); 806 } 807 if (session_max_mcs_idx == INVALID_MCS_NSS_INDEX && 808 IS_DOT11_MODE_HT(session->dot11mode)) { 809 qdf_mem_zero(&ht_cap, sizeof(tDot11fIEHTCaps)); 810 populate_dot11f_ht_caps(mac_ctx, session, &ht_cap); 811 session_max_mcs_idx = lim_get_ht_max_mcs_idx(&ht_cap); 812 } 813 if (session_max_mcs_idx == INVALID_MCS_NSS_INDEX && 814 session->extRateSet.numRates) 815 session_max_mcs_idx = 816 lim_get_max_rate_idx(&session->extRateSet); 817 818 if (session_max_mcs_idx == INVALID_MCS_NSS_INDEX && 819 session->rateSet.numRates) 820 session_max_mcs_idx = 821 lim_get_max_rate_idx(&session->rateSet); 822 823 mlme_save_vdev_max_mcs_idx(session->vdev, session_max_mcs_idx); 824 } 825 #else 826 static void 827 lim_save_max_mcs_idx(struct mac_context *mac_ctx, struct pe_session *session) 828 { 829 } 830 #endif 831 832 /** 833 * __lim_handle_sme_start_bss_request() - process SME_START_BSS_REQ message 834 *@mac_ctx: Pointer to Global MAC structure 835 *@msg_buf: A pointer to the SME message buffer 836 * 837 * This function is called to process SME_START_BSS_REQ message 838 * from HDD or upper layer application. 839 * 840 * Return: None 841 */ 842 static void 843 __lim_handle_sme_start_bss_request(struct mac_context *mac_ctx, uint32_t *msg_buf) 844 { 845 uint16_t size; 846 uint32_t val = 0; 847 tSirMacChanNum channel_number; 848 tLimMlmStartReq *mlm_start_req = NULL; 849 struct start_bss_config *sme_start_bss_req = NULL; 850 tSirResultCodes ret_code = eSIR_SME_SUCCESS; 851 uint8_t session_id; 852 struct pe_session *session = NULL; 853 uint8_t vdev_id = 0xFF; 854 uint32_t chanwidth; 855 struct vdev_type_nss *vdev_type_nss; 856 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; 857 int32_t ucast_cipher; 858 int32_t auth_mode; 859 int32_t akm; 860 int32_t rsn_caps; 861 bool cfg_value = false; 862 enum QDF_OPMODE opmode; 863 ePhyChanBondState cb_mode; 864 enum bss_type bss_type; 865 struct qdf_mac_addr bssid; 866 867 /* FEATURE_WLAN_DIAG_SUPPORT */ 868 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM 869 /* 870 * Since the session is not created yet, sending NULL. 871 * The response should have the correct state. 872 */ 873 lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_START_BSS_REQ_EVENT, 874 NULL, 0, 0); 875 #endif /* FEATURE_WLAN_DIAG_SUPPORT */ 876 877 size = sizeof(*sme_start_bss_req); 878 sme_start_bss_req = qdf_mem_malloc(size); 879 if (!sme_start_bss_req) { 880 ret_code = eSIR_SME_RESOURCES_UNAVAILABLE; 881 goto free; 882 } 883 qdf_mem_copy(sme_start_bss_req, msg_buf, size); 884 vdev_id = sme_start_bss_req->vdev_id; 885 886 opmode = wlan_get_opmode_from_vdev_id(mac_ctx->pdev, vdev_id); 887 if (opmode == QDF_NDI_MODE) 888 bss_type = eSIR_NDI_MODE; 889 else 890 bss_type = eSIR_INFRA_AP_MODE; 891 892 wlan_mlme_get_mac_vdev_id(mac_ctx->pdev, vdev_id, &bssid); 893 894 if ((mac_ctx->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) || 895 (mac_ctx->lim.gLimSmeState == eLIM_SME_IDLE_STATE)) { 896 if (!lim_is_sme_start_bss_req_valid(mac_ctx, 897 sme_start_bss_req, bss_type)) { 898 pe_warn("Received invalid eWNI_SME_START_BSS_REQ"); 899 ret_code = eSIR_SME_INVALID_PARAMETERS; 900 goto free; 901 } 902 channel_number = wlan_reg_freq_to_chan(mac_ctx->pdev, 903 sme_start_bss_req->oper_ch_freq); 904 /* 905 * This is the place where PE is going to create a session. 906 * If session is not existed, then create a new session 907 */ 908 session = pe_find_session_by_bssid(mac_ctx, bssid.bytes, 909 &session_id); 910 if (session) { 911 pe_warn("Session Already exists for given BSSID"); 912 ret_code = eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED; 913 session = NULL; 914 goto free; 915 } else { 916 session = pe_create_session(mac_ctx, bssid.bytes, 917 &session_id, 918 mac_ctx->lim.max_sta_of_pe_session, 919 bss_type, 920 sme_start_bss_req->vdev_id); 921 if (!session) { 922 pe_warn("Session Can not be created"); 923 ret_code = eSIR_SME_RESOURCES_UNAVAILABLE; 924 goto free; 925 } 926 927 /* Update the beacon/probe filter in mac_ctx */ 928 lim_set_bcn_probe_filter(mac_ctx, session, 929 channel_number); 930 } 931 932 if (QDF_NDI_MODE != opmode) { 933 /* Probe resp add ie */ 934 lim_start_bss_update_add_ie_buffer(mac_ctx, 935 &session->add_ie_params.probeRespData_buff, 936 &session->add_ie_params.probeRespDataLen, 937 sme_start_bss_req->add_ie_params. 938 probeRespData_buff, 939 sme_start_bss_req->add_ie_params. 940 probeRespDataLen); 941 942 /* Probe Beacon add ie */ 943 lim_start_bss_update_add_ie_buffer(mac_ctx, 944 &session->add_ie_params.probeRespBCNData_buff, 945 &session->add_ie_params.probeRespBCNDataLen, 946 sme_start_bss_req->add_ie_params. 947 probeRespBCNData_buff, 948 sme_start_bss_req->add_ie_params. 949 probeRespBCNDataLen); 950 951 /* Assoc resp IE */ 952 lim_start_bss_update_add_ie_buffer(mac_ctx, 953 &session->add_ie_params.assocRespData_buff, 954 &session->add_ie_params.assocRespDataLen, 955 sme_start_bss_req->add_ie_params. 956 assocRespData_buff, 957 sme_start_bss_req->add_ie_params. 958 assocRespDataLen); 959 } 960 /* Store the session related params in newly created session */ 961 session->curr_op_freq = sme_start_bss_req->oper_ch_freq; 962 session->pLimStartBssReq = sme_start_bss_req; 963 lim_start_bss_update_ht_vht_caps(mac_ctx, session); 964 965 sir_copy_mac_addr(session->self_mac_addr, bssid.bytes); 966 /* Copy SSID to session table */ 967 qdf_mem_copy((uint8_t *) &session->ssId, 968 (uint8_t *) &sme_start_bss_req->ssId, 969 (sme_start_bss_req->ssId.length + 1)); 970 971 session->nwType = sme_start_bss_req->nwType; 972 973 session->beaconParams.beaconInterval = 974 sme_start_bss_req->beaconInterval; 975 976 /* Update the phymode */ 977 session->gLimPhyMode = sme_start_bss_req->nwType; 978 979 session->maxTxPower = wlan_reg_get_channel_reg_power_for_freq( 980 mac_ctx->pdev, session->curr_op_freq); 981 /* Store the dot 11 mode in to the session Table */ 982 session->dot11mode = sme_start_bss_req->dot11mode; 983 984 if (session->dot11mode == MLME_DOT11_MODE_11B) 985 mac_ctx->mlme_cfg-> 986 feature_flags.enable_short_slot_time_11g = 0; 987 else 988 mac_ctx->mlme_cfg->feature_flags. 989 enable_short_slot_time_11g = 990 mac_ctx->mlme_cfg->ht_caps. 991 short_slot_time_enabled; 992 ucast_cipher = wlan_crypto_get_param(session->vdev, 993 WLAN_CRYPTO_PARAM_UCAST_CIPHER); 994 auth_mode = wlan_crypto_get_param(session->vdev, 995 WLAN_CRYPTO_PARAM_AUTH_MODE); 996 akm = wlan_crypto_get_param(session->vdev, 997 WLAN_CRYPTO_PARAM_KEY_MGMT); 998 999 lim_set_privacy(mac_ctx, ucast_cipher, auth_mode, akm, 1000 sme_start_bss_req->privacy); 1001 #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH 1002 lim_fill_cc_mode(mac_ctx, session); 1003 #endif 1004 1005 if (!wlan_reg_is_24ghz_ch_freq(session->curr_op_freq)) { 1006 vdev_type_nss = &mac_ctx->vdev_type_nss_5g; 1007 cb_mode = mac_ctx->roam.configParam. 1008 channelBondingMode5GHz; 1009 } else { 1010 vdev_type_nss = &mac_ctx->vdev_type_nss_2g; 1011 cb_mode = mac_ctx->roam.configParam. 1012 channelBondingMode24GHz; 1013 } 1014 1015 switch (bss_type) { 1016 case eSIR_INFRA_AP_MODE: 1017 lim_configure_ap_start_bss_session(mac_ctx, session, 1018 sme_start_bss_req); 1019 if (session->opmode == QDF_SAP_MODE) 1020 session->vdev_nss = vdev_type_nss->sap; 1021 else 1022 session->vdev_nss = vdev_type_nss->p2p_go; 1023 break; 1024 case eSIR_NDI_MODE: 1025 session->vdev_nss = vdev_type_nss->ndi; 1026 session->limSystemRole = eLIM_NDI_ROLE; 1027 break; 1028 1029 1030 /* 1031 * There is one more mode called auto mode. 1032 * which is used no where 1033 */ 1034 1035 /* FORBUILD -TEMPFIX.. HOW TO use AUTO MODE????? */ 1036 1037 default: 1038 /* not used anywhere...used in scan function */ 1039 break; 1040 } 1041 1042 session->nss = session->vdev_nss; 1043 if (!mac_ctx->mlme_cfg->vht_caps.vht_cap_info.enable2x2) 1044 session->nss = 1; 1045 1046 session->htCapability = 1047 IS_DOT11_MODE_HT(session->dot11mode); 1048 session->vhtCapability = 1049 IS_DOT11_MODE_VHT(session->dot11mode); 1050 1051 if (IS_DOT11_MODE_HE(session->dot11mode)) { 1052 lim_update_session_he_capable(mac_ctx, session); 1053 lim_copy_bss_he_cap(session); 1054 } else if (wlan_reg_is_6ghz_chan_freq(session->curr_op_freq)) { 1055 pe_err("Invalid oper_ch_freq %d for dot11mode %d", 1056 session->curr_op_freq, session->dot11mode); 1057 ret_code = eSIR_SME_INVALID_PARAMETERS; 1058 goto free; 1059 } else { 1060 lim_strip_he_ies_from_add_ies(mac_ctx, session); 1061 } 1062 1063 if (IS_DOT11_MODE_EHT(session->dot11mode)) { 1064 lim_update_session_eht_capable(mac_ctx, session); 1065 lim_copy_bss_eht_cap(session); 1066 } else { 1067 lim_strip_eht_ies_from_add_ies(mac_ctx, session); 1068 } 1069 1070 session->txLdpcIniFeatureEnabled = 1071 mac_ctx->mlme_cfg->ht_caps.tx_ldpc_enable; 1072 rsn_caps = wlan_crypto_get_param(session->vdev, 1073 WLAN_CRYPTO_PARAM_RSN_CAP); 1074 session->limRmfEnabled = 1075 rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED ? 1 : 0; 1076 1077 qdf_mem_copy((void *)&session->rateSet, 1078 (void *)&sme_start_bss_req->operationalRateSet, 1079 sizeof(tSirMacRateSet)); 1080 qdf_mem_copy((void *)&session->extRateSet, 1081 (void *)&sme_start_bss_req->extendedRateSet, 1082 sizeof(tSirMacRateSet)); 1083 /* 1084 * Allocate memory for the array of 1085 * parsed (Re)Assoc request structure 1086 */ 1087 if (bss_type == eSIR_INFRA_AP_MODE) { 1088 session->parsedAssocReq = 1089 qdf_mem_malloc(session->dph.dphHashTable. 1090 size * sizeof(tpSirAssocReq)); 1091 if (!session->parsedAssocReq) { 1092 ret_code = eSIR_SME_RESOURCES_UNAVAILABLE; 1093 goto free; 1094 } 1095 } 1096 1097 if (!sme_start_bss_req->oper_ch_freq && 1098 bss_type != eSIR_NDI_MODE) { 1099 pe_err("Received invalid eWNI_SME_START_BSS_REQ"); 1100 ret_code = eSIR_SME_INVALID_PARAMETERS; 1101 goto free; 1102 } 1103 #ifdef QCA_HT_2040_COEX 1104 if (mac_ctx->roam.configParam.obssEnabled && 1105 !policy_mgr_is_vdev_ll_lt_sap(mac_ctx->psoc, vdev_id)) 1106 session->htSupportedChannelWidthSet = 1107 session->htCapability; 1108 else 1109 #endif 1110 session->htSupportedChannelWidthSet = 1111 (sme_start_bss_req->sec_ch_offset) ? 1 : 0; 1112 session->htSecondaryChannelOffset = 1113 sme_start_bss_req->sec_ch_offset; 1114 session->htRecommendedTxWidthSet = 1115 (session->htSecondaryChannelOffset) ? 1 : 0; 1116 if (lim_is_session_he_capable(session) || 1117 lim_is_session_eht_capable(session) || 1118 session->vhtCapability || session->htCapability) { 1119 chanwidth = sme_start_bss_req->vht_channel_width; 1120 session->ch_width = chanwidth; 1121 session->ch_center_freq_seg0 = 1122 sme_start_bss_req->center_freq_seg0; 1123 session->ch_center_freq_seg1 = 1124 sme_start_bss_req->center_freq_seg1; 1125 lim_update_he_bw_cap_mcs(session, NULL); 1126 lim_update_eht_bw_cap_mcs(session, NULL); 1127 } 1128 1129 /* Delete pre-auth list if any */ 1130 lim_delete_pre_auth_list(mac_ctx); 1131 1132 /* 1133 * keep the RSN/WPA IE information in PE Session Entry 1134 * later will be using this to check when received (Re)Assoc req 1135 */ 1136 lim_set_rs_nie_wp_aiefrom_sme_start_bss_req_message(mac_ctx, 1137 &sme_start_bss_req->rsnIE, session); 1138 1139 if (LIM_IS_AP_ROLE(session) || LIM_IS_NDI_ROLE(session)) { 1140 /* Initialize WPS PBC session link list */ 1141 session->pAPWPSPBCSession = NULL; 1142 } 1143 /* Prepare and Issue LIM_MLM_START_REQ to MLM */ 1144 mlm_start_req = qdf_mem_malloc(sizeof(tLimMlmStartReq)); 1145 if (!mlm_start_req) { 1146 ret_code = eSIR_SME_RESOURCES_UNAVAILABLE; 1147 goto free; 1148 } 1149 1150 /* Copy SSID to the MLM start structure */ 1151 qdf_mem_copy((uint8_t *) &mlm_start_req->ssId, 1152 (uint8_t *) &sme_start_bss_req->ssId, 1153 sme_start_bss_req->ssId.length + 1); 1154 mlm_start_req->ssidHidden = sme_start_bss_req->ssidHidden; 1155 1156 mlm_start_req->bssType = session->bssType; 1157 1158 /* Fill PE session Id from the session Table */ 1159 mlm_start_req->sessionId = session->peSessionId; 1160 1161 sir_copy_mac_addr(mlm_start_req->bssId, session->bssId); 1162 /* store the channel num in mlmstart req structure */ 1163 mlm_start_req->oper_ch_freq = session->curr_op_freq; 1164 mlm_start_req->beaconPeriod = 1165 session->beaconParams.beaconInterval; 1166 mlm_start_req->cac_duration_ms = 1167 sme_start_bss_req->cac_duration_ms; 1168 mlm_start_req->dfs_regdomain = 1169 sme_start_bss_req->dfs_regdomain; 1170 if (LIM_IS_AP_ROLE(session)) { 1171 mlm_start_req->dtimPeriod = session->dtimPeriod; 1172 mlm_start_req->wps_state = session->wps_state; 1173 session->cac_duration_ms = 1174 mlm_start_req->cac_duration_ms; 1175 session->dfs_regdomain = mlm_start_req->dfs_regdomain; 1176 mlm_start_req->cbMode = cb_mode; 1177 qdf_status = 1178 wlan_mlme_is_ap_obss_prot_enabled(mac_ctx->psoc, 1179 &cfg_value); 1180 if (QDF_IS_STATUS_ERROR(qdf_status)) 1181 pe_err("Unable to get obssProtEnabled"); 1182 mlm_start_req->obssProtEnabled = cfg_value; 1183 } else { 1184 val = mac_ctx->mlme_cfg->sap_cfg.dtim_interval; 1185 mlm_start_req->dtimPeriod = (uint8_t) val; 1186 } 1187 1188 mlm_start_req->cfParamSet.cfpPeriod = 1189 mac_ctx->mlme_cfg->rates.cfp_period; 1190 mlm_start_req->cfParamSet.cfpMaxDuration = 1191 mac_ctx->mlme_cfg->rates.cfp_max_duration; 1192 1193 /* 1194 * this may not be needed anymore now, 1195 * as rateSet is now included in the 1196 * session entry and MLM has session context. 1197 */ 1198 qdf_mem_copy((void *)&mlm_start_req->rateSet, 1199 (void *)&session->rateSet, 1200 sizeof(tSirMacRateSet)); 1201 1202 /* Now populate the 11n related parameters */ 1203 mlm_start_req->nwType = session->nwType; 1204 mlm_start_req->htCapable = session->htCapability; 1205 1206 mlm_start_req->htOperMode = mac_ctx->lim.gHTOperMode; 1207 /* Unused */ 1208 mlm_start_req->dualCTSProtection = 1209 mac_ctx->lim.gHTDualCTSProtection; 1210 mlm_start_req->txChannelWidthSet = 1211 session->htRecommendedTxWidthSet; 1212 1213 session->limRFBand = lim_get_rf_band( 1214 sme_start_bss_req->oper_ch_freq); 1215 1216 /* Initialize 11h Enable Flag */ 1217 session->lim11hEnable = 0; 1218 if (CHAN_HOP_ALL_BANDS_ENABLE || 1219 (session->limRFBand != REG_BAND_2G)) { 1220 session->lim11hEnable = 1221 mac_ctx->mlme_cfg->gen.enabled_11h; 1222 1223 if (session->lim11hEnable && 1224 (eSIR_INFRA_AP_MODE == 1225 mlm_start_req->bssType)) { 1226 session->lim11hEnable = 1227 mac_ctx->mlme_cfg-> 1228 dfs_cfg.dfs_master_capable; 1229 } 1230 } 1231 1232 if (!session->lim11hEnable) 1233 mac_ctx->mlme_cfg->power.local_power_constraint = 0; 1234 1235 mlm_start_req->beacon_tx_rate = session->beacon_tx_rate; 1236 lim_save_max_mcs_idx(mac_ctx, session); 1237 session->limPrevSmeState = session->limSmeState; 1238 session->limSmeState = eLIM_SME_WT_START_BSS_STATE; 1239 1240 lim_dump_session_info(mac_ctx, session); 1241 lim_dump_he_info(mac_ctx, session); 1242 lim_dump_eht_info(session); 1243 1244 MTRACE(mac_trace 1245 (mac_ctx, TRACE_CODE_SME_STATE, 1246 session->peSessionId, 1247 session->limSmeState)); 1248 1249 qdf_status = lim_send_start_vdev_req(session, mlm_start_req); 1250 if (QDF_IS_STATUS_ERROR(qdf_status)) 1251 goto free; 1252 qdf_mem_free(mlm_start_req); 1253 lim_update_rrm_capability(mac_ctx); 1254 1255 return; 1256 } else { 1257 1258 pe_err("Received unexpected START_BSS_REQ, in state %X", 1259 mac_ctx->lim.gLimSmeState); 1260 ret_code = eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED; 1261 goto free; 1262 } /* if (mac_ctx->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) */ 1263 1264 free: 1265 if ((session) && 1266 (session->pLimStartBssReq == sme_start_bss_req)) { 1267 session->pLimStartBssReq = NULL; 1268 } 1269 if (sme_start_bss_req) 1270 qdf_mem_free(sme_start_bss_req); 1271 if (mlm_start_req) 1272 qdf_mem_free(mlm_start_req); 1273 if (session) { 1274 pe_delete_session(mac_ctx, session); 1275 session = NULL; 1276 } 1277 lim_send_sme_start_bss_rsp(mac_ctx, ret_code, session, vdev_id); 1278 } 1279 1280 /** 1281 * __lim_process_sme_start_bss_req() - Call handler to start BSS 1282 * 1283 * @mac: Global MAC context 1284 * @pMsg: Message pointer 1285 * 1286 * Wrapper for the function __lim_handle_sme_start_bss_request 1287 * This message will be deferred until softmac come out of 1288 * scan mode or if we have detected radar on the current 1289 * operating channel. 1290 * 1291 * return true - If we consumed the buffer 1292 * false - If have deferred the message. 1293 */ 1294 static bool __lim_process_sme_start_bss_req(struct mac_context *mac, 1295 struct scheduler_msg *pMsg) 1296 { 1297 if (__lim_is_deferred_msg_for_radar(mac, pMsg)) { 1298 /** 1299 * If message deferred, buffer is not consumed yet. 1300 * So return false 1301 */ 1302 return false; 1303 } 1304 1305 __lim_handle_sme_start_bss_request(mac, (uint32_t *) pMsg->bodyptr); 1306 return true; 1307 } 1308 1309 /** 1310 * lim_get_random_bssid() 1311 * 1312 * FUNCTION:This function is called to process generate the random number for bssid 1313 * This function is called to process SME_SCAN_REQ message 1314 * from HDD or upper layer application. 1315 * 1316 * LOGIC: 1317 * 1318 * ASSUMPTIONS: 1319 * 1320 * NOTE: 1321 * 1. geneartes the unique random number for bssid in ibss 1322 * 1323 * @param mac Pointer to Global MAC structure 1324 * @param *data Pointer to bssid buffer 1325 * @return None 1326 */ 1327 void lim_get_random_bssid(struct mac_context *mac, uint8_t *data) 1328 { 1329 uint32_t random[2]; 1330 1331 random[0] = qdf_mc_timer_get_system_ticks(); 1332 random[0] |= (random[0] << 15); 1333 random[1] = random[0] >> 1; 1334 qdf_mem_copy(data, random, sizeof(tSirMacAddr)); 1335 } 1336 1337 /** 1338 * lim_send_join_req() - send vdev start request for assoc 1339 *@session: pe session 1340 *@mlm_join_req: join req 1341 * 1342 * Return: QDF_STATUS 1343 */ 1344 static QDF_STATUS lim_send_join_req(struct pe_session *session, 1345 tLimMlmJoinReq *mlm_join_req) 1346 { 1347 QDF_STATUS status; 1348 1349 /* Continue connect only if Vdev is in INIT state */ 1350 status = wlan_vdev_mlme_is_init_state(session->vdev); 1351 if (QDF_IS_STATUS_ERROR(status)) { 1352 pe_err("Vdev %d not in int state cur state %d substate %d", 1353 session->vdev_id, 1354 wlan_vdev_mlme_get_state(session->vdev), 1355 wlan_vdev_mlme_get_substate(session->vdev)); 1356 qdf_trigger_self_recovery(session->mac_ctx->psoc, 1357 QDF_VDEV_SM_OUT_OF_SYNC); 1358 return status; 1359 } 1360 status = mlme_set_assoc_type(session->vdev, VDEV_ASSOC); 1361 if (QDF_IS_STATUS_ERROR(status)) 1362 return status; 1363 1364 return wlan_vdev_mlme_sm_deliver_evt(session->vdev, 1365 WLAN_VDEV_SM_EV_START, 1366 sizeof(*mlm_join_req), 1367 mlm_join_req); 1368 } 1369 1370 #ifdef WLAN_FEATURE_HOST_ROAM 1371 /** 1372 * lim_send_reassoc_req() - send vdev start request for reassoc 1373 *@session: pe session 1374 *@mlm_join_req: join req 1375 * 1376 * Return: QDF_STATUS 1377 */ 1378 static QDF_STATUS lim_send_reassoc_req(struct pe_session *session, 1379 tLimMlmReassocReq *reassoc_req) 1380 { 1381 QDF_STATUS status; 1382 1383 status = mlme_set_assoc_type(session->vdev, VDEV_REASSOC); 1384 if (QDF_IS_STATUS_ERROR(status)) 1385 return status; 1386 1387 if (wlan_vdev_mlme_get_state(session->vdev) != WLAN_VDEV_S_UP) { 1388 pe_err("Reassoc req in unexpected vdev SM state:%d", 1389 wlan_vdev_mlme_get_state(session->vdev)); 1390 return QDF_STATUS_E_FAILURE; 1391 } 1392 1393 lim_process_mlm_reassoc_req(session->mac_ctx, reassoc_req); 1394 return QDF_STATUS_SUCCESS; 1395 } 1396 1397 /** 1398 * lim_send_ft_reassoc_req() - send vdev start request for ft_reassoc 1399 *@session: pe session 1400 *@mlm_join_req: join req 1401 * 1402 * Return: QDF_STATUS 1403 */ 1404 static QDF_STATUS lim_send_ft_reassoc_req(struct pe_session *session, 1405 tLimMlmReassocReq *reassoc_req) 1406 { 1407 QDF_STATUS status; 1408 1409 status = mlme_set_assoc_type(session->vdev, VDEV_FT_REASSOC); 1410 if (QDF_IS_STATUS_ERROR(status)) 1411 return status; 1412 1413 if (wlan_vdev_mlme_get_state(session->vdev) == WLAN_VDEV_S_UP) { 1414 pe_err("ft_reassoc req in unexpected vdev SM state:%d", 1415 wlan_vdev_mlme_get_state(session->vdev)); 1416 return QDF_STATUS_E_FAILURE; 1417 } 1418 1419 return wlan_vdev_mlme_sm_deliver_evt(session->vdev, 1420 WLAN_VDEV_SM_EV_START, 1421 sizeof(*reassoc_req), 1422 reassoc_req); 1423 } 1424 #endif 1425 1426 static void lim_join_req_update_ht_vht_caps(struct mac_context *mac, 1427 struct pe_session *session, 1428 struct bss_description *bss_desc, 1429 tDot11fBeaconIEs *bcn_ie) 1430 { 1431 struct vdev_mlme_obj *vdev_mlme; 1432 struct wlan_vht_config vht_config; 1433 uint8_t value, value1; 1434 tDot11fIEVHTCaps *vht_caps = NULL; 1435 uint8_t tx_bf_csn = 0; 1436 struct wlan_ht_config ht_caps; 1437 1438 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(session->vdev); 1439 if (!vdev_mlme) 1440 return; 1441 1442 lim_set_ldpc_exception(mac, vdev_mlme, session->curr_op_freq); 1443 vht_config.caps = vdev_mlme->proto.vht_info.caps; 1444 1445 value = mac->mlme_cfg->vht_caps.vht_cap_info.su_bformee; 1446 value1 = mac->mlme_cfg->vht_caps.vht_cap_info.tx_bfee_ant_supp; 1447 1448 vht_config.su_beam_formee = value; 1449 1450 if (bcn_ie->VHTCaps.present) 1451 vht_caps = &bcn_ie->VHTCaps; 1452 else if (bcn_ie->vendor_vht_ie.VHTCaps.present) 1453 vht_caps = &bcn_ie->vendor_vht_ie.VHTCaps; 1454 /* Set BF CSN value only if SU Bformee is enabled */ 1455 if (vht_caps && vht_config.su_beam_formee) { 1456 tx_bf_csn = value1; 1457 /* 1458 * Certain commercial AP display a bad behavior when 1459 * CSN value in assoc request is more than AP's CSN. 1460 * Sending absolute self CSN value with such AP leads to 1461 * IOT issues. However this issue is observed only with 1462 * CSN cap of less than 4. To avoid such issues, take a 1463 * min of self and peer CSN while sending ASSOC request. 1464 */ 1465 if (bcn_ie->Vendor1IE.present && 1466 vht_caps->csnofBeamformerAntSup < 4) { 1467 if (vht_caps->csnofBeamformerAntSup) 1468 tx_bf_csn = QDF_MIN(tx_bf_csn, 1469 vht_caps->csnofBeamformerAntSup); 1470 } 1471 } 1472 vht_config.csnof_beamformer_antSup = tx_bf_csn; 1473 1474 value = mac->mlme_cfg->vht_caps.vht_cap_info.su_bformer; 1475 /* 1476 * Set SU Bformer only if SU Bformer is enabled in INI 1477 * and AP is SU Bformee capable 1478 */ 1479 if (value && !((IS_BSS_VHT_CAPABLE(bcn_ie->VHTCaps) && 1480 bcn_ie->VHTCaps.suBeamformeeCap) || 1481 (IS_BSS_VHT_CAPABLE(bcn_ie->vendor_vht_ie.VHTCaps) && 1482 bcn_ie->vendor_vht_ie.VHTCaps.suBeamformeeCap))) 1483 value = 0; 1484 1485 vht_config.su_beam_former = value; 1486 1487 /* Set num soundingdim value to 0 if SU Bformer is disabled */ 1488 if (!vht_config.su_beam_former) 1489 vht_config.num_soundingdim = 0; 1490 1491 value = mac->mlme_cfg->vht_caps.vht_cap_info.enable_mu_bformee; 1492 /* 1493 * Set MU Bformee only if SU Bformee is enabled and 1494 * MU Bformee is enabled in INI 1495 */ 1496 if (value && vht_config.su_beam_formee && 1497 bcn_ie->VHTCaps.muBeamformerCap) 1498 vht_config.mu_beam_formee = 1; 1499 else 1500 vht_config.mu_beam_formee = 0; 1501 1502 if (IS_DOT11_MODE_VHT(session->dot11mode) && 1503 session->opmode != QDF_STA_MODE) 1504 vht_config.su_beam_formee = 0; 1505 1506 session->vht_config = vht_config; 1507 ht_caps.caps = vdev_mlme->proto.ht_info.ht_caps; 1508 session->ht_config = ht_caps.ht_caps; 1509 1510 if (session->opmode == QDF_STA_MODE) { 1511 if (session->ht_config.short_gi_20_mhz) 1512 session->ht_config.short_gi_20_mhz = 1513 bcn_ie->HTCaps.shortGI20MHz; 1514 1515 if (session->ht_config.short_gi_40_mhz) 1516 session->ht_config.short_gi_40_mhz = 1517 bcn_ie->HTCaps.shortGI40MHz; 1518 } 1519 1520 lim_revise_req_vht_cap_per_band(session); 1521 pe_debug("HT cap 0x%x VHT cap 0x%x, AP cap sgi_20 %d sgi_40 %d", 1522 ht_caps.caps, vht_config.caps, 1523 bcn_ie->HTCaps.shortGI20MHz, bcn_ie->HTCaps.shortGI40MHz); 1524 } 1525 1526 bool 1527 lim_get_vdev_rmf_capable(struct mac_context *mac, struct pe_session *session) 1528 { 1529 struct wlan_objmgr_vdev *vdev; 1530 int32_t rsn_caps; 1531 bool peer_rmf_capable = false; 1532 1533 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc, 1534 session->vdev_id, 1535 WLAN_LEGACY_SME_ID); 1536 if (!vdev) { 1537 pe_err("Invalid vdev"); 1538 return false; 1539 } 1540 rsn_caps = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_RSN_CAP); 1541 if (rsn_caps < 0) { 1542 pe_err("Invalid mgmt cipher"); 1543 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID); 1544 return false; 1545 } 1546 if (wlan_crypto_vdev_has_mgmtcipher( 1547 vdev, 1548 (1 << WLAN_CRYPTO_CIPHER_AES_GMAC) | 1549 (1 << WLAN_CRYPTO_CIPHER_AES_GMAC_256) | 1550 (1 << WLAN_CRYPTO_CIPHER_AES_CMAC)) && 1551 (rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED)) 1552 peer_rmf_capable = true; 1553 1554 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID); 1555 1556 return peer_rmf_capable; 1557 } 1558 1559 /** 1560 * lim_get_nss_supported_by_sta_and_ap() - finds out nss from session 1561 * and beacon from AP 1562 * @vht_caps: VHT capabilities 1563 * @ht_caps: HT capabilities 1564 * @dot11_mode: dot11 mode 1565 * 1566 * Return: number of nss advertised by beacon 1567 */ 1568 static uint8_t 1569 lim_get_nss_supported_by_sta_and_ap(tDot11fIEVHTCaps *vht_caps, 1570 tDot11fIEHTCaps *ht_caps, 1571 tDot11fIEhe_cap *he_cap, 1572 enum mlme_dot11_mode dot11_mode) 1573 { 1574 bool vht_capability, ht_capability, he_capability; 1575 1576 vht_capability = IS_DOT11_MODE_VHT(dot11_mode); 1577 ht_capability = IS_DOT11_MODE_HT(dot11_mode); 1578 he_capability = IS_DOT11_MODE_HE(dot11_mode); 1579 1580 if (he_capability && he_cap->present) { 1581 if ((he_cap->rx_he_mcs_map_lt_80 & 0xC0) != 0xC0) 1582 return NSS_4x4_MODE; 1583 1584 if ((he_cap->rx_he_mcs_map_lt_80 & 0x30) != 0x30) 1585 return NSS_3x3_MODE; 1586 1587 if ((he_cap->rx_he_mcs_map_lt_80 & 0x0C) != 0x0C) 1588 return NSS_2x2_MODE; 1589 } else if (vht_capability && vht_caps->present) { 1590 if ((vht_caps->rxMCSMap & 0xC0) != 0xC0) 1591 return NSS_4x4_MODE; 1592 1593 if ((vht_caps->rxMCSMap & 0x30) != 0x30) 1594 return NSS_3x3_MODE; 1595 1596 if ((vht_caps->rxMCSMap & 0x0C) != 0x0C) 1597 return NSS_2x2_MODE; 1598 } else if (ht_capability && ht_caps->present) { 1599 if (ht_caps->supportedMCSSet[3]) 1600 return NSS_4x4_MODE; 1601 1602 if (ht_caps->supportedMCSSet[2]) 1603 return NSS_3x3_MODE; 1604 1605 if (ht_caps->supportedMCSSet[1]) 1606 return NSS_2x2_MODE; 1607 } 1608 1609 return NSS_1x1_MODE; 1610 } 1611 1612 /** 1613 * lim_check_vendor_ap_3_present() - Check if Vendor AP 3 is present 1614 * @mac_ctx: Pointer to Global MAC structure 1615 * @ie: Pointer to starting IE in Beacon/Probe Response 1616 * @ie_len: Length of all IEs combined 1617 * 1618 * For Vendor AP 3, the condition is that Vendor AP 3 IE should be present 1619 * and Vendor AP 4 IE should not be present. 1620 * If Vendor AP 3 IE is present and Vendor AP 4 IE is also present, 1621 * return false, else return true. 1622 * 1623 * Return: true or false 1624 */ 1625 static bool 1626 lim_check_vendor_ap_3_present(struct mac_context *mac_ctx, uint8_t *ie, 1627 uint16_t ie_len) 1628 { 1629 bool ret = true; 1630 1631 if ((wlan_get_vendor_ie_ptr_from_oui(SIR_MAC_VENDOR_AP_3_OUI, 1632 SIR_MAC_VENDOR_AP_3_OUI_LEN, ie, ie_len)) && 1633 (wlan_get_vendor_ie_ptr_from_oui(SIR_MAC_VENDOR_AP_4_OUI, 1634 SIR_MAC_VENDOR_AP_4_OUI_LEN, ie, ie_len))) { 1635 pe_debug("Vendor OUI 3 and Vendor OUI 4 found"); 1636 ret = false; 1637 } 1638 1639 return ret; 1640 } 1641 1642 #ifdef WLAN_FEATURE_11AX 1643 static void 1644 lim_handle_iot_ap_no_common_he_rates(struct mac_context *mac, 1645 struct pe_session *session, 1646 tDot11fBeaconIEs *ies) 1647 { 1648 uint16_t int_mcs; 1649 struct wlan_objmgr_vdev *vdev = session->vdev; 1650 struct mlme_legacy_priv *mlme_priv; 1651 1652 /* if the connection is not 11AX mode then return */ 1653 if (session->dot11mode != MLME_DOT11_MODE_11AX) 1654 return; 1655 1656 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 1657 if (!mlme_priv) 1658 return; 1659 1660 int_mcs = HE_INTERSECT_MCS(mlme_priv->he_config.tx_he_mcs_map_lt_80, 1661 ies->he_cap.rx_he_mcs_map_lt_80); 1662 pe_debug("HE self rates %x AP rates %x int_mcs %x vendorIE %d", 1663 mlme_priv->he_config.rx_he_mcs_map_lt_80, 1664 ies->he_cap.rx_he_mcs_map_lt_80, int_mcs, 1665 ies->vendor_vht_ie.present); 1666 if (ies->he_cap.present) 1667 if ((int_mcs == 0xFFFF) && 1668 (ies->vendor_vht_ie.present || 1669 ies->VHTCaps.present)) { 1670 session->dot11mode = MLME_DOT11_MODE_11AC; 1671 sme_debug("No common 11AX rate. Force 11AC connection"); 1672 } 1673 } 1674 #else 1675 static void lim_handle_iot_ap_no_common_he_rates(struct mac_context *mac, 1676 struct pe_session *session, 1677 tDot11fBeaconIEs *ies) 1678 { 1679 } 1680 #endif 1681 1682 #ifdef WLAN_FEATURE_11AX 1683 1684 /** 1685 * lim_update_he_caps_htc() - Update htc in he caps 1686 * @session: Pointer to PE session 1687 * @val: htc he enabled status 1688 * 1689 * Return: void 1690 */ 1691 static void 1692 lim_update_he_caps_htc(struct pe_session *session, bool val) 1693 { 1694 struct wlan_objmgr_vdev *vdev = session->vdev; 1695 struct mlme_legacy_priv *mlme_priv; 1696 1697 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 1698 if (!mlme_priv) 1699 return; 1700 1701 pe_debug("new htc he: %d", val); 1702 mlme_priv->he_config.htc_he = val; 1703 } 1704 #else 1705 1706 static void 1707 lim_update_he_caps_htc(struct pe_session *session, bool val) 1708 { 1709 } 1710 #endif 1711 1712 #ifdef WLAN_FEATURE_11BE 1713 void 1714 lim_update_eht_caps_mcs(struct mac_context *mac, struct pe_session *session) 1715 { 1716 uint8_t tx_nss = 0; 1717 uint8_t rx_nss = 0; 1718 struct wlan_objmgr_vdev *vdev = session->vdev; 1719 struct mlme_legacy_priv *mlme_priv; 1720 struct wlan_mlme_cfg *mlme_cfg = mac->mlme_cfg; 1721 tDot11fIEeht_cap *dot11_eht_cap; 1722 tDot11fIEeht_cap *eht_config; 1723 1724 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 1725 if (!mlme_priv) 1726 return; 1727 1728 eht_config = &mlme_priv->eht_config; 1729 dot11_eht_cap = &mlme_cfg->eht_caps.dot11_eht_cap; 1730 1731 if (session->nss == 1) { 1732 tx_nss = 1; 1733 rx_nss = 1; 1734 } else { 1735 tx_nss = dot11_eht_cap->bw_20_tx_max_nss_for_mcs_0_to_7; 1736 rx_nss = dot11_eht_cap->bw_20_rx_max_nss_for_mcs_0_to_7; 1737 } 1738 1739 if (!tx_nss || tx_nss > 2 || !rx_nss || rx_nss > 2) { 1740 pe_err("invalid Nss values tx_nss: %u rx_nss: %u", 1741 tx_nss, rx_nss); 1742 return; 1743 } 1744 1745 eht_config->bw_20_rx_max_nss_for_mcs_0_to_7 = rx_nss; 1746 eht_config->bw_20_tx_max_nss_for_mcs_0_to_7 = tx_nss; 1747 eht_config->bw_20_rx_max_nss_for_mcs_8_and_9 = rx_nss; 1748 eht_config->bw_20_tx_max_nss_for_mcs_8_and_9 = tx_nss; 1749 if (dot11_eht_cap->bw_20_rx_max_nss_for_mcs_10_and_11) { 1750 eht_config->bw_20_rx_max_nss_for_mcs_10_and_11 = rx_nss; 1751 eht_config->bw_20_tx_max_nss_for_mcs_10_and_11 = tx_nss; 1752 } 1753 if (dot11_eht_cap->bw_20_rx_max_nss_for_mcs_12_and_13) { 1754 eht_config->bw_20_rx_max_nss_for_mcs_12_and_13 = rx_nss; 1755 eht_config->bw_20_tx_max_nss_for_mcs_12_and_13 = tx_nss; 1756 } 1757 eht_config->bw_le_80_rx_max_nss_for_mcs_0_to_9 = rx_nss; 1758 eht_config->bw_le_80_tx_max_nss_for_mcs_0_to_9 = tx_nss; 1759 if (dot11_eht_cap->bw_le_80_rx_max_nss_for_mcs_10_and_11) { 1760 eht_config->bw_le_80_rx_max_nss_for_mcs_10_and_11 = rx_nss; 1761 eht_config->bw_le_80_tx_max_nss_for_mcs_10_and_11 = tx_nss; 1762 } 1763 if (dot11_eht_cap->bw_le_80_rx_max_nss_for_mcs_12_and_13) { 1764 eht_config->bw_le_80_rx_max_nss_for_mcs_12_and_13 = rx_nss; 1765 eht_config->bw_le_80_tx_max_nss_for_mcs_12_and_13 = tx_nss; 1766 } 1767 eht_config->bw_160_rx_max_nss_for_mcs_0_to_9 = rx_nss; 1768 eht_config->bw_160_tx_max_nss_for_mcs_0_to_9 = tx_nss; 1769 if (dot11_eht_cap->bw_160_rx_max_nss_for_mcs_10_and_11) { 1770 eht_config->bw_160_rx_max_nss_for_mcs_10_and_11 = rx_nss; 1771 eht_config->bw_160_tx_max_nss_for_mcs_10_and_11 = tx_nss; 1772 } 1773 if (dot11_eht_cap->bw_160_rx_max_nss_for_mcs_12_and_13) { 1774 eht_config->bw_160_rx_max_nss_for_mcs_12_and_13 = rx_nss; 1775 eht_config->bw_160_tx_max_nss_for_mcs_12_and_13 = tx_nss; 1776 } 1777 eht_config->bw_320_rx_max_nss_for_mcs_0_to_9 = rx_nss; 1778 eht_config->bw_320_tx_max_nss_for_mcs_0_to_9 = tx_nss; 1779 1780 if (dot11_eht_cap->bw_320_rx_max_nss_for_mcs_10_and_11) { 1781 eht_config->bw_320_rx_max_nss_for_mcs_10_and_11 = rx_nss; 1782 eht_config->bw_320_tx_max_nss_for_mcs_10_and_11 = tx_nss; 1783 } 1784 if (dot11_eht_cap->bw_320_rx_max_nss_for_mcs_12_and_13) { 1785 eht_config->bw_320_rx_max_nss_for_mcs_12_and_13 = rx_nss; 1786 eht_config->bw_320_tx_max_nss_for_mcs_12_and_13 = tx_nss; 1787 } 1788 } 1789 #endif 1790 1791 static void lim_check_oui_and_update_session(struct mac_context *mac_ctx, 1792 struct pe_session *session, 1793 tDot11fBeaconIEs *ie_struct) 1794 { 1795 struct action_oui_search_attr vendor_ap_search_attr; 1796 uint16_t ie_len; 1797 bool follow_ap_edca; 1798 struct bss_description *bss_desc = 1799 &session->lim_join_req->bssDescription; 1800 bool is_vendor_ap_present; 1801 uint8_t ap_nss; 1802 struct vdev_type_nss *vdev_type_nss; 1803 1804 if (wlan_reg_is_5ghz_ch_freq(bss_desc->chan_freq)) 1805 vdev_type_nss = &mac_ctx->vdev_type_nss_5g; 1806 else 1807 vdev_type_nss = &mac_ctx->vdev_type_nss_2g; 1808 1809 if (wlan_vdev_mlme_get_opmode(session->vdev) == QDF_P2P_CLIENT_MODE) 1810 session->vdev_nss = vdev_type_nss->p2p_cli; 1811 else 1812 session->vdev_nss = vdev_type_nss->sta; 1813 session->nss = session->vdev_nss; 1814 1815 ie_len = wlan_get_ielen_from_bss_description(bss_desc); 1816 1817 /* Fill the Vendor AP search params */ 1818 vendor_ap_search_attr.ie_data = 1819 (uint8_t *)&bss_desc->ieFields[0]; 1820 vendor_ap_search_attr.ie_length = ie_len; 1821 vendor_ap_search_attr.mac_addr = &bss_desc->bssId[0]; 1822 ap_nss = lim_get_nss_supported_by_sta_and_ap( 1823 &ie_struct->VHTCaps, &ie_struct->HTCaps, 1824 &ie_struct->he_cap, session->dot11mode); 1825 vendor_ap_search_attr.nss = ap_nss; 1826 vendor_ap_search_attr.ht_cap = ie_struct->HTCaps.present; 1827 vendor_ap_search_attr.vht_cap = ie_struct->VHTCaps.present; 1828 vendor_ap_search_attr.enable_2g = 1829 wlan_reg_is_24ghz_ch_freq(bss_desc->chan_freq); 1830 vendor_ap_search_attr.enable_5g = 1831 wlan_reg_is_5ghz_ch_freq(bss_desc->chan_freq); 1832 1833 if (!mac_ctx->mlme_cfg->vht_caps.vht_cap_info.enable2x2) { 1834 session->nss = 1; 1835 session->vdev_nss = 1; 1836 } 1837 1838 /* 1839 * If CCK WAR is set for current AP, update to firmware via 1840 * wmi_vdev_param_abg_mode_tx_chain_num 1841 */ 1842 is_vendor_ap_present = 1843 wlan_action_oui_search(mac_ctx->psoc, 1844 &vendor_ap_search_attr, 1845 ACTION_OUI_CCKM_1X1); 1846 if (is_vendor_ap_present) { 1847 pe_debug("vdev: %d wmi_vdev_param_abg_mode_tx_chain_num 1", 1848 session->vdev_id); 1849 wma_cli_set_command(session->vdev_id, 1850 (int)wmi_vdev_param_abg_mode_tx_chain_num, 1, 1851 VDEV_CMD); 1852 } 1853 1854 /* 1855 * If Switch to 11N WAR is set for current AP, change dot11 1856 * mode to 11N. 1857 */ 1858 is_vendor_ap_present = 1859 wlan_action_oui_search(mac_ctx->psoc, 1860 &vendor_ap_search_attr, 1861 ACTION_OUI_SWITCH_TO_11N_MODE); 1862 if (mac_ctx->roam.configParam.is_force_1x1 && 1863 mac_ctx->mlme_cfg->gen.as_enabled && 1864 is_vendor_ap_present && 1865 (session->dot11mode == MLME_DOT11_MODE_ALL || 1866 session->dot11mode == MLME_DOT11_MODE_11AC || 1867 session->dot11mode == MLME_DOT11_MODE_11AC_ONLY)) 1868 session->dot11mode = MLME_DOT11_MODE_11N; 1869 1870 follow_ap_edca = wlan_action_oui_search(mac_ctx->psoc, 1871 &vendor_ap_search_attr, 1872 ACTION_OUI_DISABLE_AGGRESSIVE_EDCA); 1873 mlme_set_follow_ap_edca_flag(session->vdev, follow_ap_edca); 1874 1875 if (wlan_action_oui_search(mac_ctx->psoc, &vendor_ap_search_attr, 1876 ACTION_OUI_HOST_RECONN)) { 1877 mlme_set_reconn_after_assoc_timeout_flag( 1878 mac_ctx->psoc, session->vdev_id, 1879 true); 1880 } 1881 is_vendor_ap_present = 1882 wlan_action_oui_search(mac_ctx->psoc, 1883 &vendor_ap_search_attr, 1884 ACTION_OUI_CONNECT_1X1); 1885 1886 if (is_vendor_ap_present) { 1887 is_vendor_ap_present = lim_check_vendor_ap_3_present( 1888 mac_ctx, 1889 vendor_ap_search_attr.ie_data, 1890 ie_len); 1891 } 1892 1893 /* 1894 * For WMI_ACTION_OUI_CONNECT_1x1_WITH_1_CHAIN, the host 1895 * sends the NSS as 1 to the FW and the FW then decides 1896 * after receiving the first beacon after connection to 1897 * switch to 1 Tx/Rx Chain. 1898 */ 1899 1900 if (!is_vendor_ap_present) { 1901 is_vendor_ap_present = 1902 wlan_action_oui_search(mac_ctx->psoc, 1903 &vendor_ap_search_attr, 1904 ACTION_OUI_CONNECT_1X1_WITH_1_CHAIN); 1905 if (is_vendor_ap_present) 1906 pe_debug("1x1 with 1 Chain AP"); 1907 } 1908 1909 if (is_vendor_ap_present && 1910 !policy_mgr_is_hw_dbs_2x2_capable(mac_ctx->psoc) && 1911 ((mac_ctx->roam.configParam.is_force_1x1 == 1912 FORCE_1X1_ENABLED_FOR_AS && 1913 mac_ctx->mlme_cfg->gen.as_enabled) || 1914 mac_ctx->roam.configParam.is_force_1x1 == 1915 FORCE_1X1_ENABLED_FORCED)) { 1916 session->vdev_nss = 1; 1917 session->nss = 1; 1918 session->nss_forced_1x1 = true; 1919 pe_debug("For special ap, NSS: %d force 1x1 %d", 1920 session->nss, 1921 mac_ctx->roam.configParam.is_force_1x1); 1922 } 1923 1924 if (WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq) && 1925 wlan_action_oui_search(mac_ctx->psoc, 1926 &vendor_ap_search_attr, 1927 ACTION_OUI_AUTH_ASSOC_6MBPS_2GHZ)) { 1928 session->is_oui_auth_assoc_6mbps_2ghz_enable = true; 1929 } 1930 1931 if (WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq) && 1932 !mac_ctx->mlme_cfg->vht_caps.vht_cap_info.b24ghz_band && 1933 session->dot11mode == MLME_DOT11_MODE_11AC) { 1934 /* Need to disable VHT operation in 2.4 GHz band */ 1935 session->dot11mode = MLME_DOT11_MODE_11N; 1936 } 1937 1938 lim_handle_iot_ap_no_common_he_rates(mac_ctx, session, ie_struct); 1939 lim_update_he_caps_mcs(mac_ctx, session); 1940 lim_update_eht_caps_mcs(mac_ctx, session); 1941 1942 is_vendor_ap_present = wlan_get_vendor_ie_ptr_from_oui( 1943 SIR_MAC_BA_2K_JUMP_AP_VENDOR_OUI, 1944 SIR_MAC_BA_2K_JUMP_AP_VENDOR_OUI_LEN, 1945 vendor_ap_search_attr.ie_data, ie_len); 1946 wlan_mlme_set_ba_2k_jump_iot_ap(session->vdev, is_vendor_ap_present); 1947 1948 is_vendor_ap_present = wlan_get_vendor_ie_ptr_from_oui 1949 (SIR_MAC_BAD_HTC_HE_VENDOR_OUI1, 1950 SIR_MAC_BAD_HTC_HE_VENDOR_OUI_LEN, 1951 vendor_ap_search_attr.ie_data, ie_len) && 1952 wlan_get_vendor_ie_ptr_from_oui 1953 (SIR_MAC_BAD_HTC_HE_VENDOR_OUI2, 1954 SIR_MAC_BAD_HTC_HE_VENDOR_OUI_LEN, 1955 vendor_ap_search_attr.ie_data, ie_len); 1956 1957 /* 1958 * For SAP with special OUI, if DUT STA connect with 11ax mode with ht 1959 * control enabled, SAP can't decode unicast pkt from DUT. 1960 * Fix it by clearing ht control bit in he cap when send peer assoc cmd 1961 * to firmware when connect such IOT AP with 11ax mode. 1962 * New requirement is to change default setting for HT control to false. 1963 */ 1964 if (is_vendor_ap_present) 1965 lim_update_he_caps_htc(session, !is_vendor_ap_present); 1966 } 1967 1968 static enum mlme_dot11_mode 1969 lim_get_user_dot11_mode(struct wlan_objmgr_vdev *vdev) 1970 { 1971 WMI_HOST_WIFI_STANDARD wifi_std; 1972 1973 wifi_std = mlme_get_vdev_wifi_std(vdev); 1974 1975 switch (wifi_std) { 1976 case WMI_HOST_WIFI_STANDARD_4: 1977 return MLME_DOT11_MODE_11N; 1978 case WMI_HOST_WIFI_STANDARD_5: 1979 return MLME_DOT11_MODE_11AC; 1980 case WMI_HOST_WIFI_STANDARD_6: 1981 case WMI_HOST_WIFI_STANDARD_6E: 1982 return MLME_DOT11_MODE_11AX; 1983 case WMI_HOST_WIFI_STANDARD_7: 1984 default: 1985 return MLME_DOT11_MODE_11BE; 1986 } 1987 } 1988 1989 static enum mlme_dot11_mode 1990 lim_intersect_user_dot11_mode(struct mac_context *mac_ctx, 1991 enum QDF_OPMODE opmode, uint8_t vdev_id, 1992 enum mlme_dot11_mode self_mode) 1993 { 1994 struct wlan_objmgr_vdev *vdev; 1995 enum mlme_dot11_mode user_mode; 1996 1997 switch (opmode) { 1998 case QDF_STA_MODE: 1999 case QDF_P2P_CLIENT_MODE: 2000 break; 2001 default: 2002 return self_mode; 2003 } 2004 2005 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(mac_ctx->pdev, vdev_id, 2006 WLAN_MLME_OBJMGR_ID); 2007 if (!vdev) 2008 return self_mode; 2009 2010 user_mode = lim_get_user_dot11_mode(vdev); 2011 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 2012 2013 return user_mode > self_mode ? self_mode : user_mode; 2014 } 2015 2016 static enum mlme_dot11_mode 2017 lim_get_self_dot11_mode(struct mac_context *mac_ctx, enum QDF_OPMODE opmode, 2018 uint8_t vdev_id) 2019 { 2020 struct wlan_objmgr_vdev *vdev; 2021 struct vdev_mlme_obj *vdev_mlme; 2022 enum mlme_vdev_dot11_mode vdev_dot11_mode; 2023 enum mlme_dot11_mode self_dot11_mode = 2024 mac_ctx->mlme_cfg->dot11_mode.dot11_mode; 2025 2026 switch (opmode) { 2027 case QDF_STA_MODE: 2028 case QDF_P2P_CLIENT_MODE: 2029 break; 2030 default: 2031 return self_dot11_mode; 2032 } 2033 2034 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(mac_ctx->pdev, vdev_id, 2035 WLAN_MLME_OBJMGR_ID); 2036 if (!vdev) 2037 return self_dot11_mode; 2038 2039 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 2040 if (!vdev_mlme) { 2041 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 2042 return self_dot11_mode; 2043 } 2044 2045 vdev_dot11_mode = vdev_mlme->proto.vdev_dot11_mode; 2046 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 2047 2048 if (vdev_dot11_mode == MLME_VDEV_DOT11_MODE_AUTO) 2049 return self_dot11_mode; 2050 2051 if (IS_DOT11_MODE_HT(self_dot11_mode) && 2052 vdev_dot11_mode == MLME_VDEV_DOT11_MODE_11N) 2053 return MLME_DOT11_MODE_11N; 2054 2055 if (IS_DOT11_MODE_VHT(self_dot11_mode) && 2056 vdev_dot11_mode == MLME_VDEV_DOT11_MODE_11AC) 2057 return MLME_DOT11_MODE_11AC; 2058 2059 if (IS_DOT11_MODE_HE(self_dot11_mode) && 2060 vdev_dot11_mode == MLME_VDEV_DOT11_MODE_11AX) 2061 return MLME_DOT11_MODE_11AX; 2062 2063 if (IS_DOT11_MODE_EHT(self_dot11_mode) && 2064 vdev_dot11_mode == MLME_VDEV_DOT11_MODE_11BE) 2065 return MLME_DOT11_MODE_11BE; 2066 2067 return self_dot11_mode; 2068 } 2069 2070 static bool 2071 lim_get_bss_11be_mode_allowed(struct mac_context *mac_ctx, 2072 struct bss_description *bss_desc, 2073 tDot11fBeaconIEs *ie_struct) 2074 { 2075 struct scan_cache_entry *scan_entry; 2076 bool is_eht_allowed; 2077 2078 if (!ie_struct->eht_cap.present) 2079 return false; 2080 2081 scan_entry = wlan_scan_get_entry_by_bssid(mac_ctx->pdev, 2082 (struct qdf_mac_addr *) 2083 bss_desc->bssId); 2084 2085 /* 2086 * If AP advertises multiple AKMs(WPA2 PSK + WPA3), allow connection 2087 * in 11BE mode as our connection is going to be WPA3 2088 */ 2089 if (scan_entry) { 2090 is_eht_allowed = 2091 wlan_cm_is_eht_allowed_for_current_security( 2092 wlan_pdev_get_psoc(mac_ctx->pdev), 2093 scan_entry); 2094 util_scan_free_cache_entry(scan_entry); 2095 if (!is_eht_allowed) { 2096 pe_debug("Downgrade to 11ax mode due to AP security validation failure"); 2097 return false; 2098 } 2099 } 2100 return mlme_get_bss_11be_allowed( 2101 mac_ctx->psoc, 2102 (struct qdf_mac_addr *)&bss_desc->bssId, 2103 (uint8_t *)&bss_desc->ieFields[0], 2104 wlan_get_ielen_from_bss_description(bss_desc)); 2105 } 2106 2107 static enum mlme_dot11_mode 2108 lim_get_bss_dot11_mode(struct mac_context *mac_ctx, 2109 struct bss_description *bss_desc, 2110 tDot11fBeaconIEs *ie_struct) 2111 { 2112 enum mlme_dot11_mode bss_dot11_mode; 2113 2114 switch (bss_desc->nwType) { 2115 case eSIR_11B_NW_TYPE: 2116 return MLME_DOT11_MODE_11B; 2117 case eSIR_11A_NW_TYPE: 2118 bss_dot11_mode = MLME_DOT11_MODE_11A; 2119 break; 2120 case eSIR_11G_NW_TYPE: 2121 bss_dot11_mode = MLME_DOT11_MODE_11G; 2122 break; 2123 default: 2124 if (WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq)) 2125 bss_dot11_mode = MLME_DOT11_MODE_11G; 2126 else 2127 bss_dot11_mode = MLME_DOT11_MODE_11A; 2128 } 2129 2130 if (ie_struct->HTCaps.present) 2131 bss_dot11_mode = MLME_DOT11_MODE_11N; 2132 2133 if (IS_BSS_VHT_CAPABLE(ie_struct->VHTCaps) || 2134 IS_BSS_VHT_CAPABLE(ie_struct->vendor_vht_ie.VHTCaps)) 2135 bss_dot11_mode = MLME_DOT11_MODE_11AC; 2136 2137 if (ie_struct->he_cap.present) 2138 bss_dot11_mode = MLME_DOT11_MODE_11AX; 2139 2140 if (ie_struct->eht_cap.present && 2141 lim_get_bss_11be_mode_allowed(mac_ctx, bss_desc, ie_struct)) 2142 bss_dot11_mode = MLME_DOT11_MODE_11BE; 2143 2144 return bss_dot11_mode; 2145 } 2146 2147 static QDF_STATUS 2148 lim_handle_11abg_dot11_mode(enum mlme_dot11_mode bss_dot11_mode, 2149 enum mlme_dot11_mode *intersected_mode, 2150 struct bss_description *bss_desc) 2151 { 2152 if (!WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq) && 2153 !WLAN_REG_IS_5GHZ_CH_FREQ(bss_desc->chan_freq)) { 2154 pe_err("self Dot11mode is 11ABG, BSS freq %d not 2.4 or 5 GHz", 2155 bss_desc->chan_freq); 2156 return QDF_STATUS_E_INVAL; 2157 } 2158 2159 switch (bss_dot11_mode) { 2160 case MLME_DOT11_MODE_11B: 2161 *intersected_mode = MLME_DOT11_MODE_11B; 2162 break; 2163 case MLME_DOT11_MODE_11A: 2164 *intersected_mode = MLME_DOT11_MODE_11A; 2165 break; 2166 case MLME_DOT11_MODE_11G: 2167 *intersected_mode = MLME_DOT11_MODE_11G; 2168 break; 2169 case MLME_DOT11_MODE_11N: 2170 fallthrough; 2171 case MLME_DOT11_MODE_11AC: 2172 fallthrough; 2173 case MLME_DOT11_MODE_11AX: 2174 fallthrough; 2175 case MLME_DOT11_MODE_11BE: 2176 if (WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq)) 2177 *intersected_mode = MLME_DOT11_MODE_11G; 2178 else 2179 *intersected_mode = MLME_DOT11_MODE_11A; 2180 break; 2181 default: 2182 pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode); 2183 return QDF_STATUS_E_FAILURE; 2184 } 2185 2186 return QDF_STATUS_SUCCESS; 2187 } 2188 2189 static QDF_STATUS 2190 lim_handle_11a_dot11_mode(enum mlme_dot11_mode bss_dot11_mode, 2191 enum mlme_dot11_mode *intersected_mode, 2192 struct bss_description *bss_desc) 2193 { 2194 if (!WLAN_REG_IS_5GHZ_CH_FREQ(bss_desc->chan_freq)) { 2195 pe_err("self Dot11mode is 11A and bss freq %d not 5ghz", 2196 bss_desc->chan_freq); 2197 return QDF_STATUS_E_INVAL; 2198 } 2199 2200 switch (bss_dot11_mode) { 2201 case MLME_DOT11_MODE_11B: 2202 case MLME_DOT11_MODE_11G: 2203 /* Self 11A and BSS 11B/G cannot connect */ 2204 pe_err("Self dot11mode 11A, bss dot11mode %d not compatible", 2205 bss_dot11_mode); 2206 return QDF_STATUS_E_INVAL; 2207 case MLME_DOT11_MODE_11A: 2208 case MLME_DOT11_MODE_11N: 2209 case MLME_DOT11_MODE_11AC: 2210 case MLME_DOT11_MODE_11AX: 2211 case MLME_DOT11_MODE_11BE: 2212 *intersected_mode = MLME_DOT11_MODE_11A; 2213 break; 2214 default: 2215 pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode); 2216 return QDF_STATUS_E_FAILURE; 2217 } 2218 2219 return QDF_STATUS_SUCCESS; 2220 } 2221 2222 static QDF_STATUS 2223 lim_handle_11b_dot11_mode(enum mlme_dot11_mode bss_dot11_mode, 2224 enum mlme_dot11_mode *intersected_mode, 2225 struct bss_description *bss_desc) 2226 { 2227 if (!WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq)) { 2228 pe_err("self Dot11mode is 11B and bss freq %d not 2.4ghz", 2229 bss_desc->chan_freq); 2230 return QDF_STATUS_E_INVAL; 2231 } 2232 2233 switch (bss_dot11_mode) { 2234 case MLME_DOT11_MODE_11N: 2235 case MLME_DOT11_MODE_11AC: 2236 case MLME_DOT11_MODE_11AX: 2237 case MLME_DOT11_MODE_11B: 2238 case MLME_DOT11_MODE_11G: 2239 case MLME_DOT11_MODE_11BE: 2240 /* Self 11B and BSS 11A cannot connect */ 2241 *intersected_mode = MLME_DOT11_MODE_11B; 2242 break; 2243 case MLME_DOT11_MODE_11A: 2244 pe_err("Self dot11mode 11B, bss dot11mode %d not compatible", 2245 bss_dot11_mode); 2246 return QDF_STATUS_E_INVAL; 2247 default: 2248 pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode); 2249 return QDF_STATUS_E_FAILURE; 2250 } 2251 2252 return QDF_STATUS_SUCCESS; 2253 } 2254 2255 static QDF_STATUS 2256 lim_handle_11g_dot11_mode(enum mlme_dot11_mode bss_dot11_mode, 2257 enum mlme_dot11_mode *intersected_mode, 2258 struct bss_description *bss_desc) 2259 { 2260 if (!WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq)) { 2261 pe_err("self Dot11mode is 11G and bss freq %d not 2.4ghz", 2262 bss_desc->chan_freq); 2263 return QDF_STATUS_E_INVAL; 2264 } 2265 2266 switch (bss_dot11_mode) { 2267 case MLME_DOT11_MODE_11N: 2268 case MLME_DOT11_MODE_11AC: 2269 case MLME_DOT11_MODE_11AX: 2270 case MLME_DOT11_MODE_11G: 2271 case MLME_DOT11_MODE_11BE: 2272 /* Self 11B and BSS 11A cannot connect */ 2273 *intersected_mode = MLME_DOT11_MODE_11G; 2274 break; 2275 case MLME_DOT11_MODE_11B: 2276 *intersected_mode = MLME_DOT11_MODE_11B; 2277 break; 2278 case MLME_DOT11_MODE_11A: 2279 pe_err("Self dot11mode 11G, bss dot11mode %d not compatible", 2280 bss_dot11_mode); 2281 return QDF_STATUS_E_INVAL; 2282 default: 2283 pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode); 2284 return QDF_STATUS_E_FAILURE; 2285 } 2286 2287 return QDF_STATUS_SUCCESS; 2288 } 2289 2290 static QDF_STATUS 2291 lim_handle_11n_dot11_mode(enum mlme_dot11_mode bss_dot11_mode, 2292 enum mlme_dot11_mode *intersected_mode, 2293 tDot11fBeaconIEs *ie_struct, 2294 struct bss_description *bss_desc) 2295 { 2296 if (WLAN_REG_IS_6GHZ_CHAN_FREQ(bss_desc->chan_freq)) { 2297 pe_err("self Dot11mode is 11N and bss freq %d is 6ghz", 2298 bss_desc->chan_freq); 2299 return QDF_STATUS_E_INVAL; 2300 } 2301 2302 switch (bss_dot11_mode) { 2303 case MLME_DOT11_MODE_11N: 2304 *intersected_mode = MLME_DOT11_MODE_11N; 2305 break; 2306 case MLME_DOT11_MODE_11AC: 2307 case MLME_DOT11_MODE_11BE: 2308 case MLME_DOT11_MODE_11AX: 2309 if (ie_struct->HTCaps.present) { 2310 *intersected_mode = MLME_DOT11_MODE_11N; 2311 break; 2312 } 2313 if (WLAN_REG_IS_5GHZ_CH_FREQ(bss_desc->chan_freq)) 2314 *intersected_mode = MLME_DOT11_MODE_11A; 2315 else 2316 *intersected_mode = MLME_DOT11_MODE_11G; 2317 break; 2318 case MLME_DOT11_MODE_11G: 2319 *intersected_mode = MLME_DOT11_MODE_11G; 2320 break; 2321 case MLME_DOT11_MODE_11B: 2322 *intersected_mode = MLME_DOT11_MODE_11B; 2323 break; 2324 case MLME_DOT11_MODE_11A: 2325 *intersected_mode = MLME_DOT11_MODE_11A; 2326 break; 2327 default: 2328 pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode); 2329 return QDF_STATUS_E_FAILURE; 2330 } 2331 2332 return QDF_STATUS_SUCCESS; 2333 } 2334 2335 static QDF_STATUS 2336 lim_handle_11ac_dot11_mode(enum mlme_dot11_mode bss_dot11_mode, 2337 enum mlme_dot11_mode *intersected_mode, 2338 tDot11fBeaconIEs *ie_struct, 2339 struct bss_description *bss_desc) 2340 { 2341 bool vht_capable = false; 2342 2343 if (WLAN_REG_IS_6GHZ_CHAN_FREQ(bss_desc->chan_freq)) { 2344 pe_err("self Dot11mode is 11AC and bss freq %d is 6ghz", 2345 bss_desc->chan_freq); 2346 return QDF_STATUS_E_INVAL; 2347 } 2348 2349 if (IS_BSS_VHT_CAPABLE(ie_struct->VHTCaps) || 2350 IS_BSS_VHT_CAPABLE(ie_struct->vendor_vht_ie.VHTCaps)) 2351 vht_capable = true; 2352 2353 switch (bss_dot11_mode) { 2354 case MLME_DOT11_MODE_11N: 2355 *intersected_mode = MLME_DOT11_MODE_11N; 2356 break; 2357 case MLME_DOT11_MODE_11AC: 2358 *intersected_mode = MLME_DOT11_MODE_11AC; 2359 break; 2360 case MLME_DOT11_MODE_11AX: 2361 case MLME_DOT11_MODE_11BE: 2362 if (vht_capable) { 2363 *intersected_mode = MLME_DOT11_MODE_11AC; 2364 break; 2365 } 2366 if (ie_struct->HTCaps.present) { 2367 *intersected_mode = MLME_DOT11_MODE_11N; 2368 break; 2369 } 2370 if (WLAN_REG_IS_5GHZ_CH_FREQ(bss_desc->chan_freq)) 2371 *intersected_mode = MLME_DOT11_MODE_11A; 2372 else 2373 *intersected_mode = MLME_DOT11_MODE_11G; 2374 break; 2375 case MLME_DOT11_MODE_11G: 2376 *intersected_mode = MLME_DOT11_MODE_11G; 2377 break; 2378 case MLME_DOT11_MODE_11B: 2379 *intersected_mode = MLME_DOT11_MODE_11B; 2380 break; 2381 case MLME_DOT11_MODE_11A: 2382 *intersected_mode = MLME_DOT11_MODE_11A; 2383 break; 2384 default: 2385 pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode); 2386 return QDF_STATUS_E_FAILURE; 2387 } 2388 2389 return QDF_STATUS_SUCCESS; 2390 } 2391 2392 static QDF_STATUS 2393 lim_handle_11ax_dot11_mode(enum mlme_dot11_mode bss_dot11_mode, 2394 enum mlme_dot11_mode *intersected_mode, 2395 tDot11fBeaconIEs *ie_struct, 2396 struct bss_description *bss_desc) 2397 { 2398 bool vht_capable = false; 2399 2400 if (IS_BSS_VHT_CAPABLE(ie_struct->VHTCaps) || 2401 IS_BSS_VHT_CAPABLE(ie_struct->vendor_vht_ie.VHTCaps)) 2402 vht_capable = true; 2403 2404 switch (bss_dot11_mode) { 2405 case MLME_DOT11_MODE_11N: 2406 *intersected_mode = MLME_DOT11_MODE_11N; 2407 break; 2408 case MLME_DOT11_MODE_11AC: 2409 *intersected_mode = MLME_DOT11_MODE_11AC; 2410 break; 2411 case MLME_DOT11_MODE_11AX: 2412 *intersected_mode = MLME_DOT11_MODE_11AX; 2413 break; 2414 case MLME_DOT11_MODE_11BE: 2415 if (ie_struct->he_cap.present) { 2416 *intersected_mode = MLME_DOT11_MODE_11AX; 2417 break; 2418 } 2419 if (vht_capable) { 2420 *intersected_mode = MLME_DOT11_MODE_11AC; 2421 break; 2422 } 2423 if (ie_struct->HTCaps.present) { 2424 *intersected_mode = MLME_DOT11_MODE_11N; 2425 break; 2426 } 2427 if (WLAN_REG_IS_5GHZ_CH_FREQ(bss_desc->chan_freq)) { 2428 *intersected_mode = MLME_DOT11_MODE_11A; 2429 } else if (WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq)) { 2430 *intersected_mode = MLME_DOT11_MODE_11G; 2431 } else { 2432 pe_err("Invalid bss dot11mode %d freq %d", 2433 bss_dot11_mode, bss_desc->chan_freq); 2434 return QDF_STATUS_E_FAILURE; 2435 } 2436 break; 2437 case MLME_DOT11_MODE_11G: 2438 *intersected_mode = MLME_DOT11_MODE_11G; 2439 break; 2440 case MLME_DOT11_MODE_11B: 2441 *intersected_mode = MLME_DOT11_MODE_11B; 2442 break; 2443 case MLME_DOT11_MODE_11A: 2444 *intersected_mode = MLME_DOT11_MODE_11A; 2445 break; 2446 default: 2447 pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode); 2448 return QDF_STATUS_E_FAILURE; 2449 } 2450 2451 return QDF_STATUS_SUCCESS; 2452 } 2453 2454 static QDF_STATUS 2455 lim_handle_11be_dot11_mode(enum mlme_dot11_mode bss_dot11_mode, 2456 enum mlme_dot11_mode *intersected_mode) 2457 { 2458 switch (bss_dot11_mode) { 2459 case MLME_DOT11_MODE_11N: 2460 *intersected_mode = MLME_DOT11_MODE_11N; 2461 break; 2462 case MLME_DOT11_MODE_11AC: 2463 *intersected_mode = MLME_DOT11_MODE_11AC; 2464 break; 2465 case MLME_DOT11_MODE_11AX: 2466 *intersected_mode = MLME_DOT11_MODE_11AX; 2467 break; 2468 case MLME_DOT11_MODE_11BE: 2469 *intersected_mode = MLME_DOT11_MODE_11BE; 2470 break; 2471 case MLME_DOT11_MODE_11G: 2472 *intersected_mode = MLME_DOT11_MODE_11G; 2473 break; 2474 case MLME_DOT11_MODE_11B: 2475 *intersected_mode = MLME_DOT11_MODE_11B; 2476 break; 2477 case MLME_DOT11_MODE_11A: 2478 *intersected_mode = MLME_DOT11_MODE_11A; 2479 break; 2480 default: 2481 pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode); 2482 return QDF_STATUS_E_FAILURE; 2483 } 2484 2485 return QDF_STATUS_SUCCESS; 2486 } 2487 2488 static QDF_STATUS 2489 lim_handle_11g_only_dot11_mode(enum mlme_dot11_mode bss_dot11_mode, 2490 enum mlme_dot11_mode *intersected_mode, 2491 struct bss_description *bss_desc) 2492 { 2493 if (!WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq)) { 2494 pe_err("self Dot11mode is 11G ONLY and bss freq %d not 2.4ghz", 2495 bss_desc->chan_freq); 2496 return QDF_STATUS_E_INVAL; 2497 } 2498 2499 switch (bss_dot11_mode) { 2500 case MLME_DOT11_MODE_11N: 2501 case MLME_DOT11_MODE_11AC: 2502 case MLME_DOT11_MODE_11AX: 2503 case MLME_DOT11_MODE_11G: 2504 case MLME_DOT11_MODE_11BE: 2505 /* Self 11B and BSS 11A cannot connect */ 2506 *intersected_mode = MLME_DOT11_MODE_11G; 2507 break; 2508 case MLME_DOT11_MODE_11B: 2509 case MLME_DOT11_MODE_11A: 2510 pe_err("Self dot11mode 11G only, bss dot11mode %d not compatible", 2511 bss_dot11_mode); 2512 return QDF_STATUS_E_INVAL; 2513 default: 2514 pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode); 2515 return QDF_STATUS_E_FAILURE; 2516 } 2517 2518 return QDF_STATUS_SUCCESS; 2519 } 2520 2521 static QDF_STATUS 2522 lim_handle_11n_only_dot11_mode(enum mlme_dot11_mode bss_dot11_mode, 2523 enum mlme_dot11_mode *intersected_mode, 2524 tDot11fBeaconIEs *ie_struct, 2525 struct bss_description *bss_desc) 2526 { 2527 if (WLAN_REG_IS_6GHZ_CHAN_FREQ(bss_desc->chan_freq)) { 2528 pe_err("self Dot11mode is 11N ONLY and bss freq %d is 6ghz", 2529 bss_desc->chan_freq); 2530 return QDF_STATUS_E_INVAL; 2531 } 2532 2533 switch (bss_dot11_mode) { 2534 case MLME_DOT11_MODE_11N: 2535 *intersected_mode = MLME_DOT11_MODE_11N; 2536 break; 2537 case MLME_DOT11_MODE_11AC: 2538 case MLME_DOT11_MODE_11AX: 2539 case MLME_DOT11_MODE_11BE: 2540 if (ie_struct->HTCaps.present) { 2541 *intersected_mode = MLME_DOT11_MODE_11N; 2542 break; 2543 } 2544 pe_err("Self dot11mode is 11N ONLY peer is not HT capable"); 2545 return QDF_STATUS_E_INVAL; 2546 case MLME_DOT11_MODE_11G: 2547 case MLME_DOT11_MODE_11B: 2548 case MLME_DOT11_MODE_11A: 2549 pe_err("Self dot11mode 11N only, bss dot11mode %d not compatible", 2550 bss_dot11_mode); 2551 return QDF_STATUS_E_INVAL; 2552 default: 2553 pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode); 2554 return QDF_STATUS_E_FAILURE; 2555 } 2556 2557 return QDF_STATUS_SUCCESS; 2558 } 2559 2560 static QDF_STATUS 2561 lim_handle_11ac_only_dot11_mode(enum mlme_dot11_mode bss_dot11_mode, 2562 enum mlme_dot11_mode *intersected_mode, 2563 tDot11fBeaconIEs *ie_struct, 2564 struct bss_description *bss_desc) 2565 { 2566 bool vht_capable = false; 2567 2568 if (WLAN_REG_IS_6GHZ_CHAN_FREQ(bss_desc->chan_freq)) { 2569 pe_err("self Dot11mode is 11AC and bss freq %d is 6ghz", 2570 bss_desc->chan_freq); 2571 return QDF_STATUS_E_INVAL; 2572 } 2573 2574 if (IS_BSS_VHT_CAPABLE(ie_struct->VHTCaps) || 2575 IS_BSS_VHT_CAPABLE(ie_struct->vendor_vht_ie.VHTCaps)) 2576 vht_capable = true; 2577 2578 switch (bss_dot11_mode) { 2579 case MLME_DOT11_MODE_11AC: 2580 *intersected_mode = MLME_DOT11_MODE_11AC; 2581 break; 2582 case MLME_DOT11_MODE_11AX: 2583 case MLME_DOT11_MODE_11BE: 2584 if (vht_capable) { 2585 *intersected_mode = MLME_DOT11_MODE_11AC; 2586 break; 2587 } 2588 pe_err("Self dot11mode is 11AC ONLY peer is not VHT capable"); 2589 return QDF_STATUS_E_INVAL; 2590 case MLME_DOT11_MODE_11N: 2591 case MLME_DOT11_MODE_11G: 2592 case MLME_DOT11_MODE_11B: 2593 case MLME_DOT11_MODE_11A: 2594 pe_err("Self dot11mode 11AC only, bss dot11mode %d not compatible", 2595 bss_dot11_mode); 2596 return QDF_STATUS_E_INVAL; 2597 default: 2598 pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode); 2599 return QDF_STATUS_E_FAILURE; 2600 } 2601 2602 return QDF_STATUS_SUCCESS; 2603 } 2604 2605 static QDF_STATUS 2606 lim_handle_11ax_only_dot11_mode(enum mlme_dot11_mode bss_dot11_mode, 2607 enum mlme_dot11_mode *intersected_mode, 2608 tDot11fBeaconIEs *ie_struct) 2609 { 2610 switch (bss_dot11_mode) { 2611 case MLME_DOT11_MODE_11AX: 2612 *intersected_mode = MLME_DOT11_MODE_11AX; 2613 break; 2614 case MLME_DOT11_MODE_11BE: 2615 if (ie_struct->he_cap.present) { 2616 *intersected_mode = MLME_DOT11_MODE_11AX; 2617 break; 2618 } 2619 fallthrough; 2620 case MLME_DOT11_MODE_11N: 2621 case MLME_DOT11_MODE_11AC: 2622 case MLME_DOT11_MODE_11G: 2623 case MLME_DOT11_MODE_11B: 2624 case MLME_DOT11_MODE_11A: 2625 pe_err("Self dot11mode 11AX only, bss dot11mode %d not compatible", 2626 bss_dot11_mode); 2627 return QDF_STATUS_E_INVAL; 2628 default: 2629 pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode); 2630 return QDF_STATUS_E_FAILURE; 2631 } 2632 2633 return QDF_STATUS_SUCCESS; 2634 } 2635 2636 static QDF_STATUS 2637 lim_handle_11be_only_dot11_mode(enum mlme_dot11_mode bss_dot11_mode, 2638 enum mlme_dot11_mode *intersected_mode) 2639 { 2640 switch (bss_dot11_mode) { 2641 case MLME_DOT11_MODE_11BE: 2642 *intersected_mode = MLME_DOT11_MODE_11BE; 2643 break; 2644 case MLME_DOT11_MODE_11N: 2645 case MLME_DOT11_MODE_11AC: 2646 case MLME_DOT11_MODE_11AX: 2647 case MLME_DOT11_MODE_11G: 2648 case MLME_DOT11_MODE_11B: 2649 case MLME_DOT11_MODE_11A: 2650 pe_err("Self dot11mode 11BE only, bss dot11mode %d not compatible", 2651 bss_dot11_mode); 2652 return QDF_STATUS_E_INVAL; 2653 default: 2654 pe_err("Invalid bss dot11mode %d passed", bss_dot11_mode); 2655 return QDF_STATUS_E_FAILURE; 2656 } 2657 2658 return QDF_STATUS_SUCCESS; 2659 } 2660 2661 static QDF_STATUS 2662 lim_get_intersected_dot11_mode_sta_ap(struct mac_context *mac_ctx, 2663 enum mlme_dot11_mode self_dot11_mode, 2664 enum mlme_dot11_mode bss_dot11_mode, 2665 enum mlme_dot11_mode *intersected_mode, 2666 tDot11fBeaconIEs *ie_struct, 2667 struct bss_description *bss_desc) 2668 { 2669 switch (self_dot11_mode) { 2670 case MLME_DOT11_MODE_ALL: 2671 *intersected_mode = bss_dot11_mode; 2672 return QDF_STATUS_SUCCESS; 2673 case MLME_DOT11_MODE_11A: 2674 return lim_handle_11a_dot11_mode(bss_dot11_mode, 2675 intersected_mode, bss_desc); 2676 case MLME_DOT11_MODE_11B: 2677 return lim_handle_11b_dot11_mode(bss_dot11_mode, 2678 intersected_mode, bss_desc); 2679 case MLME_DOT11_MODE_11G: 2680 return lim_handle_11g_dot11_mode(bss_dot11_mode, 2681 intersected_mode, bss_desc); 2682 case MLME_DOT11_MODE_11N: 2683 return lim_handle_11n_dot11_mode(bss_dot11_mode, 2684 intersected_mode, ie_struct, 2685 bss_desc); 2686 case MLME_DOT11_MODE_11G_ONLY: 2687 return lim_handle_11g_only_dot11_mode(bss_dot11_mode, 2688 intersected_mode, 2689 bss_desc); 2690 case MLME_DOT11_MODE_11N_ONLY: 2691 return lim_handle_11n_only_dot11_mode(bss_dot11_mode, 2692 intersected_mode, 2693 ie_struct, 2694 bss_desc); 2695 case MLME_DOT11_MODE_11AC: 2696 return lim_handle_11ac_dot11_mode(bss_dot11_mode, 2697 intersected_mode, ie_struct, 2698 bss_desc); 2699 case MLME_DOT11_MODE_11AC_ONLY: 2700 return lim_handle_11ac_only_dot11_mode(bss_dot11_mode, 2701 intersected_mode, 2702 ie_struct, 2703 bss_desc); 2704 case MLME_DOT11_MODE_11AX: 2705 return lim_handle_11ax_dot11_mode(bss_dot11_mode, 2706 intersected_mode, 2707 ie_struct, 2708 bss_desc); 2709 case MLME_DOT11_MODE_11AX_ONLY: 2710 return lim_handle_11ax_only_dot11_mode(bss_dot11_mode, 2711 intersected_mode, 2712 ie_struct); 2713 case MLME_DOT11_MODE_11BE: 2714 return lim_handle_11be_dot11_mode(bss_dot11_mode, 2715 intersected_mode); 2716 case MLME_DOT11_MODE_11BE_ONLY: 2717 return lim_handle_11be_only_dot11_mode(bss_dot11_mode, 2718 intersected_mode); 2719 case MLME_DOT11_MODE_ABG: 2720 return lim_handle_11abg_dot11_mode(bss_dot11_mode, 2721 intersected_mode, bss_desc); 2722 default: 2723 pe_err("Invalid self dot11mode %d not supported", 2724 self_dot11_mode); 2725 return QDF_STATUS_E_FAILURE; 2726 } 2727 } 2728 2729 static void 2730 lim_verify_dot11_mode_with_crypto(struct pe_session *session) 2731 { 2732 struct bss_description *bss_desc = 2733 &session->lim_join_req->bssDescription; 2734 int32_t ucast_cipher; 2735 2736 if (!(session->dot11mode == MLME_DOT11_MODE_11N || 2737 session->dot11mode == MLME_DOT11_MODE_11AC || 2738 session->dot11mode == MLME_DOT11_MODE_11AX || 2739 session->dot11mode == MLME_DOT11_MODE_11BE)) 2740 return; 2741 2742 ucast_cipher = wlan_crypto_get_param(session->vdev, 2743 WLAN_CRYPTO_PARAM_UCAST_CIPHER); 2744 2745 if (ucast_cipher == -1) 2746 return; 2747 2748 if (!((ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_TKIP)) || 2749 (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP)) || 2750 (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP_40)) || 2751 (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP_104)))) 2752 return; 2753 2754 if (WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq)) 2755 session->dot11mode = MLME_DOT11_MODE_11G; 2756 else 2757 session->dot11mode = MLME_DOT11_MODE_11A; 2758 2759 pe_info("HT not supported with TKIP/WEP overriding dot11mode to %d", 2760 session->dot11mode); 2761 2762 session->he_with_wep_tkip = 2763 session->mac_ctx->roam.configParam.wep_tkip_in_he; 2764 } 2765 2766 static QDF_STATUS 2767 lim_fill_dot11_mode(struct mac_context *mac_ctx, struct pe_session *session, 2768 tDot11fBeaconIEs *ie_struct) 2769 { 2770 struct bss_description *bss_desc = 2771 &session->lim_join_req->bssDescription; 2772 QDF_STATUS status; 2773 enum mlme_dot11_mode self_dot11_mode; 2774 enum mlme_dot11_mode bss_dot11_mode; 2775 enum mlme_dot11_mode intersected_mode; 2776 2777 self_dot11_mode = lim_get_self_dot11_mode(mac_ctx, session->opmode, 2778 session->vdev_id); 2779 2780 /* if user set dot11 mode by cmd, need to do intersect first */ 2781 self_dot11_mode = 2782 lim_intersect_user_dot11_mode(mac_ctx, session->opmode, 2783 session->vdev_id, 2784 self_dot11_mode); 2785 2786 bss_dot11_mode = lim_get_bss_dot11_mode(mac_ctx, bss_desc, ie_struct); 2787 2788 status = lim_get_intersected_dot11_mode_sta_ap(mac_ctx, self_dot11_mode, 2789 bss_dot11_mode, 2790 &intersected_mode, 2791 ie_struct, bss_desc); 2792 if (QDF_IS_STATUS_ERROR(status)) 2793 return status; 2794 2795 pe_debug("vdev id %d opmode %d self dot11mode %d bss_dot11 mode %d intersected %d", 2796 session->vdev_id, session->opmode, self_dot11_mode, 2797 bss_dot11_mode, intersected_mode); 2798 2799 if (wlan_vdev_mlme_is_mlo_link_vdev(session->vdev) && 2800 !IS_DOT11_MODE_EHT(intersected_mode)) 2801 return QDF_STATUS_E_INVAL; 2802 2803 session->dot11mode = intersected_mode; 2804 lim_verify_dot11_mode_with_crypto(session); 2805 2806 return status; 2807 } 2808 2809 #ifdef WLAN_FEATURE_11AX 2810 static bool lim_enable_twt(struct mac_context *mac_ctx, tDot11fBeaconIEs *ie) 2811 { 2812 struct s_ext_cap *ext_cap; 2813 bool twt_support_in_11n = false; 2814 bool twt_request = false; 2815 2816 if (!ie) { 2817 pe_debug("ie is null"); 2818 return false; 2819 } 2820 2821 wlan_twt_cfg_get_support_requestor(mac_ctx->psoc, &twt_request); 2822 if (twt_request && (ie->qcn_ie.present || ie->he_cap.twt_responder)) { 2823 pe_debug("TWT is supported, hence disable UAPSD; twt req supp: %d,twt respon supp: %d, QCN_IE: %d", 2824 mac_ctx->mlme_cfg->he_caps.dot11_he_cap.twt_request, 2825 ie->he_cap.twt_responder, 2826 ie->qcn_ie.present); 2827 return true; 2828 } 2829 2830 wlan_twt_cfg_get_support_in_11n(mac_ctx->psoc, 2831 &twt_support_in_11n); 2832 ext_cap = (struct s_ext_cap *)ie->ExtCap.bytes; 2833 if (twt_support_in_11n && ie->ExtCap.present && 2834 ext_cap->twt_responder_support) { 2835 pe_debug("TWT is supported for 11n, twt_support_in_11n %d, ext_cap %d, twt_responder support %d", 2836 twt_support_in_11n, ie->ExtCap.present, 2837 ext_cap->twt_responder_support); 2838 return true; 2839 } 2840 2841 return false; 2842 } 2843 #else 2844 static inline bool 2845 lim_enable_twt(struct mac_context *mac_ctx, tDot11fBeaconIEs *ie) 2846 { 2847 return false; 2848 } 2849 #endif 2850 2851 static int8_t lim_get_cfg_max_tx_power(struct mac_context *mac, 2852 uint32_t ch_freq) 2853 { 2854 return wlan_get_cfg_max_tx_power(mac->psoc, mac->pdev, ch_freq); 2855 } 2856 2857 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM 2858 static inline void lim_fill_rssi(struct pe_session *session, 2859 struct bss_description *bss_desc) 2860 { 2861 session->rssi = bss_desc->rssi; 2862 } 2863 #else 2864 static inline void lim_fill_rssi(struct pe_session *session, 2865 struct bss_description *bss_desc) 2866 { 2867 } 2868 #endif 2869 2870 #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD) 2871 /** 2872 * lim_update_sae_single_pmk_ap_cap() - Function to update sae single pmk ap ie 2873 * @mac: pointer to mac context 2874 * @session: pe session 2875 * 2876 * Return: set sae single pmk feature 2877 */ 2878 static void 2879 lim_update_sae_single_pmk_ap_cap(struct mac_context *mac, 2880 struct pe_session *session) 2881 { 2882 int32_t akm; 2883 2884 akm = wlan_crypto_get_param(session->vdev, 2885 WLAN_CRYPTO_PARAM_KEY_MGMT); 2886 2887 if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE) && 2888 mac->mlme_cfg->lfr.sae_single_pmk_feature_enabled) 2889 wlan_mlme_set_sae_single_pmk_bss_cap(mac->psoc, 2890 session->vdev_id, 2891 session->lim_join_req->bssDescription.is_single_pmk); 2892 2893 } 2894 #else 2895 static inline void 2896 lim_update_sae_single_pmk_ap_cap(struct mac_context *mac, 2897 struct pe_session *session) 2898 { 2899 } 2900 #endif 2901 2902 #ifdef WLAN_FEATURE_11BE_MLO 2903 static void lim_get_mld_peer(struct wlan_objmgr_vdev *vdev, 2904 struct qdf_mac_addr *bssid) 2905 { 2906 struct wlan_objmgr_peer *peer; 2907 2908 if (!vdev || !wlan_vdev_mlme_is_mlo_vdev(vdev)) 2909 return; 2910 2911 peer = wlan_vdev_get_bsspeer(vdev); 2912 if (!peer) 2913 return; 2914 2915 qdf_mem_copy(bssid->bytes, peer->mldaddr, QDF_MAC_ADDR_SIZE); 2916 } 2917 #else 2918 static void lim_get_mld_peer(struct wlan_objmgr_vdev *vdev, 2919 struct qdf_mac_addr *bssid) 2920 { 2921 } 2922 #endif 2923 2924 #ifdef WLAN_FEATURE_SAE 2925 static void lim_update_sae_config(struct mac_context *mac, 2926 struct pe_session *session) 2927 { 2928 struct wlan_crypto_pmksa *pmksa; 2929 struct qdf_mac_addr bssid; 2930 2931 qdf_mem_copy(bssid.bytes, session->bssId, 2932 QDF_MAC_ADDR_SIZE); 2933 2934 /* For MLO connection, override BSSID with peer mldaddr */ 2935 lim_get_mld_peer(session->vdev, &bssid); 2936 2937 pmksa = wlan_crypto_get_pmksa(session->vdev, &bssid); 2938 if (!pmksa) 2939 return; 2940 2941 session->sae_pmk_cached = true; 2942 pe_debug("PMKSA Found for BSSID=" QDF_MAC_ADDR_FMT, 2943 QDF_MAC_ADDR_REF(bssid.bytes)); 2944 } 2945 #else 2946 static inline void lim_update_sae_config(struct mac_context *mac, 2947 struct pe_session *session) 2948 { } 2949 #endif 2950 2951 static void 2952 lim_fill_11r_params(struct mac_context *mac_ctx, struct pe_session *session, 2953 bool ese_version_present) 2954 { 2955 struct wlan_mlme_psoc_ext_obj *mlme_obj; 2956 2957 mlme_obj = mlme_get_psoc_ext_obj(mac_ctx->psoc); 2958 if (!mlme_obj) 2959 return; 2960 if (wlan_cm_is_auth_type_11r(mlme_obj, session->vdev, 2961 session->lim_join_req->bssDescription.mdiePresent) && 2962 !cm_ese_open_present(session->vdev, mlme_obj, ese_version_present)) 2963 session->is11Rconnection = true; 2964 } 2965 2966 #ifdef FEATURE_WLAN_ESE 2967 static void 2968 lim_fill_ese_params(struct mac_context *mac_ctx, struct pe_session *session, 2969 bool ese_version_present) 2970 { 2971 wlan_cm_set_ese_assoc(mac_ctx->pdev, session->vdev_id, 2972 cm_is_ese_connection(session->vdev, 2973 ese_version_present)); 2974 } 2975 #else 2976 static inline void 2977 lim_fill_ese_params(struct mac_context *mac_ctx, struct pe_session *session, 2978 bool ese_version_present) 2979 { 2980 } 2981 #endif 2982 2983 void lim_get_basic_rates(tSirMacRateSet *b_rates, uint32_t chan_freq) 2984 { 2985 /* 2986 * Some IOT APs don't send supported rates in 2987 * probe resp, hence add BSS basic rates in 2988 * supported rates IE of assoc request. 2989 */ 2990 if (WLAN_REG_IS_24GHZ_CH_FREQ(chan_freq)) 2991 wlan_populate_basic_rates(b_rates, false, true); 2992 else if (WLAN_REG_IS_5GHZ_CH_FREQ(chan_freq)) 2993 wlan_populate_basic_rates(b_rates, true, true); 2994 } 2995 2996 /* 2997 * lim_iterate_triplets() - Iterate the country IE to validate it 2998 * @country_ie: country IE to iterate through 2999 * 3000 * This function always returns success because connection should not be failed 3001 * in the case of missing elements in the country IE 3002 * 3003 * Return: QDF_STATUS 3004 */ 3005 static QDF_STATUS lim_iterate_triplets(tDot11fIECountry country_ie) 3006 { 3007 u_int8_t i; 3008 3009 if (country_ie.first_triplet[0] > OP_CLASS_ID_200) { 3010 if (country_ie.more_triplets[0][0] <= OP_CLASS_ID_200) 3011 return QDF_STATUS_SUCCESS; 3012 } 3013 3014 for (i = 0; i < country_ie.num_more_triplets; i++) { 3015 if ((country_ie.more_triplets[i][0] > OP_CLASS_ID_200) && 3016 (i < country_ie.num_more_triplets - 1)) { 3017 if (country_ie.more_triplets[i + 1][0] <= 3018 OP_CLASS_ID_200) 3019 return QDF_STATUS_SUCCESS; 3020 } 3021 } 3022 pe_debug("No operating class triplet followed by sub-band triplet"); 3023 3024 return QDF_STATUS_SUCCESS; 3025 } 3026 3027 static bool lim_is_bss_description_wme(struct mac_context *mac, 3028 tDot11fBeaconIEs *ie_struct) 3029 { 3030 3031 if (!(ie_struct->WMMParams.present || ie_struct->WMMInfoAp.present)) 3032 return false; 3033 if (mac->roam.configParam.WMMSupportMode == WMM_USER_MODE_NO_QOS && 3034 !ie_struct->HTCaps.present) 3035 return false; 3036 3037 return true; 3038 } 3039 3040 static enum medium_access_type 3041 lim_get_qos_from_bss_desc(struct mac_context *mac_ctx, 3042 struct bss_description *bss_desc, 3043 tDot11fBeaconIEs *ie_struct) 3044 { 3045 enum medium_access_type qos_type = MEDIUM_ACCESS_DCF; 3046 tSirMacCapabilityInfo *ap_cap_info; 3047 3048 /* 3049 * If we find WMM in the Bss Description, then we let this 3050 * override and use WMM. 3051 */ 3052 if (lim_is_bss_description_wme(mac_ctx, ie_struct)) 3053 return MEDIUM_ACCESS_WMM_EDCF_DSCP; 3054 3055 ap_cap_info = (tSirMacCapabilityInfo *)&bss_desc->capabilityInfo; 3056 /* If the QoS bit is on, then the AP is advertising 11E QoS. */ 3057 if (ap_cap_info->qos) 3058 qos_type = MEDIUM_ACCESS_11E_EDCF; 3059 3060 if (qos_type == MEDIUM_ACCESS_11E_EDCF && 3061 !mac_ctx->roam.configParam.Is11eSupportEnabled) 3062 qos_type = MEDIUM_ACCESS_DCF; 3063 3064 return qos_type; 3065 } 3066 3067 static void lim_set_qos_to_cfg(struct pe_session *session, 3068 enum medium_access_type qos_type) 3069 { 3070 bool qos_enabled; 3071 bool wme_enabled; 3072 3073 switch (qos_type) { 3074 case MEDIUM_ACCESS_WMM_EDCF_DSCP: 3075 qos_enabled = false; 3076 wme_enabled = true; 3077 break; 3078 case MEDIUM_ACCESS_11E_EDCF: 3079 qos_enabled = true; 3080 wme_enabled = false; 3081 break; 3082 default: 3083 case MEDIUM_ACCESS_DCF: 3084 qos_enabled = false; 3085 wme_enabled = false; 3086 break; 3087 } 3088 3089 session->limWmeEnabled = wme_enabled; 3090 session->limQosEnabled = qos_enabled; 3091 } 3092 3093 static void lim_update_qos(struct mac_context *mac_ctx, 3094 struct pe_session *session, 3095 struct bss_description *bss_desc, 3096 tDot11fBeaconIEs *ie_struct) 3097 { 3098 struct mlme_legacy_priv *mlme_priv; 3099 enum medium_access_type qos_type; 3100 3101 mlme_priv = wlan_vdev_mlme_get_ext_hdl(session->vdev); 3102 if (!mlme_priv) 3103 return; 3104 3105 qos_type = lim_get_qos_from_bss_desc(mac_ctx, bss_desc, ie_struct); 3106 3107 if ((session->dot11mode != MLME_DOT11_MODE_11N) && 3108 (mac_ctx->roam.configParam.WMMSupportMode == 3109 WMM_USER_MODE_NO_QOS)) { 3110 /* 3111 * Joining BSS is not 11n capable and WMM is disabled on client. 3112 * Disable QoS and WMM 3113 */ 3114 qos_type = MEDIUM_ACCESS_DCF; 3115 } 3116 3117 if ((session->dot11mode == MLME_DOT11_MODE_11N || 3118 session->dot11mode == MLME_DOT11_MODE_11AC) && 3119 (qos_type != MEDIUM_ACCESS_WMM_EDCF_DSCP && 3120 qos_type != MEDIUM_ACCESS_11E_EDCF)) { 3121 /* 3122 * Joining BSS is 11n capable and WMM is disabled on AP. 3123 * Assume all HT AP's are QOS AP's and enable WMM 3124 */ 3125 qos_type = MEDIUM_ACCESS_WMM_EDCF_DSCP; 3126 } 3127 3128 lim_set_qos_to_cfg(session, qos_type); 3129 mlme_priv->connect_info.qos_enabled = session->limWmeEnabled; 3130 pe_debug("qos_type %d QOS %d WMM %d", qos_type, 3131 session->limQosEnabled, 3132 session->limWmeEnabled); 3133 } 3134 3135 static void lim_reset_self_ocv_caps(struct pe_session *session) 3136 { 3137 uint16_t self_rsn_cap; 3138 3139 self_rsn_cap = wlan_crypto_get_param(session->vdev, 3140 WLAN_CRYPTO_PARAM_RSN_CAP); 3141 if (self_rsn_cap == -1) 3142 return; 3143 3144 self_rsn_cap &= ~WLAN_CRYPTO_RSN_CAP_OCV_SUPPORTED; 3145 3146 /* Update the new rsn caps */ 3147 wlan_crypto_set_vdev_param(session->vdev, WLAN_CRYPTO_PARAM_RSN_CAP, 3148 self_rsn_cap); 3149 3150 } 3151 3152 bool lim_enable_cts_to_self_for_exempted_iot_ap( 3153 struct mac_context *mac_ctx, 3154 struct pe_session *session, 3155 uint8_t *ie_ptr, 3156 uint16_t ie_len) 3157 { 3158 struct action_oui_search_attr vendor_ap_search_attr; 3159 3160 vendor_ap_search_attr.ie_data = ie_ptr; 3161 vendor_ap_search_attr.ie_length = ie_len; 3162 3163 if (wlan_action_oui_search(mac_ctx->psoc, &vendor_ap_search_attr, 3164 ACTION_OUI_ENABLE_CTS2SELF)) { 3165 pe_debug("vdev %d: enable cts to self", session->vdev_id); 3166 wma_cli_set_command(session->vdev_id, 3167 wmi_vdev_param_enable_rtscts, 3168 FW_CTS2SELF_PROFILE, VDEV_CMD); 3169 return true; 3170 } 3171 return false; 3172 } 3173 3174 /** 3175 * lim_disable_bformee_for_iot_ap() - disable bformee for iot ap 3176 *@mac_ctx: mac context 3177 *@session: pe session 3178 *@bss_desc: bss descriptor 3179 * 3180 * When connect IoT AP with BW 160MHz and NSS 2, disable Beamformee 3181 * 3182 * Return: None 3183 */ 3184 static void 3185 lim_disable_bformee_for_iot_ap(struct mac_context *mac_ctx, 3186 struct pe_session *session, 3187 struct bss_description *bss_desc) 3188 { 3189 struct action_oui_search_attr vendor_ap_search_attr; 3190 uint16_t ie_len; 3191 3192 ie_len = wlan_get_ielen_from_bss_description(bss_desc); 3193 3194 vendor_ap_search_attr.ie_data = (uint8_t *)&bss_desc->ieFields[0]; 3195 vendor_ap_search_attr.ie_length = ie_len; 3196 3197 if (wlan_action_oui_search(mac_ctx->psoc, 3198 &vendor_ap_search_attr, 3199 ACTION_OUI_DISABLE_BFORMEE) && 3200 session->nss == 2 && CH_WIDTH_160MHZ == session->ch_width) { 3201 session->vht_config.su_beam_formee = 0; 3202 session->vht_config.mu_beam_formee = 0; 3203 pe_debug("IoT ap with BW 160 MHz NSS 2, disable Beamformee"); 3204 } 3205 } 3206 3207 QDF_STATUS 3208 lim_fill_pe_session(struct mac_context *mac_ctx, struct pe_session *session, 3209 struct bss_description *bss_desc) 3210 { 3211 uint8_t bss_chan_id; 3212 tDot11fBeaconIEs *ie_struct; 3213 QDF_STATUS status; 3214 ePhyChanBondState cb_mode; 3215 const uint8_t *vendor_ie; 3216 uint16_t ie_len; 3217 int8_t local_power_constraint; 3218 struct vdev_mlme_obj *mlme_obj; 3219 bool is_pwr_constraint = false; 3220 tSirMacCapabilityInfo *ap_cap_info; 3221 uint8_t wmm_mode, value; 3222 struct wlan_mlme_lfr_cfg *lfr = &mac_ctx->mlme_cfg->lfr; 3223 struct cm_roam_values_copy config = {}; 3224 bool ese_ver_present; 3225 int8_t reg_max; 3226 struct ps_global_info *ps_global_info = &mac_ctx->sme.ps_global_info; 3227 struct ps_params *ps_param = 3228 &ps_global_info->ps_params[session->vdev_id]; 3229 uint32_t timeout; 3230 enum reg_6g_ap_type power_type_6g; 3231 struct cm_roam_values_copy temp; 3232 uint32_t neighbor_lookup_threshold; 3233 uint32_t hi_rssi_scan_rssi_delta; 3234 3235 /* 3236 * Update the capability here itself as this is used in 3237 * lim_extract_ap_capability() below. If not updated issues 3238 * like not honoring power constraint on 1st association after 3239 * driver loading might occur. 3240 */ 3241 lim_update_rrm_capability(mac_ctx); 3242 bss_chan_id = wlan_reg_freq_to_chan(mac_ctx->pdev, 3243 bss_desc->chan_freq); 3244 3245 lim_update_sae_config(mac_ctx, session); 3246 lim_update_sae_single_pmk_ap_cap(mac_ctx, session); 3247 3248 /* Update the beacon/probe filter in mac_ctx */ 3249 lim_set_bcn_probe_filter(mac_ctx, session, 3250 bss_chan_id); 3251 session->max_amsdu_num = 3252 mac_ctx->mlme_cfg->ht_caps.max_num_amsdu; 3253 /* Store beaconInterval */ 3254 session->beaconParams.beaconInterval = 3255 bss_desc->beaconInterval; 3256 /* Copy oper freq to the session Table */ 3257 session->curr_op_freq = bss_desc->chan_freq; 3258 3259 status = wlan_get_parsed_bss_description_ies(mac_ctx, bss_desc, 3260 &ie_struct); 3261 if (QDF_IS_STATUS_ERROR(status)) { 3262 pe_err("IE parsing failed vdev id %d", 3263 session->vdev_id); 3264 return QDF_STATUS_E_FAILURE; 3265 } 3266 3267 qdf_mem_zero(&session->wmm_params, sizeof(tDot11fIEWMMParams)); 3268 if (ie_struct->WMMParams.present) 3269 qdf_mem_copy(&session->wmm_params, &ie_struct->WMMParams, 3270 sizeof(tDot11fIEWMMParams)); 3271 3272 mac_ctx->mlme_cfg->power.local_power_constraint = 3273 wlan_get_11h_power_constraint(mac_ctx, 3274 &ie_struct->PowerConstraints); 3275 3276 session->enable_session_twt_support = 3277 lim_enable_twt(mac_ctx, ie_struct); 3278 status = lim_fill_dot11_mode(mac_ctx, session, ie_struct); 3279 if (QDF_IS_STATUS_ERROR(status)) { 3280 status = QDF_STATUS_E_FAILURE; 3281 goto send; 3282 } 3283 cb_mode = wlan_get_cb_mode(mac_ctx, session->curr_op_freq, ie_struct, 3284 session); 3285 3286 if (WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq) && 3287 wlan_cm_get_force_20mhz_in_24ghz(session->vdev)) 3288 cb_mode = PHY_SINGLE_CHANNEL_CENTERED; 3289 3290 status = wlan_get_rate_set(mac_ctx, ie_struct, session); 3291 if (QDF_IS_STATUS_ERROR(status)) { 3292 pe_err("Get rate failed vdev id %d", session->vdev_id); 3293 lim_get_basic_rates(&session->rateSet, bss_desc->chan_freq); 3294 } 3295 3296 if (session->dot11mode == MLME_DOT11_MODE_11B) 3297 mac_ctx->mlme_cfg->feature_flags.enable_short_slot_time_11g = 0; 3298 else 3299 mac_ctx->mlme_cfg->feature_flags.enable_short_slot_time_11g = 3300 mac_ctx->mlme_cfg->ht_caps.short_slot_time_enabled; 3301 3302 /* 3303 * Join timeout: if we find a BeaconInterval in the BssDescription, 3304 * then set the Join Timeout to be 10 x the BeaconInterval. 3305 * 3306 * 10 * BeaconInterval should be greater than the minimum join 3307 * timeout and lesser than the configured timeout. 3308 */ 3309 timeout = mac_ctx->mlme_cfg->timeouts.join_failure_timeout_ori; 3310 if (bss_desc->beaconInterval) 3311 timeout = QDF_MAX(10 * bss_desc->beaconInterval, 3312 cfg_min(CFG_JOIN_FAILURE_TIMEOUT)); 3313 3314 mac_ctx->mlme_cfg->timeouts.join_failure_timeout = 3315 QDF_MIN(timeout, 3316 mac_ctx->mlme_cfg->timeouts.join_failure_timeout_ori); 3317 /* 3318 * Calculate probe request retry timeout, 3319 * Change probe req retry to MAX_JOIN_PROBE_REQ if sta freq 3320 * can cause MCC 3321 */ 3322 timeout = JOIN_PROBE_REQ_TIMER_MS; 3323 if (policy_mgr_will_freq_lead_to_mcc(mac_ctx->psoc, 3324 bss_desc->chan_freq)) { 3325 /* Send MAX_JOIN_PROBE_REQ probe req during join timeout */ 3326 timeout = mac_ctx->mlme_cfg->timeouts.join_failure_timeout/ 3327 MAX_JOIN_PROBE_REQ; 3328 timeout = QDF_MAX(JOIN_PROBE_REQ_TIMER_MS, timeout); 3329 } 3330 mac_ctx->mlme_cfg->timeouts.probe_req_retry_timeout = timeout; 3331 3332 lim_join_req_update_ht_vht_caps(mac_ctx, session, bss_desc, 3333 ie_struct); 3334 3335 lim_check_oui_and_update_session(mac_ctx, session, ie_struct); 3336 ese_ver_present = ie_struct->ESEVersion.present; 3337 3338 /* Copying of bssId is already done, while creating session */ 3339 sir_copy_mac_addr(session->self_mac_addr, 3340 wlan_vdev_mlme_get_macaddr(session->vdev)); 3341 3342 session->statypeForBss = STA_ENTRY_PEER; 3343 3344 lim_update_qos(mac_ctx, session, bss_desc, ie_struct); 3345 3346 if (session->lim_join_req->bssDescription.adaptive_11r_ap) 3347 session->is_adaptive_11r_connection = 3348 wlan_get_adaptive_11r_enabled(lfr); 3349 config.bool_value = session->is_adaptive_11r_connection; 3350 wlan_cm_roam_cfg_set_value(mac_ctx->psoc, session->vdev_id, 3351 ADAPTIVE_11R_CONNECTION, 3352 &config); 3353 lim_fill_11r_params(mac_ctx, session , ese_ver_present); 3354 lim_fill_ese_params(mac_ctx, session, ese_ver_present); 3355 3356 wlan_cm_roam_cfg_get_value(mac_ctx->psoc, session->vdev_id, 3357 NEIGHBOUR_LOOKUP_THRESHOLD, &temp); 3358 neighbor_lookup_threshold = temp.uint_value; 3359 3360 wlan_cm_roam_cfg_get_value(mac_ctx->psoc, session->vdev_id, 3361 HI_RSSI_SCAN_RSSI_DELTA, &temp); 3362 hi_rssi_scan_rssi_delta = temp.uint_value; 3363 3364 /* 3365 * Firmware will take care of checking hi_scan rssi delta, take care of 3366 * legacy -> legacy hi-rssi roam also if this feature flag is 3367 * advertised. 3368 */ 3369 if (wlan_cm_is_self_mld_roam_supported(mac_ctx->psoc)) { 3370 wlan_cm_set_disable_hi_rssi(mac_ctx->pdev, session->vdev_id, 3371 false); 3372 } else if (WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq) && 3373 (abs(bss_desc->rssi) > 3374 (neighbor_lookup_threshold - hi_rssi_scan_rssi_delta))) { 3375 pe_debug("Enabling HI_RSSI, rssi: %d lookup_th: %d, delta:%d", 3376 bss_desc->rssi, neighbor_lookup_threshold, 3377 hi_rssi_scan_rssi_delta); 3378 wlan_cm_set_disable_hi_rssi(mac_ctx->pdev, session->vdev_id, 3379 false); 3380 } else { 3381 wlan_cm_set_disable_hi_rssi(mac_ctx->pdev, session->vdev_id, 3382 true); 3383 pe_debug("Disabling HI_RSSI, AP freq=%d, rssi=%d", 3384 bss_desc->chan_freq, bss_desc->rssi); 3385 } 3386 3387 if (session->opmode == QDF_STA_MODE) 3388 session->enable_bcast_probe_rsp = 3389 mac_ctx->mlme_cfg->oce.enable_bcast_probe_rsp; 3390 3391 /* Store vendor specific IE for CISCO AP */ 3392 ie_len = (bss_desc->length + sizeof(bss_desc->length) - 3393 GET_FIELD_OFFSET(struct bss_description, ieFields)); 3394 3395 vendor_ie = wlan_get_vendor_ie_ptr_from_oui( 3396 SIR_MAC_CISCO_OUI, SIR_MAC_CISCO_OUI_SIZE, 3397 ((uint8_t *)&bss_desc->ieFields), ie_len); 3398 3399 if (vendor_ie) 3400 session->isCiscoVendorAP = true; 3401 else 3402 session->isCiscoVendorAP = false; 3403 3404 session->nwType = bss_desc->nwType; 3405 session->enableAmpduPs = 3406 mac_ctx->mlme_cfg->ht_caps.enable_ampdu_ps; 3407 session->send_smps_action = 3408 mac_ctx->roam.configParam.send_smps_action; 3409 session->vhtCapability = 3410 IS_DOT11_MODE_VHT(session->dot11mode); 3411 if (session->vhtCapability) { 3412 session->enableVhtpAid = 3413 mac_ctx->mlme_cfg->vht_caps.vht_cap_info.enable_paid; 3414 session->enableVhtGid = 3415 mac_ctx->mlme_cfg->vht_caps.vht_cap_info.enable_gid; 3416 } 3417 /*Phy mode */ 3418 session->gLimPhyMode = bss_desc->nwType; 3419 handle_ht_capabilityand_ht_info(mac_ctx, session); 3420 3421 session->htSupportedChannelWidthSet = cb_mode ? 1 : 0; 3422 session->htRecommendedTxWidthSet = 3423 session->htSupportedChannelWidthSet; 3424 session->htSecondaryChannelOffset = cb_mode; 3425 3426 if (cb_mode == PHY_DOUBLE_CHANNEL_HIGH_PRIMARY) { 3427 session->ch_center_freq_seg0 = 3428 wlan_reg_freq_to_chan( 3429 mac_ctx->pdev, session->curr_op_freq) - 2; 3430 session->ch_width = CH_WIDTH_40MHZ; 3431 } else if (cb_mode == PHY_DOUBLE_CHANNEL_LOW_PRIMARY) { 3432 session->ch_center_freq_seg0 = 3433 wlan_reg_freq_to_chan( 3434 mac_ctx->pdev, session->curr_op_freq) + 2; 3435 session->ch_width = CH_WIDTH_40MHZ; 3436 } else { 3437 session->ch_center_freq_seg0 = 0; 3438 session->ch_width = CH_WIDTH_20MHZ; 3439 } 3440 session->ap_ch_width = session->ch_width; 3441 3442 if (IS_DOT11_MODE_HE(session->dot11mode)) { 3443 lim_update_session_he_capable(mac_ctx, session); 3444 lim_copy_join_req_he_cap(session); 3445 } 3446 3447 if (IS_DOT11_MODE_EHT(session->dot11mode)) { 3448 lim_update_session_eht_capable(mac_ctx, session); 3449 lim_reset_self_ocv_caps(session); 3450 lim_copy_join_req_eht_cap(session); 3451 } 3452 3453 /* Record if management frames need to be protected */ 3454 session->limRmfEnabled = 3455 lim_get_vdev_rmf_capable(mac_ctx, session); 3456 3457 session->txLdpcIniFeatureEnabled = 3458 mac_ctx->mlme_cfg->ht_caps.tx_ldpc_enable; 3459 3460 session->limSystemRole = eLIM_STA_ROLE; 3461 if (session->nss == 1) 3462 session->supported_nss_1x1 = true; 3463 3464 session->limCurrentBssCaps = bss_desc->capabilityInfo; 3465 3466 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(session->vdev); 3467 if (!mlme_obj) { 3468 status = QDF_STATUS_E_FAILURE; 3469 goto send; 3470 } 3471 3472 lim_extract_ap_capability(mac_ctx, 3473 (uint8_t *)bss_desc->ieFields, 3474 lim_get_ielen_from_bss_description(bss_desc), 3475 &session->limCurrentBssQosCaps, 3476 &session->gLimCurrentBssUapsd, 3477 &local_power_constraint, session, &is_pwr_constraint); 3478 3479 lim_disable_bformee_for_iot_ap(mac_ctx, session, bss_desc); 3480 3481 mlme_obj->reg_tpc_obj.is_power_constraint_abs = 3482 !is_pwr_constraint; 3483 3484 if (wlan_reg_is_6ghz_chan_freq(bss_desc->chan_freq)) { 3485 if (!ie_struct->Country.present) 3486 pe_debug("Channel is 6G but country IE not present"); 3487 status = wlan_reg_get_best_6g_power_type( 3488 mac_ctx->psoc, mac_ctx->pdev, 3489 &power_type_6g, 3490 session->ap_defined_power_type_6g, 3491 bss_desc->chan_freq); 3492 if (QDF_IS_STATUS_ERROR(status)) { 3493 status = QDF_STATUS_E_NOSUPPORT; 3494 goto send; 3495 } 3496 session->best_6g_power_type = power_type_6g; 3497 mlme_set_best_6g_power_type(session->vdev, power_type_6g); 3498 3499 lim_iterate_triplets(ie_struct->Country); 3500 3501 if (!ie_struct->num_transmit_power_env || 3502 !ie_struct->transmit_power_env[0].present) 3503 pe_debug("TPE not present for 6G channel"); 3504 } 3505 3506 if (wlan_reg_is_ext_tpc_supported(mac_ctx->psoc)) { 3507 mlme_obj->reg_tpc_obj.ap_constraint_power = 3508 local_power_constraint; 3509 } else { 3510 reg_max = wlan_reg_get_channel_reg_power_for_freq( 3511 mac_ctx->pdev, session->curr_op_freq); 3512 if (is_pwr_constraint) 3513 local_power_constraint = reg_max - 3514 local_power_constraint; 3515 if (!local_power_constraint) 3516 local_power_constraint = reg_max; 3517 3518 mlme_obj->reg_tpc_obj.reg_max[0] = reg_max; 3519 mlme_obj->reg_tpc_obj.ap_constraint_power = 3520 local_power_constraint; 3521 mlme_obj->reg_tpc_obj.frequency[0] = session->curr_op_freq; 3522 3523 session->maxTxPower = lim_get_max_tx_power(mac_ctx, mlme_obj); 3524 session->def_max_tx_pwr = session->maxTxPower; 3525 } 3526 3527 /* 3528 * for mdm platform which QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET 3529 * will not call from android framework every 3 seconds, and tx 3530 * power will never update. So we use iw dev get tx power need 3531 * set maxTxPower non-zero value, that firmware can calc a non-zero 3532 * tx power, and update to host driver. 3533 */ 3534 if (LIM_IS_STA_ROLE(session) && session->maxTxPower == 0) 3535 session->maxTxPower = 3536 wlan_reg_get_channel_reg_power_for_freq(mac_ctx->pdev, 3537 session->curr_op_freq); 3538 3539 session->limRFBand = lim_get_rf_band(session->curr_op_freq); 3540 3541 /* Initialize 11h Enable Flag */ 3542 if (session->limRFBand != REG_BAND_2G) 3543 session->lim11hEnable = 3544 mac_ctx->mlme_cfg->gen.enabled_11h; 3545 else 3546 session->lim11hEnable = 0; 3547 3548 session->limPrevSmeState = session->limSmeState; 3549 session->limSmeState = eLIM_SME_WT_JOIN_STATE; 3550 MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, 3551 session->peSessionId, 3552 session->limSmeState)); 3553 3554 /* Enable MBSSID only for station */ 3555 session->is_mbssid_enabled = wma_is_mbssid_enabled(); 3556 3557 /* Enable the spectrum management if this is a DFS channel */ 3558 if (session->country_info_present && 3559 lim_isconnected_on_dfs_freq( 3560 mac_ctx, 3561 session->curr_op_freq)) 3562 session->spectrumMgtEnabled = true; 3563 3564 ap_cap_info = (tSirMacCapabilityInfo *)&bss_desc->capabilityInfo; 3565 3566 /* 3567 * tell the target AP my 11H capability only if both AP and STA 3568 * support 3569 * 11H and the channel being used is 11a 3570 */ 3571 if (mac_ctx->mlme_cfg->gen.enabled_11h && 3572 ap_cap_info->spectrumMgt && bss_desc->nwType == eSIR_11A_NW_TYPE) 3573 session->spectrumMgtEnabled = true; 3574 3575 /* 3576 * This is required for 11k test VoWiFi Ent: Test 2. 3577 * We need the power capabilities for Assoc Req. 3578 * This macro is provided by the halPhyCfg.h. We pick our 3579 * max and min capability by the halPhy provided macros 3580 * Any change in this power cap IE should also be done 3581 * in csr_update_driver_assoc_ies() which would send 3582 * assoc IE's to FW which is used for LFR3 roaming 3583 * ie. used in reassociation requests from FW. 3584 */ 3585 session->max_11h_pwr = 3586 QDF_MIN(lim_get_cfg_max_tx_power(mac_ctx, 3587 bss_desc->chan_freq), 3588 MAX_TX_PWR_CAP); 3589 3590 if (!session->max_11h_pwr) 3591 session->max_11h_pwr = MAX_TX_PWR_CAP; 3592 3593 if (session->max_11h_pwr > session->maxTxPower) 3594 session->max_11h_pwr = session->maxTxPower; 3595 3596 session->min_11h_pwr = MIN_TX_PWR_CAP; 3597 3598 if (!session->enable_session_twt_support) { 3599 status = wlan_mlme_get_wmm_mode(mac_ctx->psoc, &wmm_mode); 3600 if (!QDF_IS_STATUS_SUCCESS(status)) { 3601 pe_err("Get wmm_mode failed"); 3602 status = QDF_STATUS_E_INVAL; 3603 goto send; 3604 } 3605 if (wmm_mode == 2 || !(LIM_IS_QOS_BSS(ie_struct)) || 3606 !(LIM_IS_UAPSD_BSS(ie_struct))) { 3607 /*QoS not enabled in cfg file or in BSS*/ 3608 session->gUapsdPerAcBitmask = 0; 3609 } else { 3610 /*QoS enabled, update uapsd mask from cfg file */ 3611 status = wlan_mlme_get_wmm_uapsd_mask(mac_ctx->psoc, 3612 &value); 3613 if (QDF_IS_STATUS_ERROR(status)) { 3614 pe_err("Get uapsd_mask failed"); 3615 status = QDF_STATUS_E_INVAL; 3616 goto send; 3617 } 3618 session->gUapsdPerAcBitmask = value; 3619 } 3620 ps_param->uapsd_per_ac_bit_mask = session->gUapsdPerAcBitmask; 3621 } 3622 3623 if (session->gLimCurrentBssUapsd) { 3624 /* resetting the dynamic uapsd mask */ 3625 session->gUapsdPerAcDeliveryEnableMask = 0; 3626 session->gUapsdPerAcTriggerEnableMask = 0; 3627 } 3628 3629 lim_fill_cc_mode(mac_ctx, session); 3630 lim_fill_rssi(session, bss_desc); 3631 3632 status = QDF_STATUS_SUCCESS; 3633 3634 send: 3635 qdf_mem_free(ie_struct); 3636 return status; 3637 3638 } 3639 3640 static QDF_STATUS 3641 lim_send_connect_req_to_mlm(struct pe_session *session) 3642 { 3643 tLimMlmJoinReq *mlm_join_req; 3644 uint32_t len; 3645 QDF_STATUS status; 3646 3647 len = sizeof(tLimMlmJoinReq) + 3648 session->lim_join_req->bssDescription.length + 2; 3649 mlm_join_req = qdf_mem_malloc(len); 3650 if (!mlm_join_req) 3651 return QDF_STATUS_E_FAILURE; 3652 3653 /* PE SessionId is stored as a part of JoinReq */ 3654 mlm_join_req->sessionId = session->peSessionId; 3655 3656 mlm_join_req->bssDescription.length = 3657 session->lim_join_req->bssDescription.length; 3658 3659 qdf_mem_copy((uint8_t *) &mlm_join_req->bssDescription.bssId, 3660 (uint8_t *) 3661 &session->lim_join_req->bssDescription.bssId, 3662 session->lim_join_req->bssDescription.length + 2); 3663 3664 /* Issue LIM_MLM_JOIN_REQ to MLM */ 3665 status = lim_send_join_req(session, mlm_join_req); 3666 if (QDF_IS_STATUS_ERROR(status)) { 3667 qdf_mem_free(mlm_join_req); 3668 return QDF_STATUS_E_FAILURE; 3669 } 3670 3671 return QDF_STATUS_SUCCESS; 3672 } 3673 3674 static struct pe_session * 3675 lim_cm_create_session(struct mac_context *mac_ctx, struct cm_vdev_join_req *req) 3676 { 3677 struct pe_session *pe_session; 3678 uint8_t session_id; 3679 3680 pe_session = pe_find_session_by_bssid(mac_ctx, req->entry->bssid.bytes, 3681 &session_id); 3682 3683 if (pe_session) { 3684 pe_err("vdev_id: %d cm_id 0x%x :pe-session(%d (vdev %d)) already exists for BSSID: " 3685 QDF_MAC_ADDR_FMT " in lim_sme_state = %X", 3686 req->vdev_id, req->cm_id, session_id, 3687 pe_session->vdev_id, 3688 QDF_MAC_ADDR_REF(req->entry->bssid.bytes), 3689 pe_session->limSmeState); 3690 3691 qdf_trigger_self_recovery(mac_ctx->psoc, 3692 QDF_VDEV_SM_OUT_OF_SYNC); 3693 return NULL; 3694 } 3695 3696 pe_session = pe_create_session(mac_ctx, req->entry->bssid.bytes, 3697 &session_id, 3698 mac_ctx->lim.max_sta_of_pe_session, 3699 eSIR_INFRASTRUCTURE_MODE, 3700 req->vdev_id); 3701 if (!pe_session) 3702 pe_err("vdev_id: %d cm_id 0x%x : pe_session create failed BSSID" 3703 QDF_MAC_ADDR_FMT, req->vdev_id, req->cm_id, 3704 QDF_MAC_ADDR_REF(req->entry->bssid.bytes)); 3705 3706 return pe_session; 3707 } 3708 3709 static bool 3710 lim_is_wpa_profile(struct pe_session *session) 3711 { 3712 int32_t ucast_cipher; 3713 int32_t auth_mode; 3714 3715 ucast_cipher = wlan_crypto_get_param(session->vdev, 3716 WLAN_CRYPTO_PARAM_UCAST_CIPHER); 3717 3718 auth_mode = wlan_crypto_get_param(session->vdev, 3719 WLAN_CRYPTO_PARAM_AUTH_MODE); 3720 3721 if (auth_mode == -1 || ucast_cipher == -1) 3722 return false; 3723 3724 if (!QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_WPA)) 3725 return false; 3726 3727 if (((ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_TKIP)) || 3728 (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP)) || 3729 (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP_104)) || 3730 (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP_40)) || 3731 (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_CCM)) || 3732 (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_OCB)) || 3733 (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_CCM_256)))) 3734 return true; 3735 3736 return false; 3737 } 3738 3739 static bool 3740 lim_is_wapi_profile(struct pe_session *session) 3741 { 3742 int32_t ucast_cipher; 3743 int32_t auth_mode; 3744 3745 ucast_cipher = wlan_crypto_get_param(session->vdev, 3746 WLAN_CRYPTO_PARAM_UCAST_CIPHER); 3747 3748 auth_mode = wlan_crypto_get_param(session->vdev, 3749 WLAN_CRYPTO_PARAM_AUTH_MODE); 3750 3751 if (auth_mode == -1 || ucast_cipher == -1) 3752 return false; 3753 3754 if (!QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_WAPI)) 3755 return false; 3756 3757 if (((ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WAPI_GCM4)) || 3758 (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WAPI_SMS4)))) 3759 return true; 3760 3761 return false; 3762 } 3763 3764 static bool 3765 lim_is_rsn_profile(struct pe_session *session) 3766 { 3767 int32_t ucast_cipher; 3768 int32_t auth_mode; 3769 bool is_rsn = false; 3770 3771 ucast_cipher = wlan_crypto_get_param(session->vdev, 3772 WLAN_CRYPTO_PARAM_UCAST_CIPHER); 3773 3774 auth_mode = wlan_crypto_get_param(session->vdev, 3775 WLAN_CRYPTO_PARAM_AUTH_MODE); 3776 3777 if (auth_mode == -1 || ucast_cipher == -1) 3778 return false; 3779 3780 if (QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_8021X) || 3781 QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_RSNA) || 3782 QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_CCKM) || 3783 QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_SAE) || 3784 QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_FILS_SK)) 3785 is_rsn = true; 3786 3787 if (!is_rsn) 3788 return false; 3789 3790 if (((ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_TKIP)) || 3791 (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP)) || 3792 (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP_104)) || 3793 (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_WEP_40)) || 3794 (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_CCM)) || 3795 (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_OCB)) || 3796 (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_CCM_256)) || 3797 (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_GCM_256)) || 3798 (ucast_cipher & (1 << WLAN_CRYPTO_CIPHER_AES_GCM)))) 3799 return true; 3800 3801 return false; 3802 } 3803 3804 tAniEdType lim_get_encrypt_ed_type(int32_t ucast_cipher) 3805 { 3806 if (ucast_cipher == -1) 3807 return eSIR_ED_NONE; 3808 3809 if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_GCM_256)) 3810 return eSIR_ED_GCMP_256; 3811 else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_GCM)) 3812 return eSIR_ED_GCMP; 3813 else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_CCM) || 3814 QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_OCB) || 3815 QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_CCM_256)) 3816 return eSIR_ED_CCMP; 3817 else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_TKIP)) 3818 return eSIR_ED_TKIP; 3819 else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_CMAC) || 3820 QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_CMAC_256)) 3821 return eSIR_ED_AES_128_CMAC; 3822 else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WAPI_GCM4) || 3823 QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WAPI_SMS4)) 3824 return eSIR_ED_WPI; 3825 else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_GMAC)) 3826 return eSIR_ED_AES_GMAC_128; 3827 else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_AES_GMAC_256)) 3828 return eSIR_ED_AES_GMAC_256; 3829 else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WEP)) 3830 return eSIR_ED_WEP40; 3831 else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WEP_40)) 3832 return eSIR_ED_WEP40; 3833 else if (QDF_HAS_PARAM(ucast_cipher, WLAN_CRYPTO_CIPHER_WEP_104)) 3834 return eSIR_ED_WEP104; 3835 3836 return eSIR_ED_NONE; 3837 } 3838 3839 static enum ani_akm_type 3840 lim_get_wpa_akm(uint32_t akm) 3841 { 3842 if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X)) 3843 return ANI_AKM_TYPE_WPA; 3844 else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_PSK)) 3845 return ANI_AKM_TYPE_WPA_PSK; 3846 else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_CCKM)) 3847 return ANI_AKM_TYPE_CCKM; 3848 else 3849 return ANI_AKM_TYPE_UNKNOWN; 3850 } 3851 3852 static enum ani_akm_type 3853 lim_get_rsn_akm(uint32_t akm) 3854 { 3855 if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA384)) 3856 return ANI_AKM_TYPE_FT_FILS_SHA384; 3857 else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA256)) 3858 return ANI_AKM_TYPE_FT_FILS_SHA256; 3859 else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FILS_SHA384)) 3860 return ANI_AKM_TYPE_FILS_SHA384; 3861 else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FILS_SHA256)) 3862 return ANI_AKM_TYPE_FILS_SHA256; 3863 else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_SAE_EXT_KEY)) 3864 return ANI_AKM_TYPE_FT_SAE_EXT_KEY; 3865 else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_SAE)) 3866 return ANI_AKM_TYPE_FT_SAE; 3867 else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE)) 3868 return ANI_AKM_TYPE_SAE; 3869 else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_DPP)) 3870 return ANI_AKM_TYPE_DPP_RSN; 3871 else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_OSEN)) 3872 return ANI_AKM_TYPE_OSEN; 3873 else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_OWE)) 3874 return ANI_AKM_TYPE_OWE; 3875 else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X)) 3876 return ANI_AKM_TYPE_FT_RSN; 3877 else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_PSK)) 3878 return ANI_AKM_TYPE_FT_RSN_PSK; 3879 else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X)) 3880 return ANI_AKM_TYPE_RSN; 3881 else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_PSK)) 3882 return ANI_AKM_TYPE_RSN_PSK; 3883 else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_CCKM)) 3884 return ANI_AKM_TYPE_CCKM; 3885 else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_PSK_SHA256)) 3886 return ANI_AKM_TYPE_RSN_PSK_SHA256; 3887 else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256)) 3888 return ANI_AKM_TYPE_RSN_8021X_SHA256; 3889 else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B)) 3890 return ANI_AKM_TYPE_SUITEB_EAP_SHA256; 3891 else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B_192)) 3892 return ANI_AKM_TYPE_SUITEB_EAP_SHA384; 3893 else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384)) 3894 return ANI_AKM_TYPE_FT_SUITEB_EAP_SHA384; 3895 else if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE_EXT_KEY)) 3896 return ANI_AKM_TYPE_SAE_EXT_KEY; 3897 else 3898 return ANI_AKM_TYPE_NONE; 3899 } 3900 3901 enum ani_akm_type 3902 lim_get_connected_akm(struct pe_session *session, int32_t ucast_cipher, 3903 int32_t auth_mode, int32_t akm) 3904 { 3905 if (auth_mode == -1 || ucast_cipher == -1 || akm == -1) 3906 return ANI_AKM_TYPE_NONE; 3907 3908 if (QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_NONE) || 3909 QDF_HAS_PARAM(auth_mode, WLAN_CRYPTO_AUTH_OPEN)) 3910 return ANI_AKM_TYPE_NONE; 3911 3912 if (lim_is_rsn_profile(session)) 3913 return lim_get_rsn_akm(akm); 3914 3915 if (lim_is_wpa_profile(session)) 3916 return lim_get_wpa_akm(akm); 3917 3918 if (lim_is_wapi_profile(session)) 3919 return ANI_AKM_TYPE_UNKNOWN; 3920 3921 return ANI_AKM_TYPE_NONE; 3922 } 3923 3924 #ifdef WLAN_FEATURE_FILS_SK 3925 /** 3926 * lim_update_pmksa_to_profile() - update pmk and pmkid to profile which will be 3927 * used in case of fils session 3928 * @vdev: vdev 3929 * @pmkid_cache: pmksa cache 3930 * 3931 * Return: None 3932 */ 3933 static inline void lim_update_pmksa_to_profile(struct wlan_objmgr_vdev *vdev, 3934 struct wlan_crypto_pmksa *pmksa) 3935 { 3936 struct mlme_legacy_priv *mlme_priv; 3937 3938 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 3939 if (!mlme_priv) { 3940 pe_err("vdev legacy private object is NULL"); 3941 return; 3942 } 3943 if (!mlme_priv->connect_info.fils_con_info) 3944 return; 3945 mlme_priv->connect_info.fils_con_info->pmk_len = pmksa->pmk_len; 3946 qdf_mem_copy(mlme_priv->connect_info.fils_con_info->pmk, 3947 pmksa->pmk, pmksa->pmk_len); 3948 qdf_mem_copy(mlme_priv->connect_info.fils_con_info->pmkid, 3949 pmksa->pmkid, PMKID_LEN); 3950 } 3951 #else 3952 static inline void lim_update_pmksa_to_profile(struct wlan_objmgr_vdev *vdev, 3953 struct wlan_crypto_pmksa *pmksa) 3954 { 3955 } 3956 #endif 3957 3958 /* 3959 * lim_is_non_default_rsnxe_cap_set() - Check if non-default userspace RSNXE 3960 * CAP is set 3961 * 3962 * @mac_ctx: pointer to mac contetx 3963 * @req: join request 3964 * 3965 * Return: Non default cap set 3966 */ 3967 static inline bool 3968 lim_is_non_default_rsnxe_cap_set(struct mac_context *mac_ctx, 3969 struct cm_vdev_join_req *req) 3970 { 3971 const uint8_t *rsnxe, *rsnxe_cap; 3972 uint8_t cap_len = 0, cap_index; 3973 uint32_t cap_mask; 3974 3975 rsnxe = wlan_get_ie_ptr_from_eid(WLAN_ELEMID_RSNXE, 3976 req->assoc_ie.ptr, 3977 req->assoc_ie.len); 3978 if (!rsnxe) 3979 return false; 3980 3981 rsnxe_cap = wlan_crypto_parse_rsnxe_ie(rsnxe, &cap_len); 3982 if (!rsnxe_cap || (rsnxe[SIR_MAC_IE_LEN_OFFSET] > (cap_len + 1))) { 3983 mlme_err("RSNXE caps not present/unknown caps present. Cap len %d", 3984 cap_len); 3985 return true; 3986 } 3987 3988 /* 3989 * Below is the definition of RSNXE capabilities defined 3990 * in (IEEE Std 802.11-2020, 9.4.2.241, Table 9-780). 3991 * The Extended RSN Capabilities field, except its first 4 bits, is a 3992 * bit field indicating the extended RSN capabilities being advertised 3993 * by the STA transmitting the element. The length of the Extended 3994 * RSN Capabilities field is a variable n, in octets, as indicated by 3995 * the first 4 bits in the field. 3996 * Let's consider a uint32_t cap_mask which can accommodate 28(32-4) 3997 * bits to check if those bits are set or not. This is to keep it 3998 * simple as current supported bits are only 11. 3999 * TODO: If spec supports more than this range in future, this needs to 4000 * be an array to hold the complete bitmap/bitmask. 4001 */ 4002 cap_mask = ~(0xF | WLAN_CRYPTO_RSNX_CAP_SAE_H2E | 4003 WLAN_CRYPTO_RSNX_CAP_SAE_PK | 4004 WLAN_CRYPTO_RSNX_CAP_SECURE_LTF | 4005 WLAN_CRYPTO_RSNX_CAP_SECURE_RTT | 4006 WLAN_CRYPTO_RSNX_CAP_URNM_MFPR); 4007 4008 /* Check if any other bits are set than cap_mask */ 4009 for (cap_index = 0; cap_index <= cap_len; cap_index++) { 4010 if (rsnxe_cap[cap_index] & (cap_mask & 0xFF)) 4011 return true; 4012 cap_mask >>= 8; 4013 } 4014 4015 return false; 4016 } 4017 4018 /* 4019 * lim_rebuild_rsnxe_cap() - Rebuild the RSNXE CAP for STA 4020 * 4021 * @rsnx_ie: RSNX IE 4022 * @length: length of extended RSN cap field 4023 * 4024 * This API is used to truncate/rebuild the RSNXE based on the length 4025 * provided. This length marks the length of the extended RSN cap field. 4026 * 4027 * Return: Newly constructed RSNX IE 4028 */ 4029 static inline uint8_t *lim_rebuild_rsnxe_cap(uint8_t *rsnx_ie, uint8_t length) 4030 { 4031 const uint8_t *rsnxe_cap; 4032 uint8_t cap_len; 4033 uint8_t *new_rsnxe = NULL; 4034 4035 if (length < SIR_MAC_RSNX_CAP_MIN_LEN || 4036 length > SIR_MAC_RSNX_CAP_MAX_LEN) { 4037 pe_err("Invalid length %d", length); 4038 return NULL; 4039 } 4040 4041 rsnxe_cap = wlan_crypto_parse_rsnxe_ie(rsnx_ie, &cap_len); 4042 if (!rsnxe_cap) 4043 return NULL; 4044 4045 new_rsnxe = qdf_mem_malloc(length + SIR_MAC_IE_TYPE_LEN_SIZE); 4046 if (!new_rsnxe) 4047 return NULL; 4048 4049 new_rsnxe[SIR_MAC_IE_TYPE_OFFSET] = WLAN_ELEMID_RSNXE; 4050 new_rsnxe[SIR_MAC_IE_LEN_OFFSET] = length; 4051 qdf_mem_copy(&new_rsnxe[SIR_MAC_IE_TYPE_LEN_SIZE], rsnxe_cap, length); 4052 4053 /* Now update the new field length in octet 0 for the new length*/ 4054 new_rsnxe[SIR_MAC_IE_TYPE_LEN_SIZE] = 4055 (new_rsnxe[SIR_MAC_IE_TYPE_LEN_SIZE] & 0xF0) | (length - 1); 4056 4057 pe_debug("New RSNXE length %d", length); 4058 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, 4059 new_rsnxe, length + SIR_MAC_IE_TYPE_LEN_SIZE); 4060 return new_rsnxe; 4061 } 4062 4063 /* 4064 * lim_append_rsnxe_to_assoc_ie() - Append the new RSNXE to the 4065 * assoc ie buffer 4066 * 4067 * @req: join request 4068 * @new_rsnxe: new rsnxe to be appended 4069 * 4070 * Return: QDF_STATUS 4071 */ 4072 static inline QDF_STATUS 4073 lim_append_rsnxe_to_assoc_ie(struct cm_vdev_join_req *req, 4074 uint8_t *new_rsnxe) 4075 { 4076 uint8_t *assoc_ie = NULL; 4077 uint8_t assoc_ie_len; 4078 4079 assoc_ie = qdf_mem_malloc(req->assoc_ie.len + 4080 new_rsnxe[SIR_MAC_IE_LEN_OFFSET] + 4081 SIR_MAC_IE_TYPE_LEN_SIZE); 4082 if (!assoc_ie) 4083 return QDF_STATUS_E_FAILURE; 4084 4085 qdf_mem_copy(assoc_ie, req->assoc_ie.ptr, req->assoc_ie.len); 4086 assoc_ie_len = req->assoc_ie.len; 4087 qdf_mem_copy(&assoc_ie[assoc_ie_len], new_rsnxe, 4088 new_rsnxe[SIR_MAC_IE_LEN_OFFSET] + 4089 SIR_MAC_IE_TYPE_LEN_SIZE); 4090 assoc_ie_len += new_rsnxe[SIR_MAC_IE_LEN_OFFSET] + 4091 SIR_MAC_IE_TYPE_LEN_SIZE; 4092 4093 /* Replace the assoc ie with new assoc_ie */ 4094 qdf_mem_free(req->assoc_ie.ptr); 4095 req->assoc_ie.ptr = &assoc_ie[0]; 4096 req->assoc_ie.len = assoc_ie_len; 4097 return QDF_STATUS_SUCCESS; 4098 } 4099 4100 static inline QDF_STATUS 4101 lim_strip_rsnx_ie(struct mac_context *mac_ctx, 4102 struct pe_session *session, 4103 struct cm_vdev_join_req *req) 4104 { 4105 int32_t akm; 4106 uint8_t ap_rsnxe_len = 0, len = 0; 4107 uint8_t *rsnxe = NULL, *new_rsnxe = NULL; 4108 uint8_t *ap_rsnxe = NULL; 4109 QDF_STATUS status = QDF_STATUS_SUCCESS; 4110 4111 akm = wlan_crypto_get_param(session->vdev, WLAN_CRYPTO_PARAM_KEY_MGMT); 4112 if (akm == -1 || 4113 !(WLAN_CRYPTO_IS_WPA_WPA2(akm) || WLAN_CRYPTO_IS_WPA3(akm))) 4114 return status; 4115 4116 if (!wlan_get_ie_ptr_from_eid(WLAN_ELEMID_RSNXE, req->assoc_ie.ptr, 4117 req->assoc_ie.len)) 4118 return status; 4119 4120 /* 4121 * Userspace may send RSNXE also in connect request irrespective 4122 * of the connecting AP capabilities. This allows the driver to chose 4123 * best candidate based on score. But the chosen candidate may 4124 * not support the RSNXE feature and may not advertise RSNXE 4125 * in beacon/probe response. Station is not supposed to include 4126 * the RSNX IE in assoc request in such cases as legacy APs 4127 * may misbahave due to the new IE. It's observed that few 4128 * legacy APs which don't support the RSNXE reject the 4129 * connection at EAPOL stage. 4130 * 4131 * Modify the RSNXE only when known capability bits are set. 4132 * i.e., don't strip when bits other than SAE_H2E, SAE_PK, SECURE_LTF, 4133 * SECURE_RTT, PROT_RANGE_NEGOTIOATION are set by userspace. 4134 * 4135 */ 4136 if (lim_is_non_default_rsnxe_cap_set(mac_ctx, req)) { 4137 pe_debug("Do not strip RSNXE, unknown caps are set"); 4138 return status; 4139 } 4140 4141 ap_rsnxe = util_scan_entry_rsnxe(req->entry); 4142 if (!ap_rsnxe) 4143 ap_rsnxe_len = 0; 4144 else 4145 ap_rsnxe_len = ap_rsnxe[SIR_MAC_IE_LEN_OFFSET]; 4146 4147 /* 4148 * Do not modify userspace RSNXE if either: 4149 * a) AP supports RSNXE cap with more than 1 bytes 4150 * b) AP has zero length RSNXE. 4151 */ 4152 4153 if (ap_rsnxe_len > 1 || (ap_rsnxe && ap_rsnxe_len == 0)) 4154 return QDF_STATUS_SUCCESS; 4155 4156 rsnxe = qdf_mem_malloc(WLAN_MAX_IE_LEN + SIR_MAC_IE_TYPE_LEN_SIZE); 4157 if (!rsnxe) 4158 return QDF_STATUS_E_FAILURE; 4159 4160 lim_strip_ie(mac_ctx, req->assoc_ie.ptr, 4161 (uint16_t *)&req->assoc_ie.len, WLAN_ELEMID_RSNXE, 4162 ONE_BYTE, NULL, 0, rsnxe, WLAN_MAX_IE_LEN); 4163 4164 if (!rsnxe[0]) 4165 goto end; 4166 4167 switch (ap_rsnxe_len) { 4168 case 0: 4169 /* 4170 * AP doesn't broadcast RSNXE/invalid RSNXE: 4171 * For WPA2 - Strip the RSNXE 4172 * For WPA3 - Retain only SAE caps: H2E and PK in the 1st octet 4173 */ 4174 if (WLAN_CRYPTO_IS_WPA_WPA2(akm)) { 4175 mlme_debug("Strip RSNXE as it is not supported by AP"); 4176 goto end; 4177 } 4178 if (WLAN_CRYPTO_IS_WPA3(akm)) { 4179 len = 1; 4180 goto rebuild_rsnxe; 4181 } 4182 break; 4183 case 1: 4184 /* 4185 * In some IOT cases, APs do not recognize more than 1 octet of 4186 * RSNXE. This leads to connectivity failures. 4187 * Therefore, restrict the self RSNXE to 1 octet if AP supports 4188 * only 1 octet 4189 */ 4190 len = 1; 4191 goto rebuild_rsnxe; 4192 default: 4193 break; 4194 } 4195 4196 pe_err("Error in handling RSNXE. Length AP: %d SELF: %d", 4197 ap_rsnxe_len, rsnxe[SIR_MAC_IE_LEN_OFFSET]); 4198 status = QDF_STATUS_E_FAILURE; 4199 goto end; 4200 4201 rebuild_rsnxe: 4202 /* Build the new RSNXE */ 4203 new_rsnxe = lim_rebuild_rsnxe_cap(rsnxe, len); 4204 if (!new_rsnxe) { 4205 status = QDF_STATUS_E_FAILURE; 4206 goto end; 4207 } else if (!new_rsnxe[1]) { 4208 qdf_mem_free(new_rsnxe); 4209 status = QDF_STATUS_E_FAILURE; 4210 goto end; 4211 } 4212 4213 /* Append the new RSNXE to the assoc ie */ 4214 status = lim_append_rsnxe_to_assoc_ie(req, new_rsnxe); 4215 qdf_mem_free(new_rsnxe); 4216 4217 end: 4218 qdf_mem_free(rsnxe); 4219 return status; 4220 } 4221 4222 void 4223 lim_update_connect_rsn_ie(struct pe_session *session, 4224 uint8_t *rsn_ie_buf, struct wlan_crypto_pmksa *pmksa) 4225 { 4226 uint8_t *rsn_ie_end; 4227 uint16_t rsn_ie_len = 0; 4228 4229 rsn_ie_end = wlan_crypto_build_rsnie_with_pmksa(session->vdev, 4230 rsn_ie_buf, pmksa); 4231 if (!rsn_ie_end) { 4232 pe_debug("Build RSN IE failed"); 4233 return; 4234 } 4235 4236 rsn_ie_len = rsn_ie_end - rsn_ie_buf; 4237 session->lim_join_req->rsnIE.length = rsn_ie_len; 4238 qdf_mem_copy(session->lim_join_req->rsnIE.rsnIEdata, 4239 rsn_ie_buf, rsn_ie_len); 4240 } 4241 4242 static QDF_STATUS 4243 lim_fill_rsn_ie(struct mac_context *mac_ctx, struct pe_session *session, 4244 struct cm_vdev_join_req *req) 4245 { 4246 QDF_STATUS status; 4247 uint8_t *rsn_ie; 4248 uint8_t rsn_ie_len = 0; 4249 struct wlan_crypto_pmksa pmksa, *pmksa_peer; 4250 struct bss_description *bss_desc; 4251 4252 rsn_ie = qdf_mem_malloc(DOT11F_IE_RSN_MAX_LEN + 2); 4253 if (!rsn_ie) 4254 return QDF_STATUS_E_NOMEM; 4255 4256 status = lim_strip_ie(mac_ctx, req->assoc_ie.ptr, 4257 (uint16_t *)&req->assoc_ie.len, 4258 WLAN_ELEMID_RSN, ONE_BYTE, 4259 NULL, 0, rsn_ie, DOT11F_IE_RSN_MAX_LEN); 4260 4261 if (req->force_rsne_override && QDF_IS_STATUS_SUCCESS(status)) { 4262 rsn_ie_len = rsn_ie[1] + 2; 4263 if (rsn_ie_len < DOT11F_IE_RSN_MIN_LEN || 4264 rsn_ie_len > DOT11F_IE_RSN_MAX_LEN) { 4265 pe_err("RSN length %d not within limits", rsn_ie_len); 4266 qdf_mem_free(rsn_ie); 4267 return QDF_STATUS_E_FAILURE; 4268 } 4269 4270 session->lim_join_req->rsnIE.length = rsn_ie_len; 4271 qdf_mem_copy(session->lim_join_req->rsnIE.rsnIEdata, 4272 rsn_ie, rsn_ie_len); 4273 4274 qdf_mem_free(rsn_ie); 4275 return QDF_STATUS_SUCCESS; 4276 } 4277 4278 bss_desc = &session->lim_join_req->bssDescription; 4279 4280 qdf_mem_zero(&pmksa, sizeof(pmksa)); 4281 if (bss_desc->fils_info_element.is_cache_id_present) { 4282 pmksa.ssid_len = session->ssId.length; 4283 qdf_mem_copy(pmksa.ssid, session->ssId.ssId, 4284 session->ssId.length); 4285 qdf_mem_copy(pmksa.cache_id, 4286 bss_desc->fils_info_element.cache_id, 4287 CACHE_ID_LEN); 4288 pe_debug("FILS: vdev %d Cache id =0x%x 0x%x ssid: " QDF_SSID_FMT, 4289 session->vdev_id, pmksa.cache_id[0], pmksa.cache_id[1], 4290 QDF_SSID_REF(pmksa.ssid_len, pmksa.ssid)); 4291 } else { 4292 qdf_mem_copy(&pmksa.bssid, session->bssId, QDF_MAC_ADDR_SIZE); 4293 /* For MLO connection, override BSSID with peer mldaddr */ 4294 lim_get_mld_peer(session->vdev, &pmksa.bssid); 4295 } 4296 4297 pmksa_peer = wlan_crypto_get_peer_pmksa(session->vdev, &pmksa); 4298 if (pmksa_peer) 4299 pe_debug("PMKSA found"); 4300 4301 lim_update_connect_rsn_ie(session, rsn_ie, pmksa_peer); 4302 qdf_mem_free(rsn_ie); 4303 4304 /* 4305 * If a PMK cache is found for the BSSID, then 4306 * update the PMK in CSR session also as this 4307 * will be sent to the FW during RSO. 4308 */ 4309 if (pmksa_peer) { 4310 wlan_cm_set_psk_pmk(mac_ctx->pdev, session->vdev_id, 4311 pmksa_peer->pmk, pmksa_peer->pmk_len); 4312 lim_update_pmksa_to_profile(session->vdev, pmksa_peer); 4313 } 4314 4315 return QDF_STATUS_SUCCESS; 4316 } 4317 4318 static QDF_STATUS 4319 lim_fill_wpa_ie(struct mac_context *mac_ctx, struct pe_session *session, 4320 struct cm_vdev_join_req *req) 4321 { 4322 QDF_STATUS status; 4323 uint8_t *wpa_ie; 4324 uint8_t ie_len = 0; 4325 uint8_t *wpa_ie_end = NULL; 4326 4327 wpa_ie = qdf_mem_malloc(DOT11F_IE_WPA_MAX_LEN + 2); 4328 if (!wpa_ie) 4329 return QDF_STATUS_E_NOMEM; 4330 4331 status = lim_strip_ie(mac_ctx, req->assoc_ie.ptr, 4332 (uint16_t *)&req->assoc_ie.len, 4333 DOT11F_EID_WPA, ONE_BYTE, 4334 "\x00\x50\xf2", 3, NULL, 0); 4335 4336 wpa_ie_end = wlan_crypto_build_wpaie(session->vdev, wpa_ie); 4337 if (wpa_ie_end) 4338 ie_len = wpa_ie_end - wpa_ie; 4339 4340 session->lim_join_req->rsnIE.length = ie_len; 4341 qdf_mem_copy(session->lim_join_req->rsnIE.rsnIEdata, 4342 wpa_ie, ie_len); 4343 4344 qdf_mem_free(wpa_ie); 4345 4346 return QDF_STATUS_SUCCESS; 4347 } 4348 4349 #ifdef FEATURE_WLAN_WAPI 4350 static QDF_STATUS 4351 lim_fill_wapi_ie(struct mac_context *mac_ctx, struct pe_session *session, 4352 struct cm_vdev_join_req *req) 4353 { 4354 QDF_STATUS status; 4355 uint8_t *wapi_ie; 4356 uint8_t ie_len = 0; 4357 uint8_t *wapi_ie_end = NULL; 4358 4359 wapi_ie = qdf_mem_malloc(DOT11F_IE_WAPI_MAX_LEN + 2); 4360 if (!wapi_ie) 4361 return QDF_STATUS_E_NOMEM; 4362 4363 status = lim_strip_ie(mac_ctx, req->assoc_ie.ptr, 4364 (uint16_t *)&req->assoc_ie.len, 4365 WLAN_ELEMID_WAPI, ONE_BYTE, 4366 NULL, 0, NULL, 0); 4367 4368 wapi_ie_end = wlan_crypto_build_wapiie(session->vdev, wapi_ie); 4369 if (wapi_ie_end) 4370 ie_len = wapi_ie_end - wapi_ie; 4371 4372 session->lim_join_req->rsnIE.length = ie_len; 4373 qdf_mem_copy(session->lim_join_req->rsnIE.rsnIEdata, 4374 wapi_ie, ie_len); 4375 4376 qdf_mem_free(wapi_ie); 4377 4378 return QDF_STATUS_SUCCESS; 4379 } 4380 #else 4381 static inline QDF_STATUS 4382 lim_fill_wapi_ie(struct mac_context *mac_ctx, struct pe_session *session, 4383 struct cm_vdev_join_req *req) 4384 { 4385 return QDF_STATUS_SUCCESS; 4386 } 4387 #endif 4388 4389 static QDF_STATUS lim_fill_crypto_params(struct mac_context *mac_ctx, 4390 struct pe_session *session, 4391 struct cm_vdev_join_req *req) 4392 { 4393 int32_t ucast_cipher; 4394 int32_t auth_mode; 4395 int32_t akm; 4396 tSirMacCapabilityInfo *ap_cap_info; 4397 QDF_STATUS status; 4398 4399 ucast_cipher = wlan_crypto_get_param(session->vdev, 4400 WLAN_CRYPTO_PARAM_UCAST_CIPHER); 4401 auth_mode = wlan_crypto_get_param(session->vdev, 4402 WLAN_CRYPTO_PARAM_AUTH_MODE); 4403 akm = wlan_crypto_get_param(session->vdev, 4404 WLAN_CRYPTO_PARAM_KEY_MGMT); 4405 ap_cap_info = (tSirMacCapabilityInfo *) 4406 &session->lim_join_req->bssDescription.capabilityInfo; 4407 4408 lim_set_privacy(mac_ctx, ucast_cipher, auth_mode, akm, 4409 ap_cap_info->privacy); 4410 session->encryptType = lim_get_encrypt_ed_type(ucast_cipher); 4411 session->connected_akm = lim_get_connected_akm(session, ucast_cipher, 4412 auth_mode, akm); 4413 4414 session->wps_registration = req->is_wps_connection; 4415 session->isOSENConnection = req->is_osen_connection; 4416 4417 if (lim_is_rsn_profile(session)) 4418 lim_fill_rsn_ie(mac_ctx, session, req); 4419 else if (lim_is_wpa_profile(session)) 4420 lim_fill_wpa_ie(mac_ctx, session, req); 4421 else if (lim_is_wapi_profile(session)) 4422 lim_fill_wapi_ie(mac_ctx, session, req); 4423 4424 status = lim_strip_rsnx_ie(mac_ctx, session, req); 4425 if (QDF_IS_STATUS_ERROR(status)) 4426 return status; 4427 4428 lim_update_fils_config(mac_ctx, session, req); 4429 return QDF_STATUS_SUCCESS; 4430 } 4431 4432 #ifdef WLAN_FEATURE_11BE_MLO 4433 static void lim_fill_ml_info(struct cm_vdev_join_req *req, 4434 struct join_req *pe_join_req) 4435 { 4436 uint8_t idx, num_links = 0; 4437 struct mlo_partner_info *partner_info = NULL; 4438 4439 partner_info = &pe_join_req->partner_info; 4440 if (!partner_info) 4441 return; 4442 4443 num_links = req->partner_info.num_partner_links; 4444 if (num_links > WLAN_UMAC_MLO_MAX_VDEVS) 4445 num_links = WLAN_UMAC_MLO_MAX_VDEVS; 4446 4447 partner_info->num_partner_links = num_links; 4448 4449 for (idx = 0; idx < num_links; idx++) { 4450 partner_info->partner_link_info[idx].link_id = 4451 req->partner_info.partner_link_info[idx].link_id; 4452 qdf_copy_macaddr( 4453 &partner_info->partner_link_info[idx].link_addr, 4454 &req->partner_info.partner_link_info[idx].link_addr); 4455 partner_info->partner_link_info[idx].chan_freq = 4456 req->partner_info.partner_link_info[idx].chan_freq; 4457 } 4458 pe_join_req->assoc_link_id = req->assoc_link_id; 4459 } 4460 4461 static void lim_copy_ml_partner_info_to_session(struct pe_session *session, 4462 struct cm_vdev_join_req *req) 4463 { 4464 session->ml_partner_info = req->partner_info; 4465 } 4466 4467 void lim_set_emlsr_caps(struct mac_context *mac_ctx, struct pe_session *session) 4468 { 4469 bool emlsr_cap, emlsr_allowed, emlsr_band_check, emlsr_enabled = false; 4470 4471 /* Check if HW supports eMLSR mode */ 4472 emlsr_cap = policy_mgr_is_hw_emlsr_capable(mac_ctx->psoc); 4473 if (!emlsr_cap) 4474 return; 4475 4476 /* Check if vendor command chooses eMLSR mode */ 4477 wlan_mlme_get_emlsr_mode_enabled(mac_ctx->psoc, &emlsr_enabled); 4478 4479 /* Check if ML links are in 5 GHz + 6 GHz combination */ 4480 emlsr_band_check = lim_is_emlsr_band_supported(session); 4481 4482 emlsr_allowed = emlsr_cap && emlsr_enabled && emlsr_band_check; 4483 4484 if (emlsr_allowed) { 4485 wlan_vdev_obj_lock(session->vdev); 4486 wlan_vdev_mlme_cap_set(session->vdev, WLAN_VDEV_C_EMLSR_CAP); 4487 wlan_vdev_obj_unlock(session->vdev); 4488 } else { 4489 wlan_vdev_obj_lock(session->vdev); 4490 wlan_vdev_mlme_cap_clear(session->vdev, WLAN_VDEV_C_EMLSR_CAP); 4491 wlan_vdev_obj_unlock(session->vdev); 4492 } 4493 } 4494 #else 4495 static void lim_fill_ml_info(struct cm_vdev_join_req *req, 4496 struct join_req *pe_join_req) 4497 { 4498 } 4499 4500 static void 4501 lim_copy_ml_partner_info_to_session(struct pe_session *session, 4502 struct cm_vdev_join_req *req) 4503 {} 4504 #endif 4505 4506 static QDF_STATUS 4507 lim_fill_session_params(struct mac_context *mac_ctx, 4508 struct pe_session *session, 4509 struct cm_vdev_join_req *req) 4510 { 4511 QDF_STATUS status; 4512 struct bss_description *bss_desc; 4513 uint32_t ie_len; 4514 uint32_t bss_len; 4515 struct join_req *pe_join_req; 4516 int32_t akm; 4517 struct mlme_legacy_priv *mlme_priv; 4518 uint32_t assoc_ie_len; 4519 bool eht_capab; 4520 4521 ie_len = util_scan_entry_ie_len(req->entry); 4522 bss_len = (uint16_t)(offsetof(struct bss_description, 4523 ieFields[0]) + ie_len); 4524 4525 session->lim_join_req = qdf_mem_malloc(sizeof(*session->lim_join_req) + 4526 bss_len); 4527 if (!session->lim_join_req) 4528 return QDF_STATUS_E_NOMEM; 4529 4530 pe_join_req = session->lim_join_req; 4531 bss_desc = &session->lim_join_req->bssDescription; 4532 pe_debug("Beacon/probe frame received:"); 4533 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, 4534 util_scan_entry_frame_ptr(req->entry), 4535 util_scan_entry_frame_len(req->entry)); 4536 4537 status = wlan_fill_bss_desc_from_scan_entry(mac_ctx, bss_desc, 4538 req->entry); 4539 if (QDF_IS_STATUS_ERROR(status)) { 4540 qdf_mem_free(session->lim_join_req); 4541 session->lim_join_req = NULL; 4542 return QDF_STATUS_E_FAILURE; 4543 } 4544 4545 akm = wlan_crypto_get_param(session->vdev, 4546 WLAN_CRYPTO_PARAM_KEY_MGMT); 4547 if (!req->entry->ssid.length && 4548 QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_OWE) && 4549 req->owe_trans_ssid.length) { 4550 req->entry->ssid = req->owe_trans_ssid; 4551 pe_debug("OWE transition ssid is " QDF_SSID_FMT, 4552 QDF_SSID_REF(req->entry->ssid.length, 4553 req->entry->ssid.ssid)); 4554 } 4555 4556 /* Copy the SSID from req to session entry */ 4557 session->ssId.length = req->entry->ssid.length; 4558 qdf_mem_copy(session->ssId.ssId, req->entry->ssid.ssid, 4559 session->ssId.length); 4560 session->ssidHidden = req->is_ssid_hidden; 4561 4562 status = lim_fill_pe_session(mac_ctx, session, bss_desc); 4563 if (QDF_IS_STATUS_ERROR(status)) { 4564 pe_err("Failed to fill pe session vdev id %d", 4565 session->vdev_id); 4566 qdf_mem_free(session->lim_join_req); 4567 session->lim_join_req = NULL; 4568 return QDF_STATUS_E_FAILURE; 4569 } 4570 4571 lim_copy_ml_partner_info_to_session(session, req); 4572 4573 pe_debug("Assoc IE len: %d", req->assoc_ie.len); 4574 if (req->assoc_ie.len) 4575 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, 4576 req->assoc_ie.ptr, req->assoc_ie.len); 4577 4578 assoc_ie_len = req->assoc_ie.len; 4579 status = lim_fill_crypto_params(mac_ctx, session, req); 4580 if (QDF_IS_STATUS_ERROR(status)) { 4581 pe_err("Error in handling RSNXE"); 4582 qdf_mem_free(session->lim_join_req); 4583 session->lim_join_req = NULL; 4584 return QDF_STATUS_E_FAILURE; 4585 } 4586 4587 /* Reset the SPMK global cache for non-SAE connection */ 4588 if (session->connected_akm != ANI_AKM_TYPE_SAE) { 4589 wlan_mlme_set_sae_single_pmk_bss_cap(mac_ctx->psoc, 4590 session->vdev_id, 4591 false); 4592 wlan_mlme_clear_sae_single_pmk_info(session->vdev, 4593 NULL); 4594 } 4595 4596 if (assoc_ie_len != req->assoc_ie.len) { 4597 pe_debug("After stripping Assoc IE len: %d", req->assoc_ie.len); 4598 if (req->assoc_ie.len) 4599 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, 4600 QDF_TRACE_LEVEL_DEBUG, 4601 req->assoc_ie.ptr, 4602 req->assoc_ie.len); 4603 } 4604 4605 qdf_mem_copy(pe_join_req->addIEAssoc.addIEdata, 4606 req->assoc_ie.ptr, req->assoc_ie.len); 4607 /* update assoc ie to cm */ 4608 cm_update_session_assoc_ie(mac_ctx->psoc, session->vdev_id, 4609 &req->assoc_ie); 4610 pe_join_req->addIEAssoc.length = req->assoc_ie.len; 4611 qdf_mem_copy(pe_join_req->addIEScan.addIEdata, 4612 req->scan_ie.ptr, req->scan_ie.len); 4613 pe_join_req->addIEScan.length = req->scan_ie.len; 4614 4615 mlme_priv = wlan_vdev_mlme_get_ext_hdl(session->vdev); 4616 if (!mlme_priv) { 4617 pe_err("Invalid mlme priv object"); 4618 qdf_mem_free(session->lim_join_req); 4619 session->lim_join_req = NULL; 4620 return QDF_STATUS_E_FAILURE; 4621 } 4622 qdf_mem_zero(mlme_priv->connect_info.ext_cap_ie, 4623 DOT11F_IE_EXTCAP_MAX_LEN + 2); 4624 4625 if (session->lim_join_req->addIEAssoc.length) { 4626 uint8_t *add_ie = NULL; 4627 uint16_t add_ie_len; 4628 4629 add_ie_len = session->lim_join_req->addIEAssoc.length; 4630 add_ie = qdf_mem_malloc(add_ie_len); 4631 if (!add_ie) { 4632 qdf_mem_free(session->lim_join_req); 4633 session->lim_join_req = NULL; 4634 return QDF_STATUS_E_FAILURE; 4635 } 4636 qdf_mem_copy(add_ie, 4637 session->lim_join_req->addIEAssoc.addIEdata, 4638 add_ie_len); 4639 4640 status = lim_strip_ie(mac_ctx, add_ie, &add_ie_len, 4641 DOT11F_EID_EXTCAP, ONE_BYTE, 4642 NULL, 0, 4643 mlme_priv->connect_info.ext_cap_ie, 4644 DOT11F_IE_EXTCAP_MAX_LEN); 4645 qdf_mem_free(add_ie); 4646 4647 if (QDF_IS_STATUS_ERROR(status)) { 4648 pe_err("Parsing of ext cap failed with status : %d", 4649 status); 4650 qdf_mem_zero(mlme_priv->connect_info.ext_cap_ie, 4651 DOT11F_IE_EXTCAP_MAX_LEN + 2); 4652 qdf_mem_free(session->lim_join_req); 4653 session->lim_join_req = NULL; 4654 return QDF_STATUS_E_FAILURE; 4655 } 4656 } 4657 4658 if (wlan_reg_is_6ghz_chan_freq(session->curr_op_freq)) { 4659 if (!lim_is_session_he_capable(session)) { 4660 pe_err("JOIN_REQ with invalid 6G security"); 4661 qdf_mem_free(session->lim_join_req); 4662 session->lim_join_req = NULL; 4663 return QDF_STATUS_E_FAILURE; 4664 } 4665 } 4666 4667 wlan_psoc_mlme_get_11be_capab(mac_ctx->psoc, &eht_capab); 4668 if (eht_capab && wlan_vdev_mlme_is_mlo_vdev(session->vdev)) 4669 lim_fill_ml_info(req, pe_join_req); 4670 4671 lim_set_emlsr_caps(mac_ctx, session); 4672 4673 return QDF_STATUS_SUCCESS; 4674 } 4675 4676 static QDF_STATUS 4677 lim_cm_handle_join_req(struct cm_vdev_join_req *req) 4678 { 4679 struct mac_context *mac_ctx; 4680 struct pe_session *pe_session; 4681 QDF_STATUS status; 4682 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); 4683 4684 if (!wma) 4685 return QDF_STATUS_E_INVAL; 4686 4687 if (!req) 4688 return QDF_STATUS_E_INVAL; 4689 4690 mac_ctx = cds_get_context(QDF_MODULE_ID_PE); 4691 4692 if (!mac_ctx) 4693 return QDF_STATUS_E_INVAL; 4694 4695 lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_JOIN_REQ_EVENT, NULL, 0, 0); 4696 4697 pe_session = lim_cm_create_session(mac_ctx, req); 4698 if (!pe_session) 4699 goto fail; 4700 4701 pe_session->cm_id = req->cm_id; 4702 status = lim_fill_session_params(mac_ctx, pe_session, req); 4703 4704 if (QDF_IS_STATUS_ERROR(status)) 4705 goto fail; 4706 4707 lim_dump_session_info(mac_ctx, pe_session); 4708 lim_dump_he_info(mac_ctx, pe_session); 4709 lim_dump_eht_info(pe_session); 4710 4711 if (lim_connect_skip_join_for_gc(pe_session)) { 4712 pe_session->beacon = 4713 qdf_mem_malloc(util_scan_entry_frame_len(req->entry)); 4714 if (!pe_session->beacon) 4715 goto fail; 4716 pe_session->bcnLen = util_scan_entry_frame_len(req->entry); 4717 qdf_mem_copy(pe_session->beacon, 4718 util_scan_entry_frame_ptr(req->entry), 4719 pe_session->bcnLen); 4720 } 4721 4722 status = lim_send_connect_req_to_mlm(pe_session); 4723 if (QDF_IS_STATUS_ERROR(status)) { 4724 pe_err("Failed to send mlm req vdev id %d", 4725 pe_session->vdev_id); 4726 goto fail; 4727 } 4728 4729 if (!wlan_vdev_mlme_is_mlo_link_vdev(pe_session->vdev)) 4730 lim_send_mlo_caps_ie(mac_ctx, pe_session->vdev, 4731 QDF_STA_MODE, 4732 pe_session->vdev_id); 4733 4734 return QDF_STATUS_SUCCESS; 4735 4736 fail: 4737 if (pe_session) 4738 pe_delete_session(mac_ctx, pe_session); 4739 status = wma_remove_bss_peer_before_join(wma, req->vdev_id, req); 4740 if (status == QDF_STATUS_E_PENDING) 4741 return status; 4742 lim_cm_send_connect_rsp(mac_ctx, NULL, req, CM_GENERIC_FAILURE, 4743 QDF_STATUS_E_FAILURE, 0, false); 4744 4745 return status; 4746 } 4747 4748 QDF_STATUS cm_process_join_req(struct scheduler_msg *msg) 4749 { 4750 struct cm_vdev_join_req *req; 4751 QDF_STATUS status; 4752 4753 if (!msg || !msg->bodyptr) { 4754 pe_err("msg or msg->bodyptr is NULL"); 4755 return QDF_STATUS_E_INVAL; 4756 } 4757 4758 req = msg->bodyptr; 4759 4760 status = lim_cm_handle_join_req(req); 4761 if (status != QDF_STATUS_E_PENDING) 4762 cm_free_join_req(req); 4763 4764 return status; 4765 } 4766 4767 static void lim_process_disconnect_sta(struct pe_session *session, 4768 struct scheduler_msg *msg) 4769 { 4770 if (QDF_IS_STATUS_SUCCESS( 4771 wlan_vdev_is_restart_progress(session->vdev))) 4772 wlan_vdev_mlme_sm_deliver_evt(session->vdev, 4773 WLAN_VDEV_SM_EV_RESTART_REQ_FAIL, 4774 sizeof(*msg), msg); 4775 else 4776 wlan_vdev_mlme_sm_deliver_evt(session->vdev, 4777 WLAN_VDEV_SM_EV_DOWN, 4778 sizeof(*msg), msg); 4779 } 4780 4781 static void lim_prepare_and_send_deauth(struct mac_context *mac_ctx, 4782 struct pe_session *pe_session, 4783 struct wlan_cm_vdev_discon_req *req) 4784 { 4785 struct scheduler_msg msg = {0}; 4786 struct deauth_req deauth_req = {0}; 4787 4788 deauth_req.messageType = eWNI_SME_DEAUTH_REQ; 4789 deauth_req.length = sizeof(deauth_req); 4790 deauth_req.vdev_id = req->req.vdev_id; 4791 qdf_mem_copy(deauth_req.bssid.bytes, pe_session->bssId, 4792 QDF_MAC_ADDR_SIZE); 4793 deauth_req.bssid = deauth_req.bssid; 4794 deauth_req.peer_macaddr = req->req.bssid; 4795 deauth_req.reasonCode = req->req.reason_code; 4796 4797 msg.bodyptr = &deauth_req; 4798 msg.type = eWNI_SME_DEAUTH_REQ; 4799 lim_process_disconnect_sta(pe_session, &msg); 4800 } 4801 4802 static void lim_prepare_and_send_disassoc(struct mac_context *mac_ctx, 4803 struct pe_session *pe_session, 4804 struct wlan_cm_vdev_discon_req *req) 4805 { 4806 struct scheduler_msg msg = {0}; 4807 struct disassoc_req disassoc_req = {0}; 4808 4809 disassoc_req.messageType = eWNI_SME_DISASSOC_REQ; 4810 disassoc_req.length = sizeof(disassoc_req); 4811 disassoc_req.sessionId = req->req.vdev_id; 4812 qdf_mem_copy(disassoc_req.bssid.bytes, pe_session->bssId, 4813 QDF_MAC_ADDR_SIZE); 4814 disassoc_req.peer_macaddr = disassoc_req.bssid; 4815 disassoc_req.reasonCode = req->req.reason_code; 4816 if (req->req.reason_code == REASON_FW_TRIGGERED_ROAM_FAILURE) { 4817 disassoc_req.process_ho_fail = true; 4818 disassoc_req.doNotSendOverTheAir = 1; 4819 } else if (wlan_cm_is_vdev_roam_reassoc_state(pe_session->vdev)) { 4820 disassoc_req.doNotSendOverTheAir = 1; 4821 disassoc_req.reasonCode = 4822 REASON_AUTHORIZED_ACCESS_LIMIT_REACHED; 4823 } else if (req->req.reason_code == CM_MLO_LINK_SWITCH_DISCONNECT) { 4824 disassoc_req.doNotSendOverTheAir = 1; 4825 } 4826 4827 msg.bodyptr = &disassoc_req; 4828 msg.type = eWNI_SME_DISASSOC_REQ; 4829 lim_process_disconnect_sta(pe_session, &msg); 4830 } 4831 4832 static void lim_process_nb_disconnect_req(struct mac_context *mac_ctx, 4833 struct pe_session *pe_session, 4834 struct wlan_cm_vdev_discon_req *req) 4835 { 4836 enum wlan_reason_code reason_code; 4837 bool enable_deauth_to_disassoc_map = false; 4838 4839 reason_code = req->req.reason_code; 4840 4841 switch (reason_code) { 4842 case REASON_IFACE_DOWN: 4843 case REASON_DEVICE_RECOVERY: 4844 case REASON_OPER_CHANNEL_BAND_CHANGE: 4845 case REASON_USER_TRIGGERED_ROAM_FAILURE: 4846 case REASON_CHANNEL_SWITCH_FAILED: 4847 case REASON_GATEWAY_REACHABILITY_FAILURE: 4848 case REASON_OPER_CHANNEL_DISABLED_INDOOR: 4849 /* Set reason REASON_DEAUTH_NETWORK_LEAVING for prop deauth */ 4850 req->req.reason_code = REASON_DEAUTH_NETWORK_LEAVING; 4851 fallthrough; 4852 case REASON_PREV_AUTH_NOT_VALID: 4853 case REASON_CLASS2_FRAME_FROM_NON_AUTH_STA: 4854 lim_prepare_and_send_deauth(mac_ctx, pe_session, req); 4855 break; 4856 case REASON_DEAUTH_NETWORK_LEAVING: 4857 wlan_mlme_get_enable_deauth_to_disassoc_map( 4858 mac_ctx->psoc, 4859 &enable_deauth_to_disassoc_map); 4860 if (enable_deauth_to_disassoc_map) { 4861 req->req.reason_code = REASON_DISASSOC_NETWORK_LEAVING; 4862 return lim_prepare_and_send_disassoc(mac_ctx, 4863 pe_session, req); 4864 } 4865 lim_prepare_and_send_deauth(mac_ctx, pe_session, req); 4866 break; 4867 default: 4868 /* Set reason REASON_UNSPEC_FAILURE for prop disassoc */ 4869 if (reason_code >= REASON_PROP_START && 4870 reason_code != REASON_FW_TRIGGERED_ROAM_FAILURE) 4871 req->req.reason_code = REASON_UNSPEC_FAILURE; 4872 lim_prepare_and_send_disassoc(mac_ctx, pe_session, req); 4873 } 4874 } 4875 4876 static void lim_process_sb_disconnect_req(struct mac_context *mac_ctx, 4877 struct pe_session *pe_session, 4878 struct wlan_cm_vdev_discon_req *req) 4879 { 4880 struct scheduler_msg msg = {0}; 4881 struct disassoc_cnf disassoc_cnf = {0}; 4882 4883 /* For SB disconnect smeState should be in Deauth state 4884 * One scenario where the smeState is not updated is when 4885 * AP sends deauth on link vdev and disconnect req is triggered 4886 */ 4887 if (pe_session->limSmeState == eLIM_SME_LINK_EST_STATE) 4888 pe_session->limSmeState = eLIM_SME_WT_DEAUTH_STATE; 4889 4890 if (pe_session->limSmeState == eLIM_SME_WT_DEAUTH_STATE) 4891 disassoc_cnf.messageType = eWNI_SME_DEAUTH_CNF; 4892 else 4893 disassoc_cnf.messageType = eWNI_SME_DISASSOC_CNF; 4894 disassoc_cnf.vdev_id = req->req.vdev_id; 4895 qdf_mem_copy(disassoc_cnf.bssid.bytes, pe_session->bssId, 4896 QDF_MAC_ADDR_SIZE); 4897 disassoc_cnf.length = sizeof(disassoc_cnf); 4898 disassoc_cnf.peer_macaddr = disassoc_cnf.bssid; 4899 4900 msg.bodyptr = &disassoc_cnf; 4901 msg.type = disassoc_cnf.messageType; 4902 lim_process_disconnect_sta(pe_session, &msg); 4903 } 4904 4905 static 4906 struct pe_session *lim_get_disconnect_session(struct mac_context *mac_ctx, 4907 struct wlan_cm_vdev_discon_req *req) 4908 { 4909 struct pe_session *session; 4910 uint8_t pe_session_id; 4911 4912 /* Try to find pe session with bssid */ 4913 session = pe_find_session_by_bssid_and_vdev_id(mac_ctx, 4914 req->req.bssid.bytes, 4915 req->req.vdev_id, 4916 &pe_session_id); 4917 /* 4918 * If bssid search fail try to find by vdev id, this can happen if 4919 * Roaming change the BSSID during disconnect was getting processed. 4920 */ 4921 if (!session) { 4922 session = pe_find_session_by_vdev_id(mac_ctx, req->req.vdev_id); 4923 if (session) 4924 pe_info("vdev_id %d cm_id 0x%x: using vdev id, session (%d) found for bssid " QDF_MAC_ADDR_FMT " [bssid in req " QDF_MAC_ADDR_FMT "] sme state %d mlm state %d", 4925 req->req.vdev_id, req->cm_id, session->peSessionId, 4926 QDF_MAC_ADDR_REF(session->bssId), 4927 QDF_MAC_ADDR_REF(req->req.bssid.bytes), 4928 session->limSmeState, session->limMlmState); 4929 } 4930 4931 /* 4932 * In LFR2.0 roaming scenario, if HO disconnect is completed but 4933 * NB disconnect is received before reassoc can start OR reassoc failure 4934 * lead to disconnect, new AP's session will be idle in wait reassoc 4935 * state and vdev in INIT state, so cleanup the session and send 4936 * response of disconnect complete. 4937 */ 4938 if (session && 4939 QDF_IS_STATUS_SUCCESS(wlan_vdev_mlme_is_init_state(session->vdev))) { 4940 pe_err("vdev_id %d cm_id 0x%x: sme state %d mlm state %d: vdev is in INIT state. Delete session", 4941 req->req.vdev_id, req->cm_id, session->limSmeState, 4942 session->limMlmState); 4943 pe_delete_session(mac_ctx, session); 4944 session = NULL; 4945 } 4946 4947 return session; 4948 } 4949 static QDF_STATUS 4950 lim_cm_handle_disconnect_req(struct wlan_cm_vdev_discon_req *req) 4951 { 4952 struct mac_context *mac_ctx; 4953 struct pe_session *pe_session; 4954 4955 if (!req) 4956 return QDF_STATUS_E_INVAL; 4957 4958 mac_ctx = cds_get_context(QDF_MODULE_ID_PE); 4959 if (!mac_ctx) 4960 return QDF_STATUS_E_INVAL; 4961 4962 pe_session = lim_get_disconnect_session(mac_ctx, req); 4963 if (!pe_session) { 4964 pe_err("vdev_id %d cm_id 0x%x: bssid " QDF_MAC_ADDR_FMT " : no session found", 4965 req->req.vdev_id, req->cm_id, 4966 QDF_MAC_ADDR_REF(req->req.bssid.bytes)); 4967 lim_cm_send_disconnect_rsp(mac_ctx, req->req.vdev_id); 4968 return QDF_STATUS_E_INVAL; 4969 } 4970 4971 if (req->req.source == CM_PEER_DISCONNECT || 4972 req->req.source == CM_SB_DISCONNECT || 4973 req->req.source == CM_MLO_LINK_SWITCH_DISCONNECT) 4974 lim_process_sb_disconnect_req(mac_ctx, pe_session, req); 4975 else 4976 lim_process_nb_disconnect_req(mac_ctx, pe_session, req); 4977 4978 return QDF_STATUS_SUCCESS; 4979 } 4980 4981 QDF_STATUS cm_process_disconnect_req(struct scheduler_msg *msg) 4982 { 4983 struct wlan_cm_vdev_discon_req *req; 4984 QDF_STATUS status; 4985 4986 if (!msg || !msg->bodyptr) { 4987 mlme_err("msg or msg->bodyptr is NULL"); 4988 return QDF_STATUS_E_INVAL; 4989 } 4990 4991 req = msg->bodyptr; 4992 4993 status = lim_cm_handle_disconnect_req(req); 4994 4995 qdf_mem_free(req); 4996 return status; 4997 } 4998 4999 #ifdef WLAN_FEATURE_11BE_MLO 5000 /** 5001 * wma_get_mld_info_sta() - get peer_mld_addr and assoc peer flag for sta 5002 * @req: cm_peer_create_req 5003 * @peer_mld_addr: peer mld mac addr 5004 * @is_assoc_peer: is assoc peer 5005 * 5006 * Return: void 5007 */ 5008 static void wma_get_mld_info_sta(struct cm_peer_create_req *req, 5009 uint8_t **peer_mld_addr, 5010 bool *is_assoc_peer) 5011 { 5012 if (!qdf_is_macaddr_zero(&req->mld_mac)) { 5013 *peer_mld_addr = req->mld_mac.bytes; 5014 *is_assoc_peer = req->is_assoc_peer; 5015 } else { 5016 *peer_mld_addr = NULL; 5017 *is_assoc_peer = false; 5018 } 5019 } 5020 #else 5021 static void wma_get_mld_info_sta(struct cm_peer_create_req *req, 5022 uint8_t **peer_mld_addr, 5023 bool *is_assoc_peer) 5024 { 5025 *peer_mld_addr = NULL; 5026 *is_assoc_peer = false; 5027 } 5028 #endif 5029 5030 QDF_STATUS cm_process_peer_create(struct scheduler_msg *msg) 5031 { 5032 struct cm_peer_create_req *req; 5033 QDF_STATUS status; 5034 uint8_t *peer_mld_addr = NULL; 5035 bool is_assoc_peer = false; 5036 5037 if (!msg || !msg->bodyptr) { 5038 mlme_err("msg or msg->bodyptr is NULL"); 5039 return QDF_STATUS_E_INVAL; 5040 } 5041 5042 req = msg->bodyptr; 5043 5044 wma_get_mld_info_sta(req, &peer_mld_addr, &is_assoc_peer); 5045 status = wma_add_bss_peer_sta(req->vdev_id, req->peer_mac.bytes, true, 5046 peer_mld_addr, is_assoc_peer); 5047 5048 qdf_mem_free(req); 5049 5050 return status; 5051 } 5052 5053 #ifdef WLAN_FEATURE_HOST_ROAM 5054 static void lim_handle_reassoc_req(struct cm_vdev_join_req *req) 5055 { 5056 struct mac_context *mac_ctx; 5057 struct pe_session *session_entry; 5058 uint8_t session_id; 5059 uint8_t vdev_id; 5060 uint32_t ie_len; 5061 uint32_t bss_len; 5062 struct join_req *reassoc_req = NULL; 5063 uint16_t caps; 5064 uint32_t val; 5065 tLimMlmReassocReq *mlm_reassoc_req; 5066 tSirResultCodes ret_code = eSIR_SME_SUCCESS; 5067 int8_t local_pwr_constraint = 0, reg_max = 0; 5068 uint32_t tele_bcn_en = 0; 5069 QDF_STATUS status; 5070 tDot11fBeaconIEs *ie_struct; 5071 ePhyChanBondState cb_mode; 5072 tSirMacCapabilityInfo *ap_cap_info; 5073 struct bss_description *bss_desc; 5074 uint8_t wmm_mode, value; 5075 bool is_pwr_constraint; 5076 int32_t ucast_cipher; 5077 int32_t auth_mode; 5078 int32_t akm; 5079 5080 if (!req) 5081 return; 5082 5083 mac_ctx = cds_get_context(QDF_MODULE_ID_PE); 5084 if (!mac_ctx) 5085 return; 5086 5087 vdev_id = req->vdev_id; 5088 session_entry = pe_find_session_by_bssid(mac_ctx, 5089 req->entry->bssid.bytes, 5090 &session_id); 5091 if (!session_entry) { 5092 pe_err("Session does not exist for: "QDF_MAC_ADDR_FMT, 5093 QDF_MAC_ADDR_REF(req->entry->bssid.bytes)); 5094 ret_code = eSIR_SME_INVALID_PARAMETERS; 5095 session_entry = pe_find_session_by_vdev_id(mac_ctx, vdev_id); 5096 if (session_entry) 5097 lim_handle_sme_join_result(mac_ctx, 5098 eSIR_SME_INVALID_PARAMETERS, 5099 STATUS_UNSPECIFIED_FAILURE, 5100 session_entry); 5101 goto end; 5102 } 5103 5104 if (session_entry->lim_join_req) { 5105 qdf_mem_free(session_entry->lim_join_req); 5106 session_entry->lim_join_req = NULL; 5107 } 5108 5109 session_entry->cm_id = req->cm_id; 5110 ie_len = util_scan_entry_ie_len(req->entry); 5111 bss_len = (uint16_t)(offsetof(struct bss_description, 5112 ieFields[0]) + ie_len); 5113 5114 reassoc_req = qdf_mem_malloc(sizeof(*session_entry->lim_join_req) + 5115 bss_len); 5116 if (!reassoc_req) { 5117 ret_code = eSIR_SME_RESOURCES_UNAVAILABLE; 5118 goto end; 5119 } 5120 lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_REASSOC_REQ_EVENT, 5121 session_entry, QDF_STATUS_SUCCESS, 5122 QDF_STATUS_SUCCESS); 5123 5124 pe_debug("Beacon/probe frame received:"); 5125 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, 5126 util_scan_entry_frame_ptr(req->entry), 5127 util_scan_entry_frame_len(req->entry)); 5128 5129 bss_desc = &reassoc_req->bssDescription; 5130 status = wlan_fill_bss_desc_from_scan_entry(mac_ctx, bss_desc, 5131 req->entry); 5132 if (QDF_IS_STATUS_ERROR(status)) { 5133 ret_code = eSIR_SME_RESOURCES_UNAVAILABLE; 5134 goto end; 5135 } 5136 /* Store the reassoc handle in the session Table */ 5137 session_entry->lim_join_req = reassoc_req; 5138 session_entry->pLimReAssocReq = reassoc_req; 5139 5140 status = wlan_get_parsed_bss_description_ies(mac_ctx, bss_desc, 5141 &ie_struct); 5142 if (QDF_IS_STATUS_ERROR(status)) { 5143 pe_err("IE parsing failed vdev id %d", 5144 session_entry->vdev_id); 5145 session_entry->lim_join_req = NULL; 5146 ret_code = eSIR_SME_RESOURCES_UNAVAILABLE; 5147 goto end; 5148 } 5149 pe_debug("Assoc IE len: %d", req->assoc_ie.len); 5150 if (req->assoc_ie.len) 5151 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, 5152 req->assoc_ie.ptr, req->assoc_ie.len); 5153 if (lim_is_rsn_profile(session_entry)) 5154 lim_fill_rsn_ie(mac_ctx, session_entry, req); 5155 else if (lim_is_wpa_profile(session_entry)) 5156 lim_fill_wpa_ie(mac_ctx, session_entry, req); 5157 else if (lim_is_wapi_profile(session_entry)) 5158 lim_fill_wapi_ie(mac_ctx, session_entry, req); 5159 5160 lim_strip_rsnx_ie(mac_ctx, session_entry, req); 5161 5162 if (lim_is_rsn_profile(session_entry) && 5163 !util_scan_entry_rsnxe(req->entry)) { 5164 pe_debug("Bss bcn has no RSNXE, strip if has"); 5165 status = lim_strip_ie(mac_ctx, req->assoc_ie.ptr, 5166 (uint16_t *)&req->assoc_ie.len, 5167 WLAN_ELEMID_RSNXE, ONE_BYTE, 5168 NULL, 0, NULL, 0); 5169 if (QDF_IS_STATUS_ERROR(status)) 5170 pe_err("Strip RNSXE failed"); 5171 } 5172 5173 pe_debug("After stripping Assoc IE len: %d", req->assoc_ie.len); 5174 if (req->assoc_ie.len) 5175 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, 5176 req->assoc_ie.ptr, req->assoc_ie.len); 5177 qdf_mem_copy(reassoc_req->addIEAssoc.addIEdata, 5178 req->assoc_ie.ptr, req->assoc_ie.len); 5179 reassoc_req->addIEAssoc.length = req->assoc_ie.len; 5180 /* update assoc ie to cm */ 5181 cm_update_session_assoc_ie(mac_ctx->psoc, vdev_id, &req->assoc_ie); 5182 ucast_cipher = wlan_crypto_get_param(session_entry->vdev, 5183 WLAN_CRYPTO_PARAM_UCAST_CIPHER); 5184 auth_mode = wlan_crypto_get_param(session_entry->vdev, 5185 WLAN_CRYPTO_PARAM_AUTH_MODE); 5186 akm = wlan_crypto_get_param(session_entry->vdev, 5187 WLAN_CRYPTO_PARAM_KEY_MGMT); 5188 ap_cap_info = (tSirMacCapabilityInfo *)&req->entry->cap_info.value; 5189 5190 lim_set_privacy(mac_ctx, ucast_cipher, auth_mode, akm, 5191 ap_cap_info->privacy); 5192 5193 if (session_entry->vhtCapability) { 5194 if (session_entry->opmode == QDF_STA_MODE) { 5195 session_entry->vht_config.su_beam_formee = 5196 mac_ctx->mlme_cfg->vht_caps.vht_cap_info.su_bformee; 5197 } else { 5198 session_entry->vht_config.su_beam_formee = 0; 5199 } 5200 session_entry->enableVhtpAid = 5201 mac_ctx->mlme_cfg->vht_caps.vht_cap_info.enable_paid; 5202 session_entry->enableVhtGid = 5203 mac_ctx->mlme_cfg->vht_caps.vht_cap_info.enable_gid; 5204 } 5205 5206 if (session_entry->nss == 1) 5207 session_entry->supported_nss_1x1 = true; 5208 5209 lim_check_oui_and_update_session(mac_ctx, session_entry, ie_struct); 5210 5211 session_entry->lim_reassoc_chan_freq = req->entry->channel.chan_freq; 5212 cb_mode = wlan_get_cb_mode(mac_ctx, 5213 session_entry->lim_reassoc_chan_freq, 5214 ie_struct, 5215 session_entry); 5216 session_entry->reAssocHtSupportedChannelWidthSet = cb_mode ? 1 : 0; 5217 session_entry->reAssocHtRecommendedTxWidthSet = 5218 session_entry->reAssocHtSupportedChannelWidthSet; 5219 session_entry->reAssocHtSecondaryChannelOffset = cb_mode; 5220 5221 mac_ctx->mlme_cfg->power.local_power_constraint = 5222 wlan_get_11h_power_constraint(mac_ctx, 5223 &ie_struct->PowerConstraints); 5224 if (session_entry->dot11mode == MLME_DOT11_MODE_11B) 5225 mac_ctx->mlme_cfg->feature_flags.enable_short_slot_time_11g = 0; 5226 else 5227 mac_ctx->mlme_cfg->feature_flags.enable_short_slot_time_11g = 5228 mac_ctx->mlme_cfg->ht_caps.short_slot_time_enabled; 5229 session_entry->enable_session_twt_support = 5230 lim_enable_twt(mac_ctx, ie_struct); 5231 5232 qdf_mem_free(ie_struct); 5233 5234 session_entry->send_smps_action = 5235 mac_ctx->roam.configParam.send_smps_action; 5236 session_entry->lim_join_req = NULL; 5237 5238 /* Reassociate request is expected in link established state only. */ 5239 if (session_entry->limSmeState != eLIM_SME_LINK_EST_STATE) { 5240 if (session_entry->limSmeState == eLIM_SME_WT_REASSOC_STATE) { 5241 /* 5242 * May be from 11r FT pre-auth. So lets check it 5243 * before we bail out 5244 */ 5245 pe_debug("Session in reassoc state is %d", 5246 session_entry->peSessionId); 5247 5248 /* Make sure its our preauth bssid */ 5249 if (qdf_mem_cmp(req->entry->bssid.bytes, 5250 session_entry->limReAssocbssId, 5251 QDF_MAC_ADDR_SIZE)) { 5252 pe_err("Requested BSSID: "QDF_MAC_ADDR_FMT " but bssId in reassoc state" QDF_MAC_ADDR_FMT, 5253 QDF_MAC_ADDR_REF(req->entry->bssid.bytes), 5254 QDF_MAC_ADDR_REF(session_entry->limReAssocbssId)); 5255 ret_code = eSIR_SME_INVALID_PARAMETERS; 5256 goto end; 5257 } 5258 5259 session_entry->vdev_id = vdev_id; 5260 mlm_reassoc_req = 5261 qdf_mem_malloc(sizeof(*mlm_reassoc_req)); 5262 if (!mlm_reassoc_req) { 5263 ret_code = eSIR_SME_RESOURCES_UNAVAILABLE; 5264 goto end; 5265 } 5266 5267 lim_dump_session_info(mac_ctx, session_entry); 5268 lim_dump_he_info(mac_ctx, session_entry); 5269 lim_dump_eht_info(session_entry); 5270 5271 /* Update PE sessionId */ 5272 mlm_reassoc_req->sessionId = session_entry->peSessionId; 5273 status = lim_send_ft_reassoc_req(session_entry, 5274 mlm_reassoc_req); 5275 if (QDF_IS_STATUS_ERROR(status)) { 5276 qdf_mem_free(mlm_reassoc_req); 5277 ret_code = eSIR_SME_REFUSED; 5278 goto end; 5279 } 5280 return; 5281 } 5282 /* 5283 * Should not have received eWNI_SME_REASSOC_REQ 5284 */ 5285 pe_err("received unexpected SME_REASSOC_REQ in state %X", 5286 session_entry->limSmeState); 5287 lim_print_sme_state(mac_ctx, LOGE, session_entry->limSmeState); 5288 5289 ret_code = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; 5290 goto end; 5291 } 5292 5293 qdf_mem_copy(session_entry->limReAssocbssId, req->entry->bssid.bytes, 5294 sizeof(tSirMacAddr)); 5295 5296 session_entry->limReassocBssCaps = req->entry->cap_info.value; 5297 reg_max = wlan_reg_get_channel_reg_power_for_freq( 5298 mac_ctx->pdev, session_entry->curr_op_freq); 5299 local_pwr_constraint = reg_max; 5300 5301 lim_extract_ap_capability(mac_ctx, (uint8_t *)bss_desc->ieFields, 5302 lim_get_ielen_from_bss_description(bss_desc), 5303 &session_entry->limReassocBssQosCaps, 5304 &session_entry->gLimCurrentBssUapsd, 5305 &local_pwr_constraint, session_entry, 5306 &is_pwr_constraint); 5307 if (is_pwr_constraint) 5308 local_pwr_constraint = reg_max - local_pwr_constraint; 5309 5310 session_entry->maxTxPower = QDF_MIN(reg_max, (local_pwr_constraint)); 5311 session_entry->max_11h_pwr = 5312 QDF_MIN(lim_get_cfg_max_tx_power(mac_ctx, 5313 bss_desc->chan_freq), 5314 MAX_TX_PWR_CAP); 5315 session_entry->min_11h_pwr = MIN_TX_PWR_CAP; 5316 if (!session_entry->max_11h_pwr) 5317 session_entry->max_11h_pwr = MAX_TX_PWR_CAP; 5318 5319 if (session_entry->max_11h_pwr > session_entry->maxTxPower) 5320 session_entry->max_11h_pwr = session_entry->maxTxPower; 5321 5322 pe_info("Reg max = %d, local pwr constraint = %d, max tx = %d", 5323 reg_max, local_pwr_constraint, session_entry->maxTxPower); 5324 /* Copy the SSID from session entry to local variable */ 5325 session_entry->limReassocSSID.length = req->entry->ssid.length; 5326 qdf_mem_copy(session_entry->limReassocSSID.ssId, 5327 req->entry->ssid.ssid, 5328 session_entry->limReassocSSID.length); 5329 5330 if (!session_entry->enable_session_twt_support) { 5331 status = wlan_mlme_get_wmm_mode(mac_ctx->psoc, &wmm_mode); 5332 if (!QDF_IS_STATUS_SUCCESS(status)) { 5333 pe_err("Get wmm_mode failed"); 5334 ret_code = eSIR_SME_INVALID_PARAMETERS; 5335 goto end; 5336 } else if (wmm_mode == 2) { 5337 /*QoS not enabled in cfg file */ 5338 session_entry->gUapsdPerAcBitmask = 0; 5339 } else { 5340 /*QoS enabled, update uapsd mask from cfg file */ 5341 status = wlan_mlme_get_wmm_uapsd_mask(mac_ctx->psoc, 5342 &value); 5343 if (QDF_IS_STATUS_ERROR(status)) { 5344 pe_err("Get uapsd_mask failed"); 5345 ret_code = eSIR_SME_INVALID_PARAMETERS; 5346 goto end; 5347 } else 5348 session_entry->gUapsdPerAcBitmask = value; 5349 } 5350 } 5351 5352 mlm_reassoc_req = qdf_mem_malloc(sizeof(tLimMlmReassocReq)); 5353 if (!mlm_reassoc_req) { 5354 ret_code = eSIR_SME_RESOURCES_UNAVAILABLE; 5355 goto end; 5356 } 5357 5358 qdf_mem_copy(mlm_reassoc_req->peerMacAddr, 5359 session_entry->limReAssocbssId, sizeof(tSirMacAddr)); 5360 5361 if (lim_get_capability_info(mac_ctx, &caps, session_entry) != 5362 QDF_STATUS_SUCCESS) 5363 pe_err("could not retrieve Capabilities value"); 5364 5365 lim_update_caps_info_for_bss(mac_ctx, &caps, 5366 req->entry->cap_info.value); 5367 pe_debug("Capabilities info Reassoc: 0x%X", caps); 5368 5369 mlm_reassoc_req->capabilityInfo = caps; 5370 5371 /* Update PE session_id */ 5372 mlm_reassoc_req->sessionId = session_id; 5373 5374 /* 5375 * If telescopic beaconing is enabled, set listen interval to 5376 * CFG_TELE_BCN_MAX_LI 5377 */ 5378 5379 tele_bcn_en = mac_ctx->mlme_cfg->sap_cfg.tele_bcn_wakeup_en; 5380 5381 if (tele_bcn_en) 5382 val = mac_ctx->mlme_cfg->sap_cfg.tele_bcn_max_li; 5383 else 5384 val = mac_ctx->mlme_cfg->sap_cfg.listen_interval; 5385 5386 mlm_reassoc_req->listenInterval = (uint16_t) val; 5387 if (mac_ctx->mlme_cfg->gen.enabled_11h && 5388 ap_cap_info->spectrumMgt && bss_desc->nwType == eSIR_11A_NW_TYPE) 5389 session_entry->spectrumMgtEnabled = true; 5390 5391 /* Enable the spectrum management if this is a DFS channel */ 5392 if (session_entry->country_info_present && 5393 lim_isconnected_on_dfs_freq( 5394 mac_ctx, session_entry->curr_op_freq)) 5395 session_entry->spectrumMgtEnabled = true; 5396 5397 session_entry->limPrevSmeState = session_entry->limSmeState; 5398 session_entry->limSmeState = eLIM_SME_WT_REASSOC_STATE; 5399 5400 MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, session_entry->peSessionId, 5401 session_entry->limSmeState)); 5402 5403 lim_dump_session_info(mac_ctx, session_entry); 5404 lim_dump_he_info(mac_ctx, session_entry); 5405 lim_dump_eht_info(session_entry); 5406 5407 status = lim_send_reassoc_req(session_entry, mlm_reassoc_req); 5408 if (QDF_IS_STATUS_ERROR(status)) { 5409 qdf_mem_free(mlm_reassoc_req); 5410 ret_code = eSIR_SME_REFUSED; 5411 goto end; 5412 } 5413 5414 return; 5415 end: 5416 if (reassoc_req) { 5417 qdf_mem_free(reassoc_req); 5418 if (session_entry) 5419 session_entry->pLimReAssocReq = NULL; 5420 } 5421 5422 /* 5423 * Send Reassoc failure response to host 5424 * (note session_entry may be NULL, but that's OK) 5425 */ 5426 lim_send_sme_join_reassoc_rsp(mac_ctx, eWNI_SME_REASSOC_RSP, 5427 ret_code, STATUS_UNSPECIFIED_FAILURE, 5428 session_entry, vdev_id); 5429 } 5430 5431 QDF_STATUS cm_process_reassoc_req(struct scheduler_msg *msg) 5432 { 5433 struct cm_vdev_join_req *req; 5434 5435 if (!msg || !msg->bodyptr) { 5436 mlme_err("msg or msg->bodyptr is NULL"); 5437 return QDF_STATUS_E_INVAL; 5438 } 5439 5440 req = msg->bodyptr; 5441 5442 lim_handle_reassoc_req(req); 5443 5444 cm_free_join_req(req); 5445 5446 return QDF_STATUS_SUCCESS; 5447 } 5448 5449 static QDF_STATUS 5450 lim_fill_preauth_req_dot11_mode(struct mac_context *mac_ctx, 5451 tpSirFTPreAuthReq req, 5452 uint8_t vdev_id) 5453 { 5454 QDF_STATUS status; 5455 tDot11fBeaconIEs *ie_struct; 5456 enum mlme_dot11_mode self_dot11_mode; 5457 enum mlme_dot11_mode bss_dot11_mode; 5458 enum mlme_dot11_mode intersected_mode; 5459 struct bss_description *bss_desc = req->pbssDescription; 5460 5461 status = wlan_get_parsed_bss_description_ies(mac_ctx, bss_desc, 5462 &ie_struct); 5463 if (QDF_IS_STATUS_ERROR(status)) { 5464 mlme_err("IE parsing failed"); 5465 return QDF_STATUS_E_FAILURE; 5466 } 5467 5468 self_dot11_mode = lim_get_self_dot11_mode(mac_ctx, QDF_STA_MODE, 5469 vdev_id); 5470 /* if user set dot11 mode by cmd, need to do intersect first */ 5471 self_dot11_mode = 5472 lim_intersect_user_dot11_mode(mac_ctx, QDF_STA_MODE, 5473 vdev_id, self_dot11_mode); 5474 5475 bss_dot11_mode = lim_get_bss_dot11_mode(mac_ctx, bss_desc, ie_struct); 5476 5477 status = lim_get_intersected_dot11_mode_sta_ap(mac_ctx, self_dot11_mode, 5478 bss_dot11_mode, 5479 &intersected_mode, 5480 ie_struct, bss_desc); 5481 if (QDF_IS_STATUS_ERROR(status)) { 5482 qdf_mem_free(ie_struct); 5483 return status; 5484 } 5485 5486 req->dot11mode = intersected_mode; 5487 pe_debug("vdev %d self dot11mode %d bss_dot11 mode %d intersected_mode %d", 5488 vdev_id, self_dot11_mode, bss_dot11_mode, intersected_mode); 5489 5490 qdf_mem_free(ie_struct); 5491 return status; 5492 } 5493 5494 static QDF_STATUS lim_cm_handle_preauth_req(struct wlan_preauth_req *req) 5495 { 5496 struct mac_context *mac_ctx; 5497 struct wlan_objmgr_vdev *vdev; 5498 struct scan_cache_entry *scan_entry; 5499 struct bss_description *bss_desc = NULL; 5500 uint32_t ie_len, bss_len; 5501 uint8_t vdev_id; 5502 struct mlme_legacy_priv *mlme_priv; 5503 QDF_STATUS status = QDF_STATUS_SUCCESS; 5504 tpSirFTPreAuthReq preauth_req = NULL; 5505 bool buf_consumed = true; 5506 5507 if (!req) 5508 return QDF_STATUS_E_INVAL; 5509 5510 mac_ctx = cds_get_context(QDF_MODULE_ID_PE); 5511 if (!mac_ctx) 5512 return QDF_STATUS_E_INVAL; 5513 5514 ie_len = util_scan_entry_ie_len(req->entry); 5515 bss_len = (uint16_t)(offsetof(struct bss_description, 5516 ieFields[0]) + ie_len); 5517 5518 bss_desc = qdf_mem_malloc(sizeof(*bss_desc) + bss_len); 5519 if (!bss_desc) { 5520 status = QDF_STATUS_E_NOMEM; 5521 goto end; 5522 } 5523 5524 scan_entry = req->entry; 5525 status = wlan_fill_bss_desc_from_scan_entry(mac_ctx, bss_desc, 5526 scan_entry); 5527 if (QDF_IS_STATUS_ERROR(status)) 5528 goto end; 5529 5530 preauth_req = qdf_mem_malloc(sizeof(tSirFTPreAuthReq)); 5531 if (!preauth_req) { 5532 status = QDF_STATUS_E_NOMEM; 5533 goto end; 5534 } 5535 5536 vdev_id = req->vdev_id; 5537 preauth_req->pbssDescription = bss_desc; 5538 status = lim_fill_preauth_req_dot11_mode(mac_ctx, preauth_req, vdev_id); 5539 if (QDF_IS_STATUS_ERROR(status)) { 5540 pe_err("dot11mode doesn't get proper filling"); 5541 goto end; 5542 } 5543 5544 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(mac_ctx->pdev, vdev_id, 5545 WLAN_MLME_CM_ID); 5546 if (!vdev) { 5547 status = QDF_STATUS_E_FAILURE; 5548 goto end; 5549 } 5550 5551 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 5552 if (!mlme_priv) { 5553 status = QDF_STATUS_E_FAILURE; 5554 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 5555 goto end; 5556 } 5557 qdf_mem_copy(preauth_req->ft_ies, 5558 mlme_priv->connect_info.ft_info.auth_ft_ie, 5559 mlme_priv->connect_info.ft_info.auth_ie_len); 5560 preauth_req->ft_ies_length = 5561 mlme_priv->connect_info.ft_info.auth_ie_len; 5562 preauth_req->pre_auth_channel_freq = scan_entry->channel.chan_freq; 5563 wlan_mlme_get_bssid_vdev_id( 5564 mac_ctx->pdev, vdev_id, 5565 (struct qdf_mac_addr *)&preauth_req->currbssId); 5566 qdf_mem_copy(&preauth_req->preAuthbssId, 5567 scan_entry->bssid.bytes, QDF_MAC_ADDR_SIZE); 5568 5569 wlan_vdev_obj_lock(vdev); 5570 qdf_mem_copy(&preauth_req->self_mac_addr, 5571 wlan_vdev_mlme_get_macaddr(vdev), QDF_MAC_ADDR_SIZE); 5572 wlan_vdev_obj_unlock(vdev); 5573 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 5574 5575 buf_consumed = lim_process_ft_pre_auth_req(mac_ctx, preauth_req); 5576 5577 end: 5578 if (buf_consumed) { 5579 if (bss_desc) 5580 qdf_mem_free(bss_desc); 5581 if (preauth_req) 5582 qdf_mem_free(preauth_req); 5583 } 5584 5585 return status; 5586 } 5587 5588 QDF_STATUS cm_process_preauth_req(struct scheduler_msg *msg) 5589 { 5590 struct wlan_preauth_req *req; 5591 QDF_STATUS status; 5592 5593 if (!msg || !msg->bodyptr) { 5594 mlme_err("msg or msg->bodyptr is NULL"); 5595 return QDF_STATUS_E_INVAL; 5596 } 5597 5598 req = msg->bodyptr; 5599 5600 status = lim_cm_handle_preauth_req(req); 5601 5602 cm_free_preauth_req(req); 5603 return status; 5604 } 5605 #endif 5606 5607 static uint8_t lim_get_num_tpe_octets(uint8_t max_transmit_power_count) 5608 { 5609 if (!max_transmit_power_count) 5610 return max_transmit_power_count; 5611 5612 return 1 << (max_transmit_power_count - 1); 5613 } 5614 5615 void lim_parse_tpe_ie(struct mac_context *mac, struct pe_session *session, 5616 tDot11fIEtransmit_power_env *tpe_ies, uint8_t num_tpe_ies, 5617 tDot11fIEhe_op *he_op, bool *has_tpe_updated) 5618 { 5619 struct vdev_mlme_obj *vdev_mlme; 5620 uint8_t i, local_tpe_count = 0, reg_tpe_count = 0, num_octets; 5621 uint8_t psd_index = 0, non_psd_index = 0; 5622 uint8_t bw_num; 5623 uint16_t bw_val, ch_width; 5624 qdf_freq_t curr_op_freq, curr_freq; 5625 enum reg_6g_client_type client_mobility_type; 5626 struct ch_params ch_params = {0}; 5627 tDot11fIEtransmit_power_env single_tpe, local_tpe, reg_tpe; 5628 /* 5629 * PSD is power spectral density, incoming TPE could contain 5630 * non PSD info, or PSD info, or both, so need to keep track of them 5631 */ 5632 bool non_psd_set = false, psd_set = false; 5633 bool both_tpe_present = false; 5634 bool local_eirp_set = false, local_psd_set = false; 5635 bool reg_eirp_set = false, reg_psd_set = false; 5636 uint8_t local_eirp_idx = 0, local_psd_idx = 0; 5637 uint8_t reg_eirp_idx = 0, reg_psd_idx = 0; 5638 uint8_t min_count = 0; 5639 5640 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(session->vdev); 5641 if (!vdev_mlme) 5642 return; 5643 5644 if (session->sta_follows_sap_power) { 5645 pe_debug_rl("STA operates in 6 GHz power of SAP, do not update STA power"); 5646 return; 5647 } 5648 5649 vdev_mlme->reg_tpc_obj.num_pwr_levels = 0; 5650 *has_tpe_updated = false; 5651 5652 wlan_reg_get_cur_6g_client_type(mac->pdev, &client_mobility_type); 5653 5654 for (i = 0; i < num_tpe_ies; i++) { 5655 single_tpe = tpe_ies[i]; 5656 if (single_tpe.present && 5657 (single_tpe.max_tx_pwr_category == client_mobility_type)) { 5658 if (single_tpe.max_tx_pwr_interpret == LOCAL_EIRP || 5659 single_tpe.max_tx_pwr_interpret == LOCAL_EIRP_PSD) 5660 local_tpe_count++; 5661 else if (single_tpe.max_tx_pwr_interpret == 5662 REGULATORY_CLIENT_EIRP || 5663 single_tpe.max_tx_pwr_interpret == 5664 REGULATORY_CLIENT_EIRP_PSD) 5665 reg_tpe_count++; 5666 } 5667 } 5668 5669 if (!reg_tpe_count && !local_tpe_count) 5670 return; 5671 else if (reg_tpe_count && local_tpe_count) 5672 both_tpe_present = true; 5673 5674 for (i = 0; i < num_tpe_ies; i++) { 5675 single_tpe = tpe_ies[i]; 5676 if (single_tpe.present && 5677 (single_tpe.max_tx_pwr_category == client_mobility_type)) { 5678 if (single_tpe.max_tx_pwr_interpret == LOCAL_EIRP) { 5679 non_psd_index = i; 5680 non_psd_set = true; 5681 local_eirp_idx = non_psd_index; 5682 local_eirp_set = non_psd_set; 5683 } else if (single_tpe.max_tx_pwr_interpret == 5684 LOCAL_EIRP_PSD) { 5685 psd_index = i; 5686 psd_set = true; 5687 local_psd_idx = psd_index; 5688 local_psd_set = psd_set; 5689 } else if (single_tpe.max_tx_pwr_interpret == 5690 REGULATORY_CLIENT_EIRP) { 5691 non_psd_index = i; 5692 non_psd_set = true; 5693 reg_eirp_idx = non_psd_index; 5694 reg_eirp_set = non_psd_set; 5695 } else if (single_tpe.max_tx_pwr_interpret == 5696 REGULATORY_CLIENT_EIRP_PSD) { 5697 psd_index = i; 5698 psd_set = true; 5699 reg_psd_idx = psd_index; 5700 reg_psd_set = psd_set; 5701 } 5702 } 5703 } 5704 5705 curr_op_freq = session->curr_op_freq; 5706 bw_val = wlan_reg_get_bw_value(session->ch_width); 5707 5708 if (non_psd_set && !psd_set) { 5709 single_tpe = tpe_ies[non_psd_index]; 5710 vdev_mlme->reg_tpc_obj.is_psd_power = false; 5711 vdev_mlme->reg_tpc_obj.eirp_power = 0; 5712 bw_num = sizeof(get_next_higher_bw) / 5713 sizeof(get_next_higher_bw[0]); 5714 if (single_tpe.max_tx_pwr_count >= bw_num) { 5715 pe_debug("tx pwr count: %d, larger than bw num: %d", 5716 single_tpe.max_tx_pwr_count, bw_num); 5717 single_tpe.max_tx_pwr_count = bw_num - 1; 5718 } 5719 vdev_mlme->reg_tpc_obj.num_pwr_levels = 5720 single_tpe.max_tx_pwr_count + 1; 5721 5722 ch_params.ch_width = CH_WIDTH_20MHZ; 5723 5724 for (i = 0; i < single_tpe.max_tx_pwr_count + 1 && 5725 (ch_params.ch_width != CH_WIDTH_INVALID); i++) { 5726 wlan_reg_set_channel_params_for_pwrmode( 5727 mac->pdev, 5728 curr_op_freq, 0, 5729 &ch_params, 5730 REG_CURRENT_PWR_MODE); 5731 if (vdev_mlme->reg_tpc_obj.tpe[i] != 5732 single_tpe.tx_power[i] || 5733 vdev_mlme->reg_tpc_obj.frequency[i] != 5734 ch_params.mhz_freq_seg0) 5735 *has_tpe_updated = true; 5736 vdev_mlme->reg_tpc_obj.frequency[i] = 5737 ch_params.mhz_freq_seg0; 5738 vdev_mlme->reg_tpc_obj.tpe[i] = single_tpe.tx_power[i]; 5739 if (ch_params.ch_width != CH_WIDTH_INVALID) 5740 ch_params.ch_width = 5741 get_next_higher_bw[ch_params.ch_width]; 5742 } 5743 } 5744 5745 if (psd_set) { 5746 single_tpe = tpe_ies[psd_index]; 5747 vdev_mlme->reg_tpc_obj.is_psd_power = true; 5748 num_octets = 5749 lim_get_num_tpe_octets(single_tpe.max_tx_pwr_count); 5750 vdev_mlme->reg_tpc_obj.num_pwr_levels = num_octets; 5751 5752 ch_params.ch_width = session->ch_width; 5753 wlan_reg_set_channel_params_for_pwrmode(mac->pdev, curr_op_freq, 5754 0, &ch_params, 5755 REG_CURRENT_PWR_MODE); 5756 5757 if (ch_params.mhz_freq_seg1) 5758 curr_freq = ch_params.mhz_freq_seg1 - bw_val / 2 + 10; 5759 else 5760 curr_freq = ch_params.mhz_freq_seg0 - bw_val / 2 + 10; 5761 5762 if (!num_octets) { 5763 if (!he_op->oper_info_6g_present) 5764 ch_width = session->ch_width; 5765 else 5766 ch_width = he_op->oper_info_6g.info.ch_width; 5767 num_octets = lim_get_num_pwr_levels(true, 5768 session->ch_width); 5769 vdev_mlme->reg_tpc_obj.num_pwr_levels = num_octets; 5770 for (i = 0; i < num_octets; i++) { 5771 if (vdev_mlme->reg_tpc_obj.tpe[i] != 5772 single_tpe.tx_power[0] || 5773 vdev_mlme->reg_tpc_obj.frequency[i] != 5774 curr_freq) 5775 *has_tpe_updated = true; 5776 vdev_mlme->reg_tpc_obj.frequency[i] = curr_freq; 5777 curr_freq += 20; 5778 vdev_mlme->reg_tpc_obj.tpe[i] = 5779 single_tpe.tx_power[0]; 5780 } 5781 } else { 5782 for (i = 0; i < num_octets; i++) { 5783 if (vdev_mlme->reg_tpc_obj.tpe[i] != 5784 single_tpe.tx_power[i] || 5785 vdev_mlme->reg_tpc_obj.frequency[i] != 5786 curr_freq) 5787 *has_tpe_updated = true; 5788 vdev_mlme->reg_tpc_obj.frequency[i] = curr_freq; 5789 curr_freq += 20; 5790 vdev_mlme->reg_tpc_obj.tpe[i] = 5791 single_tpe.tx_power[i]; 5792 } 5793 } 5794 } 5795 5796 if (non_psd_set) { 5797 single_tpe = tpe_ies[non_psd_index]; 5798 vdev_mlme->reg_tpc_obj.eirp_power = 5799 single_tpe.tx_power[single_tpe.max_tx_pwr_count]; 5800 vdev_mlme->reg_tpc_obj.is_psd_power = false; 5801 } 5802 5803 if (both_tpe_present) { 5804 pe_debug("Local: eirp: %d psd: %d, Regulatory: eirp: %d psd %d", 5805 local_eirp_set, local_psd_set, reg_eirp_set, 5806 reg_psd_set); 5807 if (local_eirp_set && reg_eirp_set) { 5808 local_tpe = tpe_ies[local_eirp_idx]; 5809 reg_tpe = tpe_ies[reg_eirp_idx]; 5810 } else if (local_psd_set && reg_psd_set) { 5811 local_tpe = tpe_ies[local_psd_idx]; 5812 reg_tpe = tpe_ies[reg_psd_idx]; 5813 } else { 5814 return; 5815 } 5816 5817 min_count = QDF_MIN(local_tpe.max_tx_pwr_count, 5818 reg_tpe.max_tx_pwr_count); 5819 for (i = 0; i < min_count + 1; i++) { 5820 if (vdev_mlme->reg_tpc_obj.tpe[i] != 5821 QDF_MIN(local_tpe.tx_power[i], reg_tpe.tx_power[i])) 5822 *has_tpe_updated = true; 5823 vdev_mlme->reg_tpc_obj.tpe[i] = 5824 QDF_MIN(local_tpe.tx_power[i], 5825 reg_tpe.tx_power[i]); 5826 pe_debug("TPE: Local: %d, Reg: %d, power updated: %d", 5827 local_tpe.tx_power[i], reg_tpe.tx_power[i], 5828 *has_tpe_updated); 5829 } 5830 } 5831 } 5832 5833 void lim_process_tpe_ie_from_beacon(struct mac_context *mac, 5834 struct pe_session *session, 5835 struct bss_description *bss_desc, 5836 bool *has_tpe_updated) 5837 { 5838 tDot11fBeaconIEs *bcn_ie; 5839 uint32_t buf_len; 5840 uint8_t *buf; 5841 int status; 5842 5843 bcn_ie = qdf_mem_malloc(sizeof(*bcn_ie)); 5844 if (!bcn_ie) 5845 return; 5846 5847 buf_len = lim_get_ielen_from_bss_description(bss_desc); 5848 buf = (uint8_t *)bss_desc->ieFields; 5849 status = dot11f_unpack_beacon_i_es(mac, buf, buf_len, bcn_ie, false); 5850 if (DOT11F_FAILED(status)) { 5851 pe_err("Failed to parse Beacon IEs (0x%08x, %d bytes):", 5852 status, buf_len); 5853 qdf_mem_free(bcn_ie); 5854 return; 5855 } else if (DOT11F_WARNED(status)) { 5856 pe_debug("warnings (0x%08x, %d bytes):", status, buf_len); 5857 } 5858 5859 status = lim_strip_and_decode_eht_op(buf, buf_len, &bcn_ie->eht_op, 5860 bcn_ie->VHTOperation, 5861 bcn_ie->he_op, 5862 bcn_ie->HTInfo); 5863 if (status != QDF_STATUS_SUCCESS) { 5864 pe_err("Failed to extract eht op"); 5865 return; 5866 } 5867 5868 status = lim_strip_and_decode_eht_cap(buf, buf_len, &bcn_ie->eht_cap, 5869 bcn_ie->he_cap, 5870 session->curr_op_freq); 5871 if (status != QDF_STATUS_SUCCESS) { 5872 pe_err("Failed to extract eht cap"); 5873 return; 5874 } 5875 5876 lim_parse_tpe_ie(mac, session, bcn_ie->transmit_power_env, 5877 bcn_ie->num_transmit_power_env, &bcn_ie->he_op, 5878 has_tpe_updated); 5879 qdf_mem_free(bcn_ie); 5880 } 5881 5882 uint32_t lim_get_num_pwr_levels(bool is_psd, 5883 enum phy_ch_width ch_width) 5884 { 5885 uint32_t num_pwr_levels = 0; 5886 5887 if (is_psd) { 5888 switch (ch_width) { 5889 case CH_WIDTH_20MHZ: 5890 num_pwr_levels = 1; 5891 break; 5892 case CH_WIDTH_40MHZ: 5893 num_pwr_levels = 2; 5894 break; 5895 case CH_WIDTH_80MHZ: 5896 num_pwr_levels = 4; 5897 break; 5898 case CH_WIDTH_160MHZ: 5899 num_pwr_levels = 8; 5900 break; 5901 case CH_WIDTH_320MHZ: 5902 num_pwr_levels = 16; 5903 break; 5904 default: 5905 pe_err_rl("Invalid channel width"); 5906 return 0; 5907 } 5908 } else { 5909 switch (ch_width) { 5910 case CH_WIDTH_20MHZ: 5911 num_pwr_levels = 1; 5912 break; 5913 case CH_WIDTH_40MHZ: 5914 num_pwr_levels = 2; 5915 break; 5916 case CH_WIDTH_80MHZ: 5917 num_pwr_levels = 3; 5918 break; 5919 case CH_WIDTH_160MHZ: 5920 num_pwr_levels = 4; 5921 break; 5922 case CH_WIDTH_320MHZ: 5923 num_pwr_levels = 5; 5924 break; 5925 default: 5926 pe_err_rl("Invalid channel width"); 5927 return 0; 5928 } 5929 } 5930 return num_pwr_levels; 5931 } 5932 5933 uint8_t lim_get_max_tx_power(struct mac_context *mac, 5934 struct vdev_mlme_obj *mlme_obj) 5935 { 5936 uint8_t max_tx_power = 0; 5937 uint8_t tx_power; 5938 5939 if (wlan_reg_get_fcc_constraint(mac->pdev, 5940 mlme_obj->reg_tpc_obj.frequency[0])) 5941 return mlme_obj->reg_tpc_obj.reg_max[0]; 5942 5943 tx_power = QDF_MIN(mlme_obj->reg_tpc_obj.reg_max[0], 5944 mlme_obj->reg_tpc_obj.ap_constraint_power); 5945 5946 if (tx_power >= MIN_TX_PWR_CAP && tx_power <= MAX_TX_PWR_CAP) 5947 max_tx_power = tx_power; 5948 else if (tx_power < MIN_TX_PWR_CAP) 5949 max_tx_power = MIN_TX_PWR_CAP; 5950 else 5951 max_tx_power = MAX_TX_PWR_CAP; 5952 5953 return max_tx_power; 5954 } 5955 5956 void lim_calculate_tpc(struct mac_context *mac, 5957 struct pe_session *session) 5958 { 5959 bool is_psd_power = false; 5960 bool is_tpe_present = false, is_6ghz_freq = false; 5961 uint8_t i = 0; 5962 int8_t max_tx_power; 5963 uint16_t reg_max = 0, psd_power = 0; 5964 uint16_t tx_power_within_bw = 0, psd_power_within_bw = 0; 5965 uint16_t local_constraint, bw_val = 0; 5966 uint32_t num_pwr_levels, ap_power_type_6g = 0; 5967 qdf_freq_t oper_freq, start_freq = 0; 5968 struct ch_params ch_params = {0}; 5969 struct vdev_mlme_obj *mlme_obj; 5970 int8_t tpe_power; 5971 bool skip_tpe = false; 5972 bool rf_test_mode = false; 5973 bool safe_mode_enable = false; 5974 5975 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(session->vdev); 5976 if (!mlme_obj) { 5977 pe_err("vdev component object is NULL"); 5978 return; 5979 } 5980 5981 if (session->sta_follows_sap_power) { 5982 pe_debug_rl("STA operates in 6 GHz power of SAP, do not update STA power"); 5983 return; 5984 } 5985 5986 oper_freq = session->curr_op_freq; 5987 bw_val = wlan_reg_get_bw_value(session->ch_width); 5988 5989 ch_params.ch_width = session->ch_width; 5990 /* start frequency calculation */ 5991 wlan_reg_set_channel_params_for_pwrmode(mac->pdev, oper_freq, 0, 5992 &ch_params, 5993 REG_CURRENT_PWR_MODE); 5994 if (ch_params.mhz_freq_seg1) 5995 start_freq = ch_params.mhz_freq_seg1 - bw_val / 2 + 10; 5996 else 5997 start_freq = ch_params.mhz_freq_seg0 - bw_val / 2 + 10; 5998 5999 if (!wlan_reg_is_6ghz_chan_freq(oper_freq)) { 6000 reg_max = wlan_reg_get_channel_reg_power_for_freq(mac->pdev, 6001 oper_freq); 6002 skip_tpe = wlan_mlme_skip_tpe(mac->psoc); 6003 } else { 6004 is_6ghz_freq = true; 6005 /* Power mode calculation for 6 GHz STA*/ 6006 if (LIM_IS_STA_ROLE(session)) { 6007 ap_power_type_6g = session->best_6g_power_type; 6008 wlan_mlme_get_safe_mode_enable(mac->psoc, 6009 &safe_mode_enable); 6010 wlan_mlme_is_rf_test_mode_enabled(mac->psoc, 6011 &rf_test_mode); 6012 /* 6013 * set LPI power if safe mode is enabled OR RF test 6014 * mode is enabled. 6015 */ 6016 if (rf_test_mode || safe_mode_enable) 6017 ap_power_type_6g = REG_INDOOR_AP; 6018 } 6019 } 6020 6021 if (mlme_obj->reg_tpc_obj.num_pwr_levels) { 6022 is_tpe_present = true; 6023 num_pwr_levels = mlme_obj->reg_tpc_obj.num_pwr_levels; 6024 is_psd_power = mlme_obj->reg_tpc_obj.is_psd_power; 6025 } else { 6026 /** 6027 * Set is_psd_power based on reg channel list if it is a 6 GHz 6028 * channel and TPE IE is absent. 6029 */ 6030 if (is_6ghz_freq) 6031 is_psd_power = wlan_reg_is_6g_psd_power(mac->pdev); 6032 num_pwr_levels = lim_get_num_pwr_levels(is_psd_power, 6033 session->ch_width); 6034 } 6035 6036 if (num_pwr_levels > MAX_NUM_PWR_LEVELS) { 6037 pe_debug("reset num_pwr_levels %d to MAX_NUM_PWR_LEVELS %d", 6038 num_pwr_levels, MAX_NUM_PWR_LEVELS); 6039 num_pwr_levels = MAX_NUM_PWR_LEVELS; 6040 } 6041 6042 ch_params.ch_width = CH_WIDTH_20MHZ; 6043 6044 for (i = 0; 6045 i < num_pwr_levels && (ch_params.ch_width != CH_WIDTH_INVALID); 6046 i++) { 6047 if (is_tpe_present) { 6048 if (is_6ghz_freq) { 6049 if (is_psd_power) { 6050 wlan_reg_get_client_power_for_connecting_ap( 6051 mac->pdev, ap_power_type_6g, 6052 mlme_obj->reg_tpc_obj.frequency[i], 6053 is_psd_power, ®_max, &psd_power); 6054 } else { 6055 wlan_reg_get_client_power_for_connecting_ap( 6056 mac->pdev, ap_power_type_6g, oper_freq, 6057 is_psd_power, ®_max, &psd_power); 6058 } 6059 } 6060 } else { 6061 /* center frequency calculation */ 6062 if (is_psd_power) { 6063 mlme_obj->reg_tpc_obj.frequency[i] = 6064 start_freq + (20 * i); 6065 } else { 6066 /* Use operating frequency to fetch EIRP pwr */ 6067 mlme_obj->reg_tpc_obj.frequency[i] = oper_freq; 6068 } 6069 if (is_6ghz_freq) { 6070 if (LIM_IS_STA_ROLE(session)) { 6071 wlan_reg_get_client_power_for_connecting_ap 6072 (mac->pdev, ap_power_type_6g, 6073 mlme_obj->reg_tpc_obj.frequency[i], 6074 is_psd_power, ®_max, &psd_power); 6075 } else { 6076 if (wlan_reg_decide_6ghz_power_within_bw_for_freq( 6077 mac->pdev, oper_freq, 6078 session->ch_width, 6079 &is_psd_power, 6080 &tx_power_within_bw, 6081 &psd_power_within_bw, 6082 &ap_power_type_6g, 6083 REG_BEST_PWR_MODE, 6084 NO_SCHANS_PUNC) == 6085 QDF_STATUS_SUCCESS) { 6086 pe_debug("get pwr attr from secondary list"); 6087 reg_max = tx_power_within_bw; 6088 psd_power = psd_power_within_bw; 6089 } else { 6090 wlan_reg_get_cur_6g_ap_pwr_type( 6091 mac->pdev, 6092 &ap_power_type_6g); 6093 wlan_reg_get_6g_chan_ap_power( 6094 mac->pdev, 6095 mlme_obj->reg_tpc_obj. 6096 frequency[i], 6097 &is_psd_power, 6098 ®_max, 6099 &psd_power); 6100 } 6101 } 6102 } 6103 } 6104 /* Check for regulatory channel power. If it is zero due to 6105 * invalid frequency or other inputs, then assign the regulatory 6106 * power of operating frequency to reg_max. 6107 */ 6108 if (reg_max) { 6109 mlme_obj->reg_tpc_obj.reg_max[i] = reg_max; 6110 } else { 6111 pe_debug("Reg power due to invalid freq: %d", 6112 mlme_obj->reg_tpc_obj.frequency[i]); 6113 reg_max = mlme_obj->reg_tpc_obj.reg_max[0]; 6114 mlme_obj->reg_tpc_obj.reg_max[i] = reg_max; 6115 } 6116 6117 mlme_obj->reg_tpc_obj.chan_power_info[i].chan_cfreq = 6118 mlme_obj->reg_tpc_obj.frequency[i]; 6119 6120 /* max tx power calculation */ 6121 max_tx_power = mlme_obj->reg_tpc_obj.reg_max[i]; 6122 /* If AP local power constraint is present */ 6123 if (mlme_obj->reg_tpc_obj.ap_constraint_power) { 6124 local_constraint = 6125 mlme_obj->reg_tpc_obj.ap_constraint_power; 6126 pe_debug("local constraint: %d power constraint absolute %d", 6127 local_constraint, 6128 mlme_obj->reg_tpc_obj.is_power_constraint_abs); 6129 if (mlme_obj->reg_tpc_obj.is_power_constraint_abs) 6130 max_tx_power = QDF_MIN(reg_max, 6131 local_constraint); 6132 else 6133 max_tx_power = reg_max - local_constraint; 6134 } 6135 /* If TPE is present */ 6136 if (is_tpe_present && !skip_tpe) { 6137 if (!is_psd_power && mlme_obj->reg_tpc_obj.eirp_power) 6138 tpe_power = mlme_obj->reg_tpc_obj.eirp_power; 6139 else 6140 tpe_power = mlme_obj->reg_tpc_obj.tpe[i]; 6141 /** 6142 * AP advertises TPE IE tx power as 8-bit unsigned int. 6143 * STA needs to convert it into an 8-bit 2s complement 6144 * signed integer in the range –64 dBm to 63 dBm with a 6145 * 0.5 dB step 6146 */ 6147 tpe_power /= 2; 6148 max_tx_power = QDF_MIN(max_tx_power, tpe_power); 6149 pe_debug("TPE: %d", tpe_power); 6150 } 6151 6152 if (is_psd_power) 6153 mlme_obj->reg_tpc_obj.chan_power_info[i].tx_power = 6154 (uint8_t)psd_power; 6155 else 6156 mlme_obj->reg_tpc_obj.chan_power_info[i].tx_power = 6157 (uint8_t)max_tx_power; 6158 6159 pe_debug("freq: %d reg power: %d, max_tx_power(eirp/psd): %d", 6160 mlme_obj->reg_tpc_obj.frequency[i], reg_max, 6161 mlme_obj->reg_tpc_obj.chan_power_info[i].tx_power); 6162 } 6163 6164 mlme_obj->reg_tpc_obj.num_pwr_levels = num_pwr_levels; 6165 mlme_obj->reg_tpc_obj.eirp_power = reg_max; 6166 mlme_obj->reg_tpc_obj.power_type_6g = ap_power_type_6g; 6167 mlme_obj->reg_tpc_obj.is_psd_power = is_psd_power; 6168 6169 pe_debug("num_pwr_levels: %d, is_psd_power: %d, total eirp_power: %d, ap_pwr_type: %d", 6170 num_pwr_levels, is_psd_power, reg_max, ap_power_type_6g); 6171 } 6172 6173 /** 6174 * lim_mlo_sap_validate_and_update_ra() - Validate peer address for ML SAP 6175 * management frames. 6176 * @session: pe_session 6177 * @peer_addr: address of the peer 6178 * 6179 * Check if address pointed by @peer_addr is MLD of the client, 6180 * if so, replace the address with link address of the client 6181 * to send the management packet over the air. 6182 * 6183 * Return: void 6184 */ 6185 #ifdef WLAN_FEATURE_11BE_MLO 6186 static void lim_mlo_sap_validate_and_update_ra(struct pe_session *session, 6187 struct qdf_mac_addr *peer_addr) 6188 { 6189 uint8_t i; 6190 struct wlan_mlo_dev_context *ml_ctx; 6191 struct wlan_mlo_peer_list *mlo_peer_list; 6192 struct wlan_mlo_peer_context *ml_peer; 6193 struct wlan_mlo_link_peer_entry *link_peer; 6194 6195 if (!wlan_vdev_mlme_is_mlo_ap(session->vdev)) 6196 return; 6197 6198 ml_ctx = session->vdev->mlo_dev_ctx; 6199 mlo_peer_list = &ml_ctx->mlo_peer_list; 6200 6201 ml_peerlist_lock_acquire(mlo_peer_list); 6202 ml_peer = mlo_get_mlpeer(ml_ctx, peer_addr); 6203 if (!ml_peer) { 6204 ml_peerlist_lock_release(mlo_peer_list); 6205 return; 6206 } 6207 6208 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 6209 link_peer = &ml_peer->peer_list[i]; 6210 if (link_peer->is_primary && 6211 !qdf_is_macaddr_equal(peer_addr, &link_peer->link_addr)) { 6212 qdf_copy_macaddr(peer_addr, &link_peer->link_addr); 6213 break; 6214 } 6215 } 6216 ml_peerlist_lock_release(mlo_peer_list); 6217 } 6218 #else 6219 static inline void 6220 lim_mlo_sap_validate_and_update_ra(struct pe_session *session, 6221 struct qdf_mac_addr *peer_addr) 6222 { 6223 } 6224 #endif 6225 6226 bool send_disassoc_frame = 1; 6227 /** 6228 * __lim_process_sme_disassoc_req() 6229 * 6230 ***FUNCTION: 6231 * This function is called to process SME_DISASSOC_REQ message 6232 * from HDD or upper layer application. 6233 * 6234 ***LOGIC: 6235 * 6236 ***ASSUMPTIONS: 6237 * 6238 ***NOTE: 6239 * 6240 * @param mac Pointer to Global MAC structure 6241 * @param *msg_buf A pointer to the SME message buffer 6242 * @return None 6243 */ 6244 6245 static void __lim_process_sme_disassoc_req(struct mac_context *mac, 6246 uint32_t *msg_buf) 6247 { 6248 uint16_t disassocTrigger, reasonCode; 6249 tLimMlmDisassocReq *pMlmDisassocReq; 6250 tSirResultCodes retCode = eSIR_SME_SUCCESS; 6251 struct disassoc_req smeDisassocReq; 6252 struct pe_session *pe_session = NULL; 6253 uint8_t sessionId; 6254 uint8_t smesessionId; 6255 6256 if (!msg_buf) { 6257 pe_err("Buffer is Pointing to NULL"); 6258 return; 6259 } 6260 6261 qdf_mem_copy(&smeDisassocReq, msg_buf, sizeof(struct disassoc_req)); 6262 smesessionId = smeDisassocReq.sessionId; 6263 if (!lim_is_sme_disassoc_req_valid(mac, 6264 &smeDisassocReq, 6265 pe_session)) { 6266 pe_err("received invalid SME_DISASSOC_REQ message"); 6267 if (mac->lim.gLimRspReqd) { 6268 mac->lim.gLimRspReqd = false; 6269 6270 retCode = eSIR_SME_INVALID_PARAMETERS; 6271 disassocTrigger = eLIM_HOST_DISASSOC; 6272 goto sendDisassoc; 6273 } 6274 6275 return; 6276 } 6277 6278 pe_session = pe_find_session_by_bssid_and_vdev_id(mac, 6279 smeDisassocReq.bssid.bytes, 6280 smeDisassocReq.sessionId, 6281 &sessionId); 6282 if (!pe_session) { 6283 pe_err("session does not exist for bssid " QDF_MAC_ADDR_FMT, 6284 QDF_MAC_ADDR_REF(smeDisassocReq.bssid.bytes)); 6285 retCode = eSIR_SME_INVALID_PARAMETERS; 6286 disassocTrigger = eLIM_HOST_DISASSOC; 6287 goto sendDisassoc; 6288 } 6289 pe_debug("vdev %d (%d) opmode %d Reason: %u SmeState: %d limMlmState %d ho fail %d send OTA %d to: " QDF_MAC_ADDR_FMT " bssid " QDF_MAC_ADDR_FMT, 6290 pe_session->vdev_id, pe_session->peSessionId, 6291 pe_session->opmode, smeDisassocReq.reasonCode, 6292 pe_session->limSmeState, pe_session->limMlmState, 6293 smeDisassocReq.process_ho_fail, 6294 smeDisassocReq.doNotSendOverTheAir, 6295 QDF_MAC_ADDR_REF(smeDisassocReq.peer_macaddr.bytes), 6296 QDF_MAC_ADDR_REF(smeDisassocReq.bssid.bytes)); 6297 6298 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ 6299 lim_diag_event_report(mac, WLAN_PE_DIAG_DISASSOC_REQ_EVENT, pe_session, 6300 0, smeDisassocReq.reasonCode); 6301 #endif /* FEATURE_WLAN_DIAG_SUPPORT */ 6302 6303 pe_session->smeSessionId = smesessionId; 6304 pe_session->process_ho_fail = smeDisassocReq.process_ho_fail; 6305 6306 switch (GET_LIM_SYSTEM_ROLE(pe_session)) { 6307 case eLIM_STA_ROLE: 6308 switch (pe_session->limSmeState) { 6309 case eLIM_SME_ASSOCIATED_STATE: 6310 case eLIM_SME_LINK_EST_STATE: 6311 pe_session->limPrevSmeState = 6312 pe_session->limSmeState; 6313 pe_session->limSmeState = eLIM_SME_WT_DISASSOC_STATE; 6314 /* Delete all TDLS peers connected before leaving BSS */ 6315 lim_delete_tdls_peers(mac, pe_session); 6316 MTRACE(mac_trace(mac, TRACE_CODE_SME_STATE, 6317 pe_session->peSessionId, 6318 pe_session->limSmeState)); 6319 break; 6320 6321 case eLIM_SME_WT_DEAUTH_STATE: 6322 /* PE shall still process the DISASSOC_REQ and proceed with 6323 * link tear down even if it had already sent a DEAUTH_IND to 6324 * to SME. mac->lim.gLimPrevSmeState shall remain the same as 6325 * its been set when PE entered WT_DEAUTH_STATE. 6326 */ 6327 pe_session->limSmeState = eLIM_SME_WT_DISASSOC_STATE; 6328 MTRACE(mac_trace 6329 (mac, TRACE_CODE_SME_STATE, 6330 pe_session->peSessionId, 6331 pe_session->limSmeState)); 6332 break; 6333 6334 case eLIM_SME_WT_DISASSOC_STATE: 6335 /* PE Received a Disassoc frame. Normally it gets DISASSOC_CNF but it 6336 * received DISASSOC_REQ. Which means host is also trying to disconnect. 6337 * PE can continue processing DISASSOC_REQ and send the response instead 6338 * of failing the request. SME will anyway ignore DEAUTH_IND that was sent 6339 * for disassoc frame. 6340 * 6341 * It will send a disassoc, which is ok. However, we can use the global flag 6342 * sendDisassoc to not send disassoc frame. 6343 */ 6344 break; 6345 6346 case eLIM_SME_JOIN_FAILURE_STATE: { 6347 /* Already in Disconnected State, return success */ 6348 if (mac->lim.gLimRspReqd) { 6349 retCode = eSIR_SME_SUCCESS; 6350 disassocTrigger = eLIM_HOST_DISASSOC; 6351 goto sendDisassoc; 6352 } 6353 } 6354 break; 6355 default: 6356 /** 6357 * STA is not currently associated. 6358 * Log error and send response to host 6359 */ 6360 pe_err("received unexpected SME_DISASSOC_REQ in state %X", 6361 pe_session->limSmeState); 6362 lim_print_sme_state(mac, LOGE, 6363 pe_session->limSmeState); 6364 6365 if (mac->lim.gLimRspReqd) { 6366 if (pe_session->limSmeState != 6367 eLIM_SME_WT_ASSOC_STATE) 6368 mac->lim.gLimRspReqd = false; 6369 6370 retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; 6371 disassocTrigger = eLIM_HOST_DISASSOC; 6372 goto sendDisassoc; 6373 } 6374 6375 return; 6376 } 6377 6378 break; 6379 6380 case eLIM_AP_ROLE: 6381 /* Check if MAC address is MLD of the client and 6382 * change it to primary link address to send OTA. 6383 */ 6384 lim_mlo_sap_validate_and_update_ra( 6385 pe_session, &smeDisassocReq.peer_macaddr); 6386 break; 6387 6388 default: 6389 /* eLIM_UNKNOWN_ROLE */ 6390 pe_err("received unexpected SME_DISASSOC_REQ for role %d", 6391 GET_LIM_SYSTEM_ROLE(pe_session)); 6392 6393 retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; 6394 disassocTrigger = eLIM_HOST_DISASSOC; 6395 goto sendDisassoc; 6396 } /* end switch (mac->lim.gLimSystemRole) */ 6397 6398 disassocTrigger = eLIM_HOST_DISASSOC; 6399 reasonCode = smeDisassocReq.reasonCode; 6400 6401 if (smeDisassocReq.doNotSendOverTheAir) 6402 send_disassoc_frame = 0; 6403 6404 pMlmDisassocReq = qdf_mem_malloc(sizeof(tLimMlmDisassocReq)); 6405 if (!pMlmDisassocReq) 6406 return; 6407 6408 qdf_copy_macaddr(&pMlmDisassocReq->peer_macaddr, 6409 &smeDisassocReq.peer_macaddr); 6410 6411 pMlmDisassocReq->reasonCode = reasonCode; 6412 pMlmDisassocReq->disassocTrigger = disassocTrigger; 6413 6414 /* Update PE session ID */ 6415 pMlmDisassocReq->sessionId = sessionId; 6416 6417 lim_post_mlm_message(mac, 6418 LIM_MLM_DISASSOC_REQ, (uint32_t *) pMlmDisassocReq); 6419 return; 6420 6421 sendDisassoc: 6422 if (pe_session) 6423 lim_send_sme_disassoc_ntf(mac, 6424 smeDisassocReq.peer_macaddr.bytes, 6425 retCode, 6426 disassocTrigger, 6427 1, smesessionId, 6428 pe_session); 6429 else 6430 lim_send_sme_disassoc_ntf(mac, 6431 smeDisassocReq.peer_macaddr.bytes, 6432 retCode, disassocTrigger, 1, 6433 smesessionId, NULL); 6434 6435 } /*** end __lim_process_sme_disassoc_req() ***/ 6436 6437 /** ----------------------------------------------------------------- 6438 \brief __lim_process_sme_disassoc_cnf() - Process SME_DISASSOC_CNF 6439 6440 This function is called to process SME_DISASSOC_CNF message 6441 from HDD or upper layer application. 6442 6443 \param mac - global mac structure 6444 \param sta - station dph hash node 6445 \return none 6446 \sa 6447 ----------------------------------------------------------------- */ 6448 void __lim_process_sme_disassoc_cnf(struct mac_context *mac, uint32_t *msg_buf) 6449 { 6450 struct disassoc_cnf smeDisassocCnf; 6451 uint16_t aid; 6452 tpDphHashNode sta; 6453 struct pe_session *pe_session; 6454 uint8_t sessionId; 6455 uint32_t *msg = NULL; 6456 QDF_STATUS status; 6457 6458 qdf_mem_copy(&smeDisassocCnf, msg_buf, sizeof(smeDisassocCnf)); 6459 6460 pe_session = pe_find_session_by_bssid_and_vdev_id(mac, 6461 smeDisassocCnf.bssid.bytes, 6462 smeDisassocCnf.vdev_id, 6463 &sessionId); 6464 if (!pe_session) { 6465 pe_err("session does not exist for bssid " QDF_MAC_ADDR_FMT, 6466 QDF_MAC_ADDR_REF(smeDisassocCnf.bssid.bytes)); 6467 status = lim_prepare_disconnect_done_ind(mac, &msg, 6468 smeDisassocCnf.vdev_id, 6469 eSIR_SME_INVALID_SESSION, 6470 NULL); 6471 if (QDF_IS_STATUS_SUCCESS(status)) 6472 lim_send_sme_disassoc_deauth_ntf(mac, 6473 QDF_STATUS_SUCCESS, 6474 (uint32_t *)msg); 6475 return; 6476 } 6477 6478 if (!lim_is_sme_disassoc_cnf_valid(mac, &smeDisassocCnf, pe_session)) { 6479 pe_err("received invalid SME_DISASSOC_CNF message"); 6480 status = lim_prepare_disconnect_done_ind( 6481 mac, &msg, 6482 pe_session->smeSessionId, 6483 eSIR_SME_INVALID_PARAMETERS, 6484 &smeDisassocCnf.peer_macaddr.bytes[0]); 6485 if (QDF_IS_STATUS_SUCCESS(status)) 6486 lim_send_sme_disassoc_deauth_ntf(mac, 6487 QDF_STATUS_SUCCESS, 6488 (uint32_t *)msg); 6489 return; 6490 } 6491 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ 6492 if (smeDisassocCnf.messageType == eWNI_SME_DISASSOC_CNF) 6493 lim_diag_event_report(mac, WLAN_PE_DIAG_DISASSOC_CNF_EVENT, 6494 pe_session, 6495 (uint16_t)smeDisassocCnf.status_code, 0); 6496 else if (smeDisassocCnf.messageType == eWNI_SME_DEAUTH_CNF) 6497 lim_diag_event_report(mac, WLAN_PE_DIAG_DEAUTH_CNF_EVENT, 6498 pe_session, 6499 (uint16_t)smeDisassocCnf.status_code, 0); 6500 #endif /* FEATURE_WLAN_DIAG_SUPPORT */ 6501 pe_debug("vdev %d (%d) opmode %d SmeState: %d limMlmState %d from: " QDF_MAC_ADDR_FMT " bssid " QDF_MAC_ADDR_FMT, 6502 pe_session->vdev_id, pe_session->peSessionId, 6503 pe_session->opmode, pe_session->limSmeState, 6504 pe_session->limMlmState, 6505 QDF_MAC_ADDR_REF(smeDisassocCnf.peer_macaddr.bytes), 6506 QDF_MAC_ADDR_REF(smeDisassocCnf.bssid.bytes)); 6507 6508 switch (GET_LIM_SYSTEM_ROLE(pe_session)) { 6509 case eLIM_STA_ROLE: 6510 if ((pe_session->limSmeState != eLIM_SME_IDLE_STATE) && 6511 (pe_session->limSmeState != eLIM_SME_WT_DISASSOC_STATE) 6512 && (pe_session->limSmeState != 6513 eLIM_SME_WT_DEAUTH_STATE)) { 6514 pe_err("received unexp SME_DISASSOC_CNF in state %X", 6515 pe_session->limSmeState); 6516 lim_print_sme_state(mac, LOGE, 6517 pe_session->limSmeState); 6518 status = lim_prepare_disconnect_done_ind( 6519 mac, &msg, 6520 pe_session->smeSessionId, 6521 eSIR_SME_INVALID_STATE, 6522 &smeDisassocCnf.peer_macaddr.bytes[0]); 6523 if (QDF_IS_STATUS_SUCCESS(status)) 6524 lim_send_sme_disassoc_deauth_ntf(mac, 6525 QDF_STATUS_SUCCESS, 6526 (uint32_t *)msg); 6527 return; 6528 } 6529 break; 6530 6531 case eLIM_AP_ROLE: 6532 break; 6533 default: /* eLIM_UNKNOWN_ROLE */ 6534 pe_err("received unexpected SME_DISASSOC_CNF role %d", 6535 GET_LIM_SYSTEM_ROLE(pe_session)); 6536 status = lim_prepare_disconnect_done_ind( 6537 mac, &msg, 6538 pe_session->smeSessionId, 6539 eSIR_SME_INVALID_STATE, 6540 &smeDisassocCnf.peer_macaddr.bytes[0]); 6541 if (QDF_IS_STATUS_SUCCESS(status)) 6542 lim_send_sme_disassoc_deauth_ntf(mac, 6543 QDF_STATUS_SUCCESS, 6544 (uint32_t *)msg); 6545 return; 6546 } 6547 6548 if ((pe_session->limSmeState == eLIM_SME_WT_DISASSOC_STATE) || 6549 (pe_session->limSmeState == eLIM_SME_WT_DEAUTH_STATE) || 6550 LIM_IS_AP_ROLE(pe_session)) { 6551 sta = dph_lookup_hash_entry(mac, 6552 smeDisassocCnf.peer_macaddr.bytes, &aid, 6553 &pe_session->dph.dphHashTable); 6554 if (!sta) { 6555 pe_err("DISASSOC_CNF for a STA with no context, addr= " 6556 QDF_MAC_ADDR_FMT, 6557 QDF_MAC_ADDR_REF(smeDisassocCnf.peer_macaddr.bytes)); 6558 status = lim_prepare_disconnect_done_ind( 6559 mac, &msg, 6560 pe_session->smeSessionId, 6561 eSIR_SME_INVALID_PARAMETERS, 6562 &smeDisassocCnf.peer_macaddr.bytes[0]); 6563 if (QDF_IS_STATUS_SUCCESS(status)) 6564 lim_send_sme_disassoc_deauth_ntf(mac, 6565 QDF_STATUS_SUCCESS, 6566 (uint32_t *)msg); 6567 return; 6568 } 6569 6570 if ((sta->mlmStaContext.mlmState == 6571 eLIM_MLM_WT_DEL_STA_RSP_STATE) || 6572 (sta->mlmStaContext.mlmState == 6573 eLIM_MLM_WT_DEL_BSS_RSP_STATE)) { 6574 pe_err("No need of cleanup for addr:" QDF_MAC_ADDR_FMT "as MLM state is %d", 6575 QDF_MAC_ADDR_REF(smeDisassocCnf.peer_macaddr.bytes), 6576 sta->mlmStaContext.mlmState); 6577 status = lim_prepare_disconnect_done_ind(mac, &msg, 6578 pe_session->smeSessionId, 6579 eSIR_SME_SUCCESS, 6580 NULL); 6581 if (QDF_IS_STATUS_SUCCESS(status)) 6582 lim_send_sme_disassoc_deauth_ntf(mac, 6583 QDF_STATUS_SUCCESS, 6584 (uint32_t *)msg); 6585 return; 6586 } 6587 6588 lim_mlo_notify_peer_disconn(pe_session, sta); 6589 6590 /* Delete FT session if there exists one */ 6591 lim_ft_cleanup_pre_auth_info(mac, pe_session); 6592 lim_cleanup_rx_path(mac, sta, pe_session, true); 6593 6594 lim_clean_up_disassoc_deauth_req(mac, 6595 (char *)&smeDisassocCnf.peer_macaddr, 0); 6596 } 6597 6598 return; 6599 } 6600 6601 /** 6602 * __lim_process_sme_deauth_req() - process sme deauth req 6603 * @mac_ctx: Pointer to Global MAC structure 6604 * @msg_buf: pointer to the SME message buffer 6605 * 6606 * This function is called to process SME_DEAUTH_REQ message 6607 * from HDD or upper layer application. 6608 * 6609 * Return: None 6610 */ 6611 6612 static void __lim_process_sme_deauth_req(struct mac_context *mac_ctx, 6613 uint32_t *msg_buf) 6614 { 6615 uint16_t deauth_trigger, reason_code; 6616 tLimMlmDeauthReq *mlm_deauth_req; 6617 struct deauth_req sme_deauth_req; 6618 tSirResultCodes ret_code = eSIR_SME_SUCCESS; 6619 struct pe_session *session_entry; 6620 uint8_t session_id; /* PE sessionId */ 6621 uint8_t vdev_id; 6622 6623 qdf_mem_copy(&sme_deauth_req, msg_buf, sizeof(sme_deauth_req)); 6624 vdev_id = sme_deauth_req.vdev_id; 6625 6626 /* 6627 * We need to get a session first but we don't even know 6628 * if the message is correct. 6629 */ 6630 session_entry = pe_find_session_by_bssid_and_vdev_id(mac_ctx, 6631 sme_deauth_req.bssid.bytes, 6632 sme_deauth_req.vdev_id, 6633 &session_id); 6634 if (!session_entry) { 6635 pe_err("session does not exist for bssid " QDF_MAC_ADDR_FMT, 6636 QDF_MAC_ADDR_REF(sme_deauth_req.bssid.bytes)); 6637 ret_code = eSIR_SME_INVALID_PARAMETERS; 6638 deauth_trigger = eLIM_HOST_DEAUTH; 6639 goto send_deauth; 6640 } 6641 6642 if (!lim_is_sme_deauth_req_valid(mac_ctx, &sme_deauth_req, 6643 session_entry)) { 6644 pe_err("received invalid SME_DEAUTH_REQ message"); 6645 mac_ctx->lim.gLimRspReqd = false; 6646 6647 ret_code = eSIR_SME_INVALID_PARAMETERS; 6648 deauth_trigger = eLIM_HOST_DEAUTH; 6649 goto send_deauth; 6650 } 6651 pe_debug("vdev %d (%d) opmode %d reasoncode %u limSmestate %d limMlmState %d to " QDF_MAC_ADDR_FMT " bssid " QDF_MAC_ADDR_FMT, 6652 vdev_id, session_entry->peSessionId, 6653 session_entry->opmode, sme_deauth_req.reasonCode, 6654 session_entry->limSmeState, session_entry->limMlmState, 6655 QDF_MAC_ADDR_REF(sme_deauth_req.peer_macaddr.bytes), 6656 QDF_MAC_ADDR_REF(sme_deauth_req.bssid.bytes)); 6657 6658 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ 6659 lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_DEAUTH_REQ_EVENT, 6660 session_entry, 0, sme_deauth_req.reasonCode); 6661 #endif /* FEATURE_WLAN_DIAG_SUPPORT */ 6662 6663 session_entry->vdev_id = vdev_id; 6664 6665 switch (GET_LIM_SYSTEM_ROLE(session_entry)) { 6666 case eLIM_STA_ROLE: 6667 switch (session_entry->limSmeState) { 6668 case eLIM_SME_ASSOCIATED_STATE: 6669 case eLIM_SME_LINK_EST_STATE: 6670 /* Delete all TDLS peers connected before leaving BSS */ 6671 lim_delete_tdls_peers(mac_ctx, session_entry); 6672 fallthrough; 6673 case eLIM_SME_WT_ASSOC_STATE: 6674 case eLIM_SME_JOIN_FAILURE_STATE: 6675 case eLIM_SME_IDLE_STATE: 6676 session_entry->limPrevSmeState = 6677 session_entry->limSmeState; 6678 session_entry->limSmeState = eLIM_SME_WT_DEAUTH_STATE; 6679 MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, 6680 session_entry->peSessionId, 6681 session_entry->limSmeState)); 6682 /* Send Deauthentication request to MLM below */ 6683 break; 6684 case eLIM_SME_WT_DEAUTH_STATE: 6685 case eLIM_SME_WT_DISASSOC_STATE: 6686 /* 6687 * PE Received a Deauth/Disassoc frame. Normally it get 6688 * DEAUTH_CNF/DISASSOC_CNF but it received DEAUTH_REQ. 6689 * Which means host is also trying to disconnect. 6690 * PE can continue processing DEAUTH_REQ and send 6691 * the response instead of failing the request. 6692 * SME will anyway ignore DEAUTH_IND/DISASSOC_IND that 6693 * was sent for deauth/disassoc frame. 6694 */ 6695 session_entry->limSmeState = eLIM_SME_WT_DEAUTH_STATE; 6696 break; 6697 default: 6698 /* 6699 * STA is not in a state to deauthenticate with 6700 * peer. Log error and send response to host. 6701 */ 6702 pe_err("received unexp SME_DEAUTH_REQ in state %X", 6703 session_entry->limSmeState); 6704 lim_print_sme_state(mac_ctx, LOGE, 6705 session_entry->limSmeState); 6706 6707 if (mac_ctx->lim.gLimRspReqd) { 6708 mac_ctx->lim.gLimRspReqd = false; 6709 6710 ret_code = eSIR_SME_STA_NOT_AUTHENTICATED; 6711 deauth_trigger = eLIM_HOST_DEAUTH; 6712 6713 /* 6714 * here we received deauth request from AP so 6715 * sme state is eLIM_SME_WT_DEAUTH_STATE.if we 6716 * have ISSUED delSta then mlm state should be 6717 * eLIM_MLM_WT_DEL_STA_RSP_STATE and ifwe got 6718 * delBSS rsp then mlm state should be 6719 * eLIM_MLM_IDLE_STATE so the below condition 6720 * captures the state where delSta not done 6721 * and firmware still in connected state. 6722 */ 6723 if (session_entry->limSmeState == 6724 eLIM_SME_WT_DEAUTH_STATE && 6725 session_entry->limMlmState != 6726 eLIM_MLM_IDLE_STATE && 6727 session_entry->limMlmState != 6728 eLIM_MLM_WT_DEL_STA_RSP_STATE) 6729 ret_code = eSIR_SME_DEAUTH_STATUS; 6730 goto send_deauth; 6731 } 6732 return; 6733 } 6734 break; 6735 case eLIM_AP_ROLE: 6736 /* Check if MAC address is MLD of the client and 6737 * change it to primary link address to send OTA. 6738 */ 6739 lim_mlo_sap_validate_and_update_ra( 6740 session_entry, &sme_deauth_req.peer_macaddr); 6741 break; 6742 default: 6743 pe_err("received unexpected SME_DEAUTH_REQ for role %X", 6744 GET_LIM_SYSTEM_ROLE(session_entry)); 6745 if (mac_ctx->lim.gLimRspReqd) { 6746 mac_ctx->lim.gLimRspReqd = false; 6747 ret_code = eSIR_SME_INVALID_PARAMETERS; 6748 deauth_trigger = eLIM_HOST_DEAUTH; 6749 goto send_deauth; 6750 } 6751 return; 6752 } /* end switch (mac_ctx->lim.gLimSystemRole) */ 6753 6754 if (sme_deauth_req.reasonCode == eLIM_LINK_MONITORING_DEAUTH && 6755 session_entry->limSystemRole == eLIM_STA_ROLE) { 6756 /* Deauthentication is triggered by Link Monitoring */ 6757 pe_debug("** Lost link with AP **"); 6758 deauth_trigger = eLIM_LINK_MONITORING_DEAUTH; 6759 reason_code = REASON_UNSPEC_FAILURE; 6760 } else { 6761 deauth_trigger = eLIM_HOST_DEAUTH; 6762 reason_code = sme_deauth_req.reasonCode; 6763 } 6764 6765 /* Trigger Deauthentication frame to peer MAC entity */ 6766 mlm_deauth_req = qdf_mem_malloc(sizeof(tLimMlmDeauthReq)); 6767 if (!mlm_deauth_req) { 6768 if (mac_ctx->lim.gLimRspReqd) { 6769 mac_ctx->lim.gLimRspReqd = false; 6770 ret_code = eSIR_SME_RESOURCES_UNAVAILABLE; 6771 deauth_trigger = eLIM_HOST_DEAUTH; 6772 goto send_deauth; 6773 } 6774 return; 6775 } 6776 6777 qdf_copy_macaddr(&mlm_deauth_req->peer_macaddr, 6778 &sme_deauth_req.peer_macaddr); 6779 6780 mlm_deauth_req->reasonCode = reason_code; 6781 mlm_deauth_req->deauthTrigger = deauth_trigger; 6782 6783 /* Update PE session Id */ 6784 mlm_deauth_req->sessionId = session_id; 6785 lim_process_mlm_deauth_req(mac_ctx, (uint32_t *)mlm_deauth_req); 6786 6787 return; 6788 6789 send_deauth: 6790 lim_send_sme_deauth_ntf(mac_ctx, sme_deauth_req.peer_macaddr.bytes, 6791 ret_code, deauth_trigger, 1, vdev_id); 6792 } 6793 6794 /** 6795 * __lim_counter_measures() 6796 * 6797 * FUNCTION: 6798 * This function is called to "implement" MIC counter measure 6799 * and is *temporary* only 6800 * 6801 * LOGIC: on AP, disassoc all STA associated thru TKIP, 6802 * we don't do the proper STA disassoc sequence since the 6803 * BSS will be stopped anyway 6804 * 6805 ***ASSUMPTIONS: 6806 * 6807 ***NOTE: 6808 * 6809 * @param mac Pointer to Global MAC structure 6810 * @return None 6811 */ 6812 6813 static void __lim_counter_measures(struct mac_context *mac, struct pe_session *pe_session) 6814 { 6815 tSirMacAddr mac_addr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 6816 6817 if (LIM_IS_AP_ROLE(pe_session)) 6818 lim_send_disassoc_mgmt_frame(mac, REASON_MIC_FAILURE, 6819 mac_addr, pe_session, false); 6820 }; 6821 6822 void lim_send_stop_bss_failure_resp(struct mac_context *mac_ctx, 6823 struct pe_session *session) 6824 { 6825 session->limSmeState = session->limPrevSmeState; 6826 6827 MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, session->peSessionId, 6828 session->limSmeState)); 6829 lim_send_stop_bss_response(mac_ctx, session->vdev_id, 6830 eSIR_SME_STOP_BSS_FAILURE); 6831 } 6832 6833 static void lim_flush_all_peer_from_serialization_queue( 6834 struct mac_context *mac_ctx, 6835 struct pe_session *session) 6836 { 6837 struct wlan_serialization_queued_cmd_info cmd = {0}; 6838 struct wlan_objmgr_vdev *vdev; 6839 6840 vdev = session->vdev; 6841 if (!vdev) { 6842 pe_err("vdev is null"); 6843 return; 6844 } 6845 6846 pe_debug("vdev id is %d for disconnect/deauth cmd", session->vdev_id); 6847 6848 /* Flush any pending NB peer deauth command */ 6849 cmd.vdev = vdev; 6850 cmd.cmd_type = WLAN_SER_CMD_FORCE_DEAUTH_STA; 6851 cmd.req_type = WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE; 6852 cmd.requestor = WLAN_UMAC_COMP_MLME; 6853 cmd.queue_type = WLAN_SERIALIZATION_PENDING_QUEUE; 6854 6855 wlan_serialization_cancel_request(&cmd); 6856 6857 /* Flush any pending NB peer disassoc command */ 6858 qdf_mem_zero(&cmd, sizeof(cmd)); 6859 cmd.vdev = vdev; 6860 cmd.cmd_type = WLAN_SER_CMD_FORCE_DISASSOC_STA; 6861 cmd.req_type = WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE; 6862 cmd.requestor = WLAN_UMAC_COMP_MLME; 6863 cmd.queue_type = WLAN_SERIALIZATION_PENDING_QUEUE; 6864 6865 wlan_serialization_cancel_request(&cmd); 6866 6867 /* Flush any pending SB peer deauth/disconnect command */ 6868 qdf_mem_zero(&cmd, sizeof(cmd)); 6869 cmd.vdev = vdev; 6870 cmd.cmd_type = WLAN_SER_CMD_WM_STATUS_CHANGE; 6871 cmd.req_type = WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE; 6872 cmd.requestor = WLAN_UMAC_COMP_MLME; 6873 cmd.queue_type = WLAN_SERIALIZATION_PENDING_QUEUE; 6874 6875 wlan_serialization_cancel_request(&cmd); 6876 } 6877 6878 void lim_delete_all_peers(struct pe_session *session) 6879 { 6880 uint8_t i = 0; 6881 struct mac_context *mac_ctx = session->mac_ctx; 6882 tpDphHashNode sta_ds = NULL; 6883 QDF_STATUS status; 6884 tSirMacAddr bc_addr = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 6885 6886 /* IBSS and NDI doesn't send Disassoc frame */ 6887 if (!LIM_IS_NDI_ROLE(session)) { 6888 pe_debug("stop_bss_reason: %d", session->stop_bss_reason); 6889 if (session->stop_bss_reason == eSIR_SME_MIC_COUNTER_MEASURES) 6890 __lim_counter_measures(mac_ctx, session); 6891 else 6892 lim_send_disassoc_mgmt_frame(mac_ctx, 6893 REASON_DEAUTH_NETWORK_LEAVING, 6894 bc_addr, session, false); 6895 } 6896 6897 for (i = 1; i < session->dph.dphHashTable.size; i++) { 6898 sta_ds = dph_get_hash_entry(mac_ctx, i, 6899 &session->dph.dphHashTable); 6900 if (!sta_ds) 6901 continue; 6902 lim_mlo_notify_peer_disconn(session, sta_ds); 6903 status = lim_del_sta(mac_ctx, sta_ds, false, session); 6904 if (QDF_STATUS_SUCCESS == status) { 6905 lim_delete_dph_hash_entry(mac_ctx, sta_ds->staAddr, 6906 sta_ds->assocId, session); 6907 if (lim_is_mlo_conn(session, sta_ds)) 6908 lim_release_mlo_conn_idx(mac_ctx, 6909 sta_ds->assocId, 6910 session, false); 6911 else 6912 lim_release_peer_idx(mac_ctx, sta_ds->assocId, 6913 session); 6914 } else { 6915 pe_err("lim_del_sta failed with Status: %d", status); 6916 QDF_ASSERT(0); 6917 } 6918 } 6919 6920 /** 6921 * Scenario: CSA happens and south bound disconnection got queued 6922 * in serialization parallelly. 6923 * As part of CSA, remove all peer from serialization, so that when 6924 * south bound disconnection becomes active, it should not lead to a 6925 * race where the peer is trying to connect and the driver is trying 6926 * to disconnect the same peer, leading to an active command timeout 6927 */ 6928 lim_flush_all_peer_from_serialization_queue(mac_ctx, session); 6929 6930 lim_disconnect_complete(session, false); 6931 if (mac_ctx->del_peers_ind_cb) 6932 mac_ctx->del_peers_ind_cb(mac_ctx->psoc, session->vdev_id); 6933 } 6934 6935 QDF_STATUS lim_sta_send_del_bss(struct pe_session *session) 6936 { 6937 struct mac_context *mac_ctx = session->mac_ctx; 6938 QDF_STATUS status = QDF_STATUS_E_FAILURE; 6939 tpDphHashNode sta_ds = NULL; 6940 6941 sta_ds = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER, 6942 &session->dph.dphHashTable); 6943 if (!sta_ds) { 6944 pe_err("DPH Entry for STA is missing, failed to send delbss"); 6945 goto end; 6946 } 6947 6948 status = lim_del_bss(mac_ctx, sta_ds, 0, session); 6949 if (QDF_IS_STATUS_ERROR(status)) 6950 pe_err("delBss failed for bss %d", session->vdev_id); 6951 6952 end: 6953 return status; 6954 } 6955 6956 QDF_STATUS lim_send_vdev_stop(struct pe_session *session) 6957 { 6958 struct mac_context *mac_ctx = session->mac_ctx; 6959 QDF_STATUS status; 6960 6961 status = lim_del_bss(mac_ctx, NULL, session->vdev_id, session); 6962 6963 if (QDF_IS_STATUS_ERROR(status)) { 6964 pe_err("delBss failed for bss %d", session->vdev_id); 6965 lim_send_stop_bss_failure_resp(mac_ctx, session); 6966 } 6967 6968 return status; 6969 } 6970 6971 /** 6972 * lim_delete_peers_and_send_vdev_stop() -delete peers and send vdev stop 6973 * @session: session pointer 6974 * 6975 * Return None 6976 */ 6977 static void lim_delete_peers_and_send_vdev_stop(struct pe_session *session) 6978 { 6979 struct mac_context *mac_ctx = session->mac_ctx; 6980 QDF_STATUS status; 6981 6982 if (QDF_IS_STATUS_SUCCESS( 6983 wlan_vdev_is_restart_progress(session->vdev))) 6984 status = 6985 wlan_vdev_mlme_sm_deliver_evt(session->vdev, 6986 WLAN_VDEV_SM_EV_RESTART_REQ_FAIL, 6987 sizeof(*session), session); 6988 else 6989 status = wlan_vdev_mlme_sm_deliver_evt(session->vdev, 6990 WLAN_VDEV_SM_EV_DOWN, 6991 sizeof(*session), 6992 session); 6993 if (QDF_IS_STATUS_ERROR(status)) 6994 lim_send_stop_bss_failure_resp(mac_ctx, session); 6995 } 6996 6997 static void 6998 __lim_handle_sme_stop_bss_request(struct mac_context *mac, uint32_t *msg_buf) 6999 { 7000 struct stop_bss_req stop_bss_req; 7001 tLimSmeStates prevState; 7002 struct pe_session *pe_session; 7003 struct qdf_mac_addr bssid; 7004 uint8_t vdev_id; 7005 uint8_t session_id; 7006 7007 qdf_mem_copy(&stop_bss_req, msg_buf, sizeof(stop_bss_req)); 7008 vdev_id = stop_bss_req.vdev_id; 7009 wlan_mlme_get_mac_vdev_id(mac->pdev, vdev_id, &bssid); 7010 7011 pe_session = pe_find_session_by_bssid(mac, bssid.bytes, 7012 &session_id); 7013 if (!pe_session) { 7014 pe_err("session does not exist for bssid " QDF_MAC_ADDR_FMT, 7015 QDF_MAC_ADDR_REF(bssid.bytes)); 7016 lim_send_stop_bss_response(mac, vdev_id, 7017 eSIR_SME_INVALID_PARAMETERS); 7018 return; 7019 } 7020 7021 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ 7022 lim_diag_event_report(mac, WLAN_PE_DIAG_STOP_BSS_REQ_EVENT, pe_session, 7023 0, 0); 7024 #endif /* FEATURE_WLAN_DIAG_SUPPORT */ 7025 7026 if (pe_session->limSmeState != eLIM_SME_NORMAL_STATE || /* Added For BT -AMP Support */ 7027 LIM_IS_STA_ROLE(pe_session)) { 7028 /** 7029 * Should not have received STOP_BSS_REQ in states 7030 * other than 'normal' state or on STA in Infrastructure 7031 * mode. Log error and return response to host. 7032 */ 7033 pe_err("received unexpected SME_STOP_BSS_REQ in state %X, for role %d", 7034 pe_session->limSmeState, 7035 GET_LIM_SYSTEM_ROLE(pe_session)); 7036 lim_print_sme_state(mac, LOGE, pe_session->limSmeState); 7037 /* / Send Stop BSS response to host */ 7038 lim_send_stop_bss_response(mac, vdev_id, 7039 eSIR_SME_UNEXPECTED_REQ_RESULT_CODE); 7040 return; 7041 } 7042 7043 if (LIM_IS_AP_ROLE(pe_session)) 7044 lim_wpspbc_close(mac, pe_session); 7045 7046 prevState = pe_session->limSmeState; 7047 pe_session->limPrevSmeState = prevState; 7048 7049 pe_session->limSmeState = eLIM_SME_IDLE_STATE; 7050 MTRACE(mac_trace 7051 (mac, TRACE_CODE_SME_STATE, pe_session->peSessionId, 7052 pe_session->limSmeState)); 7053 7054 pe_session->smeSessionId = vdev_id; 7055 pe_session->stop_bss_reason = 0; 7056 7057 if (!LIM_IS_NDI_ROLE(pe_session)) { 7058 /* Free the buffer allocated in START_BSS_REQ */ 7059 qdf_mem_free(pe_session->add_ie_params.probeRespData_buff); 7060 pe_session->add_ie_params.probeRespDataLen = 0; 7061 pe_session->add_ie_params.probeRespData_buff = NULL; 7062 7063 qdf_mem_free(pe_session->add_ie_params.assocRespData_buff); 7064 pe_session->add_ie_params.assocRespDataLen = 0; 7065 pe_session->add_ie_params.assocRespData_buff = NULL; 7066 7067 qdf_mem_free(pe_session->add_ie_params.probeRespBCNData_buff); 7068 pe_session->add_ie_params.probeRespBCNDataLen = 0; 7069 pe_session->add_ie_params.probeRespBCNData_buff = NULL; 7070 } 7071 7072 lim_delete_peers_and_send_vdev_stop(pe_session); 7073 7074 } 7075 7076 /** 7077 * __lim_process_sme_stop_bss_req() - Process STOP_BSS from SME 7078 * @mac: Global MAC context 7079 * @pMsg: Message from SME 7080 * 7081 * Wrapper for the function __lim_handle_sme_stop_bss_request 7082 * This message will be deferred until softmac come out of 7083 * scan mode. Message should be handled even if we have 7084 * detected radar in the current operating channel. 7085 * 7086 * Return: true - If we consumed the buffer 7087 * false - If have deferred the message. 7088 */ 7089 7090 static bool __lim_process_sme_stop_bss_req(struct mac_context *mac, 7091 struct scheduler_msg *pMsg) 7092 { 7093 __lim_handle_sme_stop_bss_request(mac, (uint32_t *) pMsg->bodyptr); 7094 return true; 7095 } /*** end __lim_process_sme_stop_bss_req() ***/ 7096 7097 void lim_process_sme_del_bss_rsp(struct mac_context *mac, 7098 struct pe_session *pe_session) 7099 { 7100 SET_LIM_PROCESS_DEFD_MESGS(mac, true); 7101 dph_hash_table_init(mac, &pe_session->dph.dphHashTable); 7102 lim_delete_pre_auth_list(mac); 7103 lim_send_stop_bss_response(mac, pe_session->vdev_id, 7104 eSIR_SME_SUCCESS); 7105 return; 7106 } 7107 7108 /** 7109 * __lim_process_sme_assoc_cnf_new() - process sme assoc/reassoc cnf 7110 * 7111 * @mac_ctx: pointer to mac context 7112 * @msg_type: message type 7113 * @msg_buf: pointer to the SME message buffer 7114 * 7115 * This function handles SME_ASSOC_CNF/SME_REASSOC_CNF 7116 * in BTAMP AP. 7117 * 7118 * Return: None 7119 */ 7120 7121 void __lim_process_sme_assoc_cnf_new(struct mac_context *mac_ctx, uint32_t msg_type, 7122 uint32_t *msg_buf) 7123 { 7124 struct assoc_cnf assoc_cnf; 7125 tpDphHashNode sta_ds = NULL; 7126 struct pe_session *session_entry = NULL; 7127 uint8_t session_id; 7128 tpSirAssocReq assoc_req; 7129 7130 if (!msg_buf) { 7131 pe_err("msg_buf is NULL"); 7132 return; 7133 } 7134 7135 qdf_mem_copy(&assoc_cnf, msg_buf, sizeof(assoc_cnf)); 7136 if (!__lim_is_sme_assoc_cnf_valid(&assoc_cnf)) { 7137 pe_err("Received invalid SME_RE(ASSOC)_CNF message"); 7138 goto end; 7139 } 7140 7141 session_entry = pe_find_session_by_bssid(mac_ctx, assoc_cnf.bssid.bytes, 7142 &session_id); 7143 if (!session_entry) { 7144 pe_err("session does not exist for given bssId"); 7145 goto end; 7146 } 7147 7148 if ((!LIM_IS_AP_ROLE(session_entry)) || 7149 (session_entry->limSmeState != eLIM_SME_NORMAL_STATE)) { 7150 pe_err("Rcvd unexpected msg %X in state %X, in role %X", 7151 msg_type, session_entry->limSmeState, 7152 GET_LIM_SYSTEM_ROLE(session_entry)); 7153 goto end; 7154 } 7155 sta_ds = dph_get_hash_entry(mac_ctx, assoc_cnf.aid, 7156 &session_entry->dph.dphHashTable); 7157 if (!sta_ds) { 7158 pe_err("Rcvd invalid msg %X due to no STA ctx, aid %d, peer "QDF_MAC_ADDR_FMT, 7159 msg_type, assoc_cnf.aid, 7160 QDF_MAC_ADDR_REF(assoc_cnf.peer_macaddr.bytes)); 7161 7162 /* 7163 * send a DISASSOC_IND message to WSM to make sure 7164 * the state in WSM and LIM is the same 7165 */ 7166 lim_send_sme_disassoc_ntf(mac_ctx, assoc_cnf.peer_macaddr.bytes, 7167 eSIR_SME_STA_NOT_ASSOCIATED, 7168 eLIM_PEER_ENTITY_DISASSOC, assoc_cnf.aid, 7169 session_entry->smeSessionId, 7170 session_entry); 7171 goto end; 7172 } 7173 if (qdf_mem_cmp((uint8_t *)sta_ds->staAddr, 7174 (uint8_t *) assoc_cnf.peer_macaddr.bytes, 7175 QDF_MAC_ADDR_SIZE)) { 7176 pe_debug("peerMacAddr mismatched for aid %d, peer "QDF_MAC_ADDR_FMT, 7177 assoc_cnf.aid, 7178 QDF_MAC_ADDR_REF(assoc_cnf.peer_macaddr.bytes)); 7179 goto end; 7180 } 7181 7182 if ((sta_ds->mlmStaContext.mlmState != eLIM_MLM_WT_ASSOC_CNF_STATE) || 7183 ((sta_ds->mlmStaContext.subType == LIM_ASSOC) && 7184 (msg_type != eWNI_SME_ASSOC_CNF)) || 7185 ((sta_ds->mlmStaContext.subType == LIM_REASSOC) && 7186 (msg_type != eWNI_SME_ASSOC_CNF))) { 7187 pe_debug("peer " QDF_MAC_ADDR_FMT " not in WT_ASSOC_CNF_STATE, for aid %d, sta mlmstate %d", 7188 QDF_MAC_ADDR_REF(assoc_cnf.peer_macaddr.bytes), 7189 assoc_cnf.aid, sta_ds->mlmStaContext.mlmState); 7190 goto end; 7191 } 7192 /* 7193 * Deactivate/delete CNF_WAIT timer since ASSOC_CNF 7194 * has been received 7195 */ 7196 pe_debug("Received SME_ASSOC_CNF. Delete Timer"); 7197 lim_deactivate_and_change_per_sta_id_timer(mac_ctx, 7198 eLIM_CNF_WAIT_TIMER, sta_ds->assocId); 7199 7200 if (assoc_cnf.status_code == eSIR_SME_SUCCESS) { 7201 /* 7202 * In BTAMP-AP, PE already finished the WMA_ADD_STA sequence 7203 * when it had received Assoc Request frame. Now, PE just needs 7204 * to send association rsp frame to the requesting BTAMP-STA. 7205 */ 7206 sta_ds->mlmStaContext.mlmState = 7207 eLIM_MLM_LINK_ESTABLISHED_STATE; 7208 sta_ds->mlmStaContext.owe_ie = assoc_cnf.owe_ie; 7209 sta_ds->mlmStaContext.owe_ie_len = assoc_cnf.owe_ie_len; 7210 sta_ds->mlmStaContext.ft_ie = assoc_cnf.ft_ie; 7211 sta_ds->mlmStaContext.ft_ie_len = assoc_cnf.ft_ie_len; 7212 pe_debug("sending Assoc Rsp frame to STA assoc id=%d, tx cb %d", 7213 sta_ds->assocId, assoc_cnf.need_assoc_rsp_tx_cb); 7214 lim_send_assoc_rsp_mgmt_frame( 7215 mac_ctx, QDF_STATUS_SUCCESS, 7216 sta_ds->assocId, sta_ds->staAddr, 7217 sta_ds->mlmStaContext.subType, sta_ds, 7218 session_entry, 7219 assoc_cnf.need_assoc_rsp_tx_cb); 7220 sta_ds->mlmStaContext.owe_ie = NULL; 7221 sta_ds->mlmStaContext.owe_ie_len = 0; 7222 sta_ds->mlmStaContext.ft_ie = NULL; 7223 sta_ds->mlmStaContext.ft_ie_len = 0; 7224 goto end; 7225 } else { 7226 uint8_t add_pre_auth_context = true; 7227 /* 7228 * SME_ASSOC_CNF status is non-success, so STA is not allowed 7229 * to be associated since the HAL sta entry is created for 7230 * denied STA we need to remove this HAL entry. 7231 * So to do that set updateContext to 1 7232 */ 7233 enum wlan_status_code mac_status_code = 7234 STATUS_UNSPECIFIED_FAILURE; 7235 7236 if (!sta_ds->mlmStaContext.updateContext) 7237 sta_ds->mlmStaContext.updateContext = 1; 7238 pe_debug("Recv Assoc Cnf, status Code : %d(assoc id=%d) Reason code: %d", 7239 assoc_cnf.status_code, sta_ds->assocId, 7240 assoc_cnf.mac_status_code); 7241 if (assoc_cnf.mac_status_code) 7242 mac_status_code = assoc_cnf.mac_status_code; 7243 if (assoc_cnf.mac_status_code == STATUS_INVALID_PMKID || 7244 assoc_cnf.mac_status_code == 7245 STATUS_NOT_SUPPORTED_AUTH_ALG) 7246 add_pre_auth_context = false; 7247 7248 lim_reject_association(mac_ctx, sta_ds->staAddr, 7249 sta_ds->mlmStaContext.subType, 7250 add_pre_auth_context, 7251 sta_ds->mlmStaContext.authType, 7252 sta_ds->assocId, true, 7253 mac_status_code, 7254 session_entry); 7255 } 7256 end: 7257 if (((session_entry) && (sta_ds)) && 7258 (session_entry->parsedAssocReq[sta_ds->assocId]) && 7259 !assoc_cnf.need_assoc_rsp_tx_cb) { 7260 assoc_req = (tpSirAssocReq) 7261 session_entry->parsedAssocReq[sta_ds->assocId]; 7262 lim_free_assoc_req_frm_buf(assoc_req); 7263 qdf_mem_free(session_entry->parsedAssocReq[sta_ds->assocId]); 7264 session_entry->parsedAssocReq[sta_ds->assocId] = NULL; 7265 } 7266 qdf_mem_free(assoc_cnf.owe_ie); 7267 qdf_mem_free(assoc_cnf.ft_ie); 7268 } 7269 7270 static void 7271 __lim_process_sme_addts_req(struct mac_context *mac, uint32_t *msg_buf) 7272 { 7273 tpDphHashNode sta; 7274 tSirMacAddr peerMac; 7275 tpSirAddtsReq pSirAddts; 7276 uint32_t timeout; 7277 struct pe_session *pe_session; 7278 uint8_t sessionId; /* PE sessionId */ 7279 uint8_t smesessionId; 7280 7281 if (!msg_buf) { 7282 pe_err("Buffer is Pointing to NULL"); 7283 return; 7284 } 7285 7286 pSirAddts = (tpSirAddtsReq) msg_buf; 7287 smesessionId = pSirAddts->sessionId; 7288 pe_session = pe_find_session_by_bssid(mac, pSirAddts->bssid.bytes, 7289 &sessionId); 7290 if (!pe_session) { 7291 pe_err("Session Does not exist for given bssId"); 7292 lim_send_sme_addts_rsp(mac, pSirAddts->rspReqd, 7293 QDF_STATUS_E_FAILURE, 7294 NULL, pSirAddts->req.tspec, 7295 smesessionId); 7296 return; 7297 } 7298 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ 7299 lim_diag_event_report(mac, WLAN_PE_DIAG_ADDTS_REQ_EVENT, pe_session, 0, 7300 0); 7301 #endif /* FEATURE_WLAN_DIAG_SUPPORT */ 7302 7303 /* if sta 7304 * - verify assoc state 7305 * - send addts request to ap 7306 * - wait for addts response from ap 7307 * if ap, just ignore with error log 7308 */ 7309 pe_debug("Received SME_ADDTS_REQ (TSid %d, UP %d)", 7310 pSirAddts->req.tspec.tsinfo.traffic.tsid, 7311 pSirAddts->req.tspec.tsinfo.traffic.userPrio); 7312 7313 if (!LIM_IS_STA_ROLE(pe_session)) { 7314 pe_err("AddTs received on AP - ignoring"); 7315 goto send_failure_addts_rsp; 7316 } 7317 7318 sta = 7319 dph_get_hash_entry(mac, DPH_STA_HASH_INDEX_PEER, 7320 &pe_session->dph.dphHashTable); 7321 7322 if (!sta) { 7323 pe_err("Cannot find AP context for addts req"); 7324 goto send_failure_addts_rsp; 7325 } 7326 7327 if ((!sta->valid) || (sta->mlmStaContext.mlmState != 7328 eLIM_MLM_LINK_ESTABLISHED_STATE)) { 7329 pe_err("AddTs received in invalid MLM state"); 7330 goto send_failure_addts_rsp; 7331 } 7332 7333 pSirAddts->req.wsmTspecPresent = 0; 7334 pSirAddts->req.wmeTspecPresent = 0; 7335 pSirAddts->req.lleTspecPresent = 0; 7336 7337 if ((sta->wsmEnabled) && 7338 (pSirAddts->req.tspec.tsinfo.traffic.accessPolicy != 7339 SIR_MAC_ACCESSPOLICY_EDCA)) 7340 pSirAddts->req.wsmTspecPresent = 1; 7341 else if (sta->wmeEnabled) 7342 pSirAddts->req.wmeTspecPresent = 1; 7343 else if (sta->lleEnabled) 7344 pSirAddts->req.lleTspecPresent = 1; 7345 else { 7346 pe_warn("ADDTS_REQ ignore - qos is disabled"); 7347 goto send_failure_addts_rsp; 7348 } 7349 7350 if ((pe_session->limSmeState != eLIM_SME_ASSOCIATED_STATE) && 7351 (pe_session->limSmeState != eLIM_SME_LINK_EST_STATE)) { 7352 pe_err("AddTs received in invalid LIMsme state (%d)", 7353 pe_session->limSmeState); 7354 goto send_failure_addts_rsp; 7355 } 7356 7357 if (mac->lim.gLimAddtsSent) { 7358 pe_err("Addts (token %d, tsid %d, up %d) is still pending", 7359 mac->lim.gLimAddtsReq.req.dialogToken, 7360 mac->lim.gLimAddtsReq.req.tspec.tsinfo.traffic.tsid, 7361 mac->lim.gLimAddtsReq.req.tspec.tsinfo.traffic. 7362 userPrio); 7363 goto send_failure_addts_rsp; 7364 } 7365 7366 sir_copy_mac_addr(peerMac, pe_session->bssId); 7367 7368 /* save the addts request */ 7369 mac->lim.gLimAddtsSent = true; 7370 qdf_mem_copy((uint8_t *) &mac->lim.gLimAddtsReq, 7371 (uint8_t *) pSirAddts, sizeof(tSirAddtsReq)); 7372 7373 /* ship out the message now */ 7374 lim_send_addts_req_action_frame(mac, peerMac, &pSirAddts->req, 7375 pe_session); 7376 pe_debug("Sent ADDTS request"); 7377 /* start a timer to wait for the response */ 7378 if (pSirAddts->timeout) 7379 timeout = pSirAddts->timeout; 7380 else 7381 timeout = mac->mlme_cfg->timeouts.addts_rsp_timeout; 7382 7383 timeout = SYS_MS_TO_TICKS(timeout); 7384 if (tx_timer_change(&mac->lim.lim_timers.gLimAddtsRspTimer, timeout, 0) 7385 != TX_SUCCESS) { 7386 pe_err("AddtsRsp timer change failed!"); 7387 goto send_failure_addts_rsp; 7388 } 7389 mac->lim.gLimAddtsRspTimerCount++; 7390 if (tx_timer_change_context(&mac->lim.lim_timers.gLimAddtsRspTimer, 7391 mac->lim.gLimAddtsRspTimerCount) != 7392 TX_SUCCESS) { 7393 pe_err("AddtsRsp timer change failed!"); 7394 goto send_failure_addts_rsp; 7395 } 7396 MTRACE(mac_trace 7397 (mac, TRACE_CODE_TIMER_ACTIVATE, pe_session->peSessionId, 7398 eLIM_ADDTS_RSP_TIMER)); 7399 7400 /* add the sessionId to the timer object */ 7401 mac->lim.lim_timers.gLimAddtsRspTimer.sessionId = sessionId; 7402 if (tx_timer_activate(&mac->lim.lim_timers.gLimAddtsRspTimer) != 7403 TX_SUCCESS) { 7404 pe_err("AddtsRsp timer activation failed!"); 7405 goto send_failure_addts_rsp; 7406 } 7407 return; 7408 7409 send_failure_addts_rsp: 7410 lim_send_sme_addts_rsp(mac, pSirAddts->rspReqd, QDF_STATUS_E_FAILURE, 7411 pe_session, pSirAddts->req.tspec, 7412 smesessionId); 7413 } 7414 7415 #ifdef WLAN_FEATURE_MSCS 7416 static void 7417 __lim_process_sme_mscs_req(struct mac_context *mac, uint32_t *msg_buf) 7418 { 7419 struct qdf_mac_addr peer_mac; 7420 struct mscs_req_info *mscs_req; 7421 struct pe_session *pe_session; 7422 uint8_t pe_session_id; 7423 7424 if (!msg_buf) { 7425 pe_err("Buffer is Pointing to NULL"); 7426 return; 7427 } 7428 7429 mscs_req = (struct mscs_req_info *) msg_buf; 7430 pe_session = pe_find_session_by_bssid(mac, mscs_req->bssid.bytes, 7431 &pe_session_id); 7432 if (!pe_session) { 7433 pe_err("Session Does not exist for bssid: " QDF_MAC_ADDR_FMT, 7434 QDF_MAC_ADDR_REF(mscs_req->bssid.bytes)); 7435 return; 7436 } 7437 7438 if (!LIM_IS_STA_ROLE(pe_session)) { 7439 pe_err("MSCS req received on AP - ignoring"); 7440 return; 7441 } 7442 7443 if (QDF_IS_STATUS_ERROR(wlan_vdev_mlme_is_active(pe_session->vdev))) { 7444 pe_err("mscs req in unexpected vdev SM state:%d", 7445 wlan_vdev_mlme_get_state(pe_session->vdev)); 7446 return; 7447 } 7448 7449 if (mscs_req->is_mscs_req_sent) { 7450 pe_err("MSCS req already sent"); 7451 return; 7452 } 7453 7454 qdf_mem_copy(peer_mac.bytes, pe_session->bssId, QDF_MAC_ADDR_SIZE); 7455 7456 /* save the mscs request */ 7457 mscs_req->is_mscs_req_sent = true; 7458 7459 /* ship out the message now */ 7460 lim_send_mscs_req_action_frame(mac, peer_mac, mscs_req, 7461 pe_session); 7462 } 7463 #else 7464 static inline void 7465 __lim_process_sme_mscs_req(struct mac_context *mac, uint32_t *msg_buf) 7466 { 7467 return; 7468 } 7469 7470 #endif 7471 7472 static void 7473 __lim_process_sme_delts_req(struct mac_context *mac, uint32_t *msg_buf) 7474 { 7475 tSirMacAddr peerMacAddr; 7476 uint8_t ac; 7477 struct mac_ts_info *pTsinfo; 7478 tpSirDeltsReq pDeltsReq = (tpSirDeltsReq) msg_buf; 7479 tpDphHashNode sta = NULL; 7480 struct pe_session *pe_session; 7481 uint8_t sessionId; 7482 uint32_t status = QDF_STATUS_SUCCESS; 7483 uint8_t smesessionId; 7484 7485 smesessionId = pDeltsReq->sessionId; 7486 7487 pe_session = pe_find_session_by_bssid(mac, 7488 pDeltsReq->bssid.bytes, 7489 &sessionId); 7490 if (!pe_session) { 7491 pe_err("Session Does not exist for given bssId"); 7492 status = QDF_STATUS_E_FAILURE; 7493 goto end; 7494 } 7495 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ 7496 lim_diag_event_report(mac, WLAN_PE_DIAG_DELTS_REQ_EVENT, pe_session, 0, 7497 0); 7498 #endif /* FEATURE_WLAN_DIAG_SUPPORT */ 7499 7500 if (QDF_STATUS_SUCCESS != 7501 lim_validate_delts_req(mac, pDeltsReq, peerMacAddr, pe_session)) { 7502 pe_err("lim_validate_delts_req failed"); 7503 status = QDF_STATUS_E_FAILURE; 7504 lim_send_sme_delts_rsp(mac, pDeltsReq, QDF_STATUS_E_FAILURE, 7505 pe_session, smesessionId); 7506 return; 7507 } 7508 7509 pe_debug("Sent DELTS request to station with assocId = %d MacAddr = " 7510 QDF_MAC_ADDR_FMT, 7511 pDeltsReq->aid, QDF_MAC_ADDR_REF(peerMacAddr)); 7512 7513 lim_send_delts_req_action_frame(mac, peerMacAddr, 7514 pDeltsReq->req.wmeTspecPresent, 7515 &pDeltsReq->req.tsinfo, 7516 &pDeltsReq->req.tspec, pe_session); 7517 7518 pTsinfo = 7519 pDeltsReq->req.wmeTspecPresent ? &pDeltsReq->req.tspec. 7520 tsinfo : &pDeltsReq->req.tsinfo; 7521 7522 /* We've successfully send DELTS frame to AP. Update the 7523 * dynamic UAPSD mask. The AC for this TSPEC to be deleted 7524 * is no longer trigger enabled or delivery enabled 7525 */ 7526 lim_set_tspec_uapsd_mask_per_session(mac, pe_session, 7527 pTsinfo, CLEAR_UAPSD_MASK); 7528 7529 /* We're deleting the TSPEC, so this particular AC is no longer 7530 * admitted. PE needs to downgrade the EDCA 7531 * parameters(for the AC for which TS is being deleted) to the 7532 * next best AC for which ACM is not enabled, and send the 7533 * updated values to HAL. 7534 */ 7535 ac = upToAc(pTsinfo->traffic.userPrio); 7536 7537 if (pTsinfo->traffic.direction == SIR_MAC_DIRECTION_UPLINK) { 7538 pe_session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &= 7539 ~(1 << ac); 7540 } else if (pTsinfo->traffic.direction == 7541 SIR_MAC_DIRECTION_DNLINK) { 7542 pe_session->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &= 7543 ~(1 << ac); 7544 } else if (pTsinfo->traffic.direction == 7545 SIR_MAC_DIRECTION_BIDIR) { 7546 pe_session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &= 7547 ~(1 << ac); 7548 pe_session->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &= 7549 ~(1 << ac); 7550 } 7551 7552 lim_set_active_edca_params(mac, pe_session->gLimEdcaParams, 7553 pe_session); 7554 7555 sta = 7556 dph_get_hash_entry(mac, DPH_STA_HASH_INDEX_PEER, 7557 &pe_session->dph.dphHashTable); 7558 if (sta) { 7559 lim_send_edca_params(mac, pe_session->gLimEdcaParamsActive, 7560 pe_session->vdev_id, false); 7561 status = QDF_STATUS_SUCCESS; 7562 } else { 7563 pe_err("Self entry missing in Hash Table"); 7564 status = QDF_STATUS_E_FAILURE; 7565 } 7566 #ifdef FEATURE_WLAN_ESE 7567 lim_send_sme_tsm_ie_ind(mac, pe_session, 0, 0, 0); 7568 #endif 7569 7570 /* send an sme response back */ 7571 end: 7572 lim_send_sme_delts_rsp(mac, pDeltsReq, QDF_STATUS_SUCCESS, pe_session, 7573 smesessionId); 7574 } 7575 7576 void lim_process_sme_addts_rsp_timeout(struct mac_context *mac, uint32_t param) 7577 { 7578 /* fetch the pe_session based on the sessionId */ 7579 struct pe_session *pe_session; 7580 7581 pe_session = pe_find_session_by_session_id(mac, 7582 mac->lim.lim_timers.gLimAddtsRspTimer. 7583 sessionId); 7584 if (!pe_session) { 7585 pe_err("Session Does not exist for given sessionID"); 7586 return; 7587 } 7588 7589 if (!LIM_IS_STA_ROLE(pe_session)) { 7590 pe_warn("AddtsRspTimeout in non-Sta role (%d)", 7591 GET_LIM_SYSTEM_ROLE(pe_session)); 7592 mac->lim.gLimAddtsSent = false; 7593 return; 7594 } 7595 7596 if (!mac->lim.gLimAddtsSent) { 7597 pe_warn("AddtsRspTimeout but no AddtsSent"); 7598 return; 7599 } 7600 7601 if (param != mac->lim.gLimAddtsRspTimerCount) { 7602 pe_err("Invalid AddtsRsp Timer count %d (exp %d)", param, 7603 mac->lim.gLimAddtsRspTimerCount); 7604 return; 7605 } 7606 /* this a real response timeout */ 7607 mac->lim.gLimAddtsSent = false; 7608 mac->lim.gLimAddtsRspTimerCount++; 7609 7610 lim_send_sme_addts_rsp(mac, true, eSIR_SME_ADDTS_RSP_TIMEOUT, 7611 pe_session, mac->lim.gLimAddtsReq.req.tspec, 7612 pe_session->smeSessionId); 7613 } 7614 7615 #ifdef FEATURE_WLAN_ESE 7616 /** 7617 * __lim_process_sme_get_tsm_stats_request() - get tsm stats request 7618 * 7619 * @mac: Pointer to Global MAC structure 7620 * @msg_buf: A pointer to the SME message buffer 7621 * 7622 * Return: None 7623 */ 7624 static void __lim_process_sme_get_tsm_stats_request(struct mac_context *mac, 7625 uint32_t *msg_buf) 7626 { 7627 struct scheduler_msg msgQ = {0}; 7628 7629 msgQ.type = WMA_TSM_STATS_REQ; 7630 msgQ.reserved = 0; 7631 msgQ.bodyptr = msg_buf; 7632 msgQ.bodyval = 0; 7633 MTRACE(mac_trace_msg_tx(mac, NO_SESSION, msgQ.type)); 7634 7635 if (QDF_STATUS_SUCCESS != (wma_post_ctrl_msg(mac, &msgQ))) { 7636 qdf_mem_free(msg_buf); 7637 msg_buf = NULL; 7638 pe_err("Unable to forward request"); 7639 return; 7640 } 7641 } 7642 #endif /* FEATURE_WLAN_ESE */ 7643 7644 static void lim_process_sme_set_addba_accept(struct mac_context *mac_ctx, 7645 struct sme_addba_accept *msg) 7646 { 7647 if (!msg) { 7648 pe_err("Msg Buffer is NULL"); 7649 return; 7650 } 7651 if (!msg->addba_accept) 7652 mac_ctx->reject_addba_req = 1; 7653 else 7654 mac_ctx->reject_addba_req = 0; 7655 } 7656 7657 static void lim_process_sme_update_edca_params(struct mac_context *mac_ctx, 7658 uint32_t vdev_id) 7659 { 7660 struct pe_session *pe_session; 7661 tpDphHashNode sta_ds_ptr; 7662 7663 pe_session = pe_find_session_by_vdev_id(mac_ctx, vdev_id); 7664 if (!pe_session) { 7665 pe_err("Session does not exist: vdev_id %d", vdev_id); 7666 return; 7667 } 7668 pe_session->gLimEdcaParamsActive[QCA_WLAN_AC_BE].no_ack = 7669 mac_ctx->no_ack_policy_cfg[QCA_WLAN_AC_BE]; 7670 pe_session->gLimEdcaParamsActive[QCA_WLAN_AC_BK].no_ack = 7671 mac_ctx->no_ack_policy_cfg[QCA_WLAN_AC_BK]; 7672 pe_session->gLimEdcaParamsActive[QCA_WLAN_AC_VI].no_ack = 7673 mac_ctx->no_ack_policy_cfg[QCA_WLAN_AC_VI]; 7674 pe_session->gLimEdcaParamsActive[QCA_WLAN_AC_VO].no_ack = 7675 mac_ctx->no_ack_policy_cfg[QCA_WLAN_AC_VO]; 7676 sta_ds_ptr = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER, 7677 &pe_session->dph.dphHashTable); 7678 if (sta_ds_ptr) 7679 lim_send_edca_params(mac_ctx, 7680 pe_session->gLimEdcaParamsActive, 7681 pe_session->vdev_id, false); 7682 else 7683 pe_err("Self entry missing in Hash Table"); 7684 } 7685 7686 /** 7687 * lim_process_sme_update_session_edca_txq_params() 7688 * Update the edca tx queue parameters for the vdev 7689 * 7690 * @mac_ctx: Pointer to Global MAC structure 7691 * @msg_buf: Pointer to SME message buffer 7692 * 7693 * Return: None 7694 */ 7695 static void 7696 lim_process_sme_update_session_edca_txq_params(struct mac_context *mac_ctx, 7697 uint32_t *msg_buf) 7698 { 7699 struct sir_update_session_txq_edca_param *msg; 7700 struct pe_session *pe_session; 7701 uint8_t ac; 7702 7703 if (!msg_buf) { 7704 pe_err("Buffer is Pointing to NULL"); 7705 return; 7706 } 7707 7708 msg = (struct sir_update_session_txq_edca_param *)msg_buf; 7709 7710 pe_session = pe_find_session_by_vdev_id(mac_ctx, msg->vdev_id); 7711 if (!pe_session) { 7712 pe_warn("Session does not exist for given vdev_id %d", 7713 msg->vdev_id); 7714 return; 7715 } 7716 7717 ac = msg->txq_edca_params.aci.aci; 7718 pe_debug("received SME Session tx queue update for vdev %d queue %d", 7719 msg->vdev_id, ac); 7720 7721 if ((!LIM_IS_AP_ROLE(pe_session)) || 7722 (pe_session->limSmeState != eLIM_SME_NORMAL_STATE)) { 7723 pe_err("Rcvd edca update req in state %X, in role %X", 7724 pe_session->limSmeState, 7725 GET_LIM_SYSTEM_ROLE(pe_session)); 7726 return; 7727 } 7728 7729 pe_session->gLimEdcaParams[ac].cw.min = 7730 msg->txq_edca_params.cw.min; 7731 pe_session->gLimEdcaParams[ac].cw.max = 7732 msg->txq_edca_params.cw.max; 7733 pe_session->gLimEdcaParams[ac].aci.aci = 7734 msg->txq_edca_params.aci.aci; 7735 pe_session->gLimEdcaParams[ac].aci.aifsn = 7736 msg->txq_edca_params.aci.aifsn; 7737 pe_session->gLimEdcaParams[ac].txoplimit = 7738 msg->txq_edca_params.txoplimit; 7739 7740 lim_send_edca_params(mac_ctx, 7741 pe_session->gLimEdcaParams, 7742 pe_session->vdev_id, false); 7743 } 7744 7745 static void lim_process_sme_update_mu_edca_params(struct mac_context *mac_ctx, 7746 uint32_t vdev_id) 7747 { 7748 struct pe_session *pe_session; 7749 tpDphHashNode sta_ds_ptr; 7750 7751 pe_session = pe_find_session_by_vdev_id(mac_ctx, vdev_id); 7752 if (!pe_session) { 7753 pe_err("Session does not exist: vdev_id %d", vdev_id); 7754 return; 7755 } 7756 sta_ds_ptr = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER, 7757 &pe_session->dph.dphHashTable); 7758 if (sta_ds_ptr) 7759 lim_send_edca_params(mac_ctx, mac_ctx->usr_mu_edca_params, 7760 pe_session->vdev_id, true); 7761 else 7762 pe_err("Self entry missing in Hash Table"); 7763 } 7764 7765 static void 7766 lim_process_sme_cfg_action_frm_in_tb_ppdu(struct mac_context *mac_ctx, 7767 struct sir_cfg_action_frm_tb_ppdu 7768 *msg) 7769 { 7770 if (!msg) { 7771 pe_err("Buffer is NULL"); 7772 return; 7773 } 7774 7775 lim_send_action_frm_tb_ppdu_cfg(mac_ctx, msg->vdev_id, msg->cfg); 7776 } 7777 7778 static void 7779 lim_process_sme_send_vdev_pause(struct mac_context *mac_ctx, 7780 struct sme_vdev_pause *msg) 7781 { 7782 struct pe_session *session; 7783 uint16_t vdev_pause_dur_ms; 7784 7785 if (!msg) { 7786 pe_err("Buffer is NULL"); 7787 return; 7788 } 7789 7790 session = pe_find_session_by_vdev_id(mac_ctx, msg->session_id); 7791 if (!session) { 7792 pe_warn("Session does not exist for given BSSID"); 7793 return; 7794 } 7795 7796 if (!(wlan_vdev_mlme_get_opmode(session->vdev) == QDF_STA_MODE) && 7797 wlan_vdev_mlme_is_mlo_vdev(session->vdev)) { 7798 pe_err("vdev is not ML STA"); 7799 return; 7800 } 7801 7802 vdev_pause_dur_ms = session->beaconParams.beaconInterval * 7803 msg->vdev_pause_duration; 7804 wlan_mlo_send_vdev_pause(mac_ctx->psoc, session->vdev, 7805 msg->session_id, vdev_pause_dur_ms); 7806 } 7807 7808 static void lim_process_sme_update_config(struct mac_context *mac_ctx, 7809 struct update_config *msg) 7810 { 7811 struct pe_session *pe_session; 7812 7813 pe_debug("received eWNI_SME_UPDATE_HT_CONFIG message"); 7814 if (!msg) { 7815 pe_err("Buffer is Pointing to NULL"); 7816 return; 7817 } 7818 7819 pe_session = pe_find_session_by_vdev_id(mac_ctx, msg->vdev_id); 7820 if (!pe_session) { 7821 pe_warn("Session does not exist for given BSSID"); 7822 return; 7823 } 7824 7825 switch (msg->capab) { 7826 case WNI_CFG_HT_CAP_INFO_ADVANCE_CODING: 7827 pe_session->ht_config.adv_coding_cap = msg->value; 7828 break; 7829 case WNI_CFG_HT_CAP_INFO_TX_STBC: 7830 pe_session->ht_config.tx_stbc = msg->value; 7831 break; 7832 case WNI_CFG_HT_CAP_INFO_RX_STBC: 7833 pe_session->ht_config.rx_stbc = msg->value; 7834 break; 7835 case WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ: 7836 pe_session->ht_config.short_gi_20_mhz = msg->value; 7837 break; 7838 case WNI_CFG_HT_CAP_INFO_SHORT_GI_40MHZ: 7839 pe_session->ht_config.short_gi_40_mhz = msg->value; 7840 break; 7841 } 7842 7843 if (LIM_IS_AP_ROLE(pe_session)) { 7844 sch_set_fixed_beacon_fields(mac_ctx, pe_session); 7845 lim_send_beacon_ind(mac_ctx, pe_session, REASON_CONFIG_UPDATE); 7846 } 7847 } 7848 7849 void 7850 lim_send_vdev_restart(struct mac_context *mac, 7851 struct pe_session *pe_session, uint8_t sessionId) 7852 { 7853 struct vdev_mlme_obj *mlme_obj; 7854 7855 if (!pe_session) { 7856 pe_err("Invalid parameters"); 7857 return; 7858 } 7859 7860 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(pe_session->vdev); 7861 if (!mlme_obj) { 7862 pe_err("vdev component object is NULL"); 7863 return; 7864 } 7865 7866 mlme_obj->mgmt.ap.hidden_ssid = pe_session->ssidHidden ? true : false; 7867 7868 vdev_mgr_start_send(mlme_obj, true); 7869 } 7870 7871 static void lim_handle_update_ssid_hidden(struct mac_context *mac_ctx, 7872 struct pe_session *session, uint8_t ssid_hidden) 7873 { 7874 pe_debug("rcvd HIDE_SSID message old HIDE_SSID: %d new HIDE_SSID: %d", 7875 session->ssidHidden, ssid_hidden); 7876 7877 if (ssid_hidden != session->ssidHidden) { 7878 session->ssidHidden = ssid_hidden; 7879 } else { 7880 pe_debug("Dont process HIDE_SSID msg with existing setting"); 7881 return; 7882 } 7883 7884 ap_mlme_set_hidden_ssid_restart_in_progress(session->vdev, true); 7885 wlan_vdev_mlme_sm_deliver_evt(session->vdev, 7886 WLAN_VDEV_SM_EV_FW_VDEV_RESTART, 7887 sizeof(*session), session); 7888 } 7889 7890 /** 7891 * __lim_process_sme_session_update - process SME session update msg 7892 * 7893 * @mac_ctx: Pointer to global mac context 7894 * @msg_buf: Pointer to the received message buffer 7895 * 7896 * Return: None 7897 */ 7898 static void __lim_process_sme_session_update(struct mac_context *mac_ctx, 7899 uint32_t *msg_buf) 7900 { 7901 struct sir_update_session_param *msg; 7902 struct pe_session *session; 7903 7904 if (!msg_buf) { 7905 pe_err("Buffer is Pointing to NULL"); 7906 return; 7907 } 7908 7909 msg = (struct sir_update_session_param *) msg_buf; 7910 7911 session = pe_find_session_by_vdev_id(mac_ctx, msg->vdev_id); 7912 if (!session) { 7913 pe_warn("Session does not exist for given vdev_id %d", 7914 msg->vdev_id); 7915 return; 7916 } 7917 7918 pe_debug("received SME Session update for %d val %d", 7919 msg->param_type, msg->param_val); 7920 switch (msg->param_type) { 7921 case SIR_PARAM_SSID_HIDDEN: 7922 lim_handle_update_ssid_hidden(mac_ctx, session, msg->param_val); 7923 break; 7924 default: 7925 pe_err("Unknown session param"); 7926 break; 7927 } 7928 } 7929 7930 /* 7931 Update the beacon Interval dynamically if beaconInterval is different in MCC 7932 */ 7933 static void __lim_process_sme_change_bi(struct mac_context *mac, 7934 uint32_t *msg_buf) 7935 { 7936 struct wlan_change_bi *pChangeBIParams; 7937 struct pe_session *pe_session; 7938 uint8_t sessionId = 0; 7939 tUpdateBeaconParams beaconParams; 7940 7941 pe_debug("received Update Beacon Interval message"); 7942 7943 if (!msg_buf) { 7944 pe_err("Buffer is Pointing to NULL"); 7945 return; 7946 } 7947 7948 qdf_mem_zero(&beaconParams, sizeof(tUpdateBeaconParams)); 7949 pChangeBIParams = (struct wlan_change_bi *)msg_buf; 7950 7951 pe_session = pe_find_session_by_bssid(mac, 7952 pChangeBIParams->bssid.bytes, 7953 &sessionId); 7954 if (!pe_session) { 7955 pe_err("Session does not exist for given BSSID"); 7956 return; 7957 } 7958 7959 /*Update pe_session Beacon Interval */ 7960 if (pe_session->beaconParams.beaconInterval != 7961 pChangeBIParams->beacon_interval) { 7962 pe_session->beaconParams.beaconInterval = 7963 pChangeBIParams->beacon_interval; 7964 } 7965 7966 /*Update sch beaconInterval */ 7967 if (mac->sch.beacon_interval != 7968 pChangeBIParams->beacon_interval) { 7969 mac->sch.beacon_interval = 7970 pChangeBIParams->beacon_interval; 7971 7972 pe_debug("LIM send update BeaconInterval Indication: %d", 7973 pChangeBIParams->beacon_interval); 7974 7975 if (false == mac->sap.SapDfsInfo.is_dfs_cac_timer_running) { 7976 /* Update beacon */ 7977 sch_set_fixed_beacon_fields(mac, pe_session); 7978 7979 beaconParams.bss_idx = pe_session->vdev_id; 7980 /* Set change in beacon Interval */ 7981 beaconParams.beaconInterval = 7982 pChangeBIParams->beacon_interval; 7983 beaconParams.paramChangeBitmap = 7984 PARAM_BCN_INTERVAL_CHANGED; 7985 lim_send_beacon_params(mac, &beaconParams, pe_session); 7986 } 7987 } 7988 7989 return; 7990 } /*** end __lim_process_sme_change_bi() ***/ 7991 7992 #ifdef QCA_HT_2040_COEX 7993 static void __lim_process_sme_set_ht2040_mode(struct mac_context *mac, 7994 uint32_t *msg_buf) 7995 { 7996 struct set_ht2040_mode *pSetHT2040Mode; 7997 struct pe_session *pe_session; 7998 uint8_t sessionId = 0; 7999 struct scheduler_msg msg = {0}; 8000 tUpdateVHTOpMode *pHtOpMode = NULL; 8001 uint16_t staId = 0; 8002 tpDphHashNode sta = NULL; 8003 8004 pe_debug("received Set HT 20/40 mode message"); 8005 if (!msg_buf) { 8006 pe_err("Buffer is Pointing to NULL"); 8007 return; 8008 } 8009 8010 pSetHT2040Mode = (struct set_ht2040_mode *)msg_buf; 8011 8012 pe_session = pe_find_session_by_bssid(mac, 8013 pSetHT2040Mode->bssid.bytes, 8014 &sessionId); 8015 if (!pe_session) { 8016 pe_debug("Session does not exist for given BSSID: "QDF_MAC_ADDR_FMT, 8017 QDF_MAC_ADDR_REF(pSetHT2040Mode->bssid.bytes)); 8018 return; 8019 } 8020 8021 pe_debug("Update session entry for cbMod=%d", 8022 pSetHT2040Mode->cbMode); 8023 /*Update pe_session HT related fields */ 8024 switch (pSetHT2040Mode->cbMode) { 8025 case PHY_SINGLE_CHANNEL_CENTERED: 8026 pe_session->htSecondaryChannelOffset = 8027 PHY_SINGLE_CHANNEL_CENTERED; 8028 pe_session->htRecommendedTxWidthSet = 0; 8029 if (pSetHT2040Mode->obssEnabled) 8030 pe_session->htSupportedChannelWidthSet 8031 = eHT_CHANNEL_WIDTH_40MHZ; 8032 else 8033 pe_session->htSupportedChannelWidthSet 8034 = eHT_CHANNEL_WIDTH_20MHZ; 8035 break; 8036 case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: 8037 pe_session->htSecondaryChannelOffset = 8038 PHY_DOUBLE_CHANNEL_LOW_PRIMARY; 8039 pe_session->htRecommendedTxWidthSet = 1; 8040 break; 8041 case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: 8042 pe_session->htSecondaryChannelOffset = 8043 PHY_DOUBLE_CHANNEL_HIGH_PRIMARY; 8044 pe_session->htRecommendedTxWidthSet = 1; 8045 break; 8046 default: 8047 pe_err("Invalid cbMode"); 8048 return; 8049 } 8050 8051 /* Update beacon */ 8052 sch_set_fixed_beacon_fields(mac, pe_session); 8053 lim_send_beacon_ind(mac, pe_session, REASON_SET_HT2040); 8054 8055 /* update OP Mode for each associated peer */ 8056 for (staId = 0; staId < pe_session->dph.dphHashTable.size; staId++) { 8057 sta = dph_get_hash_entry(mac, staId, 8058 &pe_session->dph.dphHashTable); 8059 if (!sta) 8060 continue; 8061 8062 if (sta->valid && sta->htSupportedChannelWidthSet) { 8063 pHtOpMode = qdf_mem_malloc(sizeof(tUpdateVHTOpMode)); 8064 if (!pHtOpMode) 8065 return; 8066 pHtOpMode->opMode = 8067 (pe_session->htSecondaryChannelOffset == 8068 PHY_SINGLE_CHANNEL_CENTERED) ? 8069 eHT_CHANNEL_WIDTH_20MHZ : eHT_CHANNEL_WIDTH_40MHZ; 8070 qdf_mem_copy(pHtOpMode->peer_mac, &sta->staAddr, 8071 sizeof(tSirMacAddr)); 8072 pHtOpMode->smesessionId = pe_session->smeSessionId; 8073 8074 msg.type = WMA_UPDATE_OP_MODE; 8075 msg.reserved = 0; 8076 msg.bodyptr = pHtOpMode; 8077 if (!QDF_IS_STATUS_SUCCESS 8078 (scheduler_post_message(QDF_MODULE_ID_PE, 8079 QDF_MODULE_ID_WMA, 8080 QDF_MODULE_ID_WMA, 8081 &msg))) { 8082 pe_err("Not able to post WMA_UPDATE_OP_MODE message to WMA"); 8083 qdf_mem_free(pHtOpMode); 8084 return; 8085 } 8086 pe_debug("Notified FW about OP mode: %d", 8087 pHtOpMode->opMode); 8088 8089 } else 8090 pe_debug("station does not support HT40"); 8091 } 8092 8093 return; 8094 } 8095 #endif 8096 8097 /* -------------------------------------------------------------------- */ 8098 /** 8099 * __lim_process_report_message 8100 * 8101 * FUNCTION: Processes the next received Radio Resource Management message 8102 * 8103 * LOGIC: 8104 * 8105 * ASSUMPTIONS: 8106 * 8107 * NOTE: 8108 * 8109 * @param None 8110 * @return None 8111 */ 8112 8113 static void __lim_process_report_message(struct mac_context *mac, 8114 struct scheduler_msg *pMsg) 8115 { 8116 switch (pMsg->type) { 8117 case eWNI_SME_NEIGHBOR_REPORT_REQ_IND: 8118 rrm_process_neighbor_report_req(mac, pMsg->bodyptr); 8119 break; 8120 case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND: 8121 rrm_process_beacon_report_xmit(mac, pMsg->bodyptr); 8122 break; 8123 case eWNI_SME_CHAN_LOAD_REPORT_RESP_XMIT_IND: 8124 rrm_process_chan_load_report_xmit(mac, pMsg->bodyptr); 8125 break; 8126 default: 8127 pe_err("Invalid msg type: %d", pMsg->type); 8128 } 8129 } 8130 8131 /* -------------------------------------------------------------------- */ 8132 /** 8133 * lim_send_set_max_tx_power_req 8134 * 8135 * FUNCTION: Send SIR_HAL_SET_MAX_TX_POWER_REQ message to change the max tx power. 8136 * 8137 * LOGIC: 8138 * 8139 * ASSUMPTIONS: 8140 * 8141 * NOTE: 8142 * 8143 * @param txPower txPower to be set. 8144 * @param pe_session session entry. 8145 * @return None 8146 */ 8147 QDF_STATUS 8148 lim_send_set_max_tx_power_req(struct mac_context *mac, int8_t txPower, 8149 struct pe_session *pe_session) 8150 { 8151 tpMaxTxPowerParams pMaxTxParams = NULL; 8152 QDF_STATUS retCode = QDF_STATUS_SUCCESS; 8153 struct scheduler_msg msgQ = {0}; 8154 8155 if (!pe_session) { 8156 pe_err("Invalid parameters"); 8157 return QDF_STATUS_E_FAILURE; 8158 } 8159 8160 pMaxTxParams = qdf_mem_malloc(sizeof(tMaxTxPowerParams)); 8161 if (!pMaxTxParams) 8162 return QDF_STATUS_E_NOMEM; 8163 pMaxTxParams->power = txPower; 8164 qdf_mem_copy(pMaxTxParams->bssId.bytes, pe_session->bssId, 8165 QDF_MAC_ADDR_SIZE); 8166 qdf_mem_copy(pMaxTxParams->selfStaMacAddr.bytes, 8167 pe_session->self_mac_addr, 8168 QDF_MAC_ADDR_SIZE); 8169 8170 msgQ.type = WMA_SET_MAX_TX_POWER_REQ; 8171 msgQ.bodyptr = pMaxTxParams; 8172 msgQ.bodyval = 0; 8173 pe_debug("Post WMA_SET_MAX_TX_POWER_REQ to WMA"); 8174 MTRACE(mac_trace_msg_tx(mac, pe_session->peSessionId, msgQ.type)); 8175 retCode = wma_post_ctrl_msg(mac, &msgQ); 8176 if (QDF_STATUS_SUCCESS != retCode) { 8177 pe_err("wma_post_ctrl_msg() failed"); 8178 qdf_mem_free(pMaxTxParams); 8179 } 8180 return retCode; 8181 } 8182 8183 /** 8184 * __lim_process_sme_register_mgmt_frame_req() - process sme reg mgmt frame req 8185 * 8186 * @mac_ctx: Pointer to Global MAC structure 8187 * @msg_buf: pointer to the SME message buffer 8188 * 8189 * This function is called to process eWNI_SME_REGISTER_MGMT_FRAME_REQ message 8190 * from SME. It Register this information within PE. 8191 * 8192 * Return: None 8193 */ 8194 static void __lim_process_sme_register_mgmt_frame_req(struct mac_context *mac_ctx, 8195 uint32_t *msg_buf) 8196 { 8197 QDF_STATUS qdf_status; 8198 struct register_mgmt_frame *sme_req = 8199 (struct register_mgmt_frame *)msg_buf; 8200 struct mgmt_frm_reg_info *lim_mgmt_regn = NULL; 8201 struct mgmt_frm_reg_info *next = NULL; 8202 bool match = false; 8203 8204 pe_nofl_debug("Register Frame: register %d, type %d, match length %d", 8205 sme_req->registerFrame, sme_req->frameType, 8206 sme_req->matchLen); 8207 /* First check whether entry exists already */ 8208 qdf_mutex_acquire(&mac_ctx->lim.lim_frame_register_lock); 8209 qdf_list_peek_front(&mac_ctx->lim.gLimMgmtFrameRegistratinQueue, 8210 (qdf_list_node_t **) &lim_mgmt_regn); 8211 qdf_mutex_release(&mac_ctx->lim.lim_frame_register_lock); 8212 8213 while (lim_mgmt_regn) { 8214 if (lim_mgmt_regn->frameType != sme_req->frameType) 8215 goto skip_match; 8216 if (sme_req->matchLen) { 8217 if ((lim_mgmt_regn->matchLen == sme_req->matchLen) && 8218 (!qdf_mem_cmp(lim_mgmt_regn->matchData, 8219 sme_req->matchData, 8220 lim_mgmt_regn->matchLen))) { 8221 /* found match! */ 8222 match = true; 8223 break; 8224 } 8225 } else { 8226 /* found match! */ 8227 match = true; 8228 break; 8229 } 8230 skip_match: 8231 qdf_mutex_acquire(&mac_ctx->lim.lim_frame_register_lock); 8232 qdf_status = qdf_list_peek_next( 8233 &mac_ctx->lim.gLimMgmtFrameRegistratinQueue, 8234 (qdf_list_node_t *)lim_mgmt_regn, 8235 (qdf_list_node_t **)&next); 8236 qdf_mutex_release(&mac_ctx->lim.lim_frame_register_lock); 8237 lim_mgmt_regn = next; 8238 next = NULL; 8239 } 8240 if (match) { 8241 qdf_mutex_acquire(&mac_ctx->lim.lim_frame_register_lock); 8242 if (QDF_STATUS_SUCCESS == 8243 qdf_list_remove_node( 8244 &mac_ctx->lim.gLimMgmtFrameRegistratinQueue, 8245 (qdf_list_node_t *)lim_mgmt_regn)) 8246 qdf_mem_free(lim_mgmt_regn); 8247 qdf_mutex_release(&mac_ctx->lim.lim_frame_register_lock); 8248 } 8249 8250 if (sme_req->registerFrame) { 8251 lim_mgmt_regn = 8252 qdf_mem_malloc(sizeof(struct mgmt_frm_reg_info) + 8253 sme_req->matchLen); 8254 if (lim_mgmt_regn) { 8255 lim_mgmt_regn->frameType = sme_req->frameType; 8256 lim_mgmt_regn->matchLen = sme_req->matchLen; 8257 lim_mgmt_regn->sessionId = sme_req->sessionId; 8258 if (sme_req->matchLen) { 8259 qdf_mem_copy(lim_mgmt_regn->matchData, 8260 sme_req->matchData, 8261 sme_req->matchLen); 8262 } 8263 qdf_mutex_acquire( 8264 &mac_ctx->lim.lim_frame_register_lock); 8265 qdf_list_insert_front(&mac_ctx->lim. 8266 gLimMgmtFrameRegistratinQueue, 8267 &lim_mgmt_regn->node); 8268 qdf_mutex_release( 8269 &mac_ctx->lim.lim_frame_register_lock); 8270 } 8271 } 8272 return; 8273 } 8274 8275 /** 8276 * lim_register_mgmt_frame_ind_cb() - Save the Management frame 8277 * indication callback in PE. 8278 * @mac_ptr: Mac pointer 8279 * @msg_buf: Msg pointer containing the callback 8280 * 8281 * This function is used save the Management frame 8282 * indication callback in PE. 8283 * 8284 * Return: None 8285 */ 8286 static void lim_register_mgmt_frame_ind_cb(struct mac_context *mac_ctx, 8287 uint32_t *msg_buf) 8288 { 8289 struct sir_sme_mgmt_frame_cb_req *sme_req = 8290 (struct sir_sme_mgmt_frame_cb_req *)msg_buf; 8291 8292 if (!msg_buf) { 8293 pe_err("msg_buf is null"); 8294 return; 8295 } 8296 if (sme_req->callback) 8297 mac_ctx->mgmt_frame_ind_cb = 8298 (sir_mgmt_frame_ind_callback)sme_req->callback; 8299 else 8300 pe_err("sme_req->callback is null"); 8301 } 8302 8303 /** 8304 *__lim_process_send_disassoc_frame() - processes send disassoc frame request 8305 * @mac_ctx: pointer to mac context 8306 * @msg_buf: request message buffer 8307 * 8308 * Process a request from SME to send a disassoc frame 8309 * 8310 * Return: none 8311 */ 8312 static void __lim_process_send_disassoc_frame(struct mac_context *mac_ctx, 8313 void *msg_buf) 8314 { 8315 struct sme_send_disassoc_frm_req *req = msg_buf; 8316 struct pe_session *session_entry; 8317 8318 if (!req) { 8319 pe_err("NULL req"); 8320 return; 8321 } 8322 8323 if ((IEEE80211_IS_MULTICAST(req->peer_mac) && 8324 !QDF_IS_ADDR_BROADCAST(req->peer_mac))) { 8325 pe_err("received invalid SME_DISASSOC_REQ message"); 8326 return; 8327 } 8328 8329 session_entry = pe_find_session_by_vdev_id(mac_ctx, req->vdev_id); 8330 if (!session_entry) { 8331 pe_err("session does not exist for given bssId " 8332 QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(req->peer_mac)); 8333 return; 8334 } 8335 8336 /* Check if MAC address is MLD of the client and 8337 * change it to primary link address to send OTA. 8338 */ 8339 lim_mlo_sap_validate_and_update_ra( 8340 session_entry, (struct qdf_mac_addr *)req->peer_mac); 8341 8342 pe_debug("msg_type %d len %d vdev_id %d mac: " QDF_MAC_ADDR_FMT " reason %d wait_for_ack %d", 8343 req->msg_type, req->length, req->vdev_id, 8344 QDF_MAC_ADDR_REF(req->peer_mac), req->reason, req->wait_for_ack); 8345 8346 lim_send_disassoc_mgmt_frame(mac_ctx, req->reason, req->peer_mac, 8347 session_entry, req->wait_for_ack); 8348 } 8349 8350 /** 8351 * lim_set_pdev_ht_ie() - sends the set HT IE req to FW 8352 * @mac_ctx: Pointer to Global MAC structure 8353 * @pdev_id: pdev id to set the IE. 8354 * @nss: Nss values to prepare the HT IE. 8355 * 8356 * Prepares the HT IE with self capabilities for different 8357 * Nss values and sends the set HT IE req to FW. 8358 * 8359 * Return: None 8360 */ 8361 static void lim_set_pdev_ht_ie(struct mac_context *mac_ctx, uint8_t pdev_id, 8362 uint8_t nss) 8363 { 8364 struct set_ie_param *ie_params; 8365 struct scheduler_msg msg = {0}; 8366 QDF_STATUS rc = QDF_STATUS_SUCCESS; 8367 const uint8_t *p_ie = NULL; 8368 tHtCaps *p_ht_cap; 8369 int i; 8370 8371 for (i = 1; i <= nss; i++) { 8372 ie_params = qdf_mem_malloc(sizeof(*ie_params)); 8373 if (!ie_params) 8374 return; 8375 ie_params->nss = i; 8376 ie_params->pdev_id = pdev_id; 8377 ie_params->ie_type = DOT11_HT_IE; 8378 /* 2 for IE len and EID */ 8379 ie_params->ie_len = 2 + sizeof(tHtCaps); 8380 ie_params->ie_ptr = qdf_mem_malloc(ie_params->ie_len); 8381 if (!ie_params->ie_ptr) { 8382 qdf_mem_free(ie_params); 8383 return; 8384 } 8385 *ie_params->ie_ptr = WLAN_ELEMID_HTCAP_ANA; 8386 *(ie_params->ie_ptr + 1) = ie_params->ie_len - 2; 8387 lim_set_ht_caps(mac_ctx, ie_params->ie_ptr, 8388 ie_params->ie_len); 8389 8390 if (NSS_1x1_MODE == i) { 8391 p_ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_HTCAPS, 8392 ie_params->ie_ptr, ie_params->ie_len); 8393 if (!p_ie) { 8394 qdf_mem_free(ie_params->ie_ptr); 8395 qdf_mem_free(ie_params); 8396 pe_err("failed to get IE ptr"); 8397 return; 8398 } 8399 p_ht_cap = (tHtCaps *)&p_ie[2]; 8400 p_ht_cap->supportedMCSSet[1] = 0; 8401 p_ht_cap->txSTBC = 0; 8402 } 8403 8404 msg.type = WMA_SET_PDEV_IE_REQ; 8405 msg.bodyptr = ie_params; 8406 msg.bodyval = 0; 8407 8408 rc = wma_post_ctrl_msg(mac_ctx, &msg); 8409 if (rc != QDF_STATUS_SUCCESS) { 8410 pe_err("wma_post_ctrl_msg() return failure"); 8411 qdf_mem_free(ie_params->ie_ptr); 8412 qdf_mem_free(ie_params); 8413 return; 8414 } 8415 } 8416 } 8417 8418 /** 8419 * lim_set_pdev_vht_ie() - sends the set VHT IE to req FW 8420 * @mac_ctx: Pointer to Global MAC structure 8421 * @pdev_id: pdev id to set the IE. 8422 * @nss: Nss values to prepare the VHT IE. 8423 * 8424 * Prepares the VHT IE with self capabilities for different 8425 * Nss values and sends the set VHT IE req to FW. 8426 * 8427 * Return: None 8428 */ 8429 static void lim_set_pdev_vht_ie(struct mac_context *mac_ctx, uint8_t pdev_id, 8430 uint8_t nss) 8431 { 8432 struct set_ie_param *ie_params; 8433 struct scheduler_msg msg = {0}; 8434 QDF_STATUS rc = QDF_STATUS_SUCCESS; 8435 const uint8_t *p_ie = NULL; 8436 tSirMacVHTCapabilityInfo *vht_cap; 8437 int i; 8438 tSirVhtMcsInfo *vht_mcs; 8439 8440 for (i = 1; i <= nss; i++) { 8441 ie_params = qdf_mem_malloc(sizeof(*ie_params)); 8442 if (!ie_params) 8443 return; 8444 ie_params->nss = i; 8445 ie_params->pdev_id = pdev_id; 8446 ie_params->ie_type = DOT11_VHT_IE; 8447 /* 2 for IE len and EID */ 8448 ie_params->ie_len = 2 + sizeof(tSirMacVHTCapabilityInfo) + 8449 sizeof(tSirVhtMcsInfo); 8450 ie_params->ie_ptr = qdf_mem_malloc(ie_params->ie_len); 8451 if (!ie_params->ie_ptr) { 8452 qdf_mem_free(ie_params); 8453 return; 8454 } 8455 *ie_params->ie_ptr = WLAN_ELEMID_VHTCAP; 8456 *(ie_params->ie_ptr + 1) = ie_params->ie_len - 2; 8457 lim_set_vht_caps(mac_ctx, ie_params->ie_ptr, ie_params->ie_len); 8458 8459 if (NSS_1x1_MODE == i) { 8460 p_ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_VHTCAPS, 8461 ie_params->ie_ptr, ie_params->ie_len); 8462 if (!p_ie) { 8463 qdf_mem_free(ie_params->ie_ptr); 8464 qdf_mem_free(ie_params); 8465 pe_err("failed to get IE ptr"); 8466 return; 8467 } 8468 vht_cap = (tSirMacVHTCapabilityInfo *)&p_ie[2]; 8469 vht_cap->txSTBC = 0; 8470 vht_mcs = 8471 (tSirVhtMcsInfo *)&p_ie[2 + 8472 sizeof(tSirMacVHTCapabilityInfo)]; 8473 vht_mcs->rxMcsMap |= DISABLE_NSS2_MCS; 8474 vht_mcs->rxHighest = 8475 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1; 8476 vht_mcs->txMcsMap |= DISABLE_NSS2_MCS; 8477 vht_mcs->txHighest = 8478 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1; 8479 } 8480 msg.type = WMA_SET_PDEV_IE_REQ; 8481 msg.bodyptr = ie_params; 8482 msg.bodyval = 0; 8483 8484 rc = wma_post_ctrl_msg(mac_ctx, &msg); 8485 if (rc != QDF_STATUS_SUCCESS) { 8486 pe_err("wma_post_ctrl_msg failure"); 8487 qdf_mem_free(ie_params->ie_ptr); 8488 qdf_mem_free(ie_params); 8489 return; 8490 } 8491 } 8492 } 8493 8494 /** 8495 * lim_process_set_vdev_ies_per_band() - process the set vdev IE req 8496 * @mac_ctx: Pointer to Global MAC structure 8497 * @msg_buf: Pointer to the SME message buffer 8498 * 8499 * This function is called by limProcessMessageQueue(). This function sets the 8500 * VDEV IEs to the FW. 8501 * 8502 * Return: None 8503 */ 8504 static void lim_process_set_vdev_ies_per_band(struct mac_context *mac_ctx, 8505 uint32_t *msg_buf) 8506 { 8507 struct sir_set_vdev_ies_per_band *p_msg = 8508 (struct sir_set_vdev_ies_per_band *)msg_buf; 8509 8510 if (!p_msg) { 8511 pe_err("NULL p_msg"); 8512 return; 8513 } 8514 8515 pe_debug("rcvd set vdev ie per band req vdev_id = %d", 8516 p_msg->vdev_id); 8517 8518 if (lim_send_ies_per_band(mac_ctx, p_msg->vdev_id, 8519 p_msg->dot11_mode, p_msg->device_mode) != 8520 QDF_STATUS_SUCCESS) 8521 pe_err("Unable to send HT/VHT Cap to FW"); 8522 } 8523 8524 /** 8525 * lim_process_set_pdev_IEs() - process the set pdev IE req 8526 * @mac_ctx: Pointer to Global MAC structure 8527 * @msg_buf: Pointer to the SME message buffer 8528 * 8529 * This function is called by limProcessMessageQueue(). This 8530 * function sets the PDEV IEs to the FW. 8531 * 8532 * Return: None 8533 */ 8534 static void lim_process_set_pdev_IEs(struct mac_context *mac_ctx, uint32_t *msg_buf) 8535 { 8536 struct sir_set_ht_vht_cfg *ht_vht_cfg; 8537 8538 ht_vht_cfg = (struct sir_set_ht_vht_cfg *)msg_buf; 8539 8540 if (!ht_vht_cfg) { 8541 pe_err("NULL ht_vht_cfg"); 8542 return; 8543 } 8544 8545 pe_debug("rcvd set pdev ht vht ie req with nss = %d", 8546 ht_vht_cfg->nss); 8547 lim_set_pdev_ht_ie(mac_ctx, ht_vht_cfg->pdev_id, ht_vht_cfg->nss); 8548 8549 if (IS_DOT11_MODE_VHT(ht_vht_cfg->dot11mode)) 8550 lim_set_pdev_vht_ie(mac_ctx, ht_vht_cfg->pdev_id, 8551 ht_vht_cfg->nss); 8552 } 8553 8554 /** 8555 * lim_process_sme_update_access_policy_vendor_ie: function updates vendor IE 8556 * 8557 * access policy 8558 * @mac_ctx: pointer to mac context 8559 * @msg: message buffer 8560 * 8561 * function processes vendor IE and access policy from SME and updates PE 8562 * 8563 * session entry 8564 * 8565 * return: none 8566 */ 8567 static void lim_process_sme_update_access_policy_vendor_ie( 8568 struct mac_context *mac_ctx, 8569 uint32_t *msg) 8570 { 8571 struct sme_update_access_policy_vendor_ie *update_vendor_ie; 8572 struct pe_session *pe_session_entry; 8573 uint16_t num_bytes; 8574 8575 if (!msg) { 8576 pe_err("Buffer is Pointing to NULL"); 8577 return; 8578 } 8579 update_vendor_ie = (struct sme_update_access_policy_vendor_ie *) msg; 8580 pe_session_entry = pe_find_session_by_vdev_id(mac_ctx, 8581 update_vendor_ie->vdev_id); 8582 8583 if (!pe_session_entry) { 8584 pe_err("Session does not exist for given vdev_id %d", 8585 update_vendor_ie->vdev_id); 8586 return; 8587 } 8588 if (pe_session_entry->access_policy_vendor_ie) 8589 qdf_mem_free(pe_session_entry->access_policy_vendor_ie); 8590 8591 num_bytes = update_vendor_ie->ie[1] + 2; 8592 pe_session_entry->access_policy_vendor_ie = qdf_mem_malloc(num_bytes); 8593 if (!pe_session_entry->access_policy_vendor_ie) 8594 return; 8595 qdf_mem_copy(pe_session_entry->access_policy_vendor_ie, 8596 &update_vendor_ie->ie[0], num_bytes); 8597 8598 pe_session_entry->access_policy = update_vendor_ie->access_policy; 8599 } 8600 8601 QDF_STATUS lim_sta_mlme_vdev_disconnect_bss(struct vdev_mlme_obj *vdev_mlme, 8602 uint16_t data_len, void *data) 8603 { 8604 struct mac_context *mac_ctx; 8605 struct scheduler_msg *msg = (struct scheduler_msg *)data; 8606 8607 mac_ctx = cds_get_context(QDF_MODULE_ID_PE); 8608 if (!mac_ctx) { 8609 if (data) 8610 qdf_mem_free(data); 8611 return QDF_STATUS_E_INVAL; 8612 } 8613 pe_debug("Vdev %d: disconnect bss callback type:(%d)", 8614 wlan_vdev_get_id(vdev_mlme->vdev), msg->type); 8615 8616 switch (msg->type) { 8617 case eWNI_SME_DEAUTH_REQ: 8618 __lim_process_sme_deauth_req(mac_ctx, 8619 (uint32_t *)msg->bodyptr); 8620 break; 8621 case eWNI_SME_DISASSOC_CNF: 8622 case eWNI_SME_DEAUTH_CNF: 8623 __lim_process_sme_disassoc_cnf(mac_ctx, 8624 (uint32_t *)msg->bodyptr); 8625 break; 8626 case eWNI_SME_DISASSOC_REQ: 8627 __lim_process_sme_disassoc_req(mac_ctx, 8628 (uint32_t *)msg->bodyptr); 8629 break; 8630 default: 8631 pe_err("Vdev %d Wrong message type received %d", 8632 wlan_vdev_get_id(vdev_mlme->vdev), msg->type); 8633 } 8634 return QDF_STATUS_SUCCESS; 8635 } 8636 8637 static void lim_process_sme_disassoc_cnf(struct mac_context *mac_ctx, 8638 struct scheduler_msg *msg) 8639 { 8640 struct disassoc_cnf sme_disassoc_cnf; 8641 struct pe_session *session; 8642 uint8_t session_id; 8643 uint32_t *err_msg = NULL; 8644 QDF_STATUS status; 8645 8646 qdf_mem_copy(&sme_disassoc_cnf, msg->bodyptr, sizeof(sme_disassoc_cnf)); 8647 8648 session = pe_find_session_by_bssid(mac_ctx, 8649 sme_disassoc_cnf.bssid.bytes, 8650 &session_id); 8651 if (!session) { 8652 pe_err("session not found for bssid:"QDF_MAC_ADDR_FMT, 8653 QDF_MAC_ADDR_REF(sme_disassoc_cnf.bssid.bytes)); 8654 status = lim_prepare_disconnect_done_ind 8655 (mac_ctx, &err_msg, 8656 sme_disassoc_cnf.vdev_id, 8657 eSIR_SME_INVALID_SESSION, 8658 NULL); 8659 8660 if (QDF_IS_STATUS_SUCCESS(status)) 8661 lim_send_sme_disassoc_deauth_ntf(mac_ctx, 8662 QDF_STATUS_SUCCESS, 8663 err_msg); 8664 return; 8665 } 8666 8667 __lim_process_sme_disassoc_cnf(mac_ctx, (uint32_t *)msg->bodyptr); 8668 } 8669 8670 static void lim_process_sme_disassoc_req(struct mac_context *mac_ctx, 8671 struct scheduler_msg *msg) 8672 { 8673 struct disassoc_req disassoc_req; 8674 struct pe_session *session; 8675 uint8_t session_id; 8676 8677 qdf_mem_copy(&disassoc_req, msg->bodyptr, sizeof(struct disassoc_req)); 8678 8679 session = pe_find_session_by_bssid(mac_ctx, 8680 disassoc_req.bssid.bytes, 8681 &session_id); 8682 if (!session) { 8683 pe_err("session not found for bssid:"QDF_MAC_ADDR_FMT, 8684 QDF_MAC_ADDR_REF(disassoc_req.bssid.bytes)); 8685 lim_send_sme_disassoc_ntf(mac_ctx, 8686 disassoc_req.peer_macaddr.bytes, 8687 eSIR_SME_INVALID_PARAMETERS, 8688 eLIM_HOST_DISASSOC, 1, 8689 disassoc_req.sessionId, NULL); 8690 8691 return; 8692 } 8693 8694 __lim_process_sme_disassoc_req(mac_ctx, (uint32_t *)msg->bodyptr); 8695 } 8696 8697 static void lim_process_sme_deauth_req(struct mac_context *mac_ctx, 8698 struct scheduler_msg *msg) 8699 { 8700 struct deauth_req sme_deauth_req; 8701 struct pe_session *session; 8702 uint8_t session_id; 8703 8704 qdf_mem_copy(&sme_deauth_req, msg->bodyptr, sizeof(sme_deauth_req)); 8705 8706 session = pe_find_session_by_bssid(mac_ctx, 8707 sme_deauth_req.bssid.bytes, 8708 &session_id); 8709 if (!session) { 8710 pe_err("session not found for bssid:"QDF_MAC_ADDR_FMT, 8711 QDF_MAC_ADDR_REF(sme_deauth_req.bssid.bytes)); 8712 lim_send_sme_deauth_ntf(mac_ctx, 8713 sme_deauth_req.peer_macaddr.bytes, 8714 eSIR_SME_INVALID_PARAMETERS, 8715 eLIM_HOST_DEAUTH, 1, 8716 sme_deauth_req.vdev_id); 8717 8718 return; 8719 } 8720 8721 __lim_process_sme_deauth_req(mac_ctx, (uint32_t *)msg->bodyptr); 8722 } 8723 8724 void lim_send_bcn_rsp(struct mac_context *mac_ctx, tpSendbeaconParams rsp) 8725 { 8726 if (!rsp) { 8727 pe_err("rsp is NULL"); 8728 return; 8729 } 8730 8731 /* Success case response is sent from beacon_tx completion/timeout */ 8732 if (rsp->reason == REASON_CH_WIDTH_UPDATE && 8733 QDF_IS_STATUS_SUCCESS(rsp->status)) 8734 return; 8735 8736 pe_debug("Send beacon resp status %d for reason %d", 8737 rsp->status, rsp->reason); 8738 8739 lim_nss_or_ch_width_update_rsp(mac_ctx, rsp->vdev_id, 8740 rsp->status, rsp->reason); 8741 } 8742 8743 static void 8744 lim_update_bcn_with_new_ch_width(struct mac_context *mac_ctx, 8745 struct pe_session *session, 8746 enum phy_ch_width ch_width) 8747 { 8748 QDF_STATUS status; 8749 8750 session->gLimOperatingMode.present = 1; 8751 session->gLimOperatingMode.chanWidth = ch_width; 8752 8753 pe_debug("ch width %d", 8754 session->gLimOperatingMode.chanWidth); 8755 8756 session->bw_update_include_ch_sw_ie = true; 8757 status = qdf_mc_timer_start(&session->ap_ecsa_timer, 8758 MAX_WAIT_FOR_CH_WIDTH_UPDATE_COMPLETE); 8759 if (QDF_IS_STATUS_ERROR(status)) 8760 pe_err("cannot start ap_ecsa_timer"); 8761 8762 /* Send nss update request from here */ 8763 status = sch_set_fixed_beacon_fields(mac_ctx, session); 8764 if (QDF_IS_STATUS_ERROR(status)) { 8765 pe_err("Unable to set op mode IE in beacon"); 8766 goto end; 8767 } 8768 8769 status = lim_send_beacon_ind(mac_ctx, session, 8770 REASON_CH_WIDTH_UPDATE); 8771 if (QDF_IS_STATUS_SUCCESS(status)) 8772 return; 8773 8774 pe_err("Unable to send beacon"); 8775 end: 8776 /* 8777 * send resp only in case of failure, 8778 * success case response will be from wma. 8779 */ 8780 lim_nss_or_ch_width_update_rsp(mac_ctx, session->vdev_id, status, 8781 REASON_CH_WIDTH_UPDATE); 8782 } 8783 8784 static enum phy_ch_width 8785 lim_calculate_peer_ch_width(struct pe_session *session, 8786 uint8_t *mac_addr, 8787 enum phy_ch_width new_ch_width) 8788 { 8789 enum phy_ch_width peer_org_bw, updated_bw; 8790 struct peer_oper_mode_event data = {0}; 8791 QDF_STATUS status; 8792 8793 peer_org_bw = wlan_mlme_get_peer_ch_width( 8794 wlan_vdev_get_psoc(session->vdev), mac_addr); 8795 8796 updated_bw = new_ch_width; 8797 8798 qdf_mem_copy(&data.peer_mac_address.bytes, mac_addr, QDF_MAC_ADDR_SIZE); 8799 status = wlan_mlme_get_peer_indicated_ch_width( 8800 wlan_vdev_get_psoc(session->vdev), &data); 8801 if (QDF_IS_STATUS_SUCCESS(status)) 8802 updated_bw = data.new_bw; 8803 8804 pe_debug("Peer: " QDF_MAC_ADDR_FMT " original bw: %d, updated bw: %d, new bw: %d", 8805 QDF_MAC_ADDR_REF(mac_addr), peer_org_bw, updated_bw, 8806 new_ch_width); 8807 8808 return qdf_min(peer_org_bw, qdf_min(updated_bw, new_ch_width)); 8809 } 8810 8811 static void 8812 lim_update_new_ch_width_to_fw(struct mac_context *mac_ctx, 8813 struct pe_session *session, 8814 enum phy_ch_width ch_bandwidth) 8815 { 8816 uint8_t i; 8817 tpDphHashNode psta; 8818 tUpdateVHTOpMode params; 8819 8820 for (i = 0; i <= mac_ctx->lim.max_sta_of_pe_session; i++) { 8821 psta = session->dph.dphHashTable.pDphNodeArray + i; 8822 if (!psta || !psta->added) 8823 continue; 8824 8825 params.opMode = lim_calculate_peer_ch_width(session, 8826 psta->staAddr, ch_bandwidth); 8827 params.smesessionId = session->smeSessionId; 8828 qdf_mem_copy(params.peer_mac, psta->staAddr, 8829 sizeof(tSirMacAddr)); 8830 8831 lim_send_mode_update(mac_ctx, ¶ms, session); 8832 } 8833 } 8834 8835 /** 8836 * lim_process_sap_ch_width_update() - process sme nss update req 8837 * 8838 * @mac_ctx: Pointer to Global MAC structure 8839 * @msg_buf: pointer to the SME message buffer 8840 * 8841 * This function processes SME request messages from HDD or upper layer 8842 * application. 8843 * 8844 * Return: None 8845 */ 8846 static void 8847 lim_process_sap_ch_width_update(struct mac_context *mac_ctx, 8848 uint32_t *msg_buf) 8849 { 8850 struct sir_sap_ch_width_update *req; 8851 struct pe_session *session = NULL; 8852 uint8_t vdev_id; 8853 struct sir_bcn_update_rsp *param; 8854 struct scheduler_msg msg_return = {0}; 8855 uint8_t primary_channel; 8856 struct ch_params ch_params = {0}; 8857 8858 if (!msg_buf) { 8859 pe_err("Buffer is Pointing to NULL"); 8860 return; 8861 } 8862 8863 req = (struct sir_sap_ch_width_update *)msg_buf; 8864 vdev_id = req->vdev_id; 8865 session = pe_find_session_by_vdev_id(mac_ctx, req->vdev_id); 8866 if (!session) { 8867 pe_err("vdev %d session not found", req->vdev_id); 8868 goto fail; 8869 } 8870 8871 if (session->opmode != QDF_SAP_MODE) { 8872 pe_err("Invalid opmode %d", session->opmode); 8873 goto fail; 8874 } 8875 8876 ch_params.ch_width = req->ch_width; 8877 wlan_reg_set_channel_params_for_pwrmode(mac_ctx->pdev, 8878 session->curr_op_freq, 8879 0, 8880 &ch_params, 8881 REG_CURRENT_PWR_MODE); 8882 8883 session->gLimChannelSwitch.switchCount = 1; 8884 session->gLimChannelSwitch.sw_target_freq = session->curr_op_freq; 8885 primary_channel = wlan_reg_freq_to_chan(mac_ctx->pdev, 8886 session->curr_op_freq); 8887 session->gLimChannelSwitch.primaryChannel = primary_channel; 8888 session->gLimChannelSwitch.ch_width = req->ch_width; 8889 session->gLimChannelSwitch.ch_center_freq_seg0 = 8890 ch_params.center_freq_seg0; 8891 session->gLimChannelSwitch.ch_center_freq_seg1 = 8892 ch_params.center_freq_seg1; 8893 8894 wlan_mlme_set_ap_oper_ch_width(session->vdev, req->ch_width); 8895 8896 /* Send ECSA to the peers */ 8897 send_extended_chan_switch_action_frame(mac_ctx, 8898 session->curr_op_freq, 8899 req->ch_width, session); 8900 8901 /* Send beacon template to firmware */ 8902 lim_update_bcn_with_new_ch_width(mac_ctx, session, req->ch_width); 8903 /* Send updated bw info of each peer to firmware */ 8904 lim_update_new_ch_width_to_fw(mac_ctx, session, req->ch_width); 8905 8906 /* 8907 * Release the SER command only after this, otherwise it may cause 8908 * out of sync issues if any other WMI commands go to fw 8909 */ 8910 return; 8911 8912 fail: 8913 pe_err("vdev %d: send bandwidth update fail", vdev_id); 8914 param = qdf_mem_malloc(sizeof(*param)); 8915 if (param) { 8916 param->status = QDF_STATUS_E_FAILURE; 8917 param->vdev_id = INVALID_VDEV_ID; 8918 param->reason = REASON_CH_WIDTH_UPDATE; 8919 } 8920 msg_return.type = eWNI_SME_SAP_CH_WIDTH_UPDATE_RSP; 8921 msg_return.bodyptr = param; 8922 msg_return.bodyval = 0; 8923 sys_process_mmh_msg(mac_ctx, &msg_return); 8924 } 8925 8926 /** 8927 * lim_process_sme_req_messages() 8928 * 8929 ***FUNCTION: 8930 * This function is called by limProcessMessageQueue(). This 8931 * function processes SME request messages from HDD or upper layer 8932 * application. 8933 * 8934 ***LOGIC: 8935 * 8936 ***ASSUMPTIONS: 8937 * 8938 ***NOTE: 8939 * 8940 * @param mac Pointer to Global MAC structure 8941 * @param msgType Indicates the SME message type 8942 * @param *msg_buf A pointer to the SME message buffer 8943 * @return Boolean - true - if msg_buf is consumed and can be freed. 8944 * false - if msg_buf is not to be freed. 8945 */ 8946 8947 bool lim_process_sme_req_messages(struct mac_context *mac, 8948 struct scheduler_msg *pMsg) 8949 { 8950 /* 8951 * Set this flag to false within case block of any following message, 8952 * that doesn't want msg_buf to be freed. 8953 */ 8954 bool bufConsumed = true; 8955 uint32_t *msg_buf = pMsg->bodyptr; 8956 8957 pe_nofl_debug("LIM handle SME Msg %s(%d)", 8958 lim_msg_str(pMsg->type), pMsg->type); 8959 8960 /* If no insert NOA required then execute the code below */ 8961 8962 switch (pMsg->type) { 8963 case eWNI_SME_SYS_READY_IND: 8964 bufConsumed = __lim_process_sme_sys_ready_ind(mac, msg_buf); 8965 break; 8966 8967 case eWNI_SME_START_BSS_REQ: 8968 bufConsumed = __lim_process_sme_start_bss_req(mac, pMsg); 8969 break; 8970 case eWNI_SME_DISASSOC_REQ: 8971 lim_process_sme_disassoc_req(mac, pMsg); 8972 break; 8973 8974 case eWNI_SME_DISASSOC_CNF: 8975 case eWNI_SME_DEAUTH_CNF: 8976 lim_process_sme_disassoc_cnf(mac, pMsg); 8977 break; 8978 8979 case eWNI_SME_DEAUTH_REQ: 8980 lim_process_sme_deauth_req(mac, pMsg); 8981 break; 8982 8983 case eWNI_SME_SEND_DISASSOC_FRAME: 8984 __lim_process_send_disassoc_frame(mac, msg_buf); 8985 break; 8986 8987 case eWNI_SME_STOP_BSS_REQ: 8988 bufConsumed = __lim_process_sme_stop_bss_req(mac, pMsg); 8989 break; 8990 8991 case eWNI_SME_ASSOC_CNF: 8992 if (pMsg->type == eWNI_SME_ASSOC_CNF) 8993 pe_debug("Received ASSOC_CNF message"); 8994 __lim_process_sme_assoc_cnf_new(mac, pMsg->type, 8995 msg_buf); 8996 break; 8997 8998 case eWNI_SME_ADDTS_REQ: 8999 pe_debug("Received ADDTS_REQ message"); 9000 __lim_process_sme_addts_req(mac, msg_buf); 9001 break; 9002 9003 case eWNI_SME_MSCS_REQ: 9004 pe_debug("Received MSCS_REQ message"); 9005 __lim_process_sme_mscs_req(mac, msg_buf); 9006 break; 9007 9008 case eWNI_SME_DELTS_REQ: 9009 pe_debug("Received DELTS_REQ message"); 9010 __lim_process_sme_delts_req(mac, msg_buf); 9011 break; 9012 9013 case SIR_LIM_ADDTS_RSP_TIMEOUT: 9014 pe_debug("Received SIR_LIM_ADDTS_RSP_TIMEOUT message"); 9015 lim_process_sme_addts_rsp_timeout(mac, pMsg->bodyval); 9016 break; 9017 9018 #ifdef FEATURE_WLAN_ESE 9019 case eWNI_SME_GET_TSM_STATS_REQ: 9020 __lim_process_sme_get_tsm_stats_request(mac, msg_buf); 9021 bufConsumed = false; 9022 break; 9023 #endif /* FEATURE_WLAN_ESE */ 9024 case eWNI_SME_SESSION_UPDATE_PARAM: 9025 __lim_process_sme_session_update(mac, msg_buf); 9026 break; 9027 case eWNI_SME_CHNG_MCC_BEACON_INTERVAL: 9028 /* Update the beaconInterval */ 9029 __lim_process_sme_change_bi(mac, msg_buf); 9030 break; 9031 9032 #ifdef QCA_HT_2040_COEX 9033 case eWNI_SME_SET_HT_2040_MODE: 9034 __lim_process_sme_set_ht2040_mode(mac, msg_buf); 9035 break; 9036 #endif 9037 9038 case eWNI_SME_NEIGHBOR_REPORT_REQ_IND: 9039 case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND: 9040 case eWNI_SME_CHAN_LOAD_REPORT_RESP_XMIT_IND: 9041 __lim_process_report_message(mac, pMsg); 9042 break; 9043 case eWNI_SME_FT_AGGR_QOS_REQ: 9044 lim_process_ft_aggr_qos_req(mac, msg_buf); 9045 break; 9046 9047 case eWNI_SME_REGISTER_MGMT_FRAME_REQ: 9048 __lim_process_sme_register_mgmt_frame_req(mac, msg_buf); 9049 break; 9050 #ifdef FEATURE_WLAN_TDLS 9051 case eWNI_SME_TDLS_SEND_MGMT_REQ: 9052 lim_process_sme_tdls_mgmt_send_req(mac, msg_buf); 9053 break; 9054 case eWNI_SME_TDLS_ADD_STA_REQ: 9055 lim_process_sme_tdls_add_sta_req(mac, msg_buf); 9056 break; 9057 case eWNI_SME_TDLS_DEL_STA_REQ: 9058 lim_process_sme_tdls_del_sta_req(mac, msg_buf); 9059 break; 9060 #endif 9061 case eWNI_SME_CHANNEL_CHANGE_REQ: 9062 lim_process_sme_channel_change_request(mac, msg_buf); 9063 break; 9064 9065 case eWNI_SME_START_BEACON_REQ: 9066 lim_process_sme_start_beacon_req(mac, msg_buf); 9067 break; 9068 9069 case eWNI_SME_DFS_BEACON_CHAN_SW_IE_REQ: 9070 lim_process_sme_dfs_csa_ie_request(mac, msg_buf); 9071 break; 9072 9073 case eWNI_SME_UPDATE_ADDITIONAL_IES: 9074 lim_process_update_add_ies(mac, msg_buf); 9075 break; 9076 9077 case eWNI_SME_MODIFY_ADDITIONAL_IES: 9078 lim_process_modify_add_ies(mac, msg_buf); 9079 break; 9080 case eWNI_SME_SET_HW_MODE_REQ: 9081 lim_process_set_hw_mode(mac, msg_buf); 9082 break; 9083 case eWNI_SME_NSS_UPDATE_REQ: 9084 lim_process_nss_update_request(mac, msg_buf); 9085 break; 9086 case eWNI_SME_SET_DUAL_MAC_CFG_REQ: 9087 lim_process_set_dual_mac_cfg_req(mac, msg_buf); 9088 break; 9089 case eWNI_SME_SET_IE_REQ: 9090 lim_process_set_ie_req(mac, msg_buf); 9091 break; 9092 case eWNI_SME_REGISTER_MGMT_FRAME_CB: 9093 lim_register_mgmt_frame_ind_cb(mac, msg_buf); 9094 break; 9095 case eWNI_SME_EXT_CHANGE_CHANNEL: 9096 lim_process_ext_change_channel(mac, msg_buf); 9097 break; 9098 case eWNI_SME_SET_ANTENNA_MODE_REQ: 9099 lim_process_set_antenna_mode_req(mac, msg_buf); 9100 break; 9101 case eWNI_SME_PDEV_SET_HT_VHT_IE: 9102 lim_process_set_pdev_IEs(mac, msg_buf); 9103 break; 9104 case eWNI_SME_SET_VDEV_IES_PER_BAND: 9105 lim_process_set_vdev_ies_per_band(mac, msg_buf); 9106 break; 9107 case eWNI_SME_UPDATE_ACCESS_POLICY_VENDOR_IE: 9108 lim_process_sme_update_access_policy_vendor_ie(mac, msg_buf); 9109 break; 9110 case eWNI_SME_UPDATE_CONFIG: 9111 lim_process_sme_update_config(mac, 9112 (struct update_config *)msg_buf); 9113 break; 9114 case eWNI_SME_SET_ADDBA_ACCEPT: 9115 lim_process_sme_set_addba_accept(mac, 9116 (struct sme_addba_accept *)msg_buf); 9117 break; 9118 case eWNI_SME_UPDATE_EDCA_PROFILE: 9119 lim_process_sme_update_edca_params(mac, pMsg->bodyval); 9120 break; 9121 case WNI_SME_UPDATE_MU_EDCA_PARAMS: 9122 lim_process_sme_update_mu_edca_params(mac, pMsg->bodyval); 9123 break; 9124 case eWNI_SME_UPDATE_SESSION_EDCA_TXQ_PARAMS: 9125 lim_process_sme_update_session_edca_txq_params(mac, msg_buf); 9126 break; 9127 case WNI_SME_CFG_ACTION_FRM_HE_TB_PPDU: 9128 lim_process_sme_cfg_action_frm_in_tb_ppdu(mac, 9129 (struct sir_cfg_action_frm_tb_ppdu *)msg_buf); 9130 break; 9131 case eWNI_SME_VDEV_PAUSE_IND: 9132 lim_process_sme_send_vdev_pause(mac, 9133 (struct sme_vdev_pause *)msg_buf); 9134 break; 9135 case eWNI_SME_SAP_CH_WIDTH_UPDATE_REQ: 9136 lim_process_sap_ch_width_update(mac, msg_buf); 9137 break; 9138 default: 9139 qdf_mem_free((void *)pMsg->bodyptr); 9140 pMsg->bodyptr = NULL; 9141 break; 9142 } /* switch (msgType) */ 9143 9144 return bufConsumed; 9145 } /*** end lim_process_sme_req_messages() ***/ 9146 9147 /** 9148 * lim_process_sme_start_beacon_req() 9149 * 9150 ***FUNCTION: 9151 * This function is called by limProcessMessageQueue(). This 9152 * function processes SME request messages from HDD or upper layer 9153 * application. 9154 * 9155 ***LOGIC: 9156 * 9157 ***ASSUMPTIONS: 9158 * 9159 ***NOTE: 9160 * 9161 * @param mac Pointer to Global MAC structure 9162 * @param msgType Indicates the SME message type 9163 * @param *msg_buf A pointer to the SME message buffer 9164 * @return Boolean - true - if msg_buf is consumed and can be freed. 9165 * false - if msg_buf is not to be freed. 9166 */ 9167 static void lim_process_sme_start_beacon_req(struct mac_context *mac, uint32_t *pMsg) 9168 { 9169 tpSirStartBeaconIndication pBeaconStartInd; 9170 struct pe_session *pe_session; 9171 uint8_t sessionId; /* PE sessionID */ 9172 9173 if (!pMsg) { 9174 pe_err("Buffer is Pointing to NULL"); 9175 return; 9176 } 9177 9178 pBeaconStartInd = (tpSirStartBeaconIndication) pMsg; 9179 pe_session = pe_find_session_by_bssid(mac, 9180 pBeaconStartInd->bssid, 9181 &sessionId); 9182 if (!pe_session) { 9183 pe_err("Session does not exist for given bssId: "QDF_MAC_ADDR_FMT, 9184 QDF_MAC_ADDR_REF(pBeaconStartInd->bssid)); 9185 return; 9186 } 9187 9188 if (pBeaconStartInd->beaconStartStatus == true) { 9189 /* 9190 * Currently this Indication comes from SAP 9191 * to start Beacon Tx on a DFS channel 9192 * since beaconing has to be done on DFS 9193 * channel only after CAC WAIT is completed. 9194 * On a DFS Channel LIM does not start beacon 9195 * Tx right after the WMA_ADD_BSS_RSP. 9196 */ 9197 lim_apply_configuration(mac, pe_session); 9198 pe_debug("Start Beacon with ssid " QDF_SSID_FMT " Ch freq %d", 9199 QDF_SSID_REF(pe_session->ssId.length, 9200 pe_session->ssId.ssId), 9201 pe_session->curr_op_freq); 9202 lim_send_beacon(mac, pe_session); 9203 lim_enable_obss_detection_config(mac, pe_session); 9204 lim_send_obss_color_collision_cfg(mac, pe_session, 9205 OBSS_COLOR_COLLISION_DETECTION); 9206 } else { 9207 pe_err("Invalid Beacon Start Indication"); 9208 return; 9209 } 9210 } 9211 9212 static void lim_mon_change_channel( 9213 struct mac_context *mac_ctx, 9214 struct pe_session *session_entry) 9215 { 9216 if (wlan_vdev_mlme_get_state(session_entry->vdev) == WLAN_VDEV_S_INIT) 9217 wlan_vdev_mlme_sm_deliver_evt(session_entry->vdev, 9218 WLAN_VDEV_SM_EV_START, 9219 sizeof(*session_entry), 9220 session_entry); 9221 else if (wlan_vdev_mlme_get_state(session_entry->vdev) == 9222 WLAN_VDEV_S_UP) { 9223 mlme_set_chan_switch_in_progress(session_entry->vdev, true); 9224 wlan_vdev_mlme_sm_deliver_evt(session_entry->vdev, 9225 WLAN_VDEV_SM_EV_FW_VDEV_RESTART, 9226 sizeof(*session_entry), 9227 session_entry); 9228 } else { 9229 pe_err("Invalid vdev state to change channel"); 9230 } 9231 } 9232 9233 static void lim_change_channel( 9234 struct mac_context *mac_ctx, 9235 struct pe_session *session_entry) 9236 { 9237 if (session_entry->bssType == eSIR_MONITOR_MODE) 9238 return lim_mon_change_channel(mac_ctx, session_entry); 9239 9240 mlme_set_chan_switch_in_progress(session_entry->vdev, true); 9241 9242 if (wlan_vdev_mlme_get_state(session_entry->vdev) == 9243 WLAN_VDEV_S_DFS_CAC_WAIT) 9244 wlan_vdev_mlme_sm_deliver_evt(session_entry->vdev, 9245 WLAN_VDEV_SM_EV_RADAR_DETECTED, 9246 sizeof(*session_entry), 9247 session_entry); 9248 else 9249 wlan_vdev_mlme_sm_deliver_evt(session_entry->vdev, 9250 WLAN_VDEV_SM_EV_CSA_COMPLETE, 9251 sizeof(*session_entry), 9252 session_entry); 9253 } 9254 9255 #ifdef WLAN_FEATURE_11BE 9256 static bool 9257 lim_is_puncture_bitmap_changed(struct pe_session *session, 9258 struct channel_change_req *ch_change_req) 9259 { 9260 uint16_t ori_puncture_bitmap; 9261 9262 ori_puncture_bitmap = 9263 *(uint16_t *)session->eht_op.disabled_sub_chan_bitmap; 9264 9265 return ori_puncture_bitmap != ch_change_req->target_punc_bitmap; 9266 } 9267 #else 9268 static inline bool 9269 lim_is_puncture_bitmap_changed(struct pe_session *session, 9270 struct channel_change_req *ch_change_req) 9271 { 9272 return false; 9273 } 9274 #endif 9275 9276 /** 9277 * lim_abort_channel_change() - Abort channel change 9278 * 9279 * @mac_ctx : Pointer to pe_session 9280 * @vdev_id: vdev ID 9281 * 9282 * This function is called to abort channel change request after CSA 9283 * countdown and allow SAP/GO to operate on current channel without 9284 * vdev restart. 9285 * 9286 * Return: None 9287 */ 9288 static void lim_abort_channel_change(struct mac_context *mac_ctx, 9289 uint8_t vdev_id) 9290 { 9291 struct qdf_mac_addr bssid; 9292 struct pe_session *session_entry; 9293 uint8_t session_id; 9294 QDF_STATUS status; 9295 struct scheduler_msg sch_msg = {0}; 9296 struct sSirChanChangeResponse *chan_change_rsp; 9297 9298 status = wlan_mlme_get_mac_vdev_id(mac_ctx->pdev, vdev_id, &bssid); 9299 if (!QDF_IS_STATUS_SUCCESS(status)) { 9300 pe_err("Failed to get vdev ID"); 9301 return; 9302 } 9303 9304 session_entry = pe_find_session_by_bssid(mac_ctx, bssid.bytes, 9305 &session_id); 9306 if (!session_entry) { 9307 pe_err("Session does not exist for bssid " QDF_MAC_ADDR_FMT, 9308 QDF_MAC_ADDR_REF(bssid.bytes)); 9309 return; 9310 } 9311 9312 session_entry->channelChangeReasonCode = LIM_SWITCH_CHANNEL_SAP_DFS; 9313 mac_ctx->sap.SapDfsInfo.target_chan_freq = 9314 session_entry->curr_op_freq; 9315 mac_ctx->sap.SapDfsInfo.new_chanWidth = session_entry->ch_width; 9316 mac_ctx->sap.SapDfsInfo.new_ch_params.ch_width = 9317 session_entry->ch_width; 9318 9319 wlan_vdev_mlme_sm_deliver_evt(session_entry->vdev, 9320 WLAN_VDEV_SM_EV_CHAN_SWITCH_DISABLED, 9321 sizeof(*session_entry), session_entry); 9322 9323 chan_change_rsp = qdf_mem_malloc(sizeof(struct sSirChanChangeResponse)); 9324 if (!chan_change_rsp) { 9325 pe_err("Failed to allocate chan_change_rsp"); 9326 return; 9327 } 9328 9329 chan_change_rsp->new_op_freq = session_entry->curr_op_freq; 9330 chan_change_rsp->channelChangeStatus = QDF_STATUS_SUCCESS; 9331 chan_change_rsp->sessionId = session_id; 9332 sch_msg.type = eWNI_SME_CHANNEL_CHANGE_RSP; 9333 sch_msg.bodyptr = (void *)chan_change_rsp; 9334 sch_msg.bodyval = 0; 9335 9336 lim_sys_process_mmh_msg_api(mac_ctx, &sch_msg); 9337 } 9338 9339 /** 9340 * lim_process_sme_channel_change_request() - process sme ch change req 9341 * 9342 * @mac_ctx: Pointer to Global MAC structure 9343 * @msg_buf: pointer to the SME message buffer 9344 * 9345 * This function is called to process SME_CHANNEL_CHANGE_REQ message 9346 * 9347 * Return: None 9348 */ 9349 static void lim_process_sme_channel_change_request(struct mac_context *mac_ctx, 9350 uint32_t *msg_buf) 9351 { 9352 struct channel_change_req *ch_change_req; 9353 struct qdf_mac_addr bssid; 9354 struct pe_session *session_entry; 9355 uint8_t session_id; /* PE session_id */ 9356 int8_t max_tx_pwr; 9357 uint32_t target_freq; 9358 bool is_curr_ch_2g, is_new_ch_2g, update_he_cap, update_eht_cap; 9359 9360 if (!msg_buf) { 9361 pe_err("msg_buf is NULL"); 9362 return; 9363 } 9364 ch_change_req = (struct channel_change_req *)msg_buf; 9365 target_freq = ch_change_req->target_chan_freq; 9366 9367 max_tx_pwr = wlan_reg_get_channel_reg_power_for_freq( 9368 mac_ctx->pdev, target_freq); 9369 if (max_tx_pwr == WMA_MAX_TXPOWER_INVALID) { 9370 pe_err("Invalid max tx power"); 9371 return; 9372 } 9373 wlan_mlme_get_mac_vdev_id(mac_ctx->pdev, 9374 ch_change_req->vdev_id, &bssid); 9375 session_entry = pe_find_session_by_bssid(mac_ctx, bssid.bytes, 9376 &session_id); 9377 if (!session_entry) { 9378 pe_err("Session does not exist for bssid " QDF_MAC_ADDR_FMT, 9379 QDF_MAC_ADDR_REF(bssid.bytes)); 9380 return; 9381 } 9382 9383 /* 9384 * The scenario here is, existing SAP/GO is operating on non-DFS chan 9385 * and STA connects to a DFS AP which creates MCC. This will then 9386 * trigger SCC enforcement logic. Now during CSA countdown (before 9387 * GO/SAP actually moves to STA's channel), if STA disconnects, then 9388 * moving GO / SAP to DFS channel will lead to FCC violation if radar 9389 * detection is disabled 9390 * 9391 * Hence to handle this scenario, better to stop current GO/SAP's 9392 * movement to this DFS channel and allow to operate on current channel 9393 * only, STA associated to GO/SAP's will find that SAP/GO didn't beacon 9394 * on new channel so Heartbeat failure will happen and they will scan 9395 * and connect again. 9396 */ 9397 9398 if (LIM_IS_AP_ROLE(session_entry) && 9399 !policy_mgr_is_sap_allowed_on_dfs_freq(mac_ctx->pdev, session_id, 9400 target_freq)) { 9401 lim_abort_channel_change(mac_ctx, ch_change_req->vdev_id); 9402 return; 9403 } else if ((session_entry->curr_op_freq == target_freq && 9404 session_entry->ch_width == ch_change_req->ch_width) && 9405 (!IS_DOT11_MODE_EHT(session_entry->dot11mode) || 9406 !lim_is_puncture_bitmap_changed(session_entry, 9407 ch_change_req))) { 9408 pe_err("Target channel and mode is same as current channel and mode channel freq %d and mode %d", 9409 session_entry->curr_op_freq, session_entry->ch_width); 9410 return; 9411 } 9412 9413 if (LIM_IS_AP_ROLE(session_entry)) 9414 session_entry->channelChangeReasonCode = 9415 LIM_SWITCH_CHANNEL_SAP_DFS; 9416 else 9417 session_entry->channelChangeReasonCode = 9418 LIM_SWITCH_CHANNEL_MONITOR; 9419 9420 pe_nofl_debug("SAP CSA: %d ---> %d, ch_bw %d, nw_type %d, dot11mode %d", 9421 session_entry->curr_op_freq, target_freq, 9422 ch_change_req->ch_width, ch_change_req->nw_type, 9423 ch_change_req->dot11mode); 9424 9425 if (IS_DOT11_MODE_HE(ch_change_req->dot11mode) && 9426 ((QDF_MONITOR_MODE == session_entry->opmode) || 9427 lim_is_session_he_capable(session_entry))) { 9428 lim_update_session_he_capable_chan_switch 9429 (mac_ctx, session_entry, target_freq); 9430 is_new_ch_2g = wlan_reg_is_24ghz_ch_freq(target_freq); 9431 is_curr_ch_2g = wlan_reg_is_24ghz_ch_freq( 9432 session_entry->curr_op_freq); 9433 if ((is_new_ch_2g && !is_curr_ch_2g) || 9434 (!is_new_ch_2g && is_curr_ch_2g)) 9435 update_he_cap = true; 9436 else 9437 update_he_cap = false; 9438 if (!update_he_cap) { 9439 if ((session_entry->ch_width != 9440 ch_change_req->ch_width) && 9441 (session_entry->ch_width > CH_WIDTH_80MHZ || 9442 ch_change_req->ch_width > CH_WIDTH_80MHZ)) 9443 update_he_cap = true; 9444 } 9445 if (update_he_cap) { 9446 session_entry->curr_op_freq = target_freq; 9447 session_entry->ch_width = ch_change_req->ch_width; 9448 lim_copy_bss_he_cap(session_entry); 9449 lim_update_he_bw_cap_mcs(session_entry, NULL); 9450 } 9451 } else if (wlan_reg_is_6ghz_chan_freq(target_freq)) { 9452 pe_debug("Invalid target_freq %d for dot11mode %d cur HE %d", 9453 target_freq, ch_change_req->dot11mode, 9454 lim_is_session_he_capable(session_entry)); 9455 return; 9456 } 9457 9458 if (IS_DOT11_MODE_EHT(ch_change_req->dot11mode) && 9459 ((QDF_MONITOR_MODE == session_entry->opmode) || 9460 lim_is_session_eht_capable(session_entry))) { 9461 lim_update_session_eht_capable_chan_switch( 9462 mac_ctx, session_entry, target_freq); 9463 is_new_ch_2g = wlan_reg_is_24ghz_ch_freq(target_freq); 9464 is_curr_ch_2g = wlan_reg_is_24ghz_ch_freq( 9465 session_entry->curr_op_freq); 9466 if ((is_new_ch_2g && !is_curr_ch_2g) || 9467 (!is_new_ch_2g && is_curr_ch_2g)) 9468 update_eht_cap = true; 9469 else 9470 update_eht_cap = false; 9471 if (!update_eht_cap) { 9472 if ((session_entry->ch_width != 9473 ch_change_req->ch_width) && 9474 (session_entry->ch_width > CH_WIDTH_80MHZ || 9475 ch_change_req->ch_width > CH_WIDTH_80MHZ)) 9476 update_eht_cap = true; 9477 } 9478 if (update_eht_cap) { 9479 session_entry->curr_op_freq = target_freq; 9480 session_entry->ch_width = ch_change_req->ch_width; 9481 lim_copy_bss_eht_cap(session_entry); 9482 lim_update_eht_bw_cap_mcs(session_entry, NULL); 9483 } 9484 } 9485 9486 /* Store the New Channel Params in session_entry */ 9487 session_entry->ch_width = ch_change_req->ch_width; 9488 session_entry->ch_center_freq_seg0 = 9489 ch_change_req->center_freq_seg0; 9490 session_entry->ch_center_freq_seg1 = 9491 ch_change_req->center_freq_seg1; 9492 session_entry->htSecondaryChannelOffset = ch_change_req->sec_ch_offset; 9493 session_entry->htSupportedChannelWidthSet = 9494 (ch_change_req->ch_width ? 1 : 0); 9495 session_entry->htRecommendedTxWidthSet = 9496 session_entry->htSupportedChannelWidthSet; 9497 session_entry->curr_op_freq = target_freq; 9498 session_entry->limRFBand = lim_get_rf_band( 9499 session_entry->curr_op_freq); 9500 if (mlme_get_cac_required(session_entry->vdev)) 9501 session_entry->cac_duration_ms = ch_change_req->cac_duration_ms; 9502 else 9503 session_entry->cac_duration_ms = 0; 9504 session_entry->dfs_regdomain = ch_change_req->dfs_regdomain; 9505 session_entry->maxTxPower = max_tx_pwr; 9506 9507 /* Update the global beacon filter */ 9508 lim_update_bcn_probe_filter(mac_ctx, session_entry); 9509 9510 /* Initialize 11h Enable Flag */ 9511 if (CHAN_HOP_ALL_BANDS_ENABLE || 9512 session_entry->limRFBand != REG_BAND_2G) 9513 session_entry->lim11hEnable = 9514 mac_ctx->mlme_cfg->gen.enabled_11h; 9515 else 9516 session_entry->lim11hEnable = 0; 9517 9518 session_entry->dot11mode = ch_change_req->dot11mode; 9519 session_entry->nwType = ch_change_req->nw_type; 9520 qdf_mem_copy(&session_entry->rateSet, 9521 &ch_change_req->opr_rates, 9522 sizeof(session_entry->rateSet)); 9523 qdf_mem_copy(&session_entry->extRateSet, 9524 &ch_change_req->ext_rates, 9525 sizeof(session_entry->extRateSet)); 9526 lim_change_channel(mac_ctx, session_entry); 9527 lim_check_conc_power_for_csa(mac_ctx, session_entry); 9528 9529 lim_dump_session_info(mac_ctx, session_entry); 9530 lim_dump_he_info(mac_ctx, session_entry); 9531 lim_dump_eht_info(session_entry); 9532 } 9533 9534 /****************************************************************************** 9535 * lim_start_bss_update_add_ie_buffer() 9536 * 9537 ***FUNCTION: 9538 * This function checks the src buffer and its length and then malloc for 9539 * dst buffer update the same 9540 * 9541 ***LOGIC: 9542 * 9543 ***ASSUMPTIONS: 9544 * 9545 ***NOTE: 9546 * 9547 * @param mac Pointer to Global MAC structure 9548 * @param **pDstData_buff A pointer to pointer of uint8_t dst buffer 9549 * @param *pDstDataLen A pointer to pointer of uint16_t dst buffer length 9550 * @param *pSrcData_buff A pointer of uint8_t src buffer 9551 * @param srcDataLen src buffer length 9552 ******************************************************************************/ 9553 9554 static void 9555 lim_start_bss_update_add_ie_buffer(struct mac_context *mac, 9556 uint8_t **pDstData_buff, 9557 uint16_t *pDstDataLen, 9558 uint8_t *pSrcData_buff, uint16_t srcDataLen) 9559 { 9560 9561 if (srcDataLen > 0 && pSrcData_buff) { 9562 *pDstDataLen = srcDataLen; 9563 9564 *pDstData_buff = qdf_mem_malloc(*pDstDataLen); 9565 if (!*pDstData_buff) 9566 return; 9567 qdf_mem_copy(*pDstData_buff, pSrcData_buff, *pDstDataLen); 9568 } else { 9569 *pDstData_buff = NULL; 9570 *pDstDataLen = 0; 9571 } 9572 } 9573 9574 /****************************************************************************** 9575 * lim_update_add_ie_buffer() 9576 * 9577 ***FUNCTION: 9578 * This function checks the src buffer and length if src buffer length more 9579 * than dst buffer length then free the dst buffer and malloc for the new src 9580 * length, and update the dst buffer and length. But if dst buffer is bigger 9581 * than src buffer length then it just update the dst buffer and length 9582 * 9583 ***LOGIC: 9584 * 9585 ***ASSUMPTIONS: 9586 * 9587 ***NOTE: 9588 * 9589 * @param mac Pointer to Global MAC structure 9590 * @param **pDstData_buff A pointer to pointer of uint8_t dst buffer 9591 * @param *pDstDataLen A pointer to pointer of uint16_t dst buffer length 9592 * @param *pSrcData_buff A pointer of uint8_t src buffer 9593 * @param srcDataLen src buffer length 9594 ******************************************************************************/ 9595 9596 static void 9597 lim_update_add_ie_buffer(struct mac_context *mac, 9598 uint8_t **pDstData_buff, 9599 uint16_t *pDstDataLen, 9600 uint8_t *pSrcData_buff, uint16_t srcDataLen) 9601 { 9602 9603 if (!pSrcData_buff) { 9604 pe_err("src buffer is null"); 9605 return; 9606 } 9607 9608 if (srcDataLen > *pDstDataLen) { 9609 *pDstDataLen = srcDataLen; 9610 /* free old buffer */ 9611 qdf_mem_free(*pDstData_buff); 9612 /* allocate a new */ 9613 *pDstData_buff = qdf_mem_malloc(*pDstDataLen); 9614 if (!*pDstData_buff) { 9615 *pDstDataLen = 0; 9616 return; 9617 } 9618 } 9619 9620 /* copy the content of buffer into dst buffer 9621 */ 9622 *pDstDataLen = srcDataLen; 9623 qdf_mem_copy(*pDstData_buff, pSrcData_buff, *pDstDataLen); 9624 9625 } 9626 9627 /* 9628 * lim_process_modify_add_ies() - process modify additional IE req. 9629 * 9630 * @mac_ctx: Pointer to Global MAC structure 9631 * @msg_buf: pointer to the SME message buffer 9632 * 9633 * This function update the PE buffers for additional IEs. 9634 * 9635 * Return: None 9636 */ 9637 static void lim_process_modify_add_ies(struct mac_context *mac_ctx, 9638 uint32_t *msg_buf) 9639 { 9640 tpSirModifyIEsInd modify_add_ies; 9641 struct pe_session *session_entry; 9642 uint8_t session_id; 9643 bool ret = false; 9644 struct add_ie_params *add_ie_params; 9645 9646 if (!msg_buf) { 9647 pe_err("msg_buf is NULL"); 9648 return; 9649 } 9650 9651 modify_add_ies = (tpSirModifyIEsInd)msg_buf; 9652 /* Incoming message has smeSession, use BSSID to find PE session */ 9653 session_entry = pe_find_session_by_bssid(mac_ctx, 9654 modify_add_ies->modifyIE.bssid.bytes, &session_id); 9655 9656 if (!session_entry) { 9657 pe_err("Session not found for given bssid" 9658 QDF_MAC_ADDR_FMT, 9659 QDF_MAC_ADDR_REF(modify_add_ies->modifyIE.bssid.bytes)); 9660 goto end; 9661 } 9662 if ((0 == modify_add_ies->modifyIE.ieBufferlength) || 9663 (0 == modify_add_ies->modifyIE.ieIDLen) || 9664 (!modify_add_ies->modifyIE.pIEBuffer)) { 9665 pe_err("Invalid request pIEBuffer %pK ieBufferlength %d ieIDLen %d ieID %d. update Type %d", 9666 modify_add_ies->modifyIE.pIEBuffer, 9667 modify_add_ies->modifyIE.ieBufferlength, 9668 modify_add_ies->modifyIE.ieID, 9669 modify_add_ies->modifyIE.ieIDLen, 9670 modify_add_ies->updateType); 9671 goto end; 9672 } 9673 add_ie_params = &session_entry->add_ie_params; 9674 switch (modify_add_ies->updateType) { 9675 case eUPDATE_IE_PROBE_RESP: 9676 /* Probe resp */ 9677 break; 9678 case eUPDATE_IE_ASSOC_RESP: 9679 /* assoc resp IE */ 9680 if (!add_ie_params->assocRespDataLen) 9681 pe_err("assoc resp add ie not present"); 9682 /* search through the buffer and modify the IE */ 9683 break; 9684 case eUPDATE_IE_PROBE_BCN: 9685 /*probe beacon IE */ 9686 if (ret == true && modify_add_ies->modifyIE.notify) { 9687 lim_handle_param_update(mac_ctx, 9688 modify_add_ies->updateType); 9689 } 9690 break; 9691 default: 9692 pe_err("unhandled buffer type %d", 9693 modify_add_ies->updateType); 9694 break; 9695 } 9696 end: 9697 qdf_mem_free(modify_add_ies->modifyIE.pIEBuffer); 9698 modify_add_ies->modifyIE.pIEBuffer = NULL; 9699 } 9700 9701 /* 9702 * lim_process_update_add_ies() - process additional IE update req 9703 * 9704 * @mac_ctx: Pointer to Global MAC structure 9705 * @msg_buf: pointer to the SME message buffer 9706 * 9707 * This function update the PE buffers for additional IEs. 9708 * 9709 * Return: None 9710 */ 9711 static void lim_process_update_add_ies(struct mac_context *mac_ctx, 9712 uint32_t *msg_buf) 9713 { 9714 tpSirUpdateIEsInd update_add_ies = (tpSirUpdateIEsInd)msg_buf; 9715 uint8_t session_id; 9716 struct pe_session *session_entry; 9717 struct add_ie_params *addn_ie; 9718 uint16_t new_length = 0; 9719 uint8_t *new_ptr = NULL; 9720 tSirUpdateIE *update_ie; 9721 9722 if (!msg_buf) { 9723 pe_err("msg_buf is NULL"); 9724 return; 9725 } 9726 update_ie = &update_add_ies->updateIE; 9727 /* incoming message has smeSession, use BSSID to find PE session */ 9728 session_entry = pe_find_session_by_bssid(mac_ctx, 9729 update_ie->bssid.bytes, &session_id); 9730 9731 if (!session_entry) { 9732 pe_debug("Session not found for given bssid" 9733 QDF_MAC_ADDR_FMT, 9734 QDF_MAC_ADDR_REF(update_ie->bssid.bytes)); 9735 goto end; 9736 } 9737 addn_ie = &session_entry->add_ie_params; 9738 /* if len is 0, upper layer requested freeing of buffer */ 9739 if (0 == update_ie->ieBufferlength) { 9740 switch (update_add_ies->updateType) { 9741 case eUPDATE_IE_PROBE_RESP: 9742 qdf_mem_free(addn_ie->probeRespData_buff); 9743 addn_ie->probeRespData_buff = NULL; 9744 addn_ie->probeRespDataLen = 0; 9745 break; 9746 case eUPDATE_IE_ASSOC_RESP: 9747 qdf_mem_free(addn_ie->assocRespData_buff); 9748 addn_ie->assocRespData_buff = NULL; 9749 addn_ie->assocRespDataLen = 0; 9750 break; 9751 case eUPDATE_IE_PROBE_BCN: 9752 qdf_mem_free(addn_ie->probeRespBCNData_buff); 9753 addn_ie->probeRespBCNData_buff = NULL; 9754 addn_ie->probeRespBCNDataLen = 0; 9755 9756 if (update_ie->notify) 9757 lim_handle_param_update(mac_ctx, 9758 update_add_ies->updateType); 9759 break; 9760 default: 9761 break; 9762 } 9763 return; 9764 } 9765 switch (update_add_ies->updateType) { 9766 case eUPDATE_IE_PROBE_RESP: 9767 if (update_ie->append) { 9768 /* 9769 * In case of append, allocate new memory 9770 * with combined length. 9771 * Multiple back to back append commands 9772 * can lead to a huge length.So, check 9773 * for the validity of the length. 9774 */ 9775 if (addn_ie->probeRespDataLen > 9776 (USHRT_MAX - update_ie->ieBufferlength)) { 9777 pe_err("IE Length overflow, curr:%d, new:%d", 9778 addn_ie->probeRespDataLen, 9779 update_ie->ieBufferlength); 9780 goto end; 9781 } 9782 new_length = update_ie->ieBufferlength + 9783 addn_ie->probeRespDataLen; 9784 new_ptr = qdf_mem_malloc(new_length); 9785 if (!new_ptr) 9786 goto end; 9787 /* append buffer to end of local buffers */ 9788 qdf_mem_copy(new_ptr, addn_ie->probeRespData_buff, 9789 addn_ie->probeRespDataLen); 9790 qdf_mem_copy(&new_ptr[addn_ie->probeRespDataLen], 9791 update_ie->pAdditionIEBuffer, 9792 update_ie->ieBufferlength); 9793 /* free old memory */ 9794 qdf_mem_free(addn_ie->probeRespData_buff); 9795 /* adjust length accordingly */ 9796 addn_ie->probeRespDataLen = new_length; 9797 /* save reference of local buffer in PE session */ 9798 addn_ie->probeRespData_buff = new_ptr; 9799 goto end; 9800 } 9801 lim_update_add_ie_buffer(mac_ctx, &addn_ie->probeRespData_buff, 9802 &addn_ie->probeRespDataLen, 9803 update_ie->pAdditionIEBuffer, 9804 update_ie->ieBufferlength); 9805 break; 9806 case eUPDATE_IE_ASSOC_RESP: 9807 /* assoc resp IE */ 9808 lim_update_add_ie_buffer(mac_ctx, &addn_ie->assocRespData_buff, 9809 &addn_ie->assocRespDataLen, 9810 update_ie->pAdditionIEBuffer, 9811 update_ie->ieBufferlength); 9812 break; 9813 case eUPDATE_IE_PROBE_BCN: 9814 /* probe resp Bcn IE */ 9815 lim_update_add_ie_buffer(mac_ctx, 9816 &addn_ie->probeRespBCNData_buff, 9817 &addn_ie->probeRespBCNDataLen, 9818 update_ie->pAdditionIEBuffer, 9819 update_ie->ieBufferlength); 9820 if (update_ie->notify) 9821 lim_handle_param_update(mac_ctx, 9822 update_add_ies->updateType); 9823 break; 9824 default: 9825 pe_err("unhandled buffer type %d", update_add_ies->updateType); 9826 break; 9827 } 9828 end: 9829 qdf_mem_free(update_ie->pAdditionIEBuffer); 9830 update_ie->pAdditionIEBuffer = NULL; 9831 } 9832 9833 void send_extended_chan_switch_action_frame(struct mac_context *mac_ctx, 9834 uint16_t new_channel_freq, 9835 enum phy_ch_width ch_bandwidth, 9836 struct pe_session *session_entry) 9837 { 9838 uint8_t op_class = 0; 9839 uint8_t switch_mode = 0, i; 9840 tpDphHashNode psta; 9841 uint8_t new_channel = 0; 9842 enum phy_ch_width ch_width; 9843 tLimChannelSwitchInfo *ch_switch = &session_entry->gLimChannelSwitch; 9844 9845 op_class = 9846 lim_op_class_from_bandwidth(mac_ctx, new_channel_freq, 9847 ch_bandwidth, 9848 ch_switch->sec_ch_offset); 9849 new_channel = wlan_reg_freq_to_chan(mac_ctx->pdev, new_channel_freq); 9850 if (LIM_IS_AP_ROLE(session_entry) && 9851 (mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch == false)) 9852 switch_mode = ch_switch->switchMode; 9853 9854 if (LIM_IS_AP_ROLE(session_entry)) { 9855 for (i = 0; i <= mac_ctx->lim.max_sta_of_pe_session; i++) { 9856 psta = 9857 session_entry->dph.dphHashTable.pDphNodeArray + i; 9858 if (!psta || !psta->added) 9859 continue; 9860 ch_width = lim_calculate_peer_ch_width(session_entry, 9861 psta->staAddr, 9862 ch_bandwidth); 9863 op_class = lim_op_class_from_bandwidth(mac_ctx, 9864 new_channel_freq, ch_width, 9865 ch_switch->sec_ch_offset); 9866 lim_send_extended_chan_switch_action_frame( 9867 mac_ctx, psta->staAddr, 9868 switch_mode, op_class, new_channel, 9869 ch_switch->switchCount, session_entry); 9870 } 9871 } else if (LIM_IS_STA_ROLE(session_entry)) { 9872 lim_send_extended_chan_switch_action_frame(mac_ctx, 9873 session_entry->bssId, 9874 switch_mode, op_class, new_channel, 9875 ch_switch->switchCount, 9876 session_entry); 9877 } 9878 9879 } 9880 9881 void lim_send_chan_switch_action_frame(struct mac_context *mac_ctx, 9882 uint16_t new_channel_freq, 9883 enum phy_ch_width ch_bandwidth, 9884 struct pe_session *session_entry) 9885 { 9886 uint8_t op_class = 0, new_channel; 9887 uint8_t switch_mode = 0, i; 9888 uint8_t switch_count; 9889 tpDphHashNode psta; 9890 tpDphHashNode dph_node_array_ptr; 9891 9892 dph_node_array_ptr = session_entry->dph.dphHashTable.pDphNodeArray; 9893 op_class = 9894 lim_op_class_from_bandwidth(mac_ctx, new_channel_freq, 9895 ch_bandwidth, 9896 session_entry->gLimChannelSwitch.sec_ch_offset); 9897 new_channel = wlan_reg_freq_to_chan(mac_ctx->pdev, new_channel_freq); 9898 9899 if (LIM_IS_AP_ROLE(session_entry) && 9900 (false == mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch)) 9901 switch_mode = session_entry->gLimChannelSwitch.switchMode; 9902 9903 switch_count = session_entry->gLimChannelSwitch.switchCount; 9904 9905 if (LIM_IS_AP_ROLE(session_entry)) { 9906 for (i = 0; i <= mac_ctx->lim.max_sta_of_pe_session; i++) { 9907 psta = dph_node_array_ptr + i; 9908 if (!(psta && psta->added)) 9909 continue; 9910 if (session_entry->lim_non_ecsa_cap_num == 0) 9911 lim_send_extended_chan_switch_action_frame 9912 (mac_ctx, psta->staAddr, switch_mode, 9913 op_class, new_channel, switch_count, 9914 session_entry); 9915 else 9916 lim_send_channel_switch_mgmt_frame 9917 (mac_ctx, psta->staAddr, switch_mode, 9918 new_channel, switch_count, 9919 session_entry); 9920 } 9921 } else if (LIM_IS_STA_ROLE(session_entry)) { 9922 lim_send_extended_chan_switch_action_frame 9923 (mac_ctx, session_entry->bssId, switch_mode, op_class, 9924 new_channel, switch_count, session_entry); 9925 } 9926 } 9927 9928 /** 9929 * lim_process_sme_dfs_csa_ie_request() - process sme dfs csa ie req 9930 * 9931 * @mac_ctx: Pointer to Global MAC structure 9932 * @msg_buf: pointer to the SME message buffer 9933 * 9934 * This function processes SME request messages from HDD or upper layer 9935 * application. 9936 * 9937 * Return: None 9938 */ 9939 static void lim_process_sme_dfs_csa_ie_request(struct mac_context *mac_ctx, 9940 uint32_t *msg_buf) 9941 { 9942 tpSirDfsCsaIeRequest dfs_csa_ie_req; 9943 struct pe_session *session_entry = NULL; 9944 uint8_t session_id; 9945 tLimWiderBWChannelSwitchInfo *wider_bw_ch_switch; 9946 QDF_STATUS status; 9947 enum phy_ch_width ch_width; 9948 uint32_t target_ch_freq; 9949 bool is_vdev_ll_lt_sap = false; 9950 uint8_t peer_count; 9951 uint16_t max_wait_for_bcn_tx_complete; 9952 9953 if (!msg_buf) { 9954 pe_err("Buffer is Pointing to NULL"); 9955 return; 9956 } 9957 9958 dfs_csa_ie_req = (tSirDfsCsaIeRequest *)msg_buf; 9959 session_entry = pe_find_session_by_bssid(mac_ctx, 9960 dfs_csa_ie_req->bssid, &session_id); 9961 if (!session_entry) { 9962 pe_err("Session not found for given BSSID" QDF_MAC_ADDR_FMT, 9963 QDF_MAC_ADDR_REF(dfs_csa_ie_req->bssid)); 9964 return; 9965 } 9966 9967 if (session_entry->valid && !LIM_IS_AP_ROLE(session_entry)) { 9968 pe_err("Invalid SystemRole %d", 9969 GET_LIM_SYSTEM_ROLE(session_entry)); 9970 return; 9971 } 9972 9973 /* target channel */ 9974 session_entry->gLimChannelSwitch.primaryChannel = 9975 wlan_reg_freq_to_chan(mac_ctx->pdev, 9976 dfs_csa_ie_req->target_chan_freq); 9977 session_entry->gLimChannelSwitch.sw_target_freq = 9978 dfs_csa_ie_req->target_chan_freq; 9979 target_ch_freq = dfs_csa_ie_req->target_chan_freq; 9980 /* Channel switch announcement needs to be included in beacon */ 9981 session_entry->dfsIncludeChanSwIe = true; 9982 9983 wlan_reg_set_create_punc_bitmap(&dfs_csa_ie_req->ch_params, false); 9984 wlan_reg_set_channel_params_for_pwrmode(mac_ctx->pdev, 9985 dfs_csa_ie_req->target_chan_freq, 9986 0, 9987 &dfs_csa_ie_req->ch_params, 9988 REG_CURRENT_PWR_MODE); 9989 9990 ch_width = dfs_csa_ie_req->ch_params.ch_width; 9991 if (ch_width >= CH_WIDTH_160MHZ && 9992 wma_get_vht_ch_width() < WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ) { 9993 ch_width = CH_WIDTH_80MHZ; 9994 } 9995 session_entry->gLimChannelSwitch.ch_width = ch_width; 9996 session_entry->gLimChannelSwitch.sec_ch_offset = 9997 dfs_csa_ie_req->ch_params.sec_ch_offset; 9998 9999 is_vdev_ll_lt_sap = policy_mgr_is_vdev_ll_lt_sap( 10000 mac_ctx->psoc, 10001 session_entry->vdev_id); 10002 10003 if (is_vdev_ll_lt_sap) { 10004 session_entry->gLimChannelSwitch.switchCount = 1; 10005 session_entry->gLimChannelSwitch.switchMode = 0; 10006 } else { 10007 session_entry->gLimChannelSwitch.switchCount = 10008 dfs_csa_ie_req->ch_switch_beacon_cnt; 10009 if (!mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch) 10010 session_entry->gLimChannelSwitch.switchMode = 10011 dfs_csa_ie_req->ch_switch_mode; 10012 } 10013 10014 /* 10015 * Validate if SAP is operating HT or VHT/HE mode and set the Channel 10016 * Switch Wrapper element with the Wide Band Switch subelement. 10017 */ 10018 if (!(session_entry->vhtCapability || 10019 lim_is_session_he_capable(session_entry))) 10020 goto skip_vht; 10021 10022 /* Now encode the Wider Ch BW element depending on the ch width */ 10023 wider_bw_ch_switch = &session_entry->gLimWiderBWChannelSwitch; 10024 switch (ch_width) { 10025 case CH_WIDTH_20MHZ: 10026 /* 10027 * Wide channel BW sublement in channel wrapper element is not 10028 * required in case of 20 Mhz operation. Currently It is set 10029 * only set in case of 40/80 Mhz Operation. 10030 */ 10031 session_entry->dfsIncludeChanWrapperIe = false; 10032 wider_bw_ch_switch->newChanWidth = 10033 WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; 10034 break; 10035 case CH_WIDTH_40MHZ: 10036 session_entry->dfsIncludeChanWrapperIe = false; 10037 wider_bw_ch_switch->newChanWidth = 10038 WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; 10039 break; 10040 case CH_WIDTH_80MHZ: 10041 session_entry->dfsIncludeChanWrapperIe = true; 10042 wider_bw_ch_switch->newChanWidth = 10043 WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; 10044 break; 10045 case CH_WIDTH_160MHZ: 10046 session_entry->dfsIncludeChanWrapperIe = true; 10047 wider_bw_ch_switch->newChanWidth = 10048 WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ; 10049 break; 10050 case CH_WIDTH_80P80MHZ: 10051 session_entry->dfsIncludeChanWrapperIe = true; 10052 wider_bw_ch_switch->newChanWidth = 10053 WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ; 10054 /* 10055 * This is not applicable for 20/40/80 Mhz. 10056 * Only used when we support 80+80 Mhz operation. 10057 * In case of 80+80 Mhz, this parameter indicates 10058 * center channel frequency index of 80 Mhz channel of 10059 * frequency segment 1. 10060 */ 10061 wider_bw_ch_switch->newCenterChanFreq1 = 10062 dfs_csa_ie_req->ch_params.center_freq_seg1; 10063 break; 10064 default: 10065 session_entry->dfsIncludeChanWrapperIe = false; 10066 /* 10067 * Need to handle 80+80 Mhz Scenario. When 80+80 is supported 10068 * set the gLimWiderBWChannelSwitch.newChanWidth to 3 10069 */ 10070 pe_err("Invalid Channel Width"); 10071 break; 10072 } 10073 /* Fetch the center channel based on the channel width */ 10074 wider_bw_ch_switch->newCenterChanFreq0 = 10075 dfs_csa_ie_req->ch_params.center_freq_seg0; 10076 skip_vht: 10077 10078 /* Take a wakelock for CSA for 5 seconds and release in vdev start */ 10079 10080 qdf_wake_lock_timeout_acquire(&session_entry->ap_ecsa_wakelock, 10081 MAX_WAKELOCK_FOR_CSA); 10082 qdf_runtime_pm_prevent_suspend(&session_entry->ap_ecsa_runtime_lock); 10083 10084 session_entry->cac_duration_ms = dfs_csa_ie_req->new_chan_cac_ms; 10085 wlan_util_vdev_mgr_set_cac_timeout_for_vdev( 10086 session_entry->vdev, dfs_csa_ie_req->new_chan_cac_ms); 10087 10088 peer_count = wlan_vdev_get_peer_sta_count(session_entry->vdev); 10089 10090 if (is_vdev_ll_lt_sap && !peer_count) { 10091 pe_debug("Peer count is 0 for LL_LT_SAP, continue CSA directly"); 10092 /* initiate vdev restart if no peer connected on XPAN */ 10093 lim_send_csa_tx_complete(session_entry->vdev_id); 10094 /* Clear CSA IE count and update beacon */ 10095 lim_send_dfs_chan_sw_ie_update(mac_ctx, session_entry); 10096 return; 10097 } 10098 10099 /* Send CSA IE request from here */ 10100 lim_send_dfs_chan_sw_ie_update(mac_ctx, session_entry); 10101 10102 /* 10103 * Wait for max_wait_for_bcn_tx_complete ms for tx complete for beacon. 10104 * If tx complete for beacon is received before this timer expire, 10105 * stop this timer and then this will be restarted for every beacon 10106 * interval until switchCount become 0 and bcn template with new 10107 * switchCount will be sent to firmware. 10108 * OR 10109 * If no tx complete for beacon is received till this timer expire 10110 * this will be restarted for every beacon interval until switchCount 10111 * become 0 and bcn template with new switchCount will be sent to 10112 * firmware. 10113 */ 10114 if (is_vdev_ll_lt_sap) 10115 max_wait_for_bcn_tx_complete = MAX_WAIT_FOR_BCN_TX_COMPLETE_FOR_LL_SAP; 10116 else 10117 max_wait_for_bcn_tx_complete = MAX_WAIT_FOR_BCN_TX_COMPLETE; 10118 10119 status = qdf_mc_timer_start(&session_entry->ap_ecsa_timer, 10120 max_wait_for_bcn_tx_complete); 10121 10122 if (QDF_IS_STATUS_ERROR(status)) 10123 pe_err("cannot start ap_ecsa_timer"); 10124 10125 pe_debug("IE count:%d chan:%d freq %d width:%d wrapper:%d ch_offset:%d", 10126 session_entry->gLimChannelSwitch.switchCount, 10127 session_entry->gLimChannelSwitch.primaryChannel, 10128 session_entry->gLimChannelSwitch.sw_target_freq, 10129 session_entry->gLimChannelSwitch.ch_width, 10130 session_entry->dfsIncludeChanWrapperIe, 10131 session_entry->gLimChannelSwitch.sec_ch_offset); 10132 10133 /* 10134 * Send ECSA/CSA Action frame after updating the beacon. 10135 * For LL_LT_SAP, send ECSA action frame only 10136 */ 10137 if (CHAN_HOP_ALL_BANDS_ENABLE && 10138 session_entry->lim_non_ecsa_cap_num && 10139 !WLAN_REG_IS_6GHZ_CHAN_FREQ(target_ch_freq) && 10140 !is_vdev_ll_lt_sap) 10141 lim_send_chan_switch_action_frame 10142 (mac_ctx, 10143 session_entry->gLimChannelSwitch.primaryChannel, 10144 ch_width, session_entry); 10145 else 10146 send_extended_chan_switch_action_frame 10147 (mac_ctx, target_ch_freq, ch_width, 10148 session_entry); 10149 } 10150 10151 /** 10152 * lim_process_ext_change_channel()- function to send ECSA 10153 * action frame for STA/CLI . 10154 * @mac_ctx: pointer to global mac structure 10155 * @msg: params from sme for new channel. 10156 * 10157 * This function is called to send ECSA frame for STA/CLI. 10158 * 10159 * Return: void 10160 */ 10161 10162 static void lim_process_ext_change_channel(struct mac_context *mac_ctx, 10163 uint32_t *msg) 10164 { 10165 struct sir_sme_ext_cng_chan_req *ext_chng_channel = 10166 (struct sir_sme_ext_cng_chan_req *) msg; 10167 struct pe_session *session_entry = NULL; 10168 10169 if (!msg) { 10170 pe_err("Buffer is Pointing to NULL"); 10171 return; 10172 } 10173 session_entry = 10174 pe_find_session_by_vdev_id(mac_ctx, ext_chng_channel->vdev_id); 10175 if (!session_entry) { 10176 pe_err("Session not found for given vdev_id %d", 10177 ext_chng_channel->vdev_id); 10178 return; 10179 } 10180 if (LIM_IS_AP_ROLE(session_entry)) { 10181 pe_err("not an STA/CLI session"); 10182 return; 10183 } 10184 session_entry->gLimChannelSwitch.sec_ch_offset = 0; 10185 send_extended_chan_switch_action_frame(mac_ctx, 10186 ext_chng_channel->new_ch_freq, 0, 10187 session_entry); 10188 } 10189 10190 /** 10191 * lim_process_nss_update_request() - process sme nss update req 10192 * 10193 * @mac_ctx: Pointer to Global MAC structure 10194 * @msg_buf: pointer to the SME message buffer 10195 * 10196 * This function processes SME request messages from HDD or upper layer 10197 * application. 10198 * 10199 * Return: None 10200 */ 10201 static void lim_process_nss_update_request(struct mac_context *mac_ctx, 10202 uint32_t *msg_buf) 10203 { 10204 struct sir_nss_update_request *nss_update_req_ptr; 10205 struct pe_session *session_entry = NULL; 10206 QDF_STATUS status = QDF_STATUS_E_FAILURE; 10207 uint8_t vdev_id; 10208 10209 if (!msg_buf) { 10210 pe_err("Buffer is Pointing to NULL"); 10211 return; 10212 } 10213 10214 nss_update_req_ptr = (struct sir_nss_update_request *)msg_buf; 10215 vdev_id = nss_update_req_ptr->vdev_id; 10216 session_entry = pe_find_session_by_vdev_id(mac_ctx, 10217 nss_update_req_ptr->vdev_id); 10218 if (!session_entry) { 10219 pe_err("Session not found for given session_id %d", 10220 nss_update_req_ptr->vdev_id); 10221 goto end; 10222 } 10223 10224 if (session_entry->valid && !LIM_IS_AP_ROLE(session_entry)) { 10225 pe_err("Invalid SystemRole %d", 10226 GET_LIM_SYSTEM_ROLE(session_entry)); 10227 goto end; 10228 } 10229 10230 /* populate nss field in the beacon */ 10231 session_entry->gLimOperatingMode.present = 1; 10232 session_entry->gLimOperatingMode.rxNSS = nss_update_req_ptr->new_nss; 10233 session_entry->gLimOperatingMode.chanWidth = session_entry->ch_width; 10234 10235 if ((nss_update_req_ptr->new_nss == NSS_1x1_MODE) && 10236 (session_entry->ch_width > CH_WIDTH_80MHZ)) 10237 session_entry->gLimOperatingMode.chanWidth = CH_WIDTH_80MHZ; 10238 if (session_entry->gLimOperatingMode.chanWidth <= CH_WIDTH_160MHZ && 10239 nss_update_req_ptr->ch_width < 10240 session_entry->gLimOperatingMode.chanWidth) 10241 session_entry->gLimOperatingMode.chanWidth = 10242 nss_update_req_ptr->ch_width; 10243 10244 pe_debug("ch width %d Rx NSS %d", 10245 session_entry->gLimOperatingMode.chanWidth, 10246 session_entry->gLimOperatingMode.rxNSS); 10247 10248 /* Send nss update request from here */ 10249 status = sch_set_fixed_beacon_fields(mac_ctx, session_entry); 10250 if (QDF_IS_STATUS_ERROR(status)) { 10251 pe_err("Unable to set op mode IE in beacon"); 10252 goto end; 10253 } 10254 10255 status = lim_send_beacon_ind(mac_ctx, session_entry, REASON_NSS_UPDATE); 10256 if (QDF_IS_STATUS_SUCCESS(status)) 10257 return; 10258 10259 pe_err("Unable to send beacon"); 10260 end: 10261 /* 10262 * send resp only in case of failure, 10263 * success case response will be from wma. 10264 */ 10265 lim_nss_or_ch_width_update_rsp(mac_ctx, vdev_id, status, 10266 REASON_NSS_UPDATE); 10267 } 10268 10269 /** 10270 * lim_process_set_ie_req() - process sme set IE request 10271 * 10272 * @mac_ctx: Pointer to Global MAC structure 10273 * @msg_buf: pointer to the SME message buffer 10274 * 10275 * This function processes SME request messages from HDD or upper layer 10276 * application. 10277 * 10278 * Return: None 10279 */ 10280 static void lim_process_set_ie_req(struct mac_context *mac_ctx, uint32_t *msg_buf) 10281 { 10282 struct send_extcap_ie *msg; 10283 QDF_STATUS status; 10284 tDot11fIEExtCap extra_ext_cap = {0}; 10285 uint16_t vdev_id; 10286 struct wlan_objmgr_vdev *vdev = NULL; 10287 struct mlme_legacy_priv *mlme_priv; 10288 struct s_ext_cap *p_ext_cap; 10289 10290 if (!msg_buf) { 10291 pe_err("Buffer is Pointing to NULL"); 10292 return; 10293 } 10294 10295 msg = (struct send_extcap_ie *)msg_buf; 10296 vdev_id = msg->session_id; 10297 10298 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc, 10299 vdev_id, 10300 WLAN_LEGACY_SME_ID); 10301 if (!vdev) 10302 return; 10303 10304 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 10305 if (!mlme_priv) { 10306 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID); 10307 return; 10308 } 10309 10310 if (!mlme_priv->connect_info.ext_cap_ie[0]) 10311 goto send_ie; 10312 10313 lim_update_extcap_struct(mac_ctx, 10314 mlme_priv->connect_info.ext_cap_ie, 10315 &extra_ext_cap); 10316 p_ext_cap = (struct s_ext_cap *)extra_ext_cap.bytes; 10317 if (p_ext_cap->interworking_service) 10318 p_ext_cap->qos_map = 1; 10319 extra_ext_cap.num_bytes = 10320 lim_compute_ext_cap_ie_length(&extra_ext_cap); 10321 send_ie: 10322 status = lim_send_ext_cap_ie(mac_ctx, msg->session_id, &extra_ext_cap, 10323 true); 10324 if (QDF_IS_STATUS_ERROR(status)) 10325 pe_err("Unable to send ExtCap to FW"); 10326 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID); 10327 } 10328 10329 #ifdef WLAN_FEATURE_11AX_BSS_COLOR 10330 10331 /** 10332 * obss_color_collision_process_color_disable() - Disable bss color 10333 * @mac_ctx: Pointer to Global MAC structure 10334 * @session: pointer to session 10335 * 10336 * This function will disable bss color. 10337 * 10338 * Return: None 10339 */ 10340 static void obss_color_collision_process_color_disable(struct mac_context *mac_ctx, 10341 struct pe_session *session) 10342 { 10343 tUpdateBeaconParams beacon_params; 10344 10345 if (!session) { 10346 pe_err("Invalid session"); 10347 return; 10348 } 10349 10350 if (session->valid && !LIM_IS_AP_ROLE(session)) { 10351 pe_err("Invalid SystemRole %d", 10352 GET_LIM_SYSTEM_ROLE(session)); 10353 return; 10354 } 10355 10356 if (session->bss_color_changing == 1) { 10357 pe_warn("%d: color change in progress", session->smeSessionId); 10358 /* Continue color collision detection */ 10359 lim_send_obss_color_collision_cfg(mac_ctx, session, 10360 OBSS_COLOR_COLLISION_DETECTION); 10361 return; 10362 } 10363 10364 if (session->he_op.bss_col_disabled == 1) { 10365 pe_warn("%d: bss color already disabled", 10366 session->smeSessionId); 10367 /* Continue free color detection */ 10368 lim_send_obss_color_collision_cfg(mac_ctx, session, 10369 OBSS_COLOR_FREE_SLOT_AVAILABLE); 10370 return; 10371 } 10372 10373 qdf_mem_zero(&beacon_params, sizeof(beacon_params)); 10374 beacon_params.paramChangeBitmap |= PARAM_BSS_COLOR_CHANGED; 10375 session->he_op.bss_col_disabled = 1; 10376 beacon_params.bss_color_disabled = 1; 10377 beacon_params.bss_color = session->he_op.bss_color; 10378 10379 if (sch_set_fixed_beacon_fields(mac_ctx, session) != 10380 QDF_STATUS_SUCCESS) { 10381 pe_err("Unable to set op mode IE in beacon"); 10382 return; 10383 } 10384 10385 lim_send_beacon_params(mac_ctx, &beacon_params, session); 10386 lim_send_obss_color_collision_cfg(mac_ctx, session, 10387 OBSS_COLOR_FREE_SLOT_AVAILABLE); 10388 } 10389 10390 /** 10391 * obss_color_collision_process_color_change() - Process bss color change 10392 * @mac_ctx: Pointer to Global MAC structure 10393 * @session: pointer to session 10394 * @obss_color_info: obss color collision/free slot indication info 10395 * 10396 * This function selects new color ib case of bss color collision. 10397 * 10398 * Return: None 10399 */ 10400 static void obss_color_collision_process_color_change(struct mac_context *mac_ctx, 10401 struct pe_session *session, 10402 struct wmi_obss_color_collision_info *obss_color_info) 10403 { 10404 int i, num_bss_color = 0; 10405 uint32_t bss_color_bitmap; 10406 uint8_t bss_color_index_array[MAX_BSS_COLOR_VALUE]; 10407 uint32_t rand_byte = 0; 10408 struct sir_set_he_bss_color he_bss_color; 10409 bool is_color_collision = false; 10410 10411 10412 if (session->bss_color_changing == 1) { 10413 pe_err("%d: color change in progress", session->smeSessionId); 10414 return; 10415 } 10416 10417 if (!session->he_op.bss_col_disabled) { 10418 if (session->he_op.bss_color < 32) 10419 is_color_collision = (obss_color_info-> 10420 obss_color_bitmap_bit0to31 >> 10421 session->he_op.bss_color) & 0x01; 10422 else 10423 is_color_collision = (obss_color_info-> 10424 obss_color_bitmap_bit32to63 >> 10425 (session->he_op.bss_color - 10426 32)) & 0x01; 10427 if (!is_color_collision) { 10428 pe_err("%d: color collision not found, curr_color: %d", 10429 session->smeSessionId, 10430 session->he_op.bss_color); 10431 return; 10432 } 10433 } 10434 10435 bss_color_bitmap = obss_color_info->obss_color_bitmap_bit0to31; 10436 10437 /* Skip color zero */ 10438 bss_color_bitmap = bss_color_bitmap >> 1; 10439 for (i = 0; (i < 31) && (num_bss_color < MAX_BSS_COLOR_VALUE); i++) { 10440 if (!(bss_color_bitmap & 0x01)) { 10441 bss_color_index_array[num_bss_color] = i + 1; 10442 num_bss_color++; 10443 } 10444 bss_color_bitmap = bss_color_bitmap >> 1; 10445 } 10446 10447 bss_color_bitmap = obss_color_info->obss_color_bitmap_bit32to63; 10448 for (i = 0; (i < 32) && (num_bss_color < MAX_BSS_COLOR_VALUE); i++) { 10449 if (!(bss_color_bitmap & 0x01)) { 10450 bss_color_index_array[num_bss_color] = i + 32; 10451 num_bss_color++; 10452 } 10453 bss_color_bitmap = bss_color_bitmap >> 1; 10454 } 10455 10456 if (num_bss_color) { 10457 qdf_get_random_bytes((void *) &rand_byte, 1); 10458 i = (rand_byte + qdf_mc_timer_get_system_ticks()) % 10459 num_bss_color; 10460 pe_debug("New bss color = %d", bss_color_index_array[i]); 10461 he_bss_color.vdev_id = obss_color_info->vdev_id; 10462 he_bss_color.bss_color = bss_color_index_array[i]; 10463 10464 /* Take the wakelock for 2 sec, release it after color change */ 10465 wma_prevent_suspend_on_obss_color_collision(session->vdev); 10466 10467 lim_process_set_he_bss_color(mac_ctx, 10468 (uint32_t *)&he_bss_color); 10469 } else { 10470 pe_err("Unable to find bss color from bitmasp"); 10471 if (obss_color_info->evt_type == 10472 OBSS_COLOR_FREE_SLOT_TIMER_EXPIRY && 10473 session->obss_color_collision_dec_evt == 10474 OBSS_COLOR_FREE_SLOT_TIMER_EXPIRY) 10475 /* In dot11BSSColorCollisionAPPeriod and 10476 * timer expired, time to disable bss color. 10477 */ 10478 obss_color_collision_process_color_disable(mac_ctx, 10479 session); 10480 else 10481 /* 10482 * Enter dot11BSSColorCollisionAPPeriod period. 10483 */ 10484 lim_send_obss_color_collision_cfg(mac_ctx, session, 10485 OBSS_COLOR_FREE_SLOT_TIMER_EXPIRY); 10486 } 10487 } 10488 10489 void lim_process_set_he_bss_color(struct mac_context *mac_ctx, uint32_t *msg_buf) 10490 { 10491 struct sir_set_he_bss_color *bss_color; 10492 struct pe_session *session_entry = NULL; 10493 tUpdateBeaconParams beacon_params; 10494 10495 if (!msg_buf) { 10496 pe_err("Buffer is Pointing to NULL"); 10497 return; 10498 } 10499 10500 bss_color = (struct sir_set_he_bss_color *)msg_buf; 10501 session_entry = pe_find_session_by_vdev_id(mac_ctx, bss_color->vdev_id); 10502 if (!session_entry) { 10503 pe_err("Session not found for given vdev_id %d", 10504 bss_color->vdev_id); 10505 return; 10506 } 10507 10508 if (session_entry->valid && !LIM_IS_AP_ROLE(session_entry)) { 10509 pe_err("Invalid SystemRole %d", 10510 GET_LIM_SYSTEM_ROLE(session_entry)); 10511 return; 10512 } 10513 10514 if (bss_color->bss_color == session_entry->he_op.bss_color) { 10515 pe_err("No change in BSS color, current BSS color %d", 10516 bss_color->bss_color); 10517 return; 10518 } 10519 qdf_mem_zero(&beacon_params, sizeof(beacon_params)); 10520 beacon_params.paramChangeBitmap |= PARAM_BSS_COLOR_CHANGED; 10521 session_entry->he_op.bss_col_disabled = 1; 10522 session_entry->he_bss_color_change.countdown = 10523 BSS_COLOR_SWITCH_COUNTDOWN; 10524 session_entry->he_bss_color_change.new_color = bss_color->bss_color; 10525 beacon_params.bss_color_disabled = 1; 10526 beacon_params.bss_color = session_entry->he_op.bss_color; 10527 session_entry->bss_color_changing = 1; 10528 10529 if (wlan_vdev_mlme_get_he_spr_enabled(session_entry->vdev)) 10530 /* Disable spatial reuse during BSS color change */ 10531 wlan_spatial_reuse_config_set(session_entry->vdev, 0, 0); 10532 10533 if (sch_set_fixed_beacon_fields(mac_ctx, session_entry) != 10534 QDF_STATUS_SUCCESS) { 10535 pe_err("Unable to set op mode IE in beacon"); 10536 return; 10537 } 10538 10539 lim_send_beacon_params(mac_ctx, &beacon_params, session_entry); 10540 lim_send_obss_color_collision_cfg(mac_ctx, session_entry, 10541 OBSS_COLOR_COLLISION_DETECTION_DISABLE); 10542 } 10543 10544 void lim_reconfig_obss_scan_param(struct mac_context *mac_ctx, 10545 uint32_t *msg_buf) 10546 { 10547 struct sir_cfg_obss_scan *obss_scan_param; 10548 struct pe_session *session = NULL; 10549 struct wmi_obss_color_collision_cfg_param *cfg_param; 10550 struct scheduler_msg msg = {0}; 10551 10552 if (!msg_buf) { 10553 pe_err("Buffer is Pointing to NULL"); 10554 return; 10555 } 10556 10557 obss_scan_param = (struct sir_cfg_obss_scan *)msg_buf; 10558 session = pe_find_session_by_vdev_id(mac_ctx, obss_scan_param->vdev_id); 10559 if (!session) { 10560 pe_err("Session not found for given vdev_id %d", 10561 obss_scan_param->vdev_id); 10562 return; 10563 } 10564 10565 if (!session->he_capable || 10566 !session->is_session_obss_color_collision_det_enabled || 10567 session->obss_color_collision_dec_evt == 10568 OBSS_COLOR_COLLISION_DETECTION_DISABLE) { 10569 pe_debug("%d: obss color det not enabled, he_cap:%d, sup:%d:%d event_type:%d", 10570 session->smeSessionId, session->he_capable, 10571 session->is_session_obss_color_collision_det_enabled, 10572 mac_ctx->mlme_cfg->obss_ht40.obss_color_collision_offload_enabled, 10573 session->obss_color_collision_dec_evt); 10574 return; 10575 } 10576 10577 cfg_param = qdf_mem_malloc(sizeof(*cfg_param)); 10578 if (!cfg_param) 10579 return; 10580 10581 pe_debug("vdev_id %d: sending event:%d scan_reconfig:%d", 10582 session->smeSessionId, session->obss_color_collision_dec_evt, 10583 obss_scan_param->is_scan_reconfig); 10584 cfg_param->vdev_id = session->smeSessionId; 10585 cfg_param->evt_type = session->obss_color_collision_dec_evt; 10586 cfg_param->current_bss_color = session->he_op.bss_color; 10587 10588 if (obss_scan_param->is_scan_reconfig) 10589 cfg_param->detection_period_ms = 10590 OBSS_COLOR_COLLISION_DETECTION_NDP_PERIOD_MS; 10591 else 10592 cfg_param->detection_period_ms = 10593 OBSS_COLOR_COLLISION_DETECTION_STA_PERIOD_MS; 10594 cfg_param->scan_period_ms = OBSS_COLOR_COLLISION_SCAN_PERIOD_MS; 10595 10596 if (session->obss_color_collision_dec_evt == 10597 OBSS_COLOR_FREE_SLOT_TIMER_EXPIRY) 10598 cfg_param->free_slot_expiry_time_ms = 10599 OBSS_COLOR_COLLISION_FREE_SLOT_EXPIRY_MS; 10600 10601 msg.type = WMA_OBSS_COLOR_COLLISION_REQ; 10602 msg.bodyptr = cfg_param; 10603 msg.reserved = 0; 10604 10605 if (QDF_IS_STATUS_ERROR(scheduler_post_message(QDF_MODULE_ID_PE, 10606 QDF_MODULE_ID_WMA, 10607 QDF_MODULE_ID_WMA, 10608 &msg))) { 10609 qdf_mem_free(cfg_param); 10610 } 10611 } 10612 10613 void lim_send_obss_color_collision_cfg(struct mac_context *mac_ctx, 10614 struct pe_session *session, 10615 enum wmi_obss_color_collision_evt_type 10616 event_type) 10617 { 10618 struct wmi_obss_color_collision_cfg_param *cfg_param; 10619 struct scheduler_msg msg = {0}; 10620 10621 if (!session) { 10622 pe_err("Invalid session"); 10623 return; 10624 } 10625 10626 if (!session->he_capable || 10627 !session->is_session_obss_color_collision_det_enabled) { 10628 pe_debug("%d: obss color det not enabled, he_cap:%d, sup:%d:%d", 10629 session->smeSessionId, session->he_capable, 10630 session->is_session_obss_color_collision_det_enabled, 10631 mac_ctx->mlme_cfg->obss_ht40. 10632 obss_color_collision_offload_enabled); 10633 return; 10634 } 10635 10636 cfg_param = qdf_mem_malloc(sizeof(*cfg_param)); 10637 if (!cfg_param) 10638 return; 10639 10640 pe_debug("%d: sending event:%d", session->smeSessionId, event_type); 10641 qdf_mem_zero(cfg_param, sizeof(*cfg_param)); 10642 cfg_param->vdev_id = session->smeSessionId; 10643 cfg_param->evt_type = event_type; 10644 cfg_param->current_bss_color = session->he_op.bss_color; 10645 if (LIM_IS_AP_ROLE(session)) 10646 cfg_param->detection_period_ms = 10647 OBSS_COLOR_COLLISION_DETECTION_AP_PERIOD_MS; 10648 else 10649 cfg_param->detection_period_ms = 10650 OBSS_COLOR_COLLISION_DETECTION_STA_PERIOD_MS; 10651 10652 cfg_param->scan_period_ms = OBSS_COLOR_COLLISION_SCAN_PERIOD_MS; 10653 if (event_type == OBSS_COLOR_FREE_SLOT_TIMER_EXPIRY) 10654 cfg_param->free_slot_expiry_time_ms = 10655 OBSS_COLOR_COLLISION_FREE_SLOT_EXPIRY_MS; 10656 10657 msg.type = WMA_OBSS_COLOR_COLLISION_REQ; 10658 msg.bodyptr = cfg_param; 10659 msg.reserved = 0; 10660 10661 if (QDF_IS_STATUS_ERROR(scheduler_post_message(QDF_MODULE_ID_PE, 10662 QDF_MODULE_ID_WMA, 10663 QDF_MODULE_ID_WMA, 10664 &msg))) { 10665 qdf_mem_free(cfg_param); 10666 } else { 10667 session->obss_color_collision_dec_evt = event_type; 10668 } 10669 } 10670 10671 void lim_process_obss_color_collision_info(struct mac_context *mac_ctx, 10672 uint32_t *msg_buf) 10673 { 10674 struct wmi_obss_color_collision_info *obss_color_info; 10675 struct pe_session *session; 10676 10677 if (!msg_buf) { 10678 pe_err("Buffer is Pointing to NULL"); 10679 return; 10680 } 10681 10682 obss_color_info = (struct wmi_obss_color_collision_info *)msg_buf; 10683 session = pe_find_session_by_vdev_id(mac_ctx, obss_color_info->vdev_id); 10684 if (!session) { 10685 pe_err("Session not found for given session_id %d", 10686 obss_color_info->vdev_id); 10687 return; 10688 } 10689 10690 pe_debug("vdev_id:%d, evt:%d:%d, 0to31:0x%x, 32to63:0x%x, cap:%d:%d:%d", 10691 obss_color_info->vdev_id, 10692 obss_color_info->evt_type, 10693 session->obss_color_collision_dec_evt, 10694 obss_color_info->obss_color_bitmap_bit0to31, 10695 obss_color_info->obss_color_bitmap_bit32to63, 10696 session->he_capable, 10697 session->is_session_obss_color_collision_det_enabled, 10698 mac_ctx->mlme_cfg->obss_ht40. 10699 obss_color_collision_offload_enabled); 10700 10701 if (!session->he_capable || 10702 !session->is_session_obss_color_collision_det_enabled) { 10703 return; 10704 } 10705 10706 switch (obss_color_info->evt_type) { 10707 case OBSS_COLOR_COLLISION_DETECTION_DISABLE: 10708 pe_err("%d: FW disabled obss color det. he_cap:%d, sup:%d:%d", 10709 session->smeSessionId, session->he_capable, 10710 session->is_session_obss_color_collision_det_enabled, 10711 mac_ctx->mlme_cfg->obss_ht40. 10712 obss_color_collision_offload_enabled); 10713 session->is_session_obss_color_collision_det_enabled = false; 10714 return; 10715 case OBSS_COLOR_FREE_SLOT_AVAILABLE: 10716 case OBSS_COLOR_COLLISION_DETECTION: 10717 case OBSS_COLOR_FREE_SLOT_TIMER_EXPIRY: 10718 if (session->valid && !LIM_IS_AP_ROLE(session)) { 10719 pe_debug("Invalid System Role %d", 10720 GET_LIM_SYSTEM_ROLE(session)); 10721 return; 10722 } 10723 10724 if (session->obss_color_collision_dec_evt != 10725 obss_color_info->evt_type) { 10726 pe_debug("%d: Wrong event: %d, skipping", 10727 obss_color_info->vdev_id, 10728 obss_color_info->evt_type); 10729 return; 10730 } 10731 obss_color_collision_process_color_change(mac_ctx, session, 10732 obss_color_info); 10733 break; 10734 default: 10735 pe_err("%d: Invalid event type %d", 10736 obss_color_info->vdev_id, obss_color_info->evt_type); 10737 return; 10738 } 10739 } 10740 #endif 10741 10742 void lim_send_csa_restart_req(struct mac_context *mac_ctx, uint8_t vdev_id) 10743 { 10744 struct pe_session *session; 10745 10746 session = pe_find_session_by_vdev_id(mac_ctx, vdev_id); 10747 if (!session) { 10748 pe_err("session not found for vdev id %d", vdev_id); 10749 return; 10750 } 10751 10752 wlan_vdev_mlme_sm_deliver_evt(session->vdev, 10753 WLAN_VDEV_SM_EV_CSA_RESTART, 10754 sizeof(*session), session); 10755 } 10756 10757 void lim_continue_sta_csa_req(struct mac_context *mac_ctx, uint8_t vdev_id) 10758 { 10759 pe_info("Continue CSA for STA vdev id %d", vdev_id); 10760 lim_process_channel_switch(mac_ctx, vdev_id); 10761 } 10762