1 /* 2 * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /* 21 * This file lim_utils.cc contains the utility functions 22 * LIM uses. 23 * Author: Chandra Modumudi 24 * Date: 02/13/02 25 * History:- 26 * Date Modified by Modification Information 27 * -------------------------------------------------------------------- 28 */ 29 30 #include "sch_api.h" 31 #include "lim_utils.h" 32 #include "lim_types.h" 33 #include "lim_security_utils.h" 34 #include "lim_prop_exts_utils.h" 35 #include "lim_send_messages.h" 36 #include "lim_ser_des_utils.h" 37 #include "lim_admit_control.h" 38 #include "dot11f.h" 39 #include "dot11fdefs.h" 40 #include "wmm_apsd.h" 41 #include "lim_trace.h" 42 43 #ifdef FEATURE_WLAN_DIAG_SUPPORT 44 #include "host_diag_core_event.h" 45 #endif /* FEATURE_WLAN_DIAG_SUPPORT */ 46 #include "lim_session_utils.h" 47 #include "lim_ft_defs.h" 48 #include "lim_session.h" 49 #include "cds_reg_service.h" 50 #include "nan_datapath.h" 51 #include "wma.h" 52 #include "wlan_reg_services_api.h" 53 #include "wlan_policy_mgr_api.h" 54 #include "wlan_mlme_public_struct.h" 55 #include "wlan_mlme_ucfg_api.h" 56 #include "wma_pasn_peer_api.h" 57 #ifdef WLAN_FEATURE_11AX_BSS_COLOR 58 #include "wma_he.h" 59 #endif 60 #include "wlan_utility.h" 61 62 #include "wni_cfg.h" 63 #include "cfg_mlme_obss_ht40.h" 64 #include "cfg_ucfg_api.h" 65 #include "lim_ft.h" 66 #include "wlan_mlme_main.h" 67 #include "qdf_util.h" 68 #include "wlan_qct_sys.h" 69 #include <wlan_scan_ucfg_api.h> 70 #include <wlan_dlm_api.h> 71 #include <lim_assoc_utils.h> 72 #include "wlan_mlme_ucfg_api.h" 73 #include "nan_ucfg_api.h" 74 #include "wlan_twt_ucfg_ext_cfg.h" 75 #ifdef WLAN_FEATURE_11BE 76 #include "wma_eht.h" 77 #endif 78 #ifdef WLAN_FEATURE_11BE_MLO 79 #include <lim_mlo.h> 80 #endif 81 #include "wlan_cmn_ieee80211.h" 82 #include <wlan_cm_api.h> 83 #include <wlan_vdev_mgr_utils_api.h> 84 #include "parser_api.h" 85 #include "wlan_mlo_mgr_link_switch.h" 86 #include "wlan_epcs_api.h" 87 88 /** ------------------------------------------------------------- 89 \fn lim_delete_dialogue_token_list 90 \brief deletes the complete lim dialogue token linked list. 91 \param struct mac_context * mac 92 \return None 93 -------------------------------------------------------------*/ 94 void lim_delete_dialogue_token_list(struct mac_context *mac) 95 { 96 tpDialogueToken pCurrNode = mac->lim.pDialogueTokenHead; 97 98 while (mac->lim.pDialogueTokenHead) { 99 pCurrNode = mac->lim.pDialogueTokenHead; 100 mac->lim.pDialogueTokenHead = 101 mac->lim.pDialogueTokenHead->next; 102 qdf_mem_free(pCurrNode); 103 pCurrNode = NULL; 104 } 105 mac->lim.pDialogueTokenTail = NULL; 106 } 107 108 char *lim_mlm_state_str(tLimMlmStates state) 109 { 110 switch (state) { 111 case eLIM_MLM_OFFLINE_STATE: 112 return "eLIM_MLM_OFFLINE_STATE"; 113 case eLIM_MLM_IDLE_STATE: 114 return "eLIM_MLM_IDLE_STATE"; 115 case eLIM_MLM_WT_JOIN_BEACON_STATE: 116 return "eLIM_MLM_WT_JOIN_BEACON_STATE"; 117 case eLIM_MLM_JOINED_STATE: 118 return "eLIM_MLM_JOINED_STATE"; 119 case eLIM_MLM_BSS_STARTED_STATE: 120 return "eLIM_MLM_BSS_STARTED_STATE"; 121 case eLIM_MLM_WT_AUTH_FRAME2_STATE: 122 return "eLIM_MLM_WT_AUTH_FRAME2_STATE"; 123 case eLIM_MLM_WT_AUTH_FRAME3_STATE: 124 return "eLIM_MLM_WT_AUTH_FRAME3_STATE"; 125 case eLIM_MLM_WT_AUTH_FRAME4_STATE: 126 return "eLIM_MLM_WT_AUTH_FRAME4_STATE"; 127 case eLIM_MLM_AUTH_RSP_TIMEOUT_STATE: 128 return "eLIM_MLM_AUTH_RSP_TIMEOUT_STATE"; 129 case eLIM_MLM_AUTHENTICATED_STATE: 130 return "eLIM_MLM_AUTHENTICATED_STATE"; 131 case eLIM_MLM_WT_ASSOC_RSP_STATE: 132 return "eLIM_MLM_WT_ASSOC_RSP_STATE"; 133 case eLIM_MLM_WT_REASSOC_RSP_STATE: 134 return "eLIM_MLM_WT_REASSOC_RSP_STATE"; 135 case eLIM_MLM_WT_FT_REASSOC_RSP_STATE: 136 return "eLIM_MLM_WT_FT_REASSOC_RSP_STATE"; 137 case eLIM_MLM_WT_DEL_STA_RSP_STATE: 138 return "eLIM_MLM_WT_DEL_STA_RSP_STATE"; 139 case eLIM_MLM_WT_DEL_BSS_RSP_STATE: 140 return "eLIM_MLM_WT_DEL_BSS_RSP_STATE"; 141 case eLIM_MLM_WT_ADD_STA_RSP_STATE: 142 return "eLIM_MLM_WT_ADD_STA_RSP_STATE"; 143 case eLIM_MLM_WT_ADD_BSS_RSP_STATE: 144 return "eLIM_MLM_WT_ADD_BSS_RSP_STATE"; 145 case eLIM_MLM_REASSOCIATED_STATE: 146 return "eLIM_MLM_REASSOCIATED_STATE"; 147 case eLIM_MLM_LINK_ESTABLISHED_STATE: 148 return "eLIM_MLM_LINK_ESTABLISHED_STATE"; 149 case eLIM_MLM_WT_ASSOC_CNF_STATE: 150 return "eLIM_MLM_WT_ASSOC_CNF_STATE"; 151 case eLIM_MLM_WT_ADD_BSS_RSP_ASSOC_STATE: 152 return "eLIM_MLM_WT_ADD_BSS_RSP_ASSOC_STATE"; 153 case eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE: 154 return "eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE"; 155 case eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE: 156 return "eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE"; 157 case eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE: 158 return "eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE"; 159 case eLIM_MLM_WT_SET_BSS_KEY_STATE: 160 return "eLIM_MLM_WT_SET_BSS_KEY_STATE"; 161 case eLIM_MLM_WT_SET_STA_KEY_STATE: 162 return "eLIM_MLM_WT_SET_STA_KEY_STATE"; 163 default: 164 return "INVALID MLM state"; 165 } 166 } 167 168 void 169 lim_print_mlm_state(struct mac_context *mac, uint16_t logLevel, tLimMlmStates state) 170 { 171 pe_debug("Mlm state: %s", lim_mlm_state_str(state)); 172 } 173 174 char *lim_sme_state_str(tLimSmeStates state) 175 { 176 switch (state) { 177 case eLIM_SME_OFFLINE_STATE: 178 return "eLIM_SME_OFFLINE_STATE"; 179 case eLIM_SME_IDLE_STATE: 180 return "eLIM_SME_OFFLINE_STATE"; 181 case eLIM_SME_SUSPEND_STATE: 182 return "eLIM_SME_SUSPEND_STATE"; 183 case eLIM_SME_WT_JOIN_STATE: 184 return "eLIM_SME_WT_JOIN_STATE"; 185 case eLIM_SME_WT_AUTH_STATE: 186 return "eLIM_SME_WT_AUTH_STATE"; 187 case eLIM_SME_WT_ASSOC_STATE: 188 return "eLIM_SME_WT_ASSOC_STATE"; 189 case eLIM_SME_WT_REASSOC_STATE: 190 return "eLIM_SME_WT_REASSOC_STATE"; 191 case eLIM_SME_JOIN_FAILURE_STATE: 192 return "eLIM_SME_JOIN_FAILURE_STATE"; 193 case eLIM_SME_ASSOCIATED_STATE: 194 return "eLIM_SME_ASSOCIATED_STATE"; 195 case eLIM_SME_REASSOCIATED_STATE: 196 return "eLIM_SME_REASSOCIATED_STATE"; 197 case eLIM_SME_LINK_EST_STATE: 198 return "eLIM_SME_LINK_EST_STATE"; 199 case eLIM_SME_WT_PRE_AUTH_STATE: 200 return "eLIM_SME_WT_PRE_AUTH_STATE"; 201 case eLIM_SME_WT_DISASSOC_STATE: 202 return "eLIM_SME_WT_DISASSOC_STATE"; 203 case eLIM_SME_WT_DEAUTH_STATE: 204 return "eLIM_SME_WT_DEAUTH_STATE"; 205 case eLIM_SME_WT_START_BSS_STATE: 206 return "eLIM_SME_WT_START_BSS_STATE"; 207 case eLIM_SME_WT_STOP_BSS_STATE: 208 return "eLIM_SME_WT_STOP_BSS_STATE"; 209 case eLIM_SME_NORMAL_STATE: 210 return "eLIM_SME_NORMAL_STATE"; 211 default: 212 return "INVALID SME STATE"; 213 } 214 } 215 216 void 217 lim_print_sme_state(struct mac_context *mac, uint16_t logLevel, tLimSmeStates state) 218 { 219 pe_debug("SME state: %s", lim_sme_state_str(state)); 220 } 221 222 char *lim_msg_str(uint32_t msgType) 223 { 224 switch (msgType) { 225 case eWNI_SME_SYS_READY_IND: 226 return "eWNI_SME_SYS_READY_IND"; 227 case eWNI_SME_JOIN_REQ: 228 return "eWNI_SME_JOIN_REQ"; 229 case eWNI_SME_JOIN_RSP: 230 return "eWNI_SME_JOIN_RSP"; 231 case eWNI_SME_SETCONTEXT_RSP: 232 return "eWNI_SME_SETCONTEXT_RSP"; 233 case eWNI_SME_REASSOC_REQ: 234 return "eWNI_SME_REASSOC_REQ"; 235 case eWNI_SME_REASSOC_RSP: 236 return "eWNI_SME_REASSOC_RSP"; 237 case eWNI_SME_DISASSOC_REQ: 238 return "eWNI_SME_DISASSOC_REQ"; 239 case eWNI_SME_DISASSOC_RSP: 240 return "eWNI_SME_DISASSOC_RSP"; 241 case eWNI_SME_DISASSOC_IND: 242 return "eWNI_SME_DISASSOC_IND"; 243 case eWNI_SME_DISASSOC_CNF: 244 return "eWNI_SME_DISASSOC_CNF"; 245 case eWNI_SME_DEAUTH_REQ: 246 return "eWNI_SME_DEAUTH_REQ"; 247 case eWNI_SME_DEAUTH_RSP: 248 return "eWNI_SME_DEAUTH_RSP"; 249 case eWNI_SME_DEAUTH_IND: 250 return "eWNI_SME_DEAUTH_IND"; 251 case eWNI_SME_START_BSS_REQ: 252 return "eWNI_SME_START_BSS_REQ"; 253 case eWNI_SME_START_BSS_RSP: 254 return "eWNI_SME_START_BSS_RSP"; 255 case eWNI_SME_ASSOC_IND: 256 return "eWNI_SME_ASSOC_IND"; 257 case eWNI_SME_ASSOC_IND_UPPER_LAYER: 258 return "eWNI_SME_ASSOC_IND_UPPER_LAYER"; 259 case eWNI_SME_ASSOC_CNF: 260 return "eWNI_SME_ASSOC_CNF"; 261 case eWNI_SME_SWITCH_CHL_IND: 262 return "eWNI_SME_SWITCH_CHL_IND"; 263 case eWNI_SME_STOP_BSS_REQ: 264 return "eWNI_SME_STOP_BSS_REQ"; 265 case eWNI_SME_STOP_BSS_RSP: 266 return "eWNI_SME_STOP_BSS_RSP"; 267 case eWNI_SME_DEAUTH_CNF: 268 return "eWNI_SME_DEAUTH_CNF"; 269 case eWNI_SME_ADDTS_REQ: 270 return "eWNI_SME_ADDTS_REQ"; 271 case eWNI_SME_MSCS_REQ: 272 return "eWNI_SME_MSCS_REQ"; 273 case eWNI_SME_ADDTS_RSP: 274 return "eWNI_SME_ADDTS_RSP"; 275 case eWNI_SME_DELTS_REQ: 276 return "eWNI_SME_DELTS_REQ"; 277 case eWNI_SME_DELTS_RSP: 278 return "eWNI_SME_DELTS_RSP"; 279 case eWNI_SME_DELTS_IND: 280 return "eWNI_SME_DELTS_IND"; 281 case SIR_BB_XPORT_MGMT_MSG: 282 return "SIR_BB_XPORT_MGMT_MSG"; 283 case SIR_LIM_JOIN_FAIL_TIMEOUT: 284 return "SIR_LIM_JOIN_FAIL_TIMEOUT"; 285 case SIR_LIM_AUTH_FAIL_TIMEOUT: 286 return "SIR_LIM_AUTH_FAIL_TIMEOUT"; 287 case SIR_LIM_AUTH_RSP_TIMEOUT: 288 return "SIR_LIM_AUTH_RSP_TIMEOUT"; 289 case SIR_LIM_ASSOC_FAIL_TIMEOUT: 290 return "SIR_LIM_ASSOC_FAIL_TIMEOUT"; 291 case SIR_LIM_REASSOC_FAIL_TIMEOUT: 292 return "SIR_LIM_REASSOC_FAIL_TIMEOUT"; 293 case SIR_LIM_HEART_BEAT_TIMEOUT: 294 return "SIR_LIM_HEART_BEAT_TIMEOUT"; 295 case SIR_LIM_ADDTS_RSP_TIMEOUT: 296 return "SIR_LIM_ADDTS_RSP_TIMEOUT"; 297 case SIR_LIM_LINK_TEST_DURATION_TIMEOUT: 298 return "SIR_LIM_LINK_TEST_DURATION_TIMEOUT"; 299 case SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT: 300 return "SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT"; 301 case SIR_LIM_CNF_WAIT_TIMEOUT: 302 return "SIR_LIM_CNF_WAIT_TIMEOUT"; 303 case SIR_LIM_FT_PREAUTH_RSP_TIMEOUT: 304 return "SIR_LIM_FT_PREAUTH_RSP_TIMEOUT"; 305 #ifdef FEATURE_WLAN_ESE 306 case eWNI_SME_GET_TSM_STATS_REQ: 307 return "eWNI_SME_GET_TSM_STATS_REQ"; 308 case eWNI_SME_GET_TSM_STATS_RSP: 309 return "eWNI_SME_GET_TSM_STATS_RSP"; 310 #endif /* FEATURE_WLAN_ESE */ 311 case eWNI_SME_SET_HW_MODE_REQ: 312 return "eWNI_SME_SET_HW_MODE_REQ"; 313 case eWNI_SME_SET_HW_MODE_RESP: 314 return "eWNI_SME_SET_HW_MODE_RESP"; 315 case eWNI_SME_HW_MODE_TRANS_IND: 316 return "eWNI_SME_HW_MODE_TRANS_IND"; 317 case SIR_LIM_PROCESS_DEFERRED_QUEUE: 318 return "SIR_LIM_PROCESS_DEFERRED_QUEUE"; 319 default: 320 return "Unknown"; 321 } 322 } 323 324 char *lim_result_code_str(tSirResultCodes resultCode) 325 { 326 switch (resultCode) { 327 case eSIR_SME_SUCCESS: 328 return "eSIR_SME_SUCCESS"; 329 case eSIR_LOGE_EXCEPTION: 330 return "eSIR_LOGE_EXCEPTION"; 331 case eSIR_SME_INVALID_PARAMETERS: 332 return "eSIR_SME_INVALID_PARAMETERS"; 333 case eSIR_SME_UNEXPECTED_REQ_RESULT_CODE: 334 return "eSIR_SME_UNEXPECTED_REQ_RESULT_CODE"; 335 case eSIR_SME_RESOURCES_UNAVAILABLE: 336 return "eSIR_SME_RESOURCES_UNAVAILABLE"; 337 case eSIR_SME_SCAN_FAILED: 338 return "eSIR_SME_SCAN_FAILED"; 339 case eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED: 340 return "eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED"; 341 case eSIR_SME_LOST_LINK_WITH_PEER_RESULT_CODE: 342 return "eSIR_SME_LOST_LINK_WITH_PEER_RESULT_CODE"; 343 case eSIR_SME_REFUSED: 344 return "eSIR_SME_REFUSED"; 345 case eSIR_SME_JOIN_TIMEOUT_RESULT_CODE: 346 return "eSIR_SME_JOIN_TIMEOUT_RESULT_CODE"; 347 case eSIR_SME_AUTH_TIMEOUT_RESULT_CODE: 348 return "eSIR_SME_AUTH_TIMEOUT_RESULT_CODE"; 349 case eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE: 350 return "eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE"; 351 case eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE: 352 return "eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE"; 353 case eSIR_SME_MAX_NUM_OF_PRE_AUTH_REACHED: 354 return "eSIR_SME_MAX_NUM_OF_PRE_AUTH_REACHED"; 355 case eSIR_SME_AUTH_REFUSED: 356 return "eSIR_SME_AUTH_REFUSED"; 357 case eSIR_SME_INVALID_WEP_DEFAULT_KEY: 358 return "eSIR_SME_INVALID_WEP_DEFAULT_KEY"; 359 case eSIR_SME_ASSOC_REFUSED: 360 return "eSIR_SME_ASSOC_REFUSED"; 361 case eSIR_SME_REASSOC_REFUSED: 362 return "eSIR_SME_REASSOC_REFUSED"; 363 case eSIR_SME_STA_NOT_AUTHENTICATED: 364 return "eSIR_SME_STA_NOT_AUTHENTICATED"; 365 case eSIR_SME_STA_NOT_ASSOCIATED: 366 return "eSIR_SME_STA_NOT_ASSOCIATED"; 367 case eSIR_SME_ALREADY_JOINED_A_BSS: 368 return "eSIR_SME_ALREADY_JOINED_A_BSS"; 369 case eSIR_SME_MORE_SCAN_RESULTS_FOLLOW: 370 return "eSIR_SME_MORE_SCAN_RESULTS_FOLLOW"; 371 case eSIR_SME_INVALID_ASSOC_RSP_RXED: 372 return "eSIR_SME_INVALID_ASSOC_RSP_RXED"; 373 case eSIR_SME_MIC_COUNTER_MEASURES: 374 return "eSIR_SME_MIC_COUNTER_MEASURES"; 375 case eSIR_SME_ADDTS_RSP_TIMEOUT: 376 return "eSIR_SME_ADDTS_RSP_TIMEOUT"; 377 case eSIR_SME_CHANNEL_SWITCH_FAIL: 378 return "eSIR_SME_CHANNEL_SWITCH_FAIL"; 379 case eSIR_SME_HAL_SCAN_INIT_FAILED: 380 return "eSIR_SME_HAL_SCAN_INIT_FAILED"; 381 case eSIR_SME_HAL_SCAN_END_FAILED: 382 return "eSIR_SME_HAL_SCAN_END_FAILED"; 383 case eSIR_SME_HAL_SCAN_FINISH_FAILED: 384 return "eSIR_SME_HAL_SCAN_FINISH_FAILED"; 385 case eSIR_SME_HAL_SEND_MESSAGE_FAIL: 386 return "eSIR_SME_HAL_SEND_MESSAGE_FAIL"; 387 388 default: 389 return "Unknown resultCode"; 390 } 391 } 392 393 void lim_print_msg_name(struct mac_context *mac, uint16_t logLevel, uint32_t msgType) 394 { 395 pe_debug("Msg: %s", lim_msg_str(msgType)); 396 } 397 398 /** 399 * lim_init_mlm() - This function is called by limProcessSmeMessages() to 400 * initialize MLM state machine on STA 401 * @mac: Pointer to Global MAC structure 402 * 403 * @Return: Status of operation 404 */ 405 QDF_STATUS lim_init_mlm(struct mac_context *mac) 406 { 407 uint32_t retVal; 408 409 mac->lim.gLimTimersCreated = 0; 410 411 MTRACE(mac_trace(mac, TRACE_CODE_MLM_STATE, NO_SESSION, 412 mac->lim.gLimMlmState)); 413 414 /* Initialize number of pre-auth contexts */ 415 mac->lim.gLimNumPreAuthContexts = 0; 416 417 /* Initialize MAC based Authentication STA list */ 418 lim_init_pre_auth_list(mac); 419 420 /* Create timers used by LIM */ 421 retVal = lim_create_timers(mac); 422 if (retVal != TX_SUCCESS) { 423 pe_err("lim_create_timers Failed"); 424 return QDF_STATUS_SUCCESS; 425 } 426 427 mac->lim.gLimTimersCreated = 1; 428 return QDF_STATUS_SUCCESS; 429 } /*** end lim_init_mlm() ***/ 430 431 void lim_deactivate_timers(struct mac_context *mac_ctx) 432 { 433 uint32_t n; 434 tLimTimers *lim_timer = &mac_ctx->lim.lim_timers; 435 436 lim_deactivate_timers_host_roam(mac_ctx); 437 438 /* Deactivate addts response timer. */ 439 tx_timer_deactivate(&lim_timer->gLimAddtsRspTimer); 440 441 if (tx_timer_running(&lim_timer->gLimJoinFailureTimer)) { 442 pe_err("Join failure timer running call the timeout API"); 443 /* Cleanup as if join timer expired */ 444 lim_timer_handler(mac_ctx, SIR_LIM_JOIN_FAIL_TIMEOUT); 445 } 446 /* Deactivate Join failure timer. */ 447 tx_timer_deactivate(&lim_timer->gLimJoinFailureTimer); 448 449 /* Deactivate Periodic Join Probe Request timer. */ 450 tx_timer_deactivate(&lim_timer->gLimPeriodicJoinProbeReqTimer); 451 452 /* Deactivate Auth Retry timer. */ 453 tx_timer_deactivate 454 (&lim_timer->g_lim_periodic_auth_retry_timer); 455 456 if (tx_timer_running(&lim_timer->gLimAssocFailureTimer)) { 457 pe_err("Assoc failure timer running call the timeout API"); 458 /* Cleanup as if assoc timer expired */ 459 lim_assoc_failure_timer_handler(mac_ctx, LIM_ASSOC); 460 } 461 /* Deactivate Association failure timer. */ 462 tx_timer_deactivate(&lim_timer->gLimAssocFailureTimer); 463 464 if (tx_timer_running(&mac_ctx->lim.lim_timers.gLimAuthFailureTimer)) { 465 pe_err("Auth failure timer running call the timeout API"); 466 /* Cleanup as if auth timer expired */ 467 lim_timer_handler(mac_ctx, SIR_LIM_AUTH_FAIL_TIMEOUT); 468 } 469 /* Deactivate Authentication failure timer. */ 470 tx_timer_deactivate(&lim_timer->gLimAuthFailureTimer); 471 472 /* Deactivate cnf wait timer */ 473 for (n = 0; n < (mac_ctx->lim.maxStation + 1); n++) { 474 tx_timer_deactivate(&lim_timer->gpLimCnfWaitTimer[n]); 475 } 476 477 /* Deactivate any Authentication response timers */ 478 lim_delete_pre_auth_list(mac_ctx); 479 480 tx_timer_deactivate(&lim_timer->gLimUpdateOlbcCacheTimer); 481 tx_timer_deactivate(&lim_timer->gLimPreAuthClnupTimer); 482 483 if (tx_timer_running(&lim_timer->gLimDisassocAckTimer)) { 484 pe_err("Disassoc timer running call the timeout API"); 485 lim_timer_handler(mac_ctx, SIR_LIM_DISASSOC_ACK_TIMEOUT); 486 } 487 tx_timer_deactivate(&lim_timer->gLimDisassocAckTimer); 488 489 if (tx_timer_running(&lim_timer->gLimDeauthAckTimer)) { 490 pe_err("Deauth timer running call the timeout API"); 491 lim_process_deauth_ack_timeout(mac_ctx, WLAN_INVALID_VDEV_ID); 492 } 493 tx_timer_deactivate(&lim_timer->gLimDeauthAckTimer); 494 495 if (tx_timer_running(&lim_timer->sae_auth_timer)) { 496 pe_err("SAE Auth failure timer running call the timeout API"); 497 /* Cleanup as if SAE auth timer expired */ 498 lim_timer_handler(mac_ctx, SIR_LIM_AUTH_SAE_TIMEOUT); 499 } 500 tx_timer_deactivate(&lim_timer->sae_auth_timer); 501 502 if (tx_timer_running(&lim_timer->rrm_sta_stats_resp_timer)) { 503 pe_err("sta stats resp timer running call the timeout API"); 504 lim_timer_handler(mac_ctx, SIR_LIM_RRM_STA_STATS_RSP_TIMEOUT); 505 } 506 tx_timer_deactivate(&lim_timer->rrm_sta_stats_resp_timer); 507 } 508 509 void lim_deactivate_timers_for_vdev(struct mac_context *mac_ctx, 510 uint8_t vdev_id) 511 { 512 tLimTimers *lim_timer = &mac_ctx->lim.lim_timers; 513 struct pe_session *pe_session; 514 515 pe_session = pe_find_session_by_vdev_id(mac_ctx, vdev_id); 516 if (!pe_session) { 517 pe_err("pe session invalid for vdev %d", vdev_id); 518 return; 519 } 520 pe_debug("pe limMlmState %s vdev %d", 521 lim_mlm_state_str(pe_session->limMlmState), 522 vdev_id); 523 switch (pe_session->limMlmState) { 524 case eLIM_MLM_WT_JOIN_BEACON_STATE: 525 if (tx_timer_running( 526 &lim_timer->gLimJoinFailureTimer)) { 527 pe_debug("Trigger Join failure timeout for vdev %d", 528 vdev_id); 529 tx_timer_deactivate( 530 &lim_timer->gLimJoinFailureTimer); 531 lim_process_join_failure_timeout(mac_ctx); 532 } 533 break; 534 case eLIM_MLM_WT_AUTH_FRAME2_STATE: 535 case eLIM_MLM_WT_AUTH_FRAME4_STATE: 536 if (tx_timer_running( 537 &lim_timer->gLimAuthFailureTimer)) { 538 pe_debug("Trigger Auth failure timeout for vdev %d", 539 vdev_id); 540 tx_timer_deactivate( 541 &lim_timer->gLimAuthFailureTimer); 542 lim_process_auth_failure_timeout(mac_ctx); 543 } 544 break; 545 case eLIM_MLM_WT_ASSOC_RSP_STATE: 546 if (tx_timer_running( 547 &lim_timer->gLimAssocFailureTimer)) { 548 pe_debug("Trigger Assoc failure timeout for vdev %d", 549 vdev_id); 550 tx_timer_deactivate( 551 &lim_timer->gLimAssocFailureTimer); 552 lim_process_assoc_failure_timeout(mac_ctx, 553 LIM_ASSOC); 554 } 555 break; 556 case eLIM_MLM_WT_SAE_AUTH_STATE: 557 if (tx_timer_running(&lim_timer->sae_auth_timer)) { 558 pe_debug("Trigger SAE Auth failure timeout for vdev %d", 559 vdev_id); 560 tx_timer_deactivate( 561 &lim_timer->sae_auth_timer); 562 lim_process_sae_auth_timeout(mac_ctx); 563 } 564 break; 565 case eLIM_MLM_LINK_ESTABLISHED_STATE: 566 if (!pe_session->ftPEContext.ftPreAuthSession) 567 break; 568 569 pe_debug("pre-auth in progress"); 570 if (tx_timer_running(&lim_timer->gLimFTPreAuthRspTimer)) { 571 pe_debug("Trigger pre auth timeout for vdev %d", 572 vdev_id); 573 tx_timer_deactivate( 574 &lim_timer->gLimFTPreAuthRspTimer); 575 } 576 lim_process_ft_preauth_rsp_timeout(mac_ctx); 577 break; 578 default: 579 return; 580 } 581 } 582 583 #if defined(WIFI_POS_CONVERGED) && defined(WLAN_FEATURE_RTT_11AZ_SUPPORT) 584 QDF_STATUS 585 lim_process_pasn_delete_all_peers(struct mac_context *mac, 586 struct pasn_peer_delete_msg *msg) 587 { 588 struct wlan_objmgr_vdev *vdev; 589 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); 590 QDF_STATUS status; 591 592 if (!wma) 593 return QDF_STATUS_E_INVAL; 594 595 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc, msg->vdev_id, 596 WLAN_WIFI_POS_CORE_ID); 597 if (!vdev) 598 return QDF_STATUS_E_INVAL; 599 600 status = wma_delete_all_pasn_peers(wma, vdev); 601 if (QDF_IS_STATUS_ERROR(status)) 602 pe_err("Failed to delete all PASN peers for vdev:%d", 603 msg->vdev_id); 604 605 wlan_objmgr_vdev_release_ref(vdev, WLAN_WIFI_POS_CORE_ID); 606 607 return status; 608 } 609 #endif 610 611 /** 612 * lim_cleanup_mlm() - This function is called to cleanup 613 * @mac_ctx: Pointer to Global MAC structure 614 * 615 * Function is called to cleanup any resources allocated by the MLM 616 * state machine. 617 * 618 * Return: none 619 */ 620 void lim_cleanup_mlm(struct mac_context *mac_ctx) 621 { 622 uint32_t n; 623 624 tLimPreAuthNode **pAuthNode; 625 tLimTimers *lim_timer = NULL; 626 627 if (mac_ctx->lim.gLimTimersCreated == 1) { 628 lim_timer = &mac_ctx->lim.lim_timers; 629 630 lim_deactivate_timers(mac_ctx); 631 632 lim_delete_timers_host_roam(mac_ctx); 633 634 /* Delete addts response timer. */ 635 tx_timer_delete(&lim_timer->gLimAddtsRspTimer); 636 637 /* Delete Join failure timer. */ 638 tx_timer_delete(&lim_timer->gLimJoinFailureTimer); 639 640 /* Delete Periodic Join Probe Request timer. */ 641 tx_timer_delete(&lim_timer->gLimPeriodicJoinProbeReqTimer); 642 643 /* Delete Auth Retry timer. */ 644 tx_timer_delete(&lim_timer->g_lim_periodic_auth_retry_timer); 645 646 /* Delete Association failure timer. */ 647 tx_timer_delete(&lim_timer->gLimAssocFailureTimer); 648 649 /* Delete Authentication failure timer. */ 650 tx_timer_delete(&lim_timer->gLimAuthFailureTimer); 651 652 /* Delete cnf wait timer */ 653 for (n = 0; n < (mac_ctx->lim.maxStation + 1); n++) { 654 tx_timer_delete(&lim_timer->gpLimCnfWaitTimer[n]); 655 } 656 657 pAuthNode = mac_ctx->lim.gLimPreAuthTimerTable.pTable; 658 659 /* Delete any Auth rsp timers, which might have been started */ 660 for (n = 0; n < mac_ctx->lim.gLimPreAuthTimerTable.numEntry; 661 n++) 662 tx_timer_delete(&pAuthNode[n]->timer); 663 664 tx_timer_delete(&lim_timer->gLimUpdateOlbcCacheTimer); 665 tx_timer_delete(&lim_timer->gLimPreAuthClnupTimer); 666 667 tx_timer_delete(&lim_timer->gLimDisassocAckTimer); 668 669 tx_timer_delete(&lim_timer->gLimDeauthAckTimer); 670 671 tx_timer_delete(&lim_timer->sae_auth_timer); 672 tx_timer_delete(&lim_timer->rrm_sta_stats_resp_timer); 673 674 mac_ctx->lim.gLimTimersCreated = 0; 675 } 676 } /*** end lim_cleanup_mlm() ***/ 677 678 /* 679 * lim_reset_deferred_msg_q() 680 * 681 ***FUNCTION: 682 * This function resets the deferred message queue parameters. 683 * 684 ***PARAMS: 685 * @param mac - Pointer to Global MAC structure 686 * 687 ***LOGIC: 688 * 689 ***ASSUMPTIONS: 690 * NA 691 * 692 ***NOTE: 693 * NA 694 * 695 ***RETURNS: 696 * None 697 */ 698 699 void lim_reset_deferred_msg_q(struct mac_context *mac) 700 { 701 struct scheduler_msg *read_msg = {0}; 702 703 if (mac->lim.gLimDeferredMsgQ.size > 0) { 704 while ((read_msg = lim_read_deferred_msg_q(mac)) != NULL) { 705 pe_free_msg(mac, read_msg); 706 } 707 } 708 709 mac->lim.gLimDeferredMsgQ.size = 710 mac->lim.gLimDeferredMsgQ.write = 711 mac->lim.gLimDeferredMsgQ.read = 0; 712 713 } 714 715 #define LIM_DEFERRED_Q_CHECK_THRESHOLD (MAX_DEFERRED_QUEUE_LEN/2) 716 #define LIM_MAX_NUM_MGMT_FRAME_DEFERRED (MAX_DEFERRED_QUEUE_LEN/2) 717 718 /** 719 * lim_write_deferred_msg_q() - This function queues up a deferred message 720 * 721 * @mac_ctx: Pointer to Global MAC structure 722 * @lim_msg: a LIM message 723 * 724 * Function queues up a deferred message for later processing on the 725 * STA side. 726 * 727 * Return: none 728 */ 729 730 uint8_t lim_write_deferred_msg_q(struct mac_context *mac_ctx, 731 struct scheduler_msg *lim_msg) 732 { 733 uint8_t type = 0, subtype = 0; 734 735 pe_debug("Queue a deferred message size: %d write: %d - type: 0x%x", 736 mac_ctx->lim.gLimDeferredMsgQ.size, 737 mac_ctx->lim.gLimDeferredMsgQ.write, 738 lim_msg->type); 739 740 /* check if the deferred message queue is full */ 741 if (mac_ctx->lim.gLimDeferredMsgQ.size >= MAX_DEFERRED_QUEUE_LEN) { 742 if (!(mac_ctx->lim.deferredMsgCnt & 0xF)) { 743 pe_err("queue->MsgQ full Msg: %d Msgs Failed: %d", 744 lim_msg->type, 745 ++mac_ctx->lim.deferredMsgCnt); 746 cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL, 747 WLAN_LOG_INDICATOR_HOST_DRIVER, 748 WLAN_LOG_REASON_QUEUE_FULL, 749 false, false); 750 } else { 751 mac_ctx->lim.deferredMsgCnt++; 752 } 753 return TX_QUEUE_FULL; 754 } 755 756 /* 757 * In the application, there should not be more than 1 message get 758 * queued up. If happens, flags a warning. In the future, this can 759 * happen. 760 */ 761 if (mac_ctx->lim.gLimDeferredMsgQ.size > 0) 762 pe_debug("%d Deferred Msg type: 0x%x global sme: %d global mlme: %d addts: %d", 763 mac_ctx->lim.gLimDeferredMsgQ.size, 764 lim_msg->type, 765 mac_ctx->lim.gLimSmeState, 766 mac_ctx->lim.gLimMlmState, 767 mac_ctx->lim.gLimAddtsSent); 768 769 if (SIR_BB_XPORT_MGMT_MSG == lim_msg->type) { 770 lim_util_get_type_subtype(lim_msg->bodyptr, 771 &type, &subtype); 772 pe_debug(" Deferred management type %d subtype %d ", 773 type, subtype); 774 } 775 776 /* 777 * To prevent the deferred Q is full of management frames, only give 778 * them certain space 779 */ 780 if ((SIR_BB_XPORT_MGMT_MSG == lim_msg->type) && 781 (LIM_DEFERRED_Q_CHECK_THRESHOLD < 782 mac_ctx->lim.gLimDeferredMsgQ.size)) { 783 uint16_t idx, count = 0; 784 785 for (idx = 0; idx < mac_ctx->lim.gLimDeferredMsgQ.size; 786 idx++) { 787 if (SIR_BB_XPORT_MGMT_MSG == 788 mac_ctx->lim.gLimDeferredMsgQ. 789 deferredQueue[idx].type) { 790 count++; 791 } 792 } 793 if (LIM_MAX_NUM_MGMT_FRAME_DEFERRED < count) { 794 /* 795 * We reach the quota for management frames, 796 * drop this one 797 */ 798 pe_warn_rl("Too many queue->MsgQ Msg: %d count: %d", 799 lim_msg->type, count); 800 /* Return error, caller knows what to do */ 801 return TX_QUEUE_FULL; 802 } 803 } 804 805 ++mac_ctx->lim.gLimDeferredMsgQ.size; 806 807 /* reset the count here since we are able to defer the message */ 808 if (mac_ctx->lim.deferredMsgCnt != 0) 809 mac_ctx->lim.deferredMsgCnt = 0; 810 811 /* if the write pointer hits the end of the queue, rewind it */ 812 if (mac_ctx->lim.gLimDeferredMsgQ.write >= MAX_DEFERRED_QUEUE_LEN) 813 mac_ctx->lim.gLimDeferredMsgQ.write = 0; 814 815 /* save the message to the queue and advanced the write pointer */ 816 qdf_mem_copy((uint8_t *) &mac_ctx->lim.gLimDeferredMsgQ. 817 deferredQueue[mac_ctx->lim.gLimDeferredMsgQ.write++], 818 (uint8_t *) lim_msg, 819 sizeof(struct scheduler_msg)); 820 return TX_SUCCESS; 821 822 } 823 824 /* 825 * lim_read_deferred_msg_q() 826 * 827 ***FUNCTION: 828 * This function dequeues a deferred message for processing on the 829 * STA side. 830 * 831 ***PARAMS: 832 * @param mac - Pointer to Global MAC structure 833 * 834 ***LOGIC: 835 * 836 ***ASSUMPTIONS: 837 * NA 838 * 839 ***NOTE: 840 * 841 * 842 ***RETURNS: 843 * Returns the message at the head of the deferred message queue 844 */ 845 846 struct scheduler_msg *lim_read_deferred_msg_q(struct mac_context *mac) 847 { 848 struct scheduler_msg *msg = {0}; 849 850 /* 851 ** check any messages left. If no, return 852 **/ 853 if (mac->lim.gLimDeferredMsgQ.size <= 0) 854 return NULL; 855 856 /* 857 ** decrement the queue size 858 **/ 859 mac->lim.gLimDeferredMsgQ.size--; 860 861 /* 862 ** retrieve the message from the head of the queue 863 **/ 864 msg = 865 &mac->lim.gLimDeferredMsgQ.deferredQueue[mac->lim. 866 gLimDeferredMsgQ.read]; 867 868 /* 869 ** advance the read pointer 870 **/ 871 mac->lim.gLimDeferredMsgQ.read++; 872 873 /* 874 ** if the read pointer hits the end of the queue, rewind it 875 **/ 876 if (mac->lim.gLimDeferredMsgQ.read >= MAX_DEFERRED_QUEUE_LEN) 877 mac->lim.gLimDeferredMsgQ.read = 0; 878 879 pe_debug("DeQueue a deferred message size: %d read: %d - type: 0x%x", 880 mac->lim.gLimDeferredMsgQ.size, 881 mac->lim.gLimDeferredMsgQ.read, msg->type); 882 883 pe_debug("DQ msg -- global sme: %d global mlme: %d addts: %d", 884 mac->lim.gLimSmeState, mac->lim.gLimMlmState, 885 mac->lim.gLimAddtsSent); 886 887 return msg; 888 } 889 890 /* 891 * lim_handle_update_olbc_cache() - This function update olbc cache 892 * 893 * @mac_ctx: Pointer to Global MAC structure 894 * 895 * Function updates olbc cache 896 * 897 * Return: none 898 */ 899 void lim_handle_update_olbc_cache(struct mac_context *mac_ctx) 900 { 901 int i; 902 static int enable; 903 tUpdateBeaconParams beaconParams; 904 905 struct pe_session *pe_session = lim_is_ap_session_active(mac_ctx); 906 907 if (!pe_session) { 908 pe_debug(" Session not found"); 909 return; 910 } 911 912 if (pe_session->is_session_obss_offload_enabled) { 913 pe_debug("protection offloaded"); 914 return; 915 } 916 qdf_mem_zero((uint8_t *) &beaconParams, sizeof(tUpdateBeaconParams)); 917 beaconParams.bss_idx = pe_session->vdev_id; 918 919 beaconParams.paramChangeBitmap = 0; 920 /* 921 * This is doing a 2 pass check. The first pass is to invalidate 922 * all the cache entries. The second pass is to decide whether to 923 * disable protection. 924 */ 925 if (!enable) { 926 pe_debug("Resetting OLBC cache"); 927 pe_session->gLimOlbcParams.numSta = 0; 928 pe_session->gLimOverlap11gParams.numSta = 0; 929 pe_session->gLimOverlapHt20Params.numSta = 0; 930 pe_session->gLimNonGfParams.numSta = 0; 931 pe_session->gLimLsigTxopParams.numSta = 0; 932 933 for (i = 0; i < LIM_PROT_STA_OVERLAP_CACHE_SIZE; i++) 934 mac_ctx->lim.protStaOverlapCache[i].active = false; 935 936 enable = 1; 937 } else { 938 if ((!pe_session->gLimOlbcParams.numSta) && 939 (pe_session->gLimOlbcParams.protectionEnabled) && 940 (!pe_session->gLim11bParams.protectionEnabled)) { 941 pe_debug("Overlap cache clear and no 11B STA set"); 942 lim_enable11g_protection(mac_ctx, false, true, 943 &beaconParams, 944 pe_session); 945 } 946 947 if ((!pe_session->gLimOverlap11gParams.numSta) && 948 (pe_session->gLimOverlap11gParams.protectionEnabled) 949 && (!pe_session->gLim11gParams.protectionEnabled)) { 950 pe_debug("Overlap cache clear and no 11G STA set"); 951 lim_enable_ht_protection_from11g(mac_ctx, false, true, 952 &beaconParams, 953 pe_session); 954 } 955 956 if ((!pe_session->gLimOverlapHt20Params.numSta) && 957 (pe_session->gLimOverlapHt20Params.protectionEnabled) 958 && (!pe_session->gLimHt20Params.protectionEnabled)) { 959 pe_debug("Overlap cache clear and no HT20 STA set"); 960 lim_enable11g_protection(mac_ctx, false, true, 961 &beaconParams, 962 pe_session); 963 } 964 965 enable = 0; 966 } 967 968 if ((false == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running) 969 && beaconParams.paramChangeBitmap) { 970 sch_set_fixed_beacon_fields(mac_ctx, pe_session); 971 lim_send_beacon_params(mac_ctx, &beaconParams, pe_session); 972 } 973 /* Start OLBC timer */ 974 if (tx_timer_activate(&mac_ctx->lim.lim_timers.gLimUpdateOlbcCacheTimer) 975 != TX_SUCCESS) 976 pe_err("tx_timer_activate failed"); 977 } 978 979 /** 980 * lim_is_null_ssid() - This function checks if ssid supplied is Null SSID 981 * @ssid: pointer to tSirMacSSid 982 * 983 * Function checks if ssid supplied is Null SSID 984 * 985 * Return: none 986 */ 987 988 uint8_t lim_is_null_ssid(tSirMacSSid *ssid) 989 { 990 uint8_t fnull_ssid = false; 991 uint32_t ssid_len; 992 uint8_t *ssid_str; 993 994 if (0 == ssid->length) { 995 fnull_ssid = true; 996 return fnull_ssid; 997 } 998 /* If the first characters is space, then check if all 999 * characters in SSID are spaces to consider it as NULL SSID 1000 */ 1001 if ((ASCII_SPACE_CHARACTER == ssid->ssId[0]) && 1002 (ssid->length == 1)) { 1003 fnull_ssid = true; 1004 return fnull_ssid; 1005 } else { 1006 /* check if all the characters in SSID are NULL */ 1007 ssid_len = ssid->length; 1008 ssid_str = ssid->ssId; 1009 1010 while (ssid_len) { 1011 if (*ssid_str) 1012 return fnull_ssid; 1013 1014 ssid_str++; 1015 ssid_len--; 1016 } 1017 1018 if (0 == ssid_len) { 1019 fnull_ssid = true; 1020 return fnull_ssid; 1021 } 1022 } 1023 1024 return fnull_ssid; 1025 } 1026 1027 /** ------------------------------------------------------------- 1028 \fn lim_update_prot_sta_params 1029 \brief updates protection related counters. 1030 \param struct mac_context * mac 1031 \param tSirMacAddr peerMacAddr 1032 \param tLimProtStaCacheType protStaCacheType 1033 \param tHalBitVal gfSupported 1034 \param tHalBitVal lsigTxopSupported 1035 \return None 1036 -------------------------------------------------------------*/ 1037 static void 1038 lim_update_prot_sta_params(struct mac_context *mac, 1039 tSirMacAddr peerMacAddr, 1040 tLimProtStaCacheType protStaCacheType, 1041 tHalBitVal gfSupported, tHalBitVal lsigTxopSupported, 1042 struct pe_session *pe_session) 1043 { 1044 uint32_t i; 1045 1046 pe_debug("Associated STA addr is: "QDF_MAC_ADDR_FMT, 1047 QDF_MAC_ADDR_REF(peerMacAddr)); 1048 1049 for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { 1050 if (pe_session->protStaCache[i].active) { 1051 pe_debug("Addr:" QDF_MAC_ADDR_FMT, 1052 QDF_MAC_ADDR_REF(pe_session->protStaCache[i].addr)); 1053 1054 if (!qdf_mem_cmp 1055 (pe_session->protStaCache[i].addr, 1056 peerMacAddr, sizeof(tSirMacAddr))) { 1057 pe_debug("matching cache entry at: %d already active", 1058 i); 1059 return; 1060 } 1061 } 1062 } 1063 1064 for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { 1065 if (!pe_session->protStaCache[i].active) 1066 break; 1067 } 1068 1069 if (i >= LIM_PROT_STA_CACHE_SIZE) { 1070 pe_err("No space in ProtStaCache"); 1071 return; 1072 } 1073 1074 qdf_mem_copy(pe_session->protStaCache[i].addr, 1075 peerMacAddr, sizeof(tSirMacAddr)); 1076 1077 pe_session->protStaCache[i].protStaCacheType = protStaCacheType; 1078 pe_session->protStaCache[i].active = true; 1079 if (eLIM_PROT_STA_CACHE_TYPE_llB == protStaCacheType) { 1080 pe_session->gLim11bParams.numSta++; 1081 pe_debug("11B,"); 1082 } else if (eLIM_PROT_STA_CACHE_TYPE_llG == protStaCacheType) { 1083 pe_session->gLim11gParams.numSta++; 1084 pe_debug("11G,"); 1085 } else if (eLIM_PROT_STA_CACHE_TYPE_HT20 == protStaCacheType) { 1086 pe_session->gLimHt20Params.numSta++; 1087 pe_debug("HT20,"); 1088 } 1089 1090 if (!gfSupported) { 1091 pe_session->gLimNonGfParams.numSta++; 1092 pe_debug("NonGf,"); 1093 } 1094 if (!lsigTxopSupported) { 1095 pe_session->gLimLsigTxopParams.numSta++; 1096 pe_debug("!lsigTxopSupported"); 1097 } 1098 } /* --------------------------------------------------------------------- */ 1099 1100 /** ------------------------------------------------------------- 1101 \fn lim_decide_ap_protection 1102 \brief Decides all the protection related staiton coexistence and also sets 1103 \ short preamble and short slot appropriately. This function will be called 1104 \ when AP is ready to send assocRsp tp the station joining right now. 1105 \param struct mac_context * mac 1106 \param tSirMacAddr peerMacAddr 1107 \return None 1108 -------------------------------------------------------------*/ 1109 void 1110 lim_decide_ap_protection(struct mac_context *mac, tSirMacAddr peerMacAddr, 1111 tpUpdateBeaconParams pBeaconParams, 1112 struct pe_session *pe_session) 1113 { 1114 uint16_t tmpAid; 1115 tpDphHashNode sta; 1116 enum reg_wifi_band rfBand = REG_BAND_UNKNOWN; 1117 uint32_t phyMode; 1118 tLimProtStaCacheType protStaCacheType = 1119 eLIM_PROT_STA_CACHE_TYPE_INVALID; 1120 tHalBitVal gfSupported = eHAL_SET, lsigTxopSupported = eHAL_SET; 1121 1122 pBeaconParams->paramChangeBitmap = 0; 1123 /* check whether to enable protection or not */ 1124 sta = 1125 dph_lookup_hash_entry(mac, peerMacAddr, &tmpAid, 1126 &pe_session->dph.dphHashTable); 1127 if (!sta) 1128 return; 1129 lim_get_rf_band_new(mac, &rfBand, pe_session); 1130 /* if we are in 5 GHZ band */ 1131 if (REG_BAND_5G == rfBand) { 1132 /* We are 11N. we need to protect from 11A and Ht20. we don't need any other protection in 5 GHZ. */ 1133 /* HT20 case is common between both the bands and handled down as common code. */ 1134 if (true == pe_session->htCapability) { 1135 /* we are 11N and 11A station is joining. */ 1136 /* protection from 11A required. */ 1137 if (false == sta->mlmStaContext.htCapability) { 1138 lim_update_11a_protection(mac, true, false, 1139 pBeaconParams, 1140 pe_session); 1141 return; 1142 } 1143 } 1144 } else if (REG_BAND_2G == rfBand) { 1145 lim_get_phy_mode(mac, &phyMode, pe_session); 1146 1147 /* We are 11G. Check if we need protection from 11b Stations. */ 1148 if ((phyMode == WNI_CFG_PHY_MODE_11G) && 1149 (false == pe_session->htCapability)) { 1150 1151 if (sta->erpEnabled == eHAL_CLEAR) { 1152 protStaCacheType = eLIM_PROT_STA_CACHE_TYPE_llB; 1153 /* enable protection */ 1154 pe_debug("Enabling protection from 11B"); 1155 lim_enable11g_protection(mac, true, false, 1156 pBeaconParams, 1157 pe_session); 1158 } 1159 } 1160 /* HT station. */ 1161 if (true == pe_session->htCapability) { 1162 /* check if we need protection from 11b station */ 1163 if ((sta->erpEnabled == eHAL_CLEAR) && 1164 (!sta->mlmStaContext.htCapability)) { 1165 protStaCacheType = eLIM_PROT_STA_CACHE_TYPE_llB; 1166 /* enable protection */ 1167 pe_debug("Enabling protection from 11B"); 1168 lim_enable11g_protection(mac, true, false, 1169 pBeaconParams, 1170 pe_session); 1171 } 1172 /* station being joined is non-11b and non-ht ==> 11g device */ 1173 else if (!sta->mlmStaContext.htCapability) { 1174 protStaCacheType = eLIM_PROT_STA_CACHE_TYPE_llG; 1175 /* enable protection */ 1176 lim_enable_ht_protection_from11g(mac, true, false, 1177 pBeaconParams, 1178 pe_session); 1179 } 1180 /* ERP mode is enabled for the latest station joined */ 1181 /* latest station joined is HT capable */ 1182 /* This case is being handled in common code (commn between both the bands) below. */ 1183 } 1184 } 1185 /* we are HT and HT station is joining. This code is common for both the bands. */ 1186 if ((true == pe_session->htCapability) && 1187 (true == sta->mlmStaContext.htCapability)) { 1188 if (!sta->htGreenfield) { 1189 lim_enable_ht_non_gf_protection(mac, true, false, 1190 pBeaconParams, 1191 pe_session); 1192 gfSupported = eHAL_CLEAR; 1193 } 1194 /* Station joining is HT 20Mhz */ 1195 if ((eHT_CHANNEL_WIDTH_20MHZ == 1196 sta->htSupportedChannelWidthSet) && 1197 (eHT_CHANNEL_WIDTH_20MHZ != 1198 pe_session->htSupportedChannelWidthSet)){ 1199 protStaCacheType = eLIM_PROT_STA_CACHE_TYPE_HT20; 1200 lim_enable_ht20_protection(mac, true, false, 1201 pBeaconParams, pe_session); 1202 } 1203 /* Station joining does not support LSIG TXOP Protection */ 1204 if (!sta->htLsigTXOPProtection) { 1205 lim_enable_ht_lsig_txop_protection(mac, false, false, 1206 pBeaconParams, 1207 pe_session); 1208 lsigTxopSupported = eHAL_CLEAR; 1209 } 1210 } 1211 1212 lim_update_prot_sta_params(mac, peerMacAddr, protStaCacheType, 1213 gfSupported, lsigTxopSupported, pe_session); 1214 1215 return; 1216 } 1217 1218 /** ------------------------------------------------------------- 1219 \fn lim_enable_overlap11g_protection 1220 \brief wrapper function for setting overlap 11g protection. 1221 \param struct mac_context * mac 1222 \param tpUpdateBeaconParams pBeaconParams 1223 \param tpSirMacMgmtHdr pMh 1224 \return None 1225 -------------------------------------------------------------*/ 1226 void 1227 lim_enable_overlap11g_protection(struct mac_context *mac, 1228 tpUpdateBeaconParams pBeaconParams, 1229 tpSirMacMgmtHdr pMh, struct pe_session *pe_session) 1230 { 1231 lim_update_overlap_sta_param(mac, pMh->bssId, 1232 &(pe_session->gLimOlbcParams)); 1233 1234 if (pe_session->gLimOlbcParams.numSta && 1235 !pe_session->gLimOlbcParams.protectionEnabled) { 1236 /* enable protection */ 1237 pe_debug("OLBC happens!!!"); 1238 lim_enable11g_protection(mac, true, true, pBeaconParams, 1239 pe_session); 1240 } 1241 } 1242 1243 /** 1244 * lim_update_short_preamble() - This function Updates short preamble 1245 * @mac_ctx: pointer to Global MAC structure 1246 * @peer_mac_addr: pointer to tSirMacAddr 1247 * @pbeaconparams: pointer to tpUpdateBeaconParams 1248 * @psession_entry: pointer to struct pe_session * 1249 * 1250 * Function Updates short preamble if needed when a new station joins 1251 * 1252 * Return: none 1253 */ 1254 void 1255 lim_update_short_preamble(struct mac_context *mac_ctx, tSirMacAddr peer_mac_addr, 1256 tpUpdateBeaconParams beaconparams, 1257 struct pe_session *psession_entry) 1258 { 1259 uint16_t aid; 1260 tpDphHashNode sta_ds; 1261 uint32_t phy_mode; 1262 uint16_t i; 1263 1264 /* check whether to enable protection or not */ 1265 sta_ds = 1266 dph_lookup_hash_entry(mac_ctx, peer_mac_addr, &aid, 1267 &psession_entry->dph.dphHashTable); 1268 1269 lim_get_phy_mode(mac_ctx, &phy_mode, psession_entry); 1270 1271 if (!sta_ds || phy_mode != WNI_CFG_PHY_MODE_11G) 1272 return; 1273 1274 if (sta_ds->shortPreambleEnabled != eHAL_CLEAR) 1275 return; 1276 1277 pe_debug("Short Preamble is not enabled in Assoc Req from "QDF_MAC_ADDR_FMT, 1278 QDF_MAC_ADDR_REF(peer_mac_addr)); 1279 1280 for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { 1281 if (LIM_IS_AP_ROLE(psession_entry) && 1282 (psession_entry->gLimNoShortParams. 1283 staNoShortCache[i].active) && 1284 (!qdf_mem_cmp 1285 (psession_entry->gLimNoShortParams. 1286 staNoShortCache[i].addr, 1287 peer_mac_addr, sizeof(tSirMacAddr)))) 1288 return; 1289 else if (!LIM_IS_AP_ROLE(psession_entry) && 1290 (mac_ctx->lim.gLimNoShortParams. 1291 staNoShortCache[i].active) && 1292 (!qdf_mem_cmp(mac_ctx->lim.gLimNoShortParams. 1293 staNoShortCache[i].addr, 1294 peer_mac_addr, 1295 sizeof(tSirMacAddr)))) 1296 return; 1297 } 1298 1299 for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { 1300 if (LIM_IS_AP_ROLE(psession_entry) && 1301 !psession_entry->gLimNoShortParams. 1302 staNoShortCache[i].active) 1303 break; 1304 else if (!mac_ctx->lim.gLimNoShortParams. 1305 staNoShortCache[i].active) 1306 break; 1307 } 1308 1309 if (i >= LIM_PROT_STA_CACHE_SIZE) { 1310 tLimNoShortParams *lim_params = 1311 &psession_entry->gLimNoShortParams; 1312 if (LIM_IS_AP_ROLE(psession_entry)) { 1313 pe_err("No space in Short cache active: %d sta: %d for sta "QDF_MAC_ADDR_FMT, 1314 i, lim_params->numNonShortPreambleSta, 1315 QDF_MAC_ADDR_REF(peer_mac_addr)); 1316 return; 1317 } else { 1318 pe_err("No space in Short cache active: %d sta: %d for sta "QDF_MAC_ADDR_FMT, 1319 i, lim_params->numNonShortPreambleSta, 1320 QDF_MAC_ADDR_REF(peer_mac_addr)); 1321 return; 1322 } 1323 1324 } 1325 1326 if (LIM_IS_AP_ROLE(psession_entry)) { 1327 qdf_mem_copy(psession_entry->gLimNoShortParams. 1328 staNoShortCache[i].addr, 1329 peer_mac_addr, sizeof(tSirMacAddr)); 1330 psession_entry->gLimNoShortParams.staNoShortCache[i]. 1331 active = true; 1332 psession_entry->gLimNoShortParams.numNonShortPreambleSta++; 1333 } else { 1334 qdf_mem_copy(mac_ctx->lim.gLimNoShortParams. 1335 staNoShortCache[i].addr, 1336 peer_mac_addr, sizeof(tSirMacAddr)); 1337 mac_ctx->lim.gLimNoShortParams.staNoShortCache[i].active = true; 1338 mac_ctx->lim.gLimNoShortParams.numNonShortPreambleSta++; 1339 } 1340 1341 /* enable long preamble */ 1342 pe_debug("Disabling short preamble"); 1343 1344 if (lim_enable_short_preamble(mac_ctx, false, beaconparams, 1345 psession_entry) != QDF_STATUS_SUCCESS) 1346 pe_err("Cannot enable long preamble"); 1347 } 1348 1349 /** 1350 * lim_update_short_slot_time() - This function Updates short slot time 1351 * @mac_ctx: pointer to Global MAC structure 1352 * @peer_mac_addr: pointer to tSirMacAddr 1353 * @beacon_params: pointer to tpUpdateBeaconParams 1354 * @psession_entry: pointer to struct pe_session * 1355 * 1356 * Function Updates short slot time if needed when a new station joins 1357 * 1358 * Return: None 1359 */ 1360 void 1361 lim_update_short_slot_time(struct mac_context *mac_ctx, tSirMacAddr peer_mac_addr, 1362 tpUpdateBeaconParams beacon_params, 1363 struct pe_session *session_entry) 1364 { 1365 uint16_t aid; 1366 tpDphHashNode sta_ds; 1367 uint32_t phy_mode; 1368 uint32_t val; 1369 uint16_t i; 1370 1371 /* check whether to enable protection or not */ 1372 sta_ds = dph_lookup_hash_entry(mac_ctx, peer_mac_addr, &aid, 1373 &session_entry->dph.dphHashTable); 1374 lim_get_phy_mode(mac_ctx, &phy_mode, session_entry); 1375 1376 if (!sta_ds || phy_mode != WNI_CFG_PHY_MODE_11G) 1377 return; 1378 1379 /* 1380 * Only in case of softap in 11g mode, slot time might change 1381 * depending on the STA being added. In 11a case, it should 1382 * be always 1 and in 11b case, it should be always 0. 1383 * Only when the new STA has short slot time disabled, we need to 1384 * change softap's overall slot time settings else the default for 1385 * softap is always short slot enabled. When the last long slot STA 1386 * leaves softAP, we take care of it in lim_decide_short_slot 1387 */ 1388 if (sta_ds->shortSlotTimeEnabled != eHAL_CLEAR) 1389 return; 1390 1391 pe_debug("Short Slot Time is not enabled in Assoc Req from "QDF_MAC_ADDR_FMT, 1392 QDF_MAC_ADDR_REF(peer_mac_addr)); 1393 for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { 1394 if (LIM_IS_AP_ROLE(session_entry) && 1395 session_entry->gLimNoShortSlotParams. 1396 staNoShortSlotCache[i].active) { 1397 if (!qdf_mem_cmp(session_entry-> 1398 gLimNoShortSlotParams.staNoShortSlotCache[i].addr, 1399 peer_mac_addr, sizeof(tSirMacAddr))) 1400 return; 1401 } else if (!LIM_IS_AP_ROLE(session_entry)) { 1402 if (mac_ctx->lim.gLimNoShortSlotParams. 1403 staNoShortSlotCache[i].active) { 1404 if (!qdf_mem_cmp(mac_ctx-> 1405 lim.gLimNoShortSlotParams. 1406 staNoShortSlotCache[i].addr, 1407 peer_mac_addr, sizeof(tSirMacAddr))) 1408 return; 1409 } 1410 } 1411 } 1412 for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) { 1413 if (LIM_IS_AP_ROLE(session_entry) && 1414 !session_entry->gLimNoShortSlotParams. 1415 staNoShortSlotCache[i].active) 1416 break; 1417 else 1418 if (!mac_ctx->lim.gLimNoShortSlotParams. 1419 staNoShortSlotCache[i].active) 1420 break; 1421 } 1422 1423 if (i >= LIM_PROT_STA_CACHE_SIZE) { 1424 if (LIM_IS_AP_ROLE(session_entry)) { 1425 pe_err("No space in ShortSlot cache active: %d sta: %d for sta "QDF_MAC_ADDR_FMT, 1426 i, session_entry->gLimNoShortSlotParams.numNonShortSlotSta, 1427 QDF_MAC_ADDR_REF(peer_mac_addr)); 1428 return; 1429 } else { 1430 pe_err("No space in ShortSlot cache active: %d sta: %d for sta "QDF_MAC_ADDR_FMT, 1431 i, mac_ctx->lim.gLimNoShortSlotParams.numNonShortSlotSta, 1432 QDF_MAC_ADDR_REF(peer_mac_addr)); 1433 return; 1434 } 1435 } 1436 1437 if (LIM_IS_AP_ROLE(session_entry)) { 1438 qdf_mem_copy(session_entry->gLimNoShortSlotParams. 1439 staNoShortSlotCache[i].addr, 1440 peer_mac_addr, sizeof(tSirMacAddr)); 1441 session_entry->gLimNoShortSlotParams. 1442 staNoShortSlotCache[i].active = true; 1443 session_entry->gLimNoShortSlotParams.numNonShortSlotSta++; 1444 } else { 1445 qdf_mem_copy(mac_ctx->lim.gLimNoShortSlotParams. 1446 staNoShortSlotCache[i].addr, 1447 peer_mac_addr, sizeof(tSirMacAddr)); 1448 mac_ctx->lim.gLimNoShortSlotParams. 1449 staNoShortSlotCache[i].active = true; 1450 mac_ctx->lim.gLimNoShortSlotParams. 1451 numNonShortSlotSta++; 1452 } 1453 val = mac_ctx->mlme_cfg->feature_flags.enable_short_slot_time_11g; 1454 /* 1455 * Here we check if we are AP role and short slot enabled 1456 * (both admin and oper modes) but we have atleast one STA 1457 * connected with only long slot enabled, we need to change 1458 * our beacon/pb rsp to broadcast short slot disabled 1459 */ 1460 if ((LIM_IS_AP_ROLE(session_entry)) && (val && 1461 session_entry->gLimNoShortSlotParams.numNonShortSlotSta 1462 && session_entry->shortSlotTimeSupported)) { 1463 /* enable long slot time */ 1464 beacon_params->fShortSlotTime = false; 1465 beacon_params->paramChangeBitmap |= 1466 PARAM_SHORT_SLOT_TIME_CHANGED; 1467 pe_debug("Disable short slot time. Enable long slot time"); 1468 session_entry->shortSlotTimeSupported = false; 1469 } else if (!LIM_IS_AP_ROLE(session_entry) && 1470 (val && mac_ctx->lim.gLimNoShortSlotParams. 1471 numNonShortSlotSta && 1472 session_entry->shortSlotTimeSupported)) { 1473 /* enable long slot time */ 1474 beacon_params->fShortSlotTime = false; 1475 beacon_params->paramChangeBitmap |= 1476 PARAM_SHORT_SLOT_TIME_CHANGED; 1477 pe_debug("Disable short slot time. Enable long slot time"); 1478 session_entry->shortSlotTimeSupported = false; 1479 } 1480 } 1481 1482 /** ------------------------------------------------------------- 1483 \fn lim_decide_sta_protection_on_assoc 1484 \brief Decide protection related settings on Sta while association. 1485 \param struct mac_context * mac 1486 \param tpSchBeaconStruct pBeaconStruct 1487 \return None 1488 -------------------------------------------------------------*/ 1489 void 1490 lim_decide_sta_protection_on_assoc(struct mac_context *mac, 1491 tpSchBeaconStruct pBeaconStruct, 1492 struct pe_session *pe_session) 1493 { 1494 enum reg_wifi_band rfBand = REG_BAND_UNKNOWN; 1495 uint32_t phyMode = WNI_CFG_PHY_MODE_NONE; 1496 1497 lim_get_rf_band_new(mac, &rfBand, pe_session); 1498 lim_get_phy_mode(mac, &phyMode, pe_session); 1499 1500 if (REG_BAND_5G == rfBand) { 1501 if ((eSIR_HT_OP_MODE_MIXED == pBeaconStruct->HTInfo.opMode) || 1502 (eSIR_HT_OP_MODE_OVERLAP_LEGACY == 1503 pBeaconStruct->HTInfo.opMode)) { 1504 if (mac->lim.cfgProtection.fromlla) 1505 pe_session->beaconParams.llaCoexist = true; 1506 } else if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT == 1507 pBeaconStruct->HTInfo.opMode) { 1508 if (mac->lim.cfgProtection.ht20) 1509 pe_session->beaconParams.ht20Coexist = true; 1510 } 1511 1512 } else if (REG_BAND_2G == rfBand) { 1513 /* spec 7.3.2.13 */ 1514 /* UseProtection will be set when nonERP STA is associated. */ 1515 /* NonERPPresent bit will be set when: */ 1516 /* --nonERP Sta is associated OR */ 1517 /* --nonERP Sta exists in overlapping BSS */ 1518 /* when useProtection is not set then protection from nonERP stations is optional. */ 1519 1520 /* CFG protection from 11b is enabled and */ 1521 /* 11B device in the BSS */ 1522 /* TODO, This is not sessionized */ 1523 if (phyMode != WNI_CFG_PHY_MODE_11B) { 1524 if (mac->lim.cfgProtection.fromllb && 1525 pBeaconStruct->erpPresent && 1526 (pBeaconStruct->erpIEInfo.useProtection || 1527 pBeaconStruct->erpIEInfo.nonErpPresent)) { 1528 pe_session->beaconParams.llbCoexist = true; 1529 } 1530 /* AP has no 11b station associated. */ 1531 else { 1532 pe_session->beaconParams.llbCoexist = false; 1533 } 1534 } 1535 /* following code block is only for HT station. */ 1536 if ((pe_session->htCapability) && 1537 (pBeaconStruct->HTInfo.present)) { 1538 tDot11fIEHTInfo htInfo = pBeaconStruct->HTInfo; 1539 1540 /* Obss Non HT STA present mode */ 1541 pe_session->beaconParams.gHTObssMode = 1542 (uint8_t) htInfo.obssNonHTStaPresent; 1543 1544 /* CFG protection from 11G is enabled and */ 1545 /* our AP has at least one 11G station associated. */ 1546 if (mac->lim.cfgProtection.fromllg && 1547 ((eSIR_HT_OP_MODE_MIXED == htInfo.opMode) || 1548 (eSIR_HT_OP_MODE_OVERLAP_LEGACY == htInfo.opMode)) 1549 && (!pe_session->beaconParams.llbCoexist)) { 1550 if (mac->lim.cfgProtection.fromllg) 1551 pe_session->beaconParams.llgCoexist = 1552 true; 1553 } 1554 /* AP has only HT stations associated and at least one station is HT 20 */ 1555 /* disable protection from any non-HT devices. */ 1556 /* decision for disabling protection from 11b has already been taken above. */ 1557 if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT == htInfo.opMode) { 1558 /* Disable protection from 11G station. */ 1559 pe_session->beaconParams.llgCoexist = false; 1560 /* CFG protection from HT 20 is enabled. */ 1561 if (mac->lim.cfgProtection.ht20) 1562 pe_session->beaconParams. 1563 ht20Coexist = true; 1564 } 1565 /* Disable protection from non-HT and HT20 devices. */ 1566 /* decision for disabling protection from 11b has already been taken above. */ 1567 if (eSIR_HT_OP_MODE_PURE == htInfo.opMode) { 1568 pe_session->beaconParams.llgCoexist = false; 1569 pe_session->beaconParams.ht20Coexist = false; 1570 } 1571 1572 } 1573 } 1574 /* protection related factors other than HT operating mode. Applies to 2.4 GHZ as well as 5 GHZ. */ 1575 if ((pe_session->htCapability) && (pBeaconStruct->HTInfo.present)) { 1576 tDot11fIEHTInfo htInfo = pBeaconStruct->HTInfo; 1577 1578 pe_session->beaconParams.fRIFSMode = 1579 (uint8_t) htInfo.rifsMode; 1580 pe_session->beaconParams.llnNonGFCoexist = 1581 (uint8_t) htInfo.nonGFDevicesPresent; 1582 pe_session->beaconParams.fLsigTXOPProtectionFullSupport = 1583 (uint8_t) htInfo.lsigTXOPProtectionFullSupport; 1584 } 1585 } 1586 1587 1588 /** 1589 * lim_decide_sta_11bg_protection() - decides protection related settings on sta 1590 * @mac_ctx: pointer to global mac structure 1591 * @beacon_struct: pointer to tpschbeaconstruct 1592 * @beaconparams: pointer to tpupdatebeaconparams 1593 * @psession_entry: pointer to tppesession 1594 * @phy_mode: phy mode index 1595 * 1596 * decides 11bg protection related settings on sta while processing beacon 1597 * 1598 * Return: none 1599 */ 1600 static void 1601 lim_decide_sta_11bg_protection(struct mac_context *mac_ctx, 1602 tpSchBeaconStruct beacon_struct, 1603 tpUpdateBeaconParams beaconparams, 1604 struct pe_session *psession_entry, 1605 uint32_t phy_mode) 1606 { 1607 1608 tDot11fIEHTInfo htInfo; 1609 1610 /* 1611 * spec 7.3.2.13 1612 * UseProtection will be set when nonERP STA is associated. 1613 * NonERPPresent bit will be set when: 1614 * --nonERP Sta is associated OR 1615 * --nonERP Sta exists in overlapping BSS 1616 * when useProtection is not set then protection from 1617 * nonERP stations is optional. 1618 */ 1619 if (phy_mode != WNI_CFG_PHY_MODE_11B) { 1620 if (beacon_struct->erpPresent && 1621 (beacon_struct->erpIEInfo.useProtection || 1622 beacon_struct->erpIEInfo.nonErpPresent)) { 1623 lim_enable11g_protection(mac_ctx, true, false, 1624 beaconparams, 1625 psession_entry); 1626 } 1627 /* AP has no 11b station associated. */ 1628 else { 1629 /* disable protection from 11b station */ 1630 lim_enable11g_protection(mac_ctx, false, false, 1631 beaconparams, 1632 psession_entry); 1633 } 1634 } 1635 1636 if (!(psession_entry->htCapability) || 1637 !(beacon_struct->HTInfo.present)) 1638 return; 1639 1640 /* following code is only for HT station. */ 1641 1642 htInfo = beacon_struct->HTInfo; 1643 /* AP has at least one 11G station associated. */ 1644 if (((eSIR_HT_OP_MODE_MIXED == htInfo.opMode) || 1645 (eSIR_HT_OP_MODE_OVERLAP_LEGACY == htInfo.opMode)) && 1646 (!psession_entry->beaconParams.llbCoexist)) { 1647 lim_enable_ht_protection_from11g(mac_ctx, true, false, 1648 beaconparams, psession_entry); 1649 1650 } 1651 /* 1652 * no HT operating mode change ==> no change in 1653 * protection settings except for MIXED_MODE/Legacy 1654 * Mode. 1655 */ 1656 /* 1657 * in Mixed mode/legacy Mode even if there is no 1658 * change in HT operating mode, there might be 1659 * change in 11bCoexist or 11gCoexist. Hence this 1660 * check is being done after mixed/legacy mode 1661 * check. 1662 */ 1663 if (mac_ctx->lim.gHTOperMode != 1664 (tSirMacHTOperatingMode)htInfo.opMode) { 1665 mac_ctx->lim.gHTOperMode = 1666 (tSirMacHTOperatingMode) htInfo.opMode; 1667 /* 1668 * AP has only HT stations associated and 1669 * at least one station is HT 20 1670 */ 1671 1672 /* disable protection from any non-HT devices. */ 1673 1674 /* 1675 * decision for disabling protection from 1676 * 11b has already been taken above. 1677 */ 1678 if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT == 1679 htInfo.opMode) { 1680 /* Disable protection from 11G station. */ 1681 lim_enable_ht_protection_from11g(mac_ctx, false, 1682 false, beaconparams, 1683 psession_entry); 1684 1685 lim_enable_ht20_protection(mac_ctx, true, false, 1686 beaconparams, 1687 psession_entry); 1688 } 1689 /* 1690 * Disable protection from non-HT and 1691 * HT20 devices. 1692 */ 1693 /* 1694 * decision for disabling protection from 1695 * 11b has already been taken above. 1696 */ 1697 else if (eSIR_HT_OP_MODE_PURE == htInfo.opMode) { 1698 lim_enable_ht_protection_from11g(mac_ctx, false, 1699 false, beaconparams, 1700 psession_entry); 1701 1702 lim_enable_ht20_protection(mac_ctx, false, 1703 false, beaconparams, 1704 psession_entry); 1705 1706 } 1707 } 1708 1709 } 1710 1711 /** 1712 * lim_decide_sta_protection() - decides protection related settings on sta 1713 * @mac_ctx: pointer to global mac structure 1714 * @beacon_struct: pointer to tpschbeaconstruct 1715 * @beaconparams: pointer to tpupdatebeaconparams 1716 * @psession_entry: pointer to tppesession 1717 * 1718 * decides protection related settings on sta while processing beacon 1719 * 1720 * Return: none 1721 */ 1722 void 1723 lim_decide_sta_protection(struct mac_context *mac_ctx, 1724 tpSchBeaconStruct beacon_struct, 1725 tpUpdateBeaconParams beaconparams, 1726 struct pe_session *psession_entry) 1727 { 1728 1729 enum reg_wifi_band rfband = REG_BAND_UNKNOWN; 1730 uint32_t phy_mode = WNI_CFG_PHY_MODE_NONE; 1731 1732 lim_get_rf_band_new(mac_ctx, &rfband, psession_entry); 1733 lim_get_phy_mode(mac_ctx, &phy_mode, psession_entry); 1734 1735 if ((REG_BAND_5G == rfband) && 1736 /* we are HT capable. */ 1737 (true == psession_entry->htCapability) && 1738 (beacon_struct->HTInfo.present)) { 1739 /* 1740 * we are HT capable, AP's HT OPMode is 1741 * mixed / overlap legacy ==> need protection 1742 * from 11A. 1743 */ 1744 if ((eSIR_HT_OP_MODE_MIXED == 1745 beacon_struct->HTInfo.opMode) || 1746 (eSIR_HT_OP_MODE_OVERLAP_LEGACY == 1747 beacon_struct->HTInfo.opMode)) { 1748 lim_update_11a_protection(mac_ctx, true, false, 1749 beaconparams, psession_entry); 1750 } 1751 /* 1752 * we are HT capable, AP's HT OPMode is 1753 * HT20 ==> disable protection from 11A if 1754 * enabled. 1755 */ 1756 /* protection from HT20 if needed. */ 1757 else if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT == 1758 beacon_struct->HTInfo.opMode) { 1759 lim_update_11a_protection(mac_ctx, false, false, 1760 beaconparams, psession_entry); 1761 lim_enable_ht20_protection(mac_ctx, true, false, 1762 beaconparams, psession_entry); 1763 } else if (eSIR_HT_OP_MODE_PURE == 1764 beacon_struct->HTInfo.opMode) { 1765 lim_update_11a_protection(mac_ctx, false, false, 1766 beaconparams, psession_entry); 1767 lim_enable_ht20_protection(mac_ctx, false, 1768 false, beaconparams, 1769 psession_entry); 1770 } 1771 } else if (REG_BAND_2G == rfband) { 1772 lim_decide_sta_11bg_protection(mac_ctx, beacon_struct, 1773 beaconparams, psession_entry, phy_mode); 1774 } 1775 /* 1776 * following code block is only for HT station. 1777 * (2.4 GHZ as well as 5 GHZ) 1778 */ 1779 if ((psession_entry->htCapability) && (beacon_struct->HTInfo.present)) { 1780 tDot11fIEHTInfo htInfo = beacon_struct->HTInfo; 1781 /* 1782 * Check for changes in protection related factors other 1783 * than HT operating mode. 1784 */ 1785 /* 1786 * Check for changes in RIFS mode, nonGFDevicesPresent, 1787 * lsigTXOPProtectionFullSupport. 1788 */ 1789 if (psession_entry->beaconParams.fRIFSMode != 1790 (uint8_t) htInfo.rifsMode) { 1791 beaconparams->fRIFSMode = 1792 psession_entry->beaconParams.fRIFSMode = 1793 (uint8_t) htInfo.rifsMode; 1794 beaconparams->paramChangeBitmap |= 1795 PARAM_RIFS_MODE_CHANGED; 1796 } 1797 1798 if (psession_entry->beaconParams.llnNonGFCoexist != 1799 htInfo.nonGFDevicesPresent) { 1800 beaconparams->llnNonGFCoexist = 1801 psession_entry->beaconParams.llnNonGFCoexist = 1802 (uint8_t) htInfo.nonGFDevicesPresent; 1803 beaconparams->paramChangeBitmap |= 1804 PARAM_NON_GF_DEVICES_PRESENT_CHANGED; 1805 } 1806 1807 if (psession_entry->beaconParams. 1808 fLsigTXOPProtectionFullSupport != 1809 (uint8_t) htInfo.lsigTXOPProtectionFullSupport) { 1810 beaconparams->fLsigTXOPProtectionFullSupport = 1811 psession_entry->beaconParams. 1812 fLsigTXOPProtectionFullSupport = 1813 (uint8_t) htInfo. 1814 lsigTXOPProtectionFullSupport; 1815 beaconparams->paramChangeBitmap |= 1816 PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED; 1817 } 1818 /* 1819 * For Station just update the global lim variable, 1820 * no need to send message to HAL since Station already 1821 * taking care of HT OPR Mode=01, 1822 * meaning AP is seeing legacy 1823 */ 1824 /* stations in overlapping BSS. */ 1825 if (psession_entry->beaconParams.gHTObssMode != 1826 (uint8_t) htInfo.obssNonHTStaPresent) 1827 psession_entry->beaconParams.gHTObssMode = 1828 (uint8_t) htInfo.obssNonHTStaPresent; 1829 1830 } 1831 } 1832 1833 /** 1834 * __lim_process_channel_switch_timeout() 1835 * 1836 ***FUNCTION: 1837 * This function is invoked when Channel Switch Timer expires at 1838 * the STA. Now, STA must stop traffic, and then change/disable 1839 * primary or secondary channel. 1840 * 1841 * 1842 ***NOTE: 1843 * @param pe_session - Pointer to pe session 1844 * 1845 * @return qdf_status 1846 */ 1847 static QDF_STATUS 1848 __lim_process_channel_switch_timeout(struct pe_session *pe_session) 1849 { 1850 struct mac_context *mac; 1851 uint32_t channel_freq; 1852 QDF_STATUS status = QDF_STATUS_SUCCESS; 1853 1854 if (!pe_session) { 1855 pe_err("Invalid pe session"); 1856 return QDF_STATUS_E_INVAL; 1857 } 1858 mac = pe_session->mac_ctx; 1859 if (!mac) { 1860 pe_err("Invalid mac context"); 1861 return QDF_STATUS_E_INVAL; 1862 } 1863 1864 if (!LIM_IS_STA_ROLE(pe_session)) { 1865 pe_warn("Channel switch can be done only in STA role, Current Role: %d", 1866 GET_LIM_SYSTEM_ROLE(pe_session)); 1867 return QDF_STATUS_E_INVAL; 1868 } 1869 1870 if (pe_session->gLimSpecMgmt.dot11hChanSwState != 1871 eLIM_11H_CHANSW_RUNNING) { 1872 pe_warn("Channel switch timer should not have been running in state: %d", 1873 pe_session->gLimSpecMgmt.dot11hChanSwState); 1874 return QDF_STATUS_E_INVAL; 1875 } 1876 1877 channel_freq = pe_session->gLimChannelSwitch.sw_target_freq; 1878 /* Restore Channel Switch parameters to default */ 1879 pe_session->gLimChannelSwitch.switchTimeoutValue = 0; 1880 1881 /* Channel-switch timeout has occurred. reset the state */ 1882 pe_session->gLimSpecMgmt.dot11hChanSwState = eLIM_11H_CHANSW_END; 1883 1884 /* Check if the AP is switching to a channel that we support. 1885 * Else, just don't bother to switch. Indicate HDD to look for a 1886 * better AP to associate 1887 */ 1888 if (!lim_is_channel_valid_for_channel_switch(mac, channel_freq)) { 1889 /* We need to restore pre-channelSwitch state on the STA */ 1890 if (lim_restore_pre_channel_switch_state(mac, pe_session) != 1891 QDF_STATUS_SUCCESS) { 1892 pe_err("Could not restore pre-channelSwitch (11h) state, resetting the system"); 1893 return QDF_STATUS_E_INVAL; 1894 } 1895 1896 /* 1897 * The channel switch request received from AP is carrying 1898 * invalid channel. It's ok to ignore this channel switch 1899 * request as it might be from spoof AP. If it's from genuine 1900 * AP, it may lead to heart beat failure and result in 1901 * disconnection. DUT can go ahead and reconnect to it/any 1902 * other AP once it disconnects. 1903 */ 1904 pe_err("Invalid channel freq %u Ignore CSA request", 1905 channel_freq); 1906 return QDF_STATUS_E_INVAL; 1907 } 1908 switch (pe_session->gLimChannelSwitch.state) { 1909 case eLIM_CHANNEL_SWITCH_PRIMARY_ONLY: 1910 status = lim_switch_primary_channel(mac, 1911 pe_session->gLimChannelSwitch.sw_target_freq, 1912 pe_session); 1913 pe_session->gLimChannelSwitch.state = 1914 eLIM_CHANNEL_SWITCH_IDLE; 1915 break; 1916 case eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY: 1917 status = lim_switch_primary_secondary_channel(mac, pe_session); 1918 pe_session->gLimChannelSwitch.state = eLIM_CHANNEL_SWITCH_IDLE; 1919 break; 1920 1921 case eLIM_CHANNEL_SWITCH_IDLE: 1922 default: 1923 pe_err("incorrect state"); 1924 if (lim_restore_pre_channel_switch_state(mac, pe_session) != 1925 QDF_STATUS_SUCCESS) { 1926 pe_err("Could not restore pre-channelSwitch (11h) state, resetting the system"); 1927 status = QDF_STATUS_E_FAILURE; 1928 } 1929 /* Please note, this is 'return' and not 'break' */ 1930 return status; 1931 } 1932 1933 return status; 1934 } 1935 1936 void lim_disconnect_complete(struct pe_session *session, bool del_bss) 1937 { 1938 QDF_STATUS status; 1939 struct mac_context *mac = session->mac_ctx; 1940 1941 if (wlan_vdev_mlme_get_substate(session->vdev) == 1942 WLAN_VDEV_SS_STOP_STOP_PROGRESS) { 1943 status = wlan_vdev_mlme_sm_deliver_evt(session->vdev, 1944 WLAN_VDEV_SM_EV_STOP_REQ, 1945 sizeof(*session), 1946 session); 1947 return; 1948 } 1949 status = 1950 wlan_vdev_mlme_sm_deliver_evt(session->vdev, 1951 WLAN_VDEV_SM_EV_DISCONNECT_COMPLETE, 1952 sizeof(*session), session); 1953 if (QDF_IS_STATUS_ERROR(status)) 1954 lim_send_stop_bss_failure_resp(mac, session); 1955 } 1956 1957 void lim_process_channel_switch(struct mac_context *mac_ctx, uint8_t vdev_id) 1958 { 1959 struct pe_session *session_entry; 1960 QDF_STATUS status; 1961 1962 session_entry = pe_find_session_by_vdev_id(mac_ctx, vdev_id); 1963 if (!session_entry) { 1964 pe_err("Session does not exist for given vdev_id %d", vdev_id); 1965 return; 1966 } 1967 1968 session_entry->channelChangeReasonCode = LIM_SWITCH_CHANNEL_OPERATION; 1969 mlme_set_chan_switch_in_progress(session_entry->vdev, true); 1970 status = wlan_vdev_mlme_sm_deliver_evt( 1971 session_entry->vdev, 1972 WLAN_VDEV_SM_EV_FW_VDEV_RESTART, 1973 sizeof(*session_entry), 1974 session_entry); 1975 if (QDF_IS_STATUS_ERROR(status)) 1976 mlme_set_chan_switch_in_progress(session_entry->vdev, false); 1977 } 1978 1979 /** ------------------------------------------------------------------------ **/ 1980 /** 1981 * keep track of the number of ANI peers associated in the BSS 1982 * For the first and last ANI peer, we have to update EDCA params as needed 1983 * 1984 * When the first ANI peer joins the BSS, we notify SCH 1985 * When the last ANI peer leaves the BSS, we notfiy SCH 1986 */ 1987 void 1988 lim_util_count_sta_add(struct mac_context *mac, 1989 tpDphHashNode pSta, struct pe_session *pe_session) 1990 { 1991 1992 if ((!pSta) || (!pSta->valid) || (pSta->fAniCount)) 1993 return; 1994 1995 pSta->fAniCount = 1; 1996 1997 if (mac->lim.gLimNumOfAniSTAs++ != 0) 1998 return; 1999 2000 if (mac->mlme_cfg->wmm_params.edca_profile != 2001 WNI_CFG_EDCA_PROFILE_ANI) 2002 return; 2003 2004 /* get here only if this is the first ANI peer in the BSS */ 2005 sch_edca_profile_update(mac, pe_session); 2006 } 2007 2008 void 2009 lim_util_count_sta_del(struct mac_context *mac, 2010 tpDphHashNode pSta, struct pe_session *pe_session) 2011 { 2012 2013 if ((!pSta) || (!pSta->fAniCount)) 2014 return; 2015 2016 /* Only if sta is invalid and the validInDummyState bit is set to 1, 2017 * then go ahead and update the count and profiles. This ensures 2018 * that the "number of ani station" count is properly incremented/decremented. 2019 */ 2020 if (pSta->valid == 1) 2021 return; 2022 2023 pSta->fAniCount = 0; 2024 2025 if (mac->lim.gLimNumOfAniSTAs <= 0) { 2026 pe_err("CountStaDel: ignoring Delete Req when AniPeer count: %d", 2027 mac->lim.gLimNumOfAniSTAs); 2028 return; 2029 } 2030 2031 mac->lim.gLimNumOfAniSTAs--; 2032 2033 if (mac->lim.gLimNumOfAniSTAs != 0) 2034 return; 2035 2036 if (mac->mlme_cfg->wmm_params.edca_profile != 2037 WNI_CFG_EDCA_PROFILE_ANI) 2038 return; 2039 2040 /* get here only if this is the last ANI peer in the BSS */ 2041 sch_edca_profile_update(mac, pe_session); 2042 } 2043 2044 /** 2045 * lim_switch_channel_vdev_started() - Send vdev started when switch channel 2046 * 2047 * @pe_session: PE session entry 2048 * 2049 * This function is called to deliver WLAN_VDEV_SM_EV_START_SUCCESS to VDEV SM 2050 * 2051 * Return: None 2052 */ 2053 static void lim_switch_channel_vdev_started(struct pe_session *pe_session) 2054 { 2055 QDF_STATUS status; 2056 2057 status = wlan_vdev_mlme_sm_deliver_evt( 2058 pe_session->vdev, 2059 WLAN_VDEV_SM_EV_START_SUCCESS, 2060 sizeof(*pe_session), pe_session); 2061 } 2062 2063 /** 2064 * lim_switch_channel_cback() 2065 * 2066 ***FUNCTION: 2067 * This is the callback function registered while requesting to switch channel 2068 * after AP indicates a channel switch for spectrum management (11h). 2069 * 2070 ***NOTE: 2071 * @param mac Pointer to Global MAC structure 2072 * @param status Status of channel switch request 2073 * @param data User data 2074 * @param pe_session Session information 2075 * @return NONE 2076 */ 2077 void lim_switch_channel_cback(struct mac_context *mac, QDF_STATUS status, 2078 uint32_t *data, struct pe_session *pe_session) 2079 { 2080 struct scheduler_msg mmhMsg = { 0 }; 2081 struct switch_channel_ind *pSirSmeSwitchChInd; 2082 struct wlan_channel *des_chan; 2083 struct vdev_mlme_obj *mlme_obj; 2084 2085 if (QDF_IS_STATUS_ERROR(status)) { 2086 lim_tear_down_link_with_ap(mac, pe_session->peSessionId, 2087 REASON_CHANNEL_SWITCH_FAILED, 2088 eLIM_HOST_DISASSOC); 2089 return; 2090 } 2091 2092 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(pe_session->vdev); 2093 if (!mlme_obj) { 2094 pe_err("vdev component object is NULL"); 2095 return; 2096 } 2097 2098 des_chan = mlme_obj->vdev->vdev_mlme.des_chan; 2099 if (!des_chan) { 2100 pe_err("des_chan is NULL"); 2101 return; 2102 } 2103 pe_session->curr_op_freq = pe_session->curr_req_chan_freq; 2104 /* We need to restore pre-channelSwitch state on the STA */ 2105 if (lim_restore_pre_channel_switch_state(mac, pe_session) != 2106 QDF_STATUS_SUCCESS) { 2107 pe_err("Could not restore pre-channelSwitch (11h) state, resetting the system"); 2108 return; 2109 } 2110 2111 mmhMsg.type = eWNI_SME_SWITCH_CHL_IND; 2112 pSirSmeSwitchChInd = qdf_mem_malloc(sizeof(*pSirSmeSwitchChInd)); 2113 if (!pSirSmeSwitchChInd) 2114 return; 2115 2116 pSirSmeSwitchChInd->messageType = eWNI_SME_SWITCH_CHL_IND; 2117 pSirSmeSwitchChInd->length = sizeof(*pSirSmeSwitchChInd); 2118 pSirSmeSwitchChInd->freq = des_chan->ch_freq; 2119 pSirSmeSwitchChInd->sessionId = pe_session->smeSessionId; 2120 pSirSmeSwitchChInd->chan_params.ch_width = des_chan->ch_width; 2121 if (des_chan->ch_width > CH_WIDTH_20MHZ) { 2122 pSirSmeSwitchChInd->chan_params.sec_ch_offset = 2123 pe_session->gLimChannelSwitch.sec_ch_offset; 2124 pSirSmeSwitchChInd->chan_params.center_freq_seg0 = 2125 des_chan->ch_freq_seg1; 2126 pSirSmeSwitchChInd->chan_params.mhz_freq_seg0 = 2127 des_chan->ch_cfreq1; 2128 pSirSmeSwitchChInd->chan_params.center_freq_seg1 = 2129 des_chan->ch_freq_seg2; 2130 pSirSmeSwitchChInd->chan_params.mhz_freq_seg1 = 2131 des_chan->ch_cfreq2; 2132 } 2133 pSirSmeSwitchChInd->ch_phymode = des_chan->ch_phymode; 2134 2135 pSirSmeSwitchChInd->status = status; 2136 qdf_mem_copy(pSirSmeSwitchChInd->bssid.bytes, pe_session->bssId, 2137 QDF_MAC_ADDR_SIZE); 2138 mmhMsg.bodyptr = pSirSmeSwitchChInd; 2139 mmhMsg.bodyval = 0; 2140 2141 MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG, 2142 pe_session->peSessionId, mmhMsg.type)); 2143 2144 sys_process_mmh_msg(mac, &mmhMsg); 2145 2146 lim_switch_channel_vdev_started(pe_session); 2147 } 2148 2149 QDF_STATUS lim_switch_primary_channel(struct mac_context *mac, 2150 uint32_t new_channel_freq, 2151 struct pe_session *pe_session) 2152 { 2153 pe_debug("freq: %d --> freq: %d", pe_session->curr_op_freq, 2154 new_channel_freq); 2155 2156 pe_session->curr_req_chan_freq = new_channel_freq; 2157 pe_session->curr_op_freq = pe_session->curr_req_chan_freq; 2158 pe_session->ch_center_freq_seg0 = 0; 2159 pe_session->ch_center_freq_seg1 = 0; 2160 pe_session->ch_width = CH_WIDTH_20MHZ; 2161 pe_session->limRFBand = lim_get_rf_band(pe_session->curr_req_chan_freq); 2162 2163 pe_session->channelChangeReasonCode = LIM_SWITCH_CHANNEL_OPERATION; 2164 2165 mac->lim.gpchangeChannelCallback = lim_switch_channel_cback; 2166 mac->lim.gpchangeChannelData = NULL; 2167 2168 return lim_send_switch_chnl_params(mac, pe_session); 2169 } 2170 2171 #ifdef WLAN_FEATURE_11BE 2172 /** 2173 * lim_set_puncture_from_chan_switch_to_session() - set puncture from channel 2174 * switch to pe session 2175 * @pe_session: pointer to pe session 2176 * 2177 * Return: void 2178 */ 2179 static void 2180 lim_set_puncture_from_chan_switch_to_session(struct pe_session *pe_session) 2181 { 2182 pe_session->puncture_bitmap = 2183 pe_session->gLimChannelSwitch.puncture_bitmap; 2184 } 2185 #else 2186 static void 2187 lim_set_puncture_from_chan_switch_to_session(struct pe_session *pe_session) 2188 { 2189 } 2190 #endif 2191 2192 QDF_STATUS lim_switch_primary_secondary_channel(struct mac_context *mac, 2193 struct pe_session *pe_session) 2194 { 2195 uint32_t new_channel_freq; 2196 uint8_t ch_center_freq_seg0; 2197 uint8_t ch_center_freq_seg1; 2198 enum phy_ch_width ch_width; 2199 2200 new_channel_freq = pe_session->gLimChannelSwitch.sw_target_freq, 2201 ch_center_freq_seg0 = pe_session->gLimChannelSwitch.ch_center_freq_seg0, 2202 ch_center_freq_seg1 = pe_session->gLimChannelSwitch.ch_center_freq_seg1, 2203 ch_width = pe_session->gLimChannelSwitch.ch_width; 2204 2205 /* Assign the callback to resume TX once channel is changed. */ 2206 pe_session->curr_req_chan_freq = new_channel_freq; 2207 pe_session->limRFBand = lim_get_rf_band(pe_session->curr_req_chan_freq); 2208 pe_session->channelChangeReasonCode = LIM_SWITCH_CHANNEL_OPERATION; 2209 mac->lim.gpchangeChannelCallback = lim_switch_channel_cback; 2210 mac->lim.gpchangeChannelData = NULL; 2211 2212 /* Store the new primary and secondary channel in session entries if different */ 2213 if (pe_session->curr_op_freq != new_channel_freq || 2214 pe_session->ch_width != ch_width) { 2215 pe_warn("freq: %d[%d] --> freq: %d[%d]", 2216 pe_session->curr_op_freq, pe_session->ch_width, 2217 new_channel_freq, ch_width); 2218 pe_session->curr_op_freq = new_channel_freq; 2219 } 2220 if (pe_session->htSecondaryChannelOffset != 2221 pe_session->gLimChannelSwitch.sec_ch_offset) { 2222 pe_warn("HT sec chnl: %d --> HT sec chnl: %d", 2223 pe_session->htSecondaryChannelOffset, 2224 pe_session->gLimChannelSwitch.sec_ch_offset); 2225 pe_session->htSecondaryChannelOffset = 2226 pe_session->gLimChannelSwitch.sec_ch_offset; 2227 if (pe_session->htSecondaryChannelOffset == 2228 PHY_SINGLE_CHANNEL_CENTERED) { 2229 pe_session->htSupportedChannelWidthSet = 2230 WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; 2231 } else { 2232 pe_session->htSupportedChannelWidthSet = 2233 WNI_CFG_CHANNEL_BONDING_MODE_ENABLE; 2234 } 2235 pe_session->htRecommendedTxWidthSet = 2236 pe_session->htSupportedChannelWidthSet; 2237 } 2238 2239 pe_session->ch_center_freq_seg0 = ch_center_freq_seg0; 2240 pe_session->ch_center_freq_seg1 = ch_center_freq_seg1; 2241 pe_session->ch_width = ch_width; 2242 lim_set_puncture_from_chan_switch_to_session(pe_session); 2243 2244 return lim_send_switch_chnl_params(mac, pe_session); 2245 } 2246 2247 /** 2248 * lim_get_ht_capability() 2249 * 2250 ***FUNCTION: 2251 * A utility function that returns the "current HT capability state" for the HT 2252 * capability of interest (as requested in the API) 2253 * 2254 ***LOGIC: 2255 * This routine will return with the "current" setting of a requested HT 2256 * capability. This state info could be retrieved from - 2257 * a) CFG (for static entries) 2258 * b) Run time info 2259 * - Dynamic state maintained by LIM 2260 * - Configured at radio init time by SME 2261 * 2262 * 2263 ***ASSUMPTIONS: 2264 * NA 2265 * 2266 ***NOTE: 2267 * 2268 * @param mac Pointer to Global MAC structure 2269 * @param htCap The HT capability being queried 2270 * @return uint8_t The current state of the requested HT capability is returned in a 2271 * uint8_t variable 2272 */ 2273 2274 uint8_t lim_get_ht_capability(struct mac_context *mac, 2275 uint32_t htCap, struct pe_session *pe_session) 2276 { 2277 uint8_t retVal = 0; 2278 uint8_t *ptr; 2279 tSirMacTxBFCapabilityInfo macTxBFCapabilityInfo = { 0 }; 2280 tSirMacASCapabilityInfo macASCapabilityInfo = { 0 }; 2281 struct mlme_vht_capabilities_info *vht_cap_info; 2282 2283 vht_cap_info = &mac->mlme_cfg->vht_caps.vht_cap_info; 2284 2285 /* */ 2286 /* Determine which CFG to read from. Not ALL of the HT */ 2287 /* related CFG's need to be read each time this API is */ 2288 /* accessed */ 2289 /* */ 2290 if (htCap >= eHT_ANTENNA_SELECTION && htCap < eHT_SI_GRANULARITY) { 2291 /* Get Antenna Selection HT Capabilities */ 2292 ptr = (uint8_t *) &macASCapabilityInfo; 2293 *((uint8_t *)ptr) = (uint8_t)(vht_cap_info->as_cap & 0xff); 2294 } else if (htCap >= eHT_TX_BEAMFORMING && 2295 htCap < eHT_ANTENNA_SELECTION) { 2296 /* Get Transmit Beam Forming HT Capabilities */ 2297 ptr = (uint8_t *)&macTxBFCapabilityInfo; 2298 *((uint32_t *)ptr) = (uint32_t)(vht_cap_info->tx_bf_cap); 2299 } 2300 2301 switch (htCap) { 2302 case eHT_LSIG_TXOP_PROTECTION: 2303 retVal = mac->lim.gHTLsigTXOPProtection; 2304 break; 2305 2306 case eHT_STBC_CONTROL_FRAME: 2307 retVal = (uint8_t)mac->mlme_cfg->ht_caps.ht_cap_info. 2308 stbc_control_frame; 2309 break; 2310 2311 case eHT_PSMP: 2312 retVal = mac->lim.gHTPSMPSupport; 2313 break; 2314 2315 case eHT_DSSS_CCK_MODE_40MHZ: 2316 retVal = mac->lim.gHTDsssCckRate40MHzSupport; 2317 break; 2318 2319 case eHT_MAX_AMSDU_LENGTH: 2320 retVal = (uint8_t)mac->mlme_cfg->ht_caps.ht_cap_info. 2321 maximal_amsdu_size; 2322 break; 2323 2324 case eHT_MAX_AMSDU_NUM: 2325 retVal = (uint8_t) pe_session->max_amsdu_num; 2326 break; 2327 2328 case eHT_RX_STBC: 2329 retVal = (uint8_t) pe_session->ht_config.rx_stbc; 2330 break; 2331 2332 case eHT_TX_STBC: 2333 retVal = (uint8_t) pe_session->ht_config.tx_stbc; 2334 break; 2335 2336 case eHT_SHORT_GI_40MHZ: 2337 retVal = (uint8_t)(pe_session->ht_config.short_gi_40_mhz) ? 2338 mac->mlme_cfg->ht_caps.ht_cap_info.short_gi_40_mhz : 0; 2339 break; 2340 2341 case eHT_SHORT_GI_20MHZ: 2342 retVal = (uint8_t)(pe_session->ht_config.short_gi_20_mhz) ? 2343 mac->mlme_cfg->ht_caps.ht_cap_info.short_gi_20_mhz : 0; 2344 break; 2345 2346 case eHT_GREENFIELD: 2347 retVal = (uint8_t)mac->mlme_cfg->ht_caps.ht_cap_info. 2348 green_field; 2349 break; 2350 2351 case eHT_MIMO_POWER_SAVE: 2352 retVal = (uint8_t) mac->lim.gHTMIMOPSState; 2353 break; 2354 2355 case eHT_SUPPORTED_CHANNEL_WIDTH_SET: 2356 retVal = (uint8_t) pe_session->htSupportedChannelWidthSet; 2357 break; 2358 2359 case eHT_ADVANCED_CODING: 2360 retVal = (uint8_t) pe_session->ht_config.adv_coding_cap; 2361 break; 2362 2363 case eHT_MAX_RX_AMPDU_FACTOR: 2364 retVal = mac->lim.gHTMaxRxAMpduFactor; 2365 break; 2366 2367 case eHT_MPDU_DENSITY: 2368 retVal = mac->lim.gHTAMpduDensity; 2369 break; 2370 2371 case eHT_PCO: 2372 retVal = (uint8_t)mac->mlme_cfg->ht_caps.ext_cap_info.pco; 2373 break; 2374 2375 case eHT_TRANSITION_TIME: 2376 retVal = (uint8_t)mac->mlme_cfg->ht_caps.ext_cap_info. 2377 transition_time; 2378 break; 2379 2380 case eHT_MCS_FEEDBACK: 2381 retVal = (uint8_t)mac->mlme_cfg->ht_caps.ext_cap_info. 2382 mcs_feedback; 2383 break; 2384 2385 case eHT_TX_BEAMFORMING: 2386 retVal = (uint8_t) macTxBFCapabilityInfo.txBF; 2387 break; 2388 2389 case eHT_ANTENNA_SELECTION: 2390 retVal = (uint8_t) macASCapabilityInfo.antennaSelection; 2391 break; 2392 2393 case eHT_SI_GRANULARITY: 2394 retVal = mac->lim.gHTServiceIntervalGranularity; 2395 break; 2396 2397 case eHT_CONTROLLED_ACCESS: 2398 retVal = mac->lim.gHTControlledAccessOnly; 2399 break; 2400 2401 case eHT_RIFS_MODE: 2402 retVal = pe_session->beaconParams.fRIFSMode; 2403 break; 2404 2405 case eHT_RECOMMENDED_TX_WIDTH_SET: 2406 retVal = pe_session->htRecommendedTxWidthSet; 2407 break; 2408 2409 case eHT_EXTENSION_CHANNEL_OFFSET: 2410 retVal = pe_session->htSecondaryChannelOffset; 2411 break; 2412 2413 case eHT_OP_MODE: 2414 if (LIM_IS_AP_ROLE(pe_session)) 2415 retVal = pe_session->htOperMode; 2416 else 2417 retVal = mac->lim.gHTOperMode; 2418 break; 2419 2420 case eHT_BASIC_STBC_MCS: 2421 retVal = mac->lim.gHTSTBCBasicMCS; 2422 break; 2423 2424 case eHT_DUAL_CTS_PROTECTION: 2425 retVal = mac->lim.gHTDualCTSProtection; 2426 break; 2427 2428 case eHT_LSIG_TXOP_PROTECTION_FULL_SUPPORT: 2429 retVal = 2430 pe_session->beaconParams.fLsigTXOPProtectionFullSupport; 2431 break; 2432 2433 case eHT_PCO_ACTIVE: 2434 retVal = mac->lim.gHTPCOActive; 2435 break; 2436 2437 case eHT_PCO_PHASE: 2438 retVal = mac->lim.gHTPCOPhase; 2439 break; 2440 2441 default: 2442 break; 2443 } 2444 2445 return retVal; 2446 } 2447 2448 /** 2449 * lim_enable_11a_protection() - updates protection params for enable 11a 2450 * protection request 2451 * @mac_ctx: pointer to Global MAC structure 2452 * @overlap: 1=> called from overlap context, 0 => called from assoc context. 2453 * @bcn_prms: beacon parameters 2454 * @pe_session: pe session entry 2455 * 2456 * This function updates protection params for enable 11a protection request 2457 * 2458 * @Return: void 2459 */ 2460 static void 2461 lim_enable_11a_protection(struct mac_context *mac_ctx, 2462 uint8_t overlap, 2463 tpUpdateBeaconParams bcn_prms, 2464 struct pe_session *pe_session) 2465 { 2466 /* 2467 * If we are AP and HT capable, we need to set the HT OP mode 2468 * appropriately. 2469 */ 2470 if (LIM_IS_AP_ROLE(pe_session) && (true == pe_session->htCapability)) { 2471 if (overlap) { 2472 pe_session->gLimOverlap11aParams.protectionEnabled = 2473 true; 2474 if ((eSIR_HT_OP_MODE_OVERLAP_LEGACY != 2475 mac_ctx->lim.gHTOperMode) 2476 && (eSIR_HT_OP_MODE_MIXED != 2477 mac_ctx->lim.gHTOperMode)) { 2478 mac_ctx->lim.gHTOperMode = 2479 eSIR_HT_OP_MODE_OVERLAP_LEGACY; 2480 pe_session->htOperMode = 2481 eSIR_HT_OP_MODE_OVERLAP_LEGACY; 2482 lim_enable_ht_rifs_protection(mac_ctx, true, 2483 overlap, bcn_prms, pe_session); 2484 lim_enable_ht_obss_protection(mac_ctx, true, 2485 overlap, bcn_prms, pe_session); 2486 } 2487 } else { 2488 pe_session->gLim11aParams.protectionEnabled = true; 2489 if (eSIR_HT_OP_MODE_MIXED != pe_session->htOperMode) { 2490 mac_ctx->lim.gHTOperMode = 2491 eSIR_HT_OP_MODE_MIXED; 2492 pe_session->htOperMode = eSIR_HT_OP_MODE_MIXED; 2493 lim_enable_ht_rifs_protection(mac_ctx, true, 2494 overlap, bcn_prms, pe_session); 2495 lim_enable_ht_obss_protection(mac_ctx, true, 2496 overlap, bcn_prms, pe_session); 2497 } 2498 } 2499 } 2500 /* This part is common for station as well. */ 2501 if (false == pe_session->beaconParams.llaCoexist) { 2502 pe_debug(" => protection from 11A Enabled"); 2503 bcn_prms->llaCoexist = true; 2504 pe_session->beaconParams.llaCoexist = true; 2505 bcn_prms->paramChangeBitmap |= PARAM_llACOEXIST_CHANGED; 2506 } 2507 } 2508 2509 /** 2510 * lim_disable_11a_protection() - updates protection params for disable 11a 2511 * protection request 2512 * @mac_ctx: pointer to Global MAC structure 2513 * @overlap: 1=> called from overlap context, 0 => called from assoc context. 2514 * @bcn_prms: beacon parameters 2515 * @pe_session: pe session entry 2516 * 2517 * This function updates protection params for disable 11a protection request 2518 * 2519 * @Return: void 2520 */ 2521 static void 2522 lim_disable_11a_protection(struct mac_context *mac_ctx, 2523 uint8_t overlap, 2524 tpUpdateBeaconParams bcn_prms, 2525 struct pe_session *pe_session) 2526 { 2527 if (false == pe_session->beaconParams.llaCoexist) 2528 return; 2529 2530 /* for station role */ 2531 if (!LIM_IS_AP_ROLE(pe_session)) { 2532 pe_debug("===> Protection from 11A Disabled"); 2533 bcn_prms->llaCoexist = false; 2534 pe_session->beaconParams.llaCoexist = false; 2535 bcn_prms->paramChangeBitmap |= PARAM_llACOEXIST_CHANGED; 2536 return; 2537 } 2538 /* 2539 * for AP role. 2540 * we need to take care of HT OP mode change if needed. 2541 * We need to take care of Overlap cases. 2542 */ 2543 if (overlap) { 2544 /* Overlap Legacy protection disabled. */ 2545 pe_session->gLimOverlap11aParams.protectionEnabled = false; 2546 2547 /* 2548 * We need to take care of HT OP mode iff we are HT AP. 2549 * OR no HT op-mode change is needed if any of the overlap 2550 * protection enabled. 2551 */ 2552 if (!pe_session->htCapability || 2553 (pe_session->gLimOverlap11aParams.protectionEnabled 2554 || pe_session->gLimOverlapHt20Params.protectionEnabled 2555 || pe_session->gLimOverlapNonGfParams.protectionEnabled)) 2556 goto disable_11a_end; 2557 2558 /* Check if there is a need to change HT OP mode. */ 2559 if (eSIR_HT_OP_MODE_OVERLAP_LEGACY == 2560 mac_ctx->lim.gHTOperMode) { 2561 lim_enable_ht_rifs_protection(mac_ctx, false, overlap, 2562 bcn_prms, pe_session); 2563 lim_enable_ht_obss_protection(mac_ctx, false, overlap, 2564 bcn_prms, pe_session); 2565 2566 if (pe_session->gLimHt20Params.protectionEnabled) 2567 mac_ctx->lim.gHTOperMode = 2568 eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; 2569 else 2570 mac_ctx->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE; 2571 } 2572 } else { 2573 /* Disable protection from 11A stations. */ 2574 pe_session->gLim11aParams.protectionEnabled = false; 2575 lim_enable_ht_obss_protection(mac_ctx, false, overlap, 2576 bcn_prms, pe_session); 2577 2578 /* 2579 * Check if any other non-HT protection enabled. Right now we 2580 * are in HT OP Mixed mode. Change HT op mode appropriately. 2581 */ 2582 2583 /* Change HT OP mode to 01 if any overlap protection enabled */ 2584 if (pe_session->gLimOverlap11aParams.protectionEnabled 2585 || pe_session->gLimOverlapHt20Params.protectionEnabled 2586 || pe_session->gLimOverlapNonGfParams.protectionEnabled) { 2587 mac_ctx->lim.gHTOperMode = 2588 eSIR_HT_OP_MODE_OVERLAP_LEGACY; 2589 pe_session->htOperMode = eSIR_HT_OP_MODE_OVERLAP_LEGACY; 2590 lim_enable_ht_rifs_protection(mac_ctx, true, overlap, 2591 bcn_prms, pe_session); 2592 } else if (pe_session->gLimHt20Params.protectionEnabled) { 2593 mac_ctx->lim.gHTOperMode = 2594 eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; 2595 pe_session->htOperMode = 2596 eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; 2597 lim_enable_ht_rifs_protection(mac_ctx, false, overlap, 2598 bcn_prms, pe_session); 2599 } else { 2600 mac_ctx->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE; 2601 pe_session->htOperMode = eSIR_HT_OP_MODE_PURE; 2602 lim_enable_ht_rifs_protection(mac_ctx, false, overlap, 2603 bcn_prms, pe_session); 2604 } 2605 } 2606 2607 disable_11a_end: 2608 if (!pe_session->gLimOverlap11aParams.protectionEnabled && 2609 !pe_session->gLim11aParams.protectionEnabled) { 2610 pe_warn("===> Protection from 11A Disabled"); 2611 bcn_prms->llaCoexist = false; 2612 pe_session->beaconParams.llaCoexist = false; 2613 bcn_prms->paramChangeBitmap |= PARAM_llACOEXIST_CHANGED; 2614 } 2615 } 2616 2617 /** 2618 * lim_update_11a_protection() - based on config setting enables\disables 11a 2619 * protection. 2620 * @mac_ctx: pointer to Global MAC structure 2621 * @enable: 1=> enable protection, 0=> disable protection. 2622 * @overlap: 1=> called from overlap context, 0 => called from assoc context. 2623 * @bcn_prms: beacon parameters 2624 * @session: pe session entry 2625 * 2626 * This based on config setting enables\disables 11a protection. 2627 * 2628 * @Return: success of failure of operation 2629 */ 2630 QDF_STATUS 2631 lim_update_11a_protection(struct mac_context *mac_ctx, uint8_t enable, 2632 uint8_t overlap, tpUpdateBeaconParams bcn_prms, 2633 struct pe_session *session) 2634 { 2635 if (!session) { 2636 pe_err("session is NULL"); 2637 return QDF_STATUS_E_FAILURE; 2638 } 2639 /* overlapping protection configuration check. */ 2640 if (!overlap) { 2641 /* normal protection config check */ 2642 if ((LIM_IS_AP_ROLE(session)) && 2643 (!session->cfgProtection.fromlla)) { 2644 /* protection disabled. */ 2645 pe_warn("protection from 11a is disabled"); 2646 return QDF_STATUS_SUCCESS; 2647 } 2648 } 2649 2650 if (enable) 2651 lim_enable_11a_protection(mac_ctx, overlap, bcn_prms, session); 2652 else 2653 lim_disable_11a_protection(mac_ctx, overlap, bcn_prms, session); 2654 2655 return QDF_STATUS_SUCCESS; 2656 } 2657 2658 /** 2659 * lim_handle_enable11g_protection_enabled() - handle 11g protection enabled 2660 * @mac_ctx: pointer to Globale Mac structure 2661 * @beaconparams: pointer to tpUpdateBeaconParams 2662 * @overlap: 1=> called from overlap context, 0 => called from assoc context. 2663 * @session_entry: pointer to struct pe_session * 2664 * 2665 * Function handles 11g protection enaled case 2666 * 2667 * Return: none 2668 */ 2669 static void 2670 lim_handle_enable11g_protection_enabled(struct mac_context *mac_ctx, 2671 tpUpdateBeaconParams beaconparams, 2672 uint8_t overlap, struct pe_session *session_entry) 2673 { 2674 /* 2675 * If we are AP and HT capable, we need to set the HT OP mode 2676 * appropriately. 2677 */ 2678 if (LIM_IS_AP_ROLE(session_entry) && overlap) { 2679 session_entry->gLimOlbcParams.protectionEnabled = true; 2680 2681 pe_debug("protection from olbc is enabled"); 2682 2683 if (true == session_entry->htCapability) { 2684 if ((eSIR_HT_OP_MODE_OVERLAP_LEGACY != 2685 session_entry->htOperMode) && 2686 (eSIR_HT_OP_MODE_MIXED != 2687 session_entry->htOperMode)) { 2688 session_entry->htOperMode = 2689 eSIR_HT_OP_MODE_OVERLAP_LEGACY; 2690 } 2691 /* 2692 * CR-263021: OBSS bit is not switching back to 0 after 2693 * disabling the overlapping legacy BSS 2694 */ 2695 /* 2696 * This fixes issue of OBSS bit not set after 11b, 11g 2697 * station leaves 2698 */ 2699 lim_enable_ht_rifs_protection(mac_ctx, true, 2700 overlap, beaconparams, session_entry); 2701 /* 2702 * Not processing OBSS bit from other APs, as we are 2703 * already taking care of Protection from overlapping 2704 * BSS based on erp IE or useProtection bit 2705 */ 2706 lim_enable_ht_obss_protection(mac_ctx, true, 2707 overlap, beaconparams, session_entry); 2708 } 2709 } else if (LIM_IS_AP_ROLE(session_entry) && !overlap) { 2710 session_entry->gLim11bParams.protectionEnabled = true; 2711 pe_debug("protection from 11b is enabled"); 2712 if (true == session_entry->htCapability) { 2713 if (eSIR_HT_OP_MODE_MIXED != 2714 session_entry->htOperMode) { 2715 session_entry->htOperMode = 2716 eSIR_HT_OP_MODE_MIXED; 2717 lim_enable_ht_rifs_protection(mac_ctx, 2718 true, overlap, beaconparams, 2719 session_entry); 2720 lim_enable_ht_obss_protection(mac_ctx, 2721 true, overlap, beaconparams, 2722 session_entry); 2723 } 2724 } 2725 } 2726 2727 /* This part is common for staiton as well. */ 2728 if (false == session_entry->beaconParams.llbCoexist) { 2729 pe_debug("=> 11G Protection Enabled"); 2730 beaconparams->llbCoexist = 2731 session_entry->beaconParams.llbCoexist = true; 2732 beaconparams->paramChangeBitmap |= 2733 PARAM_llBCOEXIST_CHANGED; 2734 } 2735 } 2736 2737 /** 2738 * lim_handle_11g_protection_for_11bcoexist() - 11g protection for 11b co-ex 2739 * @mac_ctx: pointer to Globale Mac structure 2740 * @beaconparams: pointer to tpUpdateBeaconParams 2741 * @overlap: 1=> called from overlap context, 0 => called from assoc context. 2742 * @session_entry: pointer to struct pe_session * 2743 * 2744 * Function handles 11g protection for 11b co-exist 2745 * 2746 * Return: none 2747 */ 2748 static void 2749 lim_handle_11g_protection_for_11bcoexist(struct mac_context *mac_ctx, 2750 tpUpdateBeaconParams beaconparams, 2751 uint8_t overlap, struct pe_session *session_entry) 2752 { 2753 /* 2754 * For AP role: 2755 * we need to take care of HT OP mode change if needed. 2756 * We need to take care of Overlap cases. 2757 */ 2758 if (LIM_IS_AP_ROLE(session_entry) && overlap) { 2759 /* Overlap Legacy protection disabled. */ 2760 session_entry->gLimOlbcParams.protectionEnabled = false; 2761 2762 /* We need to take care of HT OP mode if we are HT AP. */ 2763 if (session_entry->htCapability) { 2764 /* 2765 * no HT op mode change if any of the overlap 2766 * protection enabled. 2767 */ 2768 if (!(session_entry->gLimOverlap11gParams. 2769 protectionEnabled || 2770 session_entry->gLimOverlapHt20Params. 2771 protectionEnabled || 2772 session_entry->gLimOverlapNonGfParams. 2773 protectionEnabled) && 2774 /* 2775 * Check if there is a need to change HT 2776 * OP mode. 2777 */ 2778 (eSIR_HT_OP_MODE_OVERLAP_LEGACY == 2779 session_entry->htOperMode)) { 2780 lim_enable_ht_rifs_protection(mac_ctx, false, 2781 overlap, beaconparams, session_entry); 2782 lim_enable_ht_obss_protection(mac_ctx, false, 2783 overlap, beaconparams, session_entry); 2784 if (session_entry->gLimHt20Params. 2785 protectionEnabled) { 2786 if (eHT_CHANNEL_WIDTH_20MHZ == 2787 session_entry->htSupportedChannelWidthSet) 2788 session_entry->htOperMode = 2789 eSIR_HT_OP_MODE_PURE; 2790 else 2791 session_entry->htOperMode = 2792 eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; 2793 } else 2794 session_entry->htOperMode = 2795 eSIR_HT_OP_MODE_PURE; 2796 } 2797 } 2798 } else if (LIM_IS_AP_ROLE(session_entry) && !overlap) { 2799 /* Disable protection from 11B stations. */ 2800 session_entry->gLim11bParams.protectionEnabled = false; 2801 pe_debug("===> 11B Protection Disabled"); 2802 /* Check if any other non-HT protection enabled. */ 2803 if (!session_entry->gLim11gParams.protectionEnabled) { 2804 /* Right now we are in HT OP Mixed mode. */ 2805 /* Change HT op mode appropriately. */ 2806 lim_enable_ht_obss_protection(mac_ctx, false, overlap, 2807 beaconparams, session_entry); 2808 /* 2809 * Change HT OP mode to 01 if any overlap protection 2810 * enabled 2811 */ 2812 if (session_entry->gLimOlbcParams.protectionEnabled || 2813 session_entry->gLimOverlap11gParams. 2814 protectionEnabled || 2815 session_entry->gLimOverlapHt20Params. 2816 protectionEnabled || 2817 session_entry->gLimOverlapNonGfParams. 2818 protectionEnabled) { 2819 session_entry->htOperMode = 2820 eSIR_HT_OP_MODE_OVERLAP_LEGACY; 2821 pe_debug("===> 11G Protection Disabled"); 2822 lim_enable_ht_rifs_protection(mac_ctx, true, 2823 overlap, beaconparams, 2824 session_entry); 2825 } else if (session_entry->gLimHt20Params. 2826 protectionEnabled) { 2827 /* Commenting because of CR 258588 WFA cert */ 2828 /* session_entry->htOperMode = 2829 eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; */ 2830 session_entry->htOperMode = 2831 eSIR_HT_OP_MODE_PURE; 2832 pe_debug("===> 11G Protection Disabled"); 2833 lim_enable_ht_rifs_protection(mac_ctx, false, 2834 overlap, beaconparams, 2835 session_entry); 2836 } else { 2837 session_entry->htOperMode = 2838 eSIR_HT_OP_MODE_PURE; 2839 lim_enable_ht_rifs_protection(mac_ctx, false, 2840 overlap, beaconparams, 2841 session_entry); 2842 } 2843 } 2844 } 2845 if (LIM_IS_AP_ROLE(session_entry)) { 2846 if (!session_entry->gLimOlbcParams.protectionEnabled && 2847 !session_entry->gLim11bParams.protectionEnabled) { 2848 pe_debug("===> 11G Protection Disabled"); 2849 beaconparams->llbCoexist = 2850 session_entry->beaconParams.llbCoexist = 2851 false; 2852 beaconparams->paramChangeBitmap |= 2853 PARAM_llBCOEXIST_CHANGED; 2854 } 2855 } 2856 /* For station role */ 2857 if (!LIM_IS_AP_ROLE(session_entry)) { 2858 pe_debug("===> 11G Protection Disabled"); 2859 beaconparams->llbCoexist = 2860 session_entry->beaconParams.llbCoexist = false; 2861 beaconparams->paramChangeBitmap |= 2862 PARAM_llBCOEXIST_CHANGED; 2863 } 2864 } 2865 2866 /** 2867 * lim_enable11g_protection() - Function to enable 11g protection 2868 * @mac_ctx: pointer to Global Mac structure 2869 * @enable: 1=> enable protection, 0=> disable protection. 2870 * @overlap: 1=> called from overlap context, 0 => called from assoc context. 2871 * @beaconparams: pointer to tpUpdateBeaconParams 2872 * @session_entry: pointer to struct pe_session * 2873 * 2874 * based on config setting enables\disables 11g protection. 2875 * 2876 * Return: Success - QDF_STATUS_SUCCESS - Success, Error number - Failure 2877 */ 2878 QDF_STATUS 2879 lim_enable11g_protection(struct mac_context *mac_ctx, uint8_t enable, 2880 uint8_t overlap, tpUpdateBeaconParams beaconparams, 2881 struct pe_session *session_entry) 2882 { 2883 2884 /* overlapping protection configuration check. */ 2885 if (!overlap) { 2886 /* normal protection config check */ 2887 if ((LIM_IS_AP_ROLE(session_entry)) && 2888 !session_entry->cfgProtection.fromllb) { 2889 /* protection disabled. */ 2890 pe_debug("protection from 11b is disabled"); 2891 return QDF_STATUS_SUCCESS; 2892 } else if (!LIM_IS_AP_ROLE(session_entry)) { 2893 if (!mac_ctx->lim.cfgProtection.fromllb) { 2894 /* protection disabled. */ 2895 pe_debug("protection from 11b is disabled"); 2896 return QDF_STATUS_SUCCESS; 2897 } 2898 } 2899 } 2900 2901 if (enable) { 2902 lim_handle_enable11g_protection_enabled(mac_ctx, beaconparams, 2903 overlap, session_entry); 2904 } else if (true == session_entry->beaconParams.llbCoexist) { 2905 lim_handle_11g_protection_for_11bcoexist(mac_ctx, beaconparams, 2906 overlap, session_entry); 2907 } 2908 return QDF_STATUS_SUCCESS; 2909 } 2910 2911 /** ------------------------------------------------------------- 2912 \fn lim_enable_ht_protection_from11g 2913 \brief based on cofig enables\disables protection from 11g. 2914 \param uint8_t enable : 1=> enable protection, 0=> disable protection. 2915 \param uint8_t overlap: 1=> called from overlap context, 0 => called from assoc context. 2916 \param tpUpdateBeaconParams pBeaconParams 2917 \return None 2918 -------------------------------------------------------------*/ 2919 QDF_STATUS 2920 lim_enable_ht_protection_from11g(struct mac_context *mac, uint8_t enable, 2921 uint8_t overlap, 2922 tpUpdateBeaconParams pBeaconParams, 2923 struct pe_session *pe_session) 2924 { 2925 if (!pe_session->htCapability) 2926 return QDF_STATUS_SUCCESS; /* protection from 11g is only for HT stations. */ 2927 2928 /* overlapping protection configuration check. */ 2929 if (overlap) { 2930 if ((LIM_IS_AP_ROLE(pe_session)) 2931 && (!pe_session->cfgProtection.overlapFromllg)) { 2932 /* protection disabled. */ 2933 pe_debug("overlap protection from 11g is disabled"); 2934 return QDF_STATUS_SUCCESS; 2935 } 2936 } else { 2937 /* normal protection config check */ 2938 if (LIM_IS_AP_ROLE(pe_session) && 2939 !pe_session->cfgProtection.fromllg) { 2940 /* protection disabled. */ 2941 pe_debug("protection from 11g is disabled"); 2942 return QDF_STATUS_SUCCESS; 2943 } else if (!LIM_IS_AP_ROLE(pe_session)) { 2944 if (!mac->lim.cfgProtection.fromllg) { 2945 /* protection disabled. */ 2946 pe_debug("protection from 11g is disabled"); 2947 return QDF_STATUS_SUCCESS; 2948 } 2949 } 2950 } 2951 if (enable) { 2952 /* If we are AP and HT capable, we need to set the HT OP mode */ 2953 /* appropriately. */ 2954 2955 if (LIM_IS_AP_ROLE(pe_session)) { 2956 if (overlap) { 2957 pe_session->gLimOverlap11gParams. 2958 protectionEnabled = true; 2959 /* 11g exists in overlap BSS. */ 2960 /* need not to change the operating mode to overlap_legacy */ 2961 /* if higher or same protection operating mode is enabled right now. */ 2962 if ((eSIR_HT_OP_MODE_OVERLAP_LEGACY != 2963 pe_session->htOperMode) 2964 && (eSIR_HT_OP_MODE_MIXED != 2965 pe_session->htOperMode)) { 2966 pe_session->htOperMode = 2967 eSIR_HT_OP_MODE_OVERLAP_LEGACY; 2968 } 2969 lim_enable_ht_rifs_protection(mac, true, overlap, 2970 pBeaconParams, 2971 pe_session); 2972 lim_enable_ht_obss_protection(mac, true, overlap, 2973 pBeaconParams, 2974 pe_session); 2975 } else { 2976 /* 11g is associated to an AP operating in 11n mode. */ 2977 /* Change the HT operating mode to 'mixed mode'. */ 2978 pe_session->gLim11gParams.protectionEnabled = 2979 true; 2980 if (eSIR_HT_OP_MODE_MIXED != 2981 pe_session->htOperMode) { 2982 pe_session->htOperMode = 2983 eSIR_HT_OP_MODE_MIXED; 2984 lim_enable_ht_rifs_protection(mac, true, 2985 overlap, 2986 pBeaconParams, 2987 pe_session); 2988 lim_enable_ht_obss_protection(mac, true, 2989 overlap, 2990 pBeaconParams, 2991 pe_session); 2992 } 2993 } 2994 } 2995 /* This part is common for staiton as well. */ 2996 if (false == pe_session->beaconParams.llgCoexist) { 2997 pBeaconParams->llgCoexist = 2998 pe_session->beaconParams.llgCoexist = true; 2999 pBeaconParams->paramChangeBitmap |= 3000 PARAM_llGCOEXIST_CHANGED; 3001 } else if (true == 3002 pe_session->gLimOverlap11gParams. 3003 protectionEnabled) { 3004 /* As operating mode changed after G station assoc some way to update beacon */ 3005 /* This addresses the issue of mode not changing to - 11 in beacon when OBSS overlap is enabled */ 3006 /* mac->sch.beacon_changed = 1; */ 3007 pBeaconParams->paramChangeBitmap |= 3008 PARAM_llGCOEXIST_CHANGED; 3009 } 3010 } else if (true == pe_session->beaconParams.llgCoexist) { 3011 /* for AP role. */ 3012 /* we need to take care of HT OP mode change if needed. */ 3013 /* We need to take care of Overlap cases. */ 3014 3015 if (LIM_IS_AP_ROLE(pe_session)) { 3016 if (overlap) { 3017 /* Overlap Legacy protection disabled. */ 3018 if (pe_session->gLim11gParams.numSta == 0) 3019 pe_session->gLimOverlap11gParams. 3020 protectionEnabled = false; 3021 3022 /* no HT op mode change if any of the overlap protection enabled. */ 3023 if (! 3024 (pe_session->gLimOlbcParams. 3025 protectionEnabled 3026 || pe_session->gLimOverlapHt20Params. 3027 protectionEnabled 3028 || pe_session->gLimOverlapNonGfParams. 3029 protectionEnabled)) { 3030 /* Check if there is a need to change HT OP mode. */ 3031 if (eSIR_HT_OP_MODE_OVERLAP_LEGACY == 3032 pe_session->htOperMode) { 3033 lim_enable_ht_rifs_protection(mac, 3034 false, 3035 overlap, 3036 pBeaconParams, 3037 pe_session); 3038 lim_enable_ht_obss_protection(mac, 3039 false, 3040 overlap, 3041 pBeaconParams, 3042 pe_session); 3043 3044 if (pe_session->gLimHt20Params.protectionEnabled) { 3045 if (eHT_CHANNEL_WIDTH_20MHZ == 3046 pe_session->htSupportedChannelWidthSet) 3047 pe_session->htOperMode = 3048 eSIR_HT_OP_MODE_PURE; 3049 else 3050 pe_session->htOperMode = 3051 eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; 3052 } else 3053 pe_session->htOperMode = 3054 eSIR_HT_OP_MODE_PURE; 3055 } 3056 } 3057 } else { 3058 /* Disable protection from 11G stations. */ 3059 pe_session->gLim11gParams.protectionEnabled = 3060 false; 3061 /* Check if any other non-HT protection enabled. */ 3062 if (!pe_session->gLim11bParams. 3063 protectionEnabled) { 3064 3065 /* Right now we are in HT OP Mixed mode. */ 3066 /* Change HT op mode appropriately. */ 3067 lim_enable_ht_obss_protection(mac, false, 3068 overlap, 3069 pBeaconParams, 3070 pe_session); 3071 3072 /* Change HT OP mode to 01 if any overlap protection enabled */ 3073 if (pe_session->gLimOlbcParams. 3074 protectionEnabled 3075 || pe_session-> 3076 gLimOverlap11gParams. 3077 protectionEnabled 3078 || pe_session-> 3079 gLimOverlapHt20Params. 3080 protectionEnabled 3081 || pe_session-> 3082 gLimOverlapNonGfParams. 3083 protectionEnabled) { 3084 pe_session->htOperMode = 3085 eSIR_HT_OP_MODE_OVERLAP_LEGACY; 3086 lim_enable_ht_rifs_protection(mac, 3087 true, 3088 overlap, 3089 pBeaconParams, 3090 pe_session); 3091 } else if (pe_session-> 3092 gLimHt20Params. 3093 protectionEnabled) { 3094 /* Commenting because of CR 258588 WFA cert */ 3095 /* pe_session->htOperMode = eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; */ 3096 pe_session->htOperMode = 3097 eSIR_HT_OP_MODE_PURE; 3098 lim_enable_ht_rifs_protection(mac, 3099 false, 3100 overlap, 3101 pBeaconParams, 3102 pe_session); 3103 } else { 3104 pe_session->htOperMode = 3105 eSIR_HT_OP_MODE_PURE; 3106 lim_enable_ht_rifs_protection(mac, 3107 false, 3108 overlap, 3109 pBeaconParams, 3110 pe_session); 3111 } 3112 } 3113 } 3114 if (!pe_session->gLimOverlap11gParams. 3115 protectionEnabled 3116 && !pe_session->gLim11gParams. 3117 protectionEnabled) { 3118 pe_debug("===> Protection from 11G Disabled"); 3119 pBeaconParams->llgCoexist = 3120 pe_session->beaconParams.llgCoexist = 3121 false; 3122 pBeaconParams->paramChangeBitmap |= 3123 PARAM_llGCOEXIST_CHANGED; 3124 } 3125 } 3126 /* for station role */ 3127 else { 3128 pe_debug("===> Protection from 11G Disabled"); 3129 pBeaconParams->llgCoexist = 3130 pe_session->beaconParams.llgCoexist = false; 3131 pBeaconParams->paramChangeBitmap |= 3132 PARAM_llGCOEXIST_CHANGED; 3133 } 3134 } 3135 return QDF_STATUS_SUCCESS; 3136 } 3137 3138 /* FIXME_PROTECTION : need to check for no APSD whenever we want to enable this protection. */ 3139 /* This check will be done at the caller. */ 3140 3141 /** ------------------------------------------------------------- 3142 \fn limEnableHtObssProtection 3143 \brief based on cofig enables\disables obss protection. 3144 \param uint8_t enable : 1=> enable protection, 0=> disable protection. 3145 \param uint8_t overlap: 1=> called from overlap context, 0 => called from assoc context. 3146 \param tpUpdateBeaconParams pBeaconParams 3147 \return None 3148 -------------------------------------------------------------*/ 3149 QDF_STATUS 3150 lim_enable_ht_obss_protection(struct mac_context *mac, uint8_t enable, 3151 uint8_t overlap, tpUpdateBeaconParams pBeaconParams, 3152 struct pe_session *pe_session) 3153 { 3154 3155 if (!pe_session->htCapability) 3156 return QDF_STATUS_SUCCESS; /* this protection is only for HT stations. */ 3157 3158 /* overlapping protection configuration check. */ 3159 if (overlap) { 3160 /* overlapping protection configuration check. */ 3161 } else { 3162 /* normal protection config check */ 3163 if ((LIM_IS_AP_ROLE(pe_session)) && 3164 !pe_session->cfgProtection.obss) { /* ToDo Update this field */ 3165 /* protection disabled. */ 3166 pe_debug("protection from Obss is disabled"); 3167 return QDF_STATUS_SUCCESS; 3168 } else if (!LIM_IS_AP_ROLE(pe_session)) { 3169 if (!mac->lim.cfgProtection.obss) { /* ToDo Update this field */ 3170 /* protection disabled. */ 3171 pe_debug("protection from Obss is disabled"); 3172 return QDF_STATUS_SUCCESS; 3173 } 3174 } 3175 } 3176 3177 if (LIM_IS_AP_ROLE(pe_session)) { 3178 if ((enable) 3179 && (false == pe_session->beaconParams.gHTObssMode)) { 3180 pe_debug("=>obss protection enabled"); 3181 pe_session->beaconParams.gHTObssMode = true; 3182 pBeaconParams->paramChangeBitmap |= PARAM_OBSS_MODE_CHANGED; /* UPDATE AN ENUM FOR OBSS MODE <todo> */ 3183 3184 } else if (!enable 3185 && (true == 3186 pe_session->beaconParams.gHTObssMode)) { 3187 pe_debug("===> obss Protection disabled"); 3188 pe_session->beaconParams.gHTObssMode = false; 3189 pBeaconParams->paramChangeBitmap |= 3190 PARAM_OBSS_MODE_CHANGED; 3191 3192 } 3193 /* CR-263021: OBSS bit is not switching back to 0 after disabling the overlapping legacy BSS */ 3194 if (!enable && !overlap) { 3195 pe_session->gLimOverlap11gParams.protectionEnabled = 3196 false; 3197 } 3198 } else { 3199 if ((enable) 3200 && (false == pe_session->beaconParams.gHTObssMode)) { 3201 pe_debug("=>obss protection enabled"); 3202 pe_session->beaconParams.gHTObssMode = true; 3203 pBeaconParams->paramChangeBitmap |= PARAM_OBSS_MODE_CHANGED; /* UPDATE AN ENUM FOR OBSS MODE <todo> */ 3204 3205 } else if (!enable 3206 && (true == 3207 pe_session->beaconParams.gHTObssMode)) { 3208 pe_debug("===> obss Protection disabled"); 3209 pe_session->beaconParams.gHTObssMode = false; 3210 pBeaconParams->paramChangeBitmap |= 3211 PARAM_OBSS_MODE_CHANGED; 3212 3213 } 3214 } 3215 return QDF_STATUS_SUCCESS; 3216 } 3217 3218 /** 3219 * lim_handle_ht20protection_enabled() - Handle ht20 protection enabled 3220 * @mac_ctx: pointer to Gloal Mac Structure 3221 * @overlap: variable for overlap detection 3222 * @beaconparams: pointer to tpUpdateBeaconParams 3223 * @session_entry: pointer to struct pe_session * 3224 * 3225 * Function handles ht20 protection enabled 3226 * 3227 * Return: none 3228 */ 3229 static void lim_handle_ht20protection_enabled(struct mac_context *mac_ctx, 3230 uint8_t overlap, tpUpdateBeaconParams beaconparams, 3231 struct pe_session *session_entry) 3232 { 3233 /* 3234 * If we are AP and HT capable, we need to set the HT OP mode 3235 * appropriately. 3236 */ 3237 if (LIM_IS_AP_ROLE(session_entry) && overlap) { 3238 session_entry->gLimOverlapHt20Params.protectionEnabled = true; 3239 if ((eSIR_HT_OP_MODE_OVERLAP_LEGACY != 3240 session_entry->htOperMode) && 3241 (eSIR_HT_OP_MODE_MIXED != 3242 session_entry->htOperMode)) { 3243 session_entry->htOperMode = 3244 eSIR_HT_OP_MODE_OVERLAP_LEGACY; 3245 lim_enable_ht_rifs_protection(mac_ctx, true, 3246 overlap, beaconparams, session_entry); 3247 } 3248 } else if (LIM_IS_AP_ROLE(session_entry) && !overlap) { 3249 session_entry->gLimHt20Params.protectionEnabled = true; 3250 if (eSIR_HT_OP_MODE_PURE == session_entry->htOperMode) { 3251 if (session_entry->htSupportedChannelWidthSet != 3252 eHT_CHANNEL_WIDTH_20MHZ) 3253 session_entry->htOperMode = 3254 eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; 3255 lim_enable_ht_rifs_protection(mac_ctx, false, 3256 overlap, beaconparams, session_entry); 3257 lim_enable_ht_obss_protection(mac_ctx, false, 3258 overlap, beaconparams, session_entry); 3259 } 3260 } 3261 /* This part is common for staiton as well. */ 3262 if (false == session_entry->beaconParams.ht20Coexist) { 3263 pe_debug("=> Protection from HT20 Enabled"); 3264 beaconparams->ht20MhzCoexist = 3265 session_entry->beaconParams.ht20Coexist = true; 3266 beaconparams->paramChangeBitmap |= 3267 PARAM_HT20MHZCOEXIST_CHANGED; 3268 } 3269 } 3270 3271 /** 3272 * lim_handle_ht20coexist_ht20protection() - ht20 protection for ht20 coexist 3273 * @mac_ctx: pointer to Gloal Mac Structure 3274 * @beaconparams: pointer to tpUpdateBeaconParams 3275 * @session_entry: pointer to struct pe_session * 3276 * @overlap: variable for overlap detection 3277 * 3278 * Function handles ht20 protection for ht20 coexist 3279 * 3280 * Return: none 3281 */ 3282 static void lim_handle_ht20coexist_ht20protection(struct mac_context *mac_ctx, 3283 tpUpdateBeaconParams beaconparams, 3284 struct pe_session *session_entry, uint8_t overlap) 3285 { 3286 /* 3287 * For AP role: 3288 * we need to take care of HT OP mode change if needed. 3289 * We need to take care of Overlap cases. 3290 */ 3291 if (LIM_IS_AP_ROLE(session_entry) && overlap) { 3292 /* Overlap Legacy protection disabled. */ 3293 session_entry->gLimOverlapHt20Params.protectionEnabled = 3294 false; 3295 /* 3296 * no HT op mode change if any of the overlap 3297 * protection enabled. 3298 */ 3299 if (!(session_entry->gLimOlbcParams.protectionEnabled || 3300 session_entry->gLimOverlap11gParams.protectionEnabled || 3301 session_entry->gLimOverlapHt20Params.protectionEnabled 3302 || session_entry->gLimOverlapNonGfParams. 3303 protectionEnabled) && 3304 /* 3305 * Check if there is a need to change HT 3306 * OP mode. 3307 */ 3308 (eSIR_HT_OP_MODE_OVERLAP_LEGACY == 3309 session_entry->htOperMode)) { 3310 if (session_entry->gLimHt20Params. 3311 protectionEnabled) { 3312 if (eHT_CHANNEL_WIDTH_20MHZ == 3313 session_entry-> 3314 htSupportedChannelWidthSet) 3315 session_entry->htOperMode = 3316 eSIR_HT_OP_MODE_PURE; 3317 else 3318 session_entry->htOperMode = 3319 eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; 3320 3321 lim_enable_ht_rifs_protection(mac_ctx, 3322 false, overlap, beaconparams, 3323 session_entry); 3324 lim_enable_ht_obss_protection(mac_ctx, 3325 false, overlap, beaconparams, 3326 session_entry); 3327 } else { 3328 session_entry->htOperMode = 3329 eSIR_HT_OP_MODE_PURE; 3330 } 3331 } 3332 } else if (LIM_IS_AP_ROLE(session_entry) && !overlap) { 3333 /* Disable protection from 11G stations. */ 3334 session_entry->gLimHt20Params.protectionEnabled = false; 3335 /* Change HT op mode appropriately. */ 3336 if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT == 3337 session_entry->htOperMode) { 3338 session_entry->htOperMode = 3339 eSIR_HT_OP_MODE_PURE; 3340 lim_enable_ht_rifs_protection(mac_ctx, false, 3341 overlap, beaconparams, session_entry); 3342 lim_enable_ht_obss_protection(mac_ctx, false, 3343 overlap, beaconparams, session_entry); 3344 } 3345 } 3346 if (LIM_IS_AP_ROLE(session_entry)) { 3347 pe_debug("===> Protection from HT 20 Disabled"); 3348 beaconparams->ht20MhzCoexist = 3349 session_entry->beaconParams.ht20Coexist = false; 3350 beaconparams->paramChangeBitmap |= 3351 PARAM_HT20MHZCOEXIST_CHANGED; 3352 } 3353 if (!LIM_IS_AP_ROLE(session_entry)) { 3354 /* For station role */ 3355 pe_debug("===> Protection from HT20 Disabled"); 3356 beaconparams->ht20MhzCoexist = 3357 session_entry->beaconParams.ht20Coexist = false; 3358 beaconparams->paramChangeBitmap |= 3359 PARAM_HT20MHZCOEXIST_CHANGED; 3360 } 3361 } 3362 3363 /** 3364 * lim_enable_ht20_protection() - Function to enable ht20 protection 3365 * @mac_ctx: pointer to Global Mac structure 3366 * @enable: 1=> enable protection, 0=> disable protection. 3367 * @overlap: 1=> called from overlap context, 0 => called from assoc context. 3368 * @beaconparams: pointer to tpUpdateBeaconParams 3369 * @session_entry: pointer to struct pe_session * 3370 * 3371 * based on cofig enables\disables protection from Ht20 3372 * 3373 * Return: 0 - success 3374 */ 3375 QDF_STATUS lim_enable_ht20_protection(struct mac_context *mac_ctx, uint8_t enable, 3376 uint8_t overlap, tpUpdateBeaconParams beaconparams, 3377 struct pe_session *session_entry) 3378 { 3379 /* This protection is only for HT stations. */ 3380 if (!session_entry->htCapability) 3381 return QDF_STATUS_SUCCESS; 3382 3383 /* overlapping protection configuration check. */ 3384 if (!overlap) { 3385 /* normal protection config check */ 3386 if ((LIM_IS_AP_ROLE(session_entry)) && 3387 !session_entry->cfgProtection.ht20) { 3388 /* protection disabled. */ 3389 pe_debug("protection from HT20 is disabled"); 3390 return QDF_STATUS_SUCCESS; 3391 } else if (!LIM_IS_AP_ROLE(session_entry)) { 3392 if (!mac_ctx->lim.cfgProtection.ht20) { 3393 /* protection disabled. */ 3394 pe_debug("protection from HT20 is disabled"); 3395 return QDF_STATUS_SUCCESS; 3396 } 3397 } 3398 } 3399 3400 if (enable) 3401 lim_handle_ht20protection_enabled(mac_ctx, overlap, 3402 beaconparams, session_entry); 3403 else if (true == session_entry->beaconParams.ht20Coexist) 3404 lim_handle_ht20coexist_ht20protection(mac_ctx, beaconparams, 3405 session_entry, overlap); 3406 3407 return QDF_STATUS_SUCCESS; 3408 } 3409 3410 /** ------------------------------------------------------------- 3411 \fn lim_enable_ht_non_gf_protection 3412 \brief based on cofig enables\disables protection from NonGf. 3413 \param uint8_t enable : 1=> enable protection, 0=> disable protection. 3414 \param uint8_t overlap: 1=> called from overlap context, 0 => called from assoc context. 3415 \param tpUpdateBeaconParams pBeaconParams 3416 \return None 3417 -------------------------------------------------------------*/ 3418 QDF_STATUS 3419 lim_enable_ht_non_gf_protection(struct mac_context *mac, uint8_t enable, 3420 uint8_t overlap, tpUpdateBeaconParams pBeaconParams, 3421 struct pe_session *pe_session) 3422 { 3423 if (!pe_session->htCapability) 3424 return QDF_STATUS_SUCCESS; /* this protection is only for HT stations. */ 3425 3426 /* overlapping protection configuration check. */ 3427 if (overlap) { 3428 } else { 3429 /* normal protection config check */ 3430 if (LIM_IS_AP_ROLE(pe_session) && 3431 !pe_session->cfgProtection.nonGf) { 3432 /* protection disabled. */ 3433 pe_debug("protection from NonGf is disabled"); 3434 return QDF_STATUS_SUCCESS; 3435 } else if (!LIM_IS_AP_ROLE(pe_session)) { 3436 /* normal protection config check */ 3437 if (!mac->lim.cfgProtection.nonGf) { 3438 /* protection disabled. */ 3439 pe_debug("protection from NonGf is disabled"); 3440 return QDF_STATUS_SUCCESS; 3441 } 3442 } 3443 } 3444 if (LIM_IS_AP_ROLE(pe_session)) { 3445 if ((enable) 3446 && (false == pe_session->beaconParams.llnNonGFCoexist)) { 3447 pe_debug(" => Protection from non GF Enabled"); 3448 pBeaconParams->llnNonGFCoexist = 3449 pe_session->beaconParams.llnNonGFCoexist = true; 3450 pBeaconParams->paramChangeBitmap |= 3451 PARAM_NON_GF_DEVICES_PRESENT_CHANGED; 3452 } else if (!enable 3453 && (true == 3454 pe_session->beaconParams.llnNonGFCoexist)) { 3455 pe_debug("===> Protection from Non GF Disabled"); 3456 pBeaconParams->llnNonGFCoexist = 3457 pe_session->beaconParams.llnNonGFCoexist = false; 3458 pBeaconParams->paramChangeBitmap |= 3459 PARAM_NON_GF_DEVICES_PRESENT_CHANGED; 3460 } 3461 } else { 3462 if ((enable) 3463 && (false == pe_session->beaconParams.llnNonGFCoexist)) { 3464 pe_debug(" => Protection from non GF Enabled"); 3465 pBeaconParams->llnNonGFCoexist = 3466 pe_session->beaconParams.llnNonGFCoexist = true; 3467 pBeaconParams->paramChangeBitmap |= 3468 PARAM_NON_GF_DEVICES_PRESENT_CHANGED; 3469 } else if (!enable 3470 && (true == 3471 pe_session->beaconParams.llnNonGFCoexist)) { 3472 pe_debug("===> Protection from Non GF Disabled"); 3473 pBeaconParams->llnNonGFCoexist = 3474 pe_session->beaconParams.llnNonGFCoexist = false; 3475 pBeaconParams->paramChangeBitmap |= 3476 PARAM_NON_GF_DEVICES_PRESENT_CHANGED; 3477 } 3478 } 3479 3480 return QDF_STATUS_SUCCESS; 3481 } 3482 3483 /** ------------------------------------------------------------- 3484 \fn lim_enable_ht_lsig_txop_protection 3485 \brief based on cofig enables\disables LsigTxop protection. 3486 \param uint8_t enable : 1=> enable protection, 0=> disable protection. 3487 \param uint8_t overlap: 1=> called from overlap context, 0 => called from assoc context. 3488 \param tpUpdateBeaconParams pBeaconParams 3489 \return None 3490 -------------------------------------------------------------*/ 3491 QDF_STATUS 3492 lim_enable_ht_lsig_txop_protection(struct mac_context *mac, uint8_t enable, 3493 uint8_t overlap, 3494 tpUpdateBeaconParams pBeaconParams, 3495 struct pe_session *pe_session) 3496 { 3497 if (!pe_session->htCapability) 3498 return QDF_STATUS_SUCCESS; /* this protection is only for HT stations. */ 3499 3500 /* overlapping protection configuration check. */ 3501 if (overlap) { 3502 } else { 3503 /* normal protection config check */ 3504 if (LIM_IS_AP_ROLE(pe_session) && 3505 !pe_session->cfgProtection.lsigTxop) { 3506 /* protection disabled. */ 3507 pe_debug("protection from LsigTxop not supported is disabled"); 3508 return QDF_STATUS_SUCCESS; 3509 } else if (!LIM_IS_AP_ROLE(pe_session)) { 3510 /* normal protection config check */ 3511 if (!mac->lim.cfgProtection.lsigTxop) { 3512 /* protection disabled. */ 3513 pe_debug("protection from LsigTxop not supported is disabled"); 3514 return QDF_STATUS_SUCCESS; 3515 } 3516 } 3517 } 3518 3519 if (LIM_IS_AP_ROLE(pe_session)) { 3520 if ((enable) 3521 && (false == 3522 pe_session->beaconParams. 3523 fLsigTXOPProtectionFullSupport)) { 3524 pe_debug(" => Protection from LsigTxop Enabled"); 3525 pBeaconParams->fLsigTXOPProtectionFullSupport = 3526 pe_session->beaconParams. 3527 fLsigTXOPProtectionFullSupport = true; 3528 pBeaconParams->paramChangeBitmap |= 3529 PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED; 3530 } else if (!enable 3531 && (true == 3532 pe_session->beaconParams. 3533 fLsigTXOPProtectionFullSupport)) { 3534 pe_debug("===> Protection from LsigTxop Disabled"); 3535 pBeaconParams->fLsigTXOPProtectionFullSupport = 3536 pe_session->beaconParams. 3537 fLsigTXOPProtectionFullSupport = false; 3538 pBeaconParams->paramChangeBitmap |= 3539 PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED; 3540 } 3541 } else { 3542 if ((enable) 3543 && (false == 3544 pe_session->beaconParams. 3545 fLsigTXOPProtectionFullSupport)) { 3546 pe_debug(" => Protection from LsigTxop Enabled"); 3547 pBeaconParams->fLsigTXOPProtectionFullSupport = 3548 pe_session->beaconParams. 3549 fLsigTXOPProtectionFullSupport = true; 3550 pBeaconParams->paramChangeBitmap |= 3551 PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED; 3552 } else if (!enable 3553 && (true == 3554 pe_session->beaconParams. 3555 fLsigTXOPProtectionFullSupport)) { 3556 pe_debug("===> Protection from LsigTxop Disabled"); 3557 pBeaconParams->fLsigTXOPProtectionFullSupport = 3558 pe_session->beaconParams. 3559 fLsigTXOPProtectionFullSupport = false; 3560 pBeaconParams->paramChangeBitmap |= 3561 PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED; 3562 } 3563 } 3564 return QDF_STATUS_SUCCESS; 3565 } 3566 3567 /* FIXME_PROTECTION : need to check for no APSD whenever we want to enable this protection. */ 3568 /* This check will be done at the caller. */ 3569 /** ------------------------------------------------------------- 3570 \fn lim_enable_ht_rifs_protection 3571 \brief based on cofig enables\disables Rifs protection. 3572 \param uint8_t enable : 1=> enable protection, 0=> disable protection. 3573 \param uint8_t overlap: 1=> called from overlap context, 0 => called from assoc context. 3574 \param tpUpdateBeaconParams pBeaconParams 3575 \return None 3576 -------------------------------------------------------------*/ 3577 QDF_STATUS 3578 lim_enable_ht_rifs_protection(struct mac_context *mac, uint8_t enable, 3579 uint8_t overlap, tpUpdateBeaconParams pBeaconParams, 3580 struct pe_session *pe_session) 3581 { 3582 if (!pe_session->htCapability) 3583 return QDF_STATUS_SUCCESS; /* this protection is only for HT stations. */ 3584 3585 /* overlapping protection configuration check. */ 3586 if (overlap) { 3587 } else { 3588 /* normal protection config check */ 3589 if (LIM_IS_AP_ROLE(pe_session) && 3590 !pe_session->cfgProtection.rifs) { 3591 /* protection disabled. */ 3592 pe_debug("protection from Rifs is disabled"); 3593 return QDF_STATUS_SUCCESS; 3594 } else if (!LIM_IS_AP_ROLE(pe_session)) { 3595 /* normal protection config check */ 3596 if (!mac->lim.cfgProtection.rifs) { 3597 /* protection disabled. */ 3598 pe_debug("protection from Rifs is disabled"); 3599 return QDF_STATUS_SUCCESS; 3600 } 3601 } 3602 } 3603 3604 if (LIM_IS_AP_ROLE(pe_session)) { 3605 /* Disabling the RIFS Protection means Enable the RIFS mode of operation in the BSS */ 3606 if ((!enable) 3607 && (false == pe_session->beaconParams.fRIFSMode)) { 3608 pe_debug(" => Rifs protection Disabled"); 3609 pBeaconParams->fRIFSMode = 3610 pe_session->beaconParams.fRIFSMode = true; 3611 pBeaconParams->paramChangeBitmap |= 3612 PARAM_RIFS_MODE_CHANGED; 3613 } 3614 /* Enabling the RIFS Protection means Disable the RIFS mode of operation in the BSS */ 3615 else if (enable 3616 && (true == pe_session->beaconParams.fRIFSMode)) { 3617 pe_debug("===> Rifs Protection Enabled"); 3618 pBeaconParams->fRIFSMode = 3619 pe_session->beaconParams.fRIFSMode = false; 3620 pBeaconParams->paramChangeBitmap |= 3621 PARAM_RIFS_MODE_CHANGED; 3622 } 3623 } else { 3624 /* Disabling the RIFS Protection means Enable the RIFS mode of operation in the BSS */ 3625 if ((!enable) 3626 && (false == pe_session->beaconParams.fRIFSMode)) { 3627 pe_debug(" => Rifs protection Disabled"); 3628 pBeaconParams->fRIFSMode = 3629 pe_session->beaconParams.fRIFSMode = true; 3630 pBeaconParams->paramChangeBitmap |= 3631 PARAM_RIFS_MODE_CHANGED; 3632 } 3633 /* Enabling the RIFS Protection means Disable the RIFS mode of operation in the BSS */ 3634 else if (enable 3635 && (true == pe_session->beaconParams.fRIFSMode)) { 3636 pe_debug("===> Rifs Protection Enabled"); 3637 pBeaconParams->fRIFSMode = 3638 pe_session->beaconParams.fRIFSMode = false; 3639 pBeaconParams->paramChangeBitmap |= 3640 PARAM_RIFS_MODE_CHANGED; 3641 } 3642 } 3643 return QDF_STATUS_SUCCESS; 3644 } 3645 3646 /* --------------------------------------------------------------------- */ 3647 /** 3648 * lim_enable_short_preamble 3649 * 3650 * FUNCTION: 3651 * Enable/Disable short preamble 3652 * 3653 * LOGIC: 3654 * 3655 * ASSUMPTIONS: 3656 * 3657 * NOTE: 3658 * 3659 * @param enable Flag to enable/disable short preamble 3660 * @return None 3661 */ 3662 3663 QDF_STATUS 3664 lim_enable_short_preamble(struct mac_context *mac, uint8_t enable, 3665 tpUpdateBeaconParams pBeaconParams, 3666 struct pe_session *pe_session) 3667 { 3668 if (!mac->mlme_cfg->ht_caps.short_preamble) 3669 return QDF_STATUS_SUCCESS; 3670 3671 /* 11G short preamble switching is disabled. */ 3672 if (!mac->mlme_cfg->feature_flags.enable_short_preamble_11g) 3673 return QDF_STATUS_SUCCESS; 3674 3675 if (LIM_IS_AP_ROLE(pe_session)) { 3676 if (enable && (pe_session->beaconParams.fShortPreamble == 0)) { 3677 pe_debug("===> Short Preamble Enabled"); 3678 pe_session->beaconParams.fShortPreamble = true; 3679 pBeaconParams->fShortPreamble = 3680 (uint8_t) pe_session->beaconParams. 3681 fShortPreamble; 3682 pBeaconParams->paramChangeBitmap |= 3683 PARAM_SHORT_PREAMBLE_CHANGED; 3684 } else if (!enable 3685 && (pe_session->beaconParams.fShortPreamble == 3686 1)) { 3687 pe_debug("===> Short Preamble Disabled"); 3688 pe_session->beaconParams.fShortPreamble = false; 3689 pBeaconParams->fShortPreamble = 3690 (uint8_t) pe_session->beaconParams. 3691 fShortPreamble; 3692 pBeaconParams->paramChangeBitmap |= 3693 PARAM_SHORT_PREAMBLE_CHANGED; 3694 } 3695 } 3696 3697 return QDF_STATUS_SUCCESS; 3698 } 3699 3700 /** 3701 * lim_tx_complete 3702 * 3703 * Function: 3704 * This is LIM's very own "TX MGMT frame complete" completion routine. 3705 * 3706 * Logic: 3707 * LIM wants to send a MGMT frame (broadcast or unicast) 3708 * LIM allocates memory using cds_packet_alloc( ..., **pData, **pPacket ) 3709 * LIM transmits the MGMT frame using the API: 3710 * wma_tx_frame( ... pPacket, ..., (void *) lim_tx_complete, pData ) 3711 * HDD, via wma_tx_frame/DXE, "transfers" the packet over to BMU 3712 * HDD, if it determines that a TX completion routine (in this case 3713 * lim_tx_complete) has been provided, will invoke this callback 3714 * LIM will try to free the TX MGMT packet that was earlier allocated, in order 3715 * to send this MGMT frame, using the PAL API cds_packet_free( ... pData, pPacket ) 3716 * 3717 * Assumptions: 3718 * Presently, this is ONLY being used for MGMT frames/packets 3719 * TODO: 3720 * Would it do good for LIM to have some sort of "signature" validation to 3721 * ensure that the pData argument passed in was a buffer that was actually 3722 * allocated by LIM and/or is not corrupted? 3723 * 3724 * Note: FIXME and TODO 3725 * Looks like cds_packet_free() is interested in pPacket. But, when this completion 3726 * routine is called, only pData is made available to LIM!! 3727 * 3728 * @param void A pointer to pData. Shouldn't it be pPacket?! 3729 * 3730 * @return QDF_STATUS_SUCCESS - in case of success 3731 */ 3732 QDF_STATUS lim_tx_complete(void *context, qdf_nbuf_t buf, bool free) 3733 { 3734 if (free) 3735 cds_packet_free((void *)buf); 3736 3737 return QDF_STATUS_SUCCESS; 3738 } 3739 3740 static QDF_STATUS 3741 lim_ht_switch_chnl_params(struct pe_session *pe_session) 3742 { 3743 uint8_t center_freq = 0; 3744 enum phy_ch_width ch_width = CH_WIDTH_20MHZ; 3745 struct mac_context *mac; 3746 uint8_t primary_channel; 3747 3748 mac = pe_session->mac_ctx; 3749 if (!mac) { 3750 pe_err("Invalid mac_ctx"); 3751 return QDF_STATUS_E_INVAL; 3752 } 3753 3754 primary_channel = wlan_reg_freq_to_chan(mac->pdev, 3755 pe_session->curr_op_freq); 3756 if (eHT_CHANNEL_WIDTH_40MHZ == 3757 pe_session->htRecommendedTxWidthSet) { 3758 ch_width = CH_WIDTH_40MHZ; 3759 if (PHY_DOUBLE_CHANNEL_LOW_PRIMARY == 3760 pe_session->htSecondaryChannelOffset) 3761 center_freq = primary_channel + 2; 3762 else if (PHY_DOUBLE_CHANNEL_HIGH_PRIMARY == 3763 pe_session->htSecondaryChannelOffset) 3764 center_freq = primary_channel - 2; 3765 else 3766 ch_width = CH_WIDTH_20MHZ; 3767 } 3768 pe_session->gLimChannelSwitch.primaryChannel = primary_channel; 3769 pe_session->curr_req_chan_freq = pe_session->curr_op_freq; 3770 pe_session->ch_center_freq_seg0 = center_freq; 3771 pe_session->gLimChannelSwitch.ch_center_freq_seg0 = center_freq; 3772 pe_session->gLimChannelSwitch.sw_target_freq = 3773 pe_session->curr_op_freq; 3774 pe_session->ch_width = ch_width; 3775 pe_session->gLimChannelSwitch.ch_width = ch_width; 3776 pe_session->gLimChannelSwitch.sec_ch_offset = 3777 pe_session->htSecondaryChannelOffset; 3778 pe_session->gLimChannelSwitch.ch_center_freq_seg1 = 0; 3779 3780 pe_debug("HT IE changed: Primary Channel: %d center chan: %d Channel Width: %d cur op freq %d", 3781 primary_channel, center_freq, 3782 pe_session->htRecommendedTxWidthSet, 3783 pe_session->gLimChannelSwitch.sw_target_freq); 3784 pe_session->channelChangeReasonCode = 3785 LIM_SWITCH_CHANNEL_HT_WIDTH; 3786 mac->lim.gpchangeChannelCallback = lim_switch_channel_cback; 3787 mac->lim.gpchangeChannelData = NULL; 3788 3789 return lim_send_switch_chnl_params(mac, pe_session); 3790 } 3791 3792 static void lim_ht_switch_chnl_req(struct pe_session *session) 3793 { 3794 struct mac_context *mac; 3795 QDF_STATUS status; 3796 3797 mac = session->mac_ctx; 3798 if (!mac) { 3799 pe_err("Invalid mac context"); 3800 return; 3801 } 3802 3803 session->channelChangeReasonCode = 3804 LIM_SWITCH_CHANNEL_HT_WIDTH; 3805 mlme_set_chan_switch_in_progress(session->vdev, true); 3806 status = wlan_vdev_mlme_sm_deliver_evt( 3807 session->vdev, 3808 WLAN_VDEV_SM_EV_FW_VDEV_RESTART, 3809 sizeof(*session), 3810 session); 3811 if (QDF_IS_STATUS_ERROR(status)) { 3812 pe_err("Failed to post WLAN_VDEV_SM_EV_FW_VDEV_RESTART for vdevid %d", 3813 session->smeSessionId); 3814 mlme_set_chan_switch_in_progress(session->vdev, false); 3815 } 3816 } 3817 3818 uint8_t lim_get_cb_mode_for_freq(struct mac_context *mac, 3819 struct pe_session *session, 3820 qdf_freq_t chan_freq) 3821 { 3822 uint8_t cb_mode = mac->roam.configParam.channelBondingMode5GHz; 3823 3824 if (WLAN_REG_IS_24GHZ_CH_FREQ(chan_freq)) { 3825 if (session->force_24ghz_in_ht20) { 3826 cb_mode = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; 3827 pe_debug_rl("vdev %d force 20 Mhz in 2.4 GHz", 3828 session->vdev_id); 3829 } else { 3830 cb_mode = mac->roam.configParam.channelBondingMode24GHz; 3831 } 3832 } 3833 3834 return cb_mode; 3835 } 3836 3837 static 3838 uint8_t lim_get_sta_cb_mode_for_24ghz(struct mac_context *mac, 3839 uint8_t vdev_id) 3840 { 3841 struct pe_session *session; 3842 uint8_t cb_mode = mac->roam.configParam.channelBondingMode24GHz; 3843 3844 session = pe_find_session_by_vdev_id(mac, vdev_id); 3845 if (!session || !session->force_24ghz_in_ht20) 3846 return cb_mode; 3847 3848 return WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; 3849 } 3850 3851 void lim_update_sta_run_time_ht_switch_chnl_params(struct mac_context *mac, 3852 tDot11fIEHTInfo *pHTInfo, 3853 struct pe_session *pe_session) 3854 { 3855 qdf_freq_t chan_freq; 3856 uint8_t cb_mode; 3857 3858 cb_mode = lim_get_cb_mode_for_freq(mac, pe_session, 3859 pe_session->curr_op_freq); 3860 3861 /* If self capability is set to '20Mhz only', then do not change the CB mode. */ 3862 if (cb_mode == WNI_CFG_CHANNEL_BONDING_MODE_DISABLE) { 3863 pe_debug_rl("self_cb_mode 0 for freq %d", 3864 pe_session->curr_op_freq); 3865 return; 3866 } 3867 3868 if (!wlan_cm_is_vdev_connected(pe_session->vdev)) { 3869 pe_debug_rl("vdev not connected, ignore HT IE BW update"); 3870 return; 3871 } 3872 3873 if (pe_session->ch_switch_in_progress == true) { 3874 pe_debug("ch switch is in progress, ignore HT IE BW update"); 3875 return; 3876 } 3877 chan_freq = wlan_reg_legacy_chan_to_freq(mac->pdev, 3878 pHTInfo->primaryChannel); 3879 3880 if (reg_is_chan_enum_invalid( 3881 wlan_reg_get_chan_enum_for_freq(chan_freq))) { 3882 pe_debug("Ignore Invalid channel in HT info"); 3883 return; 3884 } 3885 3886 /* If channel mismatch the CSA will take care of this change */ 3887 if (pHTInfo->primaryChannel != wlan_reg_freq_to_chan( 3888 mac->pdev, pe_session->curr_op_freq)) { 3889 pe_debug("Current channel doesn't match HT info ignore"); 3890 return; 3891 } 3892 3893 if (pe_session->htSecondaryChannelOffset != 3894 (uint8_t) pHTInfo->secondaryChannelOffset 3895 || pe_session->htRecommendedTxWidthSet != 3896 (uint8_t) pHTInfo->recommendedTxWidthSet) { 3897 pe_session->htSecondaryChannelOffset = 3898 (ePhyChanBondState) pHTInfo->secondaryChannelOffset; 3899 pe_session->htRecommendedTxWidthSet = 3900 (uint8_t) pHTInfo->recommendedTxWidthSet; 3901 pe_session->htSupportedChannelWidthSet = 3902 pe_session->htRecommendedTxWidthSet; 3903 3904 /* Before restarting vdev, delete the tdls peers */ 3905 lim_update_tdls_set_state_for_fw(pe_session, false); 3906 lim_delete_tdls_peers(mac, pe_session); 3907 3908 lim_ht_switch_chnl_req(pe_session); 3909 } 3910 3911 } /* End limUpdateStaRunTimeHTParams. */ 3912 3913 /** 3914 * \brief This function updates the lim global structure, if any of the 3915 * HT Capabilities have changed. 3916 * 3917 * 3918 * \param mac Pointer to Global MAC structure 3919 * 3920 * \param pHTCapability Pointer to HT Capability Information Element 3921 * obtained from a Beacon or Probe Response 3922 * 3923 * 3924 * 3925 */ 3926 3927 void lim_update_sta_run_time_ht_capability(struct mac_context *mac, 3928 tDot11fIEHTCaps *pHTCaps) 3929 { 3930 3931 if (mac->lim.gHTLsigTXOPProtection != 3932 (uint8_t) pHTCaps->lsigTXOPProtection) { 3933 mac->lim.gHTLsigTXOPProtection = 3934 (uint8_t) pHTCaps->lsigTXOPProtection; 3935 /* Send change notification to HAL */ 3936 } 3937 3938 if (mac->lim.gHTAMpduDensity != (uint8_t) pHTCaps->mpduDensity) { 3939 mac->lim.gHTAMpduDensity = (uint8_t) pHTCaps->mpduDensity; 3940 /* Send change notification to HAL */ 3941 } 3942 3943 if (mac->lim.gHTMaxRxAMpduFactor != 3944 (uint8_t) pHTCaps->maxRxAMPDUFactor) { 3945 mac->lim.gHTMaxRxAMpduFactor = 3946 (uint8_t) pHTCaps->maxRxAMPDUFactor; 3947 /* Send change notification to HAL */ 3948 } 3949 3950 } /* End lim_update_sta_run_time_ht_capability. */ 3951 3952 /** 3953 * \brief This function updates lim global structure, if any of the HT 3954 * Info Parameters have changed. 3955 * 3956 * 3957 * \param mac Pointer to the global MAC structure 3958 * 3959 * \param pHTInfo Pointer to the HT Info IE obtained from a Beacon or 3960 * Probe Response 3961 * 3962 * 3963 */ 3964 3965 void lim_update_sta_run_time_ht_info(struct mac_context *mac, 3966 tDot11fIEHTInfo *pHTInfo, 3967 struct pe_session *pe_session) 3968 { 3969 if (pe_session->htRecommendedTxWidthSet != 3970 (uint8_t) pHTInfo->recommendedTxWidthSet) { 3971 pe_session->htRecommendedTxWidthSet = 3972 (uint8_t) pHTInfo->recommendedTxWidthSet; 3973 /* Send change notification to HAL */ 3974 } 3975 3976 if (pe_session->beaconParams.fRIFSMode != 3977 (uint8_t) pHTInfo->rifsMode) { 3978 pe_session->beaconParams.fRIFSMode = 3979 (uint8_t) pHTInfo->rifsMode; 3980 /* Send change notification to HAL */ 3981 } 3982 3983 if (mac->lim.gHTServiceIntervalGranularity != 3984 (uint8_t) pHTInfo->serviceIntervalGranularity) { 3985 mac->lim.gHTServiceIntervalGranularity = 3986 (uint8_t) pHTInfo->serviceIntervalGranularity; 3987 /* Send change notification to HAL */ 3988 } 3989 3990 if (mac->lim.gHTOperMode != (tSirMacHTOperatingMode) pHTInfo->opMode) { 3991 mac->lim.gHTOperMode = 3992 (tSirMacHTOperatingMode) pHTInfo->opMode; 3993 /* Send change notification to HAL */ 3994 } 3995 3996 if (pe_session->beaconParams.llnNonGFCoexist != 3997 pHTInfo->nonGFDevicesPresent) { 3998 pe_session->beaconParams.llnNonGFCoexist = 3999 (uint8_t) pHTInfo->nonGFDevicesPresent; 4000 } 4001 4002 if (mac->lim.gHTSTBCBasicMCS != (uint8_t) pHTInfo->basicSTBCMCS) { 4003 mac->lim.gHTSTBCBasicMCS = (uint8_t) pHTInfo->basicSTBCMCS; 4004 /* Send change notification to HAL */ 4005 } 4006 4007 if (mac->lim.gHTDualCTSProtection != 4008 (uint8_t) pHTInfo->dualCTSProtection) { 4009 mac->lim.gHTDualCTSProtection = 4010 (uint8_t) pHTInfo->dualCTSProtection; 4011 /* Send change notification to HAL */ 4012 } 4013 4014 if (mac->lim.gHTSecondaryBeacon != (uint8_t) pHTInfo->secondaryBeacon) { 4015 mac->lim.gHTSecondaryBeacon = 4016 (uint8_t) pHTInfo->secondaryBeacon; 4017 /* Send change notification to HAL */ 4018 } 4019 4020 if (pe_session->beaconParams.fLsigTXOPProtectionFullSupport != 4021 (uint8_t) pHTInfo->lsigTXOPProtectionFullSupport) { 4022 pe_session->beaconParams.fLsigTXOPProtectionFullSupport = 4023 (uint8_t) pHTInfo->lsigTXOPProtectionFullSupport; 4024 /* Send change notification to HAL */ 4025 } 4026 4027 if (mac->lim.gHTPCOActive != (uint8_t) pHTInfo->pcoActive) { 4028 mac->lim.gHTPCOActive = (uint8_t) pHTInfo->pcoActive; 4029 /* Send change notification to HAL */ 4030 } 4031 4032 if (mac->lim.gHTPCOPhase != (uint8_t) pHTInfo->pcoPhase) { 4033 mac->lim.gHTPCOPhase = (uint8_t) pHTInfo->pcoPhase; 4034 /* Send change notification to HAL */ 4035 } 4036 4037 } /* End lim_update_sta_run_time_ht_info. */ 4038 4039 /** 4040 * lim_validate_delts_req() - This function validates DelTs req 4041 * @mac_ctx: pointer to Global Mac structure 4042 * @delts_req: pointer to delete traffic stream structure 4043 * @peer_mac_addr: variable for peer mac address 4044 * @session: pe session entry 4045 * 4046 * Function validates DelTs req originated by SME or by HAL and also 4047 * sends halMsg_DelTs to HAL 4048 * 4049 * Return: QDF_STATUS_SUCCESS - Success, QDF_STATUS_E_FAILURE - Failure 4050 */ 4051 4052 QDF_STATUS 4053 lim_validate_delts_req(struct mac_context *mac_ctx, tpSirDeltsReq delts_req, 4054 tSirMacAddr peer_mac_addr, 4055 struct pe_session *session) 4056 { 4057 tpDphHashNode sta; 4058 uint8_t ts_status; 4059 struct mac_ts_info *tsinfo; 4060 uint32_t i; 4061 uint8_t tspec_idx; 4062 4063 /* 4064 * if sta 4065 * - verify assoc state 4066 * - del tspec locally 4067 * if ap 4068 * - verify sta is in assoc state 4069 * - del sta tspec locally 4070 */ 4071 if (!delts_req) { 4072 pe_err("Delete TS request pointer is NULL"); 4073 return QDF_STATUS_E_FAILURE; 4074 } 4075 4076 if (LIM_IS_STA_ROLE(session)) { 4077 uint32_t val; 4078 4079 /* station always talks to the AP */ 4080 sta = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER, 4081 &session->dph.dphHashTable); 4082 4083 val = sizeof(tSirMacAddr); 4084 sir_copy_mac_addr(peer_mac_addr, session->bssId); 4085 4086 } else { 4087 uint16_t associd; 4088 uint8_t *macaddr = (uint8_t *) peer_mac_addr; 4089 4090 associd = delts_req->aid; 4091 if (associd != 0) 4092 sta = dph_get_hash_entry(mac_ctx, associd, 4093 &session->dph.dphHashTable); 4094 else 4095 sta = dph_lookup_hash_entry(mac_ctx, 4096 delts_req->macaddr.bytes, 4097 &associd, 4098 &session->dph. 4099 dphHashTable); 4100 4101 if (sta) 4102 /* TBD: check sta assoc state as well */ 4103 for (i = 0; i < sizeof(tSirMacAddr); i++) 4104 macaddr[i] = sta->staAddr[i]; 4105 } 4106 4107 if (!sta) { 4108 pe_err("Cannot find station context for delts req"); 4109 return QDF_STATUS_E_FAILURE; 4110 } 4111 4112 if ((!sta->valid) || 4113 (sta->mlmStaContext.mlmState != 4114 eLIM_MLM_LINK_ESTABLISHED_STATE)) { 4115 pe_err("Invalid Sta (or state) for DelTsReq"); 4116 return QDF_STATUS_E_FAILURE; 4117 } 4118 4119 delts_req->req.wsmTspecPresent = 0; 4120 delts_req->req.wmeTspecPresent = 0; 4121 delts_req->req.lleTspecPresent = 0; 4122 4123 if ((sta->wsmEnabled) && 4124 (delts_req->req.tspec.tsinfo.traffic.accessPolicy != 4125 SIR_MAC_ACCESSPOLICY_EDCA)) 4126 delts_req->req.wsmTspecPresent = 1; 4127 else if (sta->wmeEnabled) 4128 delts_req->req.wmeTspecPresent = 1; 4129 else if (sta->lleEnabled) 4130 delts_req->req.lleTspecPresent = 1; 4131 else { 4132 pe_warn("DELTS_REQ ignore - qos is disabled"); 4133 return QDF_STATUS_E_FAILURE; 4134 } 4135 4136 tsinfo = delts_req->req.wmeTspecPresent ? &delts_req->req.tspec.tsinfo 4137 : &delts_req->req.tsinfo; 4138 pe_debug("received DELTS_REQ message wmeTspecPresent: %d lleTspecPresent: %d wsmTspecPresent: %d tsid: %d up: %d direction: %d", 4139 delts_req->req.wmeTspecPresent, 4140 delts_req->req.lleTspecPresent, 4141 delts_req->req.wsmTspecPresent, tsinfo->traffic.tsid, 4142 tsinfo->traffic.userPrio, tsinfo->traffic.direction); 4143 4144 /* if no Access Control, ignore the request */ 4145 if (lim_admit_control_delete_ts(mac_ctx, sta->assocId, tsinfo, 4146 &ts_status, &tspec_idx) != QDF_STATUS_SUCCESS) { 4147 pe_err("DELTS request for sta assocId: %d tsid: %d up: %d", 4148 sta->assocId, tsinfo->traffic.tsid, 4149 tsinfo->traffic.userPrio); 4150 return QDF_STATUS_E_FAILURE; 4151 } else if ((tsinfo->traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_HCCA) 4152 || (tsinfo->traffic.accessPolicy == 4153 SIR_MAC_ACCESSPOLICY_BOTH)) { 4154 /* edca only now. */ 4155 } else if (tsinfo->traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_EDCA) { 4156 /* send message to HAL to delete TS */ 4157 if (QDF_STATUS_SUCCESS != 4158 lim_send_hal_msg_del_ts(mac_ctx, 4159 tspec_idx, delts_req->req, 4160 session->peSessionId, 4161 session->bssId)) { 4162 pe_warn("DelTs with UP: %d failed in lim_send_hal_msg_del_ts - ignoring request", 4163 tsinfo->traffic.userPrio); 4164 return QDF_STATUS_E_FAILURE; 4165 } 4166 } 4167 return QDF_STATUS_SUCCESS; 4168 } 4169 4170 /** 4171 * @function : lim_post_sm_state_update() 4172 * 4173 * @brief : This function Updates the HAL and Softmac about the change in the STA's SMPS state. 4174 * 4175 * LOGIC: 4176 * 4177 * ASSUMPTIONS: 4178 * NA 4179 * 4180 * NOTE: 4181 * NA 4182 * 4183 * @param mac - Pointer to Global MAC structure 4184 * @param limMsg - Lim Message structure object with the MimoPSparam in body 4185 * @return None 4186 */ 4187 QDF_STATUS 4188 lim_post_sm_state_update(struct mac_context *mac, 4189 tSirMacHTMIMOPowerSaveState state, 4190 uint8_t *pPeerStaMac, uint8_t sessionId) 4191 { 4192 QDF_STATUS retCode = QDF_STATUS_SUCCESS; 4193 struct scheduler_msg msgQ = {0}; 4194 tpSetMIMOPS pMIMO_PSParams; 4195 4196 msgQ.reserved = 0; 4197 msgQ.type = WMA_SET_MIMOPS_REQ; 4198 4199 /* Allocate for WMA_SET_MIMOPS_REQ */ 4200 pMIMO_PSParams = qdf_mem_malloc(sizeof(tSetMIMOPS)); 4201 if (!pMIMO_PSParams) 4202 return QDF_STATUS_E_NOMEM; 4203 4204 pMIMO_PSParams->htMIMOPSState = state; 4205 pMIMO_PSParams->fsendRsp = true; 4206 pMIMO_PSParams->sessionId = sessionId; 4207 qdf_mem_copy(pMIMO_PSParams->peerMac, pPeerStaMac, sizeof(tSirMacAddr)); 4208 4209 msgQ.bodyptr = pMIMO_PSParams; 4210 msgQ.bodyval = 0; 4211 4212 pe_debug("Sending WMA_SET_MIMOPS_REQ"); 4213 4214 MTRACE(mac_trace_msg_tx(mac, NO_SESSION, msgQ.type)); 4215 retCode = wma_post_ctrl_msg(mac, &msgQ); 4216 if (QDF_STATUS_SUCCESS != retCode) { 4217 pe_err("Posting WMA_SET_MIMOPS_REQ to HAL failed! Reason: %d", 4218 retCode); 4219 qdf_mem_free(pMIMO_PSParams); 4220 return retCode; 4221 } 4222 4223 return retCode; 4224 } 4225 4226 void lim_pkt_free(struct mac_context *mac, 4227 eFrameType frmType, uint8_t *pRxPacketInfo, void *pBody) 4228 { 4229 (void)mac; 4230 (void)frmType; 4231 (void)pRxPacketInfo; 4232 (void)pBody; 4233 } 4234 4235 /** 4236 * lim_get_b_dfrom_rx_packet() 4237 * 4238 ***FUNCTION: 4239 * This function is called to get pointer to Polaris 4240 * Buffer Descriptor containing MAC header & other control 4241 * info from the body of the message posted to LIM. 4242 * 4243 ***LOGIC: 4244 * NA 4245 * 4246 ***ASSUMPTIONS: 4247 * NA 4248 * 4249 ***NOTE: 4250 * NA 4251 * 4252 * @param body - Received message body 4253 * @param pRxPacketInfo - Pointer to received BD 4254 * @return None 4255 */ 4256 4257 void 4258 lim_get_b_dfrom_rx_packet(struct mac_context *mac, void *body, uint32_t **pRxPacketInfo) 4259 { 4260 *pRxPacketInfo = (uint32_t *) body; 4261 } /*** end lim_get_b_dfrom_rx_packet() ***/ 4262 4263 bool lim_is_channel_valid_for_channel_switch(struct mac_context *mac, 4264 uint32_t channel_freq) 4265 { 4266 bool ok = false; 4267 4268 if (policy_mgr_is_chan_ok_for_dnbs(mac->psoc, channel_freq, 4269 &ok)) { 4270 pe_err("policy_mgr_is_chan_ok_for_dnbs() returned error"); 4271 return false; 4272 } 4273 4274 if (!ok) { 4275 pe_debug("channel not ok for DNBS"); 4276 return false; 4277 } 4278 4279 if (wlan_reg_is_freq_enabled(mac->pdev, channel_freq, 4280 REG_CURRENT_PWR_MODE)) 4281 return true; 4282 4283 /* channel does not belong to list of valid channels */ 4284 return false; 4285 } 4286 4287 /** 4288 * @function : lim_restore_pre_channel_switch_state() 4289 * 4290 * @brief : This API is called by the user to undo any 4291 * specific changes done on the device during 4292 * channel switch. 4293 * LOGIC: 4294 * 4295 * ASSUMPTIONS: 4296 * NA 4297 * 4298 * NOTE: 4299 * NA 4300 * 4301 * @param mac - Pointer to Global MAC structure 4302 * @return None 4303 */ 4304 4305 QDF_STATUS 4306 lim_restore_pre_channel_switch_state(struct mac_context *mac, struct pe_session *pe_session) 4307 { 4308 4309 QDF_STATUS retCode = QDF_STATUS_SUCCESS; 4310 4311 if (!LIM_IS_STA_ROLE(pe_session)) 4312 return retCode; 4313 4314 /* Channel switch should be ready for the next time */ 4315 pe_session->gLimSpecMgmt.dot11hChanSwState = eLIM_11H_CHANSW_INIT; 4316 4317 return retCode; 4318 } 4319 4320 /** 4321 * @function: lim_prepare_for11h_channel_switch() 4322 * 4323 * @brief : This API is called by the user to prepare for 4324 * 11h channel switch. As of now, the API does 4325 * very minimal work. User can add more into the 4326 * same API if needed. 4327 * LOGIC: 4328 * 4329 * ASSUMPTIONS: 4330 * NA 4331 * 4332 * NOTE: 4333 * NA 4334 * 4335 * @param mac - Pointer to Global MAC structure 4336 * @param pe_session 4337 * @return None 4338 */ 4339 void 4340 lim_prepare_for11h_channel_switch(struct mac_context *mac, struct pe_session *pe_session) 4341 { 4342 if (!LIM_IS_STA_ROLE(pe_session)) 4343 return; 4344 4345 /* Flag to indicate 11h channel switch in progress */ 4346 pe_session->gLimSpecMgmt.dot11hChanSwState = eLIM_11H_CHANSW_RUNNING; 4347 4348 /** We are safe to switch channel at this point */ 4349 lim_stop_tx_and_switch_channel(mac, pe_session->peSessionId); 4350 } 4351 4352 tSirNwType lim_get_nw_type(struct mac_context *mac, uint32_t chan_freq, uint32_t type, 4353 tpSchBeaconStruct pBeacon) 4354 { 4355 tSirNwType nwType = eSIR_11B_NW_TYPE; 4356 4357 /* Logic to be cleaned up for 11AC & 11AX */ 4358 if (type == SIR_MAC_DATA_FRAME) { 4359 if (WLAN_REG_IS_24GHZ_CH_FREQ(chan_freq)) { 4360 nwType = eSIR_11G_NW_TYPE; 4361 } else { 4362 nwType = eSIR_11A_NW_TYPE; 4363 } 4364 } else { 4365 if (WLAN_REG_IS_24GHZ_CH_FREQ(chan_freq)) { 4366 int i; 4367 /* 11b or 11g packet */ 4368 /* 11g iff extended Rate IE is present or */ 4369 /* if there is an A rate in suppRate IE */ 4370 for (i = 0; i < pBeacon->supportedRates.numRates; i++) { 4371 if (sirIsArate 4372 (pBeacon->supportedRates.rate[i] & 0x7f)) { 4373 nwType = eSIR_11G_NW_TYPE; 4374 break; 4375 } 4376 } 4377 if (pBeacon->extendedRatesPresent) { 4378 nwType = eSIR_11G_NW_TYPE; 4379 } else if (pBeacon->HTInfo.present || 4380 IS_BSS_VHT_CAPABLE(pBeacon->VHTCaps)) { 4381 nwType = eSIR_11G_NW_TYPE; 4382 } 4383 } else { 4384 /* 11a packet */ 4385 nwType = eSIR_11A_NW_TYPE; 4386 } 4387 } 4388 return nwType; 4389 } 4390 4391 uint32_t lim_get_channel_from_beacon(struct mac_context *mac, tpSchBeaconStruct pBeacon) 4392 { 4393 uint8_t chan_freq = 0; 4394 4395 if (pBeacon->he_op.oper_info_6g_present) 4396 chan_freq = wlan_reg_chan_band_to_freq(mac->pdev, 4397 pBeacon->he_op.oper_info_6g.info.primary_ch, 4398 BIT(REG_BAND_6G)); 4399 else if (pBeacon->dsParamsPresent) 4400 chan_freq = pBeacon->chan_freq; 4401 else if (pBeacon->HTInfo.present) 4402 chan_freq = wlan_reg_legacy_chan_to_freq(mac->pdev, 4403 pBeacon->HTInfo.primaryChannel); 4404 else 4405 chan_freq = pBeacon->chan_freq; 4406 4407 return chan_freq; 4408 } 4409 4410 void lim_set_tspec_uapsd_mask_per_session(struct mac_context *mac, 4411 struct pe_session *pe_session, 4412 struct mac_ts_info *pTsInfo, 4413 uint32_t action) 4414 { 4415 uint8_t userPrio = (uint8_t) pTsInfo->traffic.userPrio; 4416 uint16_t direction = pTsInfo->traffic.direction; 4417 uint8_t ac = upToAc(userPrio); 4418 4419 pe_debug("Set UAPSD mask for AC: %d dir: %d action: %d" 4420 , ac, direction, action); 4421 4422 /* Converting AC to appropriate Uapsd Bit Mask 4423 * AC_BE(0) --> UAPSD_BITOFFSET_ACVO(3) 4424 * AC_BK(1) --> UAPSD_BITOFFSET_ACVO(2) 4425 * AC_VI(2) --> UAPSD_BITOFFSET_ACVO(1) 4426 * AC_VO(3) --> UAPSD_BITOFFSET_ACVO(0) 4427 */ 4428 ac = ((~ac) & 0x3); 4429 4430 if (action == CLEAR_UAPSD_MASK) { 4431 if (direction == SIR_MAC_DIRECTION_UPLINK) 4432 pe_session->gUapsdPerAcTriggerEnableMask &= 4433 ~(1 << ac); 4434 else if (direction == SIR_MAC_DIRECTION_DNLINK) 4435 pe_session->gUapsdPerAcDeliveryEnableMask &= 4436 ~(1 << ac); 4437 else if (direction == SIR_MAC_DIRECTION_BIDIR) { 4438 pe_session->gUapsdPerAcTriggerEnableMask &= 4439 ~(1 << ac); 4440 pe_session->gUapsdPerAcDeliveryEnableMask &= 4441 ~(1 << ac); 4442 } 4443 } else if (action == SET_UAPSD_MASK) { 4444 if (direction == SIR_MAC_DIRECTION_UPLINK) 4445 pe_session->gUapsdPerAcTriggerEnableMask |= 4446 (1 << ac); 4447 else if (direction == SIR_MAC_DIRECTION_DNLINK) 4448 pe_session->gUapsdPerAcDeliveryEnableMask |= 4449 (1 << ac); 4450 else if (direction == SIR_MAC_DIRECTION_BIDIR) { 4451 pe_session->gUapsdPerAcTriggerEnableMask |= 4452 (1 << ac); 4453 pe_session->gUapsdPerAcDeliveryEnableMask |= 4454 (1 << ac); 4455 } 4456 } 4457 4458 pe_debug("New pe_session->gUapsdPerAcTriggerEnableMask 0x%x pe_session->gUapsdPerAcDeliveryEnableMask 0x%x", 4459 pe_session->gUapsdPerAcTriggerEnableMask, 4460 pe_session->gUapsdPerAcDeliveryEnableMask); 4461 4462 return; 4463 } 4464 4465 /** 4466 * lim_handle_heart_beat_timeout_for_session() - Handle heart beat time out 4467 * @mac_ctx: pointer to Global Mac Structure 4468 * @psession_entry: pointer to struct pe_session * 4469 * 4470 * Function handles heart beat time out for session 4471 * 4472 * Return: none 4473 */ 4474 void lim_handle_heart_beat_timeout_for_session(struct mac_context *mac_ctx, 4475 struct pe_session *psession_entry) 4476 { 4477 if (psession_entry->valid) { 4478 if ((psession_entry->bssType == eSIR_INFRASTRUCTURE_MODE) && 4479 (LIM_IS_STA_ROLE(psession_entry))) 4480 lim_handle_heart_beat_failure(mac_ctx, psession_entry); 4481 } 4482 } 4483 4484 void lim_process_add_sta_rsp(struct mac_context *mac_ctx, 4485 struct scheduler_msg *msg) 4486 { 4487 struct pe_session *session; 4488 tpAddStaParams add_sta_params; 4489 4490 add_sta_params = (tpAddStaParams) msg->bodyptr; 4491 4492 session = pe_find_session_by_session_id(mac_ctx, 4493 add_sta_params->sessionId); 4494 if (!session) { 4495 pe_err("Session Does not exist for given sessionID"); 4496 qdf_mem_free(add_sta_params); 4497 return; 4498 } 4499 session->csaOffloadEnable = add_sta_params->csaOffloadEnable; 4500 if (LIM_IS_NDI_ROLE(session)) 4501 lim_ndp_add_sta_rsp(mac_ctx, session, msg->bodyptr); 4502 #ifdef FEATURE_WLAN_TDLS 4503 else if (add_sta_params->staType == STA_ENTRY_TDLS_PEER) 4504 lim_process_tdls_add_sta_rsp(mac_ctx, msg->bodyptr, session); 4505 #endif 4506 else 4507 lim_process_mlm_add_sta_rsp(mac_ctx, msg, session); 4508 4509 } 4510 4511 /** 4512 * lim_update_beacon() - This function updates beacon 4513 * @mac_ctx: pointer to Global Mac Structure 4514 * 4515 * This Function is invoked to update the beacon 4516 * 4517 * Return: none 4518 */ 4519 void lim_update_beacon(struct mac_context *mac_ctx) 4520 { 4521 uint8_t i; 4522 4523 for (i = 0; i < mac_ctx->lim.maxBssId; i++) { 4524 if (mac_ctx->lim.gpSession[i].valid != true) 4525 continue; 4526 if ((mac_ctx->lim.gpSession[i].limSystemRole == eLIM_AP_ROLE) 4527 && (eLIM_SME_NORMAL_STATE == 4528 mac_ctx->lim.gpSession[i].limSmeState)) { 4529 4530 sch_set_fixed_beacon_fields(mac_ctx, 4531 &mac_ctx->lim.gpSession[i]); 4532 4533 if (false == mac_ctx->sap.SapDfsInfo. 4534 is_dfs_cac_timer_running) 4535 lim_send_beacon_ind(mac_ctx, 4536 &mac_ctx->lim.gpSession[i], 4537 REASON_DEFAULT); 4538 } 4539 } 4540 } 4541 4542 struct pe_session *lim_is_ap_session_active(struct mac_context *mac) 4543 { 4544 uint8_t i; 4545 4546 for (i = 0; i < mac->lim.maxBssId; i++) { 4547 if (mac->lim.gpSession[i].valid && 4548 (mac->lim.gpSession[i].limSystemRole == eLIM_AP_ROLE)) 4549 return &mac->lim.gpSession[i]; 4550 } 4551 4552 return NULL; 4553 } 4554 4555 /**--------------------------------------------------------- 4556 \fn lim_handle_defer_msg_error 4557 \brief handles error scenario, when the msg can not be deferred. 4558 \param mac 4559 \param pLimMsg LIM msg, which could not be deferred. 4560 \return void 4561 -----------------------------------------------------------*/ 4562 4563 void lim_handle_defer_msg_error(struct mac_context *mac, 4564 struct scheduler_msg *pLimMsg) 4565 { 4566 if (SIR_BB_XPORT_MGMT_MSG == pLimMsg->type) { 4567 lim_decrement_pending_mgmt_count(mac); 4568 cds_pkt_return_packet((cds_pkt_t *) pLimMsg->bodyptr); 4569 pLimMsg->bodyptr = NULL; 4570 } else if (pLimMsg->bodyptr) { 4571 qdf_mem_free(pLimMsg->bodyptr); 4572 pLimMsg->bodyptr = NULL; 4573 } 4574 4575 } 4576 4577 #ifdef FEATURE_WLAN_DIAG_SUPPORT 4578 /**--------------------------------------------------------- 4579 \fn lim_diag_event_report 4580 \brief This function reports Diag event 4581 \param mac 4582 \param eventType 4583 \param bssid 4584 \param status 4585 \param reasonCode 4586 \return void 4587 -----------------------------------------------------------*/ 4588 void lim_diag_event_report(struct mac_context *mac, uint16_t eventType, 4589 struct pe_session *pe_session, uint16_t status, 4590 uint16_t reasonCode) 4591 { 4592 tSirMacAddr nullBssid = { 0, 0, 0, 0, 0, 0 }; 4593 4594 WLAN_HOST_DIAG_EVENT_DEF(peEvent, host_event_wlan_pe_payload_type); 4595 4596 qdf_mem_zero(&peEvent, sizeof(host_event_wlan_pe_payload_type)); 4597 4598 if (!pe_session) { 4599 qdf_mem_copy(peEvent.bssid, nullBssid, sizeof(tSirMacAddr)); 4600 peEvent.sme_state = (uint16_t) mac->lim.gLimSmeState; 4601 peEvent.mlm_state = (uint16_t) mac->lim.gLimMlmState; 4602 4603 } else { 4604 qdf_mem_copy(peEvent.bssid, pe_session->bssId, 4605 sizeof(tSirMacAddr)); 4606 peEvent.sme_state = (uint16_t) pe_session->limSmeState; 4607 peEvent.mlm_state = (uint16_t) pe_session->limMlmState; 4608 } 4609 peEvent.event_type = eventType; 4610 peEvent.status = status; 4611 peEvent.reason_code = reasonCode; 4612 4613 WLAN_HOST_DIAG_EVENT_REPORT(&peEvent, EVENT_WLAN_PE); 4614 return; 4615 } 4616 4617 static void lim_diag_fill_mgmt_event_report(struct mac_context *mac_ctx, 4618 tpSirMacMgmtHdr mac_hdr, 4619 struct pe_session *session, uint16_t result_code, 4620 uint16_t reason_code, 4621 struct host_event_wlan_mgmt_payload_type *mgmt_event) 4622 { 4623 uint8_t length; 4624 4625 qdf_mem_zero(mgmt_event, sizeof(*mgmt_event)); 4626 mgmt_event->mgmt_type = mac_hdr->fc.type; 4627 mgmt_event->mgmt_subtype = mac_hdr->fc.subType; 4628 qdf_mem_copy(mgmt_event->self_mac_addr, session->self_mac_addr, 4629 QDF_MAC_ADDR_SIZE); 4630 qdf_mem_copy(mgmt_event->bssid, mac_hdr->bssId, 4631 QDF_MAC_ADDR_SIZE); 4632 length = session->ssId.length; 4633 if (length > WLAN_SSID_MAX_LEN) 4634 length = WLAN_SSID_MAX_LEN; 4635 qdf_mem_copy(mgmt_event->ssid, session->ssId.ssId, length); 4636 mgmt_event->ssid_len = length; 4637 mgmt_event->operating_channel = wlan_reg_freq_to_chan( 4638 mac_ctx->pdev, session->curr_op_freq); 4639 mgmt_event->result_code = result_code; 4640 mgmt_event->reason_code = reason_code; 4641 } 4642 4643 void lim_diag_mgmt_tx_event_report(struct mac_context *mac_ctx, void *mgmt_hdr, 4644 struct pe_session *session, uint16_t result_code, 4645 uint16_t reason_code) 4646 { 4647 tpSirMacMgmtHdr mac_hdr = mgmt_hdr; 4648 4649 WLAN_HOST_DIAG_EVENT_DEF(mgmt_event, 4650 struct host_event_wlan_mgmt_payload_type); 4651 if (!session || !mac_hdr) { 4652 pe_err("not valid input"); 4653 return; 4654 } 4655 lim_diag_fill_mgmt_event_report(mac_ctx, mac_hdr, session, 4656 result_code, reason_code, &mgmt_event); 4657 4658 pe_debug("TX frame: type:%d sub_type:%d seq_num:%d ssid:" QDF_SSID_FMT " selfmacaddr:" QDF_MAC_ADDR_FMT " bssid:" QDF_MAC_ADDR_FMT " channel:%d", 4659 mgmt_event.mgmt_type, mgmt_event.mgmt_subtype, 4660 ((mac_hdr->seqControl.seqNumHi << 4) | 4661 mac_hdr->seqControl.seqNumLo), 4662 QDF_SSID_REF(mgmt_event.ssid_len, mgmt_event.ssid), 4663 QDF_MAC_ADDR_REF(mgmt_event.self_mac_addr), 4664 QDF_MAC_ADDR_REF(mgmt_event.bssid), 4665 mgmt_event.operating_channel); 4666 WLAN_HOST_DIAG_EVENT_REPORT(&mgmt_event, EVENT_WLAN_HOST_MGMT_TX_V2); 4667 } 4668 4669 void lim_diag_mgmt_rx_event_report(struct mac_context *mac_ctx, void *mgmt_hdr, 4670 struct pe_session *session, uint16_t result_code, 4671 uint16_t reason_code) 4672 { 4673 tpSirMacMgmtHdr mac_hdr = mgmt_hdr; 4674 4675 WLAN_HOST_DIAG_EVENT_DEF(mgmt_event, 4676 struct host_event_wlan_mgmt_payload_type); 4677 if (!session || !mac_hdr) { 4678 pe_debug("not valid input"); 4679 return; 4680 } 4681 lim_diag_fill_mgmt_event_report(mac_ctx, mac_hdr, session, 4682 result_code, reason_code, &mgmt_event); 4683 pe_debug("RX frame: type:%d sub_type:%d seq_num:%d ssid:" QDF_SSID_FMT " selfmacaddr:" QDF_MAC_ADDR_FMT " bssid:" QDF_MAC_ADDR_FMT " channel:%d", 4684 mgmt_event.mgmt_type, mgmt_event.mgmt_subtype, 4685 ((mac_hdr->seqControl.seqNumHi << 4) | 4686 mac_hdr->seqControl.seqNumLo), 4687 QDF_SSID_REF(mgmt_event.ssid_len, mgmt_event.ssid), 4688 QDF_MAC_ADDR_REF(mgmt_event.self_mac_addr), 4689 QDF_MAC_ADDR_REF(mgmt_event.bssid), 4690 mgmt_event.operating_channel); 4691 WLAN_HOST_DIAG_EVENT_REPORT(&mgmt_event, EVENT_WLAN_HOST_MGMT_RX_V2); 4692 } 4693 #endif /* FEATURE_WLAN_DIAG_SUPPORT */ 4694 4695 /* Returns length of P2P stream and Pointer ie passed to this function is filled with noa stream */ 4696 4697 uint8_t lim_build_p2p_ie(struct mac_context *mac, uint8_t *ie, uint8_t *data, 4698 uint8_t ie_len) 4699 { 4700 int length = 0; 4701 uint8_t *ptr = ie; 4702 4703 ptr[length++] = WLAN_ELEMID_VENDOR; 4704 ptr[length++] = ie_len + SIR_MAC_P2P_OUI_SIZE; 4705 qdf_mem_copy(&ptr[length], SIR_MAC_P2P_OUI, SIR_MAC_P2P_OUI_SIZE); 4706 qdf_mem_copy(&ptr[length + SIR_MAC_P2P_OUI_SIZE], data, ie_len); 4707 return ie_len + SIR_P2P_IE_HEADER_LEN; 4708 } 4709 4710 /* Returns length of NoA stream and Pointer pNoaStream passed to this function is filled with noa stream */ 4711 uint8_t lim_get_noa_attr_stream(struct mac_context *mac, uint8_t *pNoaStream, 4712 struct pe_session *pe_session) 4713 { 4714 uint8_t len = 0; 4715 4716 uint8_t *pBody = pNoaStream; 4717 4718 if ((pe_session) && (pe_session->valid) && 4719 (pe_session->opmode == QDF_P2P_GO_MODE)) { 4720 if ((!(pe_session->p2pGoPsUpdate.uNoa1Duration)) 4721 && (!(pe_session->p2pGoPsUpdate.uNoa2Duration)) 4722 && (!pe_session->p2pGoPsUpdate.oppPsFlag) 4723 ) 4724 return 0; /* No NoA Descriptor then return 0 */ 4725 4726 pBody[0] = SIR_P2P_NOA_ATTR; 4727 4728 pBody[3] = pe_session->p2pGoPsUpdate.index; 4729 pBody[4] = 4730 pe_session->p2pGoPsUpdate.ctWin | (pe_session-> 4731 p2pGoPsUpdate. 4732 oppPsFlag << 7); 4733 len = 5; 4734 pBody += len; 4735 4736 if (pe_session->p2pGoPsUpdate.uNoa1Duration) { 4737 *pBody = pe_session->p2pGoPsUpdate.uNoa1IntervalCnt; 4738 pBody += 1; 4739 len += 1; 4740 4741 *((uint32_t *) (pBody)) = 4742 sir_swap_u32if_needed(pe_session->p2pGoPsUpdate. 4743 uNoa1Duration); 4744 pBody += sizeof(uint32_t); 4745 len += 4; 4746 4747 *((uint32_t *) (pBody)) = 4748 sir_swap_u32if_needed(pe_session->p2pGoPsUpdate. 4749 uNoa1Interval); 4750 pBody += sizeof(uint32_t); 4751 len += 4; 4752 4753 *((uint32_t *) (pBody)) = 4754 sir_swap_u32if_needed(pe_session->p2pGoPsUpdate. 4755 uNoa1StartTime); 4756 pBody += sizeof(uint32_t); 4757 len += 4; 4758 4759 } 4760 4761 if (pe_session->p2pGoPsUpdate.uNoa2Duration) { 4762 *pBody = pe_session->p2pGoPsUpdate.uNoa2IntervalCnt; 4763 pBody += 1; 4764 len += 1; 4765 4766 *((uint32_t *) (pBody)) = 4767 sir_swap_u32if_needed(pe_session->p2pGoPsUpdate. 4768 uNoa2Duration); 4769 pBody += sizeof(uint32_t); 4770 len += 4; 4771 4772 *((uint32_t *) (pBody)) = 4773 sir_swap_u32if_needed(pe_session->p2pGoPsUpdate. 4774 uNoa2Interval); 4775 pBody += sizeof(uint32_t); 4776 len += 4; 4777 4778 *((uint32_t *) (pBody)) = 4779 sir_swap_u32if_needed(pe_session->p2pGoPsUpdate. 4780 uNoa2StartTime); 4781 pBody += sizeof(uint32_t); 4782 len += 4; 4783 4784 } 4785 4786 pBody = pNoaStream + 1; 4787 *((uint16_t *) (pBody)) = sir_swap_u16if_needed(len - 3); /*one byte for Attr and 2 bytes for length */ 4788 4789 return len; 4790 4791 } 4792 return 0; 4793 4794 } 4795 4796 void pe_set_resume_channel(struct mac_context *mac, uint16_t channel, 4797 ePhyChanBondState phyCbState) 4798 { 4799 4800 mac->lim.gResumeChannel = channel; 4801 mac->lim.gResumePhyCbState = phyCbState; 4802 } 4803 4804 bool lim_isconnected_on_dfs_freq(struct mac_context *mac_ctx, 4805 qdf_freq_t oper_freq) 4806 { 4807 /* Indoor channels are also marked DFS, therefore 4808 * check if the channel has REGULATORY_CHAN_RADAR 4809 * channel flag to identify if the channel is DFS 4810 */ 4811 if (wlan_reg_is_dfs_for_freq(mac_ctx->pdev, oper_freq)) 4812 return true; 4813 else 4814 return false; 4815 } 4816 4817 void lim_pmf_sa_query_timer_handler(void *pMacGlobal, uint32_t param) 4818 { 4819 struct mac_context *mac = (struct mac_context *) pMacGlobal; 4820 tPmfSaQueryTimerId timerId; 4821 struct pe_session *pe_session; 4822 tpDphHashNode pSta; 4823 uint8_t maxretries; 4824 4825 pe_debug("SA Query timer fires"); 4826 timerId.value = param; 4827 4828 /* Check that SA Query is in progress */ 4829 pe_session = pe_find_session_by_session_id(mac, 4830 timerId.fields.sessionId); 4831 if (!pe_session) { 4832 pe_err("Session does not exist for given session ID: %d", 4833 timerId.fields.sessionId); 4834 return; 4835 } 4836 pSta = dph_get_hash_entry(mac, timerId.fields.peerIdx, 4837 &pe_session->dph.dphHashTable); 4838 if (!pSta) { 4839 pe_err("Entry does not exist for given peer index: %d", 4840 timerId.fields.peerIdx); 4841 return; 4842 } 4843 if (DPH_SA_QUERY_IN_PROGRESS != pSta->pmfSaQueryState) 4844 return; 4845 4846 /* Increment the retry count, check if reached maximum */ 4847 maxretries = mac->mlme_cfg->gen.pmf_sa_query_max_retries; 4848 pSta->pmfSaQueryRetryCount++; 4849 if (pSta->pmfSaQueryRetryCount >= maxretries) { 4850 pe_err("SA Query timed out,Deleting STA: "QDF_MAC_ADDR_FMT, 4851 QDF_MAC_ADDR_REF(pSta->staAddr)); 4852 lim_send_disassoc_mgmt_frame(mac, 4853 REASON_DISASSOC_DUE_TO_INACTIVITY, 4854 pSta->staAddr, pe_session, false); 4855 lim_trigger_sta_deletion(mac, pSta, pe_session); 4856 pSta->pmfSaQueryState = DPH_SA_QUERY_TIMED_OUT; 4857 return; 4858 } 4859 /* Retry SA Query */ 4860 lim_send_sa_query_request_frame(mac, 4861 (uint8_t *) &(pSta-> 4862 pmfSaQueryCurrentTransId), 4863 pSta->staAddr, pe_session); 4864 pSta->pmfSaQueryCurrentTransId++; 4865 pe_debug("Starting SA Query retry: %d", pSta->pmfSaQueryRetryCount); 4866 if (tx_timer_activate(&pSta->pmfSaQueryTimer) != TX_SUCCESS) { 4867 pe_err("PMF SA Query timer activation failed!"); 4868 pSta->pmfSaQueryState = DPH_SA_QUERY_NOT_IN_PROGRESS; 4869 } 4870 } 4871 4872 /** 4873 * lim_get_update_bw_allow() whether bw can be sent to target directly 4874 * @session: pe session 4875 * @new_bw: bandwdith to set 4876 * @update_allow: return true if bw and puncture can be updated directly 4877 * 4878 * Return: QDF_STATUS 4879 */ 4880 static QDF_STATUS 4881 lim_get_update_bw_allow(struct pe_session *session, 4882 enum phy_ch_width new_bw, 4883 bool *update_allow) 4884 { 4885 enum phy_ch_width ch_width; 4886 struct wlan_objmgr_psoc *psoc; 4887 enum wlan_phymode phy_mode; 4888 QDF_STATUS status = QDF_STATUS_E_INVAL; 4889 4890 if (!session || !update_allow) { 4891 pe_err("invalid input"); 4892 return status; 4893 } 4894 *update_allow = false; 4895 4896 psoc = wlan_vdev_get_psoc(session->vdev); 4897 if (!psoc) { 4898 pe_err("psoc object invalid"); 4899 return status; 4900 } 4901 status = mlme_get_peer_phymode(psoc, session->bssId, &phy_mode); 4902 if (QDF_IS_STATUS_ERROR(status)) { 4903 pe_err("failed to get phy_mode %d mac: " QDF_MAC_ADDR_FMT, 4904 status, QDF_MAC_ADDR_REF(session->bssId)); 4905 return status; 4906 } 4907 ch_width = wlan_mlme_get_ch_width_from_phymode(phy_mode); 4908 if (new_bw <= ch_width) 4909 *update_allow = true; 4910 4911 return status; 4912 } 4913 4914 bool lim_check_vht_op_mode_change(struct mac_context *mac, 4915 struct pe_session *pe_session, 4916 uint8_t chanWidth, uint8_t *peerMac) 4917 { 4918 QDF_STATUS status; 4919 bool update_allow; 4920 struct ch_params ch_params; 4921 struct csa_offload_params *csa_param; 4922 enum QDF_OPMODE mode = wlan_vdev_mlme_get_opmode(pe_session->vdev); 4923 4924 if (mode == QDF_STA_MODE || mode == QDF_P2P_CLIENT_MODE) { 4925 status = lim_get_update_bw_allow(pe_session, chanWidth, 4926 &update_allow); 4927 if (QDF_IS_STATUS_ERROR(status)) 4928 return false; 4929 } else { 4930 update_allow = true; 4931 } 4932 4933 if (update_allow) { 4934 tUpdateVHTOpMode tempParam; 4935 4936 tempParam.opMode = chanWidth; 4937 tempParam.smesessionId = pe_session->smeSessionId; 4938 qdf_mem_copy(tempParam.peer_mac, peerMac, sizeof(tSirMacAddr)); 4939 4940 lim_send_mode_update(mac, &tempParam, pe_session); 4941 lim_update_tdls_2g_bw(pe_session); 4942 4943 return true; 4944 } 4945 4946 if (!wlan_cm_is_vdev_connected(pe_session->vdev)) 4947 return false; 4948 4949 /* use vdev restart to update STA mode */ 4950 qdf_mem_zero(&ch_params, sizeof(ch_params)); 4951 ch_params.ch_width = chanWidth; 4952 wlan_reg_set_channel_params_for_pwrmode(mac->pdev, 4953 pe_session->curr_op_freq, 4954 0, &ch_params, 4955 REG_CURRENT_PWR_MODE); 4956 csa_param = qdf_mem_malloc(sizeof(*csa_param)); 4957 if (!csa_param) { 4958 pe_err("csa_param allocation fails"); 4959 return false; 4960 } 4961 4962 csa_param->channel = wlan_reg_freq_to_chan(mac->pdev, 4963 pe_session->curr_op_freq); 4964 csa_param->csa_chan_freq = pe_session->curr_op_freq; 4965 csa_param->new_ch_width = ch_params.ch_width; 4966 csa_param->new_ch_freq_seg1 = ch_params.center_freq_seg0; 4967 csa_param->new_ch_freq_seg2 = ch_params.center_freq_seg1; 4968 qdf_copy_macaddr(&csa_param->bssid, 4969 (struct qdf_mac_addr *)pe_session->bssId); 4970 lim_handle_sta_csa_param(mac, csa_param); 4971 4972 return true; 4973 } 4974 4975 #ifdef WLAN_FEATURE_11AX_BSS_COLOR 4976 bool lim_send_he_ie_update(struct mac_context *mac_ctx, struct pe_session *pe_session) 4977 { 4978 QDF_STATUS status; 4979 4980 status = wma_update_he_ops_ie(cds_get_context(QDF_MODULE_ID_WMA), 4981 pe_session->smeSessionId, 4982 &pe_session->he_op); 4983 if (QDF_IS_STATUS_ERROR(status)) 4984 return false; 4985 4986 return true; 4987 } 4988 #endif 4989 4990 bool lim_set_nss_change(struct mac_context *mac, struct pe_session *pe_session, 4991 uint8_t rxNss, uint8_t *peerMac) 4992 { 4993 tUpdateRxNss tempParam; 4994 4995 if (!rxNss) { 4996 pe_err("Invalid rxNss value: %u", rxNss); 4997 return false; 4998 } 4999 5000 tempParam.rxNss = rxNss; 5001 tempParam.smesessionId = pe_session->smeSessionId; 5002 qdf_mem_copy(tempParam.peer_mac, peerMac, sizeof(tSirMacAddr)); 5003 5004 lim_send_rx_nss_update(mac, &tempParam, pe_session); 5005 5006 return true; 5007 } 5008 5009 bool lim_check_membership_user_position(struct mac_context *mac, 5010 struct pe_session *pe_session, 5011 uint32_t membership, 5012 uint32_t userPosition) 5013 { 5014 tUpdateMembership tempParamMembership; 5015 tUpdateUserPos tempParamUserPosition; 5016 5017 tempParamMembership.membership = membership; 5018 tempParamMembership.smesessionId = pe_session->smeSessionId; 5019 qdf_mem_copy(tempParamMembership.peer_mac, pe_session->bssId, 5020 sizeof(tSirMacAddr)); 5021 5022 lim_set_membership(mac, &tempParamMembership, pe_session); 5023 5024 tempParamUserPosition.userPos = userPosition; 5025 tempParamUserPosition.smesessionId = pe_session->smeSessionId; 5026 qdf_mem_copy(tempParamUserPosition.peer_mac, pe_session->bssId, 5027 sizeof(tSirMacAddr)); 5028 5029 lim_set_user_pos(mac, &tempParamUserPosition, pe_session); 5030 5031 return true; 5032 } 5033 5034 void lim_get_short_slot_from_phy_mode(struct mac_context *mac, struct pe_session *pe_session, 5035 uint32_t phyMode, uint8_t *pShortSlotEnabled) 5036 { 5037 uint8_t val = 0; 5038 5039 /* only 2.4G band should have short slot enable, rest it should be default */ 5040 if (phyMode == WNI_CFG_PHY_MODE_11G) { 5041 /* short slot is default in all other modes */ 5042 if ((pe_session->opmode == QDF_SAP_MODE) || 5043 (pe_session->opmode == QDF_IBSS_MODE) || 5044 (pe_session->opmode == QDF_P2P_GO_MODE)) { 5045 val = true; 5046 } 5047 /* Program Polaris based on AP capability */ 5048 if (pe_session->limMlmState == eLIM_MLM_WT_JOIN_BEACON_STATE) { 5049 /* Joining BSS. */ 5050 val = 5051 SIR_MAC_GET_SHORT_SLOT_TIME(pe_session-> 5052 limCurrentBssCaps); 5053 } else if (pe_session->limMlmState == 5054 eLIM_MLM_WT_REASSOC_RSP_STATE) { 5055 /* Reassociating with AP. */ 5056 val = 5057 SIR_MAC_GET_SHORT_SLOT_TIME(pe_session-> 5058 limReassocBssCaps); 5059 } 5060 } else { 5061 /* 5062 * 11B does not short slot and short slot is default 5063 * for 11A mode. Hence, not need to set this bit 5064 */ 5065 val = false; 5066 } 5067 5068 pe_debug("phyMode: %u shortslotsupported: %u", phyMode, val); 5069 *pShortSlotEnabled = val; 5070 } 5071 5072 /** 5073 * 5074 * \brief This function is called by various LIM modules to correctly set 5075 * the Protected bit in the Frame Control Field of the 802.11 frame MAC header 5076 * 5077 * 5078 * \param mac Pointer to Global MAC structure 5079 * 5080 * \param pe_session Pointer to session corresponding to the connection 5081 * 5082 * \param peer Peer address of the STA to which the frame is to be sent 5083 * 5084 * \param pMacHdr Pointer to the frame MAC header 5085 * 5086 * \return nothing 5087 * 5088 * 5089 */ 5090 void 5091 lim_set_protected_bit(struct mac_context *mac, 5092 struct pe_session *pe_session, 5093 tSirMacAddr peer, tpSirMacMgmtHdr pMacHdr) 5094 { 5095 uint16_t aid; 5096 tpDphHashNode sta; 5097 5098 sta = dph_lookup_hash_entry(mac, peer, &aid, 5099 &pe_session->dph.dphHashTable); 5100 if (sta) { 5101 /* rmfenabled will be set at the time of addbss. 5102 * but sometimes EAP auth fails and keys are not 5103 * installed then if we send any management frame 5104 * like deauth/disassoc with this bit set then 5105 * firmware crashes. so check for keys are 5106 * installed or not also before setting the bit 5107 */ 5108 if (sta->rmfEnabled && sta->is_key_installed) 5109 pMacHdr->fc.wep = 1; 5110 5111 pe_debug("wep:%d rmf:%d is_key_set:%d", pMacHdr->fc.wep, 5112 sta->rmfEnabled, sta->is_key_installed); 5113 } 5114 } /*** end lim_set_protected_bit() ***/ 5115 5116 void lim_set_ht_caps(struct mac_context *p_mac, uint8_t *p_ie_start, 5117 uint32_t num_bytes) 5118 { 5119 const uint8_t *p_ie = NULL; 5120 tDot11fIEHTCaps dot11_ht_cap = {0,}; 5121 5122 populate_dot11f_ht_caps(p_mac, NULL, &dot11_ht_cap); 5123 p_ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_HTCAPS, 5124 p_ie_start, num_bytes); 5125 pe_debug("p_ie: %pK dot11_ht_cap.supportedMCSSet[0]: 0x%x", 5126 p_ie, dot11_ht_cap.supportedMCSSet[0]); 5127 if (p_ie) { 5128 /* convert from unpacked to packed structure */ 5129 tHtCaps *p_ht_cap = (tHtCaps *) &p_ie[2]; 5130 5131 p_ht_cap->advCodingCap = dot11_ht_cap.advCodingCap; 5132 p_ht_cap->supportedChannelWidthSet = 5133 dot11_ht_cap.supportedChannelWidthSet; 5134 p_ht_cap->mimoPowerSave = dot11_ht_cap.mimoPowerSave; 5135 p_ht_cap->greenField = dot11_ht_cap.greenField; 5136 p_ht_cap->shortGI20MHz = dot11_ht_cap.shortGI20MHz; 5137 p_ht_cap->shortGI40MHz = dot11_ht_cap.shortGI40MHz; 5138 p_ht_cap->txSTBC = dot11_ht_cap.txSTBC; 5139 p_ht_cap->rxSTBC = dot11_ht_cap.rxSTBC; 5140 p_ht_cap->delayedBA = dot11_ht_cap.delayedBA; 5141 p_ht_cap->maximalAMSDUsize = dot11_ht_cap.maximalAMSDUsize; 5142 p_ht_cap->dsssCckMode40MHz = dot11_ht_cap.dsssCckMode40MHz; 5143 p_ht_cap->psmp = dot11_ht_cap.psmp; 5144 p_ht_cap->stbcControlFrame = dot11_ht_cap.stbcControlFrame; 5145 p_ht_cap->lsigTXOPProtection = dot11_ht_cap.lsigTXOPProtection; 5146 p_ht_cap->maxRxAMPDUFactor = dot11_ht_cap.maxRxAMPDUFactor; 5147 p_ht_cap->mpduDensity = dot11_ht_cap.mpduDensity; 5148 qdf_mem_copy((void *)p_ht_cap->supportedMCSSet, 5149 (void *)(dot11_ht_cap.supportedMCSSet), 5150 sizeof(p_ht_cap->supportedMCSSet)); 5151 p_ht_cap->pco = dot11_ht_cap.pco; 5152 p_ht_cap->transitionTime = dot11_ht_cap.transitionTime; 5153 p_ht_cap->mcsFeedback = dot11_ht_cap.mcsFeedback; 5154 p_ht_cap->txBF = dot11_ht_cap.txBF; 5155 p_ht_cap->rxStaggeredSounding = 5156 dot11_ht_cap.rxStaggeredSounding; 5157 p_ht_cap->txStaggeredSounding = 5158 dot11_ht_cap.txStaggeredSounding; 5159 p_ht_cap->rxZLF = dot11_ht_cap.rxZLF; 5160 p_ht_cap->txZLF = dot11_ht_cap.txZLF; 5161 p_ht_cap->implicitTxBF = dot11_ht_cap.implicitTxBF; 5162 p_ht_cap->calibration = dot11_ht_cap.calibration; 5163 p_ht_cap->explicitCSITxBF = dot11_ht_cap.explicitCSITxBF; 5164 p_ht_cap->explicitUncompressedSteeringMatrix = 5165 dot11_ht_cap.explicitUncompressedSteeringMatrix; 5166 p_ht_cap->explicitBFCSIFeedback = 5167 dot11_ht_cap.explicitBFCSIFeedback; 5168 p_ht_cap->explicitUncompressedSteeringMatrixFeedback = 5169 dot11_ht_cap.explicitUncompressedSteeringMatrixFeedback; 5170 p_ht_cap->explicitCompressedSteeringMatrixFeedback = 5171 dot11_ht_cap.explicitCompressedSteeringMatrixFeedback; 5172 p_ht_cap->csiNumBFAntennae = dot11_ht_cap.csiNumBFAntennae; 5173 p_ht_cap->uncompressedSteeringMatrixBFAntennae = 5174 dot11_ht_cap.uncompressedSteeringMatrixBFAntennae; 5175 p_ht_cap->compressedSteeringMatrixBFAntennae = 5176 dot11_ht_cap.compressedSteeringMatrixBFAntennae; 5177 p_ht_cap->antennaSelection = dot11_ht_cap.antennaSelection; 5178 p_ht_cap->explicitCSIFeedbackTx = 5179 dot11_ht_cap.explicitCSIFeedbackTx; 5180 p_ht_cap->antennaIndicesFeedbackTx = 5181 dot11_ht_cap.antennaIndicesFeedbackTx; 5182 p_ht_cap->explicitCSIFeedback = 5183 dot11_ht_cap.explicitCSIFeedback; 5184 p_ht_cap->antennaIndicesFeedback = 5185 dot11_ht_cap.antennaIndicesFeedback; 5186 p_ht_cap->rxAS = dot11_ht_cap.rxAS; 5187 p_ht_cap->txSoundingPPDUs = dot11_ht_cap.txSoundingPPDUs; 5188 } 5189 } 5190 5191 void lim_set_vht_caps(struct mac_context *p_mac, 5192 uint8_t *p_ie_start, uint32_t num_bytes) 5193 { 5194 const uint8_t *p_ie = NULL; 5195 tDot11fIEVHTCaps dot11_vht_cap; 5196 5197 populate_dot11f_vht_caps(p_mac, NULL, &dot11_vht_cap); 5198 p_ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_VHTCAPS, p_ie_start, 5199 num_bytes); 5200 if (p_ie) { 5201 tSirMacVHTCapabilityInfo *vht_cap = 5202 (tSirMacVHTCapabilityInfo *) &p_ie[2]; 5203 tSirVhtMcsInfo *vht_mcs = (tSirVhtMcsInfo *) &p_ie[2 + 5204 sizeof(tSirMacVHTCapabilityInfo)]; 5205 5206 union { 5207 uint16_t u_value; 5208 tSirMacVHTRxSupDataRateInfo vht_rx_supp_rate; 5209 tSirMacVHTTxSupDataRateInfo vht_tx_supp_rate; 5210 } u_vht_data_rate_info; 5211 5212 vht_cap->maxMPDULen = dot11_vht_cap.maxMPDULen; 5213 vht_cap->supportedChannelWidthSet = 5214 dot11_vht_cap.supportedChannelWidthSet; 5215 vht_cap->ldpcCodingCap = dot11_vht_cap.ldpcCodingCap; 5216 vht_cap->shortGI80MHz = dot11_vht_cap.shortGI80MHz; 5217 vht_cap->shortGI160and80plus80MHz = 5218 dot11_vht_cap.shortGI160and80plus80MHz; 5219 vht_cap->txSTBC = dot11_vht_cap.txSTBC; 5220 vht_cap->rxSTBC = dot11_vht_cap.rxSTBC; 5221 vht_cap->suBeamFormerCap = dot11_vht_cap.suBeamFormerCap; 5222 vht_cap->suBeamformeeCap = dot11_vht_cap.suBeamformeeCap; 5223 vht_cap->csnofBeamformerAntSup = 5224 dot11_vht_cap.csnofBeamformerAntSup; 5225 vht_cap->numSoundingDim = dot11_vht_cap.numSoundingDim; 5226 vht_cap->muBeamformerCap = dot11_vht_cap.muBeamformerCap; 5227 vht_cap->muBeamformeeCap = dot11_vht_cap.muBeamformeeCap; 5228 vht_cap->vhtTXOPPS = dot11_vht_cap.vhtTXOPPS; 5229 vht_cap->htcVHTCap = dot11_vht_cap.htcVHTCap; 5230 vht_cap->maxAMPDULenExp = dot11_vht_cap.maxAMPDULenExp; 5231 vht_cap->vhtLinkAdaptCap = dot11_vht_cap.vhtLinkAdaptCap; 5232 vht_cap->rxAntPattern = dot11_vht_cap.rxAntPattern; 5233 vht_cap->txAntPattern = dot11_vht_cap.txAntPattern; 5234 vht_cap->extended_nss_bw_supp = 5235 dot11_vht_cap.extended_nss_bw_supp; 5236 5237 /* Populate VHT MCS Information */ 5238 vht_mcs->rxMcsMap = dot11_vht_cap.rxMCSMap; 5239 u_vht_data_rate_info.vht_rx_supp_rate.rxSupDataRate = 5240 dot11_vht_cap.rxHighSupDataRate; 5241 u_vht_data_rate_info.vht_rx_supp_rate.max_nsts_total = 5242 dot11_vht_cap.max_nsts_total; 5243 vht_mcs->rxHighest = u_vht_data_rate_info.u_value; 5244 5245 vht_mcs->txMcsMap = dot11_vht_cap.txMCSMap; 5246 u_vht_data_rate_info.vht_tx_supp_rate.txSupDataRate = 5247 dot11_vht_cap.txSupDataRate; 5248 u_vht_data_rate_info.vht_tx_supp_rate.vht_extended_nss_bw_cap = 5249 dot11_vht_cap.vht_extended_nss_bw_cap; 5250 vht_mcs->txHighest = u_vht_data_rate_info.u_value; 5251 } 5252 } 5253 5254 /* 5255 * Firmware will send RTS for every frame and also will disable SIFS bursting 5256 * if value 0x11 is sent for RTS profile. 5257 */ 5258 #define A_EDCA_SCC_RTS_PROFILE_VALUE 0x11 5259 #define MAX_NUMBER_OF_SINGLE_PORT_CONC_CONNECTIONS 2 5260 5261 static void lim_update_sta_edca_params(struct mac_context *mac, 5262 struct pe_session *sta_session) 5263 { 5264 uint8_t i; 5265 5266 for (i = QCA_WLAN_AC_BE; i < QCA_WLAN_AC_ALL; i++) { 5267 sta_session->gLimEdcaParamsActive[i] = 5268 sta_session->gLimEdcaParams[i]; 5269 } 5270 lim_send_edca_params(mac, 5271 sta_session->gLimEdcaParamsActive, 5272 sta_session->vdev_id, false); 5273 } 5274 5275 static void check_and_send_vendor_oui(struct mac_context *mac, 5276 struct pe_session *sta_session) 5277 { 5278 QDF_STATUS status; 5279 uint8_t *tmp_ptr = NULL; 5280 struct element_info frame; 5281 5282 status = wlan_scan_get_entry_by_mac_addr( 5283 mac->pdev, 5284 (struct qdf_mac_addr *)&sta_session->bssId, 5285 &frame); 5286 if (QDF_IS_STATUS_ERROR(status) && !frame.len) { 5287 pe_err("Failed to get scan entry for " QDF_MAC_ADDR_FMT, 5288 QDF_MAC_ADDR_REF(sta_session->bssId)); 5289 return; 5290 } 5291 5292 tmp_ptr = frame.ptr; 5293 tmp_ptr += SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET; 5294 frame.len -= SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET; 5295 5296 if (!lim_enable_cts_to_self_for_exempted_iot_ap( 5297 mac, sta_session, 5298 tmp_ptr, frame.len)) 5299 wma_cli_set_command(sta_session->vdev_id, 5300 wmi_vdev_param_enable_rtscts, 5301 cfg_get(mac->psoc, 5302 CFG_ENABLE_FW_RTS_PROFILE), 5303 VDEV_CMD); 5304 qdf_mem_free(frame.ptr); 5305 } 5306 5307 /** 5308 * lim_check_conc_and_send_edca() - Function to check and update EDCA params 5309 * and RTS profile based on STA/SAP 5310 * concurrency. If updated, it will also send 5311 * the updated parameters to FW. It will update 5312 * EDCA params and RTS profile such that: 5313 * 1) For STA and SAP concurrency, send STA's AP EDCA params to fw. 5314 * Also, for SAP or P2P Go, update the value in Broadcast EDCA params 5315 * as well so that it should be broadcasted to other stations connected 5316 * to that BSS. Also, update the RTS profile value to 0x11 for which 5317 * FW will send RTS for every frame and will also disable SIFS 5318 * bursting. 5319 * 5320 * 2) For standalone STA (can even happen after SAP/P2P Go 5321 * disconnects), if the parameters are updated, reset them to original 5322 * parameters and send them to FW. Also, update the RTS profile 5323 * value to which it was set before. 5324 * 5325 * 3) For standalone SAP (can even happen after STA disconnects), 5326 * if the parameters are updated, reset them to original 5327 * parameters and send them to FW and reset the Broadcast EDCA params 5328 * as well so that it should be broadcasted to other stations connected 5329 * to that BSS Also, update the RTS profile value to which it was set 5330 * before. 5331 * 5332 * This update is needed because throughput drop was seen because of 5333 * inconsistency in the EDCA params used in STA-SAP or STA-P2P_GO concurrency. 5334 * 5335 * Return: void 5336 */ 5337 5338 static void lim_check_conc_and_send_edca(struct mac_context *mac, 5339 struct pe_session *sta_session, 5340 struct pe_session *sap_session) 5341 { 5342 bool params_update_required = false; 5343 uint8_t i; 5344 tpDphHashNode sta_ds = NULL; 5345 QDF_STATUS status; 5346 uint16_t assoc_id; 5347 5348 if (sta_session && sap_session && 5349 (sta_session->curr_op_freq == 5350 sap_session->curr_op_freq)) { 5351 /* RTS profile update to FW */ 5352 wma_cli_set_command(sap_session->vdev_id, 5353 wmi_vdev_param_enable_rtscts, 5354 A_EDCA_SCC_RTS_PROFILE_VALUE, 5355 VDEV_CMD); 5356 wma_cli_set_command(sta_session->vdev_id, 5357 wmi_vdev_param_enable_rtscts, 5358 A_EDCA_SCC_RTS_PROFILE_VALUE, 5359 VDEV_CMD); 5360 5361 sta_ds = dph_lookup_hash_entry(mac, 5362 sta_session->bssId, 5363 &assoc_id, 5364 &sta_session->dph.dphHashTable); 5365 5366 if (!sta_ds) { 5367 pe_debug("No STA DS entry found for " QDF_MAC_ADDR_FMT, 5368 QDF_MAC_ADDR_REF(sta_session->bssId)); 5369 return; 5370 } 5371 5372 if (!sta_ds->qos.peer_edca_params.length) { 5373 pe_debug("No sta_ds edca_params present"); 5374 return; 5375 } 5376 5377 /* 5378 * Here what we do is disable A-EDCA by sending the edca params of 5379 * connected AP which we got as part of assoc resp So as these EDCA 5380 * params are updated per mac , its fine to send for SAP which will 5381 * be used for STA as well on the same channel. No need to send for 5382 * both SAP and STA. 5383 */ 5384 5385 sap_session->gLimEdcaParamsBC[QCA_WLAN_AC_BE] = 5386 sta_ds->qos.peer_edca_params.acbe; 5387 sap_session->gLimEdcaParamsBC[QCA_WLAN_AC_BK] = 5388 sta_ds->qos.peer_edca_params.acbk; 5389 sap_session->gLimEdcaParamsBC[QCA_WLAN_AC_VI] = 5390 sta_ds->qos.peer_edca_params.acvi; 5391 sap_session->gLimEdcaParamsBC[QCA_WLAN_AC_VO] = 5392 sta_ds->qos.peer_edca_params.acvo; 5393 5394 sap_session->gLimEdcaParamsActive[QCA_WLAN_AC_BE] = 5395 sta_ds->qos.peer_edca_params.acbe; 5396 sap_session->gLimEdcaParamsActive[QCA_WLAN_AC_BK] = 5397 sta_ds->qos.peer_edca_params.acbk; 5398 sap_session->gLimEdcaParamsActive[QCA_WLAN_AC_VI] = 5399 sta_ds->qos.peer_edca_params.acvi; 5400 sap_session->gLimEdcaParamsActive[QCA_WLAN_AC_VO] = 5401 sta_ds->qos.peer_edca_params.acvo; 5402 5403 for (i = QCA_WLAN_AC_BE; i < QCA_WLAN_AC_ALL; i++) { 5404 sta_session->gLimEdcaParamsActive[i] = 5405 sap_session->gLimEdcaParamsActive[i]; 5406 } 5407 /* For AP, the bssID is stored in LIM Global context. */ 5408 lim_send_edca_params(mac, sap_session->gLimEdcaParamsActive, 5409 sap_session->vdev_id, false); 5410 5411 sap_session->gLimEdcaParamSetCount++; 5412 status = sch_set_fixed_beacon_fields(mac, sap_session); 5413 if (QDF_IS_STATUS_ERROR(status)) 5414 pe_debug("Unable to set beacon fields!"); 5415 5416 } else if (!sap_session && sta_session) { 5417 /* 5418 * Enable A-EDCA for standalone STA. The original EDCA parameters are 5419 * stored in gLimEdcaParams (computed by sch_beacon_edca_process()), 5420 * if active parameters are not equal that means they have been updated 5421 * because of conncurrency and are need to be restored now 5422 */ 5423 check_and_send_vendor_oui(mac, sta_session); 5424 5425 for (i = QCA_WLAN_AC_BE; i < QCA_WLAN_AC_ALL; i++) { 5426 if (qdf_mem_cmp(&sta_session->gLimEdcaParamsActive[i], 5427 &sta_session->gLimEdcaParams[i], 5428 sizeof(tSirMacEdcaParamRecord))) { 5429 pe_debug("local sta EDCA params are not equal to Active EDCA params, hence update required"); 5430 params_update_required = true; 5431 break; 5432 } 5433 } 5434 5435 if (params_update_required) { 5436 lim_update_sta_edca_params(mac, 5437 sta_session); 5438 } 5439 } else { 5440 /* 5441 * For STA+SAP/GO DBS, STA+SAP/GO MCC or standalone SAP/GO 5442 */ 5443 5444 wma_cli_set_command(sap_session->vdev_id, 5445 wmi_vdev_param_enable_rtscts, 5446 cfg_get(mac->psoc, 5447 CFG_ENABLE_FW_RTS_PROFILE), 5448 VDEV_CMD); 5449 if (sta_session) { 5450 check_and_send_vendor_oui(mac, sta_session); 5451 } 5452 5453 for (i = QCA_WLAN_AC_BE; i < QCA_WLAN_AC_ALL; i++) { 5454 if (qdf_mem_cmp(&sap_session->gLimEdcaParamsActive[i], 5455 &sap_session->gLimEdcaParams[i], 5456 sizeof(tSirMacEdcaParamRecord))) { 5457 pe_debug("local sap EDCA params are not equal to Active EDCA params, hence update required"); 5458 params_update_required = true; 5459 break; 5460 } 5461 } 5462 5463 if (params_update_required) { 5464 for (i = QCA_WLAN_AC_BE; i < QCA_WLAN_AC_ALL; i++) { 5465 sap_session->gLimEdcaParamsActive[i] = 5466 sap_session->gLimEdcaParams[i]; 5467 } 5468 lim_send_edca_params(mac, 5469 sap_session->gLimEdcaParamsActive, 5470 sap_session->vdev_id, false); 5471 sch_qos_update_broadcast(mac, sap_session); 5472 5473 /* 5474 * In case of mcc, where cb can come from scc to mcc switch where we 5475 * need to restore the default parameters 5476 */ 5477 if (sta_session) { 5478 lim_update_sta_edca_params(mac, 5479 sta_session); 5480 } 5481 } 5482 } 5483 } 5484 5485 void lim_send_conc_params_update(void) 5486 { 5487 struct pe_session *sta_session = NULL; 5488 struct pe_session *sap_session = NULL; 5489 uint8_t i; 5490 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE); 5491 5492 if (!mac) 5493 return; 5494 5495 if (!mac->mlme_cfg->edca_params.enable_edca_params || 5496 (policy_mgr_get_connection_count(mac->psoc) > 5497 MAX_NUMBER_OF_SINGLE_PORT_CONC_CONNECTIONS)) { 5498 pe_debug("A-EDCA not enabled or max number of connections: %d", 5499 policy_mgr_get_connection_count(mac->psoc)); 5500 return; 5501 } 5502 5503 for (i = 0; i < mac->lim.maxBssId; i++) { 5504 /* 5505 * Finding whether STA or Go session exists 5506 */ 5507 if (sta_session && sap_session) 5508 break; 5509 5510 if ((mac->lim.gpSession[i].valid) && 5511 (mac->lim.gpSession[i].limSystemRole == 5512 eLIM_STA_ROLE)) { 5513 sta_session = &mac->lim.gpSession[i]; 5514 continue; 5515 } 5516 if ((mac->lim.gpSession[i].valid) && 5517 ((mac->lim.gpSession[i].limSystemRole == eLIM_AP_ROLE) || 5518 (mac->lim.gpSession[i].limSystemRole == 5519 eLIM_P2P_DEVICE_GO))) { 5520 sap_session = &mac->lim.gpSession[i]; 5521 continue; 5522 } 5523 } 5524 5525 if (!(sta_session || sap_session)) { 5526 pe_debug("No sta or sap or P2P go session"); 5527 return; 5528 } 5529 5530 pe_debug("Valid STA session: %d Valid SAP session: %d", 5531 (sta_session ? sta_session->valid : 0), 5532 (sap_session ? sap_session->valid : 0)); 5533 lim_check_conc_and_send_edca(mac, sta_session, sap_session); 5534 } 5535 5536 /** 5537 * lim_validate_received_frame_a1_addr() - To validate received frame's A1 addr 5538 * @mac_ctx: pointer to mac context 5539 * @a1: received frame's a1 address which is nothing but our self address 5540 * @session: PE session pointer 5541 * 5542 * This routine will validate, A1 address of the received frame 5543 * 5544 * Return: true or false 5545 */ 5546 bool lim_validate_received_frame_a1_addr(struct mac_context *mac_ctx, 5547 tSirMacAddr a1, struct pe_session *session) 5548 { 5549 if (!mac_ctx || !session) { 5550 pe_err("mac or session context is null"); 5551 /* let main routine handle it */ 5552 return true; 5553 } 5554 if (IEEE80211_IS_MULTICAST(a1) || QDF_IS_ADDR_BROADCAST(a1)) { 5555 /* just for fail safe, don't handle MC/BC a1 in this routine */ 5556 return true; 5557 } 5558 if (qdf_mem_cmp(a1, session->self_mac_addr, 6)) { 5559 pe_err("Invalid A1 address in received frame"); 5560 return false; 5561 } 5562 return true; 5563 } 5564 5565 /** 5566 * lim_check_and_reset_protection_params() - reset protection related parameters 5567 * 5568 * @mac_ctx: pointer to global mac structure 5569 * 5570 * resets protection related global parameters if the pe active session count 5571 * is zero. 5572 * 5573 * Return: None 5574 */ 5575 void lim_check_and_reset_protection_params(struct mac_context *mac_ctx) 5576 { 5577 if (!pe_get_active_session_count(mac_ctx)) { 5578 mac_ctx->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE; 5579 } 5580 } 5581 5582 /** 5583 * lim_set_stads_rtt_cap() - update station node RTT capability 5584 * @sta_ds: Station hash node 5585 * @ext_cap: Pointer to extended capability 5586 * @mac_ctx: global MAC context 5587 * 5588 * This function update hash node's RTT capability based on received 5589 * Extended capability IE. 5590 * 5591 * Return: None 5592 */ 5593 void lim_set_stads_rtt_cap(tpDphHashNode sta_ds, struct s_ext_cap *ext_cap, 5594 struct mac_context *mac_ctx) 5595 { 5596 sta_ds->timingMeasCap = 0; 5597 sta_ds->timingMeasCap |= (ext_cap->timing_meas) ? 5598 RTT_TIMING_MEAS_CAPABILITY : 5599 RTT_INVALID; 5600 sta_ds->timingMeasCap |= (ext_cap->fine_time_meas_initiator) ? 5601 RTT_FINE_TIME_MEAS_INITIATOR_CAPABILITY : 5602 RTT_INVALID; 5603 sta_ds->timingMeasCap |= (ext_cap->fine_time_meas_responder) ? 5604 RTT_FINE_TIME_MEAS_RESPONDER_CAPABILITY : 5605 RTT_INVALID; 5606 5607 pe_debug("ExtCap present, timingMeas: %d Initiator: %d Responder: %d", 5608 ext_cap->timing_meas, ext_cap->fine_time_meas_initiator, 5609 ext_cap->fine_time_meas_responder); 5610 } 5611 5612 #ifdef WLAN_SUPPORT_TWT 5613 void lim_set_peer_twt_cap(struct pe_session *session, struct s_ext_cap *ext_cap) 5614 { 5615 if (session->enable_session_twt_support) { 5616 session->peer_twt_requestor = ext_cap->twt_requestor_support; 5617 session->peer_twt_responder = ext_cap->twt_responder_support; 5618 } 5619 5620 pe_debug("Ext Cap peer TWT requestor: %d, responder: %d, enable_twt %d", 5621 ext_cap->twt_requestor_support, 5622 ext_cap->twt_responder_support, 5623 session->enable_session_twt_support); 5624 } 5625 #endif 5626 5627 /** 5628 * lim_send_ie() - sends IE to wma 5629 * @mac_ctx: global MAC context 5630 * @vdev_id: vdev_id 5631 * @eid: IE id 5632 * @band: band for which IE is intended 5633 * @buf: buffer containing IE 5634 * @len: length of buffer 5635 * 5636 * This function sends the IE data to WMA. 5637 * 5638 * Return: status of operation 5639 */ 5640 static QDF_STATUS lim_send_ie(struct mac_context *mac_ctx, uint32_t vdev_id, 5641 uint8_t eid, enum cds_band_type band, 5642 uint8_t *buf, uint32_t len) 5643 { 5644 struct vdev_ie_info *ie_msg; 5645 struct scheduler_msg msg = {0}; 5646 QDF_STATUS status; 5647 5648 /* Allocate memory for the WMI request */ 5649 ie_msg = qdf_mem_malloc(sizeof(*ie_msg) + len); 5650 if (!ie_msg) 5651 return QDF_STATUS_E_NOMEM; 5652 5653 ie_msg->vdev_id = vdev_id; 5654 ie_msg->ie_id = eid; 5655 ie_msg->length = len; 5656 ie_msg->band = band; 5657 /* IE data buffer starts at end of the struct */ 5658 ie_msg->data = (uint8_t *)&ie_msg[1]; 5659 5660 qdf_mem_copy(ie_msg->data, buf, len); 5661 msg.type = WMA_SET_IE_INFO; 5662 msg.bodyptr = ie_msg; 5663 msg.reserved = 0; 5664 5665 status = scheduler_post_message(QDF_MODULE_ID_PE, 5666 QDF_MODULE_ID_WMA, 5667 QDF_MODULE_ID_WMA, &msg); 5668 if (QDF_STATUS_SUCCESS != status) { 5669 pe_err("Not able to post WMA_SET_IE_INFO to WMA"); 5670 qdf_mem_free(ie_msg); 5671 return status; 5672 } 5673 5674 return status; 5675 } 5676 5677 /** 5678 * lim_get_rx_ldpc() - gets ldpc setting for given channel(band) 5679 * @mac_ctx: global mac context 5680 * @ch: channel enum for which ldpc setting is required 5681 * Note: ch param is not absolute channel number rather it is 5682 * channel number enum. 5683 * 5684 * Return: true if enabled and false otherwise 5685 */ 5686 static inline bool lim_get_rx_ldpc(struct mac_context *mac_ctx, 5687 enum channel_enum ch) 5688 { 5689 if (mac_ctx->mlme_cfg->ht_caps.ht_cap_info.adv_coding_cap && 5690 wma_is_rx_ldpc_supported_for_channel(wlan_reg_ch_to_freq(ch))) 5691 return true; 5692 else 5693 return false; 5694 } 5695 5696 /** 5697 * lim_populate_mcs_set_ht_per_vdev() - update the MCS set according to vdev nss 5698 * @mac_ctx: global mac context 5699 * @ht_cap: pointer to ht caps 5700 * @vdev_id: vdev for which IE is targeted 5701 * @band: band for which the MCS set has to be updated 5702 * 5703 * This function updates the MCS set according to vdev nss 5704 * 5705 * Return: None 5706 */ 5707 static void lim_populate_mcs_set_ht_per_vdev(struct mac_context *mac_ctx, 5708 struct sHtCaps *ht_cap, 5709 uint8_t vdev_id, 5710 uint8_t band) 5711 { 5712 struct wlan_mlme_nss_chains *nss_chains_ini_cfg; 5713 struct wlan_objmgr_vdev *vdev = 5714 wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc, 5715 vdev_id, 5716 WLAN_MLME_SB_ID); 5717 if (!vdev) { 5718 pe_err("Got NULL vdev obj, returning"); 5719 return; 5720 } 5721 if (!ht_cap->supportedMCSSet[1]) 5722 goto end; 5723 nss_chains_ini_cfg = mlme_get_ini_vdev_config(vdev); 5724 if (!nss_chains_ini_cfg) { 5725 pe_err("nss chain dynamic config NULL"); 5726 goto end; 5727 } 5728 5729 /* convert from unpacked to packed structure */ 5730 if (nss_chains_ini_cfg->rx_nss[band] == 1) 5731 ht_cap->supportedMCSSet[1] = 0; 5732 5733 end: 5734 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID); 5735 } 5736 5737 /** 5738 * lim_populate_mcs_set_vht_per_vdev() - update MCS set according to vdev nss 5739 * @mac_ctx: global mac context 5740 * @vht_caps: pointer to vht_caps 5741 * @vdev_id: vdev for which IE is targeted 5742 * @band: band for which the MCS set has to be updated 5743 * 5744 * This function updates the MCS set according to vdev nss 5745 * 5746 * Return: None 5747 */ 5748 static void lim_populate_mcs_set_vht_per_vdev(struct mac_context *mac_ctx, 5749 uint8_t *vht_caps, 5750 uint8_t vdev_id, 5751 uint8_t band) 5752 { 5753 struct wlan_mlme_nss_chains *nss_chains_ini_cfg; 5754 tSirVhtMcsInfo *vht_mcs; 5755 struct wlan_objmgr_vdev *vdev = 5756 wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc, 5757 vdev_id, 5758 WLAN_MLME_SB_ID); 5759 if (!vdev) { 5760 pe_err("Got NULL vdev obj, returning"); 5761 return; 5762 } 5763 5764 nss_chains_ini_cfg = mlme_get_ini_vdev_config(vdev); 5765 if (!nss_chains_ini_cfg) { 5766 pe_err("nss chain dynamic config NULL"); 5767 goto end; 5768 } 5769 5770 vht_mcs = (tSirVhtMcsInfo *)&vht_caps[2 + 5771 sizeof(tSirMacVHTCapabilityInfo)]; 5772 if (nss_chains_ini_cfg->tx_nss[band] == 1) { 5773 /* Populate VHT MCS Information */ 5774 vht_mcs->txMcsMap |= DISABLE_NSS2_MCS; 5775 vht_mcs->txHighest = 5776 VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1; 5777 } 5778 5779 if (nss_chains_ini_cfg->rx_nss[band] == 1) { 5780 /* Populate VHT MCS Information */ 5781 vht_mcs->rxMcsMap |= DISABLE_NSS2_MCS; 5782 vht_mcs->rxHighest = 5783 VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1; 5784 } 5785 5786 end: 5787 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID); 5788 } 5789 5790 /** 5791 * is_dot11mode_support_ht_cap() - Check dot11mode supports HT capability 5792 * @dot11mode: dot11mode 5793 * 5794 * This function checks whether dot11mode support HT capability or not 5795 * 5796 * Return: True, if supports. False otherwise 5797 */ 5798 static bool is_dot11mode_support_ht_cap(enum csr_cfgdot11mode dot11mode) 5799 { 5800 if ((dot11mode == eCSR_CFG_DOT11_MODE_AUTO) || 5801 (dot11mode == eCSR_CFG_DOT11_MODE_11N) || 5802 (dot11mode == eCSR_CFG_DOT11_MODE_11AC) || 5803 (dot11mode == eCSR_CFG_DOT11_MODE_11N_ONLY) || 5804 (dot11mode == eCSR_CFG_DOT11_MODE_11AC_ONLY) || 5805 (dot11mode == eCSR_CFG_DOT11_MODE_11AX) || 5806 (dot11mode == eCSR_CFG_DOT11_MODE_11AX_ONLY) || 5807 (dot11mode == eCSR_CFG_DOT11_MODE_11BE) || 5808 (dot11mode == eCSR_CFG_DOT11_MODE_11BE_ONLY)) { 5809 return true; 5810 } 5811 5812 return false; 5813 } 5814 5815 /** 5816 * is_dot11mode_support_vht_cap() - Check dot11mode supports VHT capability 5817 * @dot11mode: dot11mode 5818 * 5819 * This function checks whether dot11mode support VHT capability or not 5820 * 5821 * Return: True, if supports. False otherwise 5822 */ 5823 static bool is_dot11mode_support_vht_cap(enum csr_cfgdot11mode dot11mode) 5824 { 5825 if ((dot11mode == eCSR_CFG_DOT11_MODE_AUTO) || 5826 (dot11mode == eCSR_CFG_DOT11_MODE_11AC) || 5827 (dot11mode == eCSR_CFG_DOT11_MODE_11AC_ONLY) || 5828 (dot11mode == eCSR_CFG_DOT11_MODE_11AX) || 5829 (dot11mode == eCSR_CFG_DOT11_MODE_11AX_ONLY) || 5830 (dot11mode == eCSR_CFG_DOT11_MODE_11BE) || 5831 (dot11mode == eCSR_CFG_DOT11_MODE_11BE_ONLY)) { 5832 return true; 5833 } 5834 5835 return false; 5836 } 5837 5838 /** 5839 * is_dot11mode_support_he_cap() - Check dot11mode supports HE capability 5840 * @dot11mode: dot11mode 5841 * 5842 * This function checks whether dot11mode support HE capability or not 5843 * 5844 * Return: True, if supports. False otherwise 5845 */ 5846 static bool is_dot11mode_support_he_cap(enum csr_cfgdot11mode dot11mode) 5847 { 5848 if ((dot11mode == eCSR_CFG_DOT11_MODE_AUTO) || 5849 (dot11mode == eCSR_CFG_DOT11_MODE_11AX) || 5850 (dot11mode == eCSR_CFG_DOT11_MODE_11AX_ONLY) || 5851 (dot11mode == eCSR_CFG_DOT11_MODE_11BE) || 5852 (dot11mode == eCSR_CFG_DOT11_MODE_11BE_ONLY)) { 5853 return true; 5854 } 5855 5856 return false; 5857 } 5858 5859 #ifdef WLAN_FEATURE_11BE 5860 /** 5861 * is_dot11mode_support_eht_cap() - Check dot11mode supports EHT capability 5862 * @dot11mode: dot11mode 5863 * 5864 * This function checks whether dot11mode support EHT capability or not 5865 * 5866 * Return: True, if supports. False otherwise 5867 */ 5868 static bool is_dot11mode_support_eht_cap(enum csr_cfgdot11mode dot11mode) 5869 { 5870 if ((dot11mode == eCSR_CFG_DOT11_MODE_AUTO) || 5871 (dot11mode == eCSR_CFG_DOT11_MODE_11BE) || 5872 (dot11mode == eCSR_CFG_DOT11_MODE_11BE_ONLY)) { 5873 return true; 5874 } 5875 5876 return false; 5877 } 5878 5879 bool lim_is_session_chwidth_320mhz(struct pe_session *session) 5880 { 5881 return session->ch_width == CH_WIDTH_320MHZ; 5882 } 5883 #else 5884 static bool is_dot11mode_support_eht_cap(enum csr_cfgdot11mode dot11mode) 5885 { 5886 return false; 5887 } 5888 #endif 5889 5890 /** 5891 * lim_send_ht_caps_ie() - gets HT capability and send to firmware via wma 5892 * @mac_ctx: global mac context 5893 * @device_mode: VDEV op mode 5894 * @vdev_id: vdev for which IE is targeted 5895 * 5896 * This function gets HT capability and send to firmware via wma 5897 * 5898 * Return: QDF_STATUS 5899 */ 5900 static QDF_STATUS lim_send_ht_caps_ie(struct mac_context *mac_ctx, 5901 enum QDF_OPMODE device_mode, 5902 uint8_t vdev_id) 5903 { 5904 uint8_t ht_caps[DOT11F_IE_HTCAPS_MIN_LEN + 2] = {0}; 5905 tHtCaps *p_ht_cap = (tHtCaps *)(&ht_caps[2]); 5906 QDF_STATUS status_5g, status_2g; 5907 bool nan_beamforming_supported; 5908 5909 ht_caps[0] = DOT11F_EID_HTCAPS; 5910 ht_caps[1] = DOT11F_IE_HTCAPS_MIN_LEN; 5911 lim_set_ht_caps(mac_ctx, ht_caps, 5912 DOT11F_IE_HTCAPS_MIN_LEN + 2); 5913 /* Get LDPC and over write for 2G */ 5914 p_ht_cap->advCodingCap = lim_get_rx_ldpc(mac_ctx, 5915 CHAN_ENUM_2437); 5916 /* Get self cap for HT40 support in 2G */ 5917 if (lim_get_sta_cb_mode_for_24ghz(mac_ctx, vdev_id)) { 5918 p_ht_cap->supportedChannelWidthSet = 1; 5919 p_ht_cap->shortGI40MHz = 1; 5920 } else { 5921 p_ht_cap->supportedChannelWidthSet = 0; 5922 p_ht_cap->shortGI40MHz = 0; 5923 } 5924 5925 lim_populate_mcs_set_ht_per_vdev(mac_ctx, p_ht_cap, vdev_id, 5926 NSS_CHAINS_BAND_2GHZ); 5927 5928 nan_beamforming_supported = 5929 ucfg_nan_is_beamforming_supported(mac_ctx->psoc); 5930 if (device_mode == QDF_NDI_MODE && !nan_beamforming_supported) { 5931 p_ht_cap->txBF = 0; 5932 p_ht_cap->implicitTxBF = 0; 5933 p_ht_cap->explicitCSITxBF = 0; 5934 } 5935 5936 status_2g = lim_send_ie(mac_ctx, vdev_id, DOT11F_EID_HTCAPS, 5937 CDS_BAND_2GHZ, &ht_caps[2], 5938 DOT11F_IE_HTCAPS_MIN_LEN); 5939 /* 5940 * Get LDPC and over write for 5G - using channel 64 because it 5941 * is available in all reg domains. 5942 */ 5943 p_ht_cap->advCodingCap = lim_get_rx_ldpc(mac_ctx, CHAN_ENUM_5320); 5944 /* Get self cap for HT40 support in 5G */ 5945 if (mac_ctx->roam.configParam.channelBondingMode5GHz) { 5946 p_ht_cap->supportedChannelWidthSet = 1; 5947 p_ht_cap->shortGI40MHz = 1; 5948 } else { 5949 p_ht_cap->supportedChannelWidthSet = 0; 5950 p_ht_cap->shortGI40MHz = 0; 5951 } 5952 lim_populate_mcs_set_ht_per_vdev(mac_ctx, p_ht_cap, vdev_id, 5953 NSS_CHAINS_BAND_5GHZ); 5954 status_5g = lim_send_ie(mac_ctx, vdev_id, DOT11F_EID_HTCAPS, 5955 CDS_BAND_5GHZ, &ht_caps[2], 5956 DOT11F_IE_HTCAPS_MIN_LEN); 5957 5958 if (QDF_IS_STATUS_SUCCESS(status_2g) && 5959 QDF_IS_STATUS_SUCCESS(status_5g)) 5960 return QDF_STATUS_SUCCESS; 5961 5962 return QDF_STATUS_E_FAILURE; 5963 } 5964 5965 /** 5966 * lim_send_vht_caps_ie() - gets VHT capability and send to firmware via wma 5967 * @mac_ctx: global mac context 5968 * @device_mode: VDEV op mode 5969 * @vdev_id: vdev for which IE is targeted 5970 * 5971 * This function gets VHT capability and send to firmware via wma 5972 * 5973 * Return: QDF_STATUS 5974 */ 5975 static QDF_STATUS lim_send_vht_caps_ie(struct mac_context *mac_ctx, 5976 enum QDF_OPMODE device_mode, 5977 uint8_t vdev_id) 5978 { 5979 uint8_t vht_caps[DOT11F_IE_VHTCAPS_MAX_LEN + 2] = {0}; 5980 bool vht_for_2g_enabled = false, nan_beamforming_supported; 5981 tSirMacVHTCapabilityInfo *p_vht_cap = 5982 (tSirMacVHTCapabilityInfo *)(&vht_caps[2]); 5983 QDF_STATUS status_5g, status_2g; 5984 5985 vht_caps[0] = DOT11F_EID_VHTCAPS; 5986 vht_caps[1] = DOT11F_IE_VHTCAPS_MAX_LEN; 5987 lim_set_vht_caps(mac_ctx, vht_caps, DOT11F_IE_VHTCAPS_MIN_LEN + 2); 5988 /* 5989 * Get LDPC and over write for 5G - using channel 64 because it 5990 * is available in all reg domains. 5991 */ 5992 p_vht_cap->ldpcCodingCap = lim_get_rx_ldpc(mac_ctx, CHAN_ENUM_5320); 5993 lim_populate_mcs_set_vht_per_vdev(mac_ctx, vht_caps, vdev_id, 5994 NSS_CHAINS_BAND_5GHZ); 5995 5996 nan_beamforming_supported = 5997 ucfg_nan_is_beamforming_supported(mac_ctx->psoc); 5998 if (device_mode == QDF_NDI_MODE && !nan_beamforming_supported) { 5999 p_vht_cap->muBeamformeeCap = 0; 6000 p_vht_cap->muBeamformerCap = 0; 6001 p_vht_cap->suBeamformeeCap = 0; 6002 p_vht_cap->suBeamFormerCap = 0; 6003 } 6004 /* 6005 * Self VHT channel width for 5G is already negotiated 6006 * with FW 6007 */ 6008 status_5g = lim_send_ie(mac_ctx, vdev_id, DOT11F_EID_VHTCAPS, 6009 CDS_BAND_5GHZ, &vht_caps[2], 6010 DOT11F_IE_VHTCAPS_MIN_LEN); 6011 /* Send VHT CAP for 2.4G band based on CFG_ENABLE_VHT_FOR_24GHZ ini */ 6012 ucfg_mlme_get_vht_for_24ghz(mac_ctx->psoc, &vht_for_2g_enabled); 6013 6014 if (!vht_for_2g_enabled) 6015 return status_5g; 6016 6017 6018 /* Get LDPC and over write for 2G */ 6019 p_vht_cap->ldpcCodingCap = lim_get_rx_ldpc(mac_ctx, CHAN_ENUM_2437); 6020 /* Self VHT 80/160/80+80 channel width for 2G is 0 */ 6021 p_vht_cap->supportedChannelWidthSet = 0; 6022 p_vht_cap->shortGI80MHz = 0; 6023 p_vht_cap->shortGI160and80plus80MHz = 0; 6024 lim_populate_mcs_set_vht_per_vdev(mac_ctx, vht_caps, vdev_id, 6025 NSS_CHAINS_BAND_2GHZ); 6026 status_2g = lim_send_ie(mac_ctx, vdev_id, DOT11F_EID_VHTCAPS, 6027 CDS_BAND_2GHZ, &vht_caps[2], 6028 DOT11F_IE_VHTCAPS_MIN_LEN); 6029 6030 if (QDF_IS_STATUS_SUCCESS(status_2g) && 6031 QDF_IS_STATUS_SUCCESS(status_5g)) 6032 return QDF_STATUS_SUCCESS; 6033 6034 return QDF_STATUS_E_FAILURE; 6035 } 6036 6037 QDF_STATUS lim_send_ies_per_band(struct mac_context *mac_ctx, uint8_t vdev_id, 6038 enum csr_cfgdot11mode dot11_mode, 6039 enum QDF_OPMODE device_mode) 6040 { 6041 QDF_STATUS status_ht = QDF_STATUS_SUCCESS; 6042 QDF_STATUS status_vht = QDF_STATUS_SUCCESS; 6043 QDF_STATUS status_he = QDF_STATUS_SUCCESS; 6044 6045 /* 6046 * Note: Do not use Dot11f VHT structure, since 1 byte present flag in 6047 * it is causing weird padding errors. Instead use Sir Mac VHT struct 6048 * to send IE to wma. 6049 */ 6050 if (is_dot11mode_support_ht_cap(dot11_mode)) 6051 status_ht = lim_send_ht_caps_ie(mac_ctx, device_mode, vdev_id); 6052 6053 if (is_dot11mode_support_vht_cap(dot11_mode)) 6054 status_vht = lim_send_vht_caps_ie(mac_ctx, device_mode, vdev_id); 6055 6056 if (is_dot11mode_support_he_cap(dot11_mode)) { 6057 status_he = lim_send_he_caps_ie(mac_ctx, device_mode, vdev_id); 6058 6059 if (QDF_IS_STATUS_SUCCESS(status_he)) 6060 status_he = lim_send_he_6g_band_caps_ie(mac_ctx, 6061 vdev_id); 6062 } 6063 6064 if (is_dot11mode_support_eht_cap(dot11_mode)) 6065 status_he = lim_send_eht_caps_ie(mac_ctx, device_mode, vdev_id); 6066 6067 if (QDF_IS_STATUS_SUCCESS(status_ht) && 6068 QDF_IS_STATUS_SUCCESS(status_vht) && 6069 QDF_IS_STATUS_SUCCESS(status_he)) 6070 return QDF_STATUS_SUCCESS; 6071 6072 return QDF_STATUS_E_FAILURE; 6073 } 6074 6075 #ifdef WLAN_FEATURE_11AX 6076 static 6077 void lim_update_ext_cap_he_params(struct mac_context *mac_ctx, 6078 tDot11fIEExtCap *ext_cap_data, 6079 uint8_t vdev_id) 6080 { 6081 struct wlan_objmgr_vdev *vdev; 6082 struct mlme_legacy_priv *mlme_priv; 6083 tDot11fIEhe_cap *he_cap; 6084 struct s_ext_cap *p_ext_cap; 6085 6086 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc, vdev_id, 6087 WLAN_LEGACY_MAC_ID); 6088 if (!vdev) 6089 return; 6090 6091 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 6092 if (!mlme_priv) { 6093 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID); 6094 return; 6095 } 6096 6097 he_cap = &mlme_priv->he_config; 6098 6099 p_ext_cap = (struct s_ext_cap *)ext_cap_data->bytes; 6100 p_ext_cap->twt_requestor_support = he_cap->twt_request; 6101 p_ext_cap->twt_responder_support = he_cap->twt_responder; 6102 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID); 6103 6104 ext_cap_data->num_bytes = lim_compute_ext_cap_ie_length(ext_cap_data); 6105 } 6106 6107 /** 6108 * lim_update_ap_he_op() - update ap he op 6109 * @session: session 6110 * @ch_params: pointer to ch_params 6111 * 6112 * Return: void 6113 */ 6114 static void lim_update_ap_he_op(struct pe_session *session, 6115 struct ch_params *ch_params) 6116 { 6117 pe_debug("freq0: %d, freq1: %d, width: %d", 6118 ch_params->center_freq_seg0, ch_params->center_freq_seg1, 6119 ch_params->ch_width); 6120 if (session->he_op.vht_oper_present) { 6121 session->he_op.vht_oper.info.center_freq_seg0 = 6122 ch_params->center_freq_seg0; 6123 session->he_op.vht_oper.info.center_freq_seg1 = 6124 ch_params->center_freq_seg1; 6125 session->he_op.vht_oper.info.chan_width = 6126 ch_params->ch_width; 6127 } else if (session->he_6ghz_band) { 6128 session->he_op.oper_info_6g_present = 1; 6129 session->he_op.oper_info_6g.info.center_freq_seg0 = 6130 ch_params->center_freq_seg0; 6131 session->he_op.oper_info_6g.info.center_freq_seg1 = 6132 ch_params->center_freq_seg1; 6133 session->he_op.oper_info_6g.info.ch_width = 6134 ch_params->ch_width; 6135 } 6136 } 6137 #else 6138 static inline void 6139 lim_update_ext_cap_he_params(struct mac_context *mac_ctx, 6140 tDot11fIEExtCap *ext_cap_data, 6141 uint8_t vdev_id) 6142 {} 6143 6144 static void lim_update_ap_he_op(struct pe_session *session, 6145 struct ch_params *ch_params) 6146 {} 6147 #endif 6148 6149 /** 6150 * lim_send_ext_cap_ie() - send ext cap IE to FW 6151 * @mac_ctx: global MAC context 6152 * @session_entry: PE session 6153 * @extra_extcap: extracted ext cap 6154 * @merge: merge extra ext cap 6155 * 6156 * This function is invoked after VDEV is created to update firmware 6157 * about the extended capabilities that the corresponding VDEV is capable 6158 * of. Since STA/SAP can have different Extended capabilities set, this function 6159 * is called per vdev creation. 6160 * 6161 * Return: QDF_STATUS 6162 */ 6163 QDF_STATUS lim_send_ext_cap_ie(struct mac_context *mac_ctx, 6164 uint32_t vdev_id, 6165 tDot11fIEExtCap *extra_extcap, bool merge) 6166 { 6167 tDot11fIEExtCap ext_cap_data = {0}; 6168 uint32_t dot11mode, num_bytes; 6169 bool vht_enabled = false; 6170 struct vdev_ie_info *vdev_ie; 6171 struct scheduler_msg msg = {0}; 6172 QDF_STATUS status; 6173 6174 dot11mode = mac_ctx->mlme_cfg->dot11_mode.dot11_mode; 6175 if (IS_DOT11_MODE_VHT(dot11mode)) 6176 vht_enabled = true; 6177 6178 status = populate_dot11f_ext_cap(mac_ctx, vht_enabled, &ext_cap_data, 6179 NULL); 6180 if (QDF_STATUS_SUCCESS != status) { 6181 pe_err("Failed to populate ext cap IE"); 6182 return QDF_STATUS_E_FAILURE; 6183 } 6184 6185 lim_update_ext_cap_he_params(mac_ctx, &ext_cap_data, vdev_id); 6186 num_bytes = ext_cap_data.num_bytes; 6187 6188 if (merge && extra_extcap && extra_extcap->num_bytes > 0) { 6189 if (extra_extcap->num_bytes > ext_cap_data.num_bytes) 6190 num_bytes = extra_extcap->num_bytes; 6191 lim_merge_extcap_struct(&ext_cap_data, extra_extcap, true); 6192 } 6193 6194 /* Allocate memory for the WMI request, and copy the parameter */ 6195 vdev_ie = qdf_mem_malloc(sizeof(*vdev_ie) + num_bytes); 6196 if (!vdev_ie) 6197 return QDF_STATUS_E_NOMEM; 6198 6199 vdev_ie->vdev_id = vdev_id; 6200 vdev_ie->ie_id = DOT11F_EID_EXTCAP; 6201 vdev_ie->length = num_bytes; 6202 vdev_ie->band = 0; 6203 6204 vdev_ie->data = (uint8_t *)vdev_ie + sizeof(*vdev_ie); 6205 qdf_mem_copy(vdev_ie->data, ext_cap_data.bytes, num_bytes); 6206 6207 msg.type = WMA_SET_IE_INFO; 6208 msg.bodyptr = vdev_ie; 6209 msg.reserved = 0; 6210 6211 if (QDF_STATUS_SUCCESS != 6212 scheduler_post_message(QDF_MODULE_ID_PE, 6213 QDF_MODULE_ID_WMA, 6214 QDF_MODULE_ID_WMA, &msg)) { 6215 pe_err("Not able to post WMA_SET_IE_INFO to WDA"); 6216 qdf_mem_free(vdev_ie); 6217 return QDF_STATUS_E_FAILURE; 6218 } 6219 6220 return QDF_STATUS_SUCCESS; 6221 } 6222 6223 QDF_STATUS lim_strip_ie(struct mac_context *mac_ctx, 6224 uint8_t *addn_ie, uint16_t *addn_ielen, 6225 uint8_t eid, enum size_of_len_field size_of_len_field, 6226 uint8_t *oui, uint8_t oui_length, uint8_t *extracted_ie, 6227 uint32_t eid_max_len) 6228 { 6229 return wlan_strip_ie(addn_ie, addn_ielen, eid, size_of_len_field, 6230 oui, oui_length, extracted_ie, eid_max_len); 6231 } 6232 6233 void lim_del_pmf_sa_query_timer(struct mac_context *mac_ctx, struct pe_session *pe_session) 6234 { 6235 uint32_t associated_sta; 6236 tpDphHashNode sta_ds = NULL; 6237 6238 for (associated_sta = 1; 6239 associated_sta <= 6240 mac_ctx->lim.max_sta_of_pe_session; 6241 associated_sta++) { 6242 sta_ds = dph_get_hash_entry(mac_ctx, associated_sta, 6243 &pe_session->dph.dphHashTable); 6244 if (!sta_ds) 6245 continue; 6246 if (!sta_ds->rmfEnabled) { 6247 pe_debug("no PMF timer for assoc-id:%d sta mac" 6248 QDF_MAC_ADDR_FMT, sta_ds->assocId, 6249 QDF_MAC_ADDR_REF(sta_ds->staAddr)); 6250 continue; 6251 } 6252 6253 pe_debug("Deleting pmfSaQueryTimer for assoc-id:%d sta mac" 6254 QDF_MAC_ADDR_FMT, sta_ds->assocId, 6255 QDF_MAC_ADDR_REF(sta_ds->staAddr)); 6256 tx_timer_deactivate(&sta_ds->pmfSaQueryTimer); 6257 tx_timer_delete(&sta_ds->pmfSaQueryTimer); 6258 } 6259 } 6260 6261 QDF_STATUS lim_strip_supp_op_class_update_struct(struct mac_context *mac_ctx, 6262 uint8_t *addn_ie, uint16_t *addn_ielen, 6263 tDot11fIESuppOperatingClasses *dst) 6264 { 6265 uint8_t extracted_buff[DOT11F_IE_SUPPOPERATINGCLASSES_MAX_LEN + 2]; 6266 QDF_STATUS status; 6267 6268 qdf_mem_zero((uint8_t *)&extracted_buff[0], 6269 DOT11F_IE_SUPPOPERATINGCLASSES_MAX_LEN + 2); 6270 status = lim_strip_ie(mac_ctx, addn_ie, addn_ielen, 6271 DOT11F_EID_SUPPOPERATINGCLASSES, ONE_BYTE, 6272 NULL, 0, extracted_buff, 6273 DOT11F_IE_SUPPOPERATINGCLASSES_MAX_LEN); 6274 if (QDF_STATUS_SUCCESS != status) { 6275 pe_warn("Failed to strip supp_op_mode IE status: %d", 6276 status); 6277 return status; 6278 } 6279 6280 if (DOT11F_EID_SUPPOPERATINGCLASSES != extracted_buff[0] || 6281 extracted_buff[1] > DOT11F_IE_SUPPOPERATINGCLASSES_MAX_LEN) { 6282 pe_warn("Invalid IEs eid: %d elem_len: %d", 6283 extracted_buff[0], extracted_buff[1]); 6284 return QDF_STATUS_E_FAILURE; 6285 } 6286 6287 /* update the extracted supp op class to struct*/ 6288 if (DOT11F_PARSE_SUCCESS != dot11f_unpack_ie_supp_operating_classes( 6289 mac_ctx, &extracted_buff[2], extracted_buff[1], dst, false)) { 6290 pe_err("dot11f_unpack Parse Error"); 6291 return QDF_STATUS_E_FAILURE; 6292 } 6293 6294 return QDF_STATUS_SUCCESS; 6295 } 6296 6297 uint8_t lim_op_class_from_bandwidth(struct mac_context *mac_ctx, 6298 uint16_t channel_freq, 6299 enum phy_ch_width ch_bandwidth, 6300 enum offset_t offset) 6301 { 6302 uint8_t op_class = 0; 6303 uint16_t ch_behav_limit = BEHAV_NONE; 6304 uint8_t channel; 6305 6306 if (ch_bandwidth == CH_WIDTH_40MHZ && 6307 wlan_reg_is_24ghz_ch_freq(channel_freq)) { 6308 if (offset == BW40_LOW_PRIMARY) 6309 ch_behav_limit = BEHAV_BW40_LOW_PRIMARY; 6310 else 6311 ch_behav_limit = BEHAV_BW40_HIGH_PRIMARY; 6312 } else if (ch_bandwidth == CH_WIDTH_80P80MHZ) { 6313 ch_behav_limit = BEHAV_BW80_PLUS; 6314 } 6315 wlan_reg_freq_width_to_chan_op_class(mac_ctx->pdev, channel_freq, 6316 ch_width_in_mhz(ch_bandwidth), 6317 true, BIT(ch_behav_limit), 6318 &op_class, &channel); 6319 6320 return op_class; 6321 } 6322 6323 /** 6324 * lim_update_extcap_struct() - poputlate the dot11f structure 6325 * @mac_ctx: global MAC context 6326 * @buf: extracted IE buffer 6327 * @dst: extended capability IE structure to be updated 6328 * 6329 * This function is used to update the extended capability structure 6330 * with @buf. 6331 * 6332 * Return: None 6333 */ 6334 void lim_update_extcap_struct(struct mac_context *mac_ctx, 6335 uint8_t *buf, tDot11fIEExtCap *dst) 6336 { 6337 uint8_t out[DOT11F_IE_EXTCAP_MAX_LEN]; 6338 uint32_t status; 6339 6340 if (!buf) { 6341 pe_err("Invalid Buffer Address"); 6342 return; 6343 } 6344 6345 if (!dst) { 6346 pe_err("NULL dst pointer"); 6347 return; 6348 } 6349 6350 if (DOT11F_EID_EXTCAP != buf[0] || buf[1] > DOT11F_IE_EXTCAP_MAX_LEN) { 6351 pe_debug_rl("Invalid IEs eid: %d elem_len: %d", buf[0], buf[1]); 6352 return; 6353 } 6354 6355 qdf_mem_zero((uint8_t *)&out[0], DOT11F_IE_EXTCAP_MAX_LEN); 6356 qdf_mem_copy(&out[0], &buf[2], buf[1]); 6357 6358 status = dot11f_unpack_ie_ext_cap(mac_ctx, &out[0], 6359 buf[1], dst, false); 6360 if (DOT11F_PARSE_SUCCESS != status) 6361 pe_err("dot11f_unpack Parse Error %d", status); 6362 } 6363 6364 /** 6365 * lim_strip_extcap_update_struct - strip extended capability IE and populate 6366 * the dot11f structure 6367 * @mac_ctx: global MAC context 6368 * @addn_ie: Additional IE buffer 6369 * @addn_ielen: Length of additional IE 6370 * @dst: extended capability IE structure to be updated 6371 * 6372 * This function is used to strip extended capability IE from IE buffer and 6373 * update the passed structure. 6374 * 6375 * Return: QDF_STATUS 6376 */ 6377 QDF_STATUS lim_strip_extcap_update_struct(struct mac_context *mac_ctx, 6378 uint8_t *addn_ie, uint16_t *addn_ielen, tDot11fIEExtCap *dst) 6379 { 6380 uint8_t extracted_buff[DOT11F_IE_EXTCAP_MAX_LEN + 2]; 6381 QDF_STATUS status; 6382 6383 qdf_mem_zero((uint8_t *)&extracted_buff[0], 6384 DOT11F_IE_EXTCAP_MAX_LEN + 2); 6385 status = lim_strip_ie(mac_ctx, addn_ie, addn_ielen, 6386 DOT11F_EID_EXTCAP, ONE_BYTE, 6387 NULL, 0, extracted_buff, 6388 DOT11F_IE_EXTCAP_MAX_LEN); 6389 if (QDF_STATUS_SUCCESS != status) { 6390 pe_debug("Failed to strip extcap IE status: %d", status); 6391 return status; 6392 } 6393 6394 /* update the extracted ExtCap to struct*/ 6395 lim_update_extcap_struct(mac_ctx, extracted_buff, dst); 6396 return status; 6397 } 6398 6399 /** 6400 * lim_merge_extcap_struct() - merge extended capabilities info 6401 * @dst: destination extended capabilities 6402 * @src: source extended capabilities 6403 * @add: true if add the capabilities, false if strip the capabilities. 6404 * 6405 * This function is used to take @src info and add/strip it to/from 6406 * @dst extended capabilities info. 6407 * 6408 * Return: None 6409 */ 6410 void lim_merge_extcap_struct(tDot11fIEExtCap *dst, 6411 tDot11fIEExtCap *src, 6412 bool add) 6413 { 6414 uint8_t *tempdst = (uint8_t *)dst->bytes; 6415 uint8_t *tempsrc = (uint8_t *)src->bytes; 6416 uint8_t structlen = member_size(tDot11fIEExtCap, bytes); 6417 6418 /* Return if @src not present */ 6419 if (!src->present) 6420 return; 6421 6422 pe_debug("source extended capabilities length:%d", src->num_bytes); 6423 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, 6424 src->bytes, src->num_bytes); 6425 6426 /* Return if strip the capabilities from @dst which not present */ 6427 if (!dst->present && !add) 6428 return; 6429 6430 /* Merge the capabilities info in other cases */ 6431 while (tempdst && tempsrc && structlen--) { 6432 if (add) 6433 *tempdst |= *tempsrc; 6434 else 6435 *tempdst &= *tempsrc; 6436 tempdst++; 6437 tempsrc++; 6438 } 6439 dst->num_bytes = lim_compute_ext_cap_ie_length(dst); 6440 if (dst->num_bytes == 0) { 6441 dst->present = 0; 6442 } else { 6443 dst->present = 1; 6444 pe_debug("destination extended capabilities length: %d", 6445 dst->num_bytes); 6446 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, 6447 dst->bytes, dst->num_bytes); 6448 } 6449 } 6450 6451 /** 6452 * lim_send_action_frm_tb_ppdu_cfg_flush_cb() - flush TB PPDU cfg msg 6453 * @msg: Message pointer 6454 * 6455 * Flushes the send action frame in HE TB PPDU configuration message. 6456 * 6457 * Return: QDF_STATUS 6458 */ 6459 static QDF_STATUS 6460 lim_send_action_frm_tb_ppdu_cfg_flush_cb(struct scheduler_msg *msg) 6461 { 6462 if (msg->bodyptr) { 6463 qdf_mem_free(msg->bodyptr); 6464 msg->bodyptr = NULL; 6465 } 6466 return QDF_STATUS_SUCCESS; 6467 } 6468 6469 QDF_STATUS lim_send_action_frm_tb_ppdu_cfg(struct mac_context *mac_ctx, 6470 uint32_t vdev_id, uint8_t cfg) 6471 { 6472 tDot11fvendor_action_frame *frm; 6473 uint8_t frm_len = sizeof(*frm); 6474 struct pe_session *session; 6475 struct cfg_action_frm_tb_ppdu *cfg_msg; 6476 struct scheduler_msg msg = {0}; 6477 uint8_t *data_buf; 6478 6479 session = pe_find_session_by_vdev_id(mac_ctx, vdev_id); 6480 if (!session) { 6481 pe_err("pe session does not exist for vdev_id %d", 6482 vdev_id); 6483 return QDF_STATUS_E_FAILURE; 6484 } 6485 6486 data_buf = qdf_mem_malloc(frm_len + sizeof(*cfg_msg)); 6487 if (!data_buf) 6488 return QDF_STATUS_E_FAILURE; 6489 6490 cfg_msg = (struct cfg_action_frm_tb_ppdu *)data_buf; 6491 6492 frm = (tDot11fvendor_action_frame *)(data_buf + sizeof(*cfg_msg)); 6493 6494 frm->Category.category = ACTION_CATEGORY_VENDOR_SPECIFIC; 6495 6496 frm->vendor_oui.oui_data[0] = 0x00; 6497 frm->vendor_oui.oui_data[1] = 0xA0; 6498 frm->vendor_oui.oui_data[2] = 0xC6; 6499 6500 frm->vendor_action_subtype.subtype = 0xFF; 6501 6502 cfg_msg->vdev_id = vdev_id; 6503 cfg_msg->cfg = cfg; 6504 cfg_msg->frm_len = frm_len; 6505 cfg_msg->data = (uint8_t *)frm; 6506 6507 msg.type = WMA_CFG_VENDOR_ACTION_TB_PPDU; 6508 msg.bodyptr = cfg_msg; 6509 msg.reserved = 0; 6510 msg.flush_callback = lim_send_action_frm_tb_ppdu_cfg_flush_cb; 6511 6512 if (QDF_STATUS_SUCCESS != 6513 scheduler_post_message(QDF_MODULE_ID_PE, 6514 QDF_MODULE_ID_WMA, 6515 QDF_MODULE_ID_WMA, &msg)) { 6516 pe_err("Not able to post WMA_SET_IE_INFO to WDA"); 6517 qdf_mem_free(data_buf); 6518 return QDF_STATUS_E_FAILURE; 6519 } 6520 6521 return QDF_STATUS_SUCCESS; 6522 } 6523 6524 /** 6525 * lim_get_80Mhz_center_channel - finds 80 Mhz center channel 6526 * 6527 * @primary_channel: Primary channel for given 80 MHz band 6528 * 6529 * There are fixed 80MHz band and for each fixed band there is only one center 6530 * valid channel. Also location of primary channel decides what 80 MHz band will 6531 * it use, hence it decides what center channel will be used. This function 6532 * does thus calculation and returns the center channel. 6533 * 6534 * Return: center channel 6535 */ 6536 uint8_t 6537 lim_get_80Mhz_center_channel(uint8_t primary_channel) 6538 { 6539 if (primary_channel >= 36 && primary_channel <= 48) 6540 return (36+48)/2; 6541 if (primary_channel >= 52 && primary_channel <= 64) 6542 return (52+64)/2; 6543 if (primary_channel >= 100 && primary_channel <= 112) 6544 return (100+112)/2; 6545 if (primary_channel >= 116 && primary_channel <= 128) 6546 return (116+128)/2; 6547 if (primary_channel >= 132 && primary_channel <= 144) 6548 return (132+144)/2; 6549 if (primary_channel >= 149 && primary_channel <= 161) 6550 return (149+161)/2; 6551 6552 return INVALID_CHANNEL_ID; 6553 } 6554 6555 /** 6556 * lim_bss_type_to_string(): converts bss type enum to string. 6557 * @bss_type: enum value of bss_type. 6558 * 6559 * Return: Printable string for bss_type 6560 */ 6561 const char *lim_bss_type_to_string(const uint16_t bss_type) 6562 { 6563 switch (bss_type) { 6564 CASE_RETURN_STRING(eSIR_INFRASTRUCTURE_MODE); 6565 CASE_RETURN_STRING(eSIR_INFRA_AP_MODE); 6566 CASE_RETURN_STRING(eSIR_AUTO_MODE); 6567 CASE_RETURN_STRING(eSIR_NDI_MODE); 6568 default: 6569 return "Unknown bss_type"; 6570 } 6571 } 6572 6573 /** 6574 * lim_init_obss_params(): Initializes the OBSS Scan Parameters 6575 * @session: LIM session 6576 * @mac_ctx: Mac context 6577 * 6578 * Return: None 6579 */ 6580 void lim_init_obss_params(struct mac_context *mac_ctx, struct pe_session *session) 6581 { 6582 struct wlan_mlme_obss_ht40 *obss_ht40; 6583 6584 if (!(mac_ctx->mlme_cfg)) { 6585 pe_err("invalid mlme cfg"); 6586 return; 6587 } 6588 6589 obss_ht40 = &mac_ctx->mlme_cfg->obss_ht40; 6590 6591 session->obss_ht40_scanparam.obss_active_dwelltime = 6592 obss_ht40->active_dwelltime; 6593 6594 session->obss_ht40_scanparam.obss_passive_dwelltime = 6595 obss_ht40->passive_dwelltime; 6596 6597 session->obss_ht40_scanparam.obss_width_trigger_interval = 6598 obss_ht40->width_trigger_interval; 6599 6600 session->obss_ht40_scanparam.obss_active_total_per_channel = 6601 obss_ht40->active_per_channel; 6602 6603 session->obss_ht40_scanparam.obss_passive_total_per_channel = 6604 obss_ht40->passive_per_channel; 6605 6606 session->obss_ht40_scanparam.bsswidth_ch_trans_delay = 6607 obss_ht40->width_trans_delay; 6608 6609 session->obss_ht40_scanparam.obss_activity_threshold = 6610 obss_ht40->scan_activity_threshold; 6611 } 6612 6613 /** 6614 * lim_update_obss_scanparams(): Updates OBSS SCAN IE parameters to session 6615 * @session: LIM session 6616 * @scan_params: Scan parameters 6617 * 6618 * Return: None 6619 */ 6620 void lim_update_obss_scanparams(struct pe_session *session, 6621 tDot11fIEOBSSScanParameters *scan_params) 6622 { 6623 /* 6624 * If the received value is not in the range specified 6625 * by the Specification then it will be the default value 6626 * configured through cfg 6627 */ 6628 if ((scan_params->obssScanActiveDwell > 6629 cfg_min(CFG_OBSS_HT40_SCAN_ACTIVE_DWELL_TIME)) && 6630 (scan_params->obssScanActiveDwell < 6631 cfg_max(CFG_OBSS_HT40_SCAN_ACTIVE_DWELL_TIME))) 6632 session->obss_ht40_scanparam.obss_active_dwelltime = 6633 scan_params->obssScanActiveDwell; 6634 6635 if ((scan_params->obssScanPassiveDwell > 6636 cfg_min(CFG_OBSS_HT40_SCAN_PASSIVE_DWELL_TIME)) && 6637 (scan_params->obssScanPassiveDwell < 6638 cfg_max(CFG_OBSS_HT40_SCAN_PASSIVE_DWELL_TIME))) 6639 session->obss_ht40_scanparam.obss_passive_dwelltime = 6640 scan_params->obssScanPassiveDwell; 6641 6642 if ((scan_params->bssWidthChannelTransitionDelayFactor > 6643 cfg_min(CFG_OBSS_HT40_WIDTH_CH_TRANSITION_DELAY)) && 6644 (scan_params->bssWidthChannelTransitionDelayFactor < 6645 cfg_max(CFG_OBSS_HT40_WIDTH_CH_TRANSITION_DELAY))) 6646 session->obss_ht40_scanparam.bsswidth_ch_trans_delay = 6647 scan_params->bssWidthChannelTransitionDelayFactor; 6648 6649 if ((scan_params->obssScanActiveTotalPerChannel > 6650 cfg_min(CFG_OBSS_HT40_SCAN_ACTIVE_TOTAL_PER_CHANNEL)) && 6651 (scan_params->obssScanActiveTotalPerChannel < 6652 cfg_max(CFG_OBSS_HT40_SCAN_ACTIVE_TOTAL_PER_CHANNEL))) 6653 session->obss_ht40_scanparam.obss_active_total_per_channel = 6654 scan_params->obssScanActiveTotalPerChannel; 6655 6656 if ((scan_params->obssScanPassiveTotalPerChannel > 6657 cfg_min(CFG_OBSS_HT40_SCAN_PASSIVE_TOTAL_PER_CHANNEL)) && 6658 (scan_params->obssScanPassiveTotalPerChannel < 6659 cfg_max(CFG_OBSS_HT40_SCAN_PASSIVE_TOTAL_PER_CHANNEL))) 6660 session->obss_ht40_scanparam.obss_passive_total_per_channel = 6661 scan_params->obssScanPassiveTotalPerChannel; 6662 6663 if ((scan_params->bssChannelWidthTriggerScanInterval > 6664 cfg_min(CFG_OBSS_HT40_SCAN_WIDTH_TRIGGER_INTERVAL)) && 6665 (scan_params->bssChannelWidthTriggerScanInterval < 6666 cfg_max(CFG_OBSS_HT40_SCAN_WIDTH_TRIGGER_INTERVAL))) 6667 session->obss_ht40_scanparam.obss_width_trigger_interval = 6668 scan_params->bssChannelWidthTriggerScanInterval; 6669 6670 if ((scan_params->obssScanActivityThreshold > 6671 cfg_min(CFG_OBSS_HT40_SCAN_ACTIVITY_THRESHOLD)) && 6672 (scan_params->obssScanActivityThreshold < 6673 cfg_max(CFG_OBSS_HT40_SCAN_ACTIVITY_THRESHOLD))) 6674 session->obss_ht40_scanparam.obss_activity_threshold = 6675 scan_params->obssScanActivityThreshold; 6676 return; 6677 } 6678 6679 /** 6680 * lim_compute_ext_cap_ie_length - compute the length of ext cap ie 6681 * based on the bits set 6682 * @ext_cap: extended IEs structure 6683 * 6684 * Return: length of the ext cap ie, 0 means should not present 6685 */ 6686 uint8_t lim_compute_ext_cap_ie_length(tDot11fIEExtCap *ext_cap) 6687 { 6688 uint8_t i = DOT11F_IE_EXTCAP_MAX_LEN; 6689 6690 while (i) { 6691 if (ext_cap->bytes[i-1]) 6692 break; 6693 i--; 6694 } 6695 6696 return i; 6697 } 6698 6699 /** 6700 * lim_update_caps_info_for_bss - Update capability info for this BSS 6701 * 6702 * @mac_ctx: mac context 6703 * @caps: Pointer to capability info to be updated 6704 * @bss_caps: Capability info of the BSS 6705 * 6706 * Update the capability info in Assoc/Reassoc request frames and reset 6707 * the spectrum management, short preamble, immediate block ack bits 6708 * if the BSS does not support it 6709 * 6710 * Return: None 6711 */ 6712 void lim_update_caps_info_for_bss(struct mac_context *mac_ctx, 6713 uint16_t *caps, uint16_t bss_caps) 6714 { 6715 if (!(bss_caps & LIM_SPECTRUM_MANAGEMENT_BIT_MASK)) { 6716 *caps &= (~LIM_SPECTRUM_MANAGEMENT_BIT_MASK); 6717 pe_debug("Clearing spectrum management:no AP support"); 6718 } 6719 6720 if (!(bss_caps & LIM_SHORT_PREAMBLE_BIT_MASK)) { 6721 *caps &= (~LIM_SHORT_PREAMBLE_BIT_MASK); 6722 pe_debug("Clearing short preamble:no AP support"); 6723 } 6724 6725 if (!(bss_caps & LIM_IMMEDIATE_BLOCK_ACK_MASK)) { 6726 *caps &= (~LIM_IMMEDIATE_BLOCK_ACK_MASK); 6727 pe_debug("Clearing Immed Blk Ack:no AP support"); 6728 } 6729 } 6730 /** 6731 * lim_send_set_dtim_period(): Send SIR_HAL_SET_DTIM_PERIOD message 6732 * to set dtim period. 6733 * 6734 * @session: LIM session 6735 * @dtim_period: dtim value 6736 * @mac_ctx: Mac context 6737 * @return None 6738 */ 6739 void lim_send_set_dtim_period(struct mac_context *mac_ctx, uint8_t dtim_period, 6740 struct pe_session *session) 6741 { 6742 struct set_dtim_params *dtim_params = NULL; 6743 QDF_STATUS ret = QDF_STATUS_SUCCESS; 6744 struct scheduler_msg msg = {0}; 6745 6746 if (!session) { 6747 pe_err("Inavalid parameters"); 6748 return; 6749 } 6750 dtim_params = qdf_mem_malloc(sizeof(*dtim_params)); 6751 if (!dtim_params) 6752 return; 6753 dtim_params->dtim_period = dtim_period; 6754 dtim_params->session_id = session->smeSessionId; 6755 msg.type = WMA_SET_DTIM_PERIOD; 6756 msg.bodyptr = dtim_params; 6757 msg.bodyval = 0; 6758 pe_debug("Post WMA_SET_DTIM_PERIOD to WMA"); 6759 ret = wma_post_ctrl_msg(mac_ctx, &msg); 6760 if (QDF_STATUS_SUCCESS != ret) { 6761 pe_err("wma_post_ctrl_msg() failed"); 6762 qdf_mem_free(dtim_params); 6763 } 6764 } 6765 6766 /** 6767 * lim_is_valid_frame(): validate RX frame using last processed frame details 6768 * to find if it is duplicate frame. 6769 * 6770 * @last_processed_frm: last processed frame pointer. 6771 * @pRxPacketInfo: RX packet. 6772 * 6773 * Frame treat as duplicate: 6774 * if retry bit is set and 6775 * if source address and seq number matches with the last processed frame 6776 * 6777 * Return: false if duplicate frame, else true. 6778 */ 6779 bool lim_is_valid_frame(last_processed_msg *last_processed_frm, 6780 uint8_t *pRxPacketInfo) 6781 { 6782 uint16_t seq_num; 6783 tpSirMacMgmtHdr pHdr; 6784 6785 if (!pRxPacketInfo) { 6786 pe_err("Invalid RX frame"); 6787 return false; 6788 } 6789 6790 pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); 6791 6792 if (pHdr->fc.retry == 0) 6793 return true; 6794 6795 seq_num = (((pHdr->seqControl.seqNumHi << 6796 HIGH_SEQ_NUM_OFFSET) | 6797 pHdr->seqControl.seqNumLo)); 6798 6799 if (last_processed_frm->seq_num == seq_num && 6800 qdf_mem_cmp(last_processed_frm->sa, pHdr->sa, ETH_ALEN) == 0) { 6801 pe_err("Duplicate frame from "QDF_MAC_ADDR_FMT " Seq Number %d", 6802 QDF_MAC_ADDR_REF(pHdr->sa), seq_num); 6803 return false; 6804 } 6805 return true; 6806 } 6807 6808 /** 6809 * lim_update_last_processed_frame(): update new processed frame info to cache. 6810 * 6811 * @last_processed_frm: last processed frame pointer. 6812 * @pRxPacketInfo: Successfully processed RX packet. 6813 * 6814 * Return: None. 6815 */ 6816 void lim_update_last_processed_frame(last_processed_msg *last_processed_frm, 6817 uint8_t *pRxPacketInfo) 6818 { 6819 uint16_t seq_num; 6820 tpSirMacMgmtHdr pHdr; 6821 6822 if (!pRxPacketInfo) { 6823 pe_err("Invalid RX frame"); 6824 return; 6825 } 6826 6827 pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); 6828 seq_num = (((pHdr->seqControl.seqNumHi << 6829 HIGH_SEQ_NUM_OFFSET) | 6830 pHdr->seqControl.seqNumLo)); 6831 6832 qdf_mem_copy(last_processed_frm->sa, pHdr->sa, ETH_ALEN); 6833 last_processed_frm->seq_num = seq_num; 6834 } 6835 6836 #if defined(CONFIG_BAND_6GHZ) && defined(WLAN_FEATURE_11AX) 6837 static bool lim_support_6ghz_band_op_class(struct mac_context *mac_ctx, 6838 tDot11fIESuppOperatingClasses * 6839 op_class_ie) 6840 { 6841 uint16_t i; 6842 6843 if (!op_class_ie->present) 6844 return false; 6845 for (i = 0; i < op_class_ie->num_classes; i++) { 6846 if (wlan_reg_is_6ghz_op_class(mac_ctx->pdev, 6847 op_class_ie->classes[i])) 6848 break; 6849 } 6850 if (i < op_class_ie->num_classes) 6851 return true; 6852 6853 return false; 6854 } 6855 6856 void lim_ap_check_6g_compatible_peer(struct mac_context *mac_ctx, 6857 struct pe_session *session) 6858 { 6859 uint16_t i; 6860 tpDphHashNode sta_ds; 6861 bool legacy_client_present = false; 6862 6863 if (!LIM_IS_AP_ROLE(session)) 6864 return; 6865 6866 for (i = 1; i < session->dph.dphHashTable.size; i++) { 6867 sta_ds = dph_get_hash_entry(mac_ctx, i, 6868 &session->dph.dphHashTable); 6869 if (!sta_ds) 6870 continue; 6871 if (sta_ds->staType != STA_ENTRY_PEER) 6872 continue; 6873 if (!lim_support_6ghz_band_op_class( 6874 mac_ctx, &sta_ds->supp_operating_classes)) { 6875 legacy_client_present = true; 6876 pe_debug("peer "QDF_MAC_ADDR_FMT" 6ghz not supported", 6877 QDF_MAC_ADDR_REF(sta_ds->staAddr)); 6878 break; 6879 } 6880 pe_debug("peer "QDF_MAC_ADDR_FMT" 6ghz supported", 6881 QDF_MAC_ADDR_REF(sta_ds->staAddr)); 6882 } 6883 if (legacy_client_present) 6884 policy_mgr_set_ap_6ghz_capable( 6885 mac_ctx->psoc, session->vdev_id, false, 6886 CONN_6GHZ_FLAG_NO_LEGACY_CLIENT); 6887 else 6888 policy_mgr_set_ap_6ghz_capable( 6889 mac_ctx->psoc, session->vdev_id, true, 6890 CONN_6GHZ_FLAG_NO_LEGACY_CLIENT); 6891 } 6892 #endif 6893 6894 #ifdef WLAN_FEATURE_11AX 6895 void lim_update_he_6ghz_band_caps(struct mac_context *mac, 6896 tDot11fIEhe_6ghz_band_cap *he_6ghz_band_cap, 6897 tpAddStaParams params) 6898 { 6899 qdf_mem_copy(¶ms->he_6ghz_band_caps, he_6ghz_band_cap, 6900 sizeof(tDot11fIEhe_6ghz_band_cap)); 6901 6902 lim_log_he_6g_cap(mac, ¶ms->he_6ghz_band_caps); 6903 } 6904 6905 void lim_add_he_cap(struct mac_context *mac_ctx, struct pe_session *pe_session, 6906 tpAddStaParams add_sta_params, tpSirAssocReq assoc_req) 6907 { 6908 if (!add_sta_params->he_capable || !assoc_req) 6909 return; 6910 6911 qdf_mem_copy(&add_sta_params->he_config, &assoc_req->he_cap, 6912 sizeof(add_sta_params->he_config)); 6913 6914 if (lim_is_he_6ghz_band(pe_session)) 6915 lim_update_he_6ghz_band_caps(mac_ctx, 6916 &assoc_req->he_6ghz_band_cap, 6917 add_sta_params); 6918 6919 } 6920 6921 void lim_add_self_he_cap(tpAddStaParams add_sta_params, struct pe_session *session) 6922 { 6923 if (!session) 6924 return; 6925 6926 add_sta_params->he_capable = true; 6927 6928 qdf_mem_copy(&add_sta_params->he_config, &session->he_config, 6929 sizeof(add_sta_params->he_config)); 6930 qdf_mem_copy(&add_sta_params->he_op, &session->he_op, 6931 sizeof(add_sta_params->he_op)); 6932 } 6933 6934 static bool lim_check_is_bss_greater_than_4_nss_supp(struct pe_session *session, 6935 tDot11fIEhe_cap *he_cap) 6936 { 6937 uint8_t i; 6938 uint16_t mcs_map; 6939 #define NSS_4 4 6940 #define NSS_8 8 6941 6942 if (!session->he_capable || !he_cap->present) 6943 return false; 6944 mcs_map = he_cap->rx_he_mcs_map_lt_80; 6945 for (i = NSS_4; i < NSS_8; i++) { 6946 if (((mcs_map >> (i * 2)) & 0x3) != 0x3) 6947 return true; 6948 } 6949 6950 return false; 6951 } 6952 6953 bool lim_check_he_80_mcs11_supp(struct pe_session *session, 6954 tDot11fIEhe_cap *he_cap) 6955 { 6956 uint16_t rx_mcs_map; 6957 uint16_t tx_mcs_map; 6958 6959 rx_mcs_map = he_cap->rx_he_mcs_map_lt_80; 6960 tx_mcs_map = he_cap->tx_he_mcs_map_lt_80; 6961 if ((session->nss == NSS_1x1_MODE) && 6962 ((HE_GET_MCS_4_NSS(rx_mcs_map, 1) == HE_MCS_0_11) || 6963 (HE_GET_MCS_4_NSS(tx_mcs_map, 1) == HE_MCS_0_11))) 6964 return true; 6965 6966 if ((session->nss == NSS_2x2_MODE) && 6967 ((HE_GET_MCS_4_NSS(rx_mcs_map, 2) == HE_MCS_0_11) || 6968 (HE_GET_MCS_4_NSS(tx_mcs_map, 2) == HE_MCS_0_11))) 6969 return true; 6970 6971 return false; 6972 } 6973 6974 /** 6975 * lim_check_he_ldpc_cap() - set he ldpc coding to one if 6976 * channel width is > 20 or mcs 10/11 bit are supported or 6977 * nss is greater than 4. 6978 * @beacon_struct: beacon structure 6979 * @session: A pointer to session entry. 6980 * 6981 * Return: None 6982 */ 6983 6984 void lim_check_and_force_he_ldpc_cap(struct pe_session *session, 6985 tDot11fIEhe_cap *he_cap) 6986 { 6987 if (!he_cap->ldpc_coding && 6988 (session->ch_width > CH_WIDTH_20MHZ || 6989 lim_check_he_80_mcs11_supp(session, he_cap) || 6990 lim_check_is_bss_greater_than_4_nss_supp(session, he_cap))) 6991 he_cap->ldpc_coding = 1; 6992 } 6993 6994 /** 6995 * lim_intersect_he_caps() - Intersect peer capability and self capability 6996 * @rcvd_he: pointer to received peer capability 6997 * @peer_he: pointer to Intersected capability 6998 * @session: A pointer to session entry. 6999 * 7000 * Return: None 7001 */ 7002 static void lim_intersect_he_caps(tDot11fIEhe_cap *rcvd_he, 7003 tDot11fIEhe_cap *peer_he, 7004 struct pe_session *session) 7005 { 7006 uint8_t val; 7007 tDot11fIEhe_cap *session_he = &session->he_config; 7008 7009 qdf_mem_copy(peer_he, rcvd_he, sizeof(*peer_he)); 7010 7011 peer_he->fragmentation = QDF_MIN(session_he->fragmentation, 7012 peer_he->fragmentation); 7013 7014 peer_he->ldpc_coding &= session_he->ldpc_coding; 7015 lim_check_and_force_he_ldpc_cap(session, peer_he); 7016 7017 if (session_he->tb_ppdu_tx_stbc_lt_80mhz && peer_he->rx_stbc_lt_80mhz) 7018 peer_he->rx_stbc_lt_80mhz = 1; 7019 else 7020 peer_he->rx_stbc_lt_80mhz = 0; 7021 7022 if (session_he->rx_stbc_lt_80mhz && peer_he->tb_ppdu_tx_stbc_lt_80mhz) 7023 peer_he->tb_ppdu_tx_stbc_lt_80mhz = 1; 7024 else 7025 peer_he->tb_ppdu_tx_stbc_lt_80mhz = 0; 7026 7027 if (session_he->tb_ppdu_tx_stbc_gt_80mhz && peer_he->rx_stbc_gt_80mhz) 7028 peer_he->rx_stbc_gt_80mhz = 1; 7029 else 7030 peer_he->rx_stbc_gt_80mhz = 0; 7031 7032 if (session_he->rx_stbc_gt_80mhz && peer_he->tb_ppdu_tx_stbc_gt_80mhz) 7033 peer_he->tb_ppdu_tx_stbc_gt_80mhz = 1; 7034 else 7035 peer_he->tb_ppdu_tx_stbc_gt_80mhz = 0; 7036 7037 /* Tx Doppler is first bit and Rx Doppler is second bit */ 7038 if (session_he->doppler) { 7039 val = 0; 7040 if ((session_he->doppler & 0x1) && (peer_he->doppler & 0x10)) 7041 val |= (1 << 1); 7042 if ((session_he->doppler & 0x10) && (peer_he->doppler & 0x1)) 7043 val |= (1 << 0); 7044 peer_he->doppler = val; 7045 } 7046 7047 peer_he->su_beamformer = session_he->su_beamformee ? 7048 peer_he->su_beamformer : 0; 7049 peer_he->su_beamformee = (session_he->su_beamformer || 7050 session_he->mu_beamformer) ? 7051 peer_he->su_beamformee : 0; 7052 peer_he->mu_beamformer = session_he->su_beamformee ? 7053 peer_he->mu_beamformer : 0; 7054 7055 peer_he->twt_request = session_he->twt_responder ? 7056 peer_he->twt_request : 0; 7057 peer_he->twt_responder = session_he->twt_request ? 7058 peer_he->twt_responder : 0; 7059 } 7060 7061 void lim_intersect_sta_he_caps(struct mac_context *mac_ctx, 7062 tpSirAssocReq assoc_req, 7063 struct pe_session *session, 7064 tpDphHashNode sta_ds) 7065 { 7066 tDot11fIEhe_cap *rcvd_he = &assoc_req->he_cap; 7067 tDot11fIEhe_cap *peer_he = &sta_ds->he_config; 7068 7069 if (!sta_ds->mlmStaContext.he_capable) 7070 return; 7071 7072 /* If HE is not supported, do not fill sta_ds and return */ 7073 if (!IS_DOT11_MODE_HE(session->dot11mode)) 7074 return; 7075 7076 lim_intersect_he_caps(rcvd_he, peer_he, session); 7077 7078 /* If MCS 12/13 is supported from assoc QCN IE */ 7079 if (assoc_req->qcn_ie.present && 7080 assoc_req->qcn_ie.he_mcs13_attr.present) { 7081 sta_ds->he_mcs_12_13_map = 7082 assoc_req->qcn_ie.he_mcs13_attr.he_mcs_12_13_supp_80 | 7083 assoc_req->qcn_ie.he_mcs13_attr.he_mcs_12_13_supp_160 << 8; 7084 } else { 7085 return; 7086 } 7087 7088 /* Take intersection of FW capability for HE MCS 12/13 */ 7089 if (wlan_reg_is_24ghz_ch_freq(session->curr_op_freq)) 7090 sta_ds->he_mcs_12_13_map &= 7091 mac_ctx->mlme_cfg->he_caps.he_mcs_12_13_supp_2g; 7092 else 7093 sta_ds->he_mcs_12_13_map &= 7094 mac_ctx->mlme_cfg->he_caps.he_mcs_12_13_supp_5g; 7095 } 7096 7097 static bool 7098 lim_is_vendor_htc_he_ap(struct bss_description *bss_desc) 7099 { 7100 struct action_oui_search_attr vendor_ap_search_attr; 7101 uint16_t ie_len; 7102 7103 ie_len = wlan_get_ielen_from_bss_description(bss_desc); 7104 7105 vendor_ap_search_attr.ie_data = (uint8_t *)&bss_desc->ieFields[0]; 7106 vendor_ap_search_attr.ie_length = ie_len; 7107 7108 return wlan_get_vendor_ie_ptr_from_oui(SIR_MAC_BAD_HTC_HE_VENDOR_OUI1, 7109 SIR_MAC_BAD_HTC_HE_VENDOR_OUI_LEN, 7110 vendor_ap_search_attr.ie_data, 7111 ie_len) && 7112 wlan_get_vendor_ie_ptr_from_oui( 7113 SIR_MAC_BAD_HTC_HE_VENDOR_OUI2, 7114 SIR_MAC_BAD_HTC_HE_VENDOR_OUI_LEN, 7115 vendor_ap_search_attr.ie_data, 7116 ie_len); 7117 } 7118 7119 void lim_intersect_ap_he_caps(struct pe_session *session, 7120 struct bss_params *add_bss, 7121 tSchBeaconStruct *beacon, 7122 tpSirAssocRsp assoc_rsp, 7123 struct bss_description *bss_desc) 7124 { 7125 tDot11fIEhe_cap *rcvd_he; 7126 tDot11fIEhe_cap *peer_he = &add_bss->staContext.he_config; 7127 bool vendor_ap_present = false; 7128 7129 if (assoc_rsp && assoc_rsp->he_cap.present) 7130 rcvd_he = &assoc_rsp->he_cap; 7131 else 7132 rcvd_he = &beacon->he_cap; 7133 7134 lim_intersect_he_caps(rcvd_he, peer_he, session); 7135 peer_he->htc_he = rcvd_he->htc_he; 7136 vendor_ap_present = lim_is_vendor_htc_he_ap(bss_desc); 7137 if (vendor_ap_present) { 7138 if (session->he_config.htc_he && peer_he->htc_he) 7139 peer_he->htc_he = 1; 7140 else 7141 peer_he->htc_he = 0; 7142 pe_debug("intersected htc he is: %d", peer_he->htc_he); 7143 } 7144 7145 pe_debug("HTC HE: self: %d recvd: %d, peer: %d", 7146 session->he_config.htc_he, rcvd_he->htc_he, peer_he->htc_he); 7147 add_bss->staContext.he_capable = true; 7148 } 7149 7150 void lim_add_bss_he_cap(struct bss_params *add_bss, tpSirAssocRsp assoc_rsp) 7151 { 7152 tDot11fIEhe_cap *he_cap; 7153 tDot11fIEhe_op *he_op; 7154 7155 he_cap = &assoc_rsp->he_cap; 7156 he_op = &assoc_rsp->he_op; 7157 add_bss->he_capable = he_cap->present; 7158 if (he_cap) 7159 qdf_mem_copy(&add_bss->staContext.he_config, 7160 he_cap, sizeof(*he_cap)); 7161 if (he_op) 7162 qdf_mem_copy(&add_bss->staContext.he_op, 7163 he_op, sizeof(*he_op)); 7164 } 7165 7166 void lim_add_bss_he_cfg(struct bss_params *add_bss, struct pe_session *session) 7167 { 7168 add_bss->he_sta_obsspd = session->he_sta_obsspd; 7169 } 7170 7171 void lim_update_he_6gop_assoc_resp(struct bss_params *pAddBssParams, 7172 tDot11fIEhe_op *he_op, 7173 struct pe_session *pe_session) 7174 { 7175 if (!pe_session->he_6ghz_band) 7176 return; 7177 7178 if (!he_op->oper_info_6g_present) { 7179 pe_debug("6G operation info not present in beacon"); 7180 return; 7181 } 7182 if (!pe_session->ch_width) 7183 return; 7184 7185 pAddBssParams->ch_width = QDF_MIN(he_op->oper_info_6g.info.ch_width, 7186 pe_session->ch_width); 7187 7188 if (pAddBssParams->ch_width == CH_WIDTH_160MHZ) 7189 pAddBssParams->ch_width = pe_session->ch_width; 7190 pAddBssParams->staContext.ch_width = pAddBssParams->ch_width; 7191 } 7192 7193 void lim_update_stads_he_caps(struct mac_context *mac_ctx, 7194 tpDphHashNode sta_ds, tpSirAssocRsp assoc_rsp, 7195 struct pe_session *session_entry, 7196 tSchBeaconStruct *beacon) 7197 { 7198 /* If HE is not supported, do not fill sta_ds and return */ 7199 if (!IS_DOT11_MODE_HE(session_entry->dot11mode)) 7200 goto out; 7201 7202 if (!assoc_rsp->he_cap.present && beacon && beacon->he_cap.present) { 7203 /* Use beacon HE caps if assoc resp doesn't have he caps */ 7204 pe_debug("he_caps missing in assoc rsp"); 7205 qdf_mem_copy(&assoc_rsp->he_cap, &beacon->he_cap, 7206 sizeof(tDot11fIEhe_cap)); 7207 } 7208 7209 /* assoc resp and beacon doesn't have he caps */ 7210 if (!assoc_rsp->he_cap.present) 7211 goto out; 7212 7213 sta_ds->mlmStaContext.he_capable = assoc_rsp->he_cap.present; 7214 7215 /* setting ldpc_coding if any of assoc_rsp or beacon has ldpc_coding 7216 * enabled 7217 */ 7218 if (beacon) 7219 assoc_rsp->he_cap.ldpc_coding |= beacon->he_cap.ldpc_coding; 7220 lim_check_and_force_he_ldpc_cap(session_entry, &assoc_rsp->he_cap); 7221 if (beacon) 7222 beacon->he_cap.ldpc_coding = assoc_rsp->he_cap.ldpc_coding; 7223 7224 qdf_mem_copy(&sta_ds->he_config, &assoc_rsp->he_cap, 7225 sizeof(tDot11fIEhe_cap)); 7226 7227 /* If MCS 12/13 is supported by the assoc resp QCN IE */ 7228 if (assoc_rsp->qcn_ie.present && 7229 assoc_rsp->qcn_ie.he_mcs13_attr.present) { 7230 sta_ds->he_mcs_12_13_map = 7231 assoc_rsp->qcn_ie.he_mcs13_attr.he_mcs_12_13_supp_80 | 7232 assoc_rsp->qcn_ie.he_mcs13_attr.he_mcs_12_13_supp_160 << 8; 7233 } 7234 7235 /* Take intersection of the FW capability for HE MCS 12/13 */ 7236 if (wlan_reg_is_24ghz_ch_freq(session_entry->curr_op_freq)) 7237 sta_ds->he_mcs_12_13_map &= 7238 mac_ctx->mlme_cfg->he_caps.he_mcs_12_13_supp_2g; 7239 else 7240 sta_ds->he_mcs_12_13_map &= 7241 mac_ctx->mlme_cfg->he_caps.he_mcs_12_13_supp_5g; 7242 out: 7243 pe_debug("he_mcs_12_13_map: sta_ds 0x%x, 2g_fw 0x%x, 5g_fw 0x%x", 7244 sta_ds->he_mcs_12_13_map, 7245 mac_ctx->mlme_cfg->he_caps.he_mcs_12_13_supp_2g, 7246 mac_ctx->mlme_cfg->he_caps.he_mcs_12_13_supp_5g); 7247 lim_update_he_mcs_12_13_map(mac_ctx->psoc, 7248 session_entry->smeSessionId, 7249 sta_ds->he_mcs_12_13_map); 7250 7251 } 7252 7253 void lim_update_stads_he_6ghz_op(struct pe_session *session, 7254 tpDphHashNode sta_ds) 7255 { 7256 tDot11fIEhe_cap *peer_he = &sta_ds->he_config; 7257 enum phy_ch_width ch_width; 7258 7259 if (!session->he_6ghz_band) 7260 return; 7261 7262 if (!peer_he->present) { 7263 pe_debug("HE cap not present in peer"); 7264 return; 7265 } 7266 7267 if (peer_he->chan_width_3) 7268 ch_width = CH_WIDTH_80P80MHZ; 7269 else if (peer_he->chan_width_2) 7270 ch_width = CH_WIDTH_160MHZ; 7271 else if (peer_he->chan_width_1) 7272 ch_width = CH_WIDTH_80MHZ; 7273 else 7274 ch_width = CH_WIDTH_20MHZ; 7275 if (ch_width > session->ch_width) 7276 ch_width = session->ch_width; 7277 sta_ds->ch_width = ch_width; 7278 } 7279 7280 void lim_update_usr_he_cap(struct mac_context *mac_ctx, struct pe_session *session) 7281 { 7282 struct add_ie_params *add_ie = &session->add_ie_params; 7283 tDot11fIEhe_cap *he_cap = &session->he_config; 7284 struct he_cap_network_endian *he_cap_from_ie; 7285 uint8_t extracted_buff[DOT11F_IE_HE_CAP_MAX_LEN + 2]; 7286 QDF_STATUS status; 7287 struct wlan_vht_config *vht_cfg = &session->vht_config; 7288 struct mlme_legacy_priv *mlme_priv; 7289 7290 qdf_mem_zero(extracted_buff, sizeof(extracted_buff)); 7291 status = lim_strip_ie(mac_ctx, add_ie->probeRespBCNData_buff, 7292 &add_ie->probeRespBCNDataLen, 7293 DOT11F_EID_HE_CAP, ONE_BYTE, 7294 HE_CAP_OUI_TYPE, (uint8_t)HE_CAP_OUI_SIZE, 7295 extracted_buff, DOT11F_IE_HE_CAP_MAX_LEN); 7296 if (QDF_STATUS_SUCCESS != status) { 7297 pe_debug("Failed to strip HE cap IE status: %d", status); 7298 return; 7299 } 7300 7301 pe_debug("Before update: su_beamformer: %d, su_beamformee: %d, mu_beamformer: %d", 7302 he_cap->su_beamformer, he_cap->su_beamformee, he_cap->mu_beamformer); 7303 7304 he_cap_from_ie = (struct he_cap_network_endian *) 7305 &extracted_buff[HE_CAP_OUI_SIZE + 2]; 7306 7307 he_cap->su_beamformer = 7308 he_cap->su_beamformer & he_cap_from_ie->su_beamformer; 7309 he_cap->su_beamformee = 7310 he_cap->su_beamformee & he_cap_from_ie->su_beamformee; 7311 he_cap->mu_beamformer = 7312 he_cap->mu_beamformer & he_cap_from_ie->mu_beamformer; 7313 7314 pe_debug("After update: su_beamformer: %d, su_beamformee: %d, mu_beamformer: %d", 7315 he_cap->su_beamformer, he_cap->su_beamformee, he_cap->mu_beamformer); 7316 if (!he_cap->su_beamformer) { 7317 he_cap->mu_beamformer = 0; 7318 he_cap->num_sounding_lt_80 = 0; 7319 he_cap->num_sounding_gt_80 = 0; 7320 vht_cfg->su_beam_former = 0; 7321 vht_cfg->mu_beam_former = 0; 7322 vht_cfg->num_soundingdim = 0; 7323 } 7324 if (!he_cap->su_beamformee) { 7325 he_cap->bfee_sts_lt_80 = 0; 7326 he_cap->bfee_sts_gt_80 = 0; 7327 vht_cfg->su_beam_formee = 0; 7328 vht_cfg->mu_beam_formee = 0; 7329 vht_cfg->csnof_beamformer_antSup = 0; 7330 } 7331 7332 mlme_priv = wlan_vdev_mlme_get_ext_hdl(session->vdev); 7333 if (mlme_priv) { 7334 mlme_priv->he_config.mu_beamformer = he_cap->mu_beamformer; 7335 mlme_priv->he_config.su_beamformer = he_cap->su_beamformer; 7336 mlme_priv->he_config.su_beamformee = he_cap->su_beamformee; 7337 mlme_priv->he_config.bfee_sts_lt_80 = he_cap->bfee_sts_lt_80; 7338 mlme_priv->he_config.bfee_sts_gt_80 = he_cap->bfee_sts_gt_80; 7339 mlme_priv->he_config.num_sounding_lt_80 = 7340 he_cap->num_sounding_lt_80; 7341 mlme_priv->he_config.num_sounding_gt_80 = 7342 he_cap->num_sounding_gt_80; 7343 } 7344 wma_set_he_txbf_params(session->vdev_id, he_cap->su_beamformer, 7345 he_cap->su_beamformee, he_cap->mu_beamformer); 7346 } 7347 7348 void lim_decide_he_op(struct mac_context *mac_ctx, uint32_t *mlme_he_ops, 7349 struct pe_session *session) 7350 { 7351 uint32_t val; 7352 uint8_t color; 7353 struct he_ops_network_endian *he_ops_from_ie; 7354 tDot11fIEhe_op he_ops = {0}; 7355 struct add_ie_params *add_ie = &session->add_ie_params; 7356 uint8_t extracted_buff[DOT11F_IE_HE_OP_MAX_LEN + 2]; 7357 QDF_STATUS status; 7358 7359 qdf_mem_zero(extracted_buff, sizeof(extracted_buff)); 7360 status = lim_strip_ie(mac_ctx, add_ie->probeRespBCNData_buff, 7361 &add_ie->probeRespBCNDataLen, 7362 DOT11F_EID_HE_OP, ONE_BYTE, 7363 HE_OP_OUI_TYPE, (uint8_t)HE_OP_OUI_SIZE, 7364 extracted_buff, DOT11F_IE_HE_OP_MAX_LEN); 7365 if (QDF_STATUS_SUCCESS != status) { 7366 pe_debug("Failed to strip HE OP IE status: %d", status); 7367 return; 7368 } 7369 he_ops_from_ie = (struct he_ops_network_endian *) 7370 &extracted_buff[HE_OP_OUI_SIZE + 2]; 7371 7372 if (he_ops_from_ie->bss_color) { 7373 he_ops.bss_color = he_ops_from_ie->bss_color; 7374 } else { 7375 qdf_get_random_bytes(&color, sizeof(color)); 7376 /* make sure color is within 1-63*/ 7377 he_ops.bss_color = (color % WNI_CFG_HE_OPS_BSS_COLOR_MAX) + 1; 7378 } 7379 he_ops.default_pe = he_ops_from_ie->default_pe; 7380 he_ops.twt_required = he_ops_from_ie->twt_required; 7381 he_ops.txop_rts_threshold = he_ops_from_ie->txop_rts_threshold; 7382 he_ops.partial_bss_col = he_ops_from_ie->partial_bss_col; 7383 7384 val = mac_ctx->mlme_cfg->he_caps.he_ops_basic_mcs_nss; 7385 7386 *((uint16_t *)he_ops.basic_mcs_nss) = (uint16_t)val; 7387 7388 qdf_mem_copy(&session->he_op, &he_ops, sizeof(tDot11fIEhe_op)); 7389 7390 pe_debug("HE Op: bss_color: 0x%0x, default_pe_duration: 0x%0x", 7391 he_ops.bss_color, he_ops.default_pe); 7392 pe_debug("He Op: twt_required: 0x%0x, txop_rts_threshold: 0x%0x", 7393 he_ops.twt_required, he_ops.txop_rts_threshold); 7394 pe_debug("HE Op: partial_bss_color: 0x%0x", 7395 he_ops.partial_bss_col); 7396 pe_debug("HE Op: BSS color disabled: 0x%0x", 7397 he_ops.bss_col_disabled); 7398 pe_debug("HE Op: Basic MCS NSS: 0x%04x", 7399 *((uint16_t *)he_ops.basic_mcs_nss)); 7400 7401 wma_update_vdev_he_ops(mlme_he_ops, &he_ops); 7402 } 7403 7404 void lim_update_he_caps_mcs(struct mac_context *mac, struct pe_session *session) 7405 { 7406 uint32_t tx_mcs_map = 0; 7407 uint32_t rx_mcs_map = 0; 7408 uint32_t mcs_map = 0; 7409 struct wlan_objmgr_vdev *vdev = session->vdev; 7410 struct mlme_legacy_priv *mlme_priv; 7411 struct wlan_mlme_cfg *mlme_cfg = mac->mlme_cfg; 7412 7413 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 7414 if (!mlme_priv) 7415 return; 7416 7417 rx_mcs_map = mlme_cfg->he_caps.dot11_he_cap.rx_he_mcs_map_lt_80; 7418 tx_mcs_map = mlme_cfg->he_caps.dot11_he_cap.tx_he_mcs_map_lt_80; 7419 mcs_map = rx_mcs_map & 0x3; 7420 7421 if (session->nss == 1) { 7422 tx_mcs_map = HE_SET_MCS_4_NSS(tx_mcs_map, HE_MCS_DISABLE, 2); 7423 rx_mcs_map = HE_SET_MCS_4_NSS(rx_mcs_map, HE_MCS_DISABLE, 2); 7424 } else { 7425 tx_mcs_map = HE_SET_MCS_4_NSS(tx_mcs_map, mcs_map, 2); 7426 rx_mcs_map = HE_SET_MCS_4_NSS(rx_mcs_map, mcs_map, 2); 7427 } 7428 7429 mlme_priv->he_config.tx_he_mcs_map_lt_80 = tx_mcs_map; 7430 mlme_priv->he_config.rx_he_mcs_map_lt_80 = rx_mcs_map; 7431 *((uint16_t *)mlme_priv->he_config.tx_he_mcs_map_160) = tx_mcs_map; 7432 *((uint16_t *)mlme_priv->he_config.rx_he_mcs_map_160) = rx_mcs_map; 7433 qdf_mem_copy(mlme_priv->he_config.tx_he_mcs_map_160, &tx_mcs_map, 7434 sizeof(u_int16_t)); 7435 qdf_mem_copy(mlme_priv->he_config.rx_he_mcs_map_160, &rx_mcs_map, 7436 sizeof(u_int16_t)); 7437 } 7438 7439 static void 7440 lim_revise_req_he_cap_per_band(struct mlme_legacy_priv *mlme_priv, 7441 struct pe_session *session) 7442 { 7443 struct mac_context *mac = session->mac_ctx; 7444 tDot11fIEhe_cap *he_config; 7445 struct wlan_objmgr_psoc *psoc; 7446 uint32_t max_ampdu_len_exp; 7447 7448 psoc = wlan_vdev_get_psoc(session->vdev); 7449 if (!psoc) { 7450 pe_err("Failed to get psoc"); 7451 return; 7452 } 7453 max_ampdu_len_exp = cfg_get(psoc, CFG_HE_MAX_AMPDU_LEN); 7454 7455 he_config = &mlme_priv->he_config; 7456 if (wlan_reg_is_24ghz_ch_freq(session->curr_op_freq)) { 7457 he_config->bfee_sts_lt_80 = 7458 mac->he_cap_2g.bfee_sts_lt_80; 7459 he_config->tx_he_mcs_map_lt_80 = 7460 mac->he_cap_2g.tx_he_mcs_map_lt_80; 7461 he_config->rx_he_mcs_map_lt_80 = 7462 mac->he_cap_2g.rx_he_mcs_map_lt_80; 7463 he_config->max_ampdu_len_exp_ext = 7464 QDF_MIN(max_ampdu_len_exp, 7465 mac->he_cap_2g.max_ampdu_len_exp_ext); 7466 he_config->ul_2x996_tone_ru_supp = 0; 7467 he_config->num_sounding_gt_80 = 0; 7468 he_config->bfee_sts_gt_80 = 0; 7469 he_config->tb_ppdu_tx_stbc_gt_80mhz = 0; 7470 he_config->rx_stbc_gt_80mhz = 0; 7471 he_config->he_ppdu_20_in_160_80p80Mhz = 0; 7472 he_config->he_ppdu_80_in_160_80p80Mhz = 0; 7473 } else { 7474 he_config->bfee_sts_lt_80 = 7475 mac->he_cap_5g.bfee_sts_lt_80; 7476 he_config->tx_he_mcs_map_lt_80 = 7477 mac->he_cap_5g.tx_he_mcs_map_lt_80; 7478 he_config->rx_he_mcs_map_lt_80 = 7479 mac->he_cap_5g.rx_he_mcs_map_lt_80; 7480 7481 he_config->num_sounding_lt_80 = 7482 mac->he_cap_5g.num_sounding_lt_80; 7483 he_config->max_ampdu_len_exp_ext = 7484 QDF_MIN(max_ampdu_len_exp, 7485 mac->he_cap_5g.max_ampdu_len_exp_ext); 7486 if (he_config->chan_width_2 || 7487 he_config->chan_width_3) { 7488 he_config->bfee_sts_gt_80 = 7489 mac->he_cap_5g.bfee_sts_gt_80; 7490 he_config->num_sounding_gt_80 = 7491 mac->he_cap_5g.num_sounding_gt_80; 7492 he_config->he_ppdu_20_in_160_80p80Mhz = 7493 mac->he_cap_5g.he_ppdu_20_in_160_80p80Mhz; 7494 he_config->he_ppdu_80_in_160_80p80Mhz = 7495 mac->he_cap_5g.he_ppdu_80_in_160_80p80Mhz; 7496 he_config->rx_stbc_gt_80mhz = 7497 mac->he_cap_5g.rx_stbc_gt_80mhz; 7498 he_config->tb_ppdu_tx_stbc_gt_80mhz = 7499 mac->he_cap_5g.tb_ppdu_tx_stbc_gt_80mhz; 7500 he_config->ul_2x996_tone_ru_supp = 7501 mac->he_cap_5g.ul_2x996_tone_ru_supp; 7502 } 7503 he_config->su_feedback_tone16 = 7504 mac->he_cap_5g.su_feedback_tone16; 7505 he_config->mu_feedback_tone16 = 7506 mac->he_cap_5g.mu_feedback_tone16; 7507 he_config->codebook_su = mac->he_cap_5g.codebook_su; 7508 he_config->codebook_mu = mac->he_cap_5g.codebook_mu; 7509 } 7510 } 7511 7512 void lim_copy_bss_he_cap(struct pe_session *session) 7513 { 7514 struct mlme_legacy_priv *mlme_priv; 7515 7516 mlme_priv = wlan_vdev_mlme_get_ext_hdl(session->vdev); 7517 if (!mlme_priv) 7518 return; 7519 lim_revise_req_he_cap_per_band(mlme_priv, session); 7520 lim_update_he_caps_mcs(session->mac_ctx, session); 7521 qdf_mem_copy(&(session->he_config), &(mlme_priv->he_config), 7522 sizeof(session->he_config)); 7523 } 7524 7525 void lim_copy_join_req_he_cap(struct pe_session *session) 7526 { 7527 struct mlme_legacy_priv *mlme_priv; 7528 7529 mlme_priv = wlan_vdev_mlme_get_ext_hdl(session->vdev); 7530 if (!mlme_priv) 7531 return; 7532 if (!session->mac_ctx->usr_cfg_tx_bfee_nsts) 7533 lim_revise_req_he_cap_per_band(mlme_priv, session); 7534 qdf_mem_copy(&(session->he_config), &(mlme_priv->he_config), 7535 sizeof(session->he_config)); 7536 if (WLAN_REG_IS_24GHZ_CH_FREQ(session->curr_op_freq)) { 7537 session->he_config.chan_width_1 = 0; 7538 session->he_config.chan_width_2 = 0; 7539 session->he_config.chan_width_3 = 0; 7540 session->he_config.chan_width_5 = 0; 7541 session->he_config.chan_width_6 = 0; 7542 } else { 7543 session->he_config.chan_width_0 = 0; 7544 session->he_config.chan_width_4 = 0; 7545 session->he_config.chan_width_6 = 0; 7546 } 7547 } 7548 7549 void lim_log_he_cap(struct mac_context *mac, tDot11fIEhe_cap *he_cap) 7550 { 7551 uint8_t chan_width; 7552 struct ppet_hdr *hdr; 7553 7554 if (!he_cap->present) 7555 return; 7556 7557 pe_nofl_debug("HE Capabilities: htc_he 0x%x twt_req 0x%x twt_res 0x%x fragmentation 0x%x max frag msdu amsdu 0x%x min frag 0x%x", 7558 he_cap->htc_he, he_cap->twt_request, 7559 he_cap->twt_responder, he_cap->fragmentation, 7560 he_cap->max_num_frag_msdu_amsdu_exp, 7561 he_cap->min_frag_size); 7562 pe_nofl_debug("\ttrig frm mac pad 0x%x multi tid aggr supp 0x%x link adaptation 0x%x all ack 0x%x trigd_rsp_sched 0x%x a_bsr 0x%x", 7563 he_cap->trigger_frm_mac_pad, 7564 he_cap->multi_tid_aggr_rx_supp, 7565 he_cap->he_link_adaptation, he_cap->all_ack, 7566 he_cap->trigd_rsp_sched, he_cap->a_bsr); 7567 pe_nofl_debug("\tBC twt 0x%x ba_32bit_bitmap supp 0x%x mu_cascade 0x%x ack_enabled_multitid 0x%x omi_a_ctrl 0x%x ofdma_ra 0x%x", 7568 he_cap->broadcast_twt, he_cap->ba_32bit_bitmap, 7569 he_cap->mu_cascade, he_cap->ack_enabled_multitid, 7570 he_cap->omi_a_ctrl, he_cap->ofdma_ra); 7571 pe_nofl_debug("\tmax_ampdu_len exp ext 0x%x amsdu_frag 0x%x flex_twt_sched 0x%x rx_ctrl frm 0x%x bsrp_ampdu_aggr 0x%x qtp 0x%x a_bqr 0x%x", 7572 he_cap->max_ampdu_len_exp_ext, he_cap->amsdu_frag, 7573 he_cap->flex_twt_sched, he_cap->rx_ctrl_frame, 7574 he_cap->bsrp_ampdu_aggr, he_cap->qtp, he_cap->a_bqr); 7575 pe_nofl_debug("\tSR Reponder 0x%x ndp_feedback 0x%x ops_supp 0x%x amsdu_in_ampdu 0x%x multi_tid_aggr_tx 0x%x he_sub_ch_sel_tx 0x%x", 7576 he_cap->spatial_reuse_param_rspder, 7577 he_cap->ndp_feedback_supp, 7578 he_cap->ops_supp, he_cap->amsdu_in_ampdu, 7579 he_cap->multi_tid_aggr_tx_supp, 7580 he_cap->he_sub_ch_sel_tx_supp); 7581 7582 pe_nofl_debug("\tul_2x996_tone_ru 0x%x om_ctrl_ul_mu_data_dis_rx 0x%x dynamic_smps 0x%x punctured_sounding 0x%x ht_vht_trg_frm_rx 0x%x", 7583 he_cap->ul_2x996_tone_ru_supp, 7584 he_cap->om_ctrl_ul_mu_data_dis_rx, 7585 he_cap->he_dynamic_smps, he_cap->punctured_sounding_supp, 7586 he_cap->ht_vht_trg_frm_rx_supp); 7587 7588 chan_width = HE_CH_WIDTH_COMBINE(he_cap->chan_width_0, 7589 he_cap->chan_width_1, he_cap->chan_width_2, 7590 he_cap->chan_width_3, he_cap->chan_width_4, 7591 he_cap->chan_width_5, he_cap->chan_width_6); 7592 7593 pe_nofl_debug("\tchan width %d rx_pream_puncturing 0x%x device_class 0x%x ldpc_coding 0x%x 1x_ltf_800_gi_ppdu 0x%x midamble_tx_rx_max_nsts 0x%x", 7594 chan_width, he_cap->rx_pream_puncturing, 7595 he_cap->device_class, 7596 he_cap->ldpc_coding, he_cap->he_1x_ltf_800_gi_ppdu, 7597 he_cap->midamble_tx_rx_max_nsts); 7598 7599 pe_nofl_debug("\t4x_ltf_3200_gi_ndp 0x%x tb_ppdu_tx_stbc_lt_80mhz 0x%x rx_stbc_lt_80mhz 0x%x doppler 0x%x ul_mu 0x%x dcm_enc_tx 0x%x dcm_enc_rx 0x%x", 7600 he_cap->he_4x_ltf_3200_gi_ndp, 7601 he_cap->tb_ppdu_tx_stbc_lt_80mhz, 7602 he_cap->rx_stbc_lt_80mhz, he_cap->doppler, he_cap->ul_mu, 7603 he_cap->dcm_enc_tx, he_cap->dcm_enc_rx); 7604 7605 pe_nofl_debug("\tul_he_mu 0x%x su_bfer 0x%x su_fee 0x%x mu_bfer 0x%x bfee_sts_lt_80 0x%x bfee_sts_gt_80 0x%x num_sd_lt_80 0x%x num_sd_gt_80 0x%x", 7606 he_cap->ul_he_mu, he_cap->su_beamformer, 7607 he_cap->su_beamformee, 7608 he_cap->mu_beamformer, he_cap->bfee_sts_lt_80, 7609 he_cap->bfee_sts_gt_80, he_cap->num_sounding_lt_80, 7610 he_cap->num_sounding_gt_80); 7611 7612 pe_nofl_debug("\tsu_fb_tone16 0x%x mu_fb_tone16 0x%x codebook_su 0x%x codebook_mu 0x%x bforming_feedback 0x%x he_er_su_ppdu 0x%x dl_mu_mimo_part_bw 0x%x", 7613 he_cap->su_feedback_tone16, he_cap->mu_feedback_tone16, 7614 he_cap->codebook_su, he_cap->codebook_mu, 7615 he_cap->beamforming_feedback, he_cap->he_er_su_ppdu, 7616 he_cap->dl_mu_mimo_part_bw); 7617 7618 pe_nofl_debug("\tppet_present 0x%x srp 0x%x power_boost 0x%x ltf_800_gi_4x 0x%x tb_ppdu_tx_stbc_gt_80mhz 0x%x rx_stbc_gt_80mhz 0x%x max_nc 0x%x", 7619 he_cap->ppet_present, he_cap->srp, 7620 he_cap->power_boost, he_cap->he_ltf_800_gi_4x, 7621 he_cap->tb_ppdu_tx_stbc_gt_80mhz, 7622 he_cap->rx_stbc_gt_80mhz, he_cap->max_nc); 7623 7624 pe_nofl_debug("\ter_ltf_800_gi_4x 0x%x ppdu_20_in_40Mhz_2G 0x%x ppdu_20_in_160_80p80Mhz 0x%x ppdu_80_in_160_80p80Mhz 0x%x er_1x_ltf_gi 0x%x", 7625 he_cap->er_he_ltf_800_gi_4x, 7626 he_cap->he_ppdu_20_in_40Mhz_2G, 7627 he_cap->he_ppdu_20_in_160_80p80Mhz, 7628 he_cap->he_ppdu_80_in_160_80p80Mhz, 7629 he_cap->er_1x_he_ltf_gi); 7630 7631 pe_nofl_debug("\tmidamble_tx_rx_1x_ltf 0x%x dcm_max_bw 0x%x longer_than_16_he_sigb_ofdm_sym 0x%x non_trig_cqi_feedback 0x%x tx_1024_qam_lt_242_tone_ru 0x%x", 7632 he_cap->midamble_tx_rx_1x_he_ltf, he_cap->dcm_max_bw, 7633 he_cap->longer_than_16_he_sigb_ofdm_sym, 7634 he_cap->non_trig_cqi_feedback, 7635 he_cap->tx_1024_qam_lt_242_tone_ru); 7636 7637 pe_nofl_debug("\trx_1024_qam_lt_242_tone_ru 0x%x rx_full_bw_su_he_mu_compress_sigb 0x%x rx_he_mcs_map_lt_80 0x%x tx_he_mcs_map_lt_80 0x%x", 7638 he_cap->rx_1024_qam_lt_242_tone_ru, 7639 he_cap->rx_full_bw_su_he_mu_compress_sigb, 7640 he_cap->rx_he_mcs_map_lt_80, 7641 he_cap->tx_he_mcs_map_lt_80); 7642 7643 hdr = (struct ppet_hdr *)&he_cap->ppet; 7644 pe_nofl_debug("\tRx MCS map 160 Mhz: 0x%x Tx MCS map 160 Mhz: 0x%x Rx MCS map 80+80 Mhz: 0x%x Tx MCS map 80+80 Mhz: 0x%x ppe_th:: nss_count: %d, ru_idx_msk: %d", 7645 *((uint16_t *)he_cap->rx_he_mcs_map_160), 7646 *((uint16_t *)he_cap->tx_he_mcs_map_160), 7647 *((uint16_t *)he_cap->rx_he_mcs_map_80_80), 7648 *((uint16_t *)he_cap->tx_he_mcs_map_80_80), 7649 hdr->nss, hdr->ru_idx_mask); 7650 7651 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, 7652 &he_cap->ppet, HE_MAX_PPET_SIZE); 7653 } 7654 7655 void lim_log_he_op(struct mac_context *mac, tDot11fIEhe_op *he_ops, 7656 struct pe_session *session) 7657 { 7658 pe_debug("bss_color 0x%x, default_pe_dur 0x%x, twt_req 0x%x, txop_rts_thres 0x%x, vht_op 0x%x", 7659 he_ops->bss_color, he_ops->default_pe, 7660 he_ops->twt_required, he_ops->txop_rts_threshold, 7661 he_ops->vht_oper_present); 7662 pe_debug("\tpart_bss_color 0x%x, Co-located BSS 0x%x, BSS color dis 0x%x basic mcs nss: 0x%x", 7663 he_ops->partial_bss_col, he_ops->co_located_bss, 7664 he_ops->bss_col_disabled, 7665 *((uint16_t *)he_ops->basic_mcs_nss)); 7666 7667 if (!session->he_6ghz_band) { 7668 if (!he_ops->vht_oper_present) 7669 pe_debug("VHT Info not present in HE Operation"); 7670 else 7671 pe_debug("VHT Info: ch_bw %d cntr_freq0 %d cntr_freq1 %d", 7672 he_ops->vht_oper.info.chan_width, 7673 he_ops->vht_oper.info.center_freq_seg0, 7674 he_ops->vht_oper.info.center_freq_seg1); 7675 } else { 7676 if (!he_ops->oper_info_6g_present) 7677 pe_debug("6G op_info not present in HE Operation"); 7678 else 7679 pe_debug("6G_op_info:ch_bw %d cntr_freq0 %d cntr_freq1 %d dup_bcon %d, min_rate %d", 7680 he_ops->oper_info_6g.info.ch_width, 7681 he_ops->oper_info_6g.info.center_freq_seg0, 7682 he_ops->oper_info_6g.info.center_freq_seg1, 7683 he_ops->oper_info_6g.info.dup_bcon, 7684 he_ops->oper_info_6g.info.min_rate); 7685 } 7686 } 7687 7688 void lim_log_he_6g_cap(struct mac_context *mac, 7689 tDot11fIEhe_6ghz_band_cap *he_6g_cap) 7690 { 7691 pe_debug("min_mpdu_space: %0d, max_mpdu_len_exp: %0x, max_mpdu_len %0x, smps %0x, rd %0x rx_ant_ptn %d tx_ant_ptn %d", 7692 he_6g_cap->min_mpdu_start_spacing, 7693 he_6g_cap->max_ampdu_len_exp, he_6g_cap->max_mpdu_len, 7694 he_6g_cap->sm_pow_save, he_6g_cap->rd_responder, 7695 he_6g_cap->rx_ant_pattern_consistency, 7696 he_6g_cap->tx_ant_pattern_consistency); 7697 } 7698 7699 #ifdef WLAN_FEATURE_11AX_BSS_COLOR 7700 void lim_log_he_bss_color(struct mac_context *mac, 7701 tDot11fIEbss_color_change *he_bss_color) 7702 { 7703 pe_debug("countdown: %d, new_color: %d", 7704 he_bss_color->countdown, he_bss_color->new_color); 7705 } 7706 #endif 7707 7708 void lim_update_sta_he_capable(struct mac_context *mac, 7709 tpAddStaParams add_sta_params, tpDphHashNode sta_ds, 7710 struct pe_session *session_entry) 7711 { 7712 if (LIM_IS_AP_ROLE(session_entry)) 7713 add_sta_params->he_capable = sta_ds->mlmStaContext.he_capable && 7714 session_entry->he_capable; 7715 #ifdef FEATURE_WLAN_TDLS 7716 else if (STA_ENTRY_TDLS_PEER == sta_ds->staType) 7717 add_sta_params->he_capable = sta_ds->mlmStaContext.he_capable; 7718 #endif 7719 else 7720 add_sta_params->he_capable = session_entry->he_capable; 7721 7722 add_sta_params->he_mcs_12_13_map = sta_ds->he_mcs_12_13_map; 7723 pe_debug("he_capable: %d", add_sta_params->he_capable); 7724 } 7725 7726 void lim_update_bss_he_capable(struct mac_context *mac, 7727 struct bss_params *add_bss) 7728 { 7729 add_bss->he_capable = true; 7730 pe_debug("he_capable: %d", add_bss->he_capable); 7731 } 7732 7733 void lim_update_stads_he_capable(tpDphHashNode sta_ds, tpSirAssocReq assoc_req) 7734 { 7735 sta_ds->mlmStaContext.he_capable = assoc_req->he_cap.present; 7736 } 7737 7738 void lim_update_session_he_capable(struct mac_context *mac, struct pe_session *session) 7739 { 7740 session->he_capable = true; 7741 if (wlan_reg_is_6ghz_chan_freq(session->curr_op_freq)) { 7742 session->htCapability = 0; 7743 session->vhtCapability = 0; 7744 session->he_6ghz_band = 1; 7745 } 7746 if (wlan_reg_is_24ghz_ch_freq(session->curr_op_freq) && 7747 !mac->mlme_cfg->vht_caps.vht_cap_info.b24ghz_band) 7748 session->vhtCapability = 0; 7749 7750 if (!wlan_reg_is_24ghz_ch_freq(session->curr_op_freq)) { 7751 session->he_config.ul_mu = mac->he_cap_5g.ul_mu; 7752 session->he_config.rx_pream_puncturing = 7753 mac->he_cap_5g.rx_pream_puncturing; 7754 } 7755 } 7756 7757 void lim_update_session_he_capable_chan_switch(struct mac_context *mac, 7758 struct pe_session *session, 7759 uint32_t new_chan_freq) 7760 { 7761 session->he_capable = true; 7762 if (wlan_reg_is_6ghz_chan_freq(session->curr_op_freq) && 7763 !wlan_reg_is_6ghz_chan_freq(new_chan_freq)) { 7764 session->htCapability = 1; 7765 session->vhtCapability = 1; 7766 session->he_6ghz_band = 0; 7767 } else if (!wlan_reg_is_6ghz_chan_freq(session->curr_op_freq) && 7768 wlan_reg_is_6ghz_chan_freq(new_chan_freq)) { 7769 session->htCapability = 0; 7770 session->vhtCapability = 0; 7771 session->he_6ghz_band = 1; 7772 } 7773 7774 /* 7775 * If new channel is 2.4gh set VHT as per the b24ghz_band INI 7776 * if new channel is 5Ghz set the vht, this will happen if we move from 7777 * 2.4Ghz to 5Ghz. 7778 */ 7779 if (wlan_reg_is_24ghz_ch_freq(new_chan_freq) && 7780 !mac->mlme_cfg->vht_caps.vht_cap_info.b24ghz_band) 7781 session->vhtCapability = 0; 7782 else if (wlan_reg_is_5ghz_ch_freq(new_chan_freq)) 7783 session->vhtCapability = 1; 7784 /* 7785 * Re-initialize color bss parameters during channel change 7786 */ 7787 7788 session->he_op.bss_col_disabled = 1; 7789 session->bss_color_changing = 1; 7790 session->he_bss_color_change.new_color = session->he_op.bss_color; 7791 session->he_bss_color_change.countdown = BSS_COLOR_SWITCH_COUNTDOWN; 7792 pe_debug("he_capable: %d ht %d vht %d 6ghz_band %d new freq %d vht in 2.4gh %d", 7793 session->he_capable, session->htCapability, 7794 session->vhtCapability, session->he_6ghz_band, new_chan_freq, 7795 mac->mlme_cfg->vht_caps.vht_cap_info.b24ghz_band); 7796 } 7797 7798 void lim_set_he_caps(struct mac_context *mac, uint8_t *ie_start, 7799 uint32_t num_bytes, uint8_t band) 7800 { 7801 const uint8_t *ie = NULL; 7802 tDot11fIEhe_cap dot11_cap; 7803 struct he_capability_info *he_cap; 7804 bool is_band_2g = false; 7805 7806 if (band == CDS_BAND_2GHZ) 7807 is_band_2g = true; 7808 7809 populate_dot11f_he_caps_by_band(mac, is_band_2g, &dot11_cap, 7810 NULL); 7811 lim_log_he_cap(mac, &dot11_cap); 7812 ie = wlan_get_ext_ie_ptr_from_ext_id(HE_CAP_OUI_TYPE, 7813 HE_CAP_OUI_SIZE, ie_start, num_bytes); 7814 if (ie) { 7815 /* convert from unpacked to packed structure */ 7816 he_cap = (struct he_capability_info *) &ie[2 + HE_CAP_OUI_SIZE]; 7817 7818 he_cap->htc_he = dot11_cap.htc_he; 7819 he_cap->twt_request = dot11_cap.twt_request; 7820 he_cap->twt_responder = dot11_cap.twt_responder; 7821 he_cap->fragmentation = dot11_cap.fragmentation; 7822 he_cap->max_num_frag_msdu_amsdu_exp = 7823 dot11_cap.max_num_frag_msdu_amsdu_exp; 7824 he_cap->min_frag_size = dot11_cap.min_frag_size; 7825 he_cap->trigger_frm_mac_pad = dot11_cap.trigger_frm_mac_pad; 7826 he_cap->multi_tid_aggr_rx_supp = 7827 dot11_cap.multi_tid_aggr_rx_supp; 7828 he_cap->he_link_adaptation = dot11_cap.he_link_adaptation; 7829 he_cap->all_ack = dot11_cap.all_ack; 7830 he_cap->trigd_rsp_sched = dot11_cap.trigd_rsp_sched; 7831 he_cap->a_bsr = dot11_cap.a_bsr; 7832 he_cap->broadcast_twt = dot11_cap.broadcast_twt; 7833 he_cap->ba_32bit_bitmap = dot11_cap.ba_32bit_bitmap; 7834 he_cap->mu_cascade = dot11_cap.mu_cascade; 7835 he_cap->ack_enabled_multitid = dot11_cap.ack_enabled_multitid; 7836 he_cap->omi_a_ctrl = dot11_cap.omi_a_ctrl; 7837 he_cap->ofdma_ra = dot11_cap.ofdma_ra; 7838 he_cap->max_ampdu_len_exp_ext = dot11_cap.max_ampdu_len_exp_ext; 7839 he_cap->amsdu_frag = dot11_cap.amsdu_frag; 7840 he_cap->flex_twt_sched = dot11_cap.flex_twt_sched; 7841 he_cap->rx_ctrl_frame = dot11_cap.rx_ctrl_frame; 7842 7843 he_cap->bsrp_ampdu_aggr = dot11_cap.bsrp_ampdu_aggr; 7844 he_cap->qtp = dot11_cap.qtp; 7845 he_cap->a_bqr = dot11_cap.a_bqr; 7846 he_cap->spatial_reuse_param_rspder = 7847 dot11_cap.spatial_reuse_param_rspder; 7848 he_cap->ops_supp = dot11_cap.ops_supp; 7849 he_cap->ndp_feedback_supp = dot11_cap.ndp_feedback_supp; 7850 he_cap->amsdu_in_ampdu = dot11_cap.amsdu_in_ampdu; 7851 7852 if (!mac->roam.configParam.channelBondingMode5GHz) { 7853 /* 7854 * clearing bits for setting 20MHz support 7855 */ 7856 dot11_cap.chan_width_1 = 7857 HE_CH_WIDTH_CLR_BIT(dot11_cap.chan_width_1, 0); 7858 dot11_cap.chan_width_2 = 7859 HE_CH_WIDTH_CLR_BIT(dot11_cap.chan_width_2, 0); 7860 dot11_cap.chan_width_3 = 7861 HE_CH_WIDTH_CLR_BIT(dot11_cap.chan_width_3, 0); 7862 he_cap->he_ppdu_20_in_160_80p80Mhz = 0; 7863 } 7864 he_cap->chan_width = HE_CH_WIDTH_COMBINE(dot11_cap.chan_width_0, 7865 dot11_cap.chan_width_1, dot11_cap.chan_width_2, 7866 dot11_cap.chan_width_3, dot11_cap.chan_width_4, 7867 dot11_cap.chan_width_5, dot11_cap.chan_width_6); 7868 7869 he_cap->rx_pream_puncturing = dot11_cap.rx_pream_puncturing; 7870 he_cap->device_class = dot11_cap.device_class; 7871 he_cap->ldpc_coding = dot11_cap.ldpc_coding; 7872 he_cap->he_1x_ltf_800_gi_ppdu = dot11_cap.he_1x_ltf_800_gi_ppdu; 7873 he_cap->midamble_tx_rx_max_nsts = 7874 dot11_cap.midamble_tx_rx_max_nsts; 7875 he_cap->he_4x_ltf_3200_gi_ndp = dot11_cap.he_4x_ltf_3200_gi_ndp; 7876 he_cap->tb_ppdu_tx_stbc_lt_80mhz = 7877 dot11_cap.tb_ppdu_tx_stbc_lt_80mhz; 7878 he_cap->rx_stbc_lt_80mhz = dot11_cap.rx_stbc_lt_80mhz; 7879 he_cap->tb_ppdu_tx_stbc_gt_80mhz = 7880 dot11_cap.tb_ppdu_tx_stbc_gt_80mhz; 7881 he_cap->rx_stbc_gt_80mhz = dot11_cap.rx_stbc_gt_80mhz; 7882 he_cap->doppler = dot11_cap.doppler; 7883 he_cap->ul_mu = dot11_cap.ul_mu; 7884 he_cap->dcm_enc_tx = dot11_cap.dcm_enc_tx; 7885 he_cap->dcm_enc_rx = dot11_cap.dcm_enc_rx; 7886 he_cap->ul_he_mu = dot11_cap.ul_he_mu; 7887 he_cap->su_beamformer = dot11_cap.su_beamformer; 7888 7889 he_cap->su_beamformee = dot11_cap.su_beamformee; 7890 he_cap->mu_beamformer = dot11_cap.mu_beamformer; 7891 he_cap->bfee_sts_lt_80 = dot11_cap.bfee_sts_lt_80; 7892 he_cap->bfee_sts_gt_80 = dot11_cap.bfee_sts_gt_80; 7893 he_cap->num_sounding_lt_80 = dot11_cap.num_sounding_lt_80; 7894 he_cap->num_sounding_gt_80 = dot11_cap.num_sounding_gt_80; 7895 he_cap->su_feedback_tone16 = dot11_cap.su_feedback_tone16; 7896 he_cap->mu_feedback_tone16 = dot11_cap.mu_feedback_tone16; 7897 he_cap->codebook_su = dot11_cap.codebook_su; 7898 he_cap->codebook_mu = dot11_cap.codebook_mu; 7899 he_cap->beamforming_feedback = dot11_cap.beamforming_feedback; 7900 he_cap->he_er_su_ppdu = dot11_cap.he_er_su_ppdu; 7901 he_cap->dl_mu_mimo_part_bw = dot11_cap.dl_mu_mimo_part_bw; 7902 he_cap->ppet_present = dot11_cap.ppet_present; 7903 he_cap->srp = dot11_cap.srp; 7904 he_cap->power_boost = dot11_cap.power_boost; 7905 7906 he_cap->tx_1024_qam_lt_242_tone_ru = 7907 dot11_cap.tx_1024_qam_lt_242_tone_ru; 7908 he_cap->rx_1024_qam_lt_242_tone_ru = 7909 dot11_cap.rx_1024_qam_lt_242_tone_ru; 7910 7911 he_cap->he_ltf_800_gi_4x = dot11_cap.he_ltf_800_gi_4x; 7912 he_cap->max_nc = dot11_cap.max_nc; 7913 he_cap->er_he_ltf_800_gi_4x = dot11_cap.er_he_ltf_800_gi_4x; 7914 he_cap->he_ppdu_20_in_40Mhz_2G = 7915 dot11_cap.he_ppdu_20_in_40Mhz_2G; 7916 he_cap->he_ppdu_20_in_160_80p80Mhz = 7917 dot11_cap.he_ppdu_20_in_160_80p80Mhz; 7918 he_cap->he_ppdu_80_in_160_80p80Mhz = 7919 dot11_cap.he_ppdu_80_in_160_80p80Mhz; 7920 he_cap->er_1x_he_ltf_gi = 7921 dot11_cap.er_1x_he_ltf_gi; 7922 he_cap->midamble_tx_rx_1x_he_ltf = 7923 dot11_cap.midamble_tx_rx_1x_he_ltf; 7924 he_cap->reserved2 = dot11_cap.reserved2; 7925 7926 he_cap->rx_he_mcs_map_lt_80 = dot11_cap.rx_he_mcs_map_lt_80; 7927 he_cap->tx_he_mcs_map_lt_80 = dot11_cap.tx_he_mcs_map_lt_80; 7928 if (dot11_cap.chan_width_2) { 7929 he_cap->rx_he_mcs_map_160 = 7930 *((uint16_t *)dot11_cap.rx_he_mcs_map_160); 7931 he_cap->tx_he_mcs_map_160 = 7932 *((uint16_t *)dot11_cap.tx_he_mcs_map_160); 7933 ie_start[1] += HE_CAP_160M_MCS_MAP_LEN; 7934 } 7935 if (dot11_cap.chan_width_3) { 7936 he_cap->rx_he_mcs_map_80_80 = 7937 *((uint16_t *)dot11_cap.rx_he_mcs_map_80_80); 7938 he_cap->tx_he_mcs_map_80_80 = 7939 *((uint16_t *)dot11_cap.tx_he_mcs_map_80_80); 7940 ie_start[1] += HE_CAP_80P80_MCS_MAP_LEN; 7941 } 7942 } 7943 } 7944 7945 static void lim_intersect_he_ch_width_2g(struct mac_context *mac, 7946 struct he_capability_info *he_cap, 7947 uint8_t vdev_id) 7948 { 7949 struct wlan_objmgr_psoc *psoc; 7950 uint32_t cbm_24ghz; 7951 7952 psoc = mac->psoc; 7953 if (!psoc) 7954 return; 7955 7956 cbm_24ghz = lim_get_sta_cb_mode_for_24ghz(mac, vdev_id); 7957 7958 pe_debug("channel bonding mode 2.4GHz %d", cbm_24ghz); 7959 7960 if (!cbm_24ghz) { 7961 /* B0: 40Mhz channel width in the 2.4GHz band */ 7962 he_cap->chan_width = HE_CH_WIDTH_CLR_BIT(he_cap->chan_width, 0); 7963 he_cap->he_ppdu_20_in_40Mhz_2G = 0; 7964 } 7965 7966 pe_debug("HE cap: chan_width: 0x%07x he_ppdu_20_in_40Mhz_2G %d", 7967 he_cap->chan_width, he_cap->he_ppdu_20_in_40Mhz_2G); 7968 } 7969 7970 static uint8_t lim_set_he_caps_ppet(struct mac_context *mac, uint8_t *ie, 7971 enum cds_band_type band) 7972 { 7973 uint8_t ppe_th[WNI_CFG_HE_PPET_LEN] = {0}; 7974 /* Append at the end after ID + LEN + OUI + IE_Data */ 7975 uint8_t offset = ie[1] + 1 + 1 + 1; 7976 uint8_t num_ppe_th; 7977 7978 if (band == CDS_BAND_2GHZ) 7979 qdf_mem_copy(ppe_th, mac->mlme_cfg->he_caps.he_ppet_2g, 7980 WNI_CFG_HE_PPET_LEN); 7981 else if (band == CDS_BAND_5GHZ) 7982 qdf_mem_copy(ppe_th, mac->mlme_cfg->he_caps.he_ppet_5g, 7983 WNI_CFG_HE_PPET_LEN); 7984 else 7985 return 0; 7986 7987 num_ppe_th = lim_truncate_ppet(ppe_th, WNI_CFG_HE_PPET_LEN); 7988 7989 qdf_mem_copy(ie + offset, ppe_th, num_ppe_th); 7990 7991 return num_ppe_th; 7992 } 7993 7994 QDF_STATUS lim_send_he_caps_ie(struct mac_context *mac_ctx, 7995 enum QDF_OPMODE device_mode, 7996 uint8_t vdev_id) 7997 { 7998 uint8_t he_caps[SIR_MAC_HE_CAP_MIN_LEN + HE_CAP_OUI_LEN + 7999 HE_CAP_160M_MCS_MAP_LEN + HE_CAP_80P80_MCS_MAP_LEN + 8000 WNI_CFG_HE_PPET_LEN]; 8001 struct he_capability_info *he_cap; 8002 QDF_STATUS status_5g, status_2g; 8003 uint8_t he_cap_total_len = SIR_MAC_HE_CAP_MIN_LEN + HE_CAP_OUI_LEN + 8004 HE_CAP_160M_MCS_MAP_LEN + 8005 HE_CAP_80P80_MCS_MAP_LEN; 8006 uint8_t num_ppe_th = 0; 8007 bool nan_beamforming_supported; 8008 bool disable_nan_tx_bf = false, value = false; 8009 8010 /* Sending only minimal info(no PPET) to FW now, update if required */ 8011 qdf_mem_zero(he_caps, he_cap_total_len); 8012 he_caps[0] = DOT11F_EID_HE_CAP; 8013 he_caps[1] = SIR_MAC_HE_CAP_MIN_LEN; 8014 qdf_mem_copy(&he_caps[2], HE_CAP_OUI_TYPE, HE_CAP_OUI_SIZE); 8015 lim_set_he_caps(mac_ctx, he_caps, he_cap_total_len, 8016 CDS_BAND_5GHZ); 8017 he_cap = (struct he_capability_info *) (&he_caps[2 + HE_CAP_OUI_SIZE]); 8018 8019 nan_beamforming_supported = 8020 ucfg_nan_is_beamforming_supported(mac_ctx->psoc); 8021 if (device_mode == QDF_NDI_MODE && !nan_beamforming_supported) { 8022 he_cap->su_beamformee = 0; 8023 he_cap->su_beamformer = 0; 8024 he_cap->mu_beamformer = 0; 8025 he_cap->bfee_sts_gt_80 = 0; 8026 he_cap->bfee_sts_lt_80 = 0; 8027 he_cap->num_sounding_gt_80 = 0; 8028 he_cap->num_sounding_lt_80 = 0; 8029 he_cap->su_feedback_tone16 = 0; 8030 he_cap->mu_feedback_tone16 = 0; 8031 disable_nan_tx_bf = true; 8032 } 8033 8034 /* 8035 * For 5G band HE cap, set the beamformee STS <= 80Mhz to 8036 * mac->he_cap_5g.bfee_sts_lt_80 to keep the values same 8037 * as initial connection 8038 */ 8039 if (!disable_nan_tx_bf) { 8040 he_cap->bfee_sts_lt_80 = mac_ctx->he_cap_5g.bfee_sts_lt_80; 8041 he_cap->bfee_sts_gt_80 = mac_ctx->he_cap_5g.bfee_sts_gt_80; 8042 he_cap->num_sounding_gt_80 = 8043 mac_ctx->he_cap_5g.num_sounding_gt_80; 8044 pe_debug("he_cap_5g: bfee_sts_gt_80 %d num_sounding_gt_80 %d", 8045 he_cap->bfee_sts_gt_80, he_cap->num_sounding_gt_80); 8046 } 8047 8048 if (he_cap->ppet_present) 8049 num_ppe_th = lim_set_he_caps_ppet(mac_ctx, he_caps, 8050 CDS_BAND_5GHZ); 8051 8052 if ((device_mode == QDF_STA_MODE) || 8053 (device_mode == QDF_P2P_CLIENT_MODE)) { 8054 ucfg_twt_cfg_get_requestor(mac_ctx->psoc, &value); 8055 if (!value) { 8056 he_cap->twt_request = false; 8057 he_cap->flex_twt_sched = false; 8058 } 8059 he_cap->twt_responder = false; 8060 } else if ((device_mode == QDF_SAP_MODE) || 8061 (device_mode == QDF_P2P_GO_MODE)) { 8062 ucfg_twt_cfg_get_responder(mac_ctx->psoc, &value); 8063 if (!value) { 8064 he_cap->twt_responder = false; 8065 he_cap->flex_twt_sched = false; 8066 } 8067 he_cap->twt_request = false; 8068 } 8069 8070 status_5g = lim_send_ie(mac_ctx, vdev_id, DOT11F_EID_HE_CAP, 8071 CDS_BAND_5GHZ, &he_caps[2], 8072 he_caps[1] + 1 + num_ppe_th); 8073 if (QDF_IS_STATUS_ERROR(status_5g)) 8074 pe_err("Unable send HE Cap IE for 5GHZ band, status: %d", 8075 status_5g); 8076 8077 qdf_mem_zero(he_caps, he_cap_total_len); 8078 he_caps[0] = DOT11F_EID_HE_CAP; 8079 he_caps[1] = SIR_MAC_HE_CAP_MIN_LEN; 8080 qdf_mem_copy(&he_caps[2], HE_CAP_OUI_TYPE, HE_CAP_OUI_SIZE); 8081 lim_set_he_caps(mac_ctx, he_caps, he_cap_total_len, 8082 CDS_BAND_2GHZ); 8083 he_cap = (struct he_capability_info *)(&he_caps[2 + HE_CAP_OUI_SIZE]); 8084 8085 /* 8086 * For 5G band HE cap, set the beamformee STS <= 80Mhz to 8087 * mac->he_cap_5g.bfee_sts_lt_80 to keep the values same 8088 * as initial connection 8089 */ 8090 if (!disable_nan_tx_bf) { 8091 he_cap->bfee_sts_lt_80 = mac_ctx->he_cap_2g.bfee_sts_lt_80; 8092 he_cap->bfee_sts_gt_80 = mac_ctx->he_cap_2g.bfee_sts_gt_80; 8093 he_cap->num_sounding_gt_80 = 8094 mac_ctx->he_cap_2g.num_sounding_gt_80; 8095 pe_debug("he_cap_2g: bfee_sts_gt_80 %d num_sounding_gt_80 %d", 8096 he_cap->bfee_sts_gt_80, he_cap->num_sounding_gt_80); 8097 } 8098 lim_intersect_he_ch_width_2g(mac_ctx, he_cap, vdev_id); 8099 8100 if (he_cap->ppet_present) 8101 num_ppe_th = lim_set_he_caps_ppet(mac_ctx, he_caps, 8102 CDS_BAND_2GHZ); 8103 8104 status_2g = lim_send_ie(mac_ctx, vdev_id, DOT11F_EID_HE_CAP, 8105 CDS_BAND_2GHZ, &he_caps[2], 8106 he_caps[1] + 1 + num_ppe_th); 8107 if (QDF_IS_STATUS_ERROR(status_2g)) 8108 pe_err("Unable send HE Cap IE for 2GHZ band, status: %d", 8109 status_2g); 8110 8111 if (QDF_IS_STATUS_SUCCESS(status_2g) && 8112 QDF_IS_STATUS_SUCCESS(status_5g)) 8113 return QDF_STATUS_SUCCESS; 8114 8115 return QDF_STATUS_E_FAILURE; 8116 } 8117 8118 /** 8119 * lim_populate_he_mcs_per_bw() - pouldate HE mcs set per BW (le 80, 160, 80+80) 8120 * @mac_ctx: Global MAC context 8121 * @self_rx: self rx mcs set 8122 * @self_tx: self tx mcs set 8123 * @peer_rx: peer rx mcs set 8124 * @peer_tx: peer tx mcs set 8125 * @nss: nss 8126 * @cfg_rx_param: rx wni param to read 8127 * @cfg_tx_param: tx wni param to read 8128 * 8129 * MCS values are interpreted as in IEEE 11ax-D1.4 spec onwards 8130 * +-----------------------------------------------------+ 8131 * | SS8 | SS7 | SS6 | SS5 | SS4 | SS3 | SS2 | SS1 | 8132 * +-----------------------------------------------------+ 8133 * | 15-14 | 13-12 | 11-10 | 9-8 | 7-6 | 5-4 | 3-2 | 1-0 | 8134 * +-----------------------------------------------------+ 8135 * 8136 * Return: status of operation 8137 */ 8138 QDF_STATUS lim_populate_he_mcs_per_bw(struct mac_context *mac_ctx, 8139 uint16_t *supp_rx_mcs, 8140 uint16_t *supp_tx_mcs, 8141 uint16_t peer_rx, uint16_t peer_tx, 8142 uint8_t nss, uint16_t rx_mcs, 8143 uint16_t tx_mcs) 8144 { 8145 8146 pe_debug("peer rates: rx_mcs - 0x%04x tx_mcs - 0x%04x", 8147 peer_rx, peer_tx); 8148 8149 pe_debug("self rates: rx_mcs - 0x%04x tx_mcs - 0x%04x", 8150 rx_mcs, tx_mcs); 8151 8152 *supp_tx_mcs = HE_INTERSECT_MCS(rx_mcs, peer_tx); 8153 *supp_rx_mcs = HE_INTERSECT_MCS(tx_mcs, peer_rx); 8154 8155 if (nss == NSS_1x1_MODE) { 8156 *supp_rx_mcs |= HE_MCS_INV_MSK_4_NSS(1); 8157 *supp_tx_mcs |= HE_MCS_INV_MSK_4_NSS(1); 8158 } 8159 /* if nss is 2, disable higher NSS */ 8160 if (nss == NSS_2x2_MODE) { 8161 *supp_rx_mcs |= (HE_MCS_INV_MSK_4_NSS(1) & 8162 HE_MCS_INV_MSK_4_NSS(2)); 8163 *supp_tx_mcs |= (HE_MCS_INV_MSK_4_NSS(1) & 8164 HE_MCS_INV_MSK_4_NSS(2)); 8165 } 8166 8167 return QDF_STATUS_SUCCESS; 8168 } 8169 8170 QDF_STATUS lim_populate_he_mcs_set(struct mac_context *mac_ctx, 8171 struct supported_rates *rates, 8172 tDot11fIEhe_cap *peer_he_caps, 8173 struct pe_session *session_entry, uint8_t nss) 8174 { 8175 bool support_2x2 = false; 8176 uint32_t self_sta_dot11mode = mac_ctx->mlme_cfg->dot11_mode.dot11_mode; 8177 8178 if (!IS_DOT11_MODE_HE(self_sta_dot11mode)) 8179 return QDF_STATUS_SUCCESS; 8180 8181 if ((!peer_he_caps) || (!peer_he_caps->present)) { 8182 pe_debug("peer not he capable or he_caps NULL"); 8183 return QDF_STATUS_SUCCESS; 8184 } 8185 8186 if (!session_entry) { 8187 pe_err("session is NULL"); 8188 return QDF_STATUS_E_FAILURE; 8189 } 8190 8191 pe_debug("session chan width: %d", session_entry->ch_width); 8192 pe_debug("PEER: lt 80: rx 0x%04x tx 0x%04x, 160: rx 0x%04x tx 0x%04x, 80+80: rx 0x%04x tx 0x%04x", 8193 peer_he_caps->rx_he_mcs_map_lt_80, 8194 peer_he_caps->tx_he_mcs_map_lt_80, 8195 (*(uint16_t *)peer_he_caps->rx_he_mcs_map_160), 8196 (*(uint16_t *)peer_he_caps->tx_he_mcs_map_160), 8197 (*(uint16_t *)peer_he_caps->rx_he_mcs_map_80_80), 8198 (*(uint16_t *)peer_he_caps->tx_he_mcs_map_80_80)); 8199 8200 if (nss == NSS_2x2_MODE) { 8201 if (mac_ctx->mlme_cfg->gen.as_enabled && 8202 wlan_reg_is_24ghz_ch_freq(session_entry->curr_op_freq)) { 8203 if (IS_2X2_CHAIN(session_entry->chainMask)) 8204 support_2x2 = true; 8205 else 8206 pe_err("2x2 not enabled %d", 8207 session_entry->chainMask); 8208 } else { 8209 support_2x2 = true; 8210 } 8211 } 8212 8213 if (wlan_reg_is_24ghz_ch_freq(session_entry->curr_op_freq)) 8214 lim_populate_he_mcs_per_bw(mac_ctx, 8215 &rates->rx_he_mcs_map_lt_80, 8216 &rates->tx_he_mcs_map_lt_80, 8217 peer_he_caps->rx_he_mcs_map_lt_80, 8218 peer_he_caps->tx_he_mcs_map_lt_80, nss, 8219 mac_ctx->he_cap_2g.rx_he_mcs_map_lt_80, 8220 mac_ctx->he_cap_2g.tx_he_mcs_map_lt_80); 8221 else 8222 lim_populate_he_mcs_per_bw(mac_ctx, 8223 &rates->rx_he_mcs_map_lt_80, 8224 &rates->tx_he_mcs_map_lt_80, 8225 peer_he_caps->rx_he_mcs_map_lt_80, 8226 peer_he_caps->tx_he_mcs_map_lt_80, nss, 8227 mac_ctx->he_cap_5g.rx_he_mcs_map_lt_80, 8228 mac_ctx->he_cap_5g.tx_he_mcs_map_lt_80); 8229 8230 if ((session_entry->ch_width == CH_WIDTH_160MHZ || 8231 lim_is_session_chwidth_320mhz(session_entry)) && 8232 peer_he_caps->chan_width_2) { 8233 lim_populate_he_mcs_per_bw( 8234 mac_ctx, &rates->rx_he_mcs_map_160, 8235 &rates->tx_he_mcs_map_160, 8236 *((uint16_t *)peer_he_caps->rx_he_mcs_map_160), 8237 *((uint16_t *)peer_he_caps->tx_he_mcs_map_160), 8238 nss, 8239 *((uint16_t *)mac_ctx->mlme_cfg->he_caps.dot11_he_cap. 8240 rx_he_mcs_map_160), 8241 *((uint16_t *)mac_ctx->mlme_cfg->he_caps.dot11_he_cap. 8242 tx_he_mcs_map_160)); 8243 } else { 8244 rates->tx_he_mcs_map_160 = HE_MCS_ALL_DISABLED; 8245 rates->rx_he_mcs_map_160 = HE_MCS_ALL_DISABLED; 8246 } 8247 if (session_entry->ch_width == CH_WIDTH_80P80MHZ) { 8248 lim_populate_he_mcs_per_bw( 8249 mac_ctx, &rates->rx_he_mcs_map_80_80, 8250 &rates->tx_he_mcs_map_80_80, 8251 *((uint16_t *)peer_he_caps->rx_he_mcs_map_80_80), 8252 *((uint16_t *)peer_he_caps->tx_he_mcs_map_80_80), nss, 8253 *((uint16_t *)mac_ctx->mlme_cfg->he_caps.dot11_he_cap. 8254 rx_he_mcs_map_80_80), 8255 *((uint16_t *)mac_ctx->mlme_cfg->he_caps.dot11_he_cap. 8256 tx_he_mcs_map_80_80)); 8257 } else { 8258 rates->tx_he_mcs_map_80_80 = HE_MCS_ALL_DISABLED; 8259 rates->rx_he_mcs_map_80_80 = HE_MCS_ALL_DISABLED; 8260 } 8261 if (!support_2x2) { 8262 /* disable 2 and higher NSS MCS sets */ 8263 rates->rx_he_mcs_map_lt_80 |= HE_MCS_INV_MSK_4_NSS(1); 8264 rates->tx_he_mcs_map_lt_80 |= HE_MCS_INV_MSK_4_NSS(1); 8265 rates->rx_he_mcs_map_160 |= HE_MCS_INV_MSK_4_NSS(1); 8266 rates->tx_he_mcs_map_160 |= HE_MCS_INV_MSK_4_NSS(1); 8267 rates->rx_he_mcs_map_80_80 |= HE_MCS_INV_MSK_4_NSS(1); 8268 rates->tx_he_mcs_map_80_80 |= HE_MCS_INV_MSK_4_NSS(1); 8269 } 8270 8271 pe_debug("lt 80: rx 0x%x tx 0x%x, 160: rx 0x%x tx 0x%x, 80_80: rx 0x%x tx 0x%x", 8272 rates->rx_he_mcs_map_lt_80, rates->tx_he_mcs_map_lt_80, 8273 rates->rx_he_mcs_map_160, rates->tx_he_mcs_map_160, 8274 rates->rx_he_mcs_map_80_80, rates->tx_he_mcs_map_80_80); 8275 8276 return QDF_STATUS_SUCCESS; 8277 } 8278 #endif 8279 8280 #ifdef WLAN_FEATURE_11BE_MLO 8281 void lim_update_sta_mlo_info(struct pe_session *session, 8282 tpAddStaParams add_sta_params, 8283 tpDphHashNode sta_ds) 8284 { 8285 if (lim_is_mlo_conn(session, sta_ds)) { 8286 WLAN_ADDR_COPY(add_sta_params->mld_mac_addr, sta_ds->mld_addr); 8287 add_sta_params->is_assoc_peer = lim_is_mlo_recv_assoc(sta_ds); 8288 } 8289 pe_debug("is mlo connection: %d mld mac " QDF_MAC_ADDR_FMT " assoc peer %d", 8290 lim_is_mlo_conn(session, sta_ds), 8291 QDF_MAC_ADDR_REF(add_sta_params->mld_mac_addr), 8292 add_sta_params->is_assoc_peer); 8293 } 8294 8295 void lim_set_mlo_caps(struct mac_context *mac, struct pe_session *session, 8296 uint8_t *ie_start, uint32_t num_bytes) 8297 { 8298 const uint8_t *ie = NULL; 8299 struct wlan_mlo_ie dot11_cap; 8300 struct wlan_mlo_ie_info *mlo_ie_info; 8301 8302 populate_dot11f_mlo_caps(mac, session, &dot11_cap); 8303 8304 ie = wlan_get_ext_ie_ptr_from_ext_id(MLO_IE_OUI_TYPE, 8305 MLO_IE_OUI_SIZE, 8306 ie_start, num_bytes); 8307 8308 if (ie) { 8309 /* convert from unpacked to packed structure */ 8310 mlo_ie_info = (struct wlan_mlo_ie_info *)&ie[2 + MLO_IE_OUI_SIZE]; 8311 8312 mlo_ie_info->type = dot11_cap.type; 8313 mlo_ie_info->reserved = dot11_cap.reserved; 8314 mlo_ie_info->link_id_info_present = 8315 dot11_cap.link_id_info_present; 8316 mlo_ie_info->bss_param_change_cnt_present = 8317 dot11_cap.bss_param_change_cnt_present; 8318 mlo_ie_info->medium_sync_delay_info_present = 8319 dot11_cap.medium_sync_delay_info_present; 8320 mlo_ie_info->eml_capab_present = dot11_cap.eml_capab_present; 8321 mlo_ie_info->mld_capab_and_op_present = dot11_cap.mld_capab_and_op_present; 8322 mlo_ie_info->mld_id_present = dot11_cap.mld_id_present; 8323 mlo_ie_info->ext_mld_capab_and_op_present = 8324 dot11_cap.ext_mld_capab_and_op_present; 8325 mlo_ie_info->reserved_1 = dot11_cap.reserved_1; 8326 mlo_ie_info->common_info_length = dot11_cap.common_info_length; 8327 qdf_mem_copy(&mlo_ie_info->mld_mac_addr, 8328 &dot11_cap.mld_mac_addr, 8329 QDF_MAC_ADDR_SIZE); 8330 ie_start[1] += QDF_MAC_ADDR_SIZE; 8331 } 8332 } 8333 8334 QDF_STATUS lim_send_mlo_caps_ie(struct mac_context *mac_ctx, 8335 struct wlan_objmgr_vdev *vdev, 8336 enum QDF_OPMODE device_mode, 8337 uint8_t vdev_id) 8338 { 8339 8340 QDF_STATUS status_2g, status_5g; 8341 struct wlan_mlo_ie mlo_ie; 8342 8343 populate_dot11f_mlo_ie(mac_ctx, vdev, &mlo_ie); 8344 status_2g = lim_send_ie(mac_ctx, vdev_id, DOT11F_EID_MLO_IE, 8345 CDS_BAND_2GHZ, &mlo_ie.data[2], 8346 mlo_ie.num_data - 2); 8347 8348 status_5g = lim_send_ie(mac_ctx, vdev_id, DOT11F_EID_MLO_IE, 8349 CDS_BAND_5GHZ, &mlo_ie.data[2], 8350 mlo_ie.num_data - 2); 8351 8352 if (QDF_IS_STATUS_SUCCESS(status_2g) && 8353 QDF_IS_STATUS_SUCCESS(status_5g)) { 8354 return QDF_STATUS_SUCCESS; 8355 } 8356 return QDF_STATUS_SUCCESS; 8357 } 8358 8359 void lim_strip_mlo_ie(struct mac_context *mac_ctx, 8360 uint8_t *add_ie, uint16_t *add_ielen) 8361 { 8362 uint8_t *mlo_ie_buff = NULL; 8363 uint16_t mlo_ie_buff_len = 0; 8364 QDF_STATUS qdf_status; 8365 8366 /* MLO ext ie in addition IE*/ 8367 if (wlan_get_ext_ie_ptr_from_ext_id(MLO_IE_OUI_TYPE, ONE_BYTE, 8368 add_ie, *add_ielen)) { 8369 mlo_ie_buff = qdf_mem_malloc(WLAN_MAX_IE_LEN + 2); 8370 8371 if (!mlo_ie_buff) { 8372 pe_err("Failed to allocate MLO IE buff"); 8373 return; 8374 } 8375 8376 qdf_status = lim_strip_ie(mac_ctx, add_ie, add_ielen, 8377 WLAN_ELEMID_EXTN_ELEM, ONE_BYTE, 8378 MLO_IE_OUI_TYPE, MLO_IE_OUI_SIZE, 8379 mlo_ie_buff, WLAN_MAX_IE_LEN); 8380 if (QDF_IS_STATUS_ERROR(qdf_status)) { 8381 pe_err("Failed to strip MLO IE"); 8382 qdf_mem_free(mlo_ie_buff); 8383 return; 8384 } 8385 mlo_ie_buff_len = mlo_ie_buff[1] + 2; /* 2 - EID+LEN */ 8386 pe_debug("remove supplicant mlo ie, %d bytes", mlo_ie_buff[1]); 8387 qdf_trace_hex_dump(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, 8388 mlo_ie_buff, mlo_ie_buff_len); 8389 8390 qdf_mem_free(mlo_ie_buff); 8391 } 8392 } 8393 #endif 8394 8395 #ifdef WLAN_FEATURE_11BE 8396 static void lim_populate_eht_320_mcs_set(struct mac_context *mac_ctx, 8397 struct supported_rates *rates, 8398 tDot11fIEeht_cap *peer_eht_caps) 8399 { 8400 tDot11fIEeht_cap *fw_5g_eht_cap; 8401 8402 fw_5g_eht_cap = &mac_ctx->eht_cap_5g; 8403 8404 rates->bw_320_tx_max_nss_for_mcs_12_and_13 = 8405 QDF_MIN(peer_eht_caps->bw_320_tx_max_nss_for_mcs_12_and_13, 8406 fw_5g_eht_cap->bw_320_tx_max_nss_for_mcs_12_and_13); 8407 rates->bw_320_rx_max_nss_for_mcs_12_and_13 = 8408 QDF_MIN(peer_eht_caps->bw_320_rx_max_nss_for_mcs_12_and_13, 8409 fw_5g_eht_cap->bw_320_rx_max_nss_for_mcs_12_and_13); 8410 rates->bw_320_tx_max_nss_for_mcs_10_and_11 = 8411 QDF_MIN(peer_eht_caps->bw_320_tx_max_nss_for_mcs_10_and_11, 8412 fw_5g_eht_cap->bw_320_tx_max_nss_for_mcs_10_and_11); 8413 rates->bw_320_rx_max_nss_for_mcs_10_and_11 = 8414 QDF_MIN(peer_eht_caps->bw_320_rx_max_nss_for_mcs_10_and_11, 8415 fw_5g_eht_cap->bw_320_rx_max_nss_for_mcs_10_and_11); 8416 rates->bw_320_rx_max_nss_for_mcs_0_to_9 = 8417 QDF_MIN(peer_eht_caps->bw_320_rx_max_nss_for_mcs_0_to_9, 8418 fw_5g_eht_cap->bw_320_rx_max_nss_for_mcs_0_to_9); 8419 rates->bw_320_tx_max_nss_for_mcs_0_to_9 = 8420 QDF_MIN(peer_eht_caps->bw_320_tx_max_nss_for_mcs_0_to_9, 8421 fw_5g_eht_cap->bw_320_tx_max_nss_for_mcs_0_to_9); 8422 rates->bw_320_rx_max_nss_for_mcs_0_to_9 = 8423 QDF_MIN(peer_eht_caps->bw_320_rx_max_nss_for_mcs_0_to_9, 8424 fw_5g_eht_cap->bw_320_rx_max_nss_for_mcs_0_to_9); 8425 rates->bw_320_rx_max_nss_for_mcs_0_to_9 = 8426 QDF_MIN(peer_eht_caps->bw_320_rx_max_nss_for_mcs_0_to_9, 8427 fw_5g_eht_cap->bw_320_rx_max_nss_for_mcs_0_to_9); 8428 } 8429 8430 static void lim_populate_eht_160_mcs_set(struct mac_context *mac_ctx, 8431 struct supported_rates *rates, 8432 tDot11fIEeht_cap *peer_eht_caps) 8433 { 8434 tDot11fIEeht_cap *fw_5g_eht_cap; 8435 8436 fw_5g_eht_cap = &mac_ctx->eht_cap_5g; 8437 8438 rates->bw_160_tx_max_nss_for_mcs_12_and_13 = 8439 QDF_MIN(peer_eht_caps->bw_160_tx_max_nss_for_mcs_12_and_13, 8440 fw_5g_eht_cap->bw_160_tx_max_nss_for_mcs_12_and_13); 8441 rates->bw_160_rx_max_nss_for_mcs_12_and_13 = 8442 QDF_MIN(peer_eht_caps->bw_160_rx_max_nss_for_mcs_12_and_13, 8443 fw_5g_eht_cap->bw_160_rx_max_nss_for_mcs_12_and_13); 8444 rates->bw_160_tx_max_nss_for_mcs_10_and_11 = 8445 QDF_MIN(peer_eht_caps->bw_160_tx_max_nss_for_mcs_10_and_11, 8446 fw_5g_eht_cap->bw_160_tx_max_nss_for_mcs_10_and_11); 8447 rates->bw_160_rx_max_nss_for_mcs_10_and_11 = 8448 QDF_MIN(peer_eht_caps->bw_160_rx_max_nss_for_mcs_10_and_11, 8449 fw_5g_eht_cap->bw_160_tx_max_nss_for_mcs_10_and_11); 8450 rates->bw_160_tx_max_nss_for_mcs_0_to_9 = 8451 QDF_MIN(peer_eht_caps->bw_160_tx_max_nss_for_mcs_0_to_9, 8452 fw_5g_eht_cap->bw_160_tx_max_nss_for_mcs_0_to_9); 8453 rates->bw_160_rx_max_nss_for_mcs_0_to_9 = 8454 QDF_MIN(peer_eht_caps->bw_160_rx_max_nss_for_mcs_0_to_9, 8455 fw_5g_eht_cap->bw_160_rx_max_nss_for_mcs_0_to_9); 8456 } 8457 8458 static void lim_populate_eht_le80_mcs_set(struct mac_context *mac_ctx, 8459 struct supported_rates *rates, 8460 tDot11fIEeht_cap *peer_eht_caps) 8461 { 8462 tDot11fIEeht_cap *fw_le80_eht_cap; 8463 8464 fw_le80_eht_cap = &mac_ctx->eht_cap_5g; 8465 8466 rates->bw_le_80_tx_max_nss_for_mcs_12_and_13 = 8467 QDF_MIN(peer_eht_caps->bw_le_80_tx_max_nss_for_mcs_12_and_13, 8468 fw_le80_eht_cap->bw_le_80_tx_max_nss_for_mcs_12_and_13); 8469 rates->bw_le_80_rx_max_nss_for_mcs_12_and_13 = 8470 QDF_MIN(peer_eht_caps->bw_le_80_rx_max_nss_for_mcs_12_and_13, 8471 fw_le80_eht_cap->bw_le_80_rx_max_nss_for_mcs_12_and_13); 8472 rates->bw_le_80_tx_max_nss_for_mcs_10_and_11 = 8473 QDF_MIN(peer_eht_caps->bw_le_80_tx_max_nss_for_mcs_10_and_11, 8474 fw_le80_eht_cap->bw_le_80_tx_max_nss_for_mcs_10_and_11); 8475 rates->bw_le_80_rx_max_nss_for_mcs_10_and_11 = 8476 QDF_MIN(peer_eht_caps->bw_le_80_rx_max_nss_for_mcs_10_and_11, 8477 fw_le80_eht_cap->bw_le_80_rx_max_nss_for_mcs_10_and_11); 8478 rates->bw_le_80_tx_max_nss_for_mcs_0_to_9 = 8479 QDF_MIN(peer_eht_caps->bw_le_80_tx_max_nss_for_mcs_0_to_9, 8480 fw_le80_eht_cap->bw_le_80_tx_max_nss_for_mcs_0_to_9); 8481 rates->bw_le_80_rx_max_nss_for_mcs_0_to_9 = 8482 QDF_MIN(peer_eht_caps->bw_le_80_rx_max_nss_for_mcs_0_to_9, 8483 fw_le80_eht_cap->bw_le_80_rx_max_nss_for_mcs_0_to_9); 8484 } 8485 8486 static void lim_populate_eht_20only_mcs_set(struct mac_context *mac_ctx, 8487 struct supported_rates *rates, 8488 tDot11fIEeht_cap *peer_eht_caps) 8489 { 8490 tDot11fIEeht_cap *fw_2g_eht_cap; 8491 8492 fw_2g_eht_cap = &mac_ctx->eht_cap_2g; 8493 8494 rates->bw_20_tx_max_nss_for_mcs_12_and_13 = 8495 QDF_MIN(peer_eht_caps->bw_20_tx_max_nss_for_mcs_12_and_13, 8496 fw_2g_eht_cap->bw_20_tx_max_nss_for_mcs_12_and_13); 8497 rates->bw_20_rx_max_nss_for_mcs_12_and_13 = 8498 QDF_MIN(peer_eht_caps->bw_20_rx_max_nss_for_mcs_12_and_13, 8499 fw_2g_eht_cap->bw_20_rx_max_nss_for_mcs_12_and_13); 8500 rates->bw_20_tx_max_nss_for_mcs_10_and_11 = 8501 QDF_MIN(peer_eht_caps->bw_20_tx_max_nss_for_mcs_10_and_11, 8502 fw_2g_eht_cap->bw_20_tx_max_nss_for_mcs_10_and_11); 8503 rates->bw_20_rx_max_nss_for_mcs_10_and_11 = 8504 QDF_MIN(peer_eht_caps->bw_20_rx_max_nss_for_mcs_10_and_11, 8505 fw_2g_eht_cap->bw_20_rx_max_nss_for_mcs_10_and_11); 8506 rates->bw_20_tx_max_nss_for_mcs_8_and_9 = 8507 QDF_MIN(peer_eht_caps->bw_20_tx_max_nss_for_mcs_8_and_9, 8508 fw_2g_eht_cap->bw_20_tx_max_nss_for_mcs_8_and_9); 8509 rates->bw_20_rx_max_nss_for_mcs_8_and_9 = 8510 QDF_MIN(peer_eht_caps->bw_20_rx_max_nss_for_mcs_8_and_9, 8511 fw_2g_eht_cap->bw_20_rx_max_nss_for_mcs_8_and_9); 8512 rates->bw_20_tx_max_nss_for_mcs_0_to_7 = 8513 QDF_MIN(peer_eht_caps->bw_20_tx_max_nss_for_mcs_0_to_7, 8514 fw_2g_eht_cap->bw_20_tx_max_nss_for_mcs_0_to_7); 8515 rates->bw_20_rx_max_nss_for_mcs_0_to_7 = 8516 QDF_MIN(peer_eht_caps->bw_20_rx_max_nss_for_mcs_0_to_7, 8517 fw_2g_eht_cap->bw_20_rx_max_nss_for_mcs_0_to_7); 8518 } 8519 8520 QDF_STATUS lim_populate_eht_mcs_set(struct mac_context *mac_ctx, 8521 struct supported_rates *rates, 8522 tDot11fIEeht_cap *peer_eht_caps, 8523 struct pe_session *session_entry, 8524 uint8_t nss) 8525 { 8526 if ((!peer_eht_caps) || (!peer_eht_caps->present)) { 8527 pe_debug("peer not eht capable or eht_caps NULL"); 8528 return QDF_STATUS_SUCCESS; 8529 } 8530 if (!lim_is_session_eht_capable(session_entry)) { 8531 pe_debug("session not eht capable"); 8532 return QDF_STATUS_SUCCESS; 8533 } 8534 8535 switch (session_entry->ch_width) { 8536 case CH_WIDTH_320MHZ: 8537 lim_populate_eht_320_mcs_set(mac_ctx, rates, peer_eht_caps); 8538 fallthrough; 8539 case CH_WIDTH_160MHZ: 8540 lim_populate_eht_160_mcs_set(mac_ctx, rates, peer_eht_caps); 8541 fallthrough; 8542 case CH_WIDTH_80MHZ: 8543 case CH_WIDTH_40MHZ: 8544 lim_populate_eht_le80_mcs_set(mac_ctx, rates, peer_eht_caps); 8545 break; 8546 case CH_WIDTH_20MHZ: 8547 lim_populate_eht_20only_mcs_set(mac_ctx, rates, peer_eht_caps); 8548 break; 8549 default: 8550 break; 8551 } 8552 8553 return QDF_STATUS_SUCCESS; 8554 } 8555 8556 void lim_add_self_eht_cap(tpAddStaParams add_sta_params, 8557 struct pe_session *session) 8558 { 8559 if (!session) 8560 return; 8561 8562 add_sta_params->eht_capable = true; 8563 8564 qdf_mem_copy(&add_sta_params->eht_config, &session->eht_config, 8565 sizeof(add_sta_params->eht_config)); 8566 qdf_mem_copy(&add_sta_params->eht_op, &session->eht_op, 8567 sizeof(add_sta_params->eht_op)); 8568 } 8569 8570 /** 8571 * lim_intersect_eht_caps() - Intersect peer capability and self capability 8572 * @rcvd_eht: pointer to received peer capability 8573 * @peer_eht: pointer to Intersected capability 8574 * @session: A pointer to session entry. 8575 * 8576 * Return: None 8577 */ 8578 static void lim_intersect_eht_caps(tDot11fIEeht_cap *rcvd_eht, 8579 tDot11fIEeht_cap *peer_eht, 8580 struct pe_session *session) 8581 { 8582 tDot11fIEeht_cap *session_eht = &session->eht_config; 8583 8584 qdf_mem_copy(peer_eht, rcvd_eht, sizeof(*peer_eht)); 8585 8586 peer_eht->su_beamformer = session_eht->su_beamformee ? 8587 peer_eht->su_beamformer : 0; 8588 peer_eht->su_beamformee = (session_eht->su_beamformer || 8589 session_eht->mu_bformer_le_80mhz || 8590 session_eht->mu_bformer_160mhz || 8591 session_eht->mu_bformer_320mhz) ? 8592 peer_eht->su_beamformee : 0; 8593 peer_eht->mu_bformer_le_80mhz = session_eht->su_beamformee ? 8594 peer_eht->mu_bformer_le_80mhz : 0; 8595 peer_eht->mu_bformer_160mhz = session_eht->su_beamformee ? 8596 peer_eht->mu_bformer_160mhz : 0; 8597 peer_eht->mu_bformer_320mhz = session_eht->su_beamformee ? 8598 peer_eht->mu_bformer_320mhz : 0; 8599 8600 if (session_eht->support_320mhz_6ghz && rcvd_eht->support_320mhz_6ghz) 8601 peer_eht->support_320mhz_6ghz = 1; 8602 else 8603 peer_eht->support_320mhz_6ghz = 0; 8604 } 8605 8606 void lim_update_usr_eht_cap(struct mac_context *mac_ctx, 8607 struct pe_session *session) 8608 { 8609 struct add_ie_params *add_ie = &session->add_ie_params; 8610 tDot11fIEeht_cap *eht_cap = &session->eht_config; 8611 struct wlan_eht_cap_info_network_endian *eht_cap_from_ie; 8612 uint8_t extracted_buff[DOT11F_IE_EHT_CAP_MAX_LEN + 2]; 8613 QDF_STATUS status; 8614 struct wlan_vht_config *vht_cfg = &session->vht_config; 8615 tDot11fIEhe_cap *he_cap = &session->he_config; 8616 struct mlme_legacy_priv *mlme_priv; 8617 8618 qdf_mem_zero(extracted_buff, sizeof(extracted_buff)); 8619 status = lim_strip_ie(mac_ctx, add_ie->probeRespBCNData_buff, 8620 &add_ie->probeRespBCNDataLen, 8621 DOT11F_EID_EHT_CAP, ONE_BYTE, 8622 EHT_CAP_OUI_TYPE, (uint8_t)EHT_CAP_OUI_SIZE, 8623 extracted_buff, DOT11F_IE_EHT_CAP_MAX_LEN); 8624 if (QDF_IS_STATUS_ERROR(status)) { 8625 pe_debug("Failed to strip EHT cap IE status: %d", status); 8626 return; 8627 } 8628 8629 pe_debug("Before update: su_bformer: %d, su_bformee: %d, mu_bformer <= 80MHZ: %d 160MHZ: %d 320MHZ: %d", 8630 eht_cap->su_beamformer, eht_cap->su_beamformee, 8631 eht_cap->mu_bformer_le_80mhz, eht_cap->mu_bformer_160mhz, 8632 eht_cap->mu_bformer_320mhz); 8633 8634 eht_cap_from_ie = (struct wlan_eht_cap_info_network_endian *) 8635 &extracted_buff[EHT_CAP_OUI_SIZE + 2]; 8636 8637 eht_cap->su_beamformer = 8638 eht_cap->su_beamformer & eht_cap_from_ie->su_beamformer; 8639 eht_cap->su_beamformee = 8640 eht_cap->su_beamformee & eht_cap_from_ie->su_beamformee; 8641 eht_cap->mu_bformer_le_80mhz = 8642 eht_cap->mu_bformer_le_80mhz & 8643 eht_cap_from_ie->mu_bformer_le_80mhz; 8644 eht_cap->mu_bformer_160mhz = 8645 eht_cap->mu_bformer_160mhz & 8646 eht_cap_from_ie->mu_bformer_160mhz; 8647 eht_cap->mu_bformer_320mhz = 8648 eht_cap->mu_bformer_320mhz & 8649 eht_cap_from_ie->mu_bformer_320mhz; 8650 8651 pe_debug("After update: su_bformer: %d, su_bformee: %d, mu_bformer <= 80MHZ: %d 160MHZ: %d 320MHZ: %d", 8652 eht_cap->su_beamformer, eht_cap->su_beamformee, 8653 eht_cap->mu_bformer_le_80mhz, eht_cap->mu_bformer_160mhz, 8654 eht_cap->mu_bformer_320mhz); 8655 if (!eht_cap->su_beamformer) { 8656 eht_cap->mu_bformer_le_80mhz = 0; 8657 eht_cap->mu_bformer_160mhz = 0; 8658 eht_cap->mu_bformer_320mhz = 0; 8659 eht_cap->num_sounding_dim_le_80mhz = 0; 8660 eht_cap->num_sounding_dim_160mhz = 0; 8661 eht_cap->num_sounding_dim_320mhz = 0; 8662 he_cap->mu_beamformer = 0; 8663 he_cap->num_sounding_lt_80 = 0; 8664 he_cap->num_sounding_gt_80 = 0; 8665 vht_cfg->su_beam_former = 0; 8666 vht_cfg->mu_beam_former = 0; 8667 vht_cfg->num_soundingdim = 0; 8668 } 8669 if (!eht_cap->su_beamformee) { 8670 eht_cap->bfee_ss_le_80mhz = 0; 8671 eht_cap->bfee_ss_160mhz = 0; 8672 eht_cap->bfee_ss_320mhz = 0; 8673 he_cap->bfee_sts_lt_80 = 0; 8674 he_cap->bfee_sts_gt_80 = 0; 8675 vht_cfg->su_beam_formee = 0; 8676 vht_cfg->mu_beam_formee = 0; 8677 vht_cfg->csnof_beamformer_antSup = 0; 8678 } 8679 8680 mlme_priv = wlan_vdev_mlme_get_ext_hdl(session->vdev); 8681 if (mlme_priv) { 8682 mlme_priv->eht_config.mu_bformer_le_80mhz = 8683 eht_cap->mu_bformer_le_80mhz; 8684 mlme_priv->eht_config.mu_bformer_160mhz = 8685 eht_cap->mu_bformer_160mhz; 8686 mlme_priv->eht_config.mu_bformer_320mhz = 8687 eht_cap->mu_bformer_320mhz; 8688 mlme_priv->eht_config.su_beamformer = eht_cap->su_beamformer; 8689 mlme_priv->eht_config.su_beamformee = eht_cap->su_beamformee; 8690 mlme_priv->eht_config.bfee_ss_le_80mhz = 8691 eht_cap->bfee_ss_le_80mhz; 8692 mlme_priv->eht_config.bfee_ss_160mhz = eht_cap->bfee_ss_160mhz; 8693 mlme_priv->eht_config.bfee_ss_320mhz = eht_cap->bfee_ss_320mhz; 8694 mlme_priv->eht_config.num_sounding_dim_le_80mhz = 8695 eht_cap->num_sounding_dim_le_80mhz; 8696 mlme_priv->eht_config.num_sounding_dim_160mhz = 8697 eht_cap->num_sounding_dim_160mhz; 8698 mlme_priv->eht_config.num_sounding_dim_320mhz = 8699 eht_cap->num_sounding_dim_320mhz; 8700 } 8701 wma_set_eht_txbf_params(session->vdev_id, eht_cap->su_beamformer, 8702 eht_cap->su_beamformee, 8703 eht_cap->mu_bformer_le_80mhz || 8704 eht_cap->mu_bformer_160mhz || 8705 eht_cap->mu_bformer_320mhz); 8706 } 8707 8708 static void 8709 lim_revise_req_eht_cap_per_band(struct mlme_legacy_priv *mlme_priv, 8710 struct pe_session *session) 8711 { 8712 struct mac_context *mac = session->mac_ctx; 8713 8714 if (wlan_reg_is_24ghz_ch_freq(session->curr_op_freq)) 8715 mlme_priv->eht_config = mac->eht_cap_2g; 8716 else 8717 mlme_priv->eht_config = mac->eht_cap_5g; 8718 } 8719 8720 /** 8721 * lim_revise_req_eht_cap_per_mode() - revise eht capabilities per device mode 8722 * @mlme_legacy_priv: vdev mlme legacy priv object 8723 * @session: pointer to session entry. 8724 * 8725 * Return: None 8726 */ 8727 static void lim_revise_req_eht_cap_per_mode(struct mlme_legacy_priv *mlme_priv, 8728 struct pe_session *session) 8729 { 8730 if (session->opmode == QDF_SAP_MODE || 8731 session->opmode == QDF_P2P_GO_MODE) { 8732 pe_debug("Disable eht cap for SAP/GO"); 8733 mlme_priv->eht_config.tx_1024_4096_qam_lt_242_tone_ru = 0; 8734 mlme_priv->eht_config.rx_1024_4096_qam_lt_242_tone_ru = 0; 8735 } 8736 8737 mlme_priv->eht_config.non_ofdma_ul_mu_mimo_le_80mhz = 0; 8738 mlme_priv->eht_config.non_ofdma_ul_mu_mimo_160mhz = 0; 8739 mlme_priv->eht_config.non_ofdma_ul_mu_mimo_320mhz = 0; 8740 } 8741 8742 void lim_copy_bss_eht_cap(struct pe_session *session) 8743 { 8744 struct mlme_legacy_priv *mlme_priv; 8745 8746 mlme_priv = wlan_vdev_mlme_get_ext_hdl(session->vdev); 8747 if (!mlme_priv) 8748 return; 8749 8750 lim_revise_req_eht_cap_per_band(mlme_priv, session); 8751 8752 /* 8753 * As per firmware, SAP/GO doesn’t support some EHT capabilities. So if 8754 * unsupported capabilities are advertised in beacon, probe rsp and 8755 * assoc rsp can cause IOT issues. 8756 * Disable unsupported capabilities per mode. 8757 */ 8758 lim_revise_req_eht_cap_per_mode(mlme_priv, session); 8759 lim_update_eht_caps_mcs(session->mac_ctx, session); 8760 qdf_mem_copy(&session->eht_config, &mlme_priv->eht_config, 8761 sizeof(session->eht_config)); 8762 8763 if (wlan_epcs_get_config(session->vdev)) 8764 session->eht_config.epcs_pri_access = 1; 8765 else 8766 session->eht_config.epcs_pri_access = 0; 8767 } 8768 8769 void lim_copy_join_req_eht_cap(struct pe_session *session) 8770 { 8771 struct mlme_legacy_priv *mlme_priv; 8772 8773 mlme_priv = wlan_vdev_mlme_get_ext_hdl(session->vdev); 8774 if (!mlme_priv) 8775 return; 8776 lim_revise_req_eht_cap_per_band(mlme_priv, session); 8777 lim_revise_req_eht_cap_per_mode(mlme_priv, session); 8778 qdf_mem_copy(&session->eht_config, &mlme_priv->eht_config, 8779 sizeof(session->eht_config)); 8780 } 8781 8782 void lim_add_eht_cap(struct mac_context *mac_ctx, struct pe_session *pe_session, 8783 tpAddStaParams add_sta_params, tpSirAssocReq assoc_req) 8784 { 8785 if (!add_sta_params->eht_capable || !assoc_req) 8786 return; 8787 8788 qdf_mem_copy(&add_sta_params->eht_config, &assoc_req->eht_cap, 8789 sizeof(add_sta_params->eht_config)); 8790 } 8791 8792 void lim_intersect_ap_eht_caps(struct pe_session *session, 8793 struct bss_params *add_bss, 8794 tSchBeaconStruct *beacon, 8795 tpSirAssocRsp assoc_rsp) 8796 { 8797 tDot11fIEeht_cap *rcvd_eht; 8798 tDot11fIEeht_cap *peer_eht = &add_bss->staContext.eht_config; 8799 8800 if (assoc_rsp && assoc_rsp->eht_cap.present) 8801 rcvd_eht = &assoc_rsp->eht_cap; 8802 else 8803 rcvd_eht = &beacon->eht_cap; 8804 8805 lim_intersect_eht_caps(rcvd_eht, peer_eht, session); 8806 add_bss->staContext.eht_capable = true; 8807 } 8808 8809 void lim_add_bss_eht_cap(struct bss_params *add_bss, tpSirAssocRsp assoc_rsp) 8810 { 8811 tDot11fIEeht_cap *eht_cap; 8812 tDot11fIEeht_op *eht_op; 8813 8814 eht_cap = &assoc_rsp->eht_cap; 8815 eht_op = &assoc_rsp->eht_op; 8816 add_bss->eht_capable = eht_cap->present; 8817 if (eht_cap) 8818 qdf_mem_copy(&add_bss->staContext.eht_config, 8819 eht_cap, sizeof(*eht_cap)); 8820 if (eht_op) 8821 qdf_mem_copy(&add_bss->staContext.eht_op, 8822 eht_op, sizeof(*eht_op)); 8823 } 8824 8825 void lim_intersect_sta_eht_caps(struct mac_context *mac_ctx, 8826 tpSirAssocReq assoc_req, 8827 struct pe_session *session, 8828 tpDphHashNode sta_ds) 8829 { 8830 tDot11fIEeht_cap *rcvd_eht = &assoc_req->eht_cap; 8831 tDot11fIEeht_cap *peer_eht = &sta_ds->eht_config; 8832 8833 if (!sta_ds->mlmStaContext.eht_capable) 8834 return; 8835 8836 /* If EHT is not supported, do not fill sta_ds and return */ 8837 if (!IS_DOT11_MODE_EHT(session->dot11mode)) 8838 return; 8839 8840 lim_intersect_eht_caps(rcvd_eht, peer_eht, session); 8841 } 8842 8843 void lim_update_session_eht_capable(struct mac_context *mac, 8844 struct pe_session *session) 8845 { 8846 session->eht_capable = true; 8847 } 8848 8849 void lim_add_bss_eht_cfg(struct bss_params *add_bss, struct pe_session *session) 8850 { 8851 } 8852 8853 #define EHT_OP_LEN (DOT11F_IE_EHT_OP_MAX_LEN + EHT_OP_OUI_SIZE * 2 + ONE_BYTE) 8854 void lim_decide_eht_op(struct mac_context *mac_ctx, uint32_t *mlme_eht_ops, 8855 struct pe_session *session) 8856 { 8857 struct add_ie_params *add_ie = &session->add_ie_params; 8858 uint8_t extracted_buff[EHT_OP_LEN + 2]; 8859 QDF_STATUS status; 8860 uint16_t ori_puncture_bitmap; 8861 uint8_t len; 8862 8863 pe_debug("beacon ie:"); 8864 qdf_trace_hex_dump(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, 8865 add_ie->probeRespBCNData_buff, 8866 add_ie->probeRespBCNDataLen); 8867 8868 qdf_mem_zero(extracted_buff, sizeof(extracted_buff)); 8869 status = lim_strip_ie(mac_ctx, add_ie->probeRespBCNData_buff, 8870 &add_ie->probeRespBCNDataLen, 8871 DOT11F_EID_EHT_OP, ONE_BYTE, 8872 EHT_OP_OUI_TYPE, (uint8_t)EHT_OP_OUI_SIZE, 8873 extracted_buff, EHT_OP_LEN); 8874 if (QDF_STATUS_SUCCESS != status) { 8875 pe_debug("Failed to strip EHT OP IE status: %d", status); 8876 return; 8877 } 8878 8879 pe_debug("eht op:"); 8880 qdf_trace_hex_dump(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, 8881 extracted_buff, EHT_OP_LEN); 8882 8883 session->eht_op.present = 1; 8884 8885 len = qdf_min((uint8_t)(sizeof(tDot11fIEeht_op) - 1), 8886 (uint8_t)(DOT11F_IE_EHT_OP_MAX_LEN)); 8887 qdf_mem_copy((uint8_t *)(&session->eht_op) + 1, 8888 &extracted_buff[EHT_OP_OUI_SIZE * 2 + ONE_BYTE], 8889 len); 8890 8891 ori_puncture_bitmap = 8892 *(uint16_t *)session->eht_op.disabled_sub_chan_bitmap; 8893 pe_debug("puncture bitmap: %d, ch width: %d, ccfs0: %d, ccfs1: %d", 8894 ori_puncture_bitmap, session->eht_op.channel_width, 8895 session->eht_op.ccfs0, session->eht_op.ccfs1); 8896 8897 wma_update_vdev_eht_ops(mlme_eht_ops, &session->eht_op); 8898 } 8899 8900 void lim_update_stads_eht_capable(tpDphHashNode sta_ds, tpSirAssocReq assoc_req) 8901 { 8902 sta_ds->mlmStaContext.eht_capable = assoc_req->eht_cap.present; 8903 } 8904 8905 #ifdef FEATURE_WLAN_TDLS 8906 #ifdef WLAN_FEATURE_11BE 8907 void lim_update_tdls_sta_eht_capable(struct mac_context *mac, 8908 tpAddStaParams add_sta_params, 8909 tpDphHashNode sta_ds, 8910 struct pe_session *session_entry) 8911 { 8912 if (sta_ds->staType == STA_ENTRY_TDLS_PEER) { 8913 if (!sta_ds->eht_config.present) 8914 add_sta_params->eht_capable = 0; 8915 } 8916 8917 pe_debug("tdls eht_capable: %d", add_sta_params->eht_capable); 8918 } 8919 #endif 8920 #endif 8921 8922 void lim_update_sta_eht_capable(struct mac_context *mac, 8923 tpAddStaParams add_sta_params, 8924 tpDphHashNode sta_ds, 8925 struct pe_session *session_entry) 8926 { 8927 if (LIM_IS_AP_ROLE(session_entry)) 8928 add_sta_params->eht_capable = 8929 sta_ds->mlmStaContext.eht_capable && 8930 session_entry->eht_capable; 8931 else 8932 add_sta_params->eht_capable = session_entry->eht_capable; 8933 8934 pe_debug("eht_capable: %d", add_sta_params->eht_capable); 8935 } 8936 8937 void lim_update_session_eht_capable_chan_switch(struct mac_context *mac, 8938 struct pe_session *session, 8939 uint32_t new_chan_freq) 8940 { 8941 session->eht_capable = true; 8942 session->he_capable = true; 8943 /* TODO: Update */ 8944 if (wlan_reg_is_6ghz_chan_freq(session->curr_op_freq) && 8945 !wlan_reg_is_6ghz_chan_freq(new_chan_freq)) { 8946 session->htCapability = 1; 8947 session->vhtCapability = 1; 8948 session->he_6ghz_band = 0; 8949 } else if (!wlan_reg_is_6ghz_chan_freq(session->curr_op_freq) && 8950 wlan_reg_is_6ghz_chan_freq(new_chan_freq)) { 8951 session->htCapability = 0; 8952 session->vhtCapability = 0; 8953 session->he_6ghz_band = 1; 8954 } 8955 8956 /* 8957 * If new channel is 2.4gh set VHT as per the b24ghz_band INI 8958 * if new channel is 5Ghz set the vht, this will happen if we move from 8959 * 2.4Ghz to 5Ghz. 8960 */ 8961 if (wlan_reg_is_24ghz_ch_freq(new_chan_freq) && 8962 !mac->mlme_cfg->vht_caps.vht_cap_info.b24ghz_band) 8963 session->vhtCapability = 0; 8964 else if (wlan_reg_is_5ghz_ch_freq(new_chan_freq)) 8965 session->vhtCapability = 1; 8966 8967 pe_debug("eht_capable:%d he_capable:%d ht:%d vht:%d 6ghz_band:%d new freq:%d vht in 2.4gh:%d", 8968 session->eht_capable, session->he_capable, 8969 session->htCapability, session->vhtCapability, 8970 session->he_6ghz_band, new_chan_freq, 8971 mac->mlme_cfg->vht_caps.vht_cap_info.b24ghz_band); 8972 } 8973 8974 void lim_update_bss_eht_capable(struct mac_context *mac, 8975 struct bss_params *add_bss) 8976 { 8977 add_bss->eht_capable = true; 8978 pe_debug("eht_capable: %d", add_bss->eht_capable); 8979 } 8980 8981 void lim_log_eht_cap(struct mac_context *mac, tDot11fIEeht_cap *eht_cap) 8982 { 8983 if (!eht_cap->present) 8984 return; 8985 8986 pe_nofl_debug("EHT Capabilities:"); 8987 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, 8988 eht_cap, sizeof(tDot11fIEeht_cap)); 8989 } 8990 8991 void lim_log_eht_op(struct mac_context *mac, tDot11fIEeht_op *eht_ops, 8992 struct pe_session *session) 8993 { 8994 if (!eht_ops->present) 8995 return; 8996 8997 pe_nofl_debug("EHT operation element:"); 8998 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, 8999 eht_ops, sizeof(tDot11fIEeht_op)); 9000 } 9001 9002 void lim_set_eht_caps(struct mac_context *mac, 9003 uint8_t *ie_start, uint32_t num_bytes, uint8_t band, 9004 uint8_t vdev_id) 9005 { 9006 const uint8_t *ie = NULL; 9007 uint8_t offset = 0; 9008 uint8_t offset_1 = 0; 9009 tDot11fIEeht_cap dot11_cap; 9010 tDot11fIEhe_cap dot11_he_cap; 9011 struct wlan_eht_cap_info *eht_cap; 9012 struct wlan_eht_cap_info eht_mcs_cap; 9013 bool is_band_2g = false; 9014 uint32_t cbm_24ghz; 9015 struct wlan_objmgr_vdev *vdev; 9016 9017 if (band == CDS_BAND_2GHZ) 9018 is_band_2g = true; 9019 9020 populate_dot11f_eht_caps_by_band(mac, is_band_2g, &dot11_cap, NULL); 9021 populate_dot11f_he_caps_by_band(mac, is_band_2g, &dot11_he_cap, 9022 NULL); 9023 lim_log_eht_cap(mac, &dot11_cap); 9024 9025 if (is_band_2g) { 9026 cbm_24ghz = lim_get_sta_cb_mode_for_24ghz(mac, vdev_id); 9027 if (!cbm_24ghz) { 9028 /* B0: 40Mhz channel width in the 2.4GHz band */ 9029 dot11_he_cap.chan_width_0 = 0; 9030 dot11_he_cap.he_ppdu_20_in_40Mhz_2G = 0; 9031 } 9032 } 9033 9034 ie = wlan_get_ext_ie_ptr_from_ext_id(EHT_CAP_OUI_TYPE, 9035 EHT_CAP_OUI_SIZE, 9036 ie_start, num_bytes); 9037 9038 if (ie) { 9039 /* convert from unpacked to packed structure */ 9040 eht_cap = (struct wlan_eht_cap_info *)&ie[2 + EHT_CAP_OUI_SIZE]; 9041 9042 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc, vdev_id, 9043 WLAN_MLME_CM_ID); 9044 if (wlan_epcs_get_config(vdev)) 9045 eht_cap->epcs_pri_access = 1; 9046 else 9047 eht_cap->epcs_pri_access = 0; 9048 9049 if (vdev) 9050 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 9051 9052 eht_cap->eht_om_ctl = dot11_cap.eht_om_ctl; 9053 eht_cap->triggered_txop_sharing_mode1 = 9054 dot11_cap.triggered_txop_sharing_mode1; 9055 eht_cap->triggered_txop_sharing_mode2 = 9056 dot11_cap.triggered_txop_sharing_mode2; 9057 eht_cap->restricted_twt = 9058 dot11_cap.restricted_twt; 9059 eht_cap->scs_traffic_desc = 9060 dot11_cap.scs_traffic_desc; 9061 eht_cap->max_mpdu_len = 9062 dot11_cap.max_mpdu_len; 9063 eht_cap->max_a_mpdu_len_exponent_ext = 9064 dot11_cap.max_a_mpdu_len_exponent_ext; 9065 eht_cap->eht_trs_support = dot11_cap.eht_trs_support; 9066 eht_cap->txop_return_support_txop_share_m2 = 9067 dot11_cap.txop_return_support_txop_share_m2; 9068 eht_cap->two_bqrs_support = 9069 dot11_cap.two_bqrs_support; 9070 eht_cap->eht_link_adaptation_support = 9071 dot11_cap.eht_link_adaptation_support; 9072 eht_cap->support_320mhz_6ghz = dot11_cap.support_320mhz_6ghz; 9073 eht_cap->ru_242tone_wt_20mhz = dot11_cap.ru_242tone_wt_20mhz; 9074 eht_cap->ndp_4x_eht_ltf_3dot2_us_gi = 9075 dot11_cap.ndp_4x_eht_ltf_3dot2_us_gi; 9076 eht_cap->partial_bw_mu_mimo = dot11_cap.partial_bw_mu_mimo; 9077 eht_cap->su_beamformer = dot11_cap.su_beamformer; 9078 eht_cap->su_beamformee = dot11_cap.su_beamformee; 9079 eht_cap->bfee_ss_le_80mhz = dot11_cap.bfee_ss_le_80mhz; 9080 eht_cap->bfee_ss_160mhz = dot11_cap.bfee_ss_160mhz; 9081 eht_cap->bfee_ss_320mhz = dot11_cap.bfee_ss_320mhz; 9082 eht_cap->num_sounding_dim_le_80mhz = 9083 dot11_cap.num_sounding_dim_le_80mhz; 9084 eht_cap->num_sounding_dim_160mhz = 9085 dot11_cap.num_sounding_dim_160mhz; 9086 eht_cap->num_sounding_dim_320mhz = 9087 dot11_cap.num_sounding_dim_320mhz; 9088 eht_cap->ng_16_su_feedback = dot11_cap.ng_16_su_feedback; 9089 eht_cap->ng_16_mu_feedback = dot11_cap.ng_16_mu_feedback; 9090 eht_cap->cb_sz_4_2_su_feedback = 9091 dot11_cap.cb_sz_4_2_su_feedback; 9092 eht_cap->cb_sz_7_5_su_feedback = 9093 dot11_cap.cb_sz_7_5_su_feedback; 9094 eht_cap->trig_su_bforming_feedback = 9095 dot11_cap.trig_su_bforming_feedback; 9096 eht_cap->trig_mu_bforming_partial_bw_feedback = 9097 dot11_cap.trig_mu_bforming_partial_bw_feedback; 9098 eht_cap->triggered_cqi_feedback = 9099 dot11_cap.triggered_cqi_feedback; 9100 eht_cap->partial_bw_dl_mu_mimo = 9101 dot11_cap.partial_bw_dl_mu_mimo; 9102 eht_cap->psr_based_sr = dot11_cap.psr_based_sr; 9103 eht_cap->power_boost_factor = dot11_cap.power_boost_factor; 9104 eht_cap->eht_mu_ppdu_4x_ltf_0_8_us_gi = 9105 dot11_cap.eht_mu_ppdu_4x_ltf_0_8_us_gi; 9106 eht_cap->max_nc = dot11_cap.max_nc; 9107 eht_cap->non_trig_cqi_feedback = 9108 dot11_cap.non_trig_cqi_feedback; 9109 eht_cap->tx_1024_4096_qam_lt_242_tone_ru = 9110 dot11_cap.tx_1024_4096_qam_lt_242_tone_ru; 9111 eht_cap->rx_1024_4096_qam_lt_242_tone_ru = 9112 dot11_cap.rx_1024_4096_qam_lt_242_tone_ru; 9113 eht_cap->ppet_present = dot11_cap.ppet_present; 9114 eht_cap->common_nominal_pkt_padding = 9115 dot11_cap.common_nominal_pkt_padding; 9116 eht_cap->max_num_eht_ltf = dot11_cap.max_num_eht_ltf; 9117 eht_cap->mcs_15 = dot11_cap.mcs_15; 9118 eht_cap->eht_dup_6ghz = dot11_cap.eht_dup_6ghz; 9119 eht_cap->op_sta_rx_ndp_wider_bw_20mhz = 9120 dot11_cap.op_sta_rx_ndp_wider_bw_20mhz; 9121 eht_cap->non_ofdma_ul_mu_mimo_le_80mhz = 9122 dot11_cap.non_ofdma_ul_mu_mimo_le_80mhz; 9123 eht_cap->non_ofdma_ul_mu_mimo_160mhz = 9124 dot11_cap.non_ofdma_ul_mu_mimo_160mhz; 9125 eht_cap->non_ofdma_ul_mu_mimo_320mhz = 9126 dot11_cap.non_ofdma_ul_mu_mimo_320mhz; 9127 eht_cap->mu_bformer_le_80mhz = 9128 dot11_cap.mu_bformer_le_80mhz; 9129 eht_cap->mu_bformer_160mhz = dot11_cap.mu_bformer_160mhz; 9130 eht_cap->mu_bformer_320mhz = dot11_cap.mu_bformer_320mhz; 9131 eht_cap->tb_sounding_feedback_rl = 9132 dot11_cap.tb_sounding_feedback_rl; 9133 eht_cap->rx_1k_qam_in_wider_bw_dl_ofdma = 9134 dot11_cap.rx_1k_qam_in_wider_bw_dl_ofdma; 9135 eht_cap->rx_4k_qam_in_wider_bw_dl_ofdma = 9136 dot11_cap.rx_4k_qam_in_wider_bw_dl_ofdma; 9137 eht_cap->limited_cap_support_20mhz = 9138 dot11_cap.limited_cap_support_20mhz; 9139 eht_cap->triggered_mu_bf_full_bw_fb_and_dl_mumimo = 9140 dot11_cap.triggered_mu_bf_full_bw_fb_and_dl_mumimo; 9141 eht_cap->mru_support_20mhz = 9142 dot11_cap.mru_support_20mhz; 9143 9144 if ((is_band_2g && !dot11_he_cap.chan_width_0) || 9145 (!is_band_2g && !dot11_he_cap.chan_width_1 && 9146 !dot11_he_cap.chan_width_2 && 9147 !dot11_he_cap.chan_width_3)) { 9148 eht_mcs_cap.bw_20_rx_max_nss_for_mcs_0_to_7 = 9149 dot11_cap.bw_20_rx_max_nss_for_mcs_0_to_7; 9150 eht_mcs_cap.bw_20_tx_max_nss_for_mcs_0_to_7 = 9151 dot11_cap.bw_20_tx_max_nss_for_mcs_0_to_7; 9152 eht_mcs_cap.bw_20_rx_max_nss_for_mcs_8_and_9 = 9153 dot11_cap.bw_20_rx_max_nss_for_mcs_8_and_9; 9154 eht_mcs_cap.bw_20_tx_max_nss_for_mcs_8_and_9 = 9155 dot11_cap.bw_20_tx_max_nss_for_mcs_8_and_9; 9156 eht_mcs_cap.bw_20_rx_max_nss_for_mcs_10_and_11 = 9157 dot11_cap.bw_20_rx_max_nss_for_mcs_10_and_11; 9158 eht_mcs_cap.bw_20_tx_max_nss_for_mcs_10_and_11 = 9159 dot11_cap.bw_20_tx_max_nss_for_mcs_10_and_11; 9160 eht_mcs_cap.bw_20_rx_max_nss_for_mcs_12_and_13 = 9161 dot11_cap.bw_20_rx_max_nss_for_mcs_12_and_13; 9162 eht_mcs_cap.bw_20_tx_max_nss_for_mcs_12_and_13 = 9163 dot11_cap.bw_20_tx_max_nss_for_mcs_12_and_13; 9164 offset = ie_start[1] + 3; 9165 qdf_mem_copy(&ie_start[offset], 9166 (((uint8_t *)&eht_mcs_cap) + 9167 EHT_CAP_FIXED_FIELDS), 9168 EHT_CAP_20M_MCS_MAP_LEN); 9169 ie_start[1] += EHT_CAP_20M_MCS_MAP_LEN; 9170 9171 return; 9172 } 9173 9174 if ((is_band_2g && dot11_he_cap.chan_width_0) || 9175 (!is_band_2g && dot11_he_cap.chan_width_1)) { 9176 eht_mcs_cap.bw_le_80_rx_max_nss_for_mcs_0_to_9 = 9177 dot11_cap.bw_le_80_rx_max_nss_for_mcs_0_to_9; 9178 eht_mcs_cap.bw_le_80_tx_max_nss_for_mcs_0_to_9 = 9179 dot11_cap.bw_le_80_tx_max_nss_for_mcs_0_to_9; 9180 eht_mcs_cap.bw_le_80_rx_max_nss_for_mcs_10_and_11 = 9181 dot11_cap.bw_le_80_rx_max_nss_for_mcs_10_and_11; 9182 eht_mcs_cap.bw_le_80_tx_max_nss_for_mcs_10_and_11 = 9183 dot11_cap.bw_le_80_tx_max_nss_for_mcs_10_and_11; 9184 eht_mcs_cap.bw_le_80_rx_max_nss_for_mcs_12_and_13 = 9185 dot11_cap.bw_le_80_rx_max_nss_for_mcs_12_and_13; 9186 eht_mcs_cap.bw_le_80_tx_max_nss_for_mcs_12_and_13 = 9187 dot11_cap.bw_le_80_tx_max_nss_for_mcs_12_and_13; 9188 offset = ie_start[1] + 3; 9189 offset_1 = EHT_CAP_FIXED_FIELDS + 9190 EHT_CAP_20M_MCS_MAP_LEN; 9191 qdf_mem_copy(&ie_start[offset], 9192 (((uint8_t *)&eht_mcs_cap) + offset_1), 9193 EHT_CAP_80M_MCS_MAP_LEN); 9194 ie_start[1] += EHT_CAP_80M_MCS_MAP_LEN; 9195 } 9196 9197 if (!is_band_2g && dot11_he_cap.chan_width_2) { 9198 eht_mcs_cap.bw_160_rx_max_nss_for_mcs_0_to_9 = 9199 dot11_cap.bw_160_rx_max_nss_for_mcs_0_to_9; 9200 eht_mcs_cap.bw_160_tx_max_nss_for_mcs_0_to_9 = 9201 dot11_cap.bw_160_tx_max_nss_for_mcs_0_to_9; 9202 eht_mcs_cap.bw_160_rx_max_nss_for_mcs_10_and_11 = 9203 dot11_cap.bw_160_rx_max_nss_for_mcs_10_and_11; 9204 eht_mcs_cap.bw_160_tx_max_nss_for_mcs_10_and_11 = 9205 dot11_cap.bw_160_tx_max_nss_for_mcs_10_and_11; 9206 eht_mcs_cap.bw_160_rx_max_nss_for_mcs_12_and_13 = 9207 dot11_cap.bw_160_rx_max_nss_for_mcs_12_and_13; 9208 eht_mcs_cap.bw_160_tx_max_nss_for_mcs_12_and_13 = 9209 dot11_cap.bw_160_tx_max_nss_for_mcs_12_and_13; 9210 offset = ie_start[1] + 3; 9211 offset_1 = EHT_CAP_FIXED_FIELDS + 9212 EHT_CAP_20M_MCS_MAP_LEN + 9213 EHT_CAP_80M_MCS_MAP_LEN; 9214 qdf_mem_copy(&ie_start[offset], 9215 (((uint8_t *)&eht_mcs_cap) + offset_1), 9216 EHT_CAP_160M_MCS_MAP_LEN); 9217 ie_start[1] += EHT_CAP_160M_MCS_MAP_LEN; 9218 9219 } 9220 9221 if (!is_band_2g && eht_cap->support_320mhz_6ghz) { 9222 eht_mcs_cap.bw_320_rx_max_nss_for_mcs_0_to_9 = 9223 dot11_cap.bw_320_rx_max_nss_for_mcs_0_to_9; 9224 eht_mcs_cap.bw_320_tx_max_nss_for_mcs_0_to_9 = 9225 dot11_cap.bw_320_tx_max_nss_for_mcs_0_to_9; 9226 eht_mcs_cap.bw_320_rx_max_nss_for_mcs_10_and_11 = 9227 dot11_cap.bw_320_rx_max_nss_for_mcs_10_and_11; 9228 eht_mcs_cap.bw_320_tx_max_nss_for_mcs_10_and_11 = 9229 dot11_cap.bw_320_tx_max_nss_for_mcs_10_and_11; 9230 eht_mcs_cap.bw_320_rx_max_nss_for_mcs_12_and_13 = 9231 dot11_cap.bw_320_rx_max_nss_for_mcs_12_and_13; 9232 eht_mcs_cap.bw_320_tx_max_nss_for_mcs_12_and_13 = 9233 dot11_cap.bw_320_tx_max_nss_for_mcs_12_and_13; 9234 offset = ie_start[1] + 3; 9235 offset_1 = EHT_CAP_FIXED_FIELDS + 9236 EHT_CAP_20M_MCS_MAP_LEN + 9237 EHT_CAP_80M_MCS_MAP_LEN + 9238 EHT_CAP_160M_MCS_MAP_LEN; 9239 qdf_mem_copy(&ie_start[offset], 9240 (((uint8_t *)&eht_mcs_cap) + offset_1), 9241 EHT_CAP_320M_MCS_MAP_LEN); 9242 ie_start[1] += EHT_CAP_320M_MCS_MAP_LEN; 9243 } 9244 } 9245 } 9246 9247 QDF_STATUS lim_send_eht_caps_ie(struct mac_context *mac_ctx, 9248 enum QDF_OPMODE device_mode, 9249 uint8_t vdev_id) 9250 { 9251 uint8_t eht_cap_total_len = DOT11F_IE_EHT_CAP_MIN_LEN + 9252 EHT_CAP_OUI_LEN + EHT_CAP_20M_MCS_MAP_LEN + 9253 EHT_CAP_80M_MCS_MAP_LEN + 9254 EHT_CAP_160M_MCS_MAP_LEN + 9255 EHT_CAP_320M_MCS_MAP_LEN; 9256 QDF_STATUS status_2g, status_5g; 9257 uint8_t eht_caps_2g[DOT11F_IE_EHT_CAP_MIN_LEN + 9258 EHT_CAP_OUI_LEN + EHT_CAP_20M_MCS_MAP_LEN + 9259 EHT_CAP_80M_MCS_MAP_LEN + 9260 EHT_CAP_160M_MCS_MAP_LEN + 9261 EHT_CAP_320M_MCS_MAP_LEN] = {0}; 9262 9263 uint8_t eht_caps_5g[DOT11F_IE_EHT_CAP_MIN_LEN + 9264 EHT_CAP_OUI_LEN + EHT_CAP_20M_MCS_MAP_LEN + 9265 EHT_CAP_80M_MCS_MAP_LEN + 9266 EHT_CAP_160M_MCS_MAP_LEN + 9267 EHT_CAP_320M_MCS_MAP_LEN] = {0}; 9268 9269 eht_caps_2g[0] = DOT11F_EID_EHT_CAP; 9270 eht_caps_2g[1] = EHT_CAP_FIXED_FIELDS; 9271 9272 qdf_mem_copy(&eht_caps_2g[2], EHT_CAP_OUI_TYPE, EHT_CAP_OUI_SIZE); 9273 9274 lim_set_eht_caps(mac_ctx, eht_caps_2g, eht_cap_total_len, 9275 CDS_BAND_2GHZ, vdev_id); 9276 status_2g = lim_send_ie(mac_ctx, vdev_id, DOT11F_EID_EHT_CAP, 9277 CDS_BAND_2GHZ, &eht_caps_2g[2], 9278 eht_caps_2g[1] + 1); 9279 9280 eht_caps_5g[0] = DOT11F_EID_EHT_CAP; 9281 eht_caps_5g[1] = EHT_CAP_FIXED_FIELDS; 9282 9283 qdf_mem_copy(&eht_caps_5g[2], EHT_CAP_OUI_TYPE, EHT_CAP_OUI_SIZE); 9284 9285 lim_set_eht_caps(mac_ctx, eht_caps_5g, eht_cap_total_len, 9286 CDS_BAND_5GHZ, vdev_id); 9287 status_5g = lim_send_ie(mac_ctx, vdev_id, DOT11F_EID_EHT_CAP, 9288 CDS_BAND_5GHZ, &eht_caps_5g[2], 9289 eht_caps_5g[1] + 1); 9290 9291 if (QDF_IS_STATUS_SUCCESS(status_2g) && 9292 QDF_IS_STATUS_SUCCESS(status_5g)) { 9293 return QDF_STATUS_SUCCESS; 9294 } 9295 return QDF_STATUS_SUCCESS; 9296 } 9297 9298 void lim_update_stads_eht_caps(struct mac_context *mac_ctx, 9299 tpDphHashNode sta_ds, tpSirAssocRsp assoc_rsp, 9300 struct pe_session *session_entry, 9301 tSchBeaconStruct *beacon) 9302 { 9303 /* If EHT is not supported, do not fill sta_ds and return */ 9304 if (!IS_DOT11_MODE_EHT(session_entry->dot11mode)) 9305 return; 9306 9307 if (!assoc_rsp->eht_cap.present && beacon && beacon->eht_cap.present) { 9308 /* Use beacon EHT caps if assoc resp doesn't have he caps */ 9309 pe_debug("eht_caps missing in assoc rsp"); 9310 qdf_mem_copy(&assoc_rsp->eht_cap, &beacon->eht_cap, 9311 sizeof(tDot11fIEeht_cap)); 9312 } 9313 9314 /* assoc resp and beacon doesn't have eht caps */ 9315 if (!assoc_rsp->eht_cap.present) 9316 return; 9317 9318 sta_ds->mlmStaContext.eht_capable = assoc_rsp->eht_cap.present; 9319 9320 qdf_mem_copy(&sta_ds->eht_config, &assoc_rsp->eht_cap, 9321 sizeof(tDot11fIEeht_cap)); 9322 } 9323 9324 void lim_update_stads_eht_bw_320mhz(struct pe_session *session, 9325 tpDphHashNode sta_ds) 9326 { 9327 tDot11fIEeht_cap *peer_eht = &sta_ds->eht_config; 9328 9329 if (!IS_DOT11_MODE_EHT(session->dot11mode) || !peer_eht->present) 9330 return; 9331 9332 /* EHT only defines 320 MHz. If session is not in 320 MHz, BW will be 9333 * set in HE mode. 9334 * 9335 * Set ch_width to 320 MHz only when session is in 320 MHz and peer eht 9336 * caps support 320 MHz after eht caps intersection. 9337 */ 9338 if (session->ch_width == CH_WIDTH_320MHZ && 9339 peer_eht->support_320mhz_6ghz) { 9340 sta_ds->ch_width = CH_WIDTH_320MHZ; 9341 pe_debug("ch_width %d", sta_ds->ch_width); 9342 } 9343 } 9344 9345 #endif 9346 9347 #ifdef WLAN_FEATURE_11BE_MLO 9348 void lim_extract_per_link_id(struct pe_session *session, 9349 struct bss_params *add_bss, 9350 tpSirAssocRsp assoc_rsp) 9351 { 9352 uint8_t vdev_id = wlan_vdev_get_id(session->vdev); 9353 9354 if (!wlan_vdev_mlme_is_mlo_link_vdev(session->vdev) && 9355 assoc_rsp->mlo_ie.mlo_ie.link_id_info_present) 9356 add_bss->staContext.link_id = 9357 assoc_rsp->mlo_ie.mlo_ie.link_id; 9358 else 9359 add_bss->staContext.link_id = 9360 wlan_vdev_get_link_id(session->vdev); 9361 9362 pe_debug("vdev: %d, link id: %d", vdev_id, add_bss->staContext.link_id); 9363 } 9364 9365 void lim_extract_ml_info(struct pe_session *session, 9366 struct bss_params *add_bss, 9367 tpSirAssocRsp assoc_rsp) 9368 { 9369 uint8_t i, link_id, partner_idx = 0; 9370 struct mlo_partner_info *ml_partner_info; 9371 struct mlo_link_info *link_info; 9372 struct peer_ml_info *ml_link; 9373 9374 if (!wlan_vdev_mlme_is_mlo_vdev(session->vdev)) 9375 return; 9376 9377 ml_link = &add_bss->staContext.ml_info; 9378 ml_partner_info = &session->ml_partner_info; 9379 9380 ml_link->vdev_id = wlan_vdev_get_id(session->vdev); 9381 ml_link->link_id = wlan_vdev_get_link_id(session->vdev); 9382 9383 ml_link->rec_max_simultaneous_links = 9384 session->vdev->mlo_dev_ctx->mlo_max_recom_simult_links; 9385 9386 link_info = mlo_mgr_get_ap_link_by_link_id(session->vdev->mlo_dev_ctx, 9387 ml_link->link_id); 9388 if (!link_info) 9389 return; 9390 9391 qdf_mem_copy(&ml_link->channel_info, link_info->link_chan_info, 9392 sizeof(ml_link->channel_info)); 9393 qdf_mem_copy(&ml_link->link_addr, &link_info->ap_link_addr, 9394 QDF_MAC_ADDR_SIZE); 9395 qdf_mem_copy(&ml_link->self_mac_addr, &link_info->link_addr, 9396 QDF_MAC_ADDR_SIZE); 9397 9398 if (wlan_vdev_mlme_is_mlo_link_vdev(session->vdev)) 9399 return; 9400 9401 for (i = 0; i < ml_partner_info->num_partner_links; i++) { 9402 link_id = ml_partner_info->partner_link_info[i].link_id; 9403 link_info = mlo_mgr_get_ap_link_by_link_id( 9404 session->vdev->mlo_dev_ctx, 9405 link_id); 9406 if (!link_info) 9407 continue; 9408 9409 ml_link->partner_info[partner_idx].vdev_id = link_info->vdev_id; 9410 ml_link->partner_info[partner_idx].link_id = link_info->link_id; 9411 9412 qdf_mem_copy(&ml_link->partner_info[partner_idx].channel_info, 9413 link_info->link_chan_info, 9414 sizeof(ml_link->partner_info[partner_idx].channel_info)); 9415 qdf_mem_copy(&ml_link->partner_info[partner_idx].link_addr, 9416 &link_info->ap_link_addr, QDF_MAC_ADDR_SIZE); 9417 qdf_mem_copy(&ml_link->partner_info[partner_idx].self_mac_addr, 9418 &link_info->link_addr, QDF_MAC_ADDR_SIZE); 9419 9420 partner_idx++; 9421 } 9422 9423 ml_link->num_links = partner_idx; 9424 pe_debug("vdev:%d Num of partner links: %d", session->vdev_id, 9425 ml_link->num_links); 9426 } 9427 9428 void lim_intersect_ap_emlsr_caps(struct mac_context *mac_ctx, 9429 struct pe_session *session, 9430 struct bss_params *add_bss, 9431 tpSirAssocRsp assoc_rsp) 9432 { 9433 struct wlan_mlo_sta *sta_ctx; 9434 struct wlan_objmgr_vdev *vdev = session->vdev; 9435 struct emlsr_capability *ml_emlcap; 9436 9437 wlan_objmgr_vdev_get_ref(vdev, WLAN_MLME_NB_ID); 9438 if (!vdev) { 9439 pe_err("vdev is null"); 9440 return; 9441 } 9442 9443 if (!vdev->mlo_dev_ctx) { 9444 pe_err("mlo dev ctx is null"); 9445 goto end; 9446 } 9447 9448 sta_ctx = vdev->mlo_dev_ctx->sta_ctx; 9449 if (!sta_ctx) { 9450 pe_err("sta ctx is null"); 9451 goto end; 9452 } 9453 9454 ml_emlcap = &sta_ctx->emlsr_cap; 9455 9456 if (!wlan_vdev_mlme_cap_get(vdev, WLAN_VDEV_C_EMLSR_CAP)) { 9457 add_bss->staContext.emlsr_support = false; 9458 goto end; 9459 } 9460 9461 if (wlan_vdev_mlme_is_mlo_link_vdev(session->vdev)) { 9462 add_bss->staContext.emlsr_support = ml_emlcap->emlsr_supp; 9463 add_bss->staContext.emlsr_trans_timeout = 9464 ml_emlcap->trans_timeout; 9465 } else { 9466 add_bss->staContext.emlsr_support = true; 9467 add_bss->staContext.emlsr_trans_timeout = 9468 assoc_rsp->mlo_ie.mlo_ie.eml_capabilities_info.transition_timeout; 9469 9470 ml_emlcap->emlsr_supp = add_bss->staContext.emlsr_support; 9471 ml_emlcap->trans_timeout = 9472 add_bss->staContext.emlsr_trans_timeout; 9473 } 9474 9475 end: 9476 pe_debug("emlsr support: %d, transition timeout:%d", 9477 add_bss->staContext.emlsr_support, 9478 add_bss->staContext.emlsr_trans_timeout); 9479 9480 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); 9481 } 9482 9483 #define MAX_MSD_OFDM_ED_THRESHOLD 10 9484 9485 void lim_extract_msd_caps(struct mac_context *mac_ctx, 9486 struct pe_session *session, 9487 struct bss_params *add_bss, 9488 tpSirAssocRsp assoc_rsp) 9489 { 9490 struct wlan_objmgr_peer *peer; 9491 struct wlan_mlo_peer_context *mlo_peer_ctx; 9492 9493 peer = wlan_objmgr_get_peer_by_mac(mac_ctx->psoc, add_bss->bssId, 9494 WLAN_LEGACY_MAC_ID); 9495 if (!peer) { 9496 pe_err("peer is null"); 9497 return; 9498 } 9499 9500 mlo_peer_ctx = peer->mlo_peer_ctx; 9501 if (!mlo_peer_ctx) { 9502 pe_err("mlo peer ctx is null"); 9503 wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_MAC_ID); 9504 return; 9505 } 9506 9507 if (wlan_vdev_mlme_is_mlo_link_vdev(session->vdev)) { 9508 add_bss->staContext.msd_caps_present = 9509 mlo_peer_ctx->msd_cap_present; 9510 add_bss->staContext.msd_caps.med_sync_duration = 9511 mlo_peer_ctx->mlpeer_msdcap.medium_sync_duration; 9512 add_bss->staContext.msd_caps.med_sync_ofdm_ed_thresh = 9513 mlo_peer_ctx->mlpeer_msdcap.medium_sync_ofdm_ed_thresh; 9514 add_bss->staContext.msd_caps.med_sync_max_txop_num = 9515 mlo_peer_ctx->mlpeer_msdcap.medium_sync_max_txop_num; 9516 } else { 9517 add_bss->staContext.msd_caps_present = 9518 assoc_rsp->mlo_ie.mlo_ie.medium_sync_delay_info_present; 9519 if (add_bss->staContext.msd_caps_present) { 9520 add_bss->staContext.msd_caps.med_sync_duration = 9521 assoc_rsp->mlo_ie.mlo_ie.medium_sync_delay_info.medium_sync_duration; 9522 add_bss->staContext.msd_caps.med_sync_ofdm_ed_thresh = 9523 assoc_rsp->mlo_ie.mlo_ie.medium_sync_delay_info.medium_sync_ofdm_ed_thresh; 9524 if (add_bss->staContext.msd_caps.med_sync_ofdm_ed_thresh > 9525 MAX_MSD_OFDM_ED_THRESHOLD) 9526 add_bss->staContext.msd_caps.med_sync_ofdm_ed_thresh = 0; 9527 add_bss->staContext.msd_caps.med_sync_max_txop_num = 9528 assoc_rsp->mlo_ie.mlo_ie.medium_sync_delay_info.medium_sync_max_txop_num; 9529 } else { 9530 /** 9531 * Fill MSD params with default values if MSD caps are 9532 * absent. 9533 * MSD duration = 5484usec / 32 = 171. 9534 * OFDM ED threshold = 0. FW adds -72 to Host value. 9535 * Maximum number of TXOPs = AP value (default = 0). 9536 */ 9537 add_bss->staContext.msd_caps.med_sync_duration = 171; 9538 add_bss->staContext.msd_caps.med_sync_ofdm_ed_thresh = 0; 9539 add_bss->staContext.msd_caps.med_sync_max_txop_num = 0; 9540 } 9541 mlo_peer_ctx->msd_cap_present = 9542 add_bss->staContext.msd_caps_present; 9543 mlo_peer_ctx->mlpeer_msdcap.medium_sync_duration = 9544 add_bss->staContext.msd_caps.med_sync_duration; 9545 mlo_peer_ctx->mlpeer_msdcap.medium_sync_ofdm_ed_thresh = 9546 add_bss->staContext.msd_caps.med_sync_ofdm_ed_thresh; 9547 mlo_peer_ctx->mlpeer_msdcap.medium_sync_max_txop_num = 9548 add_bss->staContext.msd_caps.med_sync_max_txop_num; 9549 } 9550 9551 wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_MAC_ID); 9552 pe_debug("MSD caps: %d, Duration: %d, Threshold:%d, TXOP num: %d", 9553 add_bss->staContext.msd_caps_present, 9554 add_bss->staContext.msd_caps.med_sync_duration, 9555 add_bss->staContext.msd_caps.med_sync_ofdm_ed_thresh, 9556 add_bss->staContext.msd_caps.med_sync_max_txop_num); 9557 } 9558 #endif 9559 9560 #if defined(CONFIG_BAND_6GHZ) && defined(WLAN_FEATURE_11AX) 9561 QDF_STATUS lim_send_he_6g_band_caps_ie(struct mac_context *mac_ctx, 9562 uint8_t vdev_id) 9563 { 9564 uint8_t he_6g_band_caps_ie[DOT11F_IE_HE_6GHZ_BAND_CAP_MIN_LEN + 3]; 9565 tDot11fIEhe_6ghz_band_cap he_6g_band_cap; 9566 QDF_STATUS status; 9567 uint32_t size = 0; 9568 uint32_t result; 9569 9570 qdf_mem_zero(&he_6g_band_cap, sizeof(he_6g_band_cap)); 9571 populate_dot11f_he_6ghz_cap(mac_ctx, NULL, &he_6g_band_cap); 9572 if (!he_6g_band_cap.present) { 9573 pe_debug("no HE 6g band cap for vdev %d", vdev_id); 9574 return QDF_STATUS_SUCCESS; 9575 } 9576 9577 qdf_mem_zero(he_6g_band_caps_ie, sizeof(he_6g_band_caps_ie)); 9578 result = dot11f_pack_ie_he_6ghz_band_cap(mac_ctx, &he_6g_band_cap, 9579 he_6g_band_caps_ie, 9580 sizeof(he_6g_band_caps_ie), 9581 &size); 9582 if (result != DOT11F_PARSE_SUCCESS) { 9583 pe_err("pack error for HE 6g band cap for vdev %d", vdev_id); 9584 return QDF_STATUS_E_FAILURE; 9585 } 9586 pe_debug("send HE 6ghz band cap: 0x%01x 0x%01x for vdev %d", 9587 he_6g_band_caps_ie[3], he_6g_band_caps_ie[4], 9588 vdev_id); 9589 status = lim_send_ie(mac_ctx, vdev_id, DOT11F_EID_HE_6GHZ_BAND_CAP, 9590 CDS_BAND_5GHZ, &he_6g_band_caps_ie[2], 9591 DOT11F_IE_HE_6GHZ_BAND_CAP_MIN_LEN + 1); 9592 if (QDF_IS_STATUS_ERROR(status)) 9593 pe_err("Unable send HE 6g band Cap IE for 5GHZ band, status: %d", 9594 status); 9595 9596 return status; 9597 } 9598 #endif 9599 9600 int 9601 lim_assoc_rej_get_remaining_delta(struct sir_rssi_disallow_lst *node) 9602 { 9603 qdf_time_t cur_time; 9604 uint32_t time_diff; 9605 9606 cur_time = qdf_do_div(qdf_get_monotonic_boottime(), 9607 QDF_MC_TIMER_TO_MS_UNIT); 9608 time_diff = cur_time - node->time_during_rejection; 9609 9610 return node->retry_delay - time_diff; 9611 } 9612 9613 QDF_STATUS 9614 lim_rem_denylist_entry_with_lowest_delta(qdf_list_t *list) 9615 { 9616 struct sir_rssi_disallow_lst *oldest_node = NULL; 9617 struct sir_rssi_disallow_lst *cur_node; 9618 qdf_list_node_t *cur_list = NULL; 9619 qdf_list_node_t *next_list = NULL; 9620 9621 qdf_list_peek_front(list, &cur_list); 9622 while (cur_list) { 9623 cur_node = qdf_container_of(cur_list, 9624 struct sir_rssi_disallow_lst, node); 9625 if (!oldest_node || 9626 (lim_assoc_rej_get_remaining_delta(oldest_node) > 9627 lim_assoc_rej_get_remaining_delta(cur_node))) 9628 oldest_node = cur_node; 9629 9630 qdf_list_peek_next(list, cur_list, &next_list); 9631 cur_list = next_list; 9632 next_list = NULL; 9633 } 9634 9635 if (oldest_node) { 9636 pe_debug("remove node "QDF_MAC_ADDR_FMT" with lowest delta %d", 9637 QDF_MAC_ADDR_REF(oldest_node->bssid.bytes), 9638 lim_assoc_rej_get_remaining_delta(oldest_node)); 9639 qdf_list_remove_node(list, &oldest_node->node); 9640 qdf_mem_free(oldest_node); 9641 return QDF_STATUS_SUCCESS; 9642 } 9643 9644 return QDF_STATUS_E_INVAL; 9645 } 9646 9647 void 9648 lim_add_bssid_to_reject_list(struct wlan_objmgr_pdev *pdev, 9649 struct sir_rssi_disallow_lst *entry) 9650 { 9651 struct reject_ap_info ap_info; 9652 9653 qdf_mem_zero(&ap_info, sizeof(struct reject_ap_info)); 9654 ap_info.bssid = entry->bssid; 9655 ap_info.reject_ap_type = DRIVER_RSSI_REJECT_TYPE; 9656 ap_info.rssi_reject_params.expected_rssi = entry->expected_rssi; 9657 ap_info.rssi_reject_params.retry_delay = entry->retry_delay; 9658 ap_info.reject_reason = entry->reject_reason; 9659 ap_info.source = entry->source; 9660 ap_info.rssi_reject_params.received_time = entry->received_time; 9661 ap_info.rssi_reject_params.original_timeout = entry->original_timeout; 9662 /* Add this ap info to the rssi reject ap type in denylist manager */ 9663 wlan_dlm_add_bssid_to_reject_list(pdev, &ap_info); 9664 } 9665 9666 void lim_decrement_pending_mgmt_count(struct mac_context *mac_ctx) 9667 { 9668 qdf_spin_lock(&mac_ctx->sys.bbt_mgmt_lock); 9669 if (!mac_ctx->sys.sys_bbt_pending_mgmt_count) { 9670 qdf_spin_unlock(&mac_ctx->sys.bbt_mgmt_lock); 9671 return; 9672 } 9673 mac_ctx->sys.sys_bbt_pending_mgmt_count--; 9674 qdf_spin_unlock(&mac_ctx->sys.bbt_mgmt_lock); 9675 } 9676 9677 bool lim_check_if_vendor_oui_match(struct mac_context *mac_ctx, 9678 uint8_t *oui, uint8_t oui_len, 9679 uint8_t *ie, uint8_t ie_len) 9680 { 9681 uint8_t *ptr = ie; 9682 uint8_t elem_id; 9683 9684 if (!ie || 0 == ie_len) { 9685 pe_err("IE Null or ie len zero %d", ie_len); 9686 return false; 9687 } 9688 9689 elem_id = *ie; 9690 9691 if (elem_id == WLAN_ELEMID_VENDOR && 9692 !qdf_mem_cmp(&ptr[2], oui, oui_len)) 9693 return true; 9694 else 9695 return false; 9696 } 9697 9698 QDF_STATUS lim_util_get_type_subtype(void *pkt, uint8_t *type, 9699 uint8_t *subtype) 9700 { 9701 cds_pkt_t *cds_pkt; 9702 QDF_STATUS status; 9703 tpSirMacMgmtHdr hdr; 9704 uint8_t *rxpktinfor; 9705 9706 cds_pkt = (cds_pkt_t *) pkt; 9707 if (!cds_pkt) { 9708 pe_err("NULL packet received"); 9709 return QDF_STATUS_E_FAILURE; 9710 } 9711 status = wma_ds_peek_rx_packet_info(cds_pkt, (void *)&rxpktinfor); 9712 if (!QDF_IS_STATUS_SUCCESS(status)) { 9713 pe_err("Failed extract cds packet. status %d", status); 9714 return QDF_STATUS_E_FAILURE; 9715 } 9716 9717 hdr = WMA_GET_RX_MAC_HEADER(rxpktinfor); 9718 if (hdr->fc.type == SIR_MAC_MGMT_FRAME) { 9719 pe_debug("RxBd: %pK mHdr: %pK Type: %d Subtype: %d SizeFC: %zu", 9720 rxpktinfor, hdr, hdr->fc.type, hdr->fc.subType, 9721 sizeof(tSirMacFrameCtl)); 9722 *type = hdr->fc.type; 9723 *subtype = hdr->fc.subType; 9724 } else { 9725 pe_err("Not a management packet type %d", hdr->fc.type); 9726 return QDF_STATUS_E_INVAL; 9727 } 9728 return QDF_STATUS_SUCCESS; 9729 } 9730 9731 static void lim_get_min_rate(uint8_t *min_rate, tSirMacRateSet *rateset) 9732 { 9733 uint8_t curr_rate, i; 9734 9735 for (i = 0; i < rateset->numRates; i++) { 9736 /* Ignore MSB - set to indicate basic rate */ 9737 curr_rate = rateset->rate[i] & 0x7F; 9738 *min_rate = (curr_rate < *min_rate) ? curr_rate : 9739 *min_rate; 9740 } 9741 9742 pe_debug("supported min_rate: %0x(%d)", *min_rate, *min_rate); 9743 } 9744 9745 static bool lim_is_enable_he_mcs0_for_6ghz_mgmt(struct pe_session *session, 9746 qdf_freq_t freq) 9747 { 9748 bool enable_he_mcs0_for_6ghz_mgmt = false; 9749 9750 if (!wlan_reg_is_6ghz_chan_freq(freq)) 9751 return enable_he_mcs0_for_6ghz_mgmt; 9752 9753 /* 9754 * For 6GHz freq and if enable_he_mcs0_for_mgmt_6ghz INI is 9755 * enabled then FW will use rate of MCS0 for 11AX and configured 9756 * via WMI_MGMT_TX_SEND_CMDID 9757 */ 9758 wlan_mlme_get_mgmt_6ghz_rate_support( 9759 session->mac_ctx->psoc, 9760 &enable_he_mcs0_for_6ghz_mgmt); 9761 9762 return enable_he_mcs0_for_6ghz_mgmt; 9763 } 9764 9765 enum rateid lim_get_min_session_txrate(struct pe_session *session, 9766 qdf_freq_t *pre_auth_freq) 9767 { 9768 enum rateid rid = RATEID_DEFAULT; 9769 uint8_t min_rate = SIR_MAC_RATE_54; 9770 tSirMacRateSet *rateset; 9771 qdf_freq_t op_freq; 9772 9773 if (!session) 9774 return rid; 9775 9776 rateset = &session->rateSet; 9777 9778 if (pre_auth_freq) { 9779 pe_debug("updated rateset to pre auth freq %d", 9780 *pre_auth_freq); 9781 if (*pre_auth_freq && 9782 !lim_is_enable_he_mcs0_for_6ghz_mgmt(session, 9783 *pre_auth_freq)) 9784 lim_get_basic_rates(rateset, *pre_auth_freq); 9785 else 9786 return rid; 9787 } 9788 9789 op_freq = wlan_get_operation_chan_freq(session->vdev); 9790 if (lim_is_enable_he_mcs0_for_6ghz_mgmt(session, op_freq)) 9791 return rid; 9792 9793 lim_get_min_rate(&min_rate, rateset); 9794 9795 if (session->is_oui_auth_assoc_6mbps_2ghz_enable) 9796 min_rate = SIR_MAC_RATE_6; 9797 9798 switch (min_rate) { 9799 case SIR_MAC_RATE_1: 9800 rid = RATEID_1MBPS; 9801 break; 9802 case SIR_MAC_RATE_2: 9803 rid = RATEID_2MBPS; 9804 break; 9805 case SIR_MAC_RATE_5_5: 9806 rid = RATEID_5_5MBPS; 9807 break; 9808 case SIR_MAC_RATE_11: 9809 rid = RATEID_11MBPS; 9810 break; 9811 case SIR_MAC_RATE_6: 9812 rid = RATEID_6MBPS; 9813 break; 9814 case SIR_MAC_RATE_9: 9815 rid = RATEID_9MBPS; 9816 break; 9817 case SIR_MAC_RATE_12: 9818 rid = RATEID_12MBPS; 9819 break; 9820 case SIR_MAC_RATE_18: 9821 rid = RATEID_18MBPS; 9822 break; 9823 case SIR_MAC_RATE_24: 9824 rid = RATEID_24MBPS; 9825 break; 9826 case SIR_MAC_RATE_36: 9827 rid = RATEID_36MBPS; 9828 break; 9829 case SIR_MAC_RATE_48: 9830 rid = RATEID_48MBPS; 9831 break; 9832 case SIR_MAC_RATE_54: 9833 rid = RATEID_54MBPS; 9834 break; 9835 default: 9836 rid = RATEID_DEFAULT; 9837 break; 9838 } 9839 9840 return rid; 9841 } 9842 9843 void lim_send_sme_mgmt_frame_ind(struct mac_context *mac_ctx, uint8_t frame_type, 9844 uint8_t *frame, uint32_t frame_len, 9845 uint16_t vdev_id, uint32_t rx_freq, 9846 int8_t rx_rssi, enum rxmgmt_flags rx_flags) 9847 { 9848 tpSirSmeMgmtFrameInd sme_mgmt_frame = NULL; 9849 uint16_t length; 9850 struct wlan_objmgr_vdev *vdev; 9851 9852 length = sizeof(tSirSmeMgmtFrameInd) + frame_len; 9853 9854 sme_mgmt_frame = qdf_mem_malloc(length); 9855 if (!sme_mgmt_frame) 9856 return; 9857 9858 if (qdf_is_macaddr_broadcast( 9859 (struct qdf_mac_addr *)(frame + 4)) && 9860 !vdev_id) { 9861 pe_debug("Broadcast action frame"); 9862 vdev_id = SME_SESSION_ID_BROADCAST; 9863 } 9864 9865 sme_mgmt_frame->frame_len = frame_len; 9866 sme_mgmt_frame->sessionId = vdev_id; 9867 sme_mgmt_frame->frameType = frame_type; 9868 sme_mgmt_frame->rxRssi = rx_rssi; 9869 sme_mgmt_frame->rx_freq = rx_freq; 9870 sme_mgmt_frame->rx_flags = rx_flags; 9871 9872 qdf_mem_zero(sme_mgmt_frame->frameBuf, frame_len); 9873 qdf_mem_copy(sme_mgmt_frame->frameBuf, frame, frame_len); 9874 9875 if (vdev_id != SME_SESSION_ID_BROADCAST && 9876 frame_type == SIR_MAC_MGMT_ACTION) { 9877 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc, 9878 vdev_id, 9879 WLAN_LEGACY_MAC_ID); 9880 if (!vdev) { 9881 pe_debug("Invalid VDEV %d", vdev_id); 9882 goto send_frame; 9883 } 9884 9885 wlan_mlo_update_action_frame_to_user(vdev, 9886 sme_mgmt_frame->frameBuf, 9887 sme_mgmt_frame->frame_len); 9888 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID); 9889 } 9890 9891 send_frame: 9892 if (mac_ctx->mgmt_frame_ind_cb) 9893 mac_ctx->mgmt_frame_ind_cb(sme_mgmt_frame); 9894 else 9895 pe_debug_rl("Management indication callback not registered!!"); 9896 9897 qdf_mem_free(sme_mgmt_frame); 9898 9899 return; 9900 } 9901 9902 void 9903 lim_send_dfs_chan_sw_ie_update(struct mac_context *mac_ctx, struct pe_session *session) 9904 { 9905 /* Update the beacon template and send to FW */ 9906 if (sch_set_fixed_beacon_fields(mac_ctx, session) != 9907 QDF_STATUS_SUCCESS) { 9908 pe_err("Unable to set CSA IE in beacon"); 9909 return; 9910 } 9911 9912 /* Send update beacon template message */ 9913 lim_send_beacon_ind(mac_ctx, session, REASON_CHANNEL_SWITCH); 9914 pe_debug("Updated CSA IE, IE COUNT: %d", 9915 session->gLimChannelSwitch.switchCount); 9916 } 9917 9918 bool lim_is_csa_tx_pending(uint8_t vdev_id) 9919 { 9920 struct pe_session *session; 9921 struct mac_context *mac_ctx = cds_get_context(QDF_MODULE_ID_PE); 9922 bool csa_tx_offload; 9923 9924 if (!mac_ctx) { 9925 mlme_err("Invalid mac context"); 9926 return false; 9927 } 9928 9929 session = pe_find_session_by_vdev_id(mac_ctx, vdev_id); 9930 if (!session) { 9931 pe_err("Session does not exist for given vdev_id %d", vdev_id); 9932 return false; 9933 } 9934 9935 csa_tx_offload = wlan_psoc_nif_fw_ext_cap_get(mac_ctx->psoc, 9936 WLAN_SOC_CEXT_CSA_TX_OFFLOAD); 9937 if (session->dfsIncludeChanSwIe && 9938 (session->gLimChannelSwitch.switchCount == 9939 mac_ctx->sap.SapDfsInfo.sap_ch_switch_beacon_cnt) && 9940 csa_tx_offload) 9941 return true; 9942 9943 return false; 9944 } 9945 9946 void lim_send_csa_tx_complete(uint8_t vdev_id) 9947 { 9948 QDF_STATUS status; 9949 tSirSmeCSAIeTxCompleteRsp *chan_switch_tx_rsp; 9950 struct pe_session *session; 9951 struct scheduler_msg msg = {0}; 9952 bool csa_tx_offload; 9953 uint8_t length = sizeof(*chan_switch_tx_rsp); 9954 struct mac_context *mac_ctx = cds_get_context(QDF_MODULE_ID_PE); 9955 9956 if (!mac_ctx) { 9957 mlme_err("Invalid mac context"); 9958 return; 9959 } 9960 9961 session = pe_find_session_by_vdev_id(mac_ctx, vdev_id); 9962 if (!session) { 9963 pe_err("Session does not exist for given vdev_id %d", vdev_id); 9964 return; 9965 } 9966 9967 /* Stop the timer if already running in case of csa*/ 9968 csa_tx_offload = wlan_psoc_nif_fw_ext_cap_get(mac_ctx->psoc, 9969 WLAN_SOC_CEXT_CSA_TX_OFFLOAD); 9970 if (csa_tx_offload) 9971 qdf_mc_timer_stop(&session->ap_ecsa_timer); 9972 9973 /* Done with CSA IE update, send response back to SME */ 9974 session->gLimChannelSwitch.switchCount = 0; 9975 if (mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch == false) 9976 session->gLimChannelSwitch.switchMode = 0; 9977 9978 session->dfsIncludeChanSwIe = false; 9979 session->dfsIncludeChanWrapperIe = false; 9980 9981 chan_switch_tx_rsp = qdf_mem_malloc(length); 9982 if (!chan_switch_tx_rsp) 9983 return; 9984 9985 chan_switch_tx_rsp->sessionId = session->smeSessionId; 9986 chan_switch_tx_rsp->chanSwIeTxStatus = QDF_STATUS_SUCCESS; 9987 9988 msg.type = eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND; 9989 msg.bodyptr = chan_switch_tx_rsp; 9990 9991 status = scheduler_post_message(QDF_MODULE_ID_PE, QDF_MODULE_ID_SME, 9992 QDF_MODULE_ID_SME, &msg); 9993 if (QDF_IS_STATUS_ERROR(status)) 9994 qdf_mem_free(chan_switch_tx_rsp); 9995 } 9996 9997 void lim_process_ap_ecsa_timeout(void *data) 9998 { 9999 struct pe_session *session = (struct pe_session *)data; 10000 struct mac_context *mac_ctx; 10001 uint8_t bcn_int, ch_width; 10002 uint32_t ch_freq; 10003 bool csa_tx_offload; 10004 QDF_STATUS status; 10005 10006 if (!session || !session->valid) { 10007 pe_err("Session is not valid"); 10008 return; 10009 } 10010 10011 mac_ctx = session->mac_ctx; 10012 10013 if (!session->dfsIncludeChanSwIe && 10014 !session->bw_update_include_ch_sw_ie) { 10015 pe_debug("session->dfsIncludeChanSwIe/chWidthUpdateIncludeChanSwIe not set"); 10016 return; 10017 } 10018 10019 if (session->bw_update_include_ch_sw_ie) { 10020 /* Stop the timer if already running */ 10021 qdf_mc_timer_stop(&session->ap_ecsa_timer); 10022 10023 lim_nss_or_ch_width_update_rsp(mac_ctx, 10024 session->vdev_id, 10025 QDF_STATUS_SUCCESS, 10026 REASON_CH_WIDTH_UPDATE); 10027 session->gLimChannelSwitch.switchCount = 0; 10028 session->bw_update_include_ch_sw_ie = false; 10029 10030 /* Clear CSA IE count and update beacon */ 10031 lim_send_dfs_chan_sw_ie_update(mac_ctx, session); 10032 10033 return; 10034 } 10035 10036 if (lim_is_csa_tx_pending(session->vdev_id)) 10037 return lim_send_csa_tx_complete(session->vdev_id); 10038 10039 csa_tx_offload = wlan_psoc_nif_fw_ext_cap_get(mac_ctx->psoc, 10040 WLAN_SOC_CEXT_CSA_TX_OFFLOAD); 10041 10042 if (csa_tx_offload) 10043 return; 10044 10045 /* Stop the timer if already running */ 10046 qdf_mc_timer_stop(&session->ap_ecsa_timer); 10047 10048 if (session->gLimChannelSwitch.switchCount) 10049 /* Decrement the beacon switch count */ 10050 session->gLimChannelSwitch.switchCount--; 10051 10052 /* 10053 * Send only g_sap_chanswitch_beacon_cnt beacons with CSA IE Set in 10054 * when a radar is detected 10055 */ 10056 if (session->gLimChannelSwitch.switchCount > 0) { 10057 /* Send the next beacon with updated CSA IE count */ 10058 lim_send_dfs_chan_sw_ie_update(mac_ctx, session); 10059 10060 ch_freq = session->gLimChannelSwitch.sw_target_freq; 10061 ch_width = session->gLimChannelSwitch.ch_width; 10062 if (mac_ctx->mlme_cfg->dfs_cfg.dfs_beacon_tx_enhanced) { 10063 if (WLAN_REG_IS_6GHZ_CHAN_FREQ(ch_freq)) { 10064 send_extended_chan_switch_action_frame 10065 (mac_ctx, ch_freq, ch_width, 10066 session); 10067 } else { 10068 /* Send Action frame after updating beacon */ 10069 lim_send_chan_switch_action_frame 10070 (mac_ctx, ch_freq, ch_width, 10071 session); 10072 } 10073 } 10074 10075 /* Restart the timer */ 10076 if (session->beaconParams.beaconInterval) 10077 bcn_int = session->beaconParams.beaconInterval; 10078 else 10079 bcn_int = MLME_CFG_BEACON_INTERVAL_DEF; 10080 10081 status = qdf_mc_timer_start(&session->ap_ecsa_timer, 10082 bcn_int); 10083 if (QDF_IS_STATUS_ERROR(status)) { 10084 pe_err("cannot start ap_ecsa_timer"); 10085 lim_process_ap_ecsa_timeout(session); 10086 } 10087 } else { 10088 lim_send_csa_tx_complete(session->vdev_id); 10089 /* Clear CSA IE count and update beacon */ 10090 lim_send_dfs_chan_sw_ie_update(mac_ctx, session); 10091 } 10092 } 10093 10094 QDF_STATUS lim_sta_mlme_vdev_start_send(struct vdev_mlme_obj *vdev_mlme, 10095 uint16_t data_len, void *data) 10096 { 10097 struct mac_context *mac_ctx; 10098 enum vdev_assoc_type assoc_type; 10099 10100 mac_ctx = cds_get_context(QDF_MODULE_ID_PE); 10101 if (!mac_ctx) { 10102 if (data) 10103 qdf_mem_free(data); 10104 return QDF_STATUS_E_INVAL; 10105 } 10106 10107 assoc_type = mlme_get_assoc_type(vdev_mlme->vdev); 10108 switch (assoc_type) { 10109 case VDEV_ASSOC: 10110 lim_process_mlm_join_req(mac_ctx, (tLimMlmJoinReq *)data); 10111 break; 10112 case VDEV_REASSOC: 10113 lim_process_mlm_reassoc_req(mac_ctx, (tLimMlmReassocReq *)data); 10114 break; 10115 case VDEV_FT_REASSOC: 10116 lim_process_mlm_ft_reassoc_req(mac_ctx, 10117 (tLimMlmReassocReq *)data); 10118 break; 10119 default: 10120 pe_err("assoc_type %d is invalid", assoc_type); 10121 } 10122 return QDF_STATUS_SUCCESS; 10123 } 10124 10125 QDF_STATUS lim_sta_mlme_vdev_restart_send(struct vdev_mlme_obj *vdev_mlme, 10126 uint16_t data_len, void *data) 10127 { 10128 struct pe_session *session; 10129 QDF_STATUS status = QDF_STATUS_SUCCESS; 10130 10131 session = (struct pe_session *)data; 10132 if (!session) { 10133 pe_err("Invalid session"); 10134 return QDF_STATUS_E_INVAL; 10135 } 10136 if (!vdev_mlme) { 10137 pe_err("vdev_mlme is NULL"); 10138 return QDF_STATUS_E_INVAL; 10139 } 10140 if (!data) { 10141 pe_err("event_data is NULL"); 10142 return QDF_STATUS_E_INVAL; 10143 } 10144 if (mlme_is_chan_switch_in_progress(vdev_mlme->vdev)) { 10145 switch (session->channelChangeReasonCode) { 10146 case LIM_SWITCH_CHANNEL_OPERATION: 10147 status = __lim_process_channel_switch_timeout(session); 10148 break; 10149 case LIM_SWITCH_CHANNEL_HT_WIDTH: 10150 status = lim_ht_switch_chnl_params(session); 10151 break; 10152 case LIM_SWITCH_CHANNEL_REASSOC: 10153 status = lim_send_switch_chnl_params(session->mac_ctx, 10154 session); 10155 break; 10156 default: 10157 break; 10158 } 10159 } 10160 if (QDF_IS_STATUS_ERROR(status)) { 10161 pe_err_rl("Failed to send VDEV_RESTART for chan switch vdev %d", 10162 wlan_vdev_get_id(vdev_mlme->vdev)); 10163 mlme_set_chan_switch_in_progress(vdev_mlme->vdev, false); 10164 } 10165 10166 return status; 10167 } 10168 10169 QDF_STATUS lim_sta_mlme_vdev_stop_send(struct vdev_mlme_obj *vdev_mlme, 10170 uint16_t data_len, void *data) 10171 { 10172 QDF_STATUS status = QDF_STATUS_SUCCESS; 10173 bool connection_fail = false; 10174 enum vdev_assoc_type assoc_type; 10175 10176 if (!vdev_mlme) { 10177 pe_err("vdev_mlme is NULL"); 10178 return QDF_STATUS_E_INVAL; 10179 } 10180 if (!data) { 10181 pe_err("event_data is NULL"); 10182 return QDF_STATUS_E_INVAL; 10183 } 10184 10185 connection_fail = mlme_is_connection_fail(vdev_mlme->vdev); 10186 pe_debug("Send vdev stop, connection_fail %d", connection_fail); 10187 if (connection_fail) { 10188 assoc_type = mlme_get_assoc_type(vdev_mlme->vdev); 10189 switch (assoc_type) { 10190 case VDEV_ASSOC: 10191 status = 10192 lim_sta_handle_connect_fail((join_params *)data); 10193 break; 10194 case VDEV_REASSOC: 10195 case VDEV_FT_REASSOC: 10196 status = lim_sta_reassoc_error_handler( 10197 (struct reassoc_params *)data); 10198 break; 10199 default: 10200 pe_info("Invalid assoc_type %d", assoc_type); 10201 status = QDF_STATUS_E_INVAL; 10202 break; 10203 } 10204 mlme_set_connection_fail(vdev_mlme->vdev, false); 10205 } else { 10206 status = lim_sta_send_del_bss((struct pe_session *)data); 10207 } 10208 10209 return status; 10210 } 10211 10212 QDF_STATUS 10213 lim_sta_mlme_vdev_sta_disconnect_start(struct vdev_mlme_obj *vdev_mlme, 10214 uint16_t data_len, void *data) 10215 { 10216 tpDphHashNode stads; 10217 struct pe_session *session; 10218 struct mac_context *mac_ctx; 10219 uint8_t vdev_id = wlan_vdev_get_id(vdev_mlme->vdev); 10220 10221 mac_ctx = cds_get_context(QDF_MODULE_ID_PE); 10222 if (!mac_ctx) 10223 return QDF_STATUS_E_INVAL; 10224 10225 session = pe_find_session_by_vdev_id(mac_ctx, vdev_id); 10226 if (!session) { 10227 pe_err("session is NULL for vdevid %d", vdev_id); 10228 return QDF_STATUS_E_INVAL; 10229 } 10230 stads = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER, 10231 &session->dph.dphHashTable); 10232 if (!stads) 10233 return QDF_STATUS_E_INVAL; 10234 mlme_set_connection_fail(vdev_mlme->vdev, false); 10235 10236 session->limPrevSmeState = session->limSmeState; 10237 session->limSmeState = eLIM_SME_WT_DISASSOC_STATE; 10238 10239 stads->mlmStaContext.disassocReason = REASON_UNSPEC_FAILURE; 10240 stads->mlmStaContext.cleanupTrigger = eLIM_HOST_DISASSOC; 10241 10242 stads->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE; 10243 10244 wlan_vdev_mlme_sm_deliver_evt(session->vdev, 10245 WLAN_VDEV_SM_EV_CONNECTION_FAIL, 10246 sizeof(*session), session); 10247 10248 return QDF_STATUS_SUCCESS; 10249 } 10250 10251 QDF_STATUS lim_sta_mlme_vdev_req_fail(struct vdev_mlme_obj *vdev_mlme, 10252 uint16_t data_len, void *data) 10253 { 10254 QDF_STATUS status = QDF_STATUS_SUCCESS; 10255 enum vdev_assoc_type assoc_type; 10256 10257 if (!vdev_mlme) { 10258 pe_err("vdev_mlme is NULL"); 10259 return QDF_STATUS_E_INVAL; 10260 } 10261 if (!data) { 10262 pe_err("event_data is NULL"); 10263 return QDF_STATUS_E_INVAL; 10264 } 10265 10266 assoc_type = mlme_get_assoc_type(vdev_mlme->vdev); 10267 switch (assoc_type) { 10268 case VDEV_ASSOC: 10269 status = lim_sta_handle_connect_fail((join_params *)data); 10270 break; 10271 case VDEV_REASSOC: 10272 case VDEV_FT_REASSOC: 10273 status = lim_sta_reassoc_error_handler( 10274 (struct reassoc_params *)data); 10275 break; 10276 default: 10277 pe_info("Invalid assoc_type %d", assoc_type); 10278 status = QDF_STATUS_E_INVAL; 10279 break; 10280 } 10281 10282 return status; 10283 } 10284 10285 void lim_send_beacon(struct mac_context *mac_ctx, struct pe_session *session) 10286 { 10287 if (wlan_vdev_mlme_get_state(session->vdev) == 10288 WLAN_VDEV_S_DFS_CAC_WAIT) 10289 wlan_vdev_mlme_sm_deliver_evt(session->vdev, 10290 WLAN_VDEV_SM_EV_DFS_CAC_COMPLETED, 10291 sizeof(*session), session); 10292 else if (mac_ctx->mlme_cfg->dfs_cfg.dfs_disable_channel_switch && 10293 (wlan_vdev_mlme_get_substate(session->vdev) == 10294 WLAN_VDEV_SS_SUSPEND_CSA_RESTART)) 10295 wlan_vdev_mlme_sm_deliver_evt( 10296 session->vdev, 10297 WLAN_VDEV_SM_EV_CHAN_SWITCH_DISABLED, 10298 sizeof(*session), session); 10299 else 10300 wlan_vdev_mlme_sm_deliver_evt(session->vdev, 10301 WLAN_VDEV_SM_EV_START_SUCCESS, 10302 sizeof(*session), session); 10303 } 10304 10305 void lim_ndi_mlme_vdev_up_transition(struct pe_session *session) 10306 { 10307 if (!LIM_IS_NDI_ROLE(session)) 10308 return; 10309 10310 wlan_vdev_mlme_sm_deliver_evt(session->vdev, 10311 WLAN_VDEV_SM_EV_START_SUCCESS, 10312 sizeof(*session), session); 10313 } 10314 10315 QDF_STATUS lim_sap_move_to_cac_wait_state(struct pe_session *session) 10316 { 10317 QDF_STATUS status; 10318 10319 status = 10320 wlan_vdev_mlme_sm_deliver_evt(session->vdev, 10321 WLAN_VDEV_SM_EV_DFS_CAC_WAIT, 10322 sizeof(*session), session); 10323 return status; 10324 } 10325 10326 QDF_STATUS lim_ap_mlme_vdev_start_send(struct vdev_mlme_obj *vdev_mlme, 10327 uint16_t data_len, void *data) 10328 { 10329 struct pe_session *session; 10330 tpLimMlmStartReq start_req = (tLimMlmStartReq *)data; 10331 struct mac_context *mac_ctx; 10332 10333 if (!data) { 10334 pe_err("data is NULL"); 10335 return QDF_STATUS_E_INVAL; 10336 } 10337 10338 mac_ctx = cds_get_context(QDF_MODULE_ID_PE); 10339 if (!mac_ctx) 10340 return QDF_STATUS_E_INVAL; 10341 10342 session = pe_find_session_by_session_id(mac_ctx, 10343 start_req->sessionId); 10344 if (!session) { 10345 pe_err("session is NULL"); 10346 return QDF_STATUS_E_INVAL; 10347 } 10348 10349 lim_process_mlm_start_req(session->mac_ctx, start_req); 10350 10351 return QDF_STATUS_SUCCESS; 10352 } 10353 10354 static inline void lim_send_csa_restart_resp(struct mac_context *mac_ctx, 10355 struct pe_session *session) 10356 { 10357 struct scheduler_msg msg = {0}; 10358 QDF_STATUS status; 10359 10360 msg.type = eWNI_SME_CSA_RESTART_RSP; 10361 msg.bodyptr = NULL; 10362 msg.bodyval = session->smeSessionId; 10363 10364 status = scheduler_post_message(QDF_MODULE_ID_PE, QDF_MODULE_ID_SME, 10365 QDF_MODULE_ID_SME, &msg); 10366 } 10367 10368 QDF_STATUS lim_ap_mlme_vdev_update_beacon(struct vdev_mlme_obj *vdev_mlme, 10369 enum beacon_update_op op, 10370 uint16_t data_len, void *data) 10371 { 10372 struct pe_session *session; 10373 struct mac_context *mac_ctx; 10374 10375 if (!data) { 10376 mac_ctx = cds_get_context(QDF_MODULE_ID_PE); 10377 if (!mac_ctx) { 10378 pe_err("mac ctx is null"); 10379 return QDF_STATUS_E_INVAL; 10380 } 10381 session = pe_find_session_by_vdev_id( 10382 mac_ctx, vdev_mlme->vdev->vdev_objmgr.vdev_id); 10383 if (!session) { 10384 pe_err("session is NULL"); 10385 return QDF_STATUS_E_INVAL; 10386 } 10387 } else { 10388 session = (struct pe_session *)data; 10389 } 10390 if (LIM_IS_NDI_ROLE(session)) 10391 return QDF_STATUS_SUCCESS; 10392 10393 if (op == BEACON_INIT) 10394 lim_send_beacon_ind(session->mac_ctx, session, REASON_DEFAULT); 10395 else if (op == BEACON_UPDATE) 10396 lim_send_beacon_ind(session->mac_ctx, 10397 session, 10398 REASON_CONFIG_UPDATE); 10399 else if (op == BEACON_CSA) 10400 lim_send_csa_restart_resp(session->mac_ctx, session); 10401 10402 return QDF_STATUS_SUCCESS; 10403 } 10404 10405 QDF_STATUS lim_ap_mlme_vdev_up_send(struct vdev_mlme_obj *vdev_mlme, 10406 uint16_t data_len, void *data) 10407 { 10408 struct scheduler_msg msg = {0}; 10409 QDF_STATUS status; 10410 struct pe_session *session; 10411 struct mac_context *mac_ctx; 10412 10413 if (!data) { 10414 mac_ctx = cds_get_context(QDF_MODULE_ID_PE); 10415 if (!mac_ctx) { 10416 pe_err("mac ctx is null"); 10417 return QDF_STATUS_E_INVAL; 10418 } 10419 session = pe_find_session_by_vdev_id( 10420 mac_ctx, vdev_mlme->vdev->vdev_objmgr.vdev_id); 10421 if (!session) { 10422 pe_err("session is NULL"); 10423 return QDF_STATUS_E_INVAL; 10424 } 10425 } else { 10426 session = (struct pe_session *)data; 10427 } 10428 10429 if (LIM_IS_NDI_ROLE(session)) 10430 return QDF_STATUS_SUCCESS; 10431 10432 10433 msg.type = SIR_HAL_SEND_AP_VDEV_UP; 10434 msg.bodyval = session->smeSessionId; 10435 10436 status = scheduler_post_message(QDF_MODULE_ID_PE, QDF_MODULE_ID_WMA, 10437 QDF_MODULE_ID_WMA, &msg); 10438 10439 return status; 10440 } 10441 10442 QDF_STATUS lim_ap_mlme_vdev_rnr_notify(struct pe_session *session) 10443 { 10444 struct mac_context *mac_ctx; 10445 uint8_t vdev_id_list[MAX_NUMBER_OF_CONC_CONNECTIONS]; 10446 qdf_freq_t freq_list[MAX_NUMBER_OF_CONC_CONNECTIONS]; 10447 uint8_t vdev_num; 10448 uint8_t i; 10449 struct pe_session *co_session; 10450 QDF_STATUS status = QDF_STATUS_SUCCESS; 10451 10452 mac_ctx = cds_get_context(QDF_MODULE_ID_PE); 10453 if (!mac_ctx) { 10454 pe_err("mac ctx is null"); 10455 return QDF_STATUS_E_INVAL; 10456 } 10457 if (!session) { 10458 pe_err("session is NULL"); 10459 return QDF_STATUS_E_INVAL; 10460 } 10461 if (!mlme_is_notify_co_located_ap_update_rnr(session->vdev)) 10462 return status; 10463 mlme_set_notify_co_located_ap_update_rnr(session->vdev, false); 10464 // Only 6G SAP need to notify co-located SAP to add RNR 10465 if (!wlan_reg_is_6ghz_chan_freq(session->curr_op_freq)) 10466 return status; 10467 pe_debug("vdev id %d non mlo 6G AP notify co-located AP to update RNR", 10468 wlan_vdev_get_id(session->vdev)); 10469 vdev_num = policy_mgr_get_sap_mode_info(mac_ctx->psoc, freq_list, 10470 vdev_id_list); 10471 for (i = 0; i < vdev_num; i++) { 10472 if (vdev_id_list[i] == session->vdev_id) 10473 continue; 10474 if (wlan_reg_is_6ghz_chan_freq(freq_list[i])) 10475 continue; 10476 co_session = pe_find_session_by_vdev_id(mac_ctx, 10477 vdev_id_list[i]); 10478 if (!co_session) 10479 continue; 10480 10481 status = sch_set_fixed_beacon_fields(mac_ctx, co_session); 10482 if (QDF_IS_STATUS_ERROR(status)) { 10483 pe_err("Unable to update 6g co located RNR in beacon"); 10484 return status; 10485 } 10486 10487 status = lim_send_beacon_ind(mac_ctx, co_session, 10488 REASON_RNR_UPDATE); 10489 if (QDF_IS_STATUS_ERROR(status)) { 10490 pe_err("Unable to send beacon indication"); 10491 return status; 10492 } 10493 } 10494 10495 return status; 10496 } 10497 10498 QDF_STATUS lim_ap_mlme_vdev_disconnect_peers(struct vdev_mlme_obj *vdev_mlme, 10499 uint16_t data_len, void *data) 10500 { 10501 struct pe_session *session; 10502 struct mac_context *mac_ctx; 10503 10504 if (!data) { 10505 mac_ctx = cds_get_context(QDF_MODULE_ID_PE); 10506 if (!mac_ctx) { 10507 pe_err("mac ctx is null"); 10508 return QDF_STATUS_E_INVAL; 10509 } 10510 session = pe_find_session_by_vdev_id( 10511 mac_ctx, vdev_mlme->vdev->vdev_objmgr.vdev_id); 10512 if (!session) { 10513 pe_err("session is NULL"); 10514 return QDF_STATUS_E_INVAL; 10515 } 10516 } else { 10517 session = (struct pe_session *)data; 10518 } 10519 10520 lim_delete_all_peers(session); 10521 10522 return QDF_STATUS_SUCCESS; 10523 } 10524 10525 #ifdef WLAN_FEATURE_11BE 10526 static 10527 void lim_apply_puncture(struct mac_context *mac, 10528 struct pe_session *session, 10529 qdf_freq_t sec_chan_freq) 10530 { 10531 uint16_t puncture_bitmap; 10532 10533 puncture_bitmap = 10534 *(uint16_t *)session->eht_op.disabled_sub_chan_bitmap; 10535 10536 if (puncture_bitmap) { 10537 pe_debug("Apply puncture to reg: bitmap 0x%x, freq: %d, bw %d, mhz_freq_seg1: %d", 10538 puncture_bitmap, 10539 session->curr_op_freq, 10540 session->ch_width, 10541 sec_chan_freq); 10542 wlan_reg_apply_puncture(mac->pdev, 10543 puncture_bitmap, 10544 session->curr_op_freq, 10545 session->ch_width, 10546 sec_chan_freq); 10547 } 10548 } 10549 10550 static 10551 void lim_remove_puncture(struct mac_context *mac, 10552 struct pe_session *session) 10553 { 10554 uint16_t puncture_bitmap; 10555 10556 puncture_bitmap = 10557 *(uint16_t *)session->eht_op.disabled_sub_chan_bitmap; 10558 if (puncture_bitmap) { 10559 pe_debug("Remove puncture from reg: bitmap 0x%x", 10560 puncture_bitmap); 10561 wlan_reg_remove_puncture(mac->pdev); 10562 } 10563 } 10564 #else 10565 static inline 10566 void lim_apply_puncture(struct mac_context *mac, 10567 struct pe_session *session, 10568 qdf_freq_t sec_chan_freq) 10569 { 10570 } 10571 10572 static inline 10573 void lim_remove_puncture(struct mac_context *mac, 10574 struct pe_session *session) 10575 { 10576 } 10577 #endif 10578 10579 QDF_STATUS lim_ap_mlme_vdev_stop_send(struct vdev_mlme_obj *vdev_mlme, 10580 uint16_t data_len, void *data) 10581 { 10582 struct pe_session *session = (struct pe_session *)data; 10583 QDF_STATUS status = QDF_STATUS_SUCCESS; 10584 struct mac_context *mac_ctx = session->mac_ctx; 10585 10586 if (!data) { 10587 pe_err("data is NULL"); 10588 return QDF_STATUS_E_INVAL; 10589 } 10590 10591 lim_remove_puncture(mac_ctx, session); 10592 10593 if (!wlan_vdev_mlme_is_mlo_ap(vdev_mlme->vdev)) { 10594 mlme_set_notify_co_located_ap_update_rnr(vdev_mlme->vdev, true); 10595 lim_ap_mlme_vdev_rnr_notify(session); 10596 } 10597 status = lim_send_vdev_stop(session); 10598 10599 return status; 10600 } 10601 10602 QDF_STATUS lim_ap_mlme_vdev_restart_send(struct vdev_mlme_obj *vdev_mlme, 10603 uint16_t data_len, void *data) 10604 { 10605 struct pe_session *session = (struct pe_session *)data; 10606 10607 if (!data) { 10608 pe_err("data is NULL"); 10609 return QDF_STATUS_E_INVAL; 10610 } 10611 10612 if (ap_mlme_is_hidden_ssid_restart_in_progress(vdev_mlme->vdev)) 10613 lim_send_vdev_restart(session->mac_ctx, session, 10614 session->smeSessionId); 10615 else 10616 lim_send_switch_chnl_params(session->mac_ctx, session); 10617 10618 return QDF_STATUS_SUCCESS; 10619 } 10620 10621 QDF_STATUS lim_ap_mlme_vdev_start_req_failed(struct vdev_mlme_obj *vdev_mlme, 10622 uint16_t data_len, void *data) 10623 { 10624 struct mac_context *mac_ctx; 10625 10626 mac_ctx = cds_get_context(QDF_MODULE_ID_PE); 10627 if (!mac_ctx) { 10628 if (data) 10629 qdf_mem_free(data); 10630 return QDF_STATUS_E_INVAL; 10631 } 10632 10633 lim_process_mlm_start_cnf(mac_ctx, data); 10634 10635 return QDF_STATUS_SUCCESS; 10636 } 10637 10638 QDF_STATUS lim_mon_mlme_vdev_start_send(struct vdev_mlme_obj *vdev_mlme, 10639 uint16_t data_len, void *data) 10640 { 10641 struct mac_context *mac_ctx; 10642 struct pe_session *session = (struct pe_session *)data; 10643 10644 if (!data) { 10645 pe_err("data is NULL"); 10646 return QDF_STATUS_E_INVAL; 10647 } 10648 10649 mac_ctx = session->mac_ctx; 10650 if (!mac_ctx) { 10651 pe_err("mac_ctx is NULL"); 10652 return QDF_STATUS_E_INVAL; 10653 } 10654 10655 lim_send_switch_chnl_params(mac_ctx, session); 10656 10657 return QDF_STATUS_SUCCESS; 10658 } 10659 10660 void lim_send_start_bss_confirm(struct mac_context *mac_ctx, 10661 tLimMlmStartCnf *start_cnf) 10662 { 10663 if (start_cnf->resultCode == eSIR_SME_SUCCESS) { 10664 lim_post_sme_message(mac_ctx, LIM_MLM_START_CNF, 10665 (uint32_t *)start_cnf); 10666 } else { 10667 struct pe_session *session; 10668 10669 session = pe_find_session_by_session_id(mac_ctx, 10670 start_cnf->sessionId); 10671 if (!session) { 10672 pe_err("session is NULL"); 10673 return; 10674 } 10675 mlme_set_vdev_start_failed(session->vdev, true); 10676 wlan_vdev_mlme_sm_deliver_evt(session->vdev, 10677 WLAN_VDEV_SM_EV_START_REQ_FAIL, 10678 sizeof(*start_cnf), start_cnf); 10679 } 10680 } 10681 10682 QDF_STATUS lim_get_capability_info(struct mac_context *mac, uint16_t *pcap, 10683 struct pe_session *pe_session) 10684 { 10685 uint32_t val = 0; 10686 tpSirMacCapabilityInfo pcap_info; 10687 10688 *pcap = 0; 10689 pcap_info = (tpSirMacCapabilityInfo)pcap; 10690 10691 if (LIM_IS_AP_ROLE(pe_session) || 10692 LIM_IS_STA_ROLE(pe_session)) 10693 pcap_info->ess = 1; /* ESS bit */ 10694 else if (LIM_IS_P2P_DEVICE_ROLE(pe_session) || 10695 LIM_IS_NDI_ROLE(pe_session)) { 10696 pcap_info->ess = 0; 10697 pcap_info->ibss = 0; 10698 } else 10699 pe_warn("can't get capability, role is UNKNOWN!!"); 10700 10701 if (LIM_IS_AP_ROLE(pe_session)) { 10702 val = pe_session->privacy; 10703 } else { 10704 /* PRIVACY bit */ 10705 val = mac->mlme_cfg->wep_params.is_privacy_enabled; 10706 } 10707 if (val) 10708 pcap_info->privacy = 1; 10709 10710 /* Short preamble bit */ 10711 if (mac->mlme_cfg->ht_caps.short_preamble) 10712 pcap_info->shortPreamble = 10713 mac->mlme_cfg->ht_caps.short_preamble; 10714 10715 /* criticalUpdateFlag bit */ 10716 pcap_info->criticalUpdateFlag = 0; 10717 10718 /* Channel agility bit */ 10719 pcap_info->channelAgility = 0; 10720 /* If STA/AP operating in 11B mode, don't set rest of the 10721 * capability info bits. 10722 */ 10723 if (pe_session->dot11mode == MLME_DOT11_MODE_11B) 10724 return QDF_STATUS_SUCCESS; 10725 10726 /* Short slot time bit */ 10727 if (LIM_IS_AP_ROLE(pe_session)) { 10728 pcap_info->shortSlotTime = pe_session->shortSlotTimeSupported; 10729 } else { 10730 /* When in STA mode, we need to check if short slot is 10731 * enabled as well as check if the current operating 10732 * mode is short slot time and then decide whether to 10733 * enable short slot or not. It is safe to check both 10734 * cfg values to determine short slot value in this 10735 * funcn since this funcn is always used after assoc 10736 * when these cfg values are already set based on 10737 * peer's capability. Even in case of IBSS, its value 10738 * is set to correct value either in delBSS as part of 10739 * deleting the previous IBSS or in start BSS as part 10740 * of coalescing 10741 */ 10742 if (mac->mlme_cfg->feature_flags.enable_short_slot_time_11g) { 10743 pcap_info->shortSlotTime = 10744 pe_session->shortSlotTimeSupported; 10745 } 10746 } 10747 10748 /* Spectrum Management bit */ 10749 if (pe_session->lim11hEnable) { 10750 if (mac->mlme_cfg->gen.enabled_11h) 10751 pcap_info->spectrumMgt = 1; 10752 } 10753 /* QoS bit */ 10754 if (mac->mlme_cfg->wmm_params.qos_enabled) 10755 pcap_info->qos = 1; 10756 10757 /* APSD bit */ 10758 if (mac->mlme_cfg->roam_scoring.apsd_enabled) 10759 pcap_info->apsd = 1; 10760 10761 pcap_info->rrm = mac->rrm.rrmConfig.rrm_enabled; 10762 pe_debug("RRM: %d", pcap_info->rrm); 10763 /* DSSS-OFDM */ 10764 /* FIXME : no config defined yet. */ 10765 10766 /* Block ack bit */ 10767 val = mac->mlme_cfg->feature_flags.enable_block_ack; 10768 pcap_info->delayedBA = 10769 (uint16_t) ((val >> WNI_CFG_BLOCK_ACK_ENABLED_DELAYED) & 1); 10770 pcap_info->immediateBA = 10771 (uint16_t) ((val >> WNI_CFG_BLOCK_ACK_ENABLED_IMMEDIATE) & 1); 10772 10773 return QDF_STATUS_SUCCESS; 10774 } 10775 10776 void lim_flush_bssid(struct mac_context *mac_ctx, uint8_t *bssid) 10777 { 10778 struct scan_filter *filter; 10779 struct wlan_objmgr_pdev *pdev = NULL; 10780 QDF_STATUS status; 10781 10782 if (!bssid) 10783 return; 10784 10785 filter = qdf_mem_malloc(sizeof(*filter)); 10786 if (!filter) 10787 return; 10788 10789 filter->num_of_bssid = 1; 10790 qdf_mem_copy(filter->bssid_list[0].bytes, bssid, QDF_MAC_ADDR_SIZE); 10791 10792 pdev = wlan_objmgr_get_pdev_by_id(mac_ctx->psoc, 0, WLAN_LEGACY_MAC_ID); 10793 if (!pdev) { 10794 pe_err("pdev is NULL"); 10795 qdf_mem_free(filter); 10796 return; 10797 } 10798 status = ucfg_scan_flush_results(pdev, filter); 10799 10800 wlan_objmgr_pdev_release_ref(pdev, WLAN_LEGACY_MAC_ID); 10801 10802 if (QDF_IS_STATUS_SUCCESS(status)) 10803 pe_debug("Removed BSS entry:"QDF_MAC_ADDR_FMT" from scan cache", 10804 QDF_MAC_ADDR_REF(bssid)); 10805 10806 if (filter) 10807 qdf_mem_free(filter); 10808 } 10809 10810 bool lim_is_sha384_akm(enum ani_akm_type akm) 10811 { 10812 switch (akm) { 10813 case ANI_AKM_TYPE_FILS_SHA384: 10814 case ANI_AKM_TYPE_FT_FILS_SHA384: 10815 case ANI_AKM_TYPE_SUITEB_EAP_SHA384: 10816 case ANI_AKM_TYPE_FT_SUITEB_EAP_SHA384: 10817 return true; 10818 default: 10819 return false; 10820 } 10821 } 10822 10823 QDF_STATUS lim_set_ch_phy_mode(struct wlan_objmgr_vdev *vdev, uint8_t dot11mode) 10824 { 10825 struct vdev_mlme_obj *mlme_obj; 10826 struct wlan_channel *des_chan; 10827 uint32_t chan_mode; 10828 enum phy_ch_width ch_width; 10829 struct mac_context *mac_ctx = cds_get_context(QDF_MODULE_ID_PE); 10830 uint16_t bw_val; 10831 enum reg_wifi_band band; 10832 uint8_t band_mask; 10833 enum channel_state ch_state; 10834 uint32_t start_ch_freq; 10835 struct ch_params ch_params = {0}; 10836 10837 if (!mac_ctx) 10838 return QDF_STATUS_E_FAILURE; 10839 10840 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(vdev); 10841 if (!mlme_obj) { 10842 pe_err("vdev component object is NULL"); 10843 return QDF_STATUS_E_FAILURE; 10844 } 10845 des_chan = vdev->vdev_mlme.des_chan; 10846 /* 10847 * Set ch_cfreq1 to ch_freq for 20Mhz. If BW is greater than 20 it 10848 * will be updated from ch_freq_seg1. 10849 */ 10850 des_chan->ch_cfreq1 = des_chan->ch_freq; 10851 band = wlan_reg_freq_to_band(des_chan->ch_freq); 10852 band_mask = 1 << band; 10853 ch_width = des_chan->ch_width; 10854 bw_val = wlan_reg_get_bw_value(ch_width); 10855 if (bw_val > 20) { 10856 if (des_chan->ch_freq_seg1) { 10857 des_chan->ch_cfreq1 = 10858 wlan_reg_chan_band_to_freq(mac_ctx->pdev, 10859 des_chan->ch_freq_seg1, 10860 band_mask); 10861 } else if (bw_val >= 160) { 10862 pe_debug("Skip center_freq check for bw %d", bw_val); 10863 } else { 10864 pe_err("Invalid cntr_freq for bw %d, drop to 20", 10865 bw_val); 10866 ch_width = CH_WIDTH_20MHZ; 10867 bw_val = 20; 10868 if (des_chan->ch_cfreq1) 10869 des_chan->ch_freq_seg1 = 10870 wlan_reg_freq_to_chan( 10871 mac_ctx->pdev, 10872 des_chan->ch_cfreq1); 10873 } 10874 } else if (des_chan->ch_cfreq1) { 10875 des_chan->ch_freq_seg1 = 10876 wlan_reg_freq_to_chan(mac_ctx->pdev, 10877 des_chan->ch_cfreq1); 10878 } 10879 if (bw_val > 80) { 10880 if (des_chan->ch_freq_seg2) { 10881 des_chan->ch_cfreq2 = 10882 wlan_reg_chan_band_to_freq(mac_ctx->pdev, 10883 des_chan->ch_freq_seg2, 10884 band_mask); 10885 } else { 10886 pe_err("Invalid cntr_freq for bw %d, drop to 80", 10887 bw_val); 10888 des_chan->ch_cfreq2 = 0; 10889 des_chan->ch_freq_seg2 = 0; 10890 ch_width = CH_WIDTH_80MHZ; 10891 } 10892 } else { 10893 des_chan->ch_cfreq2 = 0; 10894 des_chan->ch_freq_seg2 = 0; 10895 } 10896 10897 des_chan->ch_width = ch_width; 10898 10899 des_chan->ch_flags = 0; 10900 switch (ch_width) { 10901 case CH_WIDTH_20MHZ: 10902 des_chan->ch_flags |= IEEE80211_CHAN_VHT20; 10903 break; 10904 case CH_WIDTH_40MHZ: 10905 des_chan->ch_flags |= IEEE80211_CHAN_VHT40PLUS; 10906 break; 10907 case CH_WIDTH_80MHZ: 10908 des_chan->ch_flags |= IEEE80211_CHAN_VHT80; 10909 break; 10910 case CH_WIDTH_80P80MHZ: 10911 des_chan->ch_flags |= IEEE80211_CHAN_VHT80_80; 10912 break; 10913 case CH_WIDTH_160MHZ: 10914 des_chan->ch_flags |= IEEE80211_CHAN_VHT160; 10915 break; 10916 default: 10917 break; 10918 } 10919 10920 if (WLAN_REG_IS_24GHZ_CH_FREQ(des_chan->ch_freq)) 10921 des_chan->ch_flags |= IEEE80211_CHAN_2GHZ; 10922 else 10923 des_chan->ch_flags |= IEEE80211_CHAN_5GHZ; 10924 10925 des_chan->ch_flagext = 0; 10926 if (wlan_reg_is_dfs_for_freq(mac_ctx->pdev, des_chan->ch_freq)) 10927 des_chan->ch_flagext |= IEEE80211_CHAN_DFS; 10928 if (des_chan->ch_cfreq2) { 10929 if (CH_WIDTH_80P80MHZ == des_chan->ch_width) 10930 start_ch_freq = des_chan->ch_cfreq2 - 30; 10931 else 10932 start_ch_freq = des_chan->ch_freq; 10933 10934 if (IS_DOT11_MODE_EHT(dot11mode)) 10935 wlan_reg_set_create_punc_bitmap(&ch_params, true); 10936 ch_params.ch_width = des_chan->ch_width; 10937 ch_state = 10938 wlan_reg_get_5g_bonded_channel_state_for_pwrmode(mac_ctx->pdev, 10939 start_ch_freq, 10940 &ch_params, 10941 REG_CURRENT_PWR_MODE); 10942 if (CHANNEL_STATE_DFS == ch_state) 10943 des_chan->ch_flagext |= IEEE80211_CHAN_DFS_CFREQ2; 10944 } 10945 10946 chan_mode = wma_chan_phy_mode(des_chan->ch_freq, ch_width, 10947 dot11mode); 10948 10949 if (chan_mode == WLAN_PHYMODE_AUTO || chan_mode == WLAN_PHYMODE_MAX) { 10950 pe_err("Invalid phy mode!"); 10951 return QDF_STATUS_E_FAILURE; 10952 } 10953 if (!des_chan->ch_cfreq1) { 10954 pe_err("Invalid center freq1"); 10955 return QDF_STATUS_E_FAILURE; 10956 } 10957 10958 if ((ch_width == CH_WIDTH_160MHZ || 10959 ch_width == CH_WIDTH_80P80MHZ) && !des_chan->ch_cfreq2) { 10960 pe_err("Invalid center freq2 for 160MHz"); 10961 return QDF_STATUS_E_FAILURE; 10962 } 10963 /* Till conversion is not done in WMI we need to fill fw phy mode */ 10964 mlme_obj->mgmt.generic.phy_mode = wmi_host_to_fw_phymode(chan_mode); 10965 des_chan->ch_phymode = chan_mode; 10966 10967 return QDF_STATUS_SUCCESS; 10968 } 10969 10970 #ifdef WLAN_FEATURE_11BE 10971 /** 10972 * lim_update_ap_puncture() - set puncture_bitmap for ap session 10973 * @session: session 10974 * @ch_params: pointer to ch_params 10975 * 10976 * Return: void 10977 */ 10978 static void lim_update_ap_puncture(struct pe_session *session, 10979 struct ch_params *ch_params) 10980 { 10981 if (ch_params->reg_punc_bitmap) { 10982 *(uint16_t *)session->eht_op.disabled_sub_chan_bitmap = 10983 ch_params->reg_punc_bitmap; 10984 session->eht_op.disabled_sub_chan_bitmap_present = true; 10985 pe_debug("vdev %d, puncture %d", session->vdev_id, 10986 ch_params->reg_punc_bitmap); 10987 } 10988 } 10989 10990 void lim_update_des_chan_puncture(struct wlan_channel *des_chan, 10991 struct ch_params *ch_params) 10992 { 10993 des_chan->puncture_bitmap = ch_params->reg_punc_bitmap; 10994 } 10995 10996 void lim_overwrite_sta_puncture(struct pe_session *session, 10997 struct ch_params *ch_param) 10998 { 10999 uint16_t new_punc = 0; 11000 11001 wlan_reg_extract_puncture_by_bw(session->ch_width, 11002 session->puncture_bitmap, 11003 session->curr_op_freq, 11004 ch_param->mhz_freq_seg1, 11005 ch_param->ch_width, 11006 &new_punc); 11007 11008 ch_param->reg_punc_bitmap = new_punc; 11009 session->puncture_bitmap = new_punc; 11010 } 11011 11012 #else 11013 static void lim_update_ap_puncture(struct pe_session *session, 11014 struct ch_params *ch_params) 11015 { 11016 } 11017 #endif 11018 11019 QDF_STATUS lim_pre_vdev_start(struct mac_context *mac, 11020 struct vdev_mlme_obj *mlme_obj, 11021 struct pe_session *session) 11022 { 11023 struct wlan_channel *des_chan; 11024 enum reg_wifi_band band; 11025 uint8_t band_mask; 11026 struct ch_params ch_params = {0}; 11027 qdf_freq_t sec_chan_freq = 0; 11028 11029 band = wlan_reg_freq_to_band(session->curr_op_freq); 11030 band_mask = 1 << band; 11031 11032 ch_params.ch_width = session->ch_width; 11033 ch_params.mhz_freq_seg0 = 11034 wlan_reg_chan_band_to_freq(mac->pdev, 11035 session->ch_center_freq_seg0, 11036 band_mask); 11037 11038 if (session->ch_center_freq_seg1) 11039 ch_params.mhz_freq_seg1 = 11040 wlan_reg_chan_band_to_freq(mac->pdev, 11041 session->ch_center_freq_seg1, 11042 band_mask); 11043 11044 if (band == (REG_BAND_2G) && (ch_params.ch_width == CH_WIDTH_40MHZ)) { 11045 if (ch_params.mhz_freq_seg0 == session->curr_op_freq + 10) 11046 sec_chan_freq = session->curr_op_freq + 20; 11047 if (ch_params.mhz_freq_seg0 == session->curr_op_freq - 10) 11048 sec_chan_freq = session->curr_op_freq - 20; 11049 } 11050 if (LIM_IS_AP_ROLE(session) && 11051 !mlme_is_chan_switch_in_progress(mlme_obj->vdev)) 11052 lim_apply_puncture(mac, session, ch_params.mhz_freq_seg1); 11053 11054 if (LIM_IS_STA_ROLE(session)) 11055 wlan_cdp_set_peer_freq(mac->psoc, session->bssId, 11056 session->curr_op_freq, 11057 wlan_vdev_get_id(session->vdev)); 11058 11059 if (IS_DOT11_MODE_EHT(session->dot11mode)) 11060 wlan_reg_set_create_punc_bitmap(&ch_params, true); 11061 11062 wlan_reg_set_channel_params_for_pwrmode(mac->pdev, 11063 session->curr_op_freq, 11064 sec_chan_freq, &ch_params, 11065 REG_CURRENT_PWR_MODE); 11066 11067 pe_debug("vdev id %d freq %d seg0 %d seg1 %d ch_width %d cac_duration_ms %d beacon_interval %d hidden_ssid: %d dtimPeriod %d slot_time %d bcn tx rate %d mhz seg0 %d mhz seg1 %d", 11068 session->vdev_id, session->curr_op_freq, 11069 ch_params.center_freq_seg0, 11070 ch_params.center_freq_seg1, ch_params.ch_width, 11071 session->cac_duration_ms, 11072 session->beaconParams.beaconInterval, 11073 session->ssidHidden, session->dtimPeriod, 11074 session->shortSlotTimeSupported, 11075 session->beacon_tx_rate, 11076 ch_params.mhz_freq_seg0, 11077 ch_params.mhz_freq_seg1); 11078 11079 /* Invalid channel width means no suitable channel bonding in current 11080 * regdomain for requested channel frequency. Abort vdev start. 11081 */ 11082 if (ch_params.ch_width == CH_WIDTH_INVALID) { 11083 pe_debug("abort vdev start invalid chan parameters"); 11084 return QDF_STATUS_E_INVAL; 11085 } 11086 11087 if (LIM_IS_STA_ROLE(session)) 11088 lim_overwrite_sta_puncture(session, &ch_params); 11089 11090 des_chan = mlme_obj->vdev->vdev_mlme.des_chan; 11091 des_chan->ch_freq = session->curr_op_freq; 11092 des_chan->ch_width = ch_params.ch_width; 11093 des_chan->ch_freq_seg1 = ch_params.center_freq_seg0; 11094 des_chan->ch_freq_seg2 = ch_params.center_freq_seg1; 11095 des_chan->ch_ieee = wlan_reg_freq_to_chan(mac->pdev, des_chan->ch_freq); 11096 lim_update_des_chan_puncture(des_chan, &ch_params); 11097 if (LIM_IS_AP_ROLE(session)) 11098 lim_update_ap_puncture(session, &ch_params); 11099 session->ch_width = ch_params.ch_width; 11100 session->ch_center_freq_seg0 = ch_params.center_freq_seg0; 11101 session->ch_center_freq_seg1 = ch_params.center_freq_seg1; 11102 if (LIM_IS_AP_ROLE(session)) { 11103 /* Update he ops for puncture */ 11104 wlan_reg_set_create_punc_bitmap(&ch_params, false); 11105 wlan_reg_set_channel_params_for_pwrmode(mac->pdev, 11106 session->curr_op_freq, 11107 sec_chan_freq, 11108 &ch_params, 11109 REG_CURRENT_PWR_MODE); 11110 lim_update_ap_he_op(session, &ch_params); 11111 11112 wlan_mlme_set_ap_oper_ch_width(session->vdev, 11113 session->ch_width); 11114 if (session->ch_width == CH_WIDTH_320MHZ && 11115 policy_mgr_is_conn_lead_to_dbs_sbs(mac->psoc, 11116 session->curr_op_freq)) 11117 wlan_mlme_set_ap_oper_ch_width(session->vdev, 11118 CH_WIDTH_160MHZ); 11119 } 11120 mlme_obj->mgmt.generic.maxregpower = session->maxTxPower; 11121 mlme_obj->proto.generic.beacon_interval = 11122 session->beaconParams.beaconInterval; 11123 if (mlme_obj->mgmt.generic.type == WLAN_VDEV_MLME_TYPE_AP) { 11124 mlme_obj->mgmt.ap.hidden_ssid = session->ssidHidden; 11125 wlan_util_vdev_mgr_set_cac_timeout_for_vdev( 11126 mlme_obj->vdev, session->cac_duration_ms); 11127 } 11128 mlme_obj->proto.generic.dtim_period = session->dtimPeriod; 11129 mlme_obj->proto.generic.slot_time = session->shortSlotTimeSupported; 11130 mlme_obj->mgmt.rate_info.bcn_tx_rate = session->beacon_tx_rate; 11131 11132 mlme_obj->proto.ht_info.allow_ht = !!session->htCapability; 11133 mlme_obj->proto.vht_info.allow_vht = !!session->vhtCapability; 11134 mlme_obj->ext_vdev_ptr->connect_info.uapsd_per_ac_bitmask = 11135 session->gUapsdPerAcBitmask; 11136 11137 if (cds_is_5_mhz_enabled()) 11138 mlme_obj->mgmt.rate_info.quarter_rate = 1; 11139 else if (cds_is_10_mhz_enabled()) 11140 mlme_obj->mgmt.rate_info.half_rate = 1; 11141 11142 if (session->nss == 2) { 11143 mlme_obj->mgmt.chainmask_info.num_rx_chain = 2; 11144 mlme_obj->mgmt.chainmask_info.num_tx_chain = 2; 11145 } else { 11146 mlme_obj->mgmt.chainmask_info.num_rx_chain = 1; 11147 mlme_obj->mgmt.chainmask_info.num_tx_chain = 1; 11148 } 11149 wlan_vdev_mlme_set_ssid(mlme_obj->vdev, session->ssId.ssId, 11150 session->ssId.length); 11151 11152 return lim_set_ch_phy_mode(mlme_obj->vdev, session->dot11mode); 11153 } 11154 11155 uint8_t lim_get_he_max_mcs_idx(enum phy_ch_width ch_width, 11156 tDot11fIEhe_cap *he_cap) 11157 { 11158 uint16_t hecap_rxmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80_80 + 1]; 11159 uint16_t hecap_txmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80_80 + 1]; 11160 11161 qdf_mem_zero(hecap_rxmcsnssmap, sizeof(hecap_rxmcsnssmap)); 11162 qdf_mem_zero(hecap_txmcsnssmap, sizeof(hecap_txmcsnssmap)); 11163 11164 qdf_mem_copy(&hecap_rxmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80], 11165 &he_cap->rx_he_mcs_map_lt_80, 11166 sizeof(u_int16_t)); 11167 qdf_mem_copy(&hecap_txmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80], 11168 &he_cap->tx_he_mcs_map_lt_80, 11169 sizeof(u_int16_t)); 11170 if (he_cap->chan_width_2) { 11171 qdf_mem_copy(&hecap_rxmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_160], 11172 &he_cap->rx_he_mcs_map_160, 11173 sizeof(u_int16_t)); 11174 qdf_mem_copy(&hecap_txmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_160], 11175 &he_cap->tx_he_mcs_map_160, 11176 sizeof(u_int16_t)); 11177 } 11178 if (he_cap->chan_width_3) { 11179 qdf_mem_copy(&hecap_rxmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80_80], 11180 &he_cap->rx_he_mcs_map_80_80, 11181 sizeof(u_int16_t)); 11182 qdf_mem_copy(&hecap_txmcsnssmap[HECAP_TXRX_MCS_NSS_IDX_80_80], 11183 &he_cap->tx_he_mcs_map_80_80, 11184 sizeof(u_int16_t)); 11185 } 11186 11187 return mlme_get_max_he_mcs_idx(ch_width, hecap_rxmcsnssmap, 11188 hecap_txmcsnssmap); 11189 } 11190 11191 uint8_t lim_get_vht_max_mcs_idx(tDot11fIEVHTCaps *vht_cap) 11192 { 11193 return mlme_get_max_vht_mcs_idx(vht_cap->rxMCSMap & 0xff, 11194 vht_cap->txMCSMap & 0xff); 11195 } 11196 11197 uint8_t lim_get_ht_max_mcs_idx(tDot11fIEHTCaps *ht_cap) 11198 { 11199 uint8_t i, maxidx = INVALID_MCS_NSS_INDEX; 11200 11201 for (i = 0; i < 8; i++) { 11202 if (ht_cap->supportedMCSSet[0] & (1 << i)) 11203 maxidx = i; 11204 } 11205 11206 return maxidx; 11207 } 11208 11209 uint8_t lim_get_max_rate_idx(tSirMacRateSet *rateset) 11210 { 11211 uint8_t maxidx; 11212 int i; 11213 11214 maxidx = rateset->rate[0] & 0x7f; 11215 for (i = 1; i < rateset->numRates; i++) { 11216 if ((rateset->rate[i] & 0x7f) > maxidx) 11217 maxidx = rateset->rate[i] & 0x7f; 11218 } 11219 11220 return maxidx; 11221 } 11222 11223 void lim_update_nss(struct mac_context *mac_ctx, tpDphHashNode sta_ds, 11224 uint8_t rx_nss, struct pe_session *session) 11225 { 11226 if (sta_ds->vhtSupportedRxNss != (rx_nss + 1)) { 11227 if (session->nss_forced_1x1) { 11228 pe_debug("Not Updating NSS for special AP"); 11229 return; 11230 } 11231 sta_ds->vhtSupportedRxNss = rx_nss + 1; 11232 lim_set_nss_change(mac_ctx, session, 11233 sta_ds->vhtSupportedRxNss, 11234 sta_ds->staAddr); 11235 } 11236 } 11237 11238 11239 bool lim_update_channel_width(struct mac_context *mac_ctx, 11240 tpDphHashNode sta_ptr, 11241 struct pe_session *session, 11242 enum phy_ch_width ch_width, 11243 enum phy_ch_width *new_ch_width) 11244 { 11245 uint8_t cb_mode; 11246 enum phy_ch_width oper_mode; 11247 enum phy_ch_width fw_vht_ch_wd; 11248 11249 cb_mode = lim_get_cb_mode_for_freq(mac_ctx, session, 11250 session->curr_op_freq); 11251 /* 11252 * Do not update the channel bonding mode if channel bonding 11253 * mode is disabled in INI. 11254 */ 11255 if (cb_mode == WNI_CFG_CHANNEL_BONDING_MODE_DISABLE) 11256 return false; 11257 11258 if (sta_ptr->htSupportedChannelWidthSet) { 11259 if (sta_ptr->vhtSupportedChannelWidthSet > 11260 WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) 11261 oper_mode = CH_WIDTH_160MHZ; 11262 else 11263 oper_mode = sta_ptr->vhtSupportedChannelWidthSet + 1; 11264 } else { 11265 oper_mode = CH_WIDTH_20MHZ; 11266 } 11267 11268 fw_vht_ch_wd = wlan_mlme_get_max_bw(); 11269 11270 if (ch_width > fw_vht_ch_wd) { 11271 pe_debug_rl(QDF_MAC_ADDR_FMT ": Downgrade new bw: %d to max %d", 11272 QDF_MAC_ADDR_REF(sta_ptr->staAddr), 11273 ch_width, fw_vht_ch_wd); 11274 ch_width = fw_vht_ch_wd; 11275 } 11276 if (oper_mode == ch_width) 11277 return false; 11278 11279 pe_debug(QDF_MAC_ADDR_FMT ": Current : %d, New: %d max %d ", 11280 QDF_MAC_ADDR_REF(sta_ptr->staAddr), oper_mode, 11281 ch_width, fw_vht_ch_wd); 11282 11283 if (ch_width >= CH_WIDTH_160MHZ) { 11284 sta_ptr->vhtSupportedChannelWidthSet = 11285 WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ; 11286 ch_width = CH_WIDTH_160MHZ; 11287 } else if (ch_width == CH_WIDTH_80MHZ) { 11288 sta_ptr->vhtSupportedChannelWidthSet = 11289 WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; 11290 } else if (ch_width == CH_WIDTH_40MHZ) { 11291 sta_ptr->vhtSupportedChannelWidthSet = 11292 WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; 11293 } else if (ch_width == CH_WIDTH_20MHZ) { 11294 sta_ptr->vhtSupportedChannelWidthSet = 11295 WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; 11296 } else { 11297 return false; 11298 } 11299 if (ch_width >= CH_WIDTH_40MHZ) 11300 sta_ptr->htSupportedChannelWidthSet = CH_WIDTH_40MHZ; 11301 else 11302 sta_ptr->htSupportedChannelWidthSet = CH_WIDTH_20MHZ; 11303 *new_ch_width = ch_width; 11304 11305 return lim_check_vht_op_mode_change(mac_ctx, session, *new_ch_width, 11306 sta_ptr->staAddr); 11307 } 11308 11309 uint8_t lim_get_vht_ch_width(tDot11fIEVHTCaps *vht_cap, 11310 tDot11fIEVHTOperation *vht_op, 11311 tDot11fIEHTInfo *ht_info) 11312 { 11313 uint8_t ccfs0, ccfs1, offset; 11314 uint8_t ch_width; 11315 11316 ccfs0 = vht_op->chan_center_freq_seg0; 11317 ccfs1 = vht_op->chan_center_freq_seg1; 11318 ch_width = vht_op->chanWidth; 11319 11320 if (ch_width > WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ) { 11321 pe_err("Invalid ch width in vht operation IE %d", ch_width); 11322 return WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; 11323 } 11324 11325 if (vht_cap->vht_extended_nss_bw_cap && 11326 vht_cap->extended_nss_bw_supp && ht_info && ht_info->present) 11327 ccfs1 = ht_info->chan_center_freq_seg2; 11328 11329 /* According to new VHTOP IE definition, vht ch_width will 11330 * be 1 for 80MHz, 160MHz and 80+80MHz. 11331 * 11332 * To get the correct operation ch_width, find center 11333 * frequency difference. 11334 */ 11335 if (ch_width == WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ && ccfs1) { 11336 offset = abs(ccfs0 - ccfs1); 11337 11338 if (offset == 8) 11339 ch_width = WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ; 11340 else if (offset > 16) 11341 ch_width = WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ; 11342 } 11343 return ch_width; 11344 } 11345 11346 bool 11347 lim_set_tpc_power(struct mac_context *mac_ctx, struct pe_session *session) 11348 { 11349 struct wlan_lmac_if_reg_tx_ops *tx_ops; 11350 struct vdev_mlme_obj *mlme_obj; 11351 bool tpe_change = false; 11352 11353 if (!wlan_reg_is_ext_tpc_supported(mac_ctx->psoc)) 11354 return true; 11355 tx_ops = wlan_reg_get_tx_ops(mac_ctx->psoc); 11356 11357 if (!tx_ops || !tx_ops->set_tpc_power) 11358 return false; 11359 11360 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(session->vdev); 11361 if (!mlme_obj) 11362 return false; 11363 11364 if ((session->opmode == QDF_STA_MODE || 11365 session->opmode == QDF_P2P_CLIENT_MODE) && 11366 session->lim_join_req) 11367 lim_process_tpe_ie_from_beacon(mac_ctx, session, 11368 &session->lim_join_req->bssDescription, 11369 &tpe_change); 11370 11371 if (session->opmode == QDF_SAP_MODE || 11372 session->opmode == QDF_P2P_GO_MODE) 11373 mlme_obj->reg_tpc_obj.num_pwr_levels = 0; 11374 11375 lim_calculate_tpc(mac_ctx, session); 11376 11377 tx_ops->set_tpc_power(mac_ctx->psoc, session->vdev_id, 11378 &mlme_obj->reg_tpc_obj); 11379 return true; 11380 } 11381 11382 /* 11383 * lim_get_tx_power() - Function to get the Tx power of the center frequency 11384 * of the sap interface. 11385 * 11386 * @reg_tpc: reg_tpc mlme obj pointer 11387 * @freq: center frequency of the SAP. 11388 * 11389 * Return: tx power 11390 */ 11391 static uint8_t 11392 lim_get_tx_power(struct reg_tpc_power_info *reg_tpc, qdf_freq_t freq) 11393 { 11394 int i; 11395 11396 for (i = 0; i < reg_tpc->num_pwr_levels; i++) { 11397 if (reg_tpc->chan_power_info[i].chan_cfreq == freq) 11398 return reg_tpc->chan_power_info[i].tx_power; 11399 } 11400 11401 return 0; 11402 } 11403 11404 struct pe_session * 11405 lim_get_concurrent_session(struct mac_context *mac_ctx, uint8_t vdev_id, 11406 enum QDF_OPMODE opmode) 11407 { 11408 uint8_t mac_id, conc_vdev_id; 11409 struct pe_session *session; 11410 11411 policy_mgr_get_mac_id_by_session_id(mac_ctx->psoc, vdev_id, &mac_id); 11412 11413 conc_vdev_id = policy_mgr_get_conc_vdev_on_same_mac(mac_ctx->psoc, 11414 vdev_id, mac_id); 11415 11416 session = pe_find_session_by_vdev_id(mac_ctx, conc_vdev_id); 11417 if (!session) 11418 return NULL; 11419 11420 switch (opmode) { 11421 case QDF_STA_MODE: 11422 case QDF_P2P_CLIENT_MODE: 11423 if (session->opmode != QDF_SAP_MODE && 11424 session->opmode != QDF_P2P_GO_MODE) 11425 return NULL; 11426 break; 11427 case QDF_SAP_MODE: 11428 case QDF_P2P_GO_MODE: 11429 if (session->opmode != QDF_STA_MODE && 11430 session->opmode != QDF_P2P_CLIENT_MODE) 11431 return NULL; 11432 break; 11433 default: 11434 return NULL; 11435 } 11436 11437 return session; 11438 } 11439 11440 QDF_STATUS 11441 lim_update_tx_power(struct mac_context *mac_ctx, struct pe_session *sap_session, 11442 struct pe_session *sta_session, bool restore_sta_power) 11443 { 11444 uint8_t pwr_level; 11445 struct vdev_mlme_obj *sta_mlme_obj, *sap_mlme_obj; 11446 struct reg_tpc_power_info *reg_info; 11447 uint8_t tx_power, i; 11448 11449 sta_mlme_obj = wlan_vdev_mlme_get_cmpt_obj(sta_session->vdev); 11450 sap_mlme_obj = wlan_vdev_mlme_get_cmpt_obj(sap_session->vdev); 11451 11452 if (!sta_mlme_obj || !sap_mlme_obj) 11453 return QDF_STATUS_E_FAILURE; 11454 11455 if (restore_sta_power) { 11456 /* SAP interface is removed, restore the STA power */ 11457 wlan_set_tpc_update_required_for_sta(sap_session->vdev, false); 11458 sta_session->sta_follows_sap_power = false; 11459 lim_set_tpc_power(mac_ctx, sta_session); 11460 } else { 11461 /* 11462 * SAP and STA are in different AP power types. Therefore, 11463 * update the reg_tpc_obj of STA with new power levels. 11464 * Do not send new TPC power to FW. 11465 */ 11466 sta_session->sta_follows_sap_power = true; 11467 11468 if (sta_mlme_obj->reg_tpc_obj.power_type_6g == 11469 sap_mlme_obj->reg_tpc_obj.power_type_6g) { 11470 pe_err("STA and SAP are in same power type"); 11471 return QDF_STATUS_E_FAILURE; 11472 } 11473 pe_debug("STA is moved to %d from %d power type", 11474 sap_mlme_obj->reg_tpc_obj.power_type_6g, 11475 sta_mlme_obj->reg_tpc_obj.power_type_6g); 11476 sta_mlme_obj->reg_tpc_obj.power_type_6g = 11477 sap_mlme_obj->reg_tpc_obj.power_type_6g; 11478 11479 tx_power = lim_get_tx_power(&sap_mlme_obj->reg_tpc_obj, 11480 sap_session->curr_op_freq); 11481 11482 reg_info = &sta_mlme_obj->reg_tpc_obj; 11483 pwr_level = reg_info->num_pwr_levels; 11484 for (i = 0; i < pwr_level; i++) 11485 reg_info->chan_power_info[i].tx_power = tx_power; 11486 wlan_set_tpc_update_required_for_sta(sap_session->vdev, true); 11487 } 11488 return QDF_STATUS_SUCCESS; 11489 } 11490 11491 bool 11492 lim_is_power_change_required_for_sta(struct mac_context *mac_ctx, 11493 struct pe_session *sta_session, 11494 struct pe_session *sap_session) 11495 { 11496 enum channel_state channel_state; 11497 struct vdev_mlme_obj *mlme_obj; 11498 uint32_t ap_power_type_6g = 0; 11499 11500 channel_state = 11501 wlan_reg_get_channel_state_for_pwrmode(mac_ctx->pdev, 11502 sap_session->curr_op_freq, 11503 REG_AP_VLP); 11504 11505 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(sap_session->vdev); 11506 if (!mlme_obj) { 11507 pe_err("vdev component object is NULL"); 11508 return false; 11509 } 11510 11511 if (sta_session->curr_op_freq != sap_session->curr_op_freq) { 11512 pe_err("STA and SAP are not in same frequency, do not change TPC power"); 11513 return false; 11514 } 11515 11516 wlan_reg_get_cur_6g_ap_pwr_type(mac_ctx->pdev, &ap_power_type_6g); 11517 11518 if (sta_session->best_6g_power_type == REG_INDOOR_AP && 11519 channel_state & CHANNEL_STATE_ENABLE && 11520 ap_power_type_6g == REG_VERY_LOW_POWER_AP) { 11521 pe_debug("Change the power type of STA from LPI to VLP"); 11522 return true; 11523 } 11524 11525 return false; 11526 } 11527 11528 void 11529 lim_check_conc_power_for_csa(struct mac_context *mac_ctx, 11530 struct pe_session *sap_session) 11531 { 11532 struct pe_session *sta_session; 11533 bool update_required_scc_sta_power = 11534 wlan_get_tpc_update_required_for_sta(sap_session->vdev); 11535 11536 /* 11537 * If SCC power has changed and concurrent session doesn't exist, 11538 * then STA must have got deleted or moved out of 6GHz. 11539 * In that case, reset the change scc power flag for SAP. 11540 */ 11541 sta_session = lim_get_concurrent_session(mac_ctx, sap_session->vdev_id, 11542 sap_session->opmode); 11543 if (!sta_session) { 11544 pe_debug("STA session doesn't exist"); 11545 return; 11546 } 11547 11548 /* If SCC power has changed and the SAP is moving away from 6GHz, 11549 * reset the scc power flag in SAP vdev and restore the STA 11550 * power 11551 */ 11552 if (update_required_scc_sta_power && 11553 !WLAN_REG_IS_6GHZ_CHAN_FREQ(sap_session->curr_op_freq) && 11554 WLAN_REG_IS_6GHZ_CHAN_FREQ(sta_session->curr_op_freq)) { 11555 pe_debug("SAP has moved from 6GHz, restore STA power"); 11556 lim_update_tx_power(mac_ctx, sap_session, sta_session, true); 11557 return; 11558 } 11559 11560 /* If SAP is moving to 6GHz. Then: 11561 * a) If change scc power is not set, check if it needs to be set 11562 * If it is getting set, then send new tpc power to FW. 11563 * b) If change scc power is already set, then SAP is moving from one 11564 * 6GHz to another 6GHz. Recompute the TPC. 11565 */ 11566 if (WLAN_REG_IS_6GHZ_CHAN_FREQ(sap_session->curr_op_freq) && 11567 sta_session && 11568 WLAN_REG_IS_6GHZ_CHAN_FREQ(sta_session->curr_op_freq) && 11569 (wlan_vdev_mlme_get_state(sap_session->vdev) == WLAN_VDEV_S_UP)) { 11570 if (lim_is_power_change_required_for_sta(mac_ctx, sta_session, 11571 sap_session)) { 11572 lim_set_tpc_power(mac_ctx, sap_session); 11573 if (lim_update_tx_power(mac_ctx, sap_session, 11574 sta_session, false) == 11575 QDF_STATUS_SUCCESS) 11576 wlan_set_tpc_update_required_for_sta( 11577 sap_session->vdev, 11578 true); 11579 } 11580 } 11581 } 11582 11583 void 11584 lim_cleanup_power_change(struct mac_context *mac_ctx, 11585 struct pe_session *session) 11586 { 11587 struct pe_session *sap_session; 11588 11589 if (session->opmode != QDF_STA_MODE && 11590 session->opmode != QDF_P2P_CLIENT_MODE) 11591 return; 11592 11593 sap_session = 11594 lim_get_concurrent_session(mac_ctx, session->vdev_id, 11595 session->opmode); 11596 if (!sap_session) 11597 return; 11598 11599 wlan_set_tpc_update_required_for_sta(sap_session->vdev, false); 11600 } 11601 11602 void 11603 lim_update_tx_pwr_on_ctry_change_cb(uint8_t vdev_id) 11604 { 11605 struct mac_context *mac_ctx; 11606 struct pe_session *session; 11607 11608 mac_ctx = cds_get_context(QDF_MODULE_ID_PE); 11609 if (!mac_ctx) { 11610 pe_err("mac ctx is null"); 11611 return; 11612 } 11613 11614 session = pe_find_session_by_vdev_id(mac_ctx, vdev_id); 11615 if (!session) { 11616 pe_err("Unable to find session"); 11617 return; 11618 } 11619 11620 lim_set_tpc_power(mac_ctx, session); 11621 } 11622 11623 struct wlan_channel * 11624 lim_get_connected_chan_for_mode(struct wlan_objmgr_psoc *psoc, 11625 enum QDF_OPMODE device_mode, 11626 qdf_freq_t start_freq, 11627 qdf_freq_t end_freq) 11628 { 11629 struct wlan_channel *des_chan; 11630 struct wlan_objmgr_vdev *vdev; 11631 uint8_t vdev_id; 11632 11633 for (vdev_id = 0; vdev_id < WLAN_UMAC_PSOC_MAX_VDEVS; vdev_id++) { 11634 vdev = 11635 wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 11636 WLAN_LEGACY_MAC_ID); 11637 if (!vdev) 11638 continue; 11639 11640 if (vdev->vdev_mlme.vdev_opmode != device_mode) 11641 goto next; 11642 11643 if ((device_mode == QDF_STA_MODE || 11644 device_mode == QDF_P2P_CLIENT_MODE) && 11645 !wlan_cm_is_vdev_connected(vdev)) 11646 goto next; 11647 11648 des_chan = vdev->vdev_mlme.des_chan; 11649 if (!des_chan) 11650 goto next; 11651 11652 if (des_chan->ch_freq < start_freq || 11653 des_chan->ch_freq > end_freq) 11654 goto next; 11655 11656 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID); 11657 return des_chan; 11658 next: 11659 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID); 11660 } 11661 11662 return NULL; 11663 } 11664 11665 enum phy_ch_width 11666 lim_convert_vht_chwidth_to_phy_chwidth(uint8_t ch_width, bool is_40) 11667 { 11668 switch (ch_width) { 11669 case WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ: 11670 return CH_WIDTH_80P80MHZ; 11671 case WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ: 11672 return CH_WIDTH_160MHZ; 11673 case WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ: 11674 return CH_WIDTH_80MHZ; 11675 case WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ: 11676 if (is_40) 11677 return CH_WIDTH_40MHZ; 11678 else 11679 return CH_WIDTH_20MHZ; 11680 default: 11681 pe_debug("Unknown VHT ch width %d", ch_width); 11682 break; 11683 } 11684 return CH_WIDTH_20MHZ; 11685 } 11686