1 /* 2 * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /**========================================================================= 21 22 \brief implementation for PE 11r VoWiFi FT Protocol 23 24 ========================================================================*/ 25 26 /* $Header$ */ 27 28 /*-------------------------------------------------------------------------- 29 Include Files 30 ------------------------------------------------------------------------*/ 31 #include <lim_send_messages.h> 32 #include <lim_types.h> 33 #include <lim_ft.h> 34 #include <lim_ft_defs.h> 35 #include <lim_utils.h> 36 #include <lim_prop_exts_utils.h> 37 #include <lim_assoc_utils.h> 38 #include <lim_session.h> 39 #include <lim_admit_control.h> 40 #include <lim_security_utils.h> 41 #include "wmm_apsd.h" 42 #include "wma.h" 43 #include "wlan_cmn.h" 44 45 /*-------------------------------------------------------------------------- 46 Initialize the FT variables. 47 ------------------------------------------------------------------------*/ 48 void lim_ft_open(struct mac_context *mac, struct pe_session *pe_session) 49 { 50 if (pe_session) 51 qdf_mem_zero(&pe_session->ftPEContext, sizeof(tftPEContext)); 52 } 53 54 void lim_ft_cleanup_all_ft_sessions(struct mac_context *mac) 55 { 56 /* Wrapper function to cleanup all FT sessions */ 57 int i; 58 59 for (i = 0; i < mac->lim.maxBssId; i++) { 60 if (true == mac->lim.gpSession[i].valid) { 61 /* The session is valid, may have FT data */ 62 lim_ft_cleanup(mac, &mac->lim.gpSession[i]); 63 } 64 } 65 } 66 67 void lim_ft_cleanup(struct mac_context *mac, struct pe_session *pe_session) 68 { 69 if (!pe_session) { 70 pe_err("pe_session is NULL"); 71 return; 72 } 73 74 /* Nothing to be done if the session is not in STA mode */ 75 if (!LIM_IS_STA_ROLE(pe_session)) { 76 pe_debug("pe_session is not in STA mode"); 77 return; 78 } 79 80 if (pe_session->ftPEContext.pFTPreAuthReq) { 81 pe_debug("Freeing pFTPreAuthReq: %pK", 82 pe_session->ftPEContext.pFTPreAuthReq); 83 if (NULL != 84 pe_session->ftPEContext.pFTPreAuthReq-> 85 pbssDescription) { 86 qdf_mem_free(pe_session->ftPEContext.pFTPreAuthReq-> 87 pbssDescription); 88 pe_session->ftPEContext.pFTPreAuthReq-> 89 pbssDescription = NULL; 90 } 91 qdf_mem_free(pe_session->ftPEContext.pFTPreAuthReq); 92 pe_session->ftPEContext.pFTPreAuthReq = NULL; 93 } 94 95 if (pe_session->ftPEContext.pAddBssReq) { 96 qdf_mem_free(pe_session->ftPEContext.pAddBssReq); 97 pe_session->ftPEContext.pAddBssReq = NULL; 98 } 99 100 if (pe_session->ftPEContext.pAddStaReq) { 101 qdf_mem_free(pe_session->ftPEContext.pAddStaReq); 102 pe_session->ftPEContext.pAddStaReq = NULL; 103 } 104 105 /* The session is being deleted, cleanup the contents */ 106 qdf_mem_zero(&pe_session->ftPEContext, sizeof(tftPEContext)); 107 } 108 109 #if defined(WLAN_FEATURE_HOST_ROAM) || defined(WLAN_FEATURE_ROAM_OFFLOAD) 110 /*------------------------------------------------------------------ 111 * 112 * Create the new Add Bss Req to the new AP. 113 * This will be used when we are ready to FT to the new AP. 114 * The newly created ft Session entry is passed to this function 115 * 116 *------------------------------------------------------------------*/ 117 void lim_ft_prepare_add_bss_req(struct mac_context *mac, 118 struct pe_session *ft_session, 119 struct bss_description *bssDescription) 120 { 121 struct bss_params *pAddBssParams = NULL; 122 tAddStaParams *sta_ctx; 123 bool chan_width_support = false; 124 tSchBeaconStruct *pBeaconStruct; 125 tDot11fIEVHTCaps *vht_caps = NULL; 126 127 /* Nothing to be done if the session is not in STA mode */ 128 if (!LIM_IS_STA_ROLE(ft_session)) { 129 pe_err("pe_session is not in STA mode"); 130 return; 131 } 132 133 pBeaconStruct = qdf_mem_malloc(sizeof(tSchBeaconStruct)); 134 if (!pBeaconStruct) 135 return; 136 137 /* Package SIR_HAL_ADD_BSS_REQ message parameters */ 138 pAddBssParams = qdf_mem_malloc(sizeof(struct bss_params)); 139 if (!pAddBssParams) { 140 qdf_mem_free(pBeaconStruct); 141 return; 142 } 143 144 lim_extract_ap_capabilities(mac, (uint8_t *) bssDescription->ieFields, 145 lim_get_ielen_from_bss_description(bssDescription), 146 pBeaconStruct); 147 148 if (mac->lim.gLimProtectionControl != 149 MLME_FORCE_POLICY_PROTECTION_DISABLE) 150 lim_decide_sta_protection_on_assoc(mac, pBeaconStruct, 151 ft_session); 152 153 qdf_mem_copy(pAddBssParams->bssId, bssDescription->bssId, 154 sizeof(tSirMacAddr)); 155 pAddBssParams->beaconInterval = bssDescription->beaconInterval; 156 157 pAddBssParams->dtimPeriod = pBeaconStruct->tim.dtimPeriod; 158 pAddBssParams->updateBss = false; 159 160 pAddBssParams->nwType = bssDescription->nwType; 161 162 pAddBssParams->shortSlotTimeSupported = 163 (uint8_t) pBeaconStruct->capabilityInfo.shortSlotTime; 164 pAddBssParams->llbCoexist = 165 (uint8_t) ft_session->beaconParams.llbCoexist; 166 pAddBssParams->rmfEnabled = ft_session->limRmfEnabled; 167 168 /* Use the advertised capabilities from the received beacon/PR */ 169 if (IS_DOT11_MODE_HT(ft_session->dot11mode) && 170 (pBeaconStruct->HTCaps.present)) { 171 chan_width_support = 172 lim_get_ht_capability(mac, 173 eHT_SUPPORTED_CHANNEL_WIDTH_SET, 174 ft_session); 175 lim_sta_add_bss_update_ht_parameter(bssDescription->chan_freq, 176 &pBeaconStruct->HTCaps, 177 &pBeaconStruct->HTInfo, 178 chan_width_support, 179 pAddBssParams); 180 qdf_mem_copy(&pAddBssParams->staContext.capab_info, 181 &pBeaconStruct->capabilityInfo, 182 sizeof(pAddBssParams->staContext.capab_info)); 183 qdf_mem_copy(&pAddBssParams->staContext.ht_caps, 184 (uint8_t *) &pBeaconStruct->HTCaps + 185 sizeof(uint8_t), 186 sizeof(pAddBssParams->staContext.ht_caps)); 187 } 188 189 ft_session->htSecondaryChannelOffset = 190 pBeaconStruct->HTInfo.secondaryChannelOffset; 191 sta_ctx = &pAddBssParams->staContext; 192 /* 193 * in lim_extract_ap_capability function intersection of FW 194 * advertised channel width and AP advertised channel 195 * width has been taken into account for calculating 196 * pe_session->ch_width 197 */ 198 pAddBssParams->ch_width = ft_session->ch_width; 199 sta_ctx->ch_width = ft_session->ch_width; 200 201 if (ft_session->vhtCapability && 202 ft_session->vhtCapabilityPresentInBeacon) { 203 pAddBssParams->vhtCapable = pBeaconStruct->VHTCaps.present; 204 vht_caps = &pBeaconStruct->VHTCaps; 205 lim_update_vhtcaps_assoc_resp(mac, pAddBssParams, 206 vht_caps, ft_session); 207 } else if (ft_session->vhtCapability && 208 pBeaconStruct->vendor_vht_ie.VHTCaps.present) { 209 pe_debug("VHT caps are present in vendor specific IE"); 210 pAddBssParams->vhtCapable = 211 pBeaconStruct->vendor_vht_ie.VHTCaps.present; 212 vht_caps = &pBeaconStruct->vendor_vht_ie.VHTCaps; 213 lim_update_vhtcaps_assoc_resp(mac, pAddBssParams, 214 vht_caps, ft_session); 215 } else { 216 pAddBssParams->vhtCapable = 0; 217 } 218 219 if (lim_is_session_he_capable(ft_session) && 220 pBeaconStruct->he_cap.present) { 221 lim_update_bss_he_capable(mac, pAddBssParams); 222 lim_add_bss_he_cfg(pAddBssParams, ft_session); 223 } 224 225 if (lim_is_session_eht_capable(ft_session) && 226 pBeaconStruct->eht_cap.present) { 227 lim_update_bss_eht_capable(mac, pAddBssParams); 228 lim_add_bss_eht_cfg(pAddBssParams, ft_session); 229 } 230 231 pe_debug("SIR_HAL_ADD_BSS_REQ with frequency: %d, width: %d", 232 bssDescription->chan_freq, pAddBssParams->ch_width); 233 234 /* Populate the STA-related parameters here */ 235 /* Note that the STA here refers to the AP */ 236 { 237 pAddBssParams->staContext.staType = STA_ENTRY_OTHER; 238 239 qdf_mem_copy(pAddBssParams->staContext.bssId, 240 bssDescription->bssId, sizeof(tSirMacAddr)); 241 pAddBssParams->staContext.listenInterval = 242 bssDescription->beaconInterval; 243 244 pAddBssParams->staContext.assocId = 0; 245 pAddBssParams->staContext.uAPSD = 0; 246 pAddBssParams->staContext.maxSPLen = 0; 247 pAddBssParams->staContext.updateSta = false; 248 pAddBssParams->staContext.encryptType = 249 ft_session->encryptType; 250 pAddBssParams->staContext.rmfEnabled = 251 ft_session->limRmfEnabled; 252 253 if (IS_DOT11_MODE_HT(ft_session->dot11mode) && 254 (pBeaconStruct->HTCaps.present)) { 255 pAddBssParams->staContext.htCapable = 1; 256 if (ft_session->vhtCapability && 257 IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps)) { 258 pAddBssParams->staContext.vhtCapable = 1; 259 if ((pBeaconStruct->VHTCaps.suBeamFormerCap || 260 pBeaconStruct->VHTCaps.muBeamformerCap) && 261 ft_session->vht_config.su_beam_formee) 262 sta_ctx->vhtTxBFCapable 263 = 1; 264 if (pBeaconStruct->VHTCaps.suBeamformeeCap && 265 ft_session->vht_config.su_beam_former) 266 sta_ctx->enable_su_tx_bformer = 1; 267 } 268 if (lim_is_session_he_capable(ft_session) && 269 pBeaconStruct->he_cap.present) 270 lim_intersect_ap_he_caps(ft_session, 271 pAddBssParams, 272 pBeaconStruct, NULL, 273 bssDescription); 274 275 if (lim_is_session_eht_capable(ft_session) && 276 pBeaconStruct->eht_cap.present) 277 lim_intersect_ap_eht_caps(ft_session, 278 pAddBssParams, 279 pBeaconStruct, NULL); 280 281 pAddBssParams->staContext.mimoPS = 282 (tSirMacHTMIMOPowerSaveState) pBeaconStruct->HTCaps. 283 mimoPowerSave; 284 pAddBssParams->staContext.maxAmpduDensity = 285 pBeaconStruct->HTCaps.mpduDensity; 286 pAddBssParams->staContext.fShortGI20Mhz = 287 (uint8_t) pBeaconStruct->HTCaps.shortGI20MHz; 288 pAddBssParams->staContext.fShortGI40Mhz = 289 (uint8_t) pBeaconStruct->HTCaps.shortGI40MHz; 290 pAddBssParams->staContext.maxAmpduSize = 291 pBeaconStruct->HTCaps.maxRxAMPDUFactor; 292 } 293 294 if ((ft_session->limWmeEnabled 295 && pBeaconStruct->wmeEdcaPresent) 296 || (ft_session->limQosEnabled 297 && pBeaconStruct->edcaPresent)) 298 pAddBssParams->staContext.wmmEnabled = 1; 299 else 300 pAddBssParams->staContext.wmmEnabled = 0; 301 302 pAddBssParams->staContext.wpa_rsn = pBeaconStruct->rsnPresent; 303 /* For OSEN Connection AP does not advertise RSN or WPA IE 304 * so from the IEs we get from supplicant we get this info 305 * so for FW to transmit EAPOL message 4 we shall set 306 * wpa_rsn 307 */ 308 pAddBssParams->staContext.wpa_rsn |= 309 (pBeaconStruct->wpaPresent << 1); 310 if ((!pAddBssParams->staContext.wpa_rsn) 311 && (ft_session->isOSENConnection)) 312 pAddBssParams->staContext.wpa_rsn = 1; 313 /* Update the rates */ 314 lim_populate_peer_rate_set(mac, 315 &pAddBssParams->staContext. 316 supportedRates, 317 pBeaconStruct->HTCaps.supportedMCSSet, 318 false, ft_session, 319 &pBeaconStruct->VHTCaps, 320 &pBeaconStruct->he_cap, 321 &pBeaconStruct->eht_cap, NULL, 322 bssDescription); 323 } 324 325 pAddBssParams->maxTxPower = ft_session->maxTxPower; 326 327 if (ft_session->limRmfEnabled) { 328 pAddBssParams->rmfEnabled = 1; 329 pAddBssParams->staContext.rmfEnabled = 1; 330 } 331 pAddBssParams->staContext.sessionId = ft_session->peSessionId; 332 pAddBssParams->staContext.smesessionId = ft_session->smeSessionId; 333 334 /* Set a new state for MLME */ 335 if (!lim_is_roam_synch_in_progress(mac->psoc, ft_session)) { 336 ft_session->limMlmState = 337 eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE; 338 MTRACE(mac_trace 339 (mac, TRACE_CODE_MLM_STATE, 340 ft_session->peSessionId, 341 eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE)); 342 } 343 ft_session->ftPEContext.pAddBssReq = pAddBssParams; 344 345 pe_debug("Saving SIR_HAL_ADD_BSS_REQ for pre-auth ap"); 346 347 qdf_mem_free(pBeaconStruct); 348 return; 349 } 350 #endif 351 352 #if defined(WLAN_FEATURE_ROAM_OFFLOAD) 353 354 /** 355 * lim_convert_phymode_to_dot11mode() - get dot11 mode from phymode 356 * @phymode: phymode 357 * 358 * The function is to convert the phymode to corresponding dot11 mode 359 * 360 * Return: dot11mode. 361 */ 362 static uint8_t lim_convert_phymode_to_dot11mode(enum wlan_phymode phymode) 363 { 364 365 if (IS_WLAN_PHYMODE_HE(phymode)) 366 return MLME_DOT11_MODE_11AX; 367 368 if (IS_WLAN_PHYMODE_VHT(phymode)) 369 return MLME_DOT11_MODE_11AC; 370 371 if (IS_WLAN_PHYMODE_HT(phymode)) 372 return MLME_DOT11_MODE_11N; 373 374 #ifdef WLAN_FEATURE_11BE 375 if (IS_WLAN_PHYMODE_EHT(phymode)) 376 return MLME_DOT11_MODE_11BE; 377 #endif 378 379 if (phymode == WLAN_PHYMODE_11G) 380 return MLME_DOT11_MODE_11G; 381 382 if (phymode == WLAN_PHYMODE_11G_ONLY) 383 return MLME_DOT11_MODE_11G_ONLY; 384 385 if (phymode == WLAN_PHYMODE_11A) 386 return MLME_DOT11_MODE_11A; 387 388 if (phymode == WLAN_PHYMODE_11B) 389 return MLME_DOT11_MODE_11B; 390 391 return MLME_DOT11_MODE_ALL; 392 } 393 394 /** 395 * lim_calculate_dot11_mode() - calculate dot11 mode. 396 * @mac_context: mac context 397 * @bcn: beacon structure 398 * @band: reg_wifi_band 399 * 400 * The function is to calculate dot11 mode in case fw doesn't send phy mode. 401 * 402 * Return: dot11mode. 403 */ 404 static uint8_t lim_calculate_dot11_mode(struct mac_context *mac_ctx, 405 tSchBeaconStruct *bcn, 406 enum reg_wifi_band band) 407 { 408 enum mlme_dot11_mode self_dot11_mode; 409 enum mlme_dot11_mode new_dot11_mode; 410 411 self_dot11_mode = mac_ctx->mlme_cfg->dot11_mode.dot11_mode; 412 413 if (band == REG_BAND_2G) 414 new_dot11_mode = MLME_DOT11_MODE_11G; 415 else 416 new_dot11_mode = MLME_DOT11_MODE_11A; 417 418 switch (self_dot11_mode) { 419 case MLME_DOT11_MODE_11AX: 420 case MLME_DOT11_MODE_11AX_ONLY: 421 case MLME_DOT11_MODE_ALL: 422 if (bcn->he_cap.present) 423 return MLME_DOT11_MODE_11AX; 424 else if ((bcn->VHTCaps.present || 425 bcn->vendor_vht_ie.present) && 426 (!(band == REG_BAND_2G && 427 !mac_ctx->mlme_cfg->vht_caps.vht_cap_info.b24ghz_band) 428 )) 429 430 return MLME_DOT11_MODE_11AC; 431 else if (bcn->HTCaps.present) 432 return MLME_DOT11_MODE_11N; 433 fallthrough; 434 case MLME_DOT11_MODE_11AC: 435 case MLME_DOT11_MODE_11AC_ONLY: 436 if ((bcn->VHTCaps.present || 437 bcn->vendor_vht_ie.present) && 438 (!(band == REG_BAND_2G && 439 !mac_ctx->mlme_cfg->vht_caps.vht_cap_info.b24ghz_band) 440 )) 441 return MLME_DOT11_MODE_11AC; 442 else if (bcn->HTCaps.present) 443 return MLME_DOT11_MODE_11N; 444 fallthrough; 445 case MLME_DOT11_MODE_11N: 446 case MLME_DOT11_MODE_11N_ONLY: 447 if (bcn->HTCaps.present) 448 return MLME_DOT11_MODE_11N; 449 fallthrough; 450 default: 451 return new_dot11_mode; 452 } 453 454 } 455 456 /** 457 * lim_fill_dot11mode() - to fill 802.11 mode in FT session 458 * @mac_ctx: pointer to mac ctx 459 * @ft_session: FT session 460 * @pe_session: PE session 461 * @bcn: AP beacon pointer 462 * @bss_phymode: bss phy mode 463 * 464 * This API fills FT session's dot11mode either from pe session or 465 * from CFG depending on the condition. 466 * 467 * Return: none 468 */ 469 static void lim_fill_dot11mode(struct mac_context *mac_ctx, 470 struct pe_session *ft_session, 471 struct pe_session *pe_session, 472 tSchBeaconStruct *bcn, 473 enum wlan_phymode bss_phymode) 474 { 475 if (pe_session->ftPEContext.pFTPreAuthReq && 476 !wlan_is_roam_offload_enabled(mac_ctx->mlme_cfg->lfr)) { 477 ft_session->dot11mode = 478 pe_session->ftPEContext.pFTPreAuthReq->dot11mode; 479 return; 480 } 481 482 if (bss_phymode == WLAN_PHYMODE_AUTO) 483 ft_session->dot11mode = lim_calculate_dot11_mode( 484 mac_ctx, bcn, 485 ft_session->limRFBand); 486 487 else 488 ft_session->dot11mode = 489 lim_convert_phymode_to_dot11mode(bss_phymode); 490 } 491 #elif defined(WLAN_FEATURE_HOST_ROAM) 492 /** 493 * lim_fill_dot11mode() - to fill 802.11 mode in FT session 494 * @mac_ctx: pointer to mac ctx 495 * @ft_session: FT session 496 * @pe_session: PE session 497 * @bcn: AP beacon pointer 498 * @bss_phymode: bss phy mode 499 * 500 * This API fills FT session's dot11mode either from pe session. 501 * 502 * Return: none 503 */ 504 static void lim_fill_dot11mode(struct mac_context *mac_ctx, 505 struct pe_session *ft_session, 506 struct pe_session *pe_session, 507 tSchBeaconStruct *bcn, 508 enum wlan_phymode bss_phymode) 509 { 510 ft_session->dot11mode = 511 pe_session->ftPEContext.pFTPreAuthReq->dot11mode; 512 } 513 #endif 514 515 #if defined(WLAN_FEATURE_HOST_ROAM) || defined(WLAN_FEATURE_ROAM_OFFLOAD) 516 /** 517 * lim_fill_session_power_info() - to fill power info in session 518 * @mac_ctx: pointer to mac ctx 519 * @pbssDescription: Pointer to pbssDescription 520 * @ft_session: Pointer to FT session 521 * @pe_session: Pointer to PE session 522 * 523 * Return: QDF_STATUS 524 */ 525 static QDF_STATUS lim_fill_session_power_info( 526 struct mac_context *mac, 527 struct bss_description *pbssDescription, 528 struct pe_session *ft_session, 529 struct pe_session *pe_session) 530 { 531 uint8_t currentBssUapsd; 532 int8_t localPowerConstraint = 0; 533 int8_t regMax = 0; 534 bool is_pwr_constraint = false; 535 struct vdev_mlme_obj *mlme_obj; 536 enum reg_6g_ap_type power_type_6g; 537 QDF_STATUS status; 538 539 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(pe_session->vdev); 540 if (!mlme_obj) { 541 pe_err("vdev component object is NULL"); 542 return QDF_STATUS_E_FAILURE; 543 } 544 545 lim_extract_ap_capability(mac, (uint8_t *)pbssDescription->ieFields, 546 lim_get_ielen_from_bss_description(pbssDescription), 547 &ft_session->limCurrentBssQosCaps, 548 ¤tBssUapsd, 549 &localPowerConstraint, ft_session, &is_pwr_constraint); 550 551 mlme_obj->reg_tpc_obj.is_power_constraint_abs = !is_pwr_constraint; 552 553 if (wlan_reg_is_6ghz_chan_freq(pbssDescription->chan_freq)) { 554 status = wlan_reg_get_best_6g_power_type( 555 mac->psoc, mac->pdev, 556 &power_type_6g, 557 ft_session->ap_defined_power_type_6g, 558 pbssDescription->chan_freq); 559 if (QDF_IS_STATUS_ERROR(status)) 560 return status; 561 562 ft_session->best_6g_power_type = power_type_6g; 563 mlme_set_best_6g_power_type(ft_session->vdev, power_type_6g); 564 } 565 566 if (wlan_reg_is_ext_tpc_supported(mac->psoc)) { 567 mlme_obj->reg_tpc_obj.ap_constraint_power = 568 localPowerConstraint; 569 } else { 570 regMax = wlan_reg_get_channel_reg_power_for_freq( 571 mac->pdev, ft_session->curr_op_freq); 572 if (is_pwr_constraint) 573 localPowerConstraint = regMax - localPowerConstraint; 574 if (!localPowerConstraint) 575 localPowerConstraint = regMax; 576 577 mlme_obj->reg_tpc_obj.reg_max[0] = regMax; 578 mlme_obj->reg_tpc_obj.ap_constraint_power = 579 localPowerConstraint; 580 mlme_obj->reg_tpc_obj.frequency[0] = ft_session->curr_op_freq; 581 582 #ifdef FEATURE_WLAN_ESE 583 ft_session->maxTxPower = lim_get_max_tx_power(mac, mlme_obj); 584 #else 585 ft_session->maxTxPower = QDF_MIN(regMax, localPowerConstraint); 586 #endif 587 ft_session->def_max_tx_pwr = ft_session->maxTxPower; 588 } 589 590 /* 591 * for mdm platform which QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET 592 * will not call from android framework every 3 seconds, and tx 593 * power will never update. So we use iw dev get tx power need 594 * set maxTxPower non-zero value, that firmware can calc a non-zero 595 * tx power, and update to host driver. 596 */ 597 if (ft_session->maxTxPower == 0) 598 ft_session->maxTxPower = 599 wlan_reg_get_channel_reg_power_for_freq(mac->pdev, 600 ft_session->curr_op_freq); 601 602 pe_debug("Reg max: %d local pwr: %d, max tx pwr: %d", regMax, 603 localPowerConstraint, ft_session->maxTxPower); 604 605 return QDF_STATUS_SUCCESS; 606 } 607 608 /*------------------------------------------------------------------ 609 * 610 * Setup the new session for the pre-auth AP. 611 * Return the newly created session entry. 612 * 613 *------------------------------------------------------------------*/ 614 QDF_STATUS 615 lim_fill_ft_session(struct mac_context *mac, 616 struct bss_description *pbssDescription, 617 struct pe_session *ft_session, 618 struct pe_session *pe_session, 619 enum wlan_phymode bss_phymode) 620 { 621 uint8_t bss_chan_id; 622 tSchBeaconStruct *pBeaconStruct; 623 ePhyChanBondState cbEnabledMode; 624 QDF_STATUS status = QDF_STATUS_SUCCESS; 625 626 pBeaconStruct = qdf_mem_malloc(sizeof(tSchBeaconStruct)); 627 if (!pBeaconStruct) 628 return QDF_STATUS_E_NOMEM; 629 630 /* Retrieve the session that was already created and update the entry */ 631 ft_session->limWmeEnabled = pe_session->limWmeEnabled; 632 ft_session->limQosEnabled = pe_session->limQosEnabled; 633 ft_session->limWsmEnabled = pe_session->limWsmEnabled; 634 ft_session->lim11hEnable = pe_session->lim11hEnable; 635 ft_session->isOSENConnection = pe_session->isOSENConnection; 636 ft_session->connected_akm = pe_session->connected_akm; 637 638 /* Fields to be filled later */ 639 ft_session->lim_join_req = NULL; 640 ft_session->smeSessionId = pe_session->smeSessionId; 641 642 lim_extract_ap_capabilities(mac, (uint8_t *) pbssDescription->ieFields, 643 lim_get_ielen_from_bss_description(pbssDescription), 644 pBeaconStruct); 645 646 qdf_mem_zero(&ft_session->wmm_params, sizeof(tDot11fIEWMMParams)); 647 if (pBeaconStruct->wmm_params.present) 648 qdf_mem_copy(&ft_session->wmm_params, 649 &pBeaconStruct->wmm_params, 650 sizeof(tDot11fIEWMMParams)); 651 652 ft_session->rateSet.numRates = 653 pBeaconStruct->supportedRates.numRates; 654 qdf_mem_copy(ft_session->rateSet.rate, 655 pBeaconStruct->supportedRates.rate, 656 pBeaconStruct->supportedRates.numRates); 657 658 ft_session->extRateSet.numRates = 659 pBeaconStruct->extendedRates.numRates; 660 qdf_mem_copy(ft_session->extRateSet.rate, 661 pBeaconStruct->extendedRates.rate, 662 ft_session->extRateSet.numRates); 663 664 ft_session->ssId.length = pBeaconStruct->ssId.length; 665 qdf_mem_copy(ft_session->ssId.ssId, pBeaconStruct->ssId.ssId, 666 ft_session->ssId.length); 667 /* Copy The channel Id to the session Table */ 668 bss_chan_id = 669 wlan_reg_freq_to_chan(mac->pdev, pbssDescription->chan_freq); 670 ft_session->lim_reassoc_chan_freq = pbssDescription->chan_freq; 671 ft_session->curr_op_freq = pbssDescription->chan_freq; 672 ft_session->limRFBand = lim_get_rf_band(ft_session->curr_op_freq); 673 674 lim_fill_dot11mode(mac, ft_session, pe_session, pBeaconStruct, 675 bss_phymode); 676 pe_debug("dot11mode: %d bss_phymode %d", ft_session->dot11mode, 677 bss_phymode); 678 679 ft_session->vhtCapability = 680 (IS_DOT11_MODE_VHT(ft_session->dot11mode) && 681 (IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps) || 682 IS_BSS_VHT_CAPABLE(pBeaconStruct->vendor_vht_ie.VHTCaps))); 683 ft_session->htCapability = 684 (IS_DOT11_MODE_HT(ft_session->dot11mode) 685 && pBeaconStruct->HTCaps.present); 686 687 if (IS_DOT11_MODE_HE(ft_session->dot11mode) && 688 pBeaconStruct->he_cap.present) { 689 lim_update_session_he_capable(mac, ft_session); 690 lim_copy_join_req_he_cap(ft_session); 691 } 692 if (IS_DOT11_MODE_EHT(ft_session->dot11mode) && 693 pBeaconStruct->eht_cap.present) { 694 lim_update_session_eht_capable(mac, ft_session); 695 lim_copy_join_req_eht_cap(ft_session); 696 } 697 /* Assign default configured nss value in the new session */ 698 if (!wlan_reg_is_24ghz_ch_freq(ft_session->curr_op_freq)) 699 ft_session->vdev_nss = mac->vdev_type_nss_5g.sta; 700 else 701 ft_session->vdev_nss = mac->vdev_type_nss_2g.sta; 702 703 ft_session->nss = ft_session ->vdev_nss; 704 705 if (ft_session->limRFBand == REG_BAND_2G) { 706 cbEnabledMode = mac->roam.configParam.channelBondingMode24GHz; 707 } else { 708 cbEnabledMode = mac->roam.configParam.channelBondingMode5GHz; 709 } 710 ft_session->htSupportedChannelWidthSet = 711 (pBeaconStruct->HTInfo.present) ? 712 (cbEnabledMode && pBeaconStruct->HTInfo.recommendedTxWidthSet && 713 pBeaconStruct->HTCaps.supportedChannelWidthSet) : 0; 714 ft_session->htRecommendedTxWidthSet = 715 ft_session->htSupportedChannelWidthSet; 716 717 if (IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps) && 718 pBeaconStruct->VHTOperation.present && 719 ft_session->vhtCapability) { 720 ft_session->vhtCapabilityPresentInBeacon = 1; 721 } else if (IS_BSS_VHT_CAPABLE(pBeaconStruct->vendor_vht_ie.VHTCaps) && 722 pBeaconStruct->vendor_vht_ie.VHTOperation.present && 723 ft_session->vhtCapability){ 724 ft_session->vhtCapabilityPresentInBeacon = 1; 725 } else { 726 ft_session->vhtCapabilityPresentInBeacon = 0; 727 } 728 729 if (ft_session->htRecommendedTxWidthSet) { 730 ft_session->ch_width = CH_WIDTH_40MHZ; 731 if (ft_session->vhtCapabilityPresentInBeacon && 732 pBeaconStruct->VHTOperation.chanWidth) { 733 ft_session->ch_width = 734 pBeaconStruct->VHTOperation.chanWidth + 1; 735 ft_session->ch_center_freq_seg0 = 736 pBeaconStruct->VHTOperation.chan_center_freq_seg0; 737 ft_session->ch_center_freq_seg1 = 738 pBeaconStruct->VHTOperation.chan_center_freq_seg1; 739 } else if (ft_session->vhtCapabilityPresentInBeacon && 740 pBeaconStruct->vendor_vht_ie.VHTOperation.chanWidth){ 741 ft_session->ch_width = 742 pBeaconStruct->vendor_vht_ie.VHTOperation.chanWidth + 1; 743 ft_session->ch_center_freq_seg0 = 744 pBeaconStruct->vendor_vht_ie.VHTOperation.chan_center_freq_seg0; 745 ft_session->ch_center_freq_seg1 = 746 pBeaconStruct->vendor_vht_ie.VHTOperation.chan_center_freq_seg1; 747 748 } else { 749 if (pBeaconStruct->HTInfo.secondaryChannelOffset == 750 PHY_DOUBLE_CHANNEL_LOW_PRIMARY) 751 ft_session->ch_center_freq_seg0 = 752 bss_chan_id + 2; 753 else if (pBeaconStruct->HTInfo.secondaryChannelOffset == 754 PHY_DOUBLE_CHANNEL_HIGH_PRIMARY) 755 ft_session->ch_center_freq_seg0 = 756 bss_chan_id - 2; 757 else { 758 pe_warn("Invalid sec ch offset"); 759 ft_session->ch_width = CH_WIDTH_20MHZ; 760 ft_session->ch_center_freq_seg0 = 0; 761 ft_session->ch_center_freq_seg1 = 0; 762 } 763 } 764 } else { 765 ft_session->ch_width = CH_WIDTH_20MHZ; 766 ft_session->ch_center_freq_seg0 = 0; 767 ft_session->ch_center_freq_seg1 = 0; 768 } 769 770 sir_copy_mac_addr(ft_session->self_mac_addr, 771 wlan_vdev_mlme_get_macaddr(pe_session->vdev)); 772 sir_copy_mac_addr(ft_session->limReAssocbssId, 773 pbssDescription->bssId); 774 sir_copy_mac_addr(ft_session->prev_ap_bssid, pe_session->bssId); 775 776 /* Store beaconInterval */ 777 ft_session->beaconParams.beaconInterval = 778 pbssDescription->beaconInterval; 779 ft_session->bssType = pe_session->bssType; 780 781 ft_session->statypeForBss = STA_ENTRY_PEER; 782 ft_session->nwType = pbssDescription->nwType; 783 784 785 if (ft_session->bssType == eSIR_INFRASTRUCTURE_MODE) { 786 ft_session->limSystemRole = eLIM_STA_ROLE; 787 } else { 788 /* Throw an error & return & make sure to delete the session */ 789 pe_warn("Invalid bss type"); 790 } 791 792 ft_session->limCurrentBssCaps = pbssDescription->capabilityInfo; 793 ft_session->limReassocBssCaps = pbssDescription->capabilityInfo; 794 if (mac->mlme_cfg->ht_caps.short_slot_time_enabled && 795 SIR_MAC_GET_SHORT_SLOT_TIME(ft_session->limReassocBssCaps)) { 796 ft_session->shortSlotTimeSupported = true; 797 } 798 799 status = lim_fill_session_power_info(mac, pbssDescription, ft_session, 800 pe_session); 801 if (QDF_IS_STATUS_ERROR(status)) { 802 pe_err("Failed to fill power info in ft session"); 803 goto exit; 804 } 805 806 ft_session->limReassocBssQosCaps = 807 ft_session->limCurrentBssQosCaps; 808 809 ft_session->is11Rconnection = pe_session->is11Rconnection; 810 811 #ifdef FEATURE_WLAN_ESE 812 ft_session->is_ese_version_ie_present = 813 pBeaconStruct->is_ese_ver_ie_present; 814 #endif 815 816 if (!lim_is_roam_synch_in_progress(mac->psoc, pe_session)) { 817 ft_session->limPrevSmeState = ft_session->limSmeState; 818 ft_session->limSmeState = eLIM_SME_WT_REASSOC_STATE; 819 MTRACE(mac_trace(mac, 820 TRACE_CODE_SME_STATE, 821 ft_session->peSessionId, 822 ft_session->limSmeState)); 823 } 824 ft_session->encryptType = pe_session->encryptType; 825 ft_session->limRmfEnabled = pe_session->limRmfEnabled; 826 /* Load default OBSS parameters to session entry */ 827 lim_init_obss_params(mac, ft_session); 828 829 /* 830 * By default supported NSS 1x1 is set to true 831 * and later on updated while determining session 832 * supported rates which is the intersection of 833 * self and peer rates 834 */ 835 ft_session->supported_nss_1x1 = true; 836 pe_debug("FT enable smps: %d mode: %d supported nss 1x1: %d", 837 mac->mlme_cfg->ht_caps.enable_smps, 838 mac->mlme_cfg->ht_caps.smps, 839 ft_session->supported_nss_1x1); 840 841 exit: 842 qdf_mem_free(pBeaconStruct); 843 return status; 844 } 845 #endif 846 847 static void 848 lim_ft_send_aggr_qos_rsp(struct mac_context *mac, uint8_t rspReqd, 849 struct aggr_add_ts_param *aggrQosRsp, 850 uint8_t smesessionId) 851 { 852 tpSirAggrQosRsp rsp; 853 int i = 0; 854 855 if (!rspReqd) { 856 return; 857 } 858 rsp = qdf_mem_malloc(sizeof(tSirAggrQosRsp)); 859 if (!rsp) 860 return; 861 862 rsp->messageType = eWNI_SME_FT_AGGR_QOS_RSP; 863 rsp->sessionId = smesessionId; 864 rsp->length = sizeof(*rsp); 865 rsp->aggrInfo.tspecIdx = aggrQosRsp->tspecIdx; 866 for (i = 0; i < QCA_WLAN_AC_ALL; i++) { 867 if ((1 << i) & aggrQosRsp->tspecIdx) { 868 if (QDF_IS_STATUS_SUCCESS(aggrQosRsp->status[i])) 869 rsp->aggrInfo.aggrRsp[i].status = 870 STATUS_SUCCESS; 871 else 872 rsp->aggrInfo.aggrRsp[i].status = 873 STATUS_UNSPECIFIED_FAILURE; 874 rsp->aggrInfo.aggrRsp[i].tspec = aggrQosRsp->tspec[i]; 875 } 876 } 877 lim_send_sme_aggr_qos_rsp(mac, rsp, smesessionId); 878 return; 879 } 880 881 void lim_process_ft_aggr_qos_rsp(struct mac_context *mac, 882 struct scheduler_msg *limMsg) 883 { 884 struct aggr_add_ts_param *pAggrQosRspMsg; 885 struct add_ts_param addTsParam = { 0 }; 886 tpDphHashNode pSta = NULL; 887 uint16_t assocId = 0; 888 tSirMacAddr peerMacAddr; 889 uint8_t rspReqd = 1; 890 struct pe_session *pe_session = NULL; 891 int i = 0; 892 893 pe_debug(" Received AGGR_QOS_RSP from HAL"); 894 SET_LIM_PROCESS_DEFD_MESGS(mac, true); 895 pAggrQosRspMsg = limMsg->bodyptr; 896 if (!pAggrQosRspMsg) { 897 pe_err("NULL pAggrQosRspMsg"); 898 return; 899 } 900 pe_session = 901 pe_find_session_by_session_id(mac, pAggrQosRspMsg->sessionId); 902 if (!pe_session) { 903 pe_err("Cant find session entry"); 904 if (pAggrQosRspMsg) { 905 qdf_mem_free(pAggrQosRspMsg); 906 } 907 return; 908 } 909 if (!LIM_IS_STA_ROLE(pe_session)) { 910 pe_err("pe_session is not in STA mode"); 911 return; 912 } 913 for (i = 0; i < QCA_WLAN_AC_ALL; i++) { 914 if ((((1 << i) & pAggrQosRspMsg->tspecIdx)) && 915 (pAggrQosRspMsg->status[i] != QDF_STATUS_SUCCESS)) { 916 sir_copy_mac_addr(peerMacAddr, pe_session->bssId); 917 addTsParam.pe_session_id = pAggrQosRspMsg->sessionId; 918 addTsParam.tspec = pAggrQosRspMsg->tspec[i]; 919 addTsParam.tspec_idx = pAggrQosRspMsg->tspecIdx; 920 lim_send_delts_req_action_frame(mac, peerMacAddr, 921 rspReqd, 922 &addTsParam.tspec.tsinfo, 923 &addTsParam.tspec, 924 pe_session); 925 pSta = 926 dph_lookup_hash_entry(mac, peerMacAddr, 927 &assocId, 928 &pe_session-> 929 dph.dphHashTable); 930 931 if (pSta) { 932 lim_admit_control_delete_ts(mac, assocId, 933 &addTsParam.tspec. 934 tsinfo, NULL, 935 (uint8_t *) & 936 addTsParam.tspec_idx); 937 } 938 } 939 } 940 lim_ft_send_aggr_qos_rsp(mac, rspReqd, pAggrQosRspMsg, 941 pe_session->smeSessionId); 942 if (pAggrQosRspMsg) { 943 qdf_mem_free(pAggrQosRspMsg); 944 } 945 return; 946 } 947 948 QDF_STATUS lim_process_ft_aggr_qos_req(struct mac_context *mac, 949 uint32_t *msg_buf) 950 { 951 struct scheduler_msg msg = {0}; 952 tSirAggrQosReq *aggrQosReq = (tSirAggrQosReq *) msg_buf; 953 struct aggr_add_ts_param *pAggrAddTsParam; 954 struct pe_session *pe_session = NULL; 955 tpLimTspecInfo tspecInfo; 956 uint8_t ac; 957 tpDphHashNode pSta; 958 uint16_t aid; 959 uint8_t sessionId; 960 int i; 961 962 pAggrAddTsParam = qdf_mem_malloc(sizeof(*pAggrAddTsParam)); 963 if (!pAggrAddTsParam) 964 return QDF_STATUS_E_NOMEM; 965 966 pe_session = pe_find_session_by_bssid(mac, aggrQosReq->bssid.bytes, 967 &sessionId); 968 969 if (!pe_session) { 970 pe_err("psession Entry Null for sessionId: %d", 971 aggrQosReq->sessionId); 972 qdf_mem_free(pAggrAddTsParam); 973 return QDF_STATUS_E_FAILURE; 974 } 975 976 /* Nothing to be done if the session is not in STA mode */ 977 if (!LIM_IS_STA_ROLE(pe_session)) { 978 pe_err("pe_session is not in STA mode"); 979 qdf_mem_free(pAggrAddTsParam); 980 return QDF_STATUS_E_FAILURE; 981 } 982 983 pSta = dph_lookup_hash_entry(mac, aggrQosReq->bssid.bytes, &aid, 984 &pe_session->dph.dphHashTable); 985 if (!pSta) { 986 pe_err("Station context not found - ignoring AddTsRsp"); 987 qdf_mem_free(pAggrAddTsParam); 988 return QDF_STATUS_E_FAILURE; 989 } 990 991 /* Fill in the sessionId specific to PE */ 992 pAggrAddTsParam->sessionId = sessionId; 993 pAggrAddTsParam->tspecIdx = aggrQosReq->aggrInfo.tspecIdx; 994 pAggrAddTsParam->vdev_id = pe_session->smeSessionId; 995 996 for (i = 0; i < QCA_WLAN_AC_ALL; i++) { 997 if (aggrQosReq->aggrInfo.tspecIdx & (1 << i)) { 998 struct mac_tspec_ie *pTspec = 999 &aggrQosReq->aggrInfo.aggrAddTsInfo[i].tspec; 1000 /* Since AddTS response was successful, check for the PSB flag 1001 * and directional flag inside the TS Info field. 1002 * An AC is trigger enabled AC if the PSB subfield is set to 1 1003 * in the uplink direction. 1004 * An AC is delivery enabled AC if the PSB subfield is set to 1 1005 * in the downlink direction. 1006 * An AC is trigger and delivery enabled AC if the PSB subfield 1007 * is set to 1 in the bi-direction field. 1008 */ 1009 if (pTspec->tsinfo.traffic.psb == 1) { 1010 lim_set_tspec_uapsd_mask_per_session(mac, 1011 pe_session, 1012 &pTspec-> 1013 tsinfo, 1014 SET_UAPSD_MASK); 1015 } else { 1016 lim_set_tspec_uapsd_mask_per_session(mac, 1017 pe_session, 1018 &pTspec-> 1019 tsinfo, 1020 CLEAR_UAPSD_MASK); 1021 } 1022 /* 1023 * ADDTS success, so AC is now admitted. 1024 * We shall now use the default 1025 * EDCA parameters as advertised by AP and 1026 * send the updated EDCA params 1027 * to HAL. 1028 */ 1029 ac = upToAc(pTspec->tsinfo.traffic.userPrio); 1030 if (pTspec->tsinfo.traffic.direction == 1031 SIR_MAC_DIRECTION_UPLINK) { 1032 pe_session-> 1033 gAcAdmitMask 1034 [SIR_MAC_DIRECTION_UPLINK] |= 1035 (1 << ac); 1036 } else if (pTspec->tsinfo.traffic.direction == 1037 SIR_MAC_DIRECTION_DNLINK) { 1038 pe_session-> 1039 gAcAdmitMask 1040 [SIR_MAC_DIRECTION_DNLINK] |= 1041 (1 << ac); 1042 } else if (pTspec->tsinfo.traffic.direction == 1043 SIR_MAC_DIRECTION_BIDIR) { 1044 pe_session-> 1045 gAcAdmitMask 1046 [SIR_MAC_DIRECTION_UPLINK] |= 1047 (1 << ac); 1048 pe_session-> 1049 gAcAdmitMask 1050 [SIR_MAC_DIRECTION_DNLINK] |= 1051 (1 << ac); 1052 } 1053 lim_set_active_edca_params(mac, 1054 pe_session->gLimEdcaParams, 1055 pe_session); 1056 1057 lim_send_edca_params(mac, 1058 pe_session->gLimEdcaParamsActive, 1059 pe_session->vdev_id, false); 1060 1061 if (QDF_STATUS_SUCCESS != 1062 lim_tspec_add(mac, pSta->staAddr, pSta->assocId, 1063 pTspec, 0, &tspecInfo)) { 1064 pe_err("Adding entry in lim Tspec Table failed"); 1065 mac->lim.gLimAddtsSent = false; 1066 qdf_mem_free(pAggrAddTsParam); 1067 return QDF_STATUS_E_FAILURE; 1068 } 1069 1070 pAggrAddTsParam->tspec[i] = 1071 aggrQosReq->aggrInfo.aggrAddTsInfo[i].tspec; 1072 } 1073 } 1074 1075 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 1076 if (!mac->mlme_cfg->lfr.lfr3_roaming_offload || 1077 (mac->mlme_cfg->lfr.lfr3_roaming_offload && 1078 !pe_session->is11Rconnection)) 1079 #endif 1080 { 1081 msg.type = WMA_AGGR_QOS_REQ; 1082 msg.bodyptr = pAggrAddTsParam; 1083 msg.bodyval = 0; 1084 1085 /* We need to defer any incoming messages until we get a 1086 * WMA_AGGR_QOS_RSP from HAL. 1087 */ 1088 SET_LIM_PROCESS_DEFD_MESGS(mac, false); 1089 MTRACE(mac_trace_msg_tx(mac, pe_session->peSessionId, msg.type)); 1090 1091 if (QDF_STATUS_SUCCESS != wma_post_ctrl_msg(mac, &msg)) { 1092 pe_warn("wma_post_ctrl_msg() failed"); 1093 SET_LIM_PROCESS_DEFD_MESGS(mac, true); 1094 qdf_mem_free(pAggrAddTsParam); 1095 return QDF_STATUS_E_FAILURE; 1096 } 1097 } 1098 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 1099 else { 1100 /* Implies it is a LFR3.0 based 11r connection 1101 * so donot send add ts request to firmware since it 1102 * already has the RIC IEs */ 1103 1104 /* Send the Aggr QoS response to SME */ 1105 lim_ft_send_aggr_qos_rsp(mac, true, pAggrAddTsParam, 1106 pe_session->smeSessionId); 1107 if (pAggrAddTsParam) { 1108 qdf_mem_free(pAggrAddTsParam); 1109 } 1110 } 1111 #endif 1112 1113 return QDF_STATUS_SUCCESS; 1114 } 1115