1 /* 2 * Copyright (c) 2020-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 any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /* 19 * DOC: wlan_cm_roam_api.c 20 * 21 * Implementation for the Common Roaming interfaces. 22 */ 23 24 #include "wlan_cm_roam_api.h" 25 #include "wlan_vdev_mlme_api.h" 26 #include "wlan_mlme_main.h" 27 #include "wlan_policy_mgr_api.h" 28 #include <wmi_unified_priv.h> 29 #include <../../core/src/wlan_cm_vdev_api.h> 30 #include "wlan_crypto_global_api.h" 31 #include <wlan_cm_api.h> 32 #include "connection_mgr/core/src/wlan_cm_roam.h" 33 #include "wlan_cm_roam_api.h" 34 #include "wlan_dlm_api.h" 35 #include <../../core/src/wlan_cm_roam_i.h> 36 #include "wlan_reg_ucfg_api.h" 37 #include "wlan_connectivity_logging.h" 38 #include "target_if.h" 39 #include "wlan_mlo_mgr_roam.h" 40 41 /* Support for "Fast roaming" (i.e., ESE, LFR, or 802.11r.) */ 42 #define BG_SCAN_OCCUPIED_CHANNEL_LIST_LEN 15 43 #define CM_MIN_RSSI 0 /* 0dbm */ 44 45 #if defined(WLAN_FEATURE_HOST_ROAM) || defined(WLAN_FEATURE_ROAM_OFFLOAD) 46 QDF_STATUS 47 wlan_cm_enable_roaming_on_connected_sta(struct wlan_objmgr_pdev *pdev, 48 uint8_t vdev_id) 49 { 50 uint32_t op_ch_freq_list[MAX_NUMBER_OF_CONC_CONNECTIONS]; 51 uint8_t vdev_id_list[MAX_NUMBER_OF_CONC_CONNECTIONS]; 52 uint32_t sta_vdev_id = WLAN_INVALID_VDEV_ID; 53 uint32_t count, idx; 54 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 55 56 sta_vdev_id = policy_mgr_get_roam_enabled_sta_session_id(psoc, vdev_id); 57 if (sta_vdev_id != WLAN_UMAC_VDEV_ID_MAX) 58 return QDF_STATUS_E_FAILURE; 59 60 count = policy_mgr_get_mode_specific_conn_info(psoc, 61 op_ch_freq_list, 62 vdev_id_list, 63 PM_STA_MODE); 64 if (!count) 65 return QDF_STATUS_E_FAILURE; 66 67 /* 68 * Loop through all connected STA vdevs and roaming will be enabled 69 * on the STA that has a different vdev id from the one passed as 70 * input and has non zero roam trigger value. 71 */ 72 for (idx = 0; idx < count; idx++) { 73 if (vdev_id_list[idx] != vdev_id && 74 mlme_get_roam_trigger_bitmap(psoc, vdev_id_list[idx])) { 75 sta_vdev_id = vdev_id_list[idx]; 76 break; 77 } 78 } 79 80 if (sta_vdev_id == WLAN_INVALID_VDEV_ID) 81 return QDF_STATUS_E_FAILURE; 82 83 if (mlo_check_is_given_vdevs_on_same_mld(psoc, sta_vdev_id, vdev_id)) { 84 mlme_debug("RSO_CFG: vdev:%d , vdev:%d are on same MLD skip RSO enable", 85 sta_vdev_id, vdev_id); 86 87 return QDF_STATUS_E_FAILURE; 88 } 89 90 mlme_debug("ROAM: Enabling roaming on vdev[%d]", sta_vdev_id); 91 92 return cm_roam_state_change(pdev, 93 sta_vdev_id, 94 WLAN_ROAM_RSO_ENABLED, 95 REASON_CTX_INIT, 96 NULL, false); 97 } 98 99 QDF_STATUS wlan_cm_roam_state_change(struct wlan_objmgr_pdev *pdev, 100 uint8_t vdev_id, 101 enum roam_offload_state requested_state, 102 uint8_t reason) 103 { 104 return cm_roam_state_change(pdev, vdev_id, requested_state, reason, 105 NULL, false); 106 } 107 108 QDF_STATUS wlan_cm_roam_send_rso_cmd(struct wlan_objmgr_psoc *psoc, 109 uint8_t vdev_id, uint8_t rso_command, 110 uint8_t reason) 111 { 112 return cm_roam_send_rso_cmd(psoc, vdev_id, rso_command, reason); 113 } 114 115 void wlan_cm_handle_sta_sta_roaming_enablement(struct wlan_objmgr_psoc *psoc, 116 uint8_t vdev_id) 117 { 118 return cm_handle_sta_sta_roaming_enablement(psoc, vdev_id); 119 } 120 121 QDF_STATUS 122 wlan_roam_update_cfg(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, 123 uint8_t reason) 124 { 125 if (!MLME_IS_ROAM_STATE_RSO_ENABLED(psoc, vdev_id)) { 126 mlme_debug("Update cfg received while ROAM RSO not started"); 127 return QDF_STATUS_E_INVAL; 128 } 129 130 return cm_roam_send_rso_cmd(psoc, vdev_id, ROAM_SCAN_OFFLOAD_UPDATE_CFG, 131 reason); 132 } 133 134 #endif 135 136 void 137 cm_update_associated_ch_info(struct wlan_objmgr_vdev *vdev, bool is_update) 138 { 139 struct mlme_legacy_priv *mlme_priv; 140 struct wlan_channel *des_chan; 141 struct assoc_channel_info *assoc_chan_info; 142 struct wlan_objmgr_pdev *pdev; 143 enum phy_ch_width ch_width; 144 QDF_STATUS status; 145 uint8_t band_mask; 146 147 pdev = wlan_vdev_get_pdev(vdev); 148 if (!pdev) { 149 mlme_err("invalid pdev"); 150 return; 151 } 152 153 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 154 if (!mlme_priv) 155 return; 156 157 assoc_chan_info = &mlme_priv->connect_info.assoc_chan_info; 158 if (!is_update) { 159 assoc_chan_info->assoc_ch_width = CH_WIDTH_INVALID; 160 return; 161 } 162 163 des_chan = wlan_vdev_mlme_get_des_chan(vdev); 164 if (!des_chan) 165 return; 166 167 /* If operating mode is STA / P2P-CLI then get the channel width 168 * from phymode. This is due the reason where actual operating 169 * channel width is configured as part of WMI_PEER_ASSOC_CMDID 170 * which could be downgraded while the peer associated. 171 * If there is a failure or operating mode is not STA / P2P-CLI 172 * then get channel width from wlan_channel. 173 */ 174 status = wlan_mlme_get_sta_ch_width(vdev, &ch_width); 175 if (QDF_IS_STATUS_ERROR(status)) 176 assoc_chan_info->assoc_ch_width = des_chan->ch_width; 177 else 178 assoc_chan_info->assoc_ch_width = ch_width; 179 180 if (WLAN_REG_IS_24GHZ_CH_FREQ(des_chan->ch_freq) && 181 des_chan->ch_width == CH_WIDTH_40MHZ) { 182 if (des_chan->ch_cfreq1 == des_chan->ch_freq + BW_10_MHZ) 183 assoc_chan_info->sec_2g_freq = 184 des_chan->ch_freq + BW_20_MHZ; 185 if (des_chan->ch_cfreq1 == des_chan->ch_freq - BW_10_MHZ) 186 assoc_chan_info->sec_2g_freq = 187 des_chan->ch_freq - BW_20_MHZ; 188 } else if (des_chan->ch_width == CH_WIDTH_320MHZ) { 189 if (WLAN_REG_IS_6GHZ_CHAN_FREQ(des_chan->ch_freq)) 190 band_mask = BIT(REG_BAND_6G); 191 else 192 band_mask = BIT(REG_BAND_5G); 193 assoc_chan_info->cen320_freq = 194 wlan_reg_chan_band_to_freq(pdev, 195 des_chan->ch_freq_seg2, 196 band_mask); 197 198 mlme_debug("ch_freq_seg2: %d, cen320_freq: %d", 199 des_chan->ch_freq_seg2, 200 assoc_chan_info->cen320_freq); 201 } 202 203 mlme_debug("ch width :%d, ch_freq:%d, ch_cfreq1:%d, sec_2g_freq:%d", 204 assoc_chan_info->assoc_ch_width, des_chan->ch_freq, 205 des_chan->ch_cfreq1, assoc_chan_info->sec_2g_freq); 206 } 207 208 char *cm_roam_get_requestor_string(enum wlan_cm_rso_control_requestor requestor) 209 { 210 switch (requestor) { 211 case RSO_INVALID_REQUESTOR: 212 default: 213 return "No requestor"; 214 case RSO_START_BSS: 215 return "SAP start"; 216 case RSO_CHANNEL_SWITCH: 217 return "CSA"; 218 case RSO_CONNECT_START: 219 return "STA connection"; 220 case RSO_SAP_CHANNEL_CHANGE: 221 return "SAP Ch switch"; 222 case RSO_NDP_CON_ON_NDI: 223 return "NDP connection"; 224 case RSO_SET_PCL: 225 return "Set PCL"; 226 } 227 } 228 229 QDF_STATUS 230 wlan_cm_rso_set_roam_trigger(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, 231 struct wlan_roam_triggers *trigger) 232 { 233 QDF_STATUS status; 234 struct wlan_objmgr_vdev *vdev; 235 236 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, 237 WLAN_MLME_CM_ID); 238 if (!vdev) { 239 mlme_err("vdev object is NULL"); 240 return QDF_STATUS_E_INVAL; 241 } 242 243 status = cm_roam_acquire_lock(vdev); 244 if (QDF_IS_STATUS_ERROR(status)) 245 goto release_ref; 246 247 status = cm_rso_set_roam_trigger(pdev, vdev_id, trigger); 248 249 cm_roam_release_lock(vdev); 250 251 release_ref: 252 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 253 254 return status; 255 } 256 257 QDF_STATUS wlan_cm_disable_rso(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, 258 enum wlan_cm_rso_control_requestor requestor, 259 uint8_t reason) 260 { 261 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 262 QDF_STATUS status; 263 264 if (reason == REASON_DRIVER_DISABLED && requestor) 265 mlme_set_operations_bitmap(psoc, vdev_id, requestor, false); 266 267 mlme_debug("ROAM_CONFIG: vdev[%d] Disable roaming - requestor:%s", 268 vdev_id, cm_roam_get_requestor_string(requestor)); 269 270 status = cm_roam_state_change(pdev, vdev_id, WLAN_ROAM_RSO_STOPPED, 271 REASON_DRIVER_DISABLED, NULL, false); 272 273 return status; 274 } 275 276 QDF_STATUS wlan_cm_enable_rso(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, 277 enum wlan_cm_rso_control_requestor requestor, 278 uint8_t reason) 279 { 280 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 281 QDF_STATUS status; 282 283 if (reason == REASON_DRIVER_ENABLED && requestor) 284 mlme_set_operations_bitmap(psoc, vdev_id, requestor, true); 285 286 mlme_debug("ROAM_CONFIG: vdev[%d] Enable roaming - requestor:%s", 287 vdev_id, cm_roam_get_requestor_string(requestor)); 288 289 status = cm_roam_state_change(pdev, vdev_id, WLAN_ROAM_RSO_ENABLED, 290 REASON_DRIVER_ENABLED, NULL, false); 291 292 return status; 293 } 294 295 bool wlan_cm_host_roam_in_progress(struct wlan_objmgr_psoc *psoc, 296 uint8_t vdev_id) 297 { 298 struct wlan_objmgr_vdev *vdev; 299 bool host_roam_in_progress = false; 300 301 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 302 WLAN_MLME_CM_ID); 303 if (!vdev) { 304 mlme_err("vdev object is NULL for vdev %d", vdev_id); 305 return host_roam_in_progress; 306 } 307 308 if (wlan_cm_is_vdev_roam_preauth_state(vdev) || 309 wlan_cm_is_vdev_roam_reassoc_state(vdev)) 310 host_roam_in_progress = true; 311 312 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 313 314 return host_roam_in_progress; 315 } 316 317 bool wlan_cm_roaming_in_progress(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id) 318 { 319 bool roaming_in_progress = false; 320 struct wlan_objmgr_vdev *vdev; 321 enum QDF_OPMODE opmode; 322 323 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, 324 WLAN_MLME_CM_ID); 325 if (!vdev) 326 return roaming_in_progress; 327 328 opmode = wlan_vdev_mlme_get_opmode(vdev); 329 if (opmode != QDF_STA_MODE && opmode != QDF_P2P_CLIENT_MODE) 330 goto exit; 331 332 roaming_in_progress = wlan_cm_is_vdev_roaming(vdev); 333 334 exit: 335 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 336 337 return roaming_in_progress; 338 } 339 340 QDF_STATUS wlan_cm_roam_stop_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, 341 uint8_t reason) 342 { 343 return cm_roam_stop_req(psoc, vdev_id, reason, NULL, false); 344 } 345 346 bool wlan_cm_same_band_sta_allowed(struct wlan_objmgr_psoc *psoc) 347 { 348 struct wlan_mlme_psoc_ext_obj *mlme_obj; 349 struct dual_sta_policy *dual_sta_policy; 350 351 if (!wlan_mlme_get_dual_sta_roaming_enabled(psoc)) 352 return true; 353 354 mlme_obj = mlme_get_psoc_ext_obj(psoc); 355 if (!mlme_obj) 356 return true; 357 358 dual_sta_policy = &mlme_obj->cfg.gen.dual_sta_policy; 359 if (dual_sta_policy->primary_vdev_id != WLAN_UMAC_VDEV_ID_MAX && 360 dual_sta_policy->concurrent_sta_policy == 361 QCA_WLAN_CONCURRENT_STA_POLICY_PREFER_PRIMARY) 362 return true; 363 364 return false; 365 } 366 367 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 368 #ifdef FEATURE_RX_LINKSPEED_ROAM_TRIGGER 369 QDF_STATUS wlan_cm_send_roam_linkspeed_state(struct scheduler_msg *msg) 370 { 371 QDF_STATUS status = QDF_STATUS_SUCCESS; 372 struct roam_link_speed_cfg *link_speed_cfg; 373 struct roam_disable_cfg roam_link_speed_cfg; 374 375 if (!msg || !msg->bodyptr) 376 return QDF_STATUS_E_FAILURE; 377 378 link_speed_cfg = msg->bodyptr; 379 roam_link_speed_cfg.vdev_id = link_speed_cfg->vdev_id; 380 roam_link_speed_cfg.cfg = link_speed_cfg->is_link_speed_good; 381 status = wlan_cm_tgt_send_roam_linkspeed_state(link_speed_cfg->psoc, 382 &roam_link_speed_cfg); 383 qdf_mem_free(link_speed_cfg); 384 385 return status; 386 } 387 388 void wlan_cm_roam_link_speed_update(struct wlan_objmgr_psoc *psoc, 389 uint8_t vdev_id, 390 bool is_link_speed_good) 391 { 392 QDF_STATUS qdf_status; 393 struct scheduler_msg msg = {0}; 394 struct roam_link_speed_cfg *link_speed_cfg; 395 396 link_speed_cfg = qdf_mem_malloc(sizeof(*link_speed_cfg)); 397 if (!link_speed_cfg) 398 return; 399 400 link_speed_cfg->psoc = psoc; 401 link_speed_cfg->vdev_id = vdev_id; 402 link_speed_cfg->is_link_speed_good = is_link_speed_good; 403 404 msg.bodyptr = link_speed_cfg; 405 msg.callback = wlan_cm_send_roam_linkspeed_state; 406 407 qdf_status = scheduler_post_message(QDF_MODULE_ID_MLME, 408 QDF_MODULE_ID_OS_IF, 409 QDF_MODULE_ID_OS_IF, &msg); 410 411 if (QDF_IS_STATUS_ERROR(qdf_status)) { 412 mlme_err("post msg failed"); 413 qdf_mem_free(link_speed_cfg); 414 } 415 } 416 417 bool wlan_cm_is_linkspeed_roam_trigger_supported(struct wlan_objmgr_psoc *psoc) 418 { 419 struct wmi_unified *wmi_handle; 420 421 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 422 if (!wmi_handle) { 423 mlme_debug("Invalid WMI handle"); 424 return false; 425 } 426 427 return wmi_service_enabled(wmi_handle, 428 wmi_service_linkspeed_roam_trigger_support); 429 } 430 #endif 431 432 QDF_STATUS 433 wlan_cm_fw_roam_abort_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id) 434 { 435 return cm_fw_roam_abort_req(psoc, vdev_id); 436 } 437 438 uint32_t wlan_cm_get_roam_band_value(struct wlan_objmgr_psoc *psoc, 439 struct wlan_objmgr_vdev *vdev) 440 { 441 struct cm_roam_values_copy config; 442 uint32_t band_mask; 443 444 wlan_cm_roam_cfg_get_value(psoc, wlan_vdev_get_id(vdev), ROAM_BAND, 445 &config); 446 447 band_mask = config.uint_value; 448 mlme_debug("[ROAM BAND] band mask:%d", band_mask); 449 return band_mask; 450 } 451 452 void wlan_cm_roam_activate_pcl_per_vdev(struct wlan_objmgr_psoc *psoc, 453 uint8_t vdev_id, bool pcl_per_vdev) 454 { 455 struct wlan_objmgr_vdev *vdev; 456 struct mlme_legacy_priv *mlme_priv; 457 458 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 459 WLAN_MLME_NB_ID); 460 if (!vdev) { 461 mlme_err("vdev object is NULL"); 462 return; 463 } 464 465 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 466 if (!mlme_priv) { 467 mlme_err("vdev legacy private object is NULL"); 468 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); 469 return; 470 } 471 472 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); 473 474 /* value - true (vdev pcl) false - pdev pcl */ 475 mlme_priv->cm_roam.pcl_vdev_cmd_active = pcl_per_vdev; 476 mlme_debug("CM_ROAM: vdev[%d] SET PCL cmd level - [%s]", vdev_id, 477 pcl_per_vdev ? "VDEV" : "PDEV"); 478 } 479 480 bool wlan_cm_roam_is_pcl_per_vdev_active(struct wlan_objmgr_psoc *psoc, 481 uint8_t vdev_id) 482 { 483 struct wlan_objmgr_vdev *vdev; 484 struct mlme_legacy_priv *mlme_priv; 485 486 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 487 WLAN_MLME_NB_ID); 488 if (!vdev) { 489 mlme_err("vdev object is NULL"); 490 return false; 491 } 492 493 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 494 if (!mlme_priv) { 495 mlme_err("vdev legacy private object is NULL"); 496 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); 497 return false; 498 } 499 500 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); 501 502 return mlme_priv->cm_roam.pcl_vdev_cmd_active; 503 } 504 505 /** 506 * wlan_cm_dual_sta_is_freq_allowed() - This API is used to check if the 507 * provided frequency is allowed for the 2nd STA vdev for connection. 508 * @psoc: Pointer to PSOC object 509 * @freq: Frequency in the given frequency list for the STA that is about to 510 * connect 511 * @connected_sta_freq: 1st connected sta freq 512 * 513 * Make sure to validate the STA+STA condition before calling this 514 * 515 * Return: True if this channel is allowed for connection when dual sta roaming 516 * is enabled 517 */ 518 static bool 519 wlan_cm_dual_sta_is_freq_allowed(struct wlan_objmgr_psoc *psoc, 520 qdf_freq_t freq, qdf_freq_t connected_sta_freq) 521 { 522 if (!connected_sta_freq) 523 return true; 524 525 if (policy_mgr_2_freq_always_on_same_mac(psoc, freq, 526 connected_sta_freq)) 527 return false; 528 529 return true; 530 } 531 532 void 533 wlan_cm_dual_sta_roam_update_connect_channels(struct wlan_objmgr_psoc *psoc, 534 struct scan_filter *filter) 535 { 536 uint32_t i, num_channels = 0; 537 uint32_t *channel_list; 538 bool is_ch_allowed; 539 struct wlan_mlme_psoc_ext_obj *mlme_obj; 540 struct wlan_mlme_cfg *mlme_cfg; 541 struct dual_sta_policy *dual_sta_policy; 542 uint32_t buff_len; 543 char *chan_buff; 544 uint32_t len = 0; 545 uint32_t sta_count; 546 qdf_freq_t op_ch_freq_list[MAX_NUMBER_OF_CONC_CONNECTIONS] = {0}; 547 uint8_t vdev_id_list[MAX_NUMBER_OF_CONC_CONNECTIONS] = {0}; 548 549 filter->num_of_channels = 0; 550 sta_count = policy_mgr_get_mode_specific_conn_info(psoc, op_ch_freq_list, 551 vdev_id_list, 552 PM_STA_MODE); 553 554 /* No need to fill freq list, if no other STA is in connected state */ 555 if (!sta_count) 556 return; 557 558 mlme_obj = mlme_get_psoc_ext_obj(psoc); 559 if (!mlme_obj) 560 return; 561 dual_sta_policy = &mlme_obj->cfg.gen.dual_sta_policy; 562 mlme_cfg = &mlme_obj->cfg; 563 564 mlme_debug("sta_count %d, primary vdev is %d dual sta roaming enabled %d", 565 sta_count, dual_sta_policy->primary_vdev_id, 566 wlan_mlme_get_dual_sta_roaming_enabled(psoc)); 567 568 if (!wlan_mlme_get_dual_sta_roaming_enabled(psoc)) 569 return; 570 571 /* 572 * Check if primary iface is configured. If yes, 573 * then allow further STA connection to all 574 * available bands/channels irrespective of first 575 * STA connection band, which allow driver to 576 * connect with the best available AP present in 577 * environment, so that user can switch to second 578 * connection and mark it as primary. 579 */ 580 if (wlan_mlme_is_primary_interface_configured(psoc)) 581 return; 582 583 /* 584 * If an ML STA exists with more than one link, allow further STA 585 * connection to all available bands/channels irrespective of existing 586 * STA connection/link band. Link that is causing MCC with the second 587 * STA can be disabled post connection. 588 * TODO: Check if disabling the MCC link is allowed or not. TID to 589 * link mapping restricts disabling the link. 590 * 591 * If only one ML link is present, allow the second STA only on other 592 * mac than this link mac. If second STA is allowed on the same mac 593 * also, it may result in MCC and the link can't be disabled 594 * post connection as only one link is present. 595 */ 596 if (policy_mgr_is_mlo_sta_present(psoc) && sta_count > 1) { 597 mlme_debug("Multi link mlo sta present"); 598 return; 599 } 600 601 /* 602 * Get Reg domain valid channels and update to the scan filter 603 * if already 1st sta is in connected state. Don't allow channels 604 * on which the 1st STA is connected. 605 */ 606 num_channels = mlme_cfg->reg.valid_channel_list_num; 607 channel_list = mlme_cfg->reg.valid_channel_freq_list; 608 609 /* 610 * Buffer of (num channel * 5) + 1 to consider the 4 char freq, 611 * 1 space after it for each channel and 1 to end the string 612 * with NULL. 613 */ 614 buff_len = (num_channels * 5) + 1; 615 chan_buff = qdf_mem_malloc(buff_len); 616 if (!chan_buff) 617 return; 618 619 for (i = 0; i < num_channels; i++) { 620 is_ch_allowed = 621 wlan_cm_dual_sta_is_freq_allowed(psoc, channel_list[i], 622 op_ch_freq_list[0]); 623 if (!is_ch_allowed) 624 continue; 625 626 filter->chan_freq_list[filter->num_of_channels] = 627 channel_list[i]; 628 filter->num_of_channels++; 629 630 len += qdf_scnprintf(chan_buff + len, buff_len - len, 631 "%d ", channel_list[i]); 632 } 633 634 if (filter->num_of_channels) 635 mlme_debug("Freq list (%d): %s", filter->num_of_channels, 636 chan_buff); 637 638 qdf_mem_free(chan_buff); 639 } 640 641 void 642 wlan_cm_roam_set_vendor_btm_params(struct wlan_objmgr_psoc *psoc, 643 struct wlan_cm_roam_vendor_btm_params *param) 644 { 645 struct wlan_mlme_psoc_ext_obj *mlme_obj; 646 647 mlme_obj = mlme_get_psoc_ext_obj(psoc); 648 if (!mlme_obj) 649 return; 650 651 qdf_mem_copy(&mlme_obj->cfg.lfr.vendor_btm_param, param, 652 sizeof(struct wlan_cm_roam_vendor_btm_params)); 653 } 654 655 void 656 wlan_cm_roam_get_vendor_btm_params(struct wlan_objmgr_psoc *psoc, 657 struct wlan_cm_roam_vendor_btm_params *param) 658 { 659 struct wlan_mlme_psoc_ext_obj *mlme_obj; 660 661 mlme_obj = mlme_get_psoc_ext_obj(psoc); 662 if (!mlme_obj) 663 return; 664 665 qdf_mem_copy(param, &mlme_obj->cfg.lfr.vendor_btm_param, 666 sizeof(struct wlan_cm_roam_vendor_btm_params)); 667 } 668 669 void wlan_cm_set_psk_pmk(struct wlan_objmgr_pdev *pdev, 670 uint8_t vdev_id, uint8_t *psk_pmk, 671 uint8_t pmk_len) 672 { 673 static struct rso_config *rso_cfg; 674 struct wlan_objmgr_vdev *vdev; 675 676 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, 677 WLAN_MLME_CM_ID); 678 if (!vdev) 679 return; 680 681 rso_cfg = wlan_cm_get_rso_config(vdev); 682 if (!rso_cfg) { 683 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 684 return; 685 } 686 qdf_mem_zero(rso_cfg->psk_pmk, sizeof(rso_cfg->psk_pmk)); 687 if (psk_pmk) 688 qdf_mem_copy(rso_cfg->psk_pmk, psk_pmk, pmk_len); 689 rso_cfg->pmk_len = pmk_len; 690 691 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_MLME, QDF_TRACE_LEVEL_DEBUG, 692 rso_cfg->psk_pmk, WLAN_MAX_PMK_DUMP_BYTES); 693 694 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 695 } 696 697 void wlan_cm_get_psk_pmk(struct wlan_objmgr_pdev *pdev, 698 uint8_t vdev_id, uint8_t *psk_pmk, 699 uint8_t *pmk_len) 700 { 701 static struct rso_config *rso_cfg; 702 struct wlan_objmgr_vdev *vdev; 703 704 if (!psk_pmk || !pmk_len) 705 return; 706 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, 707 WLAN_MLME_CM_ID); 708 if (!vdev) { 709 mlme_err("vdev object is NULL"); 710 return; 711 } 712 rso_cfg = wlan_cm_get_rso_config(vdev); 713 if (!rso_cfg) { 714 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 715 return; 716 } 717 qdf_mem_copy(psk_pmk, rso_cfg->psk_pmk, rso_cfg->pmk_len); 718 *pmk_len = rso_cfg->pmk_len; 719 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 720 } 721 722 void 723 wlan_cm_roam_get_score_delta_params(struct wlan_objmgr_psoc *psoc, 724 struct wlan_roam_triggers *params) 725 { 726 struct wlan_mlme_psoc_ext_obj *mlme_obj; 727 728 mlme_obj = mlme_get_psoc_ext_obj(psoc); 729 if (!mlme_obj) 730 return; 731 732 params->score_delta_param[IDLE_ROAM_TRIGGER] = 733 mlme_obj->cfg.trig_score_delta[IDLE_ROAM_TRIGGER]; 734 params->score_delta_param[BTM_ROAM_TRIGGER] = 735 mlme_obj->cfg.trig_score_delta[BTM_ROAM_TRIGGER]; 736 } 737 738 void 739 wlan_cm_roam_get_min_rssi_params(struct wlan_objmgr_psoc *psoc, 740 struct wlan_roam_triggers *params) 741 { 742 struct wlan_mlme_psoc_ext_obj *mlme_obj; 743 744 mlme_obj = mlme_get_psoc_ext_obj(psoc); 745 if (!mlme_obj) 746 return; 747 748 params->min_rssi_params[DEAUTH_MIN_RSSI] = 749 mlme_obj->cfg.trig_min_rssi[DEAUTH_MIN_RSSI]; 750 params->min_rssi_params[BMISS_MIN_RSSI] = 751 mlme_obj->cfg.trig_min_rssi[BMISS_MIN_RSSI]; 752 params->min_rssi_params[MIN_RSSI_2G_TO_5G_ROAM] = 753 mlme_obj->cfg.trig_min_rssi[MIN_RSSI_2G_TO_5G_ROAM]; 754 } 755 #endif 756 757 QDF_STATUS wlan_cm_roam_cfg_get_value(struct wlan_objmgr_psoc *psoc, 758 uint8_t vdev_id, 759 enum roam_cfg_param roam_cfg_type, 760 struct cm_roam_values_copy *dst_config) 761 { 762 struct wlan_objmgr_vdev *vdev; 763 QDF_STATUS status = QDF_STATUS_SUCCESS; 764 struct rso_config *rso_cfg; 765 struct rso_cfg_params *src_cfg; 766 struct wlan_mlme_psoc_ext_obj *mlme_obj; 767 768 qdf_mem_zero(dst_config, sizeof(*dst_config)); 769 mlme_obj = mlme_get_psoc_ext_obj(psoc); 770 if (!mlme_obj) 771 return QDF_STATUS_E_FAILURE; 772 773 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 774 WLAN_MLME_NB_ID); 775 if (!vdev) { 776 mlme_err("vdev object is NULL"); 777 return QDF_STATUS_E_FAILURE; 778 } 779 780 rso_cfg = wlan_cm_get_rso_config(vdev); 781 if (!rso_cfg) { 782 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); 783 return QDF_STATUS_E_FAILURE; 784 } 785 src_cfg = &rso_cfg->cfg_param; 786 switch (roam_cfg_type) { 787 case RSSI_CHANGE_THRESHOLD: 788 dst_config->int_value = rso_cfg->rescan_rssi_delta; 789 break; 790 case BEACON_RSSI_WEIGHT: 791 dst_config->uint_value = rso_cfg->beacon_rssi_weight; 792 break; 793 case HI_RSSI_DELAY_BTW_SCANS: 794 dst_config->uint_value = rso_cfg->hi_rssi_scan_delay; 795 break; 796 case EMPTY_SCAN_REFRESH_PERIOD: 797 dst_config->uint_value = src_cfg->empty_scan_refresh_period; 798 break; 799 case SCAN_MIN_CHAN_TIME: 800 dst_config->uint_value = src_cfg->min_chan_scan_time; 801 break; 802 case SCAN_MAX_CHAN_TIME: 803 dst_config->uint_value = src_cfg->max_chan_scan_time; 804 break; 805 case NEIGHBOR_SCAN_PERIOD: 806 dst_config->uint_value = src_cfg->neighbor_scan_period; 807 break; 808 case FULL_ROAM_SCAN_PERIOD: 809 dst_config->uint_value = src_cfg->full_roam_scan_period; 810 break; 811 case ROAM_RSSI_DIFF: 812 dst_config->uint_value = src_cfg->roam_rssi_diff; 813 break; 814 case ROAM_RSSI_DIFF_6GHZ: 815 dst_config->uint_value = src_cfg->roam_rssi_diff_6ghz; 816 break; 817 case NEIGHBOUR_LOOKUP_THRESHOLD: 818 dst_config->uint_value = src_cfg->neighbor_lookup_threshold; 819 break; 820 case SCAN_N_PROBE: 821 dst_config->uint_value = src_cfg->roam_scan_n_probes; 822 break; 823 case SCAN_HOME_AWAY: 824 dst_config->uint_value = src_cfg->roam_scan_home_away_time; 825 break; 826 case NEIGHBOUR_SCAN_REFRESH_PERIOD: 827 dst_config->uint_value = 828 src_cfg->neighbor_results_refresh_period; 829 break; 830 case ROAM_CONTROL_ENABLE: 831 dst_config->bool_value = rso_cfg->roam_control_enable; 832 break; 833 case UAPSD_MASK: 834 dst_config->uint_value = rso_cfg->uapsd_mask; 835 break; 836 case MOBILITY_DOMAIN: 837 dst_config->bool_value = rso_cfg->mdid.mdie_present; 838 dst_config->uint_value = rso_cfg->mdid.mobility_domain; 839 break; 840 case IS_11R_CONNECTION: 841 dst_config->bool_value = rso_cfg->is_11r_assoc; 842 break; 843 case ADAPTIVE_11R_CONNECTION: 844 dst_config->bool_value = rso_cfg->is_adaptive_11r_connection; 845 break; 846 case HS_20_AP: 847 dst_config->bool_value = rso_cfg->hs_20_ap; 848 break; 849 case MBO_OCE_ENABLED_AP: 850 dst_config->uint_value = rso_cfg->mbo_oce_enabled_ap; 851 break; 852 case IS_SINGLE_PMK: 853 dst_config->bool_value = rso_cfg->is_single_pmk; 854 break; 855 case LOST_LINK_RSSI: 856 dst_config->int_value = rso_cfg->lost_link_rssi; 857 break; 858 case ROAM_BAND: 859 dst_config->uint_value = rso_cfg->roam_band_bitmask; 860 break; 861 case HI_RSSI_SCAN_RSSI_DELTA: 862 dst_config->uint_value = src_cfg->hi_rssi_scan_rssi_delta; 863 break; 864 case ROAM_CONFIG_ENABLE: 865 dst_config->bool_value = rso_cfg->roam_control_enable; 866 break; 867 default: 868 mlme_err("Invalid roam config requested:%d", roam_cfg_type); 869 status = QDF_STATUS_E_FAILURE; 870 break; 871 } 872 873 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); 874 875 return status; 876 } 877 878 void wlan_cm_set_disable_hi_rssi(struct wlan_objmgr_pdev *pdev, 879 uint8_t vdev_id, bool value) 880 { 881 static struct rso_config *rso_cfg; 882 struct wlan_objmgr_vdev *vdev; 883 884 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, 885 WLAN_MLME_CM_ID); 886 if (!vdev) { 887 mlme_err("vdev object is NULL"); 888 return; 889 } 890 rso_cfg = wlan_cm_get_rso_config(vdev); 891 if (!rso_cfg) { 892 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 893 return; 894 } 895 896 rso_cfg->disable_hi_rssi = value; 897 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 898 } 899 900 void wlan_cm_set_country_code(struct wlan_objmgr_pdev *pdev, 901 uint8_t vdev_id, uint8_t *cc) 902 { 903 static struct rso_config *rso_cfg; 904 struct wlan_objmgr_vdev *vdev; 905 906 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, 907 WLAN_MLME_CM_ID); 908 if (!vdev) { 909 mlme_err("vdev object is NULL"); 910 return; 911 } 912 rso_cfg = wlan_cm_get_rso_config(vdev); 913 if (!rso_cfg || !cc) 914 goto release_vdev_ref; 915 916 mlme_debug("Country info from bcn IE:%c%c 0x%x", cc[0], cc[1], cc[2]); 917 918 qdf_mem_copy(rso_cfg->country_code, cc, REG_ALPHA2_LEN + 1); 919 920 release_vdev_ref: 921 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 922 } 923 924 QDF_STATUS wlan_cm_get_country_code(struct wlan_objmgr_pdev *pdev, 925 uint8_t vdev_id, uint8_t *cc) 926 { 927 static struct rso_config *rso_cfg; 928 struct wlan_objmgr_vdev *vdev; 929 QDF_STATUS status = QDF_STATUS_SUCCESS; 930 931 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, 932 WLAN_MLME_CM_ID); 933 if (!vdev) { 934 mlme_err("vdev object is NULL"); 935 return QDF_STATUS_E_INVAL; 936 } 937 rso_cfg = wlan_cm_get_rso_config(vdev); 938 if (!rso_cfg || !cc) { 939 status = QDF_STATUS_E_INVAL; 940 goto release_vdev_ref; 941 } 942 943 qdf_mem_copy(cc, rso_cfg->country_code, REG_ALPHA2_LEN + 1); 944 945 release_vdev_ref: 946 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 947 return status; 948 } 949 950 #ifdef FEATURE_WLAN_ESE 951 void wlan_cm_set_ese_assoc(struct wlan_objmgr_pdev *pdev, 952 uint8_t vdev_id, bool value) 953 { 954 static struct rso_config *rso_cfg; 955 struct wlan_objmgr_vdev *vdev; 956 957 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, 958 WLAN_MLME_CM_ID); 959 if (!vdev) { 960 mlme_err("vdev object is NULL"); 961 return; 962 } 963 rso_cfg = wlan_cm_get_rso_config(vdev); 964 if (!rso_cfg) { 965 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 966 return; 967 } 968 969 rso_cfg->is_ese_assoc = value; 970 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 971 } 972 973 bool wlan_cm_get_ese_assoc(struct wlan_objmgr_pdev *pdev, 974 uint8_t vdev_id) 975 { 976 static struct rso_config *rso_cfg; 977 struct wlan_objmgr_vdev *vdev; 978 bool ese_assoc; 979 980 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, 981 WLAN_MLME_CM_ID); 982 if (!vdev) { 983 mlme_err("vdev object is NULL"); 984 return false; 985 } 986 rso_cfg = wlan_cm_get_rso_config(vdev); 987 if (!rso_cfg) { 988 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 989 return false; 990 } 991 992 ese_assoc = rso_cfg->is_ese_assoc; 993 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 994 995 return ese_assoc; 996 } 997 #endif 998 999 static QDF_STATUS 1000 cm_roam_update_cfg(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, 1001 uint8_t reason) 1002 { 1003 QDF_STATUS status; 1004 struct wlan_objmgr_vdev *vdev; 1005 1006 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 1007 WLAN_MLME_CM_ID); 1008 if (!vdev) { 1009 mlme_err("vdev object is NULL"); 1010 return QDF_STATUS_E_INVAL; 1011 } 1012 1013 status = cm_roam_acquire_lock(vdev); 1014 if (QDF_IS_STATUS_ERROR(status)) 1015 goto release_ref; 1016 if (!MLME_IS_ROAM_STATE_RSO_ENABLED(psoc, vdev_id)) { 1017 mlme_debug("Update cfg received while ROAM RSO not started"); 1018 cm_roam_release_lock(vdev); 1019 status = QDF_STATUS_E_INVAL; 1020 goto release_ref; 1021 } 1022 1023 status = cm_roam_send_rso_cmd(psoc, vdev_id, 1024 ROAM_SCAN_OFFLOAD_UPDATE_CFG, reason); 1025 cm_roam_release_lock(vdev); 1026 1027 release_ref: 1028 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 1029 1030 return status; 1031 } 1032 1033 void cm_dump_freq_list(struct rso_chan_info *chan_info) 1034 { 1035 uint8_t *channel_list; 1036 uint8_t i = 0, j = 0; 1037 uint32_t buflen = CFG_VALID_CHANNEL_LIST_LEN * 4; 1038 1039 channel_list = qdf_mem_malloc(buflen); 1040 if (!channel_list) 1041 return; 1042 1043 if (chan_info->freq_list) { 1044 for (i = 0; i < chan_info->num_chan; i++) { 1045 if (j < buflen) 1046 j += qdf_scnprintf(channel_list + j, buflen - j, 1047 "%d ", 1048 chan_info->freq_list[i]); 1049 else 1050 break; 1051 } 1052 } 1053 1054 mlme_debug("frequency list [%u]: %s", i, channel_list); 1055 qdf_mem_free(channel_list); 1056 } 1057 1058 static uint8_t 1059 cm_append_pref_chan_list(struct rso_chan_info *chan_info, qdf_freq_t *freq_list, 1060 uint8_t num_chan) 1061 { 1062 uint8_t i = 0, j = 0; 1063 1064 for (i = 0; i < chan_info->num_chan; i++) { 1065 for (j = 0; j < num_chan; j++) 1066 if (chan_info->freq_list[i] == freq_list[j]) 1067 break; 1068 1069 if (j < num_chan) 1070 continue; 1071 if (num_chan == CFG_VALID_CHANNEL_LIST_LEN) 1072 break; 1073 freq_list[num_chan++] = chan_info->freq_list[i]; 1074 } 1075 1076 return num_chan; 1077 } 1078 1079 /** 1080 * cm_modify_chan_list_based_on_band() - Modify RSO channel list based on band 1081 * @freq_list: Channel list coming from user space 1082 * @num_chan: Number of channel present in freq_list buffer 1083 * @band_bitmap: On basis of this band host modify RSO channel list 1084 * 1085 * Return: valid number of channel as per bandmap 1086 */ 1087 static uint8_t 1088 cm_modify_chan_list_based_on_band(qdf_freq_t *freq_list, uint8_t num_chan, 1089 uint32_t band_bitmap) 1090 { 1091 uint8_t i = 0, valid_chan_num = 0; 1092 1093 if (!(band_bitmap & BIT(REG_BAND_2G))) { 1094 mlme_debug("disabling 2G"); 1095 for (i = 0; i < num_chan; i++) { 1096 if (WLAN_REG_IS_24GHZ_CH_FREQ(freq_list[i])) 1097 freq_list[i] = 0; 1098 } 1099 } 1100 1101 if (!(band_bitmap & BIT(REG_BAND_5G))) { 1102 mlme_debug("disabling 5G"); 1103 for (i = 0; i < num_chan; i++) { 1104 if (WLAN_REG_IS_5GHZ_CH_FREQ(freq_list[i])) 1105 freq_list[i] = 0; 1106 } 1107 } 1108 1109 if (!(band_bitmap & BIT(REG_BAND_6G))) { 1110 mlme_debug("disabling 6G"); 1111 for (i = 0; i < num_chan; i++) { 1112 if (WLAN_REG_IS_6GHZ_CHAN_FREQ(freq_list[i])) 1113 freq_list[i] = 0; 1114 } 1115 } 1116 1117 for (i = 0; i < num_chan; i++) { 1118 if (freq_list[i]) 1119 freq_list[valid_chan_num++] = freq_list[i]; 1120 } 1121 1122 return valid_chan_num; 1123 } 1124 1125 static QDF_STATUS cm_create_bg_scan_roam_channel_list(struct rso_chan_info *chan_info, 1126 const qdf_freq_t *chan_freq_lst, 1127 const uint8_t num_chan) 1128 { 1129 QDF_STATUS status = QDF_STATUS_SUCCESS; 1130 uint8_t i; 1131 1132 chan_info->freq_list = qdf_mem_malloc(sizeof(qdf_freq_t) * num_chan); 1133 if (!chan_info->freq_list) 1134 return QDF_STATUS_E_NOMEM; 1135 1136 chan_info->num_chan = num_chan; 1137 for (i = 0; i < num_chan; i++) 1138 chan_info->freq_list[i] = chan_freq_lst[i]; 1139 1140 return status; 1141 } 1142 1143 /** 1144 * cm_remove_disabled_channels() - Remove disabled channels as per current 1145 * connected band 1146 * @vdev: vdev common object 1147 * @freq_list: Channel list coming from user space 1148 * @num_chan: Number of channel present in freq_list buffer 1149 * 1150 * Return: Number of channels as per SETBAND mask 1151 */ 1152 static uint32_t cm_remove_disabled_channels(struct wlan_objmgr_vdev *vdev, 1153 qdf_freq_t *freq_list, 1154 uint8_t num_chan) 1155 { 1156 struct regulatory_channel *cur_chan_list; 1157 struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev); 1158 uint32_t valid_chan_num = 0; 1159 enum channel_state state; 1160 uint32_t freq, i, j; 1161 QDF_STATUS status; 1162 uint32_t filtered_lst[NUM_CHANNELS] = {0}; 1163 1164 cur_chan_list = 1165 qdf_mem_malloc(NUM_CHANNELS * sizeof(struct regulatory_channel)); 1166 if (!cur_chan_list) 1167 return 0; 1168 1169 status = wlan_reg_get_current_chan_list(pdev, cur_chan_list); 1170 if (QDF_IS_STATUS_ERROR(status)) { 1171 qdf_mem_free(cur_chan_list); 1172 return 0; 1173 } 1174 1175 for (i = 0; i < NUM_CHANNELS; i++) { 1176 freq = cur_chan_list[i].center_freq; 1177 state = wlan_reg_get_channel_state_for_pwrmode( 1178 pdev, freq, 1179 REG_CURRENT_PWR_MODE); 1180 if (state != CHANNEL_STATE_DISABLE && 1181 state != CHANNEL_STATE_INVALID) { 1182 for (j = 0; j < num_chan; j++) { 1183 if (freq == freq_list[j]) { 1184 filtered_lst[valid_chan_num++] = 1185 freq_list[j]; 1186 break; 1187 } 1188 } 1189 } 1190 } 1191 1192 mlme_debug("[ROAM_BAND]: num channel :%d", valid_chan_num); 1193 for (i = 0; i < valid_chan_num; i++) 1194 freq_list[i] = filtered_lst[i]; 1195 1196 qdf_mem_free(cur_chan_list); 1197 1198 return valid_chan_num; 1199 } 1200 1201 /** 1202 * cm_update_roam_scan_channel_list() - Update channel list as per RSO chan info 1203 * band bitmask 1204 * @psoc: Psoc common object 1205 * @vdev: vdev common object 1206 * @rso_cfg: connect config to be used to send info in RSO 1207 * @vdev_id: vdev id 1208 * @chan_info: hannel list already sent via RSO 1209 * @freq_list: Channel list coming from user space 1210 * @num_chan: Number of channel present in freq_list buffer 1211 * @update_preferred_chan: Decide whether to update preferred chan list or not 1212 * 1213 * Return: QDF_STATUS 1214 */ 1215 static QDF_STATUS 1216 cm_update_roam_scan_channel_list(struct wlan_objmgr_psoc *psoc, 1217 struct wlan_objmgr_vdev *vdev, 1218 struct rso_config *rso_cfg, uint8_t vdev_id, 1219 struct rso_chan_info *chan_info, 1220 qdf_freq_t *freq_list, uint8_t num_chan, 1221 bool update_preferred_chan) 1222 { 1223 uint16_t pref_chan_cnt = 0; 1224 uint32_t valid_chan_num = 0; 1225 struct cm_roam_values_copy config; 1226 uint32_t current_band; 1227 1228 if (chan_info->num_chan) { 1229 mlme_debug("Current channel num: %d", chan_info->num_chan); 1230 cm_dump_freq_list(chan_info); 1231 } 1232 1233 if (update_preferred_chan) { 1234 pref_chan_cnt = cm_append_pref_chan_list(chan_info, freq_list, 1235 num_chan); 1236 num_chan = pref_chan_cnt; 1237 } 1238 1239 num_chan = cm_remove_disabled_channels(vdev, freq_list, num_chan); 1240 if (!num_chan) 1241 return QDF_STATUS_E_FAILURE; 1242 1243 wlan_cm_roam_cfg_get_value(psoc, vdev_id, ROAM_BAND, &config); 1244 ucfg_reg_get_band(wlan_vdev_get_pdev(vdev), ¤t_band); 1245 /* No need to modify channel list if all channel is allowed */ 1246 if (config.uint_value != current_band) { 1247 valid_chan_num = 1248 cm_modify_chan_list_based_on_band(freq_list, num_chan, 1249 config.uint_value); 1250 if (!valid_chan_num) { 1251 mlme_debug("No valid channels left to send to the fw"); 1252 return QDF_STATUS_E_FAILURE; 1253 } 1254 num_chan = valid_chan_num; 1255 } 1256 1257 cm_flush_roam_channel_list(chan_info); 1258 cm_create_bg_scan_roam_channel_list(chan_info, freq_list, num_chan); 1259 1260 mlme_debug("New channel num: %d", num_chan); 1261 cm_dump_freq_list(chan_info); 1262 1263 return QDF_STATUS_SUCCESS; 1264 } 1265 1266 QDF_STATUS 1267 wlan_cm_roam_cfg_set_value(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, 1268 enum roam_cfg_param roam_cfg_type, 1269 struct cm_roam_values_copy *src_config) 1270 { 1271 struct wlan_objmgr_vdev *vdev; 1272 QDF_STATUS status = QDF_STATUS_SUCCESS; 1273 struct rso_config *rso_cfg; 1274 struct rso_cfg_params *dst_cfg; 1275 struct wlan_mlme_psoc_ext_obj *mlme_obj; 1276 1277 mlme_obj = mlme_get_psoc_ext_obj(psoc); 1278 if (!mlme_obj) 1279 return QDF_STATUS_E_FAILURE; 1280 1281 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 1282 WLAN_MLME_NB_ID); 1283 if (!vdev) { 1284 mlme_err("vdev object is NULL"); 1285 return QDF_STATUS_E_FAILURE; 1286 } 1287 1288 rso_cfg = wlan_cm_get_rso_config(vdev); 1289 if (!rso_cfg) { 1290 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); 1291 return QDF_STATUS_E_FAILURE; 1292 } 1293 dst_cfg = &rso_cfg->cfg_param; 1294 mlme_debug("roam_cfg_type %d, uint val %d int val %d bool val %d num chan %d", 1295 roam_cfg_type, src_config->uint_value, src_config->int_value, 1296 src_config->bool_value, src_config->chan_info.num_chan); 1297 switch (roam_cfg_type) { 1298 case RSSI_CHANGE_THRESHOLD: 1299 rso_cfg->rescan_rssi_delta = src_config->uint_value; 1300 break; 1301 case BEACON_RSSI_WEIGHT: 1302 rso_cfg->beacon_rssi_weight = src_config->uint_value; 1303 break; 1304 case HI_RSSI_DELAY_BTW_SCANS: 1305 rso_cfg->hi_rssi_scan_delay = src_config->uint_value; 1306 break; 1307 case EMPTY_SCAN_REFRESH_PERIOD: 1308 dst_cfg->empty_scan_refresh_period = src_config->uint_value; 1309 if (mlme_obj->cfg.lfr.roam_scan_offload_enabled) 1310 cm_roam_update_cfg(psoc, vdev_id, 1311 REASON_EMPTY_SCAN_REF_PERIOD_CHANGED); 1312 break; 1313 case FULL_ROAM_SCAN_PERIOD: 1314 dst_cfg->full_roam_scan_period = src_config->uint_value; 1315 if (mlme_obj->cfg.lfr.roam_scan_offload_enabled) 1316 cm_roam_update_cfg(psoc, vdev_id, 1317 REASON_ROAM_FULL_SCAN_PERIOD_CHANGED); 1318 break; 1319 case ENABLE_SCORING_FOR_ROAM: 1320 dst_cfg->enable_scoring_for_roam = src_config->bool_value; 1321 if (mlme_obj->cfg.lfr.roam_scan_offload_enabled) 1322 cm_roam_update_cfg(psoc, vdev_id, 1323 REASON_SCORING_CRITERIA_CHANGED); 1324 break; 1325 case SCAN_MIN_CHAN_TIME: 1326 mlme_obj->cfg.lfr.neighbor_scan_min_chan_time = 1327 src_config->uint_value; 1328 dst_cfg->min_chan_scan_time = src_config->uint_value; 1329 break; 1330 case SCAN_MAX_CHAN_TIME: 1331 dst_cfg->max_chan_scan_time = src_config->uint_value; 1332 if (mlme_obj->cfg.lfr.roam_scan_offload_enabled) 1333 cm_roam_update_cfg(psoc, vdev_id, 1334 REASON_SCAN_CH_TIME_CHANGED); 1335 break; 1336 case NEIGHBOR_SCAN_PERIOD: 1337 dst_cfg->neighbor_scan_period = src_config->uint_value; 1338 if (mlme_obj->cfg.lfr.roam_scan_offload_enabled) 1339 cm_roam_update_cfg(psoc, vdev_id, 1340 REASON_SCAN_HOME_TIME_CHANGED); 1341 break; 1342 case ROAM_CONFIG_ENABLE: 1343 rso_cfg->roam_control_enable = src_config->bool_value; 1344 if (!rso_cfg->roam_control_enable) 1345 break; 1346 dst_cfg->roam_inactive_data_packet_count = 0; 1347 dst_cfg->roam_scan_inactivity_time = 0; 1348 if (mlme_obj->cfg.lfr.roam_scan_offload_enabled) 1349 cm_roam_update_cfg(psoc, vdev_id, 1350 REASON_ROAM_CONTROL_CONFIG_ENABLED); 1351 break; 1352 case ROAM_PREFERRED_CHAN: 1353 /* 1354 * In RSO update command, the specific channel list is 1355 * given priority. So flush the Specific channel list if 1356 * preferred channel list is received. Else the channel list 1357 * type will be filled as static instead of dynamic. 1358 */ 1359 cm_flush_roam_channel_list(&dst_cfg->specific_chan_info); 1360 status = cm_update_roam_scan_channel_list(psoc, vdev, rso_cfg, 1361 vdev_id, &dst_cfg->pref_chan_info, 1362 src_config->chan_info.freq_list, 1363 src_config->chan_info.num_chan, true); 1364 if (QDF_IS_STATUS_ERROR(status)) 1365 break; 1366 if (mlme_obj->cfg.lfr.roam_scan_offload_enabled) 1367 cm_roam_update_cfg(psoc, vdev_id, 1368 REASON_CHANNEL_LIST_CHANGED); 1369 break; 1370 case ROAM_SPECIFIC_CHAN: 1371 status = cm_update_roam_scan_channel_list(psoc, vdev, rso_cfg, 1372 vdev_id, &dst_cfg->specific_chan_info, 1373 src_config->chan_info.freq_list, 1374 src_config->chan_info.num_chan, 1375 false); 1376 if (QDF_IS_STATUS_ERROR(status)) 1377 break; 1378 if (mlme_obj->cfg.lfr.roam_scan_offload_enabled) 1379 cm_roam_update_cfg(psoc, vdev_id, 1380 REASON_CHANNEL_LIST_CHANGED); 1381 break; 1382 case ROAM_RSSI_DIFF: 1383 dst_cfg->roam_rssi_diff = src_config->uint_value; 1384 if (mlme_obj->cfg.lfr.roam_scan_offload_enabled) 1385 cm_roam_update_cfg(psoc, vdev_id, 1386 REASON_RSSI_DIFF_CHANGED); 1387 break; 1388 case ROAM_RSSI_DIFF_6GHZ: 1389 dst_cfg->roam_rssi_diff_6ghz = src_config->uint_value; 1390 break; 1391 case NEIGHBOUR_LOOKUP_THRESHOLD: 1392 dst_cfg->neighbor_lookup_threshold = src_config->uint_value; 1393 break; 1394 case SCAN_N_PROBE: 1395 dst_cfg->roam_scan_n_probes = src_config->uint_value; 1396 if (mlme_obj->cfg.lfr.roam_scan_offload_enabled) 1397 cm_roam_update_cfg(psoc, vdev_id, 1398 REASON_NPROBES_CHANGED); 1399 break; 1400 case SCAN_HOME_AWAY: 1401 dst_cfg->roam_scan_home_away_time = src_config->uint_value; 1402 if (mlme_obj->cfg.lfr.roam_scan_offload_enabled && 1403 src_config->bool_value) 1404 cm_roam_update_cfg(psoc, vdev_id, 1405 REASON_HOME_AWAY_TIME_CHANGED); 1406 break; 1407 case NEIGHBOUR_SCAN_REFRESH_PERIOD: 1408 dst_cfg->neighbor_results_refresh_period = 1409 src_config->uint_value; 1410 mlme_obj->cfg.lfr.neighbor_scan_results_refresh_period = 1411 src_config->uint_value; 1412 if (mlme_obj->cfg.lfr.roam_scan_offload_enabled) 1413 cm_roam_update_cfg(psoc, vdev_id, 1414 REASON_NEIGHBOR_SCAN_REFRESH_PERIOD_CHANGED); 1415 break; 1416 case UAPSD_MASK: 1417 rso_cfg->uapsd_mask = src_config->uint_value; 1418 break; 1419 case MOBILITY_DOMAIN: 1420 rso_cfg->mdid.mdie_present = src_config->bool_value; 1421 rso_cfg->mdid.mobility_domain = src_config->uint_value; 1422 break; 1423 case IS_11R_CONNECTION: 1424 rso_cfg->is_11r_assoc = src_config->bool_value; 1425 break; 1426 case ADAPTIVE_11R_CONNECTION: 1427 rso_cfg->is_adaptive_11r_connection = src_config->bool_value; 1428 break; 1429 case HS_20_AP: 1430 rso_cfg->hs_20_ap = src_config->bool_value; 1431 break; 1432 case MBO_OCE_ENABLED_AP: 1433 rso_cfg->mbo_oce_enabled_ap = src_config->uint_value; 1434 break; 1435 case IS_SINGLE_PMK: 1436 rso_cfg->is_single_pmk = src_config->bool_value; 1437 break; 1438 case LOST_LINK_RSSI: 1439 rso_cfg->lost_link_rssi = src_config->int_value; 1440 break; 1441 case ROAM_BAND: 1442 rso_cfg->roam_band_bitmask = src_config->uint_value; 1443 mlme_debug("[ROAM BAND] Set roam band:%d", 1444 rso_cfg->roam_band_bitmask); 1445 break; 1446 default: 1447 mlme_err("Invalid roam config requested:%d", roam_cfg_type); 1448 status = QDF_STATUS_E_FAILURE; 1449 break; 1450 } 1451 1452 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); 1453 1454 return status; 1455 } 1456 1457 void wlan_roam_reset_roam_params(struct wlan_objmgr_vdev *vdev) 1458 { 1459 struct rso_user_config *rso_usr_cfg; 1460 1461 rso_usr_cfg = wlan_cm_get_rso_user_config(vdev); 1462 if (!rso_usr_cfg) 1463 return; 1464 1465 /* 1466 * clear all the allowlist parameters and remaining 1467 * needs to be retained across connections. 1468 */ 1469 rso_usr_cfg->num_ssid_allowed_list = 0; 1470 qdf_mem_zero(&rso_usr_cfg->ssid_allowed_list, 1471 sizeof(struct wlan_ssid) * MAX_SSID_ALLOWED_LIST); 1472 } 1473 1474 static void cm_rso_chan_to_freq_list(struct wlan_objmgr_pdev *pdev, 1475 qdf_freq_t *freq_list, 1476 const uint8_t *chan_list, 1477 uint32_t chan_list_len) 1478 { 1479 uint32_t count; 1480 1481 for (count = 0; count < chan_list_len; count++) 1482 freq_list[count] = 1483 wlan_reg_legacy_chan_to_freq(pdev, chan_list[count]); 1484 } 1485 1486 #ifdef WLAN_FEATURE_HOST_ROAM 1487 static QDF_STATUS cm_init_reassoc_timer(struct rso_config *rso_cfg) 1488 { 1489 QDF_STATUS status; 1490 1491 status = qdf_mc_timer_init(&rso_cfg->reassoc_timer, QDF_TIMER_TYPE_SW, 1492 cm_reassoc_timer_callback, &rso_cfg->ctx); 1493 1494 if (QDF_IS_STATUS_ERROR(status)) 1495 mlme_err("Preauth Reassoc interval Timer allocation failed"); 1496 1497 return status; 1498 } 1499 1500 static void cm_deinit_reassoc_timer(struct rso_config *rso_cfg) 1501 { 1502 /* check if the timer is running */ 1503 if (QDF_TIMER_STATE_RUNNING == 1504 qdf_mc_timer_get_current_state(&rso_cfg->reassoc_timer)) 1505 qdf_mc_timer_stop(&rso_cfg->reassoc_timer); 1506 1507 qdf_mc_timer_destroy(&rso_cfg->reassoc_timer); 1508 } 1509 #else 1510 static inline QDF_STATUS cm_init_reassoc_timer(struct rso_config *rso_cfg) 1511 { 1512 return QDF_STATUS_SUCCESS; 1513 } 1514 static inline void cm_deinit_reassoc_timer(struct rso_config *rso_cfg) {} 1515 #endif 1516 1517 QDF_STATUS wlan_cm_rso_config_init(struct wlan_objmgr_vdev *vdev, 1518 struct rso_config *rso_cfg) 1519 { 1520 QDF_STATUS status = QDF_STATUS_SUCCESS; 1521 struct rso_chan_info *chan_info; 1522 struct rso_cfg_params *cfg_params; 1523 struct wlan_mlme_psoc_ext_obj *mlme_obj; 1524 struct wlan_objmgr_pdev *pdev; 1525 struct wlan_objmgr_psoc *psoc; 1526 uint32_t current_band = REG_BAND_MASK_ALL; 1527 1528 pdev = wlan_vdev_get_pdev(vdev); 1529 if (!pdev) 1530 return QDF_STATUS_E_INVAL; 1531 1532 psoc = wlan_pdev_get_psoc(pdev); 1533 if (!psoc) 1534 return QDF_STATUS_E_INVAL; 1535 1536 mlme_obj = mlme_get_psoc_ext_obj(psoc); 1537 if (!mlme_obj) 1538 return QDF_STATUS_E_INVAL; 1539 1540 status = cm_init_reassoc_timer(rso_cfg); 1541 if (QDF_IS_STATUS_ERROR(status)) 1542 return status; 1543 1544 qdf_mutex_create(&rso_cfg->cm_rso_lock); 1545 cfg_params = &rso_cfg->cfg_param; 1546 cfg_params->max_chan_scan_time = 1547 mlme_obj->cfg.lfr.neighbor_scan_max_chan_time; 1548 cfg_params->passive_max_chan_time = 1549 mlme_obj->cfg.lfr.passive_max_channel_time; 1550 cfg_params->min_chan_scan_time = 1551 mlme_obj->cfg.lfr.neighbor_scan_min_chan_time; 1552 cfg_params->neighbor_lookup_threshold = 1553 mlme_obj->cfg.lfr.neighbor_lookup_rssi_threshold; 1554 cfg_params->rssi_thresh_offset_5g = 1555 mlme_obj->cfg.lfr.rssi_threshold_offset_5g; 1556 cfg_params->opportunistic_threshold_diff = 1557 mlme_obj->cfg.lfr.opportunistic_scan_threshold_diff; 1558 cfg_params->roam_rescan_rssi_diff = 1559 mlme_obj->cfg.lfr.roam_rescan_rssi_diff; 1560 1561 cfg_params->roam_bmiss_first_bcn_cnt = 1562 mlme_obj->cfg.lfr.roam_bmiss_first_bcnt; 1563 cfg_params->roam_bmiss_final_cnt = 1564 mlme_obj->cfg.lfr.roam_bmiss_final_bcnt; 1565 1566 cfg_params->neighbor_scan_period = 1567 mlme_obj->cfg.lfr.neighbor_scan_timer_period; 1568 cfg_params->neighbor_scan_min_period = 1569 mlme_obj->cfg.lfr.neighbor_scan_min_timer_period; 1570 cfg_params->neighbor_results_refresh_period = 1571 mlme_obj->cfg.lfr.neighbor_scan_results_refresh_period; 1572 cfg_params->empty_scan_refresh_period = 1573 mlme_obj->cfg.lfr.empty_scan_refresh_period; 1574 cfg_params->full_roam_scan_period = 1575 mlme_obj->cfg.lfr.roam_full_scan_period; 1576 cfg_params->enable_scoring_for_roam = 1577 mlme_obj->cfg.roam_scoring.enable_scoring_for_roam; 1578 cfg_params->roam_scan_n_probes = 1579 mlme_obj->cfg.lfr.roam_scan_n_probes; 1580 cfg_params->roam_scan_home_away_time = 1581 mlme_obj->cfg.lfr.roam_scan_home_away_time; 1582 cfg_params->roam_scan_inactivity_time = 1583 mlme_obj->cfg.lfr.roam_scan_inactivity_time; 1584 cfg_params->roam_inactive_data_packet_count = 1585 mlme_obj->cfg.lfr.roam_inactive_data_packet_count; 1586 1587 chan_info = &cfg_params->specific_chan_info; 1588 chan_info->num_chan = 1589 mlme_obj->cfg.lfr.neighbor_scan_channel_list_num; 1590 mlme_debug("number of channels: %u", chan_info->num_chan); 1591 if (chan_info->num_chan) { 1592 chan_info->freq_list = 1593 qdf_mem_malloc(sizeof(qdf_freq_t) * 1594 chan_info->num_chan); 1595 if (!chan_info->freq_list) { 1596 chan_info->num_chan = 0; 1597 return QDF_STATUS_E_NOMEM; 1598 } 1599 /* Update the roam global structure from CFG */ 1600 cm_rso_chan_to_freq_list(pdev, chan_info->freq_list, 1601 mlme_obj->cfg.lfr.neighbor_scan_channel_list, 1602 mlme_obj->cfg.lfr.neighbor_scan_channel_list_num); 1603 } else { 1604 chan_info->freq_list = NULL; 1605 } 1606 1607 cfg_params->hi_rssi_scan_max_count = 1608 mlme_obj->cfg.lfr.roam_scan_hi_rssi_maxcount; 1609 cfg_params->hi_rssi_scan_rssi_delta = 1610 mlme_obj->cfg.lfr.roam_scan_hi_rssi_delta; 1611 1612 cfg_params->hi_rssi_scan_delay = 1613 mlme_obj->cfg.lfr.roam_scan_hi_rssi_delay; 1614 1615 cfg_params->hi_rssi_scan_rssi_ub = 1616 mlme_obj->cfg.lfr.roam_scan_hi_rssi_ub; 1617 cfg_params->roam_rssi_diff = 1618 mlme_obj->cfg.lfr.roam_rssi_diff; 1619 cfg_params->roam_rssi_diff_6ghz = 1620 mlme_obj->cfg.lfr.roam_rssi_diff_6ghz; 1621 cfg_params->bg_rssi_threshold = 1622 mlme_obj->cfg.lfr.bg_rssi_threshold; 1623 1624 ucfg_reg_get_band(wlan_vdev_get_pdev(vdev), ¤t_band); 1625 rso_cfg->roam_band_bitmask = current_band; 1626 1627 return status; 1628 } 1629 1630 void wlan_cm_rso_config_deinit(struct wlan_objmgr_vdev *vdev, 1631 struct rso_config *rso_cfg) 1632 { 1633 struct rso_cfg_params *cfg_params; 1634 1635 cfg_params = &rso_cfg->cfg_param; 1636 if (rso_cfg->assoc_ie.ptr) { 1637 qdf_mem_free(rso_cfg->assoc_ie.ptr); 1638 rso_cfg->assoc_ie.ptr = NULL; 1639 rso_cfg->assoc_ie.len = 0; 1640 } 1641 if (rso_cfg->prev_ap_bcn_ie.ptr) { 1642 qdf_mem_free(rso_cfg->prev_ap_bcn_ie.ptr); 1643 rso_cfg->prev_ap_bcn_ie.ptr = NULL; 1644 rso_cfg->prev_ap_bcn_ie.len = 0; 1645 } 1646 if (rso_cfg->roam_scan_freq_lst.freq_list) 1647 qdf_mem_free(rso_cfg->roam_scan_freq_lst.freq_list); 1648 rso_cfg->roam_scan_freq_lst.freq_list = NULL; 1649 rso_cfg->roam_scan_freq_lst.num_chan = 0; 1650 1651 cm_flush_roam_channel_list(&cfg_params->specific_chan_info); 1652 cm_flush_roam_channel_list(&cfg_params->pref_chan_info); 1653 1654 qdf_mutex_destroy(&rso_cfg->cm_rso_lock); 1655 1656 cm_deinit_reassoc_timer(rso_cfg); 1657 } 1658 1659 struct rso_config *wlan_cm_get_rso_config_fl(struct wlan_objmgr_vdev *vdev, 1660 const char *func, uint32_t line) 1661 1662 { 1663 struct cm_ext_obj *cm_ext_obj; 1664 enum QDF_OPMODE op_mode = wlan_vdev_mlme_get_opmode(vdev); 1665 1666 /* get only for CLI and STA */ 1667 if (op_mode != QDF_STA_MODE && op_mode != QDF_P2P_CLIENT_MODE) 1668 return NULL; 1669 1670 cm_ext_obj = cm_get_ext_hdl_fl(vdev, func, line); 1671 if (!cm_ext_obj) 1672 return NULL; 1673 1674 return &cm_ext_obj->rso_cfg; 1675 } 1676 1677 struct rso_user_config * 1678 wlan_cm_get_rso_user_config_fl(struct wlan_objmgr_vdev *vdev, 1679 const char *func, uint32_t line) 1680 { 1681 struct cm_ext_obj *cm_ext_obj; 1682 enum QDF_OPMODE op_mode = wlan_vdev_mlme_get_opmode(vdev); 1683 1684 /* get only for CLI and STA */ 1685 if (op_mode != QDF_STA_MODE && op_mode != QDF_P2P_CLIENT_MODE) 1686 return NULL; 1687 1688 cm_ext_obj = cm_get_ext_hdl_fl(vdev, func, line); 1689 if (!cm_ext_obj) 1690 return NULL; 1691 1692 return &cm_ext_obj->rso_usr_cfg; 1693 } 1694 1695 QDF_STATUS cm_roam_acquire_lock(struct wlan_objmgr_vdev *vdev) 1696 { 1697 static struct rso_config *rso_cfg; 1698 1699 rso_cfg = wlan_cm_get_rso_config(vdev); 1700 if (!rso_cfg) 1701 return QDF_STATUS_E_INVAL; 1702 1703 return qdf_mutex_acquire(&rso_cfg->cm_rso_lock); 1704 } 1705 1706 QDF_STATUS cm_roam_release_lock(struct wlan_objmgr_vdev *vdev) 1707 { 1708 static struct rso_config *rso_cfg; 1709 1710 rso_cfg = wlan_cm_get_rso_config(vdev); 1711 if (!rso_cfg) 1712 return QDF_STATUS_E_INVAL; 1713 1714 return qdf_mutex_release(&rso_cfg->cm_rso_lock); 1715 } 1716 1717 QDF_STATUS 1718 wlan_cm_roam_invoke(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, 1719 struct qdf_mac_addr *bssid, qdf_freq_t chan_freq, 1720 enum wlan_cm_source source) 1721 { 1722 QDF_STATUS status; 1723 struct wlan_objmgr_psoc *psoc; 1724 struct wlan_objmgr_vdev *vdev; 1725 1726 psoc = wlan_pdev_get_psoc(pdev); 1727 if (!psoc) { 1728 mlme_err("Invalid psoc"); 1729 return QDF_STATUS_E_FAILURE; 1730 } 1731 1732 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 1733 WLAN_MLME_NB_ID); 1734 if (!vdev) { 1735 mlme_err("vdev object is NULL"); 1736 return QDF_STATUS_E_NULL_VALUE; 1737 } 1738 1739 mlme_debug("vdev: %d source: %d freq: %d bssid: " QDF_MAC_ADDR_FMT, 1740 vdev_id, source, chan_freq, QDF_MAC_ADDR_REF(bssid->bytes)); 1741 1742 status = cm_start_roam_invoke(psoc, vdev, bssid, chan_freq, source); 1743 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); 1744 1745 return status; 1746 } 1747 1748 bool cm_is_fast_roam_enabled(struct wlan_objmgr_psoc *psoc) 1749 { 1750 struct wlan_mlme_psoc_ext_obj *mlme_obj; 1751 1752 mlme_obj = mlme_get_psoc_ext_obj(psoc); 1753 if (!mlme_obj) 1754 return false; 1755 1756 if (!mlme_obj->cfg.lfr.lfr_enabled) 1757 return false; 1758 1759 if (mlme_obj->cfg.lfr.enable_fast_roam_in_concurrency) 1760 return true; 1761 /* return true if no concurrency */ 1762 if (policy_mgr_get_connection_count(psoc) < 2) 1763 return true; 1764 1765 return false; 1766 } 1767 1768 bool cm_is_rsn_or_8021x_sha256_auth_type(struct wlan_objmgr_vdev *vdev) 1769 { 1770 int32_t akm; 1771 1772 akm = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT); 1773 if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256) || 1774 QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X)) 1775 return true; 1776 1777 return false; 1778 } 1779 1780 #ifdef WLAN_FEATURE_HOST_ROAM 1781 QDF_STATUS wlan_cm_host_roam_start(struct scheduler_msg *msg) 1782 { 1783 QDF_STATUS status; 1784 struct cm_host_roam_start_ind *req; 1785 struct qdf_mac_addr bssid = QDF_MAC_ADDR_ZERO_INIT; 1786 1787 if (!msg || !msg->bodyptr) 1788 return QDF_STATUS_E_FAILURE; 1789 1790 req = msg->bodyptr; 1791 status = wlan_cm_roam_invoke(req->pdev, req->vdev_id, &bssid, 0, 1792 CM_ROAMING_FW); 1793 qdf_mem_free(req); 1794 1795 return status; 1796 } 1797 1798 QDF_STATUS cm_mlme_roam_preauth_fail(struct wlan_objmgr_vdev *vdev, 1799 struct wlan_cm_roam_req *req, 1800 enum wlan_cm_connect_fail_reason reason) 1801 { 1802 uint8_t vdev_id, roam_reason; 1803 struct wlan_objmgr_pdev *pdev; 1804 1805 if (!vdev || !req) { 1806 mlme_err("vdev or req is NULL"); 1807 return QDF_STATUS_E_INVAL; 1808 } 1809 1810 if (reason == CM_NO_CANDIDATE_FOUND) 1811 roam_reason = REASON_NO_CAND_FOUND_OR_NOT_ROAMING_NOW; 1812 else 1813 roam_reason = REASON_PREAUTH_FAILED_FOR_ALL; 1814 1815 pdev = wlan_vdev_get_pdev(vdev); 1816 vdev_id = wlan_vdev_get_id(vdev); 1817 1818 if (req->source == CM_ROAMING_FW) 1819 cm_roam_state_change(pdev, vdev_id, 1820 ROAM_SCAN_OFFLOAD_RESTART, 1821 roam_reason, NULL, false); 1822 else 1823 cm_roam_state_change(pdev, vdev_id, 1824 ROAM_SCAN_OFFLOAD_START, 1825 roam_reason, NULL, false); 1826 return QDF_STATUS_SUCCESS; 1827 } 1828 #endif 1829 1830 void wlan_cm_fill_crypto_filter_from_vdev(struct wlan_objmgr_vdev *vdev, 1831 struct scan_filter *filter) 1832 { 1833 struct rso_config *rso_cfg; 1834 1835 filter->authmodeset = 1836 wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_AUTH_MODE); 1837 filter->mcastcipherset = 1838 wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_MCAST_CIPHER); 1839 filter->ucastcipherset = 1840 wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_UCAST_CIPHER); 1841 filter->key_mgmt = 1842 wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT); 1843 filter->mgmtcipherset = 1844 wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_MGMT_CIPHER); 1845 1846 rso_cfg = wlan_cm_get_rso_config(vdev); 1847 if (!rso_cfg) 1848 return; 1849 1850 if (rso_cfg->orig_sec_info.rsn_caps & 1851 WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED) 1852 filter->pmf_cap = WLAN_PMF_REQUIRED; 1853 else if (rso_cfg->orig_sec_info.rsn_caps & 1854 WLAN_CRYPTO_RSN_CAP_MFP_ENABLED) 1855 filter->pmf_cap = WLAN_PMF_CAPABLE; 1856 } 1857 1858 static void cm_dump_occupied_chan_list(struct wlan_chan_list *occupied_ch) 1859 { 1860 uint8_t idx; 1861 uint32_t buff_len; 1862 char *chan_buff; 1863 uint32_t len = 0; 1864 1865 buff_len = (occupied_ch->num_chan * 5) + 1; 1866 chan_buff = qdf_mem_malloc(buff_len); 1867 if (!chan_buff) 1868 return; 1869 1870 for (idx = 0; idx < occupied_ch->num_chan; idx++) 1871 len += qdf_scnprintf(chan_buff + len, buff_len - len, " %d", 1872 occupied_ch->freq_list[idx]); 1873 1874 mlme_nofl_debug("Occupied chan list[%d]:%s", 1875 occupied_ch->num_chan, chan_buff); 1876 1877 qdf_mem_free(chan_buff); 1878 } 1879 1880 /** 1881 * cm_should_add_to_occupied_channels() - validates bands of active_ch_freq and 1882 * curr node freq before addition of curr node freq to occupied channels 1883 * 1884 * @active_ch_freq: active channel frequency 1885 * @cur_node_chan_freq: curr channel frequency 1886 * @dual_sta_roam_active: dual sta roam active 1887 * 1888 * Return: True if active_ch_freq and cur_node_chan_freq belongs to same 1889 * bands else false 1890 **/ 1891 static bool cm_should_add_to_occupied_channels(qdf_freq_t active_ch_freq, 1892 qdf_freq_t cur_node_chan_freq, 1893 bool dual_sta_roam_active) 1894 { 1895 /* all channels can be added if dual STA roam is not active */ 1896 if (!dual_sta_roam_active) 1897 return true; 1898 1899 /* when dual STA roam is active, channels must be in the same band */ 1900 if (WLAN_REG_IS_24GHZ_CH_FREQ(active_ch_freq) && 1901 WLAN_REG_IS_24GHZ_CH_FREQ(cur_node_chan_freq)) 1902 return true; 1903 1904 if (!WLAN_REG_IS_24GHZ_CH_FREQ(active_ch_freq) && 1905 !WLAN_REG_IS_24GHZ_CH_FREQ(cur_node_chan_freq)) 1906 return true; 1907 1908 /* not in same band */ 1909 return false; 1910 } 1911 1912 static QDF_STATUS cm_add_to_freq_list_front(qdf_freq_t *ch_freq_lst, 1913 int num_chan, qdf_freq_t chan_freq) 1914 { 1915 int i = 0; 1916 1917 /* Check for NULL pointer */ 1918 if (!ch_freq_lst) 1919 return QDF_STATUS_E_NULL_VALUE; 1920 1921 /* Make room for the addition. (Start moving from the back.) */ 1922 for (i = num_chan; i > 0; i--) 1923 ch_freq_lst[i] = ch_freq_lst[i - 1]; 1924 1925 /* Now add the NEW channel...at the front */ 1926 ch_freq_lst[0] = chan_freq; 1927 1928 return QDF_STATUS_SUCCESS; 1929 } 1930 1931 /* Add the channel to the occupied channels array */ 1932 static void cm_add_to_occupied_channels(qdf_freq_t ch_freq, 1933 struct rso_config *rso_cfg, 1934 bool is_init_list) 1935 { 1936 QDF_STATUS status; 1937 uint8_t num_occupied_ch = rso_cfg->occupied_chan_lst.num_chan; 1938 qdf_freq_t *occupied_ch_lst = rso_cfg->occupied_chan_lst.freq_list; 1939 1940 if (is_init_list) 1941 rso_cfg->roam_candidate_count++; 1942 1943 if (wlan_is_channel_present_in_list(occupied_ch_lst, 1944 num_occupied_ch, ch_freq)) 1945 return; 1946 1947 if (num_occupied_ch >= CFG_VALID_CHANNEL_LIST_LEN) 1948 num_occupied_ch = CFG_VALID_CHANNEL_LIST_LEN - 1; 1949 1950 status = cm_add_to_freq_list_front(occupied_ch_lst, 1951 num_occupied_ch, ch_freq); 1952 if (QDF_IS_STATUS_SUCCESS(status)) { 1953 rso_cfg->occupied_chan_lst.num_chan++; 1954 if (rso_cfg->occupied_chan_lst.num_chan > 1955 BG_SCAN_OCCUPIED_CHANNEL_LIST_LEN) 1956 rso_cfg->occupied_chan_lst.num_chan = 1957 BG_SCAN_OCCUPIED_CHANNEL_LIST_LEN; 1958 } 1959 } 1960 1961 void wlan_cm_init_occupied_ch_freq_list(struct wlan_objmgr_pdev *pdev, 1962 struct wlan_objmgr_psoc *psoc, 1963 uint8_t vdev_id) 1964 { 1965 qdf_list_t *list = NULL; 1966 qdf_list_node_t *cur_lst = NULL; 1967 qdf_list_node_t *next_lst = NULL; 1968 struct scan_cache_node *cur_node = NULL; 1969 struct scan_filter *filter; 1970 bool dual_sta_roam_active; 1971 struct wlan_objmgr_vdev *vdev; 1972 QDF_STATUS status; 1973 struct rso_config *rso_cfg; 1974 struct rso_cfg_params *cfg_params; 1975 struct wlan_ssid ssid; 1976 qdf_freq_t op_freq, freq; 1977 1978 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, 1979 WLAN_MLME_CM_ID); 1980 if (!vdev) { 1981 mlme_err("vdev object is NULL for vdev %d", vdev_id); 1982 return; 1983 } 1984 rso_cfg = wlan_cm_get_rso_config(vdev); 1985 if (!rso_cfg) 1986 goto rel_vdev_ref; 1987 op_freq = wlan_get_operation_chan_freq(vdev); 1988 if (!op_freq) { 1989 mlme_debug("failed to get op freq"); 1990 goto rel_vdev_ref; 1991 } 1992 status = wlan_vdev_mlme_get_ssid(vdev, ssid.ssid, &ssid.length); 1993 if (QDF_IS_STATUS_ERROR(status)) { 1994 mlme_err("failed to find SSID for vdev %d", vdev_id); 1995 goto rel_vdev_ref; 1996 } 1997 1998 cfg_params = &rso_cfg->cfg_param; 1999 2000 if (cfg_params->specific_chan_info.num_chan) { 2001 /* 2002 * Ini file contains neighbor scan channel list, hence NO need 2003 * to build occupied channel list" 2004 */ 2005 mlme_debug("Ini contains neighbor scan ch list"); 2006 goto rel_vdev_ref; 2007 } 2008 2009 filter = qdf_mem_malloc(sizeof(*filter)); 2010 if (!filter) 2011 goto rel_vdev_ref; 2012 2013 wlan_cm_fill_crypto_filter_from_vdev(vdev, filter); 2014 filter->num_of_ssid = 1; 2015 qdf_mem_copy(&filter->ssid_list[0], &ssid, sizeof(ssid)); 2016 2017 /* Empty occupied channels here */ 2018 rso_cfg->occupied_chan_lst.num_chan = 0; 2019 rso_cfg->roam_candidate_count = 0; 2020 2021 cm_add_to_occupied_channels(op_freq, rso_cfg, true); 2022 list = wlan_scan_get_result(pdev, filter); 2023 qdf_mem_free(filter); 2024 if (!list || (list && !qdf_list_size(list))) 2025 goto err; 2026 2027 dual_sta_roam_active = 2028 wlan_mlme_get_dual_sta_roaming_enabled(psoc); 2029 dual_sta_roam_active = dual_sta_roam_active && 2030 policy_mgr_mode_specific_connection_count 2031 (psoc, PM_STA_MODE, NULL) >= 2; 2032 2033 qdf_list_peek_front(list, &cur_lst); 2034 while (cur_lst) { 2035 cur_node = qdf_container_of(cur_lst, struct scan_cache_node, 2036 node); 2037 freq = cur_node->entry->channel.chan_freq; 2038 if (cm_should_add_to_occupied_channels(op_freq, freq, 2039 dual_sta_roam_active)) 2040 cm_add_to_occupied_channels(freq, rso_cfg, true); 2041 2042 qdf_list_peek_next(list, cur_lst, &next_lst); 2043 cur_lst = next_lst; 2044 next_lst = NULL; 2045 } 2046 err: 2047 cm_dump_occupied_chan_list(&rso_cfg->occupied_chan_lst); 2048 if (list) 2049 wlan_scan_purge_results(list); 2050 rel_vdev_ref: 2051 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 2052 } 2053 2054 #ifdef WLAN_FEATURE_FILS_SK 2055 QDF_STATUS 2056 wlan_cm_update_mlme_fils_info(struct wlan_objmgr_vdev *vdev, 2057 struct wlan_fils_con_info *src_fils_info) 2058 { 2059 struct mlme_legacy_priv *mlme_priv; 2060 uint8_t vdev_id = wlan_vdev_get_id(vdev); 2061 struct wlan_fils_connection_info *tgt_info; 2062 2063 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 2064 if (!mlme_priv) { 2065 mlme_err("vdev legacy private object is NULL for vdev %d", 2066 vdev_id); 2067 return QDF_STATUS_E_FAILURE; 2068 } 2069 2070 if (!src_fils_info) { 2071 mlme_debug("FILS: vdev:%d Clear fils info", vdev_id); 2072 qdf_mem_free(mlme_priv->connect_info.fils_con_info); 2073 mlme_priv->connect_info.fils_con_info = NULL; 2074 return QDF_STATUS_SUCCESS; 2075 } 2076 2077 if (mlme_priv->connect_info.fils_con_info) 2078 qdf_mem_free(mlme_priv->connect_info.fils_con_info); 2079 2080 mlme_priv->connect_info.fils_con_info = 2081 qdf_mem_malloc(sizeof(struct wlan_fils_connection_info)); 2082 if (!mlme_priv->connect_info.fils_con_info) 2083 return QDF_STATUS_E_NOMEM; 2084 2085 tgt_info = mlme_priv->connect_info.fils_con_info; 2086 mlme_debug("FILS: vdev:%d update fils info", vdev_id); 2087 tgt_info->is_fils_connection = src_fils_info->is_fils_connection; 2088 tgt_info->key_nai_length = src_fils_info->username_len; 2089 qdf_mem_copy(tgt_info->keyname_nai, src_fils_info->username, 2090 tgt_info->key_nai_length); 2091 2092 tgt_info->realm_len = src_fils_info->realm_len; 2093 qdf_mem_copy(tgt_info->realm, src_fils_info->realm, 2094 tgt_info->realm_len); 2095 2096 tgt_info->r_rk_length = src_fils_info->rrk_len; 2097 qdf_mem_copy(tgt_info->r_rk, src_fils_info->rrk, 2098 tgt_info->r_rk_length); 2099 tgt_info->erp_sequence_number = src_fils_info->next_seq_num; 2100 tgt_info->auth_type = src_fils_info->auth_type; 2101 2102 return QDF_STATUS_SUCCESS; 2103 } 2104 2105 void wlan_cm_update_hlp_info(struct wlan_objmgr_psoc *psoc, 2106 const uint8_t *gen_ie, uint16_t len, 2107 uint8_t vdev_id, bool flush) 2108 { 2109 struct wlan_objmgr_vdev *vdev; 2110 2111 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 2112 WLAN_MLME_NB_ID); 2113 if (!vdev) { 2114 mlme_err("vdev object is NULL for vdev_id %d", vdev_id); 2115 return; 2116 } 2117 2118 cm_update_hlp_info(vdev, gen_ie, len, flush); 2119 2120 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); 2121 } 2122 2123 struct wlan_fils_connection_info *wlan_cm_get_fils_connection_info( 2124 struct wlan_objmgr_psoc *psoc, 2125 uint8_t vdev_id) 2126 { 2127 struct wlan_objmgr_vdev *vdev; 2128 struct mlme_legacy_priv *mlme_priv; 2129 struct wlan_fils_connection_info *fils_info; 2130 2131 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 2132 WLAN_MLME_NB_ID); 2133 if (!vdev) { 2134 mlme_err("vdev object is NULL"); 2135 return NULL; 2136 } 2137 2138 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 2139 if (!mlme_priv) { 2140 mlme_err("vdev legacy private object is NULL"); 2141 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); 2142 return NULL; 2143 } 2144 2145 fils_info = mlme_priv->connect_info.fils_con_info; 2146 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); 2147 2148 return fils_info; 2149 } 2150 2151 QDF_STATUS wlan_cm_update_fils_ft(struct wlan_objmgr_psoc *psoc, 2152 uint8_t vdev_id, uint8_t *fils_ft, 2153 uint8_t fils_ft_len) 2154 { 2155 struct wlan_objmgr_vdev *vdev; 2156 struct mlme_legacy_priv *mlme_priv; 2157 2158 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 2159 WLAN_MLME_NB_ID); 2160 if (!vdev) { 2161 mlme_err("vdev object is NULL"); 2162 return QDF_STATUS_E_FAILURE; 2163 } 2164 2165 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 2166 if (!mlme_priv) { 2167 mlme_err("vdev legacy private object is NULL"); 2168 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); 2169 return QDF_STATUS_E_FAILURE; 2170 } 2171 2172 if (!mlme_priv->connect_info.fils_con_info || !fils_ft || 2173 !fils_ft_len || 2174 !mlme_priv->connect_info.fils_con_info->is_fils_connection) { 2175 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); 2176 return QDF_STATUS_E_FAILURE; 2177 } 2178 2179 mlme_priv->connect_info.fils_con_info->fils_ft_len = fils_ft_len; 2180 qdf_mem_copy(mlme_priv->connect_info.fils_con_info->fils_ft, fils_ft, 2181 fils_ft_len); 2182 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); 2183 2184 return QDF_STATUS_SUCCESS; 2185 } 2186 #endif 2187 2188 #ifdef WLAN_FEATURE_11BE_MLO 2189 static void 2190 wlan_cm_get_mlo_associated_ch_info(struct wlan_objmgr_vdev *vdev, 2191 enum phy_ch_width scanned_ch_width, 2192 struct assoc_channel_info *assoc_chan_info) 2193 { 2194 struct mlme_legacy_priv *mlme_priv; 2195 struct wlan_channel *des_chan; 2196 struct wlan_mlo_dev_context *mlo_dev_ctx; 2197 struct wlan_mlo_sta *sta_ctx = NULL; 2198 uint8_t i; 2199 struct wlan_objmgr_vdev *mlo_vdev; 2200 struct assoc_channel_info *temp_assoc_chan_info; 2201 2202 mlo_dev_ctx = vdev->mlo_dev_ctx; 2203 if (!mlo_dev_ctx) { 2204 mlme_err("vdev %d :mlo_dev_ctx is NULL", 2205 vdev->vdev_objmgr.vdev_id); 2206 return; 2207 } 2208 2209 sta_ctx = mlo_dev_ctx->sta_ctx; 2210 if (!sta_ctx) { 2211 mlme_err("vdev %d :mlo_dev_ctx is NULL", 2212 vdev->vdev_objmgr.vdev_id); 2213 return; 2214 } 2215 2216 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 2217 if (!mlo_dev_ctx->wlan_vdev_list[i]) 2218 continue; 2219 if (qdf_test_bit(i, sta_ctx->wlan_connected_links)) { 2220 mlo_vdev = mlo_dev_ctx->wlan_vdev_list[i]; 2221 des_chan = wlan_vdev_mlme_get_des_chan(mlo_vdev); 2222 if (!des_chan) { 2223 mlme_debug("NULL des_chan"); 2224 return; 2225 } 2226 2227 if (des_chan->ch_width == scanned_ch_width) { 2228 mlme_priv = 2229 wlan_vdev_mlme_get_ext_hdl(mlo_vdev); 2230 if (!mlme_priv) { 2231 mlme_legacy_err("mlme_priv is NULL"); 2232 return; 2233 } 2234 temp_assoc_chan_info = 2235 &mlme_priv->connect_info.assoc_chan_info; 2236 assoc_chan_info->sec_2g_freq = 2237 temp_assoc_chan_info->sec_2g_freq; 2238 mlme_debug("vdev %d: assoc sec_2g_freq:%d", 2239 mlo_vdev->vdev_objmgr.vdev_id, 2240 assoc_chan_info->sec_2g_freq); 2241 break; 2242 } 2243 } 2244 } 2245 } 2246 #else 2247 static void 2248 wlan_cm_get_mlo_associated_ch_info(struct wlan_objmgr_vdev *vdev, 2249 enum phy_ch_width ch_width, 2250 struct assoc_channel_info *chan_info) 2251 { 2252 } 2253 #endif 2254 2255 void wlan_cm_get_associated_ch_info(struct wlan_objmgr_psoc *psoc, 2256 uint8_t vdev_id, 2257 enum phy_ch_width scanned_ch_width, 2258 struct assoc_channel_info *assoc_chan_info) 2259 { 2260 struct wlan_objmgr_vdev *vdev; 2261 struct mlme_legacy_priv *mlme_priv; 2262 2263 assoc_chan_info->assoc_ch_width = CH_WIDTH_INVALID; 2264 assoc_chan_info->sec_2g_freq = 0; 2265 2266 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 2267 WLAN_MLME_NB_ID); 2268 if (!vdev) { 2269 mlme_legacy_err("vdev %d: vdev not found", vdev_id); 2270 return; 2271 } 2272 2273 if (wlan_vdev_mlme_is_mlo_vdev(vdev)) { 2274 mlme_debug("vdev %d: get assoc chan info for mlo connection", 2275 vdev_id); 2276 wlan_cm_get_mlo_associated_ch_info(vdev, scanned_ch_width, 2277 assoc_chan_info); 2278 goto release; 2279 } 2280 2281 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 2282 if (!mlme_priv) { 2283 mlme_legacy_err("mlme_priv is NULL"); 2284 goto release; 2285 } 2286 2287 assoc_chan_info->assoc_ch_width = 2288 mlme_priv->connect_info.assoc_chan_info.assoc_ch_width; 2289 assoc_chan_info->sec_2g_freq = 2290 mlme_priv->connect_info.assoc_chan_info.sec_2g_freq; 2291 2292 mlme_debug("vdev %d: associated_ch_width:%d, sec_2g_freq:%d", vdev_id, 2293 assoc_chan_info->assoc_ch_width, 2294 assoc_chan_info->sec_2g_freq); 2295 2296 release: 2297 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); 2298 } 2299 2300 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 2301 QDF_STATUS 2302 wlan_cm_update_roam_scan_scheme_bitmap(struct wlan_objmgr_psoc *psoc, 2303 uint8_t vdev_id, 2304 uint32_t roam_scan_scheme_bitmap) 2305 { 2306 struct wlan_objmgr_vdev *vdev; 2307 struct rso_config *rso_cfg; 2308 2309 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 2310 WLAN_MLME_NB_ID); 2311 2312 if (!vdev) { 2313 mlme_err("vdev%d: vdev object is NULL", vdev_id); 2314 return QDF_STATUS_E_FAILURE; 2315 } 2316 2317 rso_cfg = wlan_cm_get_rso_config(vdev); 2318 if (!rso_cfg) { 2319 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); 2320 return QDF_STATUS_E_FAILURE; 2321 } 2322 rso_cfg->roam_scan_scheme_bitmap = roam_scan_scheme_bitmap; 2323 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); 2324 2325 return QDF_STATUS_SUCCESS; 2326 } 2327 2328 QDF_STATUS wlan_cm_set_roam_band_bitmask(struct wlan_objmgr_psoc *psoc, 2329 uint8_t vdev_id, 2330 uint32_t roam_band_bitmask) 2331 { 2332 struct cm_roam_values_copy src_config = {}; 2333 2334 src_config.uint_value = roam_band_bitmask; 2335 return wlan_cm_roam_cfg_set_value(psoc, vdev_id, ROAM_BAND, 2336 &src_config); 2337 } 2338 2339 QDF_STATUS wlan_cm_set_roam_band_update(struct wlan_objmgr_psoc *psoc, 2340 uint8_t vdev_id) 2341 { 2342 return cm_roam_update_cfg(psoc, vdev_id, 2343 REASON_ROAM_CONTROL_CONFIG_ENABLED); 2344 } 2345 2346 uint32_t wlan_cm_get_roam_scan_scheme_bitmap(struct wlan_objmgr_psoc *psoc, 2347 uint8_t vdev_id) 2348 { 2349 struct wlan_objmgr_vdev *vdev; 2350 uint32_t roam_scan_scheme_bitmap; 2351 struct rso_config *rso_cfg; 2352 2353 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 2354 WLAN_MLME_NB_ID); 2355 2356 if (!vdev) { 2357 mlme_err("vdev%d: vdev object is NULL", vdev_id); 2358 return 0; 2359 } 2360 2361 rso_cfg = wlan_cm_get_rso_config(vdev); 2362 if (!rso_cfg) { 2363 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); 2364 return 0; 2365 } 2366 2367 roam_scan_scheme_bitmap = rso_cfg->roam_scan_scheme_bitmap; 2368 2369 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); 2370 2371 return roam_scan_scheme_bitmap; 2372 } 2373 2374 QDF_STATUS 2375 wlan_cm_update_roam_states(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, 2376 uint32_t value, enum roam_fail_params states) 2377 { 2378 struct wlan_objmgr_vdev *vdev; 2379 struct rso_config *rso_cfg; 2380 2381 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 2382 WLAN_MLME_NB_ID); 2383 2384 if (!vdev) { 2385 mlme_err("vdev%d: vdev object is NULL", vdev_id); 2386 return QDF_STATUS_E_FAILURE; 2387 } 2388 2389 rso_cfg = wlan_cm_get_rso_config(vdev); 2390 if (!rso_cfg) { 2391 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); 2392 return QDF_STATUS_E_FAILURE; 2393 } 2394 2395 switch (states) { 2396 case ROAM_TRIGGER_REASON: 2397 rso_cfg->roam_trigger_reason = value; 2398 break; 2399 case ROAM_INVOKE_FAIL_REASON: 2400 rso_cfg->roam_invoke_fail_reason = value; 2401 break; 2402 case ROAM_FAIL_REASON: 2403 rso_cfg->roam_fail_reason = value; 2404 break; 2405 default: 2406 break; 2407 } 2408 2409 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); 2410 2411 return QDF_STATUS_SUCCESS; 2412 } 2413 2414 uint32_t wlan_cm_get_roam_states(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, 2415 enum roam_fail_params states) 2416 { 2417 struct wlan_objmgr_vdev *vdev; 2418 uint32_t roam_states = 0; 2419 struct rso_config *rso_cfg; 2420 2421 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 2422 WLAN_MLME_NB_ID); 2423 2424 if (!vdev) { 2425 mlme_err("vdev%d: vdev object is NULL", vdev_id); 2426 return 0; 2427 } 2428 2429 rso_cfg = wlan_cm_get_rso_config(vdev); 2430 if (!rso_cfg) { 2431 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); 2432 return 0; 2433 } 2434 2435 switch (states) { 2436 case ROAM_TRIGGER_REASON: 2437 roam_states = rso_cfg->roam_trigger_reason; 2438 break; 2439 case ROAM_INVOKE_FAIL_REASON: 2440 roam_states = rso_cfg->roam_invoke_fail_reason; 2441 break; 2442 case ROAM_FAIL_REASON: 2443 roam_states = rso_cfg->roam_fail_reason; 2444 break; 2445 default: 2446 break; 2447 } 2448 2449 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID); 2450 2451 return roam_states; 2452 } 2453 2454 QDF_STATUS 2455 wlan_cm_update_roam_rt_stats(struct wlan_objmgr_psoc *psoc, 2456 uint8_t value, enum roam_rt_stats_params stats) 2457 { 2458 struct wlan_mlme_psoc_ext_obj *mlme_obj; 2459 struct wlan_cm_roam_rt_stats *roam_rt_stats; 2460 2461 mlme_obj = mlme_get_psoc_ext_obj(psoc); 2462 if (!mlme_obj) { 2463 mlme_legacy_err("Failed to get MLME Obj"); 2464 return QDF_STATUS_E_FAILURE; 2465 } 2466 2467 roam_rt_stats = &mlme_obj->cfg.lfr.roam_rt_stats; 2468 2469 switch (stats) { 2470 case ROAM_RT_STATS_ENABLE: 2471 roam_rt_stats->roam_stats_enabled = value; 2472 break; 2473 case ROAM_RT_STATS_SUSPEND_MODE_ENABLE: 2474 roam_rt_stats->roam_stats_wow_sent = value; 2475 break; 2476 default: 2477 break; 2478 } 2479 2480 return QDF_STATUS_SUCCESS; 2481 } 2482 2483 uint8_t wlan_cm_get_roam_rt_stats(struct wlan_objmgr_psoc *psoc, 2484 enum roam_rt_stats_params stats) 2485 { 2486 struct wlan_mlme_psoc_ext_obj *mlme_obj; 2487 struct wlan_cm_roam_rt_stats *roam_rt_stats; 2488 uint8_t rstats_value = 0; 2489 2490 mlme_obj = mlme_get_psoc_ext_obj(psoc); 2491 if (!mlme_obj) { 2492 mlme_legacy_err("Failed to get MLME Obj"); 2493 return QDF_STATUS_E_FAILURE; 2494 } 2495 2496 roam_rt_stats = &mlme_obj->cfg.lfr.roam_rt_stats; 2497 switch (stats) { 2498 case ROAM_RT_STATS_ENABLE: 2499 rstats_value = roam_rt_stats->roam_stats_enabled; 2500 break; 2501 case ROAM_RT_STATS_SUSPEND_MODE_ENABLE: 2502 rstats_value = roam_rt_stats->roam_stats_wow_sent; 2503 break; 2504 default: 2505 break; 2506 } 2507 2508 return rstats_value; 2509 } 2510 #endif 2511 2512 QDF_STATUS wlan_get_chan_by_bssid_from_rnr(struct wlan_objmgr_vdev *vdev, 2513 wlan_cm_id cm_id, 2514 struct qdf_mac_addr *link_addr, 2515 uint8_t *chan, uint8_t *op_class) 2516 { 2517 struct reduced_neighbor_report *rnr; 2518 int i; 2519 QDF_STATUS status; 2520 2521 *chan = 0; 2522 rnr = qdf_mem_malloc(sizeof(*rnr)); 2523 if (!rnr) 2524 return QDF_STATUS_E_NOMEM; 2525 2526 status = wlan_cm_get_rnr(vdev, cm_id, rnr); 2527 if (QDF_IS_STATUS_ERROR(status)) { 2528 qdf_mem_free(rnr); 2529 return status; 2530 } 2531 2532 for (i = 0; i < MAX_RNR_BSS; i++) { 2533 if (!rnr->bss_info[i].channel_number) 2534 continue; 2535 if (qdf_is_macaddr_equal(link_addr, &rnr->bss_info[i].bssid)) { 2536 *chan = rnr->bss_info[i].channel_number; 2537 *op_class = rnr->bss_info[i].operating_class; 2538 break; 2539 } 2540 } 2541 qdf_mem_free(rnr); 2542 2543 return QDF_STATUS_SUCCESS; 2544 } 2545 2546 #ifdef WLAN_FEATURE_11BE_MLO 2547 /** 2548 * mlo_rnr_link_id_cmp() - compare given link id with link id in rnr 2549 * @rnr_bss_info: rnr bss info 2550 * @link_id: link id 2551 * 2552 * Return: true if given link id is the same with link id in rnr 2553 */ 2554 static bool mlo_rnr_link_id_cmp(struct rnr_bss_info *rnr_bss_info, 2555 uint8_t link_id) 2556 { 2557 if (rnr_bss_info) 2558 return link_id == rnr_bss_info->mld_info.link_id; 2559 2560 return false; 2561 } 2562 2563 QDF_STATUS wlan_get_chan_by_link_id_from_rnr(struct wlan_objmgr_vdev *vdev, 2564 wlan_cm_id cm_id, 2565 uint8_t link_id, 2566 uint8_t *chan, uint8_t *op_class) 2567 { 2568 struct reduced_neighbor_report *rnr; 2569 int i; 2570 QDF_STATUS status; 2571 2572 *chan = 0; 2573 rnr = qdf_mem_malloc(sizeof(*rnr)); 2574 if (!rnr) 2575 return QDF_STATUS_E_NOMEM; 2576 2577 status = wlan_cm_get_rnr(vdev, cm_id, rnr); 2578 if (QDF_IS_STATUS_ERROR(status)) { 2579 qdf_mem_free(rnr); 2580 return status; 2581 } 2582 2583 for (i = 0; i < MAX_RNR_BSS; i++) { 2584 if (!rnr->bss_info[i].channel_number) 2585 continue; 2586 if (mlo_rnr_link_id_cmp(&rnr->bss_info[i], link_id)) { 2587 *chan = rnr->bss_info[i].channel_number; 2588 *op_class = rnr->bss_info[i].operating_class; 2589 break; 2590 } 2591 } 2592 qdf_mem_free(rnr); 2593 2594 return QDF_STATUS_SUCCESS; 2595 } 2596 #endif 2597 2598 QDF_STATUS wlan_cm_sta_mlme_vdev_roam_notify(struct vdev_mlme_obj *vdev_mlme, 2599 uint16_t data_len, void *data) 2600 { 2601 QDF_STATUS status = QDF_STATUS_SUCCESS; 2602 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 2603 status = cm_roam_sync_event_handler_cb(vdev_mlme->vdev, data, data_len); 2604 if (QDF_IS_STATUS_ERROR(status)) 2605 mlme_err("Failed to process roam synch event"); 2606 #endif 2607 return status; 2608 } 2609 2610 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 2611 static void 2612 cm_handle_roam_offload_events(struct roam_offload_roam_event *roam_event) 2613 { 2614 switch (roam_event->reason) { 2615 case ROAM_REASON_HO_FAILED: { 2616 struct qdf_mac_addr bssid; 2617 2618 bssid.bytes[0] = roam_event->notif_params >> 0 & 0xFF; 2619 bssid.bytes[1] = roam_event->notif_params >> 8 & 0xFF; 2620 bssid.bytes[2] = roam_event->notif_params >> 16 & 0xFF; 2621 bssid.bytes[3] = roam_event->notif_params >> 24 & 0xFF; 2622 bssid.bytes[4] = roam_event->notif_params1 >> 0 & 0xFF; 2623 bssid.bytes[5] = roam_event->notif_params1 >> 8 & 0xFF; 2624 cm_handle_roam_reason_ho_failed(roam_event->vdev_id, bssid, 2625 roam_event->hw_mode_trans_ind); 2626 } 2627 break; 2628 case ROAM_REASON_INVALID: 2629 cm_invalid_roam_reason_handler(roam_event->vdev_id, 2630 roam_event->notif, 2631 roam_event->notif_params); 2632 break; 2633 default: 2634 break; 2635 } 2636 } 2637 2638 QDF_STATUS 2639 cm_vdev_disconnect_event_handler(struct vdev_disconnect_event_data *data) 2640 { 2641 return cm_handle_disconnect_reason(data); 2642 } 2643 2644 QDF_STATUS 2645 cm_roam_auth_offload_event_handler(struct auth_offload_event *auth_event) 2646 { 2647 return cm_handle_auth_offload(auth_event); 2648 } 2649 2650 QDF_STATUS 2651 cm_roam_pmkid_request_handler(struct roam_pmkid_req_event *data) 2652 { 2653 QDF_STATUS status; 2654 2655 status = cm_roam_pmkid_req_ind(data->psoc, data->vdev_id, data); 2656 if (QDF_IS_STATUS_ERROR(status)) 2657 mlme_err("Pmkid request failed"); 2658 2659 return status; 2660 } 2661 #else 2662 static void 2663 cm_handle_roam_offload_events(struct roam_offload_roam_event *roam_event) 2664 { 2665 mlme_debug("Unhandled roam event with reason 0x%x for vdev_id %u", 2666 roam_event->reason, roam_event->vdev_id); 2667 } 2668 2669 QDF_STATUS 2670 cm_vdev_disconnect_event_handler(struct vdev_disconnect_event_data *data) 2671 { 2672 return QDF_STATUS_SUCCESS; 2673 } 2674 2675 QDF_STATUS 2676 cm_roam_auth_offload_event_handler(struct auth_offload_event *auth_event) 2677 { 2678 return QDF_STATUS_SUCCESS; 2679 } 2680 2681 QDF_STATUS 2682 cm_roam_pmkid_request_handler(struct roam_pmkid_req_event *data) 2683 { 2684 return QDF_STATUS_SUCCESS; 2685 } 2686 #endif 2687 2688 #ifdef WLAN_VENDOR_HANDOFF_CONTROL 2689 void 2690 cm_roam_vendor_handoff_event_handler(struct wlan_objmgr_psoc *psoc, 2691 struct roam_vendor_handoff_params *data) 2692 { 2693 struct wlan_objmgr_vdev *vdev; 2694 struct mlme_legacy_priv *mlme_priv; 2695 void *vendor_handoff_context; 2696 QDF_STATUS status; 2697 2698 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, data->vdev_id, 2699 WLAN_MLME_OBJMGR_ID); 2700 if (!vdev) { 2701 mlme_err("vdev object is NULL for vdev %d", data->vdev_id); 2702 return; 2703 } 2704 2705 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 2706 if (!mlme_priv) 2707 return; 2708 2709 vendor_handoff_context = 2710 mlme_priv->cm_roam.vendor_handoff_param.vendor_handoff_context; 2711 2712 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 2713 2714 status = mlme_cm_osif_get_vendor_handoff_params(psoc, 2715 vendor_handoff_context); 2716 if (QDF_IS_STATUS_ERROR(status)) { 2717 mlme_debug("Failed to free vendor handoff request"); 2718 return; 2719 } 2720 2721 mlme_debug("Reset vendor handoff req in progress context"); 2722 mlme_priv->cm_roam.vendor_handoff_param.req_in_progress = false; 2723 mlme_priv->cm_roam.vendor_handoff_param.vendor_handoff_context = NULL; 2724 2725 status = cm_roam_update_vendor_handoff_config(psoc, data); 2726 if (QDF_IS_STATUS_ERROR(status)) 2727 mlme_debug("Failed to update params in rso_config struct"); 2728 } 2729 #endif 2730 2731 QDF_STATUS 2732 cm_roam_event_handler(struct roam_offload_roam_event *roam_event) 2733 { 2734 switch (roam_event->reason) { 2735 case ROAM_REASON_BTM: 2736 cm_handle_roam_reason_btm(roam_event->vdev_id); 2737 break; 2738 case ROAM_REASON_BMISS: 2739 cm_handle_roam_reason_bmiss(roam_event->vdev_id, 2740 roam_event->rssi); 2741 break; 2742 case ROAM_REASON_BETTER_AP: 2743 cm_handle_roam_reason_better_ap(roam_event->vdev_id, 2744 roam_event->rssi); 2745 break; 2746 case ROAM_REASON_SUITABLE_AP: 2747 cm_handle_roam_reason_suitable_ap(roam_event->vdev_id, 2748 roam_event->rssi); 2749 break; 2750 case ROAM_REASON_HO_FAILED: 2751 /* 2752 * Continue disconnect only if RSO_STOP timer is running when 2753 * this event is received and stopped as part of this. 2754 * Otherwise it's a normal HO_FAIL event and handle it in 2755 * legacy way. 2756 */ 2757 if (roam_event->rso_timer_stopped) 2758 wlan_cm_rso_stop_continue_disconnect(roam_event->psoc, 2759 roam_event->vdev_id, true); 2760 fallthrough; 2761 case ROAM_REASON_INVALID: 2762 cm_handle_roam_offload_events(roam_event); 2763 break; 2764 case ROAM_REASON_RSO_STATUS: 2765 /* 2766 * roam_event->rso_timer_stopped is set to true in target_if 2767 * only if RSO_STOP timer is running and it's stopped 2768 * successfully 2769 */ 2770 if (roam_event->rso_timer_stopped && 2771 (roam_event->notif == CM_ROAM_NOTIF_SCAN_MODE_SUCCESS || 2772 roam_event->notif == CM_ROAM_NOTIF_SCAN_MODE_FAIL)) 2773 wlan_cm_rso_stop_continue_disconnect(roam_event->psoc, 2774 roam_event->vdev_id, false); 2775 cm_rso_cmd_status_event_handler(roam_event->vdev_id, 2776 roam_event->notif); 2777 break; 2778 case ROAM_REASON_INVOKE_ROAM_FAIL: 2779 cm_handle_roam_reason_invoke_roam_fail(roam_event->vdev_id, 2780 roam_event->notif_params, 2781 roam_event->hw_mode_trans_ind); 2782 break; 2783 case ROAM_REASON_DEAUTH: 2784 cm_handle_roam_reason_deauth(roam_event->vdev_id, 2785 roam_event->notif_params, 2786 roam_event->deauth_disassoc_frame, 2787 roam_event->notif_params1); 2788 break; 2789 default: 2790 mlme_debug("Unhandled roam event with reason 0x%x for vdev_id %u", 2791 roam_event->reason, roam_event->vdev_id); 2792 break; 2793 } 2794 2795 return QDF_STATUS_SUCCESS; 2796 } 2797 2798 static void 2799 cm_add_bssid_to_reject_list(struct wlan_objmgr_pdev *pdev, 2800 struct sir_rssi_disallow_lst *entry) 2801 { 2802 struct reject_ap_info ap_info; 2803 2804 qdf_mem_zero(&ap_info, sizeof(struct reject_ap_info)); 2805 2806 ap_info.bssid = entry->bssid; 2807 ap_info.reject_ap_type = DRIVER_RSSI_REJECT_TYPE; 2808 ap_info.rssi_reject_params.expected_rssi = entry->expected_rssi; 2809 ap_info.rssi_reject_params.retry_delay = entry->retry_delay; 2810 ap_info.reject_reason = entry->reject_reason; 2811 ap_info.source = entry->source; 2812 ap_info.rssi_reject_params.received_time = entry->received_time; 2813 ap_info.rssi_reject_params.original_timeout = entry->original_timeout; 2814 /* Add this ap info to the rssi reject ap type in denylist manager */ 2815 wlan_dlm_add_bssid_to_reject_list(pdev, &ap_info); 2816 } 2817 2818 QDF_STATUS 2819 cm_btm_denylist_event_handler(struct wlan_objmgr_psoc *psoc, 2820 struct roam_denylist_event *list) 2821 { 2822 uint32_t i, pdev_id; 2823 struct sir_rssi_disallow_lst entry; 2824 struct roam_denylist_timeout *denylist; 2825 struct wlan_objmgr_pdev *pdev; 2826 2827 pdev_id = wlan_get_pdev_id_from_vdev_id(psoc, list->vdev_id, 2828 WLAN_MLME_CM_ID); 2829 if (pdev_id == WLAN_INVALID_PDEV_ID) { 2830 mlme_err("Invalid pdev id"); 2831 return QDF_STATUS_E_INVAL; 2832 } 2833 2834 pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, WLAN_MLME_CM_ID); 2835 if (!pdev) { 2836 mlme_err("Invalid pdev"); 2837 return QDF_STATUS_E_INVAL; 2838 } 2839 2840 mlme_debug("Received Denylist event from FW num entries %d", 2841 list->num_entries); 2842 denylist = &list->roam_denylist[0]; 2843 for (i = 0; i < list->num_entries; i++) { 2844 qdf_mem_zero(&entry, sizeof(struct sir_rssi_disallow_lst)); 2845 entry.bssid = denylist->bssid; 2846 entry.time_during_rejection = denylist->received_time; 2847 entry.reject_reason = denylist->reject_reason; 2848 entry.source = denylist->source ? denylist->source : 2849 ADDED_BY_TARGET; 2850 entry.original_timeout = denylist->original_timeout; 2851 entry.received_time = denylist->received_time; 2852 /* If timeout = 0 and rssi = 0 ignore the entry */ 2853 if (!denylist->timeout && !denylist->rssi) { 2854 continue; 2855 } else if (denylist->timeout) { 2856 entry.retry_delay = denylist->timeout; 2857 /* set 0dbm as expected rssi */ 2858 entry.expected_rssi = CM_MIN_RSSI; 2859 } else { 2860 /* denylist timeout as 0 */ 2861 entry.retry_delay = denylist->timeout; 2862 entry.expected_rssi = denylist->rssi; 2863 } 2864 2865 /* Add this bssid to the rssi reject ap type in denylist mgr */ 2866 cm_add_bssid_to_reject_list(pdev, &entry); 2867 denylist++; 2868 } 2869 wlan_objmgr_pdev_release_ref(pdev, WLAN_MLME_CM_ID); 2870 2871 return QDF_STATUS_SUCCESS; 2872 } 2873 2874 QDF_STATUS 2875 cm_roam_scan_ch_list_event_handler(struct cm_roam_scan_ch_resp *data) 2876 { 2877 return cm_handle_scan_ch_list_data(data); 2878 } 2879 2880 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 2881 /** 2882 * cm_roam_stats_get_trigger_detail_str - Return roam trigger string from the 2883 * enum roam_trigger_reason 2884 * @ptr: Pointer to the roam trigger info 2885 * @buf: Destination buffer to write the reason string 2886 * @is_full_scan: Is roam scan partial scan or all channels scan 2887 * @vdev_id: vdev id 2888 * 2889 * Return: None 2890 */ 2891 static void 2892 cm_roam_stats_get_trigger_detail_str(struct wmi_roam_trigger_info *ptr, 2893 char *buf, bool is_full_scan, 2894 uint8_t vdev_id) 2895 { 2896 uint16_t buf_cons, buf_left = MAX_ROAM_DEBUG_BUF_SIZE; 2897 char *temp = buf; 2898 2899 buf_cons = qdf_snprint(temp, buf_left, "Reason: \"%s\" ", 2900 mlme_get_roam_trigger_str(ptr->trigger_reason)); 2901 temp += buf_cons; 2902 buf_left -= buf_cons; 2903 2904 if (ptr->trigger_sub_reason) { 2905 buf_cons = qdf_snprint(temp, buf_left, "Sub-Reason: %s", 2906 mlme_get_sub_reason_str(ptr->trigger_sub_reason)); 2907 temp += buf_cons; 2908 buf_left -= buf_cons; 2909 } 2910 2911 switch (ptr->trigger_reason) { 2912 case ROAM_TRIGGER_REASON_PER: 2913 case ROAM_TRIGGER_REASON_BMISS: 2914 case ROAM_TRIGGER_REASON_HIGH_RSSI: 2915 case ROAM_TRIGGER_REASON_MAWC: 2916 case ROAM_TRIGGER_REASON_DENSE: 2917 case ROAM_TRIGGER_REASON_BACKGROUND: 2918 case ROAM_TRIGGER_REASON_IDLE: 2919 case ROAM_TRIGGER_REASON_FORCED: 2920 case ROAM_TRIGGER_REASON_UNIT_TEST: 2921 break; 2922 case ROAM_TRIGGER_REASON_BTM: 2923 cm_roam_btm_req_event(&ptr->btm_trig_data, ptr, vdev_id, false); 2924 buf_cons = qdf_snprint( 2925 temp, buf_left, 2926 "Req_mode: %d Disassoc_timer: %d", 2927 ptr->btm_trig_data.btm_request_mode, 2928 ptr->btm_trig_data.disassoc_timer / 1000); 2929 temp += buf_cons; 2930 buf_left -= buf_cons; 2931 2932 buf_cons = qdf_snprint(temp, buf_left, 2933 "validity_interval: %d candidate_list_cnt: %d resp_status: %d, bss_termination_timeout: %d, mbo_assoc_retry_timeout: %d", 2934 ptr->btm_trig_data.validity_interval / 1000, 2935 ptr->btm_trig_data.candidate_list_count, 2936 ptr->btm_trig_data.btm_resp_status, 2937 ptr->btm_trig_data.btm_bss_termination_timeout, 2938 ptr->btm_trig_data.btm_mbo_assoc_retry_timeout); 2939 buf_left -= buf_cons; 2940 temp += buf_cons; 2941 break; 2942 case ROAM_TRIGGER_REASON_BSS_LOAD: 2943 buf_cons = qdf_snprint(temp, buf_left, "CU: %d %% ", 2944 ptr->cu_trig_data.cu_load); 2945 temp += buf_cons; 2946 buf_left -= buf_cons; 2947 break; 2948 case ROAM_TRIGGER_REASON_DEAUTH: 2949 buf_cons = qdf_snprint(temp, buf_left, "Type: %d Reason: %d ", 2950 ptr->deauth_trig_data.type, 2951 ptr->deauth_trig_data.reason); 2952 temp += buf_cons; 2953 buf_left -= buf_cons; 2954 break; 2955 case ROAM_TRIGGER_REASON_LOW_RSSI: 2956 case ROAM_TRIGGER_REASON_PERIODIC: 2957 /* 2958 * Use ptr->current_rssi get the RSSI of current AP after 2959 * roam scan is triggered. This avoids discrepancy with the 2960 * next rssi threshold value printed in roam scan details. 2961 * ptr->rssi_trig_data.threshold gives the rssi threshold 2962 * for the Low Rssi/Periodic scan trigger. 2963 */ 2964 if (ptr->common_roam) 2965 buf_cons = qdf_snprint(temp, buf_left, 2966 "Cur_Rssi threshold:%d Current AP RSSI: %d", 2967 ptr->low_rssi_trig_data.roam_rssi_threshold, 2968 ptr->low_rssi_trig_data.current_rssi); 2969 else 2970 buf_cons = qdf_snprint(temp, buf_left, 2971 "Cur_Rssi threshold:%d Current AP RSSI: %d", 2972 ptr->rssi_trig_data.threshold, 2973 ptr->current_rssi); 2974 temp += buf_cons; 2975 buf_left -= buf_cons; 2976 break; 2977 case ROAM_TRIGGER_REASON_WTC_BTM: 2978 cm_roam_btm_resp_event(ptr, NULL, vdev_id, true); 2979 2980 if (ptr->wtc_btm_trig_data.wtc_candi_rssi_ext_present) { 2981 buf_cons = qdf_snprint(temp, buf_left, 2982 "Roaming Mode: %d, Trigger Reason: %d, Sub code:%d, wtc mode:%d, wtc scan mode:%d, wtc rssi th:%d, wtc candi rssi th_2g:%d, wtc_candi_rssi_th_5g:%d, wtc_candi_rssi_th_6g:%d", 2983 ptr->wtc_btm_trig_data.roaming_mode, 2984 ptr->wtc_btm_trig_data.vsie_trigger_reason, 2985 ptr->wtc_btm_trig_data.sub_code, 2986 ptr->wtc_btm_trig_data.wtc_mode, 2987 ptr->wtc_btm_trig_data.wtc_scan_mode, 2988 ptr->wtc_btm_trig_data.wtc_rssi_th, 2989 ptr->wtc_btm_trig_data.wtc_candi_rssi_th, 2990 ptr->wtc_btm_trig_data.wtc_candi_rssi_th_5g, 2991 ptr->wtc_btm_trig_data.wtc_candi_rssi_th_6g); 2992 } else { 2993 buf_cons = qdf_snprint(temp, buf_left, 2994 "Roaming Mode: %d, Trigger Reason: %d, Sub code:%d, wtc mode:%d, wtc scan mode:%d, wtc rssi th:%d, wtc candi rssi th:%d", 2995 ptr->wtc_btm_trig_data.roaming_mode, 2996 ptr->wtc_btm_trig_data.vsie_trigger_reason, 2997 ptr->wtc_btm_trig_data.sub_code, 2998 ptr->wtc_btm_trig_data.wtc_mode, 2999 ptr->wtc_btm_trig_data.wtc_scan_mode, 3000 ptr->wtc_btm_trig_data.wtc_rssi_th, 3001 ptr->wtc_btm_trig_data.wtc_candi_rssi_th); 3002 } 3003 3004 temp += buf_cons; 3005 buf_left -= buf_cons; 3006 break; 3007 default: 3008 break; 3009 } 3010 } 3011 3012 /** 3013 * cm_roam_stats_print_trigger_info - Roam trigger related details 3014 * @psoc: Pointer to PSOC object 3015 * @data: Pointer to the roam trigger data 3016 * @scan_data: Roam scan data pointer 3017 * @vdev_id: Vdev ID 3018 * @is_full_scan: Was a full scan performed 3019 * 3020 * Prints the vdev, roam trigger reason, time of the day at which roaming 3021 * was triggered. 3022 * 3023 * Return: None 3024 */ 3025 static void 3026 cm_roam_stats_print_trigger_info(struct wlan_objmgr_psoc *psoc, 3027 struct wmi_roam_trigger_info *data, 3028 struct wmi_roam_scan_data *scan_data, 3029 uint8_t vdev_id, bool is_full_scan) 3030 { 3031 char *buf; 3032 char time[TIME_STRING_LEN]; 3033 QDF_STATUS status; 3034 3035 buf = qdf_mem_malloc(MAX_ROAM_DEBUG_BUF_SIZE); 3036 if (!buf) 3037 return; 3038 3039 cm_roam_stats_get_trigger_detail_str(data, buf, is_full_scan, vdev_id); 3040 mlme_get_converted_timestamp(data->timestamp, time); 3041 3042 /* Update roam trigger info to userspace */ 3043 cm_roam_trigger_info_event(data, scan_data, vdev_id, is_full_scan); 3044 3045 mlme_nofl_info("%s [ROAM_TRIGGER]: VDEV[%d] %s", 3046 time, vdev_id, buf); 3047 qdf_mem_free(buf); 3048 3049 status = wlan_cm_update_roam_states(psoc, vdev_id, data->trigger_reason, 3050 ROAM_TRIGGER_REASON); 3051 if (QDF_IS_STATUS_ERROR(status)) 3052 mlme_err("failed to update rt stats trigger reason"); 3053 } 3054 3055 /** 3056 * cm_roam_stats_print_btm_rsp_info - BTM RSP related details 3057 * @trigger_info: Roam scan trigger reason 3058 * @data: Pointer to the btm rsp data 3059 * @vdev_id: vdev id 3060 * @is_wtc: is WTC? 3061 * 3062 * Prints the vdev, btm status, target_bssid and vsie reason 3063 * 3064 * Return: None 3065 */ 3066 static void 3067 cm_roam_stats_print_btm_rsp_info(struct wmi_roam_trigger_info *trigger_info, 3068 struct roam_btm_response_data *data, 3069 uint8_t vdev_id, bool is_wtc) 3070 { 3071 char time[TIME_STRING_LEN]; 3072 3073 mlme_get_converted_timestamp(data->timestamp, time); 3074 mlme_nofl_info("%s [BTM RSP]:VDEV[%d], Status:%d, VSIE reason:%d, BSSID: " 3075 QDF_MAC_ADDR_FMT, time, vdev_id, data->btm_status, 3076 data->vsie_reason, 3077 QDF_MAC_ADDR_REF(data->target_bssid.bytes)); 3078 cm_roam_btm_resp_event(trigger_info, data, vdev_id, is_wtc); 3079 } 3080 3081 /** 3082 * cm_roam_stats_print_roam_initial_info - Roaming related initial details 3083 * @data: Pointer to the btm rsp data 3084 * @vdev_id: vdev id 3085 * 3086 * Prints the vdev, roam_full_scan_count, channel and rssi 3087 * utilization threshold and timer 3088 * 3089 * Return: None 3090 */ 3091 static void 3092 cm_roam_stats_print_roam_initial_info(struct roam_initial_data *data, 3093 uint8_t vdev_id) 3094 { 3095 mlme_nofl_info("[ROAM INIT INFO]: VDEV[%d], roam_full_scan_count: %d, rssi_th: %d, cu_th: %d, fw_cancel_timer_bitmap: %d", 3096 vdev_id, data->roam_full_scan_count, data->rssi_th, 3097 data->cu_th, data->fw_cancel_timer_bitmap); 3098 } 3099 3100 /** 3101 * cm_roam_stats_print_roam_msg_info - Roaming related message details 3102 * @data: Pointer to the btm rsp data 3103 * @vdev_id: vdev id 3104 * 3105 * Prints the vdev, msg_id, msg_param1, msg_param2 and timer 3106 * 3107 * Return: None 3108 */ 3109 static void cm_roam_stats_print_roam_msg_info(struct roam_msg_info *data, 3110 uint8_t vdev_id) 3111 { 3112 char time[TIME_STRING_LEN]; 3113 static const char msg_id1_str[] = "Roam RSSI TH Reset"; 3114 3115 if (data->msg_id == WMI_ROAM_MSG_RSSI_RECOVERED) { 3116 mlme_get_converted_timestamp(data->timestamp, time); 3117 mlme_nofl_info("%s [ROAM MSG INFO]: VDEV[%d] %s, Current rssi: %d dbm, next_rssi_threshold: %d dbm", 3118 time, vdev_id, msg_id1_str, data->msg_param1, 3119 data->msg_param2); 3120 } 3121 } 3122 3123 /** 3124 * cm_stats_log_roam_scan_candidates - Print roam scan candidate AP info 3125 * @ap: Pointer to the candidate AP list 3126 * @num_entries: Number of candidate APs 3127 * 3128 * Print the RSSI, CU load, Cu score, RSSI score, total score, BSSID 3129 * and time stamp at which the candidate was found details. 3130 * 3131 * Return: None 3132 */ 3133 static void 3134 cm_stats_log_roam_scan_candidates(struct wmi_roam_candidate_info *ap, 3135 uint8_t num_entries) 3136 { 3137 uint16_t i; 3138 char time[TIME_STRING_LEN], time2[TIME_STRING_LEN]; 3139 3140 3141 mlme_nofl_info("%62s%62s", LINE_STR, LINE_STR); 3142 mlme_nofl_info("%13s %16s %8s %4s %4s %5s/%3s %3s/%3s %7s %7s %6s %12s %20s", 3143 "AP BSSID", "TSTAMP", "CH", "TY", "ETP", "RSSI", 3144 "SCR", "CU%", "SCR", "TOT_SCR", "BL_RSN", "BL_SRC", 3145 "BL_TSTAMP", "BL_TIMEOUT(ms)"); 3146 mlme_nofl_info("%62s%62s", LINE_STR, LINE_STR); 3147 3148 if (num_entries > MAX_ROAM_CANDIDATE_AP) 3149 num_entries = MAX_ROAM_CANDIDATE_AP; 3150 3151 for (i = 0; i < num_entries; i++) { 3152 mlme_get_converted_timestamp(ap->timestamp, time); 3153 mlme_get_converted_timestamp(ap->dl_timestamp, time2); 3154 mlme_nofl_info(QDF_MAC_ADDR_FMT " %17s %4d %-4s %4d %3d/%-4d %2d/%-4d %5d %7d %7d %17s %9d", 3155 QDF_MAC_ADDR_REF(ap->bssid.bytes), time, 3156 ap->freq, 3157 ((ap->type == 0) ? "C_AP" : 3158 ((ap->type == 2) ? "R_AP" : "P_AP")), 3159 ap->etp, ap->rssi, ap->rssi_score, ap->cu_load, 3160 ap->cu_score, ap->total_score, ap->dl_reason, 3161 ap->dl_source, time2, ap->dl_original_timeout); 3162 /* Update roam candidates info to userspace */ 3163 cm_roam_candidate_info_event(ap, i); 3164 ap++; 3165 } 3166 } 3167 3168 /** 3169 * cm_get_roam_scan_type_str() - Get the string for roam scan type 3170 * @roam_scan_type: roam scan type coming from fw via 3171 * wmi_roam_scan_info tlv 3172 * 3173 * Return: Meaningful string for roam scan type 3174 */ 3175 static char *cm_get_roam_scan_type_str(uint32_t roam_scan_type) 3176 { 3177 switch (roam_scan_type) { 3178 case ROAM_STATS_SCAN_TYPE_PARTIAL: 3179 return "PARTIAL"; 3180 case ROAM_STATS_SCAN_TYPE_FULL: 3181 return "FULL"; 3182 case ROAM_STATS_SCAN_TYPE_NO_SCAN: 3183 return "NO SCAN"; 3184 case ROAM_STATS_SCAN_TYPE_HIGHER_BAND_5GHZ_6GHZ: 3185 return "Higher Band: 5 GHz + 6 GHz"; 3186 case ROAM_STATS_SCAN_TYPE_HIGHER_BAND_6GHZ: 3187 return "Higher Band : 6 GHz"; 3188 default: 3189 return "UNKNOWN"; 3190 } 3191 } 3192 3193 /** 3194 * cm_roam_stats_print_scan_info - Print the roam scan details and candidate AP 3195 * details 3196 * @psoc: psoc common object 3197 * @scan: Pointer to the received tlv after sanitization 3198 * @vdev_id: Vdev ID 3199 * @trigger: Roam scan trigger reason 3200 * @timestamp: Host timestamp in millisecs 3201 * 3202 * Prinst the roam scan details with time of the day when the scan was 3203 * triggered and roam candidate AP with score details 3204 * 3205 * Return: None 3206 */ 3207 static void 3208 cm_roam_stats_print_scan_info(struct wlan_objmgr_psoc *psoc, 3209 struct wmi_roam_scan_data *scan, uint8_t vdev_id, 3210 uint32_t trigger, uint32_t timestamp) 3211 { 3212 uint16_t num_ch = scan->num_chan; 3213 uint16_t buf_cons = 0, buf_left = ROAM_CHANNEL_BUF_SIZE; 3214 uint8_t i; 3215 char *buf, *buf1, *tmp; 3216 char time[TIME_STRING_LEN]; 3217 3218 /* Update roam scan info to userspace */ 3219 cm_roam_scan_info_event(psoc, scan, vdev_id); 3220 3221 buf = qdf_mem_malloc(ROAM_CHANNEL_BUF_SIZE); 3222 if (!buf) 3223 return; 3224 3225 tmp = buf; 3226 /* For partial scans, print the channel info */ 3227 if (scan->type == ROAM_STATS_SCAN_TYPE_PARTIAL) { 3228 buf_cons = qdf_snprint(tmp, buf_left, "{"); 3229 buf_left -= buf_cons; 3230 tmp += buf_cons; 3231 3232 for (i = 0; i < num_ch; i++) { 3233 buf_cons = qdf_snprint(tmp, buf_left, "%d ", 3234 scan->chan_freq[i]); 3235 buf_left -= buf_cons; 3236 tmp += buf_cons; 3237 } 3238 buf_cons = qdf_snprint(tmp, buf_left, "}"); 3239 buf_left -= buf_cons; 3240 tmp += buf_cons; 3241 } 3242 3243 buf1 = qdf_mem_malloc(ROAM_FAILURE_BUF_SIZE); 3244 if (!buf1) { 3245 qdf_mem_free(buf); 3246 return; 3247 } 3248 3249 if (trigger == ROAM_TRIGGER_REASON_LOW_RSSI || 3250 trigger == ROAM_TRIGGER_REASON_PERIODIC) 3251 qdf_snprint(buf1, ROAM_FAILURE_BUF_SIZE, 3252 "next_rssi_threshold: %d dBm", 3253 scan->next_rssi_threshold); 3254 3255 mlme_get_converted_timestamp(timestamp, time); 3256 mlme_nofl_info("%s [ROAM_SCAN]: VDEV[%d] Scan_type: %s %s %s", 3257 time, vdev_id, cm_get_roam_scan_type_str(scan->type), 3258 buf1, buf); 3259 cm_stats_log_roam_scan_candidates(scan->ap, scan->num_ap); 3260 3261 qdf_mem_free(buf); 3262 qdf_mem_free(buf1); 3263 } 3264 3265 /** 3266 * cm_roam_stats_print_roam_result() - Print roam result related info 3267 * @psoc: Pointer to psoc object 3268 * @trigger: roam trigger information 3269 * @res: Roam result structure pointer 3270 * @scan_data: scan data 3271 * @vdev_id: vdev id 3272 * 3273 * Print roam result and failure reason if roaming failed. 3274 * 3275 * Return: None 3276 */ 3277 static void 3278 cm_roam_stats_print_roam_result(struct wlan_objmgr_psoc *psoc, 3279 struct wmi_roam_trigger_info *trigger, 3280 struct wmi_roam_result *res, 3281 struct wmi_roam_scan_data *scan_data, 3282 uint8_t vdev_id) 3283 { 3284 char *buf; 3285 char time[TIME_STRING_LEN]; 3286 QDF_STATUS status; 3287 3288 /* Update roam result info to userspace */ 3289 cm_roam_result_info_event(psoc, trigger, res, scan_data, vdev_id); 3290 3291 buf = qdf_mem_malloc(ROAM_FAILURE_BUF_SIZE); 3292 if (!buf) 3293 return; 3294 3295 if (res->status == 1) 3296 qdf_snprint(buf, ROAM_FAILURE_BUF_SIZE, "Reason: %s", 3297 mlme_get_roam_fail_reason_str(res->fail_reason)); 3298 3299 mlme_get_converted_timestamp(res->timestamp, time); 3300 3301 if (res->fail_reason == ROAM_FAIL_REASON_CURR_AP_STILL_OK) 3302 mlme_nofl_info("%s [ROAM_RESULT]: VDEV[%d] %s", 3303 time, vdev_id, buf); 3304 else 3305 mlme_nofl_info("%s [ROAM_RESULT]: VDEV[%d] %s %s", 3306 time, vdev_id, 3307 mlme_get_roam_status_str(res->status), buf); 3308 qdf_mem_free(buf); 3309 3310 status = wlan_cm_update_roam_states(psoc, vdev_id, res->fail_reason, 3311 ROAM_FAIL_REASON); 3312 if (QDF_IS_STATUS_ERROR(status)) 3313 mlme_err("failed to update rt stats roam fail reason"); 3314 } 3315 3316 #define WLAN_ROAM_11KV_REQ_TYPE_BTM 1 3317 #define WLAN_ROAM_11KV_REQ_TYPE_NEIGH_RPT 2 3318 3319 /** 3320 * cm_roam_stats_print_11kv_info - Print neighbor report/BTM related data 3321 * @psoc: Pointer to psoc object 3322 * @neigh_rpt: Pointer to the extracted TLV structure 3323 * @vdev_id: Vdev ID 3324 * 3325 * Print BTM/neighbor report info that is sent by firmware after 3326 * connection/roaming to an AP. 3327 * 3328 * Return: none 3329 */ 3330 static void 3331 cm_roam_stats_print_11kv_info(struct wlan_objmgr_psoc *psoc, 3332 struct wmi_neighbor_report_data *neigh_rpt, 3333 uint8_t vdev_id) 3334 { 3335 char time[TIME_STRING_LEN], time1[TIME_STRING_LEN]; 3336 char *buf, *tmp; 3337 uint8_t type = neigh_rpt->req_type, i; 3338 uint16_t buf_left = ROAM_CHANNEL_BUF_SIZE, buf_cons; 3339 uint8_t num_ch = neigh_rpt->num_freq; 3340 struct wlan_objmgr_vdev *vdev; 3341 3342 if (!type) 3343 return; 3344 3345 buf = qdf_mem_malloc(ROAM_CHANNEL_BUF_SIZE); 3346 if (!buf) 3347 return; 3348 3349 tmp = buf; 3350 if (num_ch) { 3351 buf_cons = qdf_snprint(tmp, buf_left, "{ "); 3352 buf_left -= buf_cons; 3353 tmp += buf_cons; 3354 3355 for (i = 0; i < num_ch; i++) { 3356 buf_cons = qdf_snprint(tmp, buf_left, "%d ", 3357 neigh_rpt->freq[i]); 3358 buf_left -= buf_cons; 3359 tmp += buf_cons; 3360 } 3361 3362 buf_cons = qdf_snprint(tmp, buf_left, "}"); 3363 buf_left -= buf_cons; 3364 tmp += buf_cons; 3365 } 3366 3367 mlme_get_converted_timestamp(neigh_rpt->req_time, time); 3368 mlme_nofl_info("%s [%s] VDEV[%d]", time, 3369 (type == WLAN_ROAM_11KV_REQ_TYPE_BTM) ? 3370 "BTM_QUERY" : "NEIGH_RPT_REQ", vdev_id); 3371 3372 if (type == WLAN_ROAM_11KV_REQ_TYPE_BTM) 3373 cm_roam_btm_query_event(neigh_rpt, vdev_id); 3374 else if (type == WLAN_ROAM_11KV_REQ_TYPE_NEIGH_RPT) { 3375 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 3376 WLAN_MLME_OBJMGR_ID); 3377 if (!vdev) { 3378 mlme_err("vdev pointer not found"); 3379 goto out; 3380 } 3381 3382 cm_roam_neigh_rpt_req_event(neigh_rpt, vdev); 3383 3384 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 3385 } 3386 3387 if (neigh_rpt->resp_time) { 3388 mlme_get_converted_timestamp(neigh_rpt->resp_time, time1); 3389 mlme_nofl_info("%s [%s] VDEV[%d] %s", time1, 3390 (type == WLAN_ROAM_11KV_REQ_TYPE_BTM) ? 3391 "BTM_REQ" : "NEIGH_RPT_RSP", 3392 vdev_id, 3393 (num_ch > 0) ? buf : "NO Ch update"); 3394 3395 if (type == WLAN_ROAM_11KV_REQ_TYPE_NEIGH_RPT) 3396 cm_roam_neigh_rpt_resp_event(neigh_rpt, vdev_id); 3397 3398 } else { 3399 mlme_nofl_info("%s No response received from AP", 3400 (type == WLAN_ROAM_11KV_REQ_TYPE_BTM) ? 3401 "BTM" : "NEIGH_RPT"); 3402 } 3403 out: 3404 qdf_mem_free(buf); 3405 } 3406 3407 static char * 3408 cm_get_frame_subtype_str(enum mgmt_subtype frame_subtype) 3409 { 3410 switch (frame_subtype) { 3411 case MGMT_SUBTYPE_ASSOC_REQ: 3412 return "ASSOC"; 3413 case MGMT_SUBTYPE_ASSOC_RESP: 3414 return "ASSOC"; 3415 case MGMT_SUBTYPE_REASSOC_REQ: 3416 return "REASSOC"; 3417 case MGMT_SUBTYPE_REASSOC_RESP: 3418 return "REASSOC"; 3419 case MGMT_SUBTYPE_DISASSOC: 3420 return "DISASSOC"; 3421 case MGMT_SUBTYPE_AUTH: 3422 return "AUTH"; 3423 case MGMT_SUBTYPE_DEAUTH: 3424 return "DEAUTH"; 3425 default: 3426 break; 3427 } 3428 3429 return "Invalid frm"; 3430 } 3431 3432 #define WLAN_SAE_AUTH_ALGO 3 3433 static void 3434 cm_roam_print_frame_info(struct wlan_objmgr_psoc *psoc, 3435 struct wlan_objmgr_vdev *vdev, 3436 struct roam_frame_stats *frame_data, 3437 struct wmi_roam_scan_data *scan_data, 3438 struct wmi_roam_result *result) 3439 { 3440 struct roam_frame_info *frame_info; 3441 char time[TIME_STRING_LEN]; 3442 uint8_t i, vdev_id, cached_vdev_id; 3443 3444 if (!frame_data->num_frame) 3445 return; 3446 3447 vdev_id = wlan_vdev_get_id(vdev); 3448 3449 for (i = 0; i < frame_data->num_frame; i++) { 3450 cached_vdev_id = vdev_id; 3451 frame_info = &frame_data->frame_info[i]; 3452 /* 3453 * For SAE auth frame, since host sends the authentication 3454 * frames, its cached in the TX/RX path and the cached 3455 * frames are printed from here. 3456 */ 3457 if (frame_info->auth_algo == WLAN_SAE_AUTH_ALGO && 3458 wlan_is_sae_auth_log_present_for_bssid(psoc, 3459 &frame_info->bssid, 3460 &cached_vdev_id)) { 3461 wlan_print_cached_sae_auth_logs(psoc, 3462 &frame_info->bssid, 3463 cached_vdev_id); 3464 continue; 3465 } 3466 3467 qdf_mem_zero(time, TIME_STRING_LEN); 3468 mlme_get_converted_timestamp(frame_info->timestamp, time); 3469 3470 /* Log the auth & reassoc frames here to driver log */ 3471 if (frame_info->type != ROAM_FRAME_INFO_FRAME_TYPE_EXT) 3472 mlme_nofl_info("%s [%s%s] VDEV[%d] bssid: " QDF_MAC_ADDR_FMT " status:%d seq_num:%d", 3473 time, 3474 cm_get_frame_subtype_str(frame_info->subtype), 3475 frame_info->subtype == MGMT_SUBTYPE_AUTH ? 3476 (frame_info->is_rsp ? " RX" : " TX") : "", 3477 vdev_id, 3478 QDF_MAC_ADDR_REF(frame_info->bssid.bytes), 3479 frame_info->status_code, 3480 frame_info->seq_num); 3481 3482 cm_roam_mgmt_frame_event(vdev, frame_info, scan_data, result); 3483 } 3484 } 3485 3486 void cm_report_roam_rt_stats(struct wlan_objmgr_psoc *psoc, 3487 uint8_t vdev_id, 3488 enum roam_rt_stats_type events, 3489 struct roam_stats_event *roam_info, 3490 uint32_t value, uint8_t idx, uint32_t reason) 3491 { 3492 struct roam_stats_event *roam_event = NULL; 3493 3494 if (!wlan_cm_get_roam_rt_stats(psoc, ROAM_RT_STATS_ENABLE)) { 3495 mlme_debug("Roam events stats is disabled"); 3496 return; 3497 } 3498 3499 switch (events) { 3500 case ROAM_RT_STATS_TYPE_SCAN_STATE: 3501 roam_event = qdf_mem_malloc(sizeof(*roam_event)); 3502 if (!roam_event) 3503 return; 3504 3505 if (value == WMI_ROAM_NOTIF_SCAN_START) { 3506 roam_event->roam_event_param.roam_scan_state = 3507 QCA_WLAN_VENDOR_ROAM_SCAN_STATE_START; 3508 if (reason) { 3509 roam_event->trigger[idx].present = true; 3510 roam_event->trigger[idx].trigger_reason = 3511 reason; 3512 } 3513 } else if (value == WMI_ROAM_NOTIF_SCAN_END) { 3514 roam_event->roam_event_param.roam_scan_state = 3515 QCA_WLAN_VENDOR_ROAM_SCAN_STATE_END; 3516 } 3517 3518 mlme_debug("Invoke HDD roam events callback for roam " 3519 "scan notif"); 3520 roam_event->vdev_id = vdev_id; 3521 mlme_cm_osif_roam_rt_stats(roam_event, idx); 3522 qdf_mem_free(roam_event); 3523 break; 3524 case ROAM_RT_STATS_TYPE_INVOKE_FAIL_REASON: 3525 roam_event = qdf_mem_malloc(sizeof(*roam_event)); 3526 if (!roam_event) 3527 return; 3528 3529 roam_event->roam_event_param.roam_invoke_fail_reason = value; 3530 3531 mlme_debug("Invoke HDD roam events callback for roam " 3532 "invoke fail"); 3533 roam_event->vdev_id = vdev_id; 3534 mlme_cm_osif_roam_rt_stats(roam_event, idx); 3535 qdf_mem_free(roam_event); 3536 break; 3537 case ROAM_RT_STATS_TYPE_ROAM_SCAN_INFO: 3538 if (roam_info->scan[idx].present || 3539 roam_info->trigger[idx].present || 3540 (roam_info->result[idx].present && 3541 roam_info->result[idx].fail_reason)) { 3542 mlme_debug("Invoke HDD roam events callback for roam " 3543 "stats event"); 3544 roam_info->vdev_id = vdev_id; 3545 mlme_cm_osif_roam_rt_stats(roam_info, idx); 3546 } 3547 break; 3548 default: 3549 break; 3550 } 3551 } 3552 3553 /** 3554 * cm_roam_handle_btm_stats() - Handle BTM related logging roam stats. 3555 * @psoc: psoc pointer 3556 * @stats_info: Pointer to the roam stats 3557 * @i: TLV indev for BTM roam trigger 3558 * @rem_tlv_len: Remaining TLV length 3559 * 3560 * Return: None 3561 */ 3562 static void 3563 cm_roam_handle_btm_stats(struct wlan_objmgr_psoc *psoc, 3564 struct roam_stats_event *stats_info, uint8_t i, 3565 uint8_t *rem_tlv_len) 3566 { 3567 bool log_btm_frames_only = false; 3568 struct wlan_objmgr_vdev *vdev; 3569 3570 if (stats_info->data_11kv[i].present) 3571 cm_roam_stats_print_11kv_info(psoc, &stats_info->data_11kv[i], 3572 stats_info->vdev_id); 3573 3574 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, 3575 stats_info->vdev_id, 3576 WLAN_MLME_CM_ID); 3577 if (!vdev) { 3578 mlme_err("vdev: %d vdev not found", stats_info->vdev_id); 3579 return; 3580 } 3581 3582 /* 3583 * If roam trigger is BTM and roam scan type is no scan then 3584 * the roam stats event is for BTM frames logging. 3585 * So log the BTM frames alone and return. 3586 */ 3587 if (stats_info->scan[i].present && 3588 stats_info->scan[i].type == ROAM_STATS_SCAN_TYPE_NO_SCAN) { 3589 cm_roam_btm_req_event(&stats_info->trigger[i].btm_trig_data, 3590 &stats_info->trigger[i], 3591 stats_info->vdev_id, false); 3592 log_btm_frames_only = true; 3593 goto log_btm_frames_only; 3594 } 3595 3596 if (stats_info->trigger[i].present) { 3597 bool is_full_scan = stats_info->scan[i].present && 3598 stats_info->scan[i].type; 3599 3600 /* BTM request diag log event will be sent from inside below */ 3601 cm_roam_stats_print_trigger_info(psoc, &stats_info->trigger[i], 3602 &stats_info->scan[i], 3603 stats_info->vdev_id, 3604 is_full_scan); 3605 3606 if (stats_info->scan[i].present) 3607 cm_roam_stats_print_scan_info( 3608 psoc, &stats_info->scan[i], 3609 stats_info->vdev_id, 3610 stats_info->trigger[i].trigger_reason, 3611 stats_info->trigger[i].timestamp); 3612 } 3613 3614 if (stats_info->result[i].present) 3615 cm_roam_stats_print_roam_result(psoc, 3616 &stats_info->trigger[i], 3617 &stats_info->result[i], 3618 &stats_info->scan[i], 3619 stats_info->vdev_id); 3620 3621 if (stats_info->frame_stats[i].num_frame) 3622 cm_roam_print_frame_info(psoc, vdev, 3623 &stats_info->frame_stats[i], 3624 &stats_info->scan[i], 3625 &stats_info->result[i]); 3626 3627 log_btm_frames_only: 3628 3629 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 3630 3631 /* 3632 * Print BTM resp TLV info (wmi_roam_btm_response_info) only 3633 * when trigger reason is BTM or WTC_BTM. As for other roam 3634 * triggers this TLV contains zeros, so host should not print. 3635 */ 3636 if (stats_info->btm_rsp[i].present && stats_info->trigger[i].present && 3637 (stats_info->trigger[i].trigger_reason == ROAM_TRIGGER_REASON_BTM || 3638 stats_info->trigger[i].trigger_reason == 3639 ROAM_TRIGGER_REASON_WTC_BTM)) 3640 cm_roam_stats_print_btm_rsp_info(&stats_info->trigger[i], 3641 &stats_info->btm_rsp[i], 3642 stats_info->vdev_id, false); 3643 3644 if (log_btm_frames_only) 3645 return; 3646 3647 if (stats_info->roam_init_info[i].present) 3648 cm_roam_stats_print_roam_initial_info( 3649 &stats_info->roam_init_info[i], 3650 stats_info->vdev_id); 3651 3652 if (stats_info->roam_msg_info && stats_info->roam_msg_info[i].present && 3653 i < stats_info->num_roam_msg_info) { 3654 *rem_tlv_len = *rem_tlv_len + 1; 3655 cm_roam_stats_print_roam_msg_info( 3656 &stats_info->roam_msg_info[i], 3657 stats_info->vdev_id); 3658 } 3659 3660 cm_report_roam_rt_stats(psoc, stats_info->vdev_id, 3661 ROAM_RT_STATS_TYPE_ROAM_SCAN_INFO, 3662 stats_info, 0, i, 0); 3663 } 3664 3665 #ifdef WLAN_FEATURE_ROAM_INFO_STATS 3666 void mlme_cm_free_roam_stats_info(mlme_vdev_ext_t *ext_hdl) 3667 { 3668 uint32_t roam_cache_num; 3669 3670 roam_cache_num = ext_hdl->roam_cache_num; 3671 3672 if (roam_cache_num == 0) { 3673 mlme_debug("enhanced roam disable, no need free memory"); 3674 return; 3675 } 3676 3677 qdf_mutex_destroy(&ext_hdl->roam_rd_wr_lock); 3678 qdf_mem_free(ext_hdl->roam_info); 3679 ext_hdl->roam_info = NULL; 3680 } 3681 3682 void 3683 mlme_cm_alloc_roam_stats_info(struct vdev_mlme_obj *vdev_mlme) 3684 { 3685 uint32_t cache_num; 3686 struct wlan_objmgr_psoc *psoc; 3687 QDF_STATUS status; 3688 3689 if (!vdev_mlme->ext_vdev_ptr) { 3690 mlme_err("vdev legacy private object is NULL"); 3691 return; 3692 } 3693 3694 psoc = wlan_vdev_get_psoc(vdev_mlme->vdev); 3695 if (!psoc) { 3696 mlme_err("Invalid PSOC"); 3697 return; 3698 } 3699 status = wlan_mlme_get_roam_info_stats_num(psoc, &cache_num); 3700 if (QDF_IS_STATUS_ERROR(status)) { 3701 mlme_err("failed to get groam_info_stats_num"); 3702 return; 3703 } 3704 3705 if (cache_num == 0) { 3706 mlme_err("groam_info_stats_num = 0, not support enhanced roam"); 3707 return; 3708 } 3709 3710 if (vdev_mlme->ext_vdev_ptr->roam_info) { 3711 mlme_debug("mlme_priv->enhance_roam_info already malloced"); 3712 return; 3713 } 3714 3715 vdev_mlme->ext_vdev_ptr->roam_info = 3716 qdf_mem_malloc(cache_num * sizeof(struct enhance_roam_info)); 3717 if (!vdev_mlme->ext_vdev_ptr->roam_info) 3718 return; 3719 3720 vdev_mlme->ext_vdev_ptr->roam_cache_num = cache_num; 3721 vdev_mlme->ext_vdev_ptr->roam_write_index = 0; 3722 qdf_mutex_create(&vdev_mlme->ext_vdev_ptr->roam_rd_wr_lock); 3723 } 3724 3725 /** 3726 * wlan_cm_update_roam_trigger_info() - API to update roam trigger info 3727 * @mlme_priv: Pointer to vdev mlme legacy priv struct 3728 * @data: Data from target_if wmi event 3729 * 3730 * Get roam trigger info from target_if wmi event and save in vdev mlme ring 3731 * buffer, it is required that the mlme_priv->roam_rd_wr_lock be held before 3732 * this API is called 3733 * 3734 * Return: void 3735 */ 3736 static void 3737 wlan_cm_update_roam_trigger_info(struct mlme_legacy_priv *mlme_priv, 3738 struct wmi_roam_trigger_info *data) 3739 { 3740 uint32_t trigger_reason; 3741 uint32_t index; 3742 struct enhance_roam_info *info; 3743 3744 index = mlme_priv->roam_write_index; 3745 info = &mlme_priv->roam_info[index]; 3746 3747 info->trigger.timestamp = data->timestamp; 3748 info->trigger.trigger_reason = data->trigger_reason; 3749 trigger_reason = data->trigger_reason; 3750 3751 mlme_debug("roam trigger info: timestamp:%llu, reason:%u,index:%u", 3752 info->trigger.timestamp, 3753 info->trigger.trigger_reason, index); 3754 3755 switch (trigger_reason) { 3756 case ROAM_TRIGGER_REASON_PER: 3757 info->trigger.condition.roam_per.tx_rate_thresh_percent = 3758 data->per_trig_data.tx_rate_thresh_percent; 3759 info->trigger.condition.roam_per.tx_rate_thresh_percent = 3760 data->per_trig_data.tx_rate_thresh_percent; 3761 mlme_debug("roam per: rx:%u, tx:%u", 3762 data->per_trig_data.rx_rate_thresh_percent, 3763 data->per_trig_data.tx_rate_thresh_percent); 3764 break; 3765 case ROAM_TRIGGER_REASON_BMISS: 3766 info->trigger.condition.roam_bmiss.final_bmiss_cnt = 3767 data->bmiss_trig_data.final_bmiss_cnt; 3768 info->trigger.condition.roam_bmiss.consecutive_bmiss_cnt = 3769 data->bmiss_trig_data.consecutive_bmiss_cnt; 3770 info->trigger.condition.roam_bmiss.qos_null_success = 3771 data->bmiss_trig_data.qos_null_success; 3772 mlme_debug("roam bmiss: final:%u, consecutive:%u, qos:%u", 3773 data->bmiss_trig_data.final_bmiss_cnt, 3774 data->bmiss_trig_data.consecutive_bmiss_cnt, 3775 data->bmiss_trig_data.qos_null_success); 3776 break; 3777 case ROAM_TRIGGER_REASON_LOW_RSSI: 3778 info->trigger.condition.roam_poor_rssi.current_rssi = 3779 data->low_rssi_trig_data.current_rssi; 3780 info->trigger.condition.roam_poor_rssi.roam_rssi_threshold = 3781 data->low_rssi_trig_data.roam_rssi_threshold; 3782 info->trigger.condition.roam_poor_rssi.rx_linkspeed_status = 3783 data->low_rssi_trig_data.rx_linkspeed_status; 3784 mlme_debug("roam low rssi: rssi:%d, rssi_th:%d, rx_linkspeed:%u", 3785 data->low_rssi_trig_data.current_rssi, 3786 data->low_rssi_trig_data.roam_rssi_threshold, 3787 data->low_rssi_trig_data.rx_linkspeed_status); 3788 break; 3789 case ROAM_TRIGGER_REASON_HIGH_RSSI: 3790 info->trigger.condition.roam_better_rssi.current_rssi = 3791 data->hi_rssi_trig_data.current_rssi; 3792 info->trigger.condition.roam_better_rssi.hi_rssi_threshold = 3793 data->hi_rssi_trig_data.hirssi_threshold; 3794 mlme_debug("roam better rssi: cu_rssi:%d, hi_rssi_th:%d", 3795 data->hi_rssi_trig_data.current_rssi, 3796 data->hi_rssi_trig_data.hirssi_threshold); 3797 break; 3798 case ROAM_TRIGGER_REASON_PERIODIC: 3799 info->trigger.condition.roam_periodic.periodic_timer_ms = 3800 data->periodic_trig_data.periodic_timer_ms; 3801 mlme_debug("roam periodic: periodic_timer:%u", 3802 data->periodic_trig_data.periodic_timer_ms); 3803 break; 3804 3805 case ROAM_TRIGGER_REASON_DENSE: 3806 info->trigger.condition.roam_congestion.rx_tput = 3807 data->congestion_trig_data.rx_tput; 3808 info->trigger.condition.roam_congestion.tx_tput = 3809 data->congestion_trig_data.tx_tput; 3810 info->trigger.condition.roam_congestion.roamable_count = 3811 data->congestion_trig_data.roamable_count; 3812 mlme_debug("roam dense: rx_tput:%u, tx_tput:%u, roamable %u", 3813 data->congestion_trig_data.rx_tput, 3814 data->congestion_trig_data.tx_tput, 3815 data->congestion_trig_data.roamable_count); 3816 break; 3817 case ROAM_TRIGGER_REASON_BACKGROUND: 3818 info->trigger.condition.roam_background.current_rssi = 3819 data->background_trig_data.current_rssi; 3820 info->trigger.condition.roam_background.data_rssi = 3821 data->background_trig_data.data_rssi; 3822 info->trigger.condition.roam_background.data_rssi_threshold = 3823 data->background_trig_data.data_rssi_threshold; 3824 mlme_debug("roam background: rssi:%d, datarssi:%d, rssi_th %d", 3825 data->background_trig_data.current_rssi, 3826 data->background_trig_data.data_rssi, 3827 data->background_trig_data.data_rssi_threshold); 3828 break; 3829 case ROAM_TRIGGER_REASON_FORCED: 3830 info->trigger.condition.roam_user_trigger.invoke_reason = 3831 data->user_trig_data.invoke_reason; 3832 mlme_debug("roam force: invoke_reason:%u", 3833 data->user_trig_data.invoke_reason); 3834 break; 3835 case ROAM_TRIGGER_REASON_BTM: 3836 info->trigger.condition.roam_btm.btm_request_mode = 3837 data->btm_trig_data.btm_request_mode; 3838 info->trigger.condition.roam_btm.disassoc_imminent_timer = 3839 data->btm_trig_data.disassoc_timer; 3840 info->trigger.condition.roam_btm.validity_internal = 3841 data->btm_trig_data.validity_interval; 3842 info->trigger.condition.roam_btm.candidate_list_count = 3843 data->btm_trig_data.candidate_list_count; 3844 info->trigger.condition.roam_btm.btm_response_status_code = 3845 data->btm_trig_data.btm_resp_status; 3846 info->trigger.condition.roam_btm.btm_bss_termination_timeout = 3847 data->btm_trig_data.btm_bss_termination_timeout; 3848 info->trigger.condition.roam_btm.btm_mbo_assoc_retry_timeout = 3849 data->btm_trig_data.btm_mbo_assoc_retry_timeout; 3850 info->trigger.condition.roam_btm.btm_req_dialog_token = 3851 (uint8_t)data->btm_trig_data.token; 3852 mlme_debug("roam btm: %u %u %u %u %u %u %u %u", 3853 data->btm_trig_data.btm_request_mode, 3854 data->btm_trig_data.disassoc_timer, 3855 data->btm_trig_data.validity_interval, 3856 data->btm_trig_data.candidate_list_count, 3857 data->btm_trig_data.btm_resp_status, 3858 data->btm_trig_data.btm_bss_termination_timeout, 3859 data->btm_trig_data.btm_mbo_assoc_retry_timeout, 3860 data->btm_trig_data.token); 3861 break; 3862 case ROAM_TRIGGER_REASON_BSS_LOAD: 3863 info->trigger.condition.roam_bss_load.cu_load = 3864 (uint8_t)data->cu_trig_data.cu_load; 3865 mlme_debug("roam bss_load: cu_load:%u", 3866 data->cu_trig_data.cu_load); 3867 break; 3868 case ROAM_TRIGGER_REASON_DEAUTH: 3869 info->trigger.condition.roam_disconnection.deauth_type = 3870 (uint8_t)data->deauth_trig_data.type; 3871 info->trigger.condition.roam_disconnection.deauth_reason = 3872 (uint16_t)data->deauth_trig_data.reason; 3873 mlme_debug("roam disconnection: type:%u reason:%u", 3874 data->deauth_trig_data.type, 3875 data->deauth_trig_data.reason); 3876 break; 3877 case ROAM_TRIGGER_REASON_STA_KICKOUT: 3878 info->trigger.condition.roam_tx_failures.kickout_threshold = 3879 data->tx_failures_trig_data.kickout_threshold; 3880 info->trigger.condition.roam_tx_failures.kickout_reason = 3881 data->tx_failures_trig_data.kickout_reason; 3882 mlme_debug("roam tx_failures: kickout_th:%u kickout_reason:%u", 3883 data->tx_failures_trig_data.kickout_threshold, 3884 data->tx_failures_trig_data.kickout_reason); 3885 break; 3886 case ROAM_TRIGGER_REASON_IDLE: 3887 case ROAM_TRIGGER_REASON_UNIT_TEST: 3888 case ROAM_TRIGGER_REASON_MAWC: 3889 default: 3890 break; 3891 } 3892 3893 info->trigger.roam_scan_type = data->scan_type; 3894 info->trigger.roam_status = data->roam_status; 3895 mlme_debug("roam trigger info: scan_type:%u,status:%u", 3896 data->scan_type, data->roam_status); 3897 3898 if (info->trigger.roam_status) { 3899 info->trigger.roam_fail_reason = data->fail_reason; 3900 3901 if (data->abort_reason.abort_reason_code) { 3902 info->trigger.abort.abort_reason_code = 3903 data->abort_reason.abort_reason_code; 3904 info->trigger.abort.data_rssi = 3905 data->abort_reason.data_rssi; 3906 info->trigger.abort.data_rssi_threshold = 3907 data->abort_reason.data_rssi_threshold; 3908 info->trigger.abort.rx_linkspeed_status = 3909 data->abort_reason.rx_linkspeed_status; 3910 } 3911 3912 mlme_debug("abort:reason:%u,rssi:%d,rssit:%d,status:%u,fail:%u", 3913 info->trigger.abort.abort_reason_code, 3914 info->trigger.abort.data_rssi, 3915 info->trigger.abort.data_rssi_threshold, 3916 info->trigger.abort.rx_linkspeed_status, 3917 info->trigger.roam_fail_reason); 3918 } 3919 } 3920 3921 static uint32_t 3922 wlan_cm_get_roam_chn_dwell_time(struct wlan_objmgr_vdev *vdev, 3923 uint16_t freq, 3924 enum roam_scan_dwell_type dwell_type) 3925 { 3926 struct wlan_scan_obj *scan_obj; 3927 3928 scan_obj = wlan_vdev_get_scan_obj(vdev); 3929 if (!scan_obj) { 3930 mlme_err("scan_obj is NULL"); 3931 return 0; 3932 } 3933 3934 if (WLAN_REG_IS_24GHZ_CH_FREQ(freq)) { 3935 return scan_obj->scan_def.active_dwell_2g; 3936 } else if (WLAN_REG_IS_5GHZ_CH_FREQ(freq)) { 3937 if (dwell_type == WLAN_ROAM_DWELL_PASSIVE_TYPE) 3938 return scan_obj->scan_def.passive_dwell; 3939 else 3940 return scan_obj->scan_def.active_dwell; 3941 } else if (WLAN_REG_IS_6GHZ_CHAN_FREQ(freq)) { 3942 if (dwell_type == WLAN_ROAM_DWELL_PASSIVE_TYPE) 3943 return scan_obj->scan_def.passive_dwell_6g; 3944 else 3945 return scan_obj->scan_def.active_dwell_6g; 3946 } 3947 3948 return 0; 3949 } 3950 3951 /** 3952 * wlan_cm_update_roam_scan_info() - API to update roam scan info 3953 * @vdev: Pointer to vdev 3954 * @scan: Scan data from target_if wmi event 3955 * 3956 * Get roam scan info from target_if wmi event and save in vdev mlme ring 3957 * buffer, it is required that the mlme_priv->roam_rd_wr_lock be held before 3958 * this API is called 3959 * 3960 * Return: void 3961 */ 3962 static void 3963 wlan_cm_update_roam_scan_info(struct wlan_objmgr_vdev *vdev, 3964 struct wmi_roam_scan_data *scan) 3965 { 3966 struct mlme_legacy_priv *mlme_priv; 3967 struct enhance_roam_info *info; 3968 uint32_t freq; 3969 uint32_t dwell_type; 3970 uint32_t i, index; 3971 3972 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 3973 if (!mlme_priv) { 3974 mlme_err("vdev legacy private object is NULL"); 3975 return; 3976 } 3977 3978 index = mlme_priv->roam_write_index; 3979 info = &mlme_priv->roam_info[index]; 3980 info->scan.num_channels = scan->num_chan; 3981 3982 if (scan->num_chan) { 3983 for (i = 0; i < scan->num_chan; i++) { 3984 info->scan.roam_chn[i].chan_freq = 3985 scan->chan_freq[i]; 3986 info->scan.roam_chn[i].dwell_type = 3987 scan->dwell_type[i]; 3988 3989 freq = scan->chan_freq[i]; 3990 dwell_type = scan->dwell_type[i]; 3991 info->scan.roam_chn[i].max_dwell_time = 3992 wlan_cm_get_roam_chn_dwell_time(vdev, freq, 3993 dwell_type); 3994 3995 mlme_debug("freq %u dwell_type %u dwell_time:%u", 3996 freq, dwell_type, 3997 info->scan.roam_chn[i].max_dwell_time); 3998 } 3999 4000 info->scan.total_scan_time = 4001 scan->scan_complete_timestamp - 4002 info->trigger.timestamp; 4003 4004 mlme_debug("roam scan:chn_num:%u,com:%u,total_time:%u,index:%u", 4005 info->scan.num_channels, 4006 scan->scan_complete_timestamp, 4007 info->scan.total_scan_time, index); 4008 } 4009 } 4010 4011 /** 4012 * wlan_cm_roam_frame_subtype() - Convert roam host enum 4013 * @frame: Roam frame info 4014 * @frame_type: roam frame type 4015 * 4016 * Return: Roam frame type defined in host driver 4017 */ 4018 static enum eroam_frame_subtype 4019 wlan_cm_roam_frame_subtype(struct roam_frame_info *frame, uint8_t frame_type) 4020 { 4021 switch (frame_type) { 4022 case MGMT_SUBTYPE_AUTH: 4023 if (frame->is_rsp) 4024 return WLAN_ROAM_STATS_FRAME_SUBTYPE_AUTH_RESP; 4025 else 4026 return WLAN_ROAM_STATS_FRAME_SUBTYPE_AUTH_REQ; 4027 case MGMT_SUBTYPE_REASSOC_REQ: 4028 return WLAN_ROAM_STATS_FRAME_SUBTYPE_REASSOC_REQ; 4029 case MGMT_SUBTYPE_REASSOC_RESP: 4030 return WLAN_ROAM_STATS_FRAME_SUBTYPE_REASSOC_RESP; 4031 case ROAM_FRAME_SUBTYPE_M1: 4032 return WLAN_ROAM_STATS_FRAME_SUBTYPE_EAPOL_M1; 4033 case ROAM_FRAME_SUBTYPE_M2: 4034 return WLAN_ROAM_STATS_FRAME_SUBTYPE_EAPOL_M2; 4035 case ROAM_FRAME_SUBTYPE_M3: 4036 return WLAN_ROAM_STATS_FRAME_SUBTYPE_EAPOL_M3; 4037 case ROAM_FRAME_SUBTYPE_M4: 4038 return WLAN_ROAM_STATS_FRAME_SUBTYPE_EAPOL_M4; 4039 case ROAM_FRAME_SUBTYPE_GTK_M1: 4040 return WLAN_ROAM_STATS_FRAME_SUBTYPE_EAPOL_GTK_M1; 4041 case ROAM_FRAME_SUBTYPE_GTK_M2: 4042 return WLAN_ROAM_STATS_FRAME_SUBTYPE_EAPOL_GTK_M2; 4043 default: 4044 return WLAN_ROAM_STATS_FRAME_SUBTYPE_AUTH_REQ; 4045 } 4046 } 4047 4048 static bool 4049 wlan_cm_get_valid_frame_type(struct roam_frame_info *frame) 4050 { 4051 if (frame->subtype == MGMT_SUBTYPE_AUTH || 4052 frame->subtype == MGMT_SUBTYPE_REASSOC_REQ || 4053 frame->subtype == MGMT_SUBTYPE_REASSOC_RESP || 4054 frame->subtype == ROAM_FRAME_SUBTYPE_M1 || 4055 frame->subtype == ROAM_FRAME_SUBTYPE_M2 || 4056 frame->subtype == ROAM_FRAME_SUBTYPE_M3 || 4057 frame->subtype == ROAM_FRAME_SUBTYPE_M4) 4058 return true; 4059 else 4060 return false; 4061 } 4062 4063 /** 4064 * wlan_cm_update_roam_frame_info() - API to update roam frame info 4065 * @mlme_priv: Pointer to Pointer to vdev mlme legacy priv struct 4066 * @frame_data: Frame data from target_if wmi event 4067 * 4068 * Get roam frame info from target_if wmi event and save in vdev mlme ring 4069 * buffer, it is required that the mlme_priv->roam_rd_wr_lock be held before 4070 * this API is called 4071 * 4072 * Return: void 4073 */ 4074 static void 4075 wlan_cm_update_roam_frame_info(struct mlme_legacy_priv *mlme_priv, 4076 struct roam_frame_stats *frame_data) 4077 { 4078 struct enhance_roam_info *info; 4079 uint32_t index, i, j = 0; 4080 uint8_t subtype; 4081 4082 index = mlme_priv->roam_write_index; 4083 info = &mlme_priv->roam_info[index]; 4084 4085 for (i = 0; i < frame_data->num_frame; i++) { 4086 if (!wlan_cm_get_valid_frame_type(&frame_data->frame_info[i])) 4087 continue; 4088 j++; 4089 if (j >= WLAN_ROAM_MAX_FRAME_INFO) 4090 break; 4091 /* 4092 * fill frame preauth req/rsp, reassoc req/rsp 4093 * and EAPOL-M1/M2/M3/M4 into roam buffer 4094 */ 4095 subtype = frame_data->frame_info[i].subtype; 4096 info->timestamp[j].frame_type = 4097 wlan_cm_roam_frame_subtype(&frame_data->frame_info[i], 4098 subtype); 4099 info->timestamp[j].timestamp = 4100 frame_data->frame_info[i].timestamp; 4101 info->timestamp[j].status = 4102 frame_data->frame_info[i].status_code; 4103 4104 qdf_mem_copy(info->timestamp[j].bssid.bytes, 4105 frame_data->frame_info[i].bssid.bytes, 4106 QDF_MAC_ADDR_SIZE); 4107 4108 mlme_debug("frame:idx:%u subtype:%x time:%llu status:%u AP BSSID" QDF_MAC_ADDR_FMT, 4109 j, info->timestamp[j].frame_type, 4110 info->timestamp[j].timestamp, 4111 info->timestamp[j].status, 4112 QDF_MAC_ADDR_REF(info->timestamp[j].bssid.bytes)); 4113 } 4114 } 4115 4116 /** 4117 * wlan_cm_clear_current_roam_stats_info() - API to clear roam stats buffer date 4118 * @mlme_priv: Pointer to Pointer to vdev mlme legacy priv struct 4119 * 4120 * clear the roam stats buffer data before write 4121 * 4122 * Return: void 4123 */ 4124 static void 4125 wlan_cm_clear_current_roam_stats_info(struct mlme_legacy_priv *mlme_priv) 4126 { 4127 uint32_t index; 4128 4129 index = mlme_priv->roam_write_index; 4130 qdf_mem_set(&mlme_priv->roam_info[index], 4131 sizeof(struct enhance_roam_info), 0); 4132 } 4133 4134 /** 4135 * wlan_cm_update_roam_bssid() - API to get roam stats AP BSSID 4136 * @mlme_priv: Pointer to Pointer to vdev mlme legacy priv struct 4137 * @scan: Scan data from target_if wmi event 4138 * 4139 * get AP BSSID from roam stats info which keep in scan data. 4140 * 4141 * Return: void 4142 */ 4143 static void 4144 wlan_cm_update_roam_bssid(struct mlme_legacy_priv *mlme_priv, 4145 struct wmi_roam_scan_data *scan) 4146 { 4147 struct enhance_roam_info *info; 4148 int16_t i; 4149 uint16_t index, scan_ap_idx; 4150 struct wmi_roam_candidate_info *ap = NULL; 4151 4152 if (scan->num_ap == 0) 4153 return; 4154 4155 scan_ap_idx = scan->num_ap - 1; 4156 ap = &scan->ap[scan_ap_idx]; 4157 4158 index = mlme_priv->roam_write_index; 4159 info = &mlme_priv->roam_info[index]; 4160 4161 /* For roam failed, we may get candidate ap list, and only 4162 * fetch the last candidate AP bssid. 4163 */ 4164 4165 for (i = scan_ap_idx; i >= 0; i--) { 4166 if (ap->type == WLAN_ROAM_SCAN_CURRENT_AP) 4167 qdf_mem_copy(info->scan.original_bssid.bytes, 4168 ap->bssid.bytes, 4169 QDF_MAC_ADDR_SIZE); 4170 else if (ap->type == WLAN_ROAM_SCAN_ROAMED_AP) 4171 qdf_mem_copy(info->scan.roamed_bssid.bytes, 4172 ap->bssid.bytes, 4173 QDF_MAC_ADDR_SIZE); 4174 else 4175 mlme_debug("unknown type:%u of AP", ap->type); 4176 ap--; 4177 } 4178 } 4179 4180 /** 4181 * wlan_cm_update_roam_stats_info() - API to update roam stats info 4182 * @psoc: Pointer to psoc 4183 * @stats_info: Roam stats event 4184 * @index: TLV index in roam stats event 4185 * 4186 * Get roam stats info from target_if wmi event and save in vdev mlme ring 4187 * buffer. 4188 * 4189 * Return: void 4190 */ 4191 static void 4192 wlan_cm_update_roam_stats_info(struct wlan_objmgr_psoc *psoc, 4193 struct roam_stats_event *stats_info, 4194 uint8_t index) 4195 { 4196 struct wlan_objmgr_vdev *vdev; 4197 struct mlme_legacy_priv *mlme_priv; 4198 4199 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, stats_info->vdev_id, 4200 WLAN_MLME_SB_ID); 4201 if (!vdev) { 4202 mlme_err("vdev%d: vdev object is NULL", stats_info->vdev_id); 4203 return; 4204 } 4205 4206 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 4207 if (!mlme_priv) { 4208 mlme_err("vdev legacy private object is NULL"); 4209 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID); 4210 return; 4211 } 4212 4213 if (mlme_priv->roam_cache_num == 0) { 4214 mlme_debug("Enhanced roam stats not supported"); 4215 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID); 4216 return; 4217 } 4218 4219 if (!mlme_priv->roam_info) { 4220 mlme_err("enhance_roam_info buffer is NULL"); 4221 return; 4222 } 4223 4224 qdf_mutex_acquire(&mlme_priv->roam_rd_wr_lock); 4225 4226 if (stats_info->trigger[index].present) { 4227 wlan_cm_clear_current_roam_stats_info(mlme_priv); 4228 wlan_cm_update_roam_trigger_info(mlme_priv, 4229 &stats_info->trigger[index]); 4230 if (stats_info->scan[index].present) 4231 wlan_cm_update_roam_scan_info(vdev, 4232 &stats_info->scan[index]); 4233 if (stats_info->frame_stats[index].num_frame) 4234 wlan_cm_update_roam_frame_info(mlme_priv, 4235 &stats_info->frame_stats[index]); 4236 if (stats_info->scan[index].present) 4237 wlan_cm_update_roam_bssid(mlme_priv, 4238 &stats_info->scan[index]); 4239 4240 mlme_priv->roam_write_index += 1; 4241 if (mlme_priv->roam_write_index == mlme_priv->roam_cache_num) 4242 mlme_priv->roam_write_index = 0; 4243 } 4244 qdf_mutex_release(&mlme_priv->roam_rd_wr_lock); 4245 4246 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID); 4247 } 4248 4249 QDF_STATUS 4250 wlan_cm_roam_stats_info_get(struct wlan_objmgr_vdev *vdev, 4251 struct enhance_roam_info **roam_info, 4252 uint32_t *roam_num) 4253 { 4254 struct mlme_legacy_priv *mlme_priv; 4255 uint32_t i, src, dst; 4256 uint32_t index = 0; 4257 uint32_t valid_cache_num; 4258 struct enhance_roam_info *eroam_info; 4259 4260 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 4261 if (!mlme_priv) { 4262 mlme_err("vdev legacy private object is NULL"); 4263 return QDF_STATUS_E_INVAL; 4264 } 4265 4266 if (mlme_priv->roam_cache_num == 0) { 4267 mlme_debug("Enhanced roam stats not supported"); 4268 return QDF_STATUS_E_NOSUPPORT; 4269 } 4270 4271 qdf_mutex_acquire(&mlme_priv->roam_rd_wr_lock); 4272 4273 /* get all roam event info from oldest to 4274 * latest by timestamp. 4275 */ 4276 valid_cache_num = mlme_priv->roam_cache_num; 4277 for (i = 0; i < mlme_priv->roam_cache_num; i++) { 4278 if (mlme_priv->roam_info[i].trigger.timestamp == 0) { 4279 valid_cache_num--; 4280 continue; 4281 } 4282 if (mlme_priv->roam_info[i].trigger.timestamp < 4283 mlme_priv->roam_info[index].trigger.timestamp) 4284 index = i; 4285 } 4286 mlme_debug("valid num: %d, start index:%u", valid_cache_num, index); 4287 4288 if (valid_cache_num == 0) { 4289 mlme_debug("Enhanced roam stats not existed"); 4290 qdf_mutex_release(&mlme_priv->roam_rd_wr_lock); 4291 return QDF_STATUS_E_INVAL; 4292 } 4293 4294 /* Send all driver cached roam info to user space one time, 4295 * and don't flush them, since they will be cover by 4296 * new roam event info. 4297 */ 4298 eroam_info = 4299 qdf_mem_malloc(valid_cache_num * 4300 sizeof(*eroam_info)); 4301 if (!eroam_info) { 4302 qdf_mutex_release(&mlme_priv->roam_rd_wr_lock); 4303 return QDF_STATUS_E_NOMEM; 4304 } 4305 4306 dst = 0; 4307 src = index; 4308 while (dst < valid_cache_num) { 4309 if (mlme_priv->roam_info[src].trigger.timestamp == 0) { 4310 src++; 4311 } else { 4312 eroam_info[dst] = mlme_priv->roam_info[src]; 4313 src++; 4314 dst++; 4315 } 4316 if (src == mlme_priv->roam_cache_num) 4317 src = 0; 4318 } 4319 4320 *roam_num = valid_cache_num; 4321 *roam_info = eroam_info; 4322 qdf_mutex_release(&mlme_priv->roam_rd_wr_lock); 4323 4324 return QDF_STATUS_SUCCESS; 4325 } 4326 #else 4327 static void 4328 wlan_cm_update_roam_stats_info(struct wlan_objmgr_psoc *psoc, 4329 struct roam_stats_event *stats_info, 4330 uint8_t index) 4331 { 4332 } 4333 #endif 4334 4335 QDF_STATUS 4336 cm_roam_stats_event_handler(struct wlan_objmgr_psoc *psoc, 4337 struct roam_stats_event *stats_info) 4338 { 4339 uint8_t i, rem_tlv = 0; 4340 bool is_wtc = false; 4341 QDF_STATUS status = QDF_STATUS_SUCCESS; 4342 struct wlan_objmgr_vdev *vdev; 4343 4344 if (!stats_info) 4345 return QDF_STATUS_E_FAILURE; 4346 4347 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, stats_info->vdev_id, 4348 WLAN_MLME_CM_ID); 4349 if (!vdev) { 4350 status = QDF_STATUS_E_FAILURE; 4351 goto out; 4352 } 4353 4354 for (i = 0; i < stats_info->num_tlv; i++) { 4355 if (stats_info->trigger[i].present) { 4356 bool is_full_scan = 4357 stats_info->scan[i].present && 4358 stats_info->scan[i].type; 4359 4360 if (stats_info->trigger[i].trigger_reason == 4361 ROAM_TRIGGER_REASON_BTM) { 4362 cm_roam_handle_btm_stats(psoc, stats_info, i, 4363 &rem_tlv); 4364 if (!stats_info->trigger[i].common_roam) 4365 continue; 4366 } 4367 4368 cm_roam_stats_print_trigger_info( 4369 psoc, &stats_info->trigger[i], 4370 &stats_info->scan[i], 4371 stats_info->vdev_id, is_full_scan); 4372 4373 if (stats_info->scan[i].present) 4374 cm_roam_stats_print_scan_info( 4375 psoc, &stats_info->scan[i], 4376 stats_info->vdev_id, 4377 stats_info->trigger[i].trigger_reason, 4378 stats_info->trigger[i].timestamp); 4379 } 4380 4381 if (stats_info->result[i].present) 4382 cm_roam_stats_print_roam_result(psoc, 4383 &stats_info->trigger[i], 4384 &stats_info->result[i], 4385 &stats_info->scan[i], 4386 stats_info->vdev_id); 4387 4388 if (stats_info->frame_stats[i].num_frame) 4389 cm_roam_print_frame_info(psoc, 4390 vdev, 4391 &stats_info->frame_stats[i], 4392 &stats_info->scan[i], 4393 &stats_info->result[i]); 4394 4395 wlan_cm_update_roam_stats_info(psoc, stats_info, i); 4396 4397 /* 4398 * Print BTM resp TLV info (wmi_roam_btm_response_info) only 4399 * when trigger reason is BTM or WTC_BTM. As for other roam 4400 * triggers this TLV contains zeros, so host should not print. 4401 */ 4402 if (stats_info->btm_rsp[i].present && 4403 stats_info->trigger[i].present && 4404 (stats_info->trigger[i].trigger_reason == 4405 ROAM_TRIGGER_REASON_BTM || 4406 stats_info->trigger[i].trigger_reason == 4407 ROAM_TRIGGER_REASON_WTC_BTM)) 4408 cm_roam_stats_print_btm_rsp_info( 4409 &stats_info->trigger[i], 4410 &stats_info->btm_rsp[i], 4411 stats_info->vdev_id, false); 4412 4413 if (stats_info->roam_init_info[i].present) 4414 cm_roam_stats_print_roam_initial_info( 4415 &stats_info->roam_init_info[i], 4416 stats_info->vdev_id); 4417 4418 if (stats_info->roam_msg_info && 4419 i < stats_info->num_roam_msg_info && 4420 stats_info->roam_msg_info[i].present) { 4421 rem_tlv++; 4422 cm_roam_stats_print_roam_msg_info( 4423 &stats_info->roam_msg_info[i], 4424 stats_info->vdev_id); 4425 } 4426 4427 cm_report_roam_rt_stats(psoc, stats_info->vdev_id, 4428 ROAM_RT_STATS_TYPE_ROAM_SCAN_INFO, 4429 stats_info, 0, i, 0); 4430 } 4431 4432 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 4433 4434 if (!stats_info->num_tlv) { 4435 /* 4436 * wmi_roam_trigger_reason TLV is sent only for userspace 4437 * logging of BTM/WTC frame without roam scans. 4438 */ 4439 4440 if (stats_info->data_11kv[0].present) 4441 cm_roam_stats_print_11kv_info(psoc, 4442 &stats_info->data_11kv[0], 4443 stats_info->vdev_id); 4444 4445 if (stats_info->trigger[0].present && 4446 (stats_info->trigger[0].trigger_reason == 4447 ROAM_TRIGGER_REASON_BTM || 4448 stats_info->trigger[0].trigger_reason == 4449 ROAM_TRIGGER_REASON_WTC_BTM)) { 4450 if (stats_info->trigger[0].trigger_reason == 4451 ROAM_TRIGGER_REASON_WTC_BTM) 4452 is_wtc = true; 4453 4454 cm_roam_btm_req_event(&stats_info->trigger[0].btm_trig_data, 4455 &stats_info->trigger[0], 4456 stats_info->vdev_id, is_wtc); 4457 } 4458 4459 if (stats_info->scan[0].present && 4460 stats_info->trigger[0].present) 4461 cm_roam_stats_print_scan_info(psoc, 4462 &stats_info->scan[0], 4463 stats_info->vdev_id, 4464 stats_info->trigger[0].trigger_reason, 4465 stats_info->trigger[0].timestamp); 4466 4467 if (stats_info->btm_rsp[0].present) 4468 cm_roam_stats_print_btm_rsp_info( 4469 &stats_info->trigger[0], 4470 &stats_info->btm_rsp[0], 4471 stats_info->vdev_id, 0); 4472 4473 /* 4474 * WTC BTM response with reason code 4475 * WTC print should be after the normal BTM 4476 * response print 4477 */ 4478 if (stats_info->trigger[0].present && 4479 stats_info->trigger[0].trigger_reason == 4480 ROAM_TRIGGER_REASON_WTC_BTM) 4481 cm_roam_btm_resp_event(&stats_info->trigger[0], NULL, 4482 stats_info->vdev_id, true); 4483 } 4484 4485 if (stats_info->roam_msg_info && stats_info->num_roam_msg_info && 4486 stats_info->num_roam_msg_info - rem_tlv) { 4487 for (i = 0; i < (stats_info->num_roam_msg_info-rem_tlv); i++) { 4488 if (stats_info->roam_msg_info[rem_tlv + i].present) 4489 cm_roam_stats_print_roam_msg_info( 4490 &stats_info->roam_msg_info[rem_tlv + i], 4491 stats_info->vdev_id); 4492 } 4493 } 4494 4495 out: 4496 wlan_clear_sae_auth_logs_cache(psoc, stats_info->vdev_id); 4497 qdf_mem_free(stats_info->roam_msg_info); 4498 qdf_mem_free(stats_info); 4499 4500 return status; 4501 } 4502 4503 bool wlan_cm_is_roam_sync_in_progress(struct wlan_objmgr_psoc *psoc, 4504 uint8_t vdev_id) 4505 { 4506 struct wlan_objmgr_vdev *vdev; 4507 bool ret; 4508 enum QDF_OPMODE opmode; 4509 4510 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 4511 WLAN_MLME_CM_ID); 4512 4513 if (!vdev) 4514 return false; 4515 4516 opmode = wlan_vdev_mlme_get_opmode(vdev); 4517 4518 if (opmode != QDF_STA_MODE) { 4519 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 4520 return false; 4521 } 4522 4523 ret = cm_is_vdev_roam_sync_inprogress(vdev); 4524 4525 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 4526 4527 return ret; 4528 } 4529 4530 void 4531 wlan_cm_set_roam_offload_bssid(struct wlan_objmgr_vdev *vdev, 4532 struct qdf_mac_addr *bssid) 4533 { 4534 struct mlme_legacy_priv *mlme_priv; 4535 struct qdf_mac_addr *mlme_bssid; 4536 4537 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 4538 if (!mlme_priv) { 4539 mlme_err("vdev legacy private object is NULL"); 4540 return; 4541 } 4542 4543 mlme_bssid = &(mlme_priv->cm_roam.sae_offload.bssid); 4544 4545 if (!bssid || qdf_is_macaddr_zero(bssid)) { 4546 mlme_err("NULL BSSID"); 4547 return; 4548 } 4549 qdf_mem_copy(mlme_bssid->bytes, bssid->bytes, QDF_MAC_ADDR_SIZE); 4550 } 4551 4552 void 4553 wlan_cm_get_roam_offload_bssid(struct wlan_objmgr_vdev *vdev, 4554 struct qdf_mac_addr *bssid) 4555 { 4556 struct mlme_legacy_priv *mlme_priv; 4557 struct qdf_mac_addr *mlme_bssid; 4558 4559 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 4560 if (!mlme_priv) { 4561 mlme_err("vdev legacy private object is NULL"); 4562 return; 4563 } 4564 4565 mlme_bssid = &(mlme_priv->cm_roam.sae_offload.bssid); 4566 4567 if (!bssid) 4568 return; 4569 qdf_mem_copy(bssid->bytes, mlme_bssid->bytes, QDF_MAC_ADDR_SIZE); 4570 } 4571 4572 void 4573 wlan_cm_set_roam_offload_ssid(struct wlan_objmgr_vdev *vdev, 4574 uint8_t *ssid, uint8_t len) 4575 { 4576 struct mlme_legacy_priv *mlme_priv; 4577 struct wlan_ssid *mlme_ssid; 4578 4579 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 4580 if (!mlme_priv) { 4581 mlme_err("vdev legacy private object is NULL"); 4582 return; 4583 } 4584 4585 mlme_ssid = &mlme_priv->cm_roam.sae_offload.ssid; 4586 4587 if (len > WLAN_SSID_MAX_LEN) 4588 len = WLAN_SSID_MAX_LEN; 4589 4590 qdf_mem_zero(mlme_ssid, sizeof(struct wlan_ssid)); 4591 qdf_mem_copy(&mlme_ssid->ssid[0], ssid, len); 4592 mlme_ssid->length = len; 4593 4594 mlme_debug("Set roam offload ssid: " QDF_SSID_FMT, 4595 QDF_SSID_REF(mlme_ssid->length, 4596 mlme_ssid->ssid)); 4597 } 4598 4599 void 4600 wlan_cm_get_roam_offload_ssid(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, 4601 uint8_t *ssid, uint8_t *len) 4602 { 4603 struct wlan_objmgr_vdev *vdev; 4604 struct mlme_legacy_priv *mlme_priv; 4605 struct wlan_ssid *mlme_ssid; 4606 4607 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 4608 WLAN_MLME_CM_ID); 4609 if (!vdev) { 4610 mlme_err("VDEV is NULL"); 4611 return; 4612 } 4613 4614 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 4615 if (!mlme_priv) { 4616 mlme_err("vdev legacy private object is NULL"); 4617 goto ret; 4618 } 4619 4620 mlme_ssid = &mlme_priv->cm_roam.sae_offload.ssid; 4621 4622 qdf_mem_copy(ssid, mlme_ssid->ssid, mlme_ssid->length); 4623 *len = mlme_ssid->length; 4624 4625 ret: 4626 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 4627 } 4628 4629 void 4630 wlan_cm_roam_set_ho_delay_config(struct wlan_objmgr_psoc *psoc, 4631 uint16_t roam_ho_delay) 4632 { 4633 struct wlan_mlme_psoc_ext_obj *mlme_obj; 4634 4635 mlme_obj = mlme_get_psoc_ext_obj(psoc); 4636 if (!mlme_obj) 4637 return; 4638 4639 mlme_obj->cfg.lfr.roam_ho_delay_config = roam_ho_delay; 4640 } 4641 4642 uint16_t 4643 wlan_cm_roam_get_ho_delay_config(struct wlan_objmgr_psoc *psoc) 4644 { 4645 struct wlan_mlme_psoc_ext_obj *mlme_obj; 4646 4647 mlme_obj = mlme_get_psoc_ext_obj(psoc); 4648 if (!mlme_obj) { 4649 mlme_legacy_err("Failed to get MLME Obj"); 4650 return 0; 4651 } 4652 4653 return mlme_obj->cfg.lfr.roam_ho_delay_config; 4654 } 4655 4656 void 4657 wlan_cm_set_exclude_rm_partial_scan_freq(struct wlan_objmgr_psoc *psoc, 4658 uint8_t exclude_rm_partial_scan_freq) 4659 { 4660 struct wlan_mlme_psoc_ext_obj *mlme_obj; 4661 4662 mlme_obj = mlme_get_psoc_ext_obj(psoc); 4663 if (!mlme_obj) 4664 return; 4665 4666 mlme_obj->cfg.lfr.exclude_rm_partial_scan_freq = 4667 exclude_rm_partial_scan_freq; 4668 } 4669 4670 uint8_t 4671 wlan_cm_get_exclude_rm_partial_scan_freq(struct wlan_objmgr_psoc *psoc) 4672 { 4673 struct wlan_mlme_psoc_ext_obj *mlme_obj; 4674 4675 mlme_obj = mlme_get_psoc_ext_obj(psoc); 4676 if (!mlme_obj) { 4677 mlme_legacy_err("Failed to get MLME Obj"); 4678 return 0; 4679 } 4680 4681 return mlme_obj->cfg.lfr.exclude_rm_partial_scan_freq; 4682 } 4683 4684 void 4685 wlan_cm_roam_set_full_scan_6ghz_on_disc(struct wlan_objmgr_psoc *psoc, 4686 uint8_t roam_full_scan_6ghz_on_disc) 4687 { 4688 struct wlan_mlme_psoc_ext_obj *mlme_obj; 4689 4690 mlme_obj = mlme_get_psoc_ext_obj(psoc); 4691 if (!mlme_obj) 4692 return; 4693 4694 mlme_obj->cfg.lfr.roam_full_scan_6ghz_on_disc = 4695 roam_full_scan_6ghz_on_disc; 4696 } 4697 4698 uint8_t wlan_cm_roam_get_full_scan_6ghz_on_disc(struct wlan_objmgr_psoc *psoc) 4699 { 4700 struct wlan_mlme_psoc_ext_obj *mlme_obj; 4701 4702 mlme_obj = mlme_get_psoc_ext_obj(psoc); 4703 if (!mlme_obj) { 4704 mlme_legacy_err("Failed to get MLME Obj"); 4705 return 0; 4706 } 4707 4708 return mlme_obj->cfg.lfr.roam_full_scan_6ghz_on_disc; 4709 } 4710 4711 void 4712 wlan_cm_set_roam_scan_high_rssi_offset(struct wlan_objmgr_psoc *psoc, 4713 uint8_t roam_high_rssi_delta) 4714 { 4715 struct wlan_mlme_psoc_ext_obj *mlme_obj; 4716 4717 mlme_obj = mlme_get_psoc_ext_obj(psoc); 4718 if (!mlme_obj) 4719 return; 4720 4721 mlme_obj->cfg.lfr.roam_high_rssi_delta = roam_high_rssi_delta; 4722 } 4723 4724 uint8_t 4725 wlan_cm_get_roam_scan_high_rssi_offset(struct wlan_objmgr_psoc *psoc) 4726 { 4727 struct wlan_mlme_psoc_ext_obj *mlme_obj; 4728 4729 mlme_obj = mlme_get_psoc_ext_obj(psoc); 4730 if (!mlme_obj) 4731 return 0; 4732 4733 return mlme_obj->cfg.lfr.roam_high_rssi_delta; 4734 } 4735 4736 #else 4737 QDF_STATUS 4738 cm_roam_stats_event_handler(struct wlan_objmgr_psoc *psoc, 4739 struct roam_stats_event *stats_info) 4740 { 4741 return QDF_STATUS_SUCCESS; 4742 } 4743 #endif 4744 4745 #ifdef WLAN_FEATURE_FIPS 4746 QDF_STATUS cm_roam_pmkid_req_ind(struct wlan_objmgr_psoc *psoc, 4747 uint8_t vdev_id, 4748 struct roam_pmkid_req_event *src_lst) 4749 { 4750 QDF_STATUS status = QDF_STATUS_SUCCESS; 4751 struct wlan_objmgr_vdev *vdev; 4752 struct qdf_mac_addr *dst_list; 4753 uint32_t num_entries, i; 4754 4755 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 4756 WLAN_MLME_SB_ID); 4757 if (!vdev) { 4758 mlme_err("vdev object is NULL"); 4759 return QDF_STATUS_E_NULL_VALUE; 4760 } 4761 4762 num_entries = src_lst->num_entries; 4763 mlme_debug("Num entries %d", num_entries); 4764 for (i = 0; i < num_entries; i++) { 4765 dst_list = &src_lst->ap_bssid[i]; 4766 status = mlme_cm_osif_pmksa_candidate_notify(vdev, dst_list, 4767 1, false); 4768 if (QDF_IS_STATUS_ERROR(status)) { 4769 mlme_err("Number %d Notify failed for " QDF_MAC_ADDR_FMT, 4770 i, QDF_MAC_ADDR_REF(dst_list->bytes)); 4771 goto rel_ref; 4772 } 4773 } 4774 4775 rel_ref: 4776 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID); 4777 4778 return status; 4779 } 4780 #endif /* WLAN_FEATURE_FIPS */ 4781 4782 QDF_STATUS 4783 cm_cleanup_mlo_link(struct wlan_objmgr_vdev *vdev) 4784 { 4785 QDF_STATUS status; 4786 4787 /* Use MLO roam internal disconnect as this is for cleanup and 4788 * no need to inform OSIF, and REASON_FW_TRIGGERED_ROAM_FAILURE will 4789 * cleanup host without informing the FW 4790 */ 4791 status = wlan_cm_disconnect(vdev, 4792 CM_MLO_ROAM_INTERNAL_DISCONNECT, 4793 REASON_FW_TRIGGERED_ROAM_FAILURE, 4794 NULL); 4795 if (QDF_IS_STATUS_ERROR(status)) 4796 mlme_debug("Failed to post disconnect for link vdev"); 4797 4798 return status; 4799 } 4800 4801 bool wlan_is_rso_enabled(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id) 4802 { 4803 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 4804 enum roam_offload_state cur_state; 4805 4806 cur_state = mlme_get_roam_state(psoc, vdev_id); 4807 if (cur_state == WLAN_ROAM_RSO_ENABLED || 4808 cur_state == WLAN_ROAMING_IN_PROG || 4809 cur_state == WLAN_ROAM_SYNCH_IN_PROG || 4810 cur_state == WLAN_MLO_ROAM_SYNCH_IN_PROG) 4811 return true; 4812 4813 return false; 4814 } 4815 4816 bool wlan_is_roaming_enabled(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id) 4817 { 4818 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 4819 4820 if (mlme_get_roam_state(psoc, vdev_id) == WLAN_ROAM_DEINIT) 4821 return false; 4822 4823 return true; 4824 } 4825 4826 QDF_STATUS 4827 wlan_cm_set_sae_auth_ta(struct wlan_objmgr_pdev *pdev, 4828 uint8_t vdev_id, 4829 struct qdf_mac_addr sae_auth_ta) 4830 { 4831 struct mlme_legacy_priv *mlme_priv; 4832 struct wlan_objmgr_vdev *vdev; 4833 4834 if (!pdev) 4835 return QDF_STATUS_E_INVAL; 4836 4837 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, 4838 WLAN_MLME_CM_ID); 4839 if (!vdev) 4840 return QDF_STATUS_E_INVAL; 4841 4842 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 4843 if (!mlme_priv) { 4844 mlme_legacy_err("vdev legacy private object is NULL"); 4845 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 4846 return QDF_STATUS_E_INVAL; 4847 } 4848 qdf_mem_copy(mlme_priv->mlme_roam.sae_auth_ta.bytes, sae_auth_ta.bytes, 4849 QDF_MAC_ADDR_SIZE); 4850 mlme_priv->mlme_roam.sae_auth_pending = true; 4851 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 4852 4853 return QDF_STATUS_SUCCESS; 4854 } 4855 4856 QDF_STATUS 4857 wlan_cm_get_sae_auth_ta(struct wlan_objmgr_pdev *pdev, 4858 uint8_t vdev_id, 4859 struct qdf_mac_addr *sae_auth_ta) 4860 { 4861 struct mlme_legacy_priv *mlme_priv; 4862 struct wlan_objmgr_vdev *vdev; 4863 4864 if (!pdev) 4865 return QDF_STATUS_E_INVAL; 4866 4867 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, 4868 WLAN_MLME_CM_ID); 4869 if (!vdev) 4870 return QDF_STATUS_E_INVAL; 4871 4872 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 4873 if (!mlme_priv) { 4874 mlme_legacy_err("vdev legacy private object is NULL"); 4875 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 4876 return QDF_STATUS_E_INVAL; 4877 } 4878 4879 if (mlme_priv->mlme_roam.sae_auth_pending) { 4880 qdf_mem_copy(sae_auth_ta->bytes, 4881 mlme_priv->mlme_roam.sae_auth_ta.bytes, 4882 QDF_MAC_ADDR_SIZE); 4883 mlme_priv->mlme_roam.sae_auth_pending = false; 4884 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 4885 return QDF_STATUS_SUCCESS; 4886 } 4887 4888 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 4889 4890 return QDF_STATUS_E_ALREADY; 4891 } 4892 4893 void 4894 wlan_cm_set_assoc_btm_cap(struct wlan_objmgr_vdev *vdev, bool val) 4895 { 4896 struct mlme_legacy_priv *mlme_priv; 4897 4898 if (!vdev) 4899 return; 4900 4901 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 4902 if (!mlme_priv) 4903 return; 4904 4905 mlme_priv->connect_info.assoc_btm_cap = val; 4906 } 4907 4908 bool 4909 wlan_cm_get_assoc_btm_cap(struct wlan_objmgr_vdev *vdev) 4910 { 4911 struct mlme_legacy_priv *mlme_priv; 4912 4913 if (!vdev) 4914 return true; 4915 4916 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 4917 if (!mlme_priv) 4918 return true; 4919 4920 return mlme_priv->connect_info.assoc_btm_cap; 4921 } 4922 4923 bool wlan_cm_is_self_mld_roam_supported(struct wlan_objmgr_psoc *psoc) 4924 { 4925 struct wmi_unified *wmi_handle; 4926 4927 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 4928 if (!wmi_handle) { 4929 mlme_debug("Invalid WMI handle"); 4930 return false; 4931 } 4932 4933 return wmi_service_enabled(wmi_handle, 4934 wmi_service_self_mld_roam_between_dbs_and_hbs); 4935 } 4936 4937 void 4938 wlan_cm_set_force_20mhz_in_24ghz(struct wlan_objmgr_vdev *vdev, 4939 bool is_40mhz_cap) 4940 { 4941 struct wlan_objmgr_psoc *psoc; 4942 struct wlan_mlme_psoc_ext_obj *mlme_obj; 4943 struct mlme_legacy_priv *mlme_priv; 4944 uint16_t dot11_mode; 4945 bool send_ie_to_fw = false; 4946 4947 if (!vdev) 4948 return; 4949 4950 psoc = wlan_vdev_get_psoc(vdev); 4951 if (!psoc) 4952 return; 4953 4954 mlme_obj = mlme_get_psoc_ext_obj(psoc); 4955 if (!mlme_obj || !mlme_obj->cfg.obss_ht40.is_override_ht20_40_24g) 4956 return; 4957 4958 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 4959 if (!mlme_priv) 4960 return; 4961 4962 /* 4963 * Force 20 MHz in 2.4 GHz only if "override_ht20_40_24g" ini 4964 * is set and userspace connect req doesn't have 40 MHz HT caps 4965 */ 4966 if (mlme_priv->connect_info.force_20mhz_in_24ghz != !is_40mhz_cap) 4967 send_ie_to_fw = true; 4968 4969 mlme_priv->connect_info.force_20mhz_in_24ghz = !is_40mhz_cap; 4970 4971 if (cm_is_vdev_connected(vdev) && send_ie_to_fw) { 4972 dot11_mode = 4973 cm_csr_get_vdev_dot11_mode(wlan_vdev_get_id(vdev)); 4974 cm_send_ies_for_roam_invoke(vdev, dot11_mode); 4975 } 4976 } 4977 4978 bool 4979 wlan_cm_get_force_20mhz_in_24ghz(struct wlan_objmgr_vdev *vdev) 4980 { 4981 struct mlme_legacy_priv *mlme_priv; 4982 4983 if (!vdev) 4984 return true; 4985 4986 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 4987 if (!mlme_priv) 4988 return true; 4989 4990 return mlme_priv->connect_info.force_20mhz_in_24ghz; 4991 } 4992 4993 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 4994 QDF_STATUS 4995 wlan_cm_update_offload_ssid_from_candidate(struct wlan_objmgr_pdev *pdev, 4996 uint8_t vdev_id, 4997 struct qdf_mac_addr *ap_bssid) 4998 { 4999 struct wlan_objmgr_vdev *vdev; 5000 struct wlan_objmgr_psoc *psoc; 5001 qdf_list_t *list = NULL; 5002 struct scan_cache_node *first_node = NULL; 5003 struct scan_filter *scan_filter; 5004 struct scan_cache_entry *entry; 5005 struct qdf_mac_addr cache_bssid; 5006 QDF_STATUS status = QDF_STATUS_SUCCESS; 5007 5008 psoc = wlan_pdev_get_psoc(pdev); 5009 if (!psoc) 5010 return QDF_STATUS_E_NULL_VALUE; 5011 5012 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 5013 WLAN_MLME_OBJMGR_ID); 5014 if (!vdev) 5015 return QDF_STATUS_E_NULL_VALUE; 5016 5017 /* 5018 * sae_offload ssid, bssid would have already been cached 5019 * from the tx profile of the roam_candidate_frame from FW, 5020 * but if the roam offload is received for a non-tx BSSID, 5021 * then the ssid stored in mlme_priv would be incorrect. 5022 * 5023 * If the bssid cached in sae_offload_param doesn't match 5024 * with the bssid received in roam_offload_event, then 5025 * get the scan entry from scan table to save the proper 5026 * ssid, bssid. 5027 */ 5028 wlan_cm_get_roam_offload_bssid(vdev, &cache_bssid); 5029 if (!qdf_mem_cmp(cache_bssid.bytes, ap_bssid->bytes, QDF_MAC_ADDR_SIZE)) 5030 goto end; 5031 5032 mlme_debug("Update the roam offload ssid from scan cache"); 5033 5034 scan_filter = qdf_mem_malloc(sizeof(*scan_filter)); 5035 if (!scan_filter) { 5036 status = QDF_STATUS_E_NOMEM; 5037 goto end; 5038 } 5039 5040 scan_filter->num_of_bssid = 1; 5041 qdf_mem_copy(scan_filter->bssid_list[0].bytes, 5042 ap_bssid, sizeof(struct qdf_mac_addr)); 5043 5044 list = wlan_scan_get_result(pdev, scan_filter); 5045 qdf_mem_free(scan_filter); 5046 5047 if (!list || !qdf_list_size(list)) { 5048 mlme_err("Scan result is empty, candidate entry not found"); 5049 status = QDF_STATUS_E_FAILURE; 5050 goto end; 5051 } 5052 5053 qdf_list_peek_front(list, (qdf_list_node_t **)&first_node); 5054 if (first_node && first_node->entry) { 5055 entry = first_node->entry; 5056 wlan_cm_set_roam_offload_ssid(vdev, 5057 &entry->ssid.ssid[0], 5058 entry->ssid.length); 5059 wlan_cm_set_roam_offload_bssid(vdev, ap_bssid); 5060 } 5061 5062 end: 5063 if (list) 5064 wlan_scan_purge_results(list); 5065 5066 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 5067 return status; 5068 } 5069 5070 QDF_STATUS 5071 wlan_cm_add_frame_to_scan_db(struct wlan_objmgr_psoc *psoc, 5072 struct roam_scan_candidate_frame *frame) 5073 { 5074 struct wlan_objmgr_vdev *vdev; 5075 struct wlan_objmgr_pdev *pdev; 5076 struct cnx_mgr *cm_ctx; 5077 uint32_t ie_offset, ie_len; 5078 uint8_t *ie_ptr = NULL; 5079 uint8_t *extracted_ie = NULL; 5080 uint8_t primary_channel, band; 5081 qdf_freq_t op_freq; 5082 struct wlan_frame_hdr *wh; 5083 struct qdf_mac_addr bssid; 5084 5085 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, frame->vdev_id, 5086 WLAN_MLME_CM_ID); 5087 if (!vdev) { 5088 mlme_err("vdev object is NULL"); 5089 return QDF_STATUS_E_NULL_VALUE; 5090 } 5091 5092 pdev = wlan_vdev_get_pdev(vdev); 5093 if (!pdev) { 5094 mlme_err("pdev object is NULL"); 5095 goto err; 5096 } 5097 5098 cm_ctx = cm_get_cm_ctx(vdev); 5099 if (!cm_ctx) { 5100 mlme_err("cm ctx is NULL"); 5101 goto err; 5102 } 5103 5104 /* Fixed parameters offset */ 5105 ie_offset = sizeof(struct wlan_frame_hdr) + MAC_B_PR_SSID_OFFSET; 5106 5107 if (frame->frame_length <= ie_offset) { 5108 mlme_err("Invalid frame length"); 5109 goto err; 5110 } 5111 5112 ie_ptr = frame->frame + ie_offset; 5113 ie_len = frame->frame_length - ie_offset; 5114 5115 extracted_ie = (uint8_t *)wlan_get_ie_ptr_from_eid(WLAN_ELEMID_SSID, 5116 ie_ptr, ie_len); 5117 /* 5118 * Roam offload ssid/bssid needs to be set only for SAE roam offload 5119 * candidate frames for supporting cross-ssid roaming. 5120 * This update is not needed for probe/beacons received from the 5121 * roam sync frame event. 5122 */ 5123 if (frame->roam_offload_candidate_frm && 5124 extracted_ie && extracted_ie[0] == WLAN_ELEMID_SSID) { 5125 wh = (struct wlan_frame_hdr *)frame->frame; 5126 WLAN_ADDR_COPY(&bssid.bytes[0], wh->i_addr2); 5127 5128 mlme_debug("SSID of the candidate is " QDF_SSID_FMT, 5129 QDF_SSID_REF(extracted_ie[1], &extracted_ie[2])); 5130 wlan_cm_set_roam_offload_ssid(vdev, &extracted_ie[2], 5131 extracted_ie[1]); 5132 wlan_cm_set_roam_offload_bssid(vdev, &bssid); 5133 } 5134 5135 /* For 2.4GHz,5GHz get channel from DS IE */ 5136 extracted_ie = (uint8_t *)wlan_get_ie_ptr_from_eid(WLAN_ELEMID_DSPARMS, 5137 ie_ptr, ie_len); 5138 if (extracted_ie && extracted_ie[0] == WLAN_ELEMID_DSPARMS && 5139 extracted_ie[1] == WLAN_DS_PARAM_IE_MAX_LEN) { 5140 band = BIT(REG_BAND_2G) | BIT(REG_BAND_5G); 5141 primary_channel = *(extracted_ie + 2); 5142 mlme_debug("Extracted primary channel from DS : %d", 5143 primary_channel); 5144 goto update_beacon; 5145 } 5146 5147 /* For HT, VHT and non-6GHz HE, get channel from HTINFO IE */ 5148 extracted_ie = (uint8_t *) 5149 wlan_get_ie_ptr_from_eid(WLAN_ELEMID_HTINFO_ANA, 5150 ie_ptr, ie_len); 5151 if (extracted_ie && extracted_ie[0] == WLAN_ELEMID_HTINFO_ANA && 5152 extracted_ie[1] == sizeof(struct wlan_ie_htinfo_cmn)) { 5153 band = BIT(REG_BAND_2G) | BIT(REG_BAND_5G); 5154 primary_channel = 5155 ((struct wlan_ie_htinfo *)extracted_ie)-> 5156 hi_ie.hi_ctrlchannel; 5157 mlme_debug("Extracted primary channel from HT INFO : %d", 5158 primary_channel); 5159 goto update_beacon; 5160 } 5161 /* For 6GHz, get channel from HE OP IE */ 5162 extracted_ie = (uint8_t *) 5163 wlan_get_ext_ie_ptr_from_ext_id(WLAN_HEOP_OUI_TYPE, 5164 (uint8_t) 5165 WLAN_HEOP_OUI_SIZE, 5166 ie_ptr, ie_len); 5167 if (extracted_ie && !qdf_mem_cmp(&extracted_ie[2], WLAN_HEOP_OUI_TYPE, 5168 WLAN_HEOP_OUI_SIZE) && 5169 extracted_ie[1] <= WLAN_MAX_HEOP_IE_LEN) { 5170 band = BIT(REG_BAND_6G); 5171 primary_channel = util_scan_get_6g_oper_channel(extracted_ie); 5172 mlme_debug("Extracted primary channel from HE OP : %d", 5173 primary_channel); 5174 if (primary_channel) 5175 goto update_beacon; 5176 } 5177 5178 mlme_err("Ignore beacon, Primary channel was not found in the candidate frame"); 5179 goto err; 5180 5181 update_beacon: 5182 op_freq = wlan_reg_chan_band_to_freq(pdev, primary_channel, band); 5183 cm_inform_bcn_probe(cm_ctx, frame->frame, frame->frame_length, 5184 op_freq, 5185 frame->rssi, 5186 cm_ctx->active_cm_id); 5187 5188 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 5189 return QDF_STATUS_SUCCESS; 5190 err: 5191 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 5192 return QDF_STATUS_E_FAILURE; 5193 } 5194 #endif 5195 5196 #ifdef WLAN_FEATURE_11BE_MLO 5197 bool wlan_cm_is_sae_auth_addr_conversion_required(struct wlan_objmgr_vdev *vdev) 5198 { 5199 if (!wlan_vdev_get_mlo_external_sae_auth_conversion(vdev)) 5200 return false; 5201 5202 if (wlan_cm_is_vdev_roaming(vdev)) { 5203 if (!wlan_cm_roam_is_mlo_ap(vdev)) 5204 return false; 5205 } else if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) { 5206 return false; 5207 } 5208 5209 return true; 5210 } 5211 #endif /* WLAN_FEATURE_11BE_MLO */ 5212 5213 #if defined(WLAN_FEATURE_ROAM_OFFLOAD) && defined(WLAN_FEATURE_11BE_MLO) 5214 /** 5215 * wlan_cm_reset_mlo_roam_peer_address() - this API reset the sae_roam_auth 5216 * structure values to zero. 5217 * @rso_config: pointer to struct rso_config 5218 * 5219 * Return: void 5220 */ 5221 static void wlan_cm_reset_mlo_roam_peer_address(struct rso_config *rso_config) 5222 { 5223 qdf_mem_zero(&rso_config->sae_roam_auth.peer_mldaddr, 5224 QDF_MAC_ADDR_SIZE); 5225 qdf_mem_zero(&rso_config->sae_roam_auth.peer_linkaddr, 5226 QDF_MAC_ADDR_SIZE); 5227 } 5228 5229 void wlan_cm_store_mlo_roam_peer_address(struct wlan_objmgr_pdev *pdev, 5230 struct auth_offload_event *auth_event) 5231 { 5232 struct wlan_objmgr_vdev *vdev; 5233 struct rso_config *rso_config; 5234 struct qdf_mac_addr mld_addr; 5235 QDF_STATUS status; 5236 5237 if (!pdev) { 5238 mlme_err("pdev is NULL"); 5239 return; 5240 } 5241 5242 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, auth_event->vdev_id, 5243 WLAN_LEGACY_MAC_ID); 5244 if (!vdev) { 5245 mlme_err("vdev %d not found", auth_event->vdev_id); 5246 return; 5247 } 5248 5249 if (!wlan_vdev_get_mlo_external_sae_auth_conversion(vdev)) 5250 goto rel_ref; 5251 5252 if (!wlan_cm_is_vdev_roaming(vdev)) 5253 goto rel_ref; 5254 5255 rso_config = wlan_cm_get_rso_config(vdev); 5256 if (!rso_config) 5257 goto rel_ref; 5258 5259 if (qdf_is_macaddr_zero(&auth_event->ta)) { 5260 /* ta have zero value for non-ML AP */ 5261 rso_config->sae_roam_auth.is_mlo_ap = false; 5262 wlan_cm_reset_mlo_roam_peer_address(rso_config); 5263 goto rel_ref; 5264 } 5265 5266 status = scm_get_mld_addr_by_link_addr(pdev, &auth_event->ap_bssid, 5267 &mld_addr); 5268 5269 rso_config->sae_roam_auth.is_mlo_ap = true; 5270 5271 if (QDF_IS_STATUS_ERROR(status)) { 5272 wlan_cm_reset_mlo_roam_peer_address(rso_config); 5273 goto rel_ref; 5274 } 5275 5276 qdf_mem_copy(rso_config->sae_roam_auth.peer_mldaddr.bytes, 5277 mld_addr.bytes, QDF_MAC_ADDR_SIZE); 5278 qdf_mem_copy(rso_config->sae_roam_auth.peer_linkaddr.bytes, 5279 &auth_event->ap_bssid, QDF_MAC_ADDR_SIZE); 5280 5281 mlme_debug("mld addr " QDF_MAC_ADDR_FMT "link addr " QDF_MAC_ADDR_FMT, 5282 QDF_MAC_ADDR_REF(rso_config->sae_roam_auth.peer_mldaddr.bytes), 5283 QDF_MAC_ADDR_REF(rso_config->sae_roam_auth.peer_linkaddr.bytes)); 5284 rel_ref: 5285 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID); 5286 } 5287 5288 struct qdf_mac_addr * 5289 wlan_cm_roaming_get_peer_mld_addr(struct wlan_objmgr_vdev *vdev) 5290 { 5291 struct rso_config *rso_config; 5292 5293 rso_config = wlan_cm_get_rso_config(vdev); 5294 if (!rso_config) 5295 return NULL; 5296 5297 if (qdf_is_macaddr_zero(&rso_config->sae_roam_auth.peer_mldaddr)) 5298 return NULL; 5299 5300 return &rso_config->sae_roam_auth.peer_mldaddr; 5301 } 5302 5303 struct qdf_mac_addr * 5304 wlan_cm_roaming_get_peer_link_addr(struct wlan_objmgr_vdev *vdev) 5305 { 5306 struct rso_config *rso_config; 5307 5308 rso_config = wlan_cm_get_rso_config(vdev); 5309 if (!rso_config) 5310 return NULL; 5311 5312 if (qdf_is_macaddr_zero(&rso_config->sae_roam_auth.peer_linkaddr)) 5313 return NULL; 5314 5315 return &rso_config->sae_roam_auth.peer_linkaddr; 5316 } 5317 5318 bool wlan_cm_roam_is_mlo_ap(struct wlan_objmgr_vdev *vdev) 5319 { 5320 struct rso_config *rso_config; 5321 5322 rso_config = wlan_cm_get_rso_config(vdev); 5323 if (!rso_config) 5324 return false; 5325 5326 return rso_config->sae_roam_auth.is_mlo_ap; 5327 } 5328 5329 QDF_STATUS 5330 cm_roam_candidate_event_handler(struct wlan_objmgr_psoc *psoc, 5331 struct roam_scan_candidate_frame *candidate) 5332 { 5333 return mlo_add_all_link_probe_rsp_to_scan_db(psoc, candidate); 5334 } 5335 5336 QDF_STATUS 5337 wlan_cm_add_all_link_probe_rsp_to_scan_db(struct wlan_objmgr_psoc *psoc, 5338 struct roam_scan_candidate_frame *candidate) 5339 { 5340 return mlo_add_all_link_probe_rsp_to_scan_db(psoc, candidate); 5341 } 5342 5343 #elif defined(WLAN_FEATURE_ROAM_OFFLOAD) /* end WLAN_FEATURE_11BE_MLO */ 5344 QDF_STATUS 5345 cm_roam_candidate_event_handler(struct wlan_objmgr_psoc *psoc, 5346 struct roam_scan_candidate_frame *candidate) 5347 { 5348 return wlan_cm_add_frame_to_scan_db(psoc, candidate); 5349 } 5350 5351 QDF_STATUS 5352 wlan_cm_add_all_link_probe_rsp_to_scan_db(struct wlan_objmgr_psoc *psoc, 5353 struct roam_scan_candidate_frame *candidate) 5354 { 5355 return wlan_cm_add_frame_to_scan_db(psoc, candidate); 5356 } 5357 5358 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */ 5359 5360 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_FEATURE_ROAM_OFFLOAD) 5361 QDF_STATUS wlan_cm_link_switch_notif_cb(struct wlan_objmgr_vdev *vdev, 5362 struct wlan_mlo_link_switch_req *req, 5363 enum wlan_mlo_link_switch_notify_reason notify_reason) 5364 { 5365 QDF_STATUS status = QDF_STATUS_SUCCESS; 5366 5367 if (notify_reason != MLO_LINK_SWITCH_NOTIFY_REASON_PRE_START_PRE_SER) 5368 return status; 5369 5370 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) 5371 return status; 5372 5373 /* Only send RSO stop for assoc vdev */ 5374 if (wlan_vdev_mlme_is_mlo_link_vdev(vdev)) 5375 return status; 5376 5377 status = cm_roam_state_change(wlan_vdev_get_pdev(vdev), 5378 wlan_vdev_get_id(vdev), 5379 WLAN_ROAM_RSO_STOPPED, 5380 REASON_DISCONNECTED, NULL, false); 5381 if (QDF_IS_STATUS_ERROR(status)) 5382 mlme_err("vdev:%d switch to RSO Stop failed", 5383 wlan_vdev_get_id(vdev)); 5384 5385 return status; 5386 } 5387 #endif 5388 5389