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