1 /* 2 * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /* 21 * DOC: wlan_cm_roam_fw_sync.c 22 * 23 * Implementation for the FW based roaming sync api interfaces. 24 */ 25 #include "qdf_types.h" 26 #include "wlan_objmgr_psoc_obj.h" 27 #include "wlan_objmgr_pdev_obj.h" 28 #include "wlan_objmgr_vdev_obj.h" 29 #include "wlan_cm_roam_i.h" 30 #include "wlan_dlm_api.h" 31 #include "wlan_cm_roam_public_struct.h" 32 #include "wlan_utility.h" 33 #include "wlan_scan_api.h" 34 #include "wlan_crypto_global_api.h" 35 #include "wlan_cm_tgt_if_tx_api.h" 36 #include "wlan_cm_vdev_api.h" 37 #include "wlan_p2p_api.h" 38 #include "wlan_tdls_api.h" 39 #include "wlan_mlme_vdev_mgr_interface.h" 40 #include "wlan_pkt_capture_ucfg_api.h" 41 #include "cds_utils.h" 42 #include "wlan_roam_debug.h" 43 #include "wlan_mlme_twt_api.h" 44 #include "connection_mgr/core/src/wlan_cm_roam.h" 45 #include "connection_mgr/core/src/wlan_cm_main.h" 46 #include "connection_mgr/core/src/wlan_cm_sm.h" 47 #include <wlan_mlo_mgr_sta.h> 48 #include "wlan_mlo_mgr_roam.h" 49 #include "wlan_vdev_mgr_utils_api.h" 50 #include "wlan_mlo_link_force.h" 51 #include <wlan_psoc_mlme_api.h> 52 #include <wma.h> 53 54 /* 55 * cm_is_peer_preset_on_other_sta() - Check if peer exists on other STA 56 * @psoc: Pointer to psoc 57 * @vdev: pointer to vdev 58 * @vdev_id: vdev id 59 * @event: Roam sync event pointer 60 * 61 * Return: True is peer found on other STA else return false 62 */ 63 static bool 64 cm_is_peer_preset_on_other_sta(struct wlan_objmgr_psoc *psoc, 65 struct wlan_objmgr_vdev *vdev, 66 uint8_t vdev_id, void *event) 67 { 68 bool peer_exists_other_sta = false; 69 struct roam_offload_synch_ind *sync_ind; 70 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); 71 uint8_t peer_vdev_id; 72 73 if (!wma) { 74 wma_err("wma_handle is NULL"); 75 return false; 76 } 77 78 sync_ind = (struct roam_offload_synch_ind *)event; 79 80 if (wma_objmgr_peer_exist(wma, sync_ind->bssid.bytes, &peer_vdev_id)) { 81 if ((!wlan_vdev_mlme_is_mlo_vdev(vdev) && 82 vdev_id != peer_vdev_id) || 83 !mlo_check_is_given_vdevs_on_same_mld(psoc, vdev_id, 84 peer_vdev_id)) { 85 wma_debug("Peer " QDF_MAC_ADDR_FMT 86 " already exists on vdev %d, current vdev %d", 87 QDF_MAC_ADDR_REF(sync_ind->bssid.bytes), 88 peer_vdev_id, vdev_id); 89 peer_exists_other_sta = true; 90 } 91 } 92 93 return peer_exists_other_sta; 94 } 95 96 QDF_STATUS cm_fw_roam_sync_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, 97 void *event, uint32_t event_data_len) 98 { 99 QDF_STATUS status; 100 struct wlan_objmgr_vdev *vdev; 101 102 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 103 WLAN_MLME_SB_ID); 104 105 if (!vdev) { 106 mlme_err("vdev object is NULL"); 107 return QDF_STATUS_E_NULL_VALUE; 108 } 109 110 if (mlo_is_mld_disconnecting_connecting(vdev) || 111 cm_is_vdev_connecting(vdev) || 112 cm_is_vdev_disconnecting(vdev) || 113 cm_is_peer_preset_on_other_sta(psoc, vdev, vdev_id, event)) { 114 mlme_err("vdev %d Roam sync not handled in connecting/disconnecting state", 115 vdev_id); 116 wlan_cm_roam_state_change(wlan_vdev_get_pdev(vdev), 117 vdev_id, 118 WLAN_ROAM_RSO_STOPPED, 119 REASON_ROAM_SYNCH_FAILED); 120 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID); 121 return QDF_STATUS_E_INVAL; 122 } 123 mlo_sta_stop_reconfig_timer(vdev); 124 wlan_clear_mlo_sta_link_removed_flag(vdev); 125 126 status = cm_sm_deliver_event(vdev, WLAN_CM_SM_EV_ROAM_SYNC, 127 event_data_len, event); 128 129 if (QDF_IS_STATUS_ERROR(status)) { 130 mlme_err("Roam sync was not handled"); 131 wlan_cm_roam_state_change(wlan_vdev_get_pdev(vdev), 132 vdev_id, WLAN_ROAM_RSO_STOPPED, 133 REASON_ROAM_SYNCH_FAILED); 134 } 135 136 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID); 137 138 return status; 139 } 140 141 QDF_STATUS 142 cm_fw_send_vdev_roam_event(struct cnx_mgr *cm_ctx, uint16_t data_len, 143 void *data) 144 { 145 QDF_STATUS status; 146 wlan_cm_id cm_id; 147 struct wlan_objmgr_psoc *psoc; 148 struct cm_roam_req *roam_req = NULL; 149 150 roam_req = cm_get_first_roam_command(cm_ctx->vdev); 151 if (!roam_req) { 152 mlme_err("Failed to find roam req from list"); 153 cm_id = CM_ID_INVALID; 154 status = QDF_STATUS_E_FAILURE; 155 goto error; 156 } 157 158 cm_id = roam_req->cm_id; 159 psoc = wlan_vdev_get_psoc(cm_ctx->vdev); 160 if (!psoc) { 161 mlme_err(CM_PREFIX_FMT "Failed to find psoc", 162 CM_PREFIX_REF(roam_req->req.vdev_id, 163 roam_req->cm_id)); 164 status = QDF_STATUS_E_FAILURE; 165 goto error; 166 } 167 168 status = wlan_vdev_mlme_sm_deliver_evt(cm_ctx->vdev, 169 WLAN_VDEV_SM_EV_ROAM, 170 data_len, 171 data); 172 173 error: 174 175 return status; 176 } 177 178 QDF_STATUS 179 cm_fw_roam_sync_start_ind(struct wlan_objmgr_vdev *vdev, 180 struct roam_offload_synch_ind *sync_ind) 181 { 182 QDF_STATUS status = QDF_STATUS_SUCCESS; 183 struct wlan_objmgr_pdev *pdev; 184 struct qdf_mac_addr connected_bssid; 185 uint8_t vdev_id; 186 struct wlan_objmgr_psoc *psoc; 187 uint8_t good_rssi_cfg; 188 struct psoc_mlme_obj *mlme_psoc_obj; 189 struct scoring_cfg *score_config; 190 191 pdev = wlan_vdev_get_pdev(vdev); 192 vdev_id = wlan_vdev_get_id(vdev); 193 psoc = wlan_pdev_get_psoc(pdev); 194 195 mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc); 196 if (!mlme_psoc_obj) 197 return QDF_STATUS_E_INVAL; 198 199 if (wlan_vdev_mlme_is_mlo_link_vdev(vdev)) { 200 if (!MLME_IS_ROAM_SYNCH_IN_PROGRESS(psoc, 201 sync_ind->roamed_vdev_id)) 202 status = wlan_cm_roam_state_change(pdev, 203 sync_ind->roamed_vdev_id, 204 WLAN_ROAM_SYNCH_IN_PROG, 205 REASON_ROAM_HANDOFF_DONE); 206 207 status = wlan_cm_roam_state_change(pdev, 208 vdev_id, 209 WLAN_MLO_ROAM_SYNCH_IN_PROG, 210 REASON_ROAM_HANDOFF_DONE); 211 return status; 212 } 213 214 /* 215 * Get old bssid as, new AP is not updated yet and do cleanup 216 * for old bssid. 217 */ 218 wlan_mlme_get_bssid_vdev_id(pdev, vdev_id, 219 &connected_bssid); 220 221 /* Update the DLM that the previous profile has disconnected */ 222 wlan_dlm_update_bssid_connect_params(pdev, 223 connected_bssid, 224 DLM_AP_DISCONNECTED); 225 226 if (IS_ROAM_REASON_STA_KICKOUT(sync_ind->roam_reason)) { 227 struct reject_ap_info ap_info; 228 229 score_config = &mlme_psoc_obj->psoc_cfg.score_config; 230 good_rssi_cfg = score_config->rssi_score.good_rssi_threshold; 231 if (good_rssi_cfg > sync_ind->rssi) { 232 qdf_mem_zero(&ap_info, sizeof(struct reject_ap_info)); 233 ap_info.bssid = connected_bssid; 234 ap_info.reject_ap_type = DRIVER_AVOID_TYPE; 235 ap_info.reject_reason = REASON_STA_KICKOUT; 236 ap_info.source = ADDED_BY_DRIVER; 237 wlan_dlm_add_bssid_to_reject_list(pdev, &ap_info); 238 } 239 } 240 241 cm_update_scan_mlme_on_roam(vdev, &connected_bssid, 242 SCAN_ENTRY_CON_STATE_NONE); 243 244 if (!MLME_IS_ROAM_SYNCH_IN_PROGRESS(psoc, vdev_id)) 245 status = wlan_cm_roam_state_change(pdev, 246 vdev_id, 247 WLAN_ROAM_SYNCH_IN_PROG, 248 REASON_ROAM_HANDOFF_DONE); 249 250 mlme_init_twt_context(wlan_pdev_get_psoc(pdev), &connected_bssid, 251 TWT_ALL_SESSIONS_DIALOG_ID); 252 253 mlme_cm_osif_roam_sync_ind(vdev); 254 255 return status; 256 } 257 258 void 259 cm_update_scan_mlme_on_roam(struct wlan_objmgr_vdev *vdev, 260 struct qdf_mac_addr *connected_bssid, 261 enum scan_entry_connection_state state) 262 { 263 struct wlan_objmgr_pdev *pdev; 264 struct bss_info bss_info; 265 struct mlme_info mlme; 266 struct wlan_channel *chan; 267 QDF_STATUS status; 268 269 pdev = wlan_vdev_get_pdev(vdev); 270 if (!pdev) { 271 mlme_err("failed to find pdev"); 272 return; 273 } 274 275 chan = wlan_vdev_get_active_channel(vdev); 276 if (!chan) { 277 mlme_err("failed to get active channel"); 278 return; 279 } 280 281 status = wlan_vdev_mlme_get_ssid(vdev, bss_info.ssid.ssid, 282 &bss_info.ssid.length); 283 284 if (QDF_IS_STATUS_ERROR(status)) { 285 mlme_err("failed to get ssid"); 286 return; 287 } 288 289 mlme.assoc_state = state; 290 qdf_copy_macaddr(&bss_info.bssid, connected_bssid); 291 292 bss_info.freq = chan->ch_freq; 293 294 wlan_scan_update_mlme_by_bssinfo(pdev, &bss_info, &mlme); 295 } 296 297 #ifdef WLAN_FEATURE_FILS_SK 298 static QDF_STATUS 299 cm_fill_fils_ie(struct wlan_connect_rsp_ies *connect_ies, 300 struct roam_offload_synch_ind *roam_synch_data) 301 { 302 struct fils_connect_rsp_params *fils_ie; 303 304 if (!roam_synch_data->hlp_data_len) 305 return QDF_STATUS_SUCCESS; 306 307 connect_ies->fils_ie = qdf_mem_malloc(sizeof(*fils_ie)); 308 if (!connect_ies->fils_ie) 309 return QDF_STATUS_E_NOMEM; 310 311 fils_ie = connect_ies->fils_ie; 312 cds_copy_hlp_info(&roam_synch_data->dst_mac, 313 &roam_synch_data->src_mac, 314 roam_synch_data->hlp_data_len, 315 roam_synch_data->hlp_data, 316 &fils_ie->dst_mac, 317 &fils_ie->src_mac, 318 &fils_ie->hlp_data_len, 319 fils_ie->hlp_data); 320 321 fils_ie->fils_seq_num = roam_synch_data->next_erp_seq_num; 322 323 return QDF_STATUS_SUCCESS; 324 } 325 #else 326 static inline QDF_STATUS 327 cm_fill_fils_ie(struct wlan_connect_rsp_ies *connect_ies, 328 struct roam_offload_synch_ind *roam_synch_data) 329 { 330 return QDF_STATUS_SUCCESS; 331 } 332 #endif 333 334 static QDF_STATUS 335 cm_populate_connect_ies(struct roam_offload_synch_ind *roam_synch_data, 336 struct cm_vdev_join_rsp *rsp) 337 { 338 struct wlan_connect_rsp_ies *connect_ies; 339 uint8_t *bcn_probe_rsp_ptr; 340 uint8_t *reassoc_rsp_ptr; 341 uint8_t *reassoc_req_ptr; 342 343 connect_ies = &rsp->connect_rsp.connect_ies; 344 345 /* Beacon/Probe Rsp frame */ 346 if (roam_synch_data->beacon_probe_resp_length) { 347 connect_ies->bcn_probe_rsp.len = 348 roam_synch_data->beacon_probe_resp_length; 349 bcn_probe_rsp_ptr = (uint8_t *)roam_synch_data + 350 roam_synch_data->beacon_probe_resp_offset; 351 352 connect_ies->bcn_probe_rsp.ptr = 353 qdf_mem_malloc(connect_ies->bcn_probe_rsp.len); 354 if (!connect_ies->bcn_probe_rsp.ptr) 355 return QDF_STATUS_E_NOMEM; 356 qdf_mem_copy(connect_ies->bcn_probe_rsp.ptr, bcn_probe_rsp_ptr, 357 connect_ies->bcn_probe_rsp.len); 358 } 359 360 /* Beacon/Probe Rsp frame */ 361 if (roam_synch_data->link_beacon_probe_resp_length) { 362 connect_ies->link_bcn_probe_rsp.len = 363 roam_synch_data->link_beacon_probe_resp_length; 364 bcn_probe_rsp_ptr = (uint8_t *)roam_synch_data + 365 roam_synch_data->link_beacon_probe_resp_offset; 366 367 connect_ies->link_bcn_probe_rsp.ptr = 368 qdf_mem_malloc(connect_ies->link_bcn_probe_rsp.len); 369 if (!connect_ies->link_bcn_probe_rsp.ptr) 370 return QDF_STATUS_E_NOMEM; 371 qdf_mem_copy(connect_ies->link_bcn_probe_rsp.ptr, 372 bcn_probe_rsp_ptr, 373 connect_ies->link_bcn_probe_rsp.len); 374 } 375 376 /* ReAssoc Rsp IE data */ 377 if (roam_synch_data->reassoc_resp_length > 378 sizeof(struct wlan_frame_hdr)) { 379 connect_ies->assoc_rsp.len = 380 roam_synch_data->reassoc_resp_length - 381 sizeof(struct wlan_frame_hdr); 382 reassoc_rsp_ptr = (uint8_t *)roam_synch_data + 383 roam_synch_data->reassoc_resp_offset + 384 sizeof(struct wlan_frame_hdr); 385 connect_ies->assoc_rsp.ptr = 386 qdf_mem_malloc(connect_ies->assoc_rsp.len); 387 if (!connect_ies->assoc_rsp.ptr) 388 return QDF_STATUS_E_NOMEM; 389 390 qdf_mem_copy(connect_ies->assoc_rsp.ptr, reassoc_rsp_ptr, 391 connect_ies->assoc_rsp.len); 392 } 393 394 /* ReAssoc Req IE data */ 395 if (roam_synch_data->reassoc_req_length > 396 sizeof(struct wlan_frame_hdr)) { 397 connect_ies->assoc_req.len = 398 roam_synch_data->reassoc_req_length - 399 sizeof(struct wlan_frame_hdr); 400 reassoc_req_ptr = (uint8_t *)roam_synch_data + 401 roam_synch_data->reassoc_req_offset + 402 sizeof(struct wlan_frame_hdr); 403 connect_ies->assoc_req.ptr = 404 qdf_mem_malloc(connect_ies->assoc_req.len); 405 if (!connect_ies->assoc_req.ptr) 406 return QDF_STATUS_E_NOMEM; 407 qdf_mem_copy(connect_ies->assoc_req.ptr, reassoc_req_ptr, 408 connect_ies->assoc_req.len); 409 } 410 rsp->connect_rsp.is_assoc = roam_synch_data->is_assoc; 411 412 cm_fill_fils_ie(connect_ies, roam_synch_data); 413 414 return QDF_STATUS_SUCCESS; 415 } 416 417 #ifdef FEATURE_WLAN_ESE 418 static QDF_STATUS 419 cm_copy_tspec_ie(struct cm_vdev_join_rsp *rsp, 420 struct roam_offload_synch_ind *roam_synch_data) 421 { 422 if (roam_synch_data->tspec_len) { 423 rsp->tspec_ie.len = roam_synch_data->tspec_len; 424 rsp->tspec_ie.ptr = 425 qdf_mem_malloc(rsp->tspec_ie.len); 426 if (!rsp->tspec_ie.ptr) 427 return QDF_STATUS_E_NOMEM; 428 429 qdf_mem_copy(rsp->tspec_ie.ptr, 430 roam_synch_data->ric_tspec_data + 431 roam_synch_data->ric_data_len, 432 rsp->tspec_ie.len); 433 } 434 435 return QDF_STATUS_SUCCESS; 436 } 437 #else 438 static inline QDF_STATUS 439 cm_copy_tspec_ie(struct cm_vdev_join_rsp *rsp, 440 struct roam_offload_synch_ind *roam_synch_data) 441 { 442 return QDF_STATUS_SUCCESS; 443 } 444 #endif 445 446 #ifdef WLAN_FEATURE_FILS_SK 447 static void 448 cm_fils_update_erp_seq_num(struct wlan_objmgr_vdev *vdev, 449 uint16_t next_erp_seq_num, 450 wlan_cm_id cm_id) 451 { 452 struct wlan_objmgr_psoc *psoc; 453 struct wlan_objmgr_pdev *pdev; 454 struct wlan_fils_connection_info *fils_info; 455 uint8_t vdev_id = wlan_vdev_get_id(vdev); 456 457 pdev = wlan_vdev_get_pdev(vdev); 458 if (!pdev) { 459 mlme_err(CM_PREFIX_FMT "Failed to find pdev", 460 CM_PREFIX_REF(vdev_id, cm_id)); 461 return; 462 } 463 464 psoc = wlan_pdev_get_psoc(pdev); 465 if (!psoc) { 466 mlme_err(CM_PREFIX_FMT "Failed to find psoc", 467 CM_PREFIX_REF(vdev_id, cm_id)); 468 return; 469 } 470 471 fils_info = wlan_cm_get_fils_connection_info(psoc, vdev_id); 472 if (!fils_info) 473 return; 474 475 /* 476 * update the erp sequence number to the vdev level 477 * FILS cache. This will be sent in the next RSO 478 * command. 479 */ 480 fils_info->erp_sequence_number = next_erp_seq_num; 481 } 482 #else 483 static inline void 484 cm_fils_update_erp_seq_num(struct wlan_objmgr_vdev *vdev, 485 uint16_t next_erp_seq_num, wlan_cm_id cm_id) 486 {} 487 #endif 488 489 #ifdef WLAN_FEATURE_11BE_MLO 490 static void 491 cm_roam_update_mlo_mgr_info(struct wlan_objmgr_vdev *vdev, 492 struct roam_offload_synch_ind *roam_synch_data) 493 { 494 struct wlan_channel channel = {0}; 495 struct ml_setup_link_param *ml_link; 496 uint8_t i; 497 498 if (!is_multi_link_roam(roam_synch_data)) 499 return; 500 501 mlo_mgr_reset_ap_link_info(vdev); 502 for (i = 0; i < roam_synch_data->num_setup_links; i++) { 503 ml_link = &roam_synch_data->ml_link[i]; 504 505 qdf_mem_zero(&channel, sizeof(channel)); 506 507 channel.ch_freq = ml_link->channel.mhz; 508 channel.ch_cfreq1 = ml_link->channel.band_center_freq1; 509 channel.ch_cfreq2 = ml_link->channel.band_center_freq2; 510 511 /* 512 * Update Link switch context for each vdev with roamed AP link 513 * address and self link address for each vdev 514 */ 515 mlo_mgr_roam_update_ap_link_info(vdev, ml_link, &channel); 516 } 517 } 518 519 static QDF_STATUS 520 cm_fill_bssid_freq_info(uint8_t vdev_id, 521 struct roam_offload_synch_ind *roam_synch_data, 522 struct cm_vdev_join_rsp *rsp) 523 { 524 uint8_t i; 525 struct ml_setup_link_param *ml_link; 526 527 /* The @bssid field in roam synch indication will 528 * contain MLD address in case of roaming to ML 529 * candidate or else legacy MAC address for non-ML 530 * roaming. 531 */ 532 if (is_multi_link_roam(roam_synch_data)) 533 qdf_copy_macaddr(&rsp->connect_rsp.mld_addr, 534 &roam_synch_data->bssid); 535 else 536 qdf_zero_macaddr(&rsp->connect_rsp.mld_addr); 537 538 for (i = 0; i < roam_synch_data->num_setup_links; i++) { 539 ml_link = &roam_synch_data->ml_link[i]; 540 if (vdev_id == ml_link->vdev_id) { 541 qdf_copy_macaddr(&rsp->connect_rsp.bssid, 542 &ml_link->link_addr); 543 rsp->connect_rsp.freq = ml_link->channel.mhz; 544 545 return QDF_STATUS_SUCCESS; 546 } 547 } 548 549 qdf_copy_macaddr(&rsp->connect_rsp.bssid, &roam_synch_data->bssid); 550 rsp->connect_rsp.freq = roam_synch_data->chan_freq; 551 552 return QDF_STATUS_SUCCESS; 553 } 554 555 static void 556 cm_mlo_roam_copy_partner_info(struct wlan_cm_connect_resp *connect_rsp, 557 struct roam_offload_synch_ind *roam_synch_data) 558 { 559 mlo_roam_copy_partner_info(&connect_rsp->ml_parnter_info, 560 roam_synch_data, WLAN_INVALID_VDEV_ID, 561 true); 562 } 563 #else 564 static inline void 565 cm_roam_update_mlo_mgr_info(struct wlan_objmgr_vdev *vdev, 566 struct roam_offload_synch_ind *roam_synch_data) 567 {} 568 static QDF_STATUS 569 cm_fill_bssid_freq_info(uint8_t vdev_id, 570 struct roam_offload_synch_ind *roam_synch_data, 571 struct cm_vdev_join_rsp *rsp) 572 { 573 qdf_copy_macaddr(&rsp->connect_rsp.bssid, &roam_synch_data->bssid); 574 rsp->connect_rsp.freq = roam_synch_data->chan_freq; 575 576 return QDF_STATUS_SUCCESS; 577 } 578 579 static void 580 cm_mlo_roam_copy_partner_info(struct wlan_cm_connect_resp *connect_rsp, 581 struct roam_offload_synch_ind *roam_synch_data) 582 { 583 } 584 #endif 585 586 static void 587 cm_update_assoc_btm_cap(struct wlan_objmgr_vdev *vdev, 588 struct cm_vdev_join_rsp *rsp) 589 { 590 struct wlan_connect_rsp_ies *connect_ies; 591 const uint8_t *ext_cap_ie; 592 struct s_ext_cap *extcap; 593 uint8_t offset; 594 595 connect_ies = &rsp->connect_rsp.connect_ies; 596 /* 597 * Retain the btm cap from initial assoc if 598 * there is no assoc request 599 */ 600 if (!connect_ies->assoc_req.ptr || 601 !connect_ies->assoc_req.len) 602 return; 603 604 if (rsp->connect_rsp.is_assoc) 605 offset = WLAN_ASSOC_REQ_IES_OFFSET; 606 else 607 offset = WLAN_REASSOC_REQ_IES_OFFSET; 608 609 ext_cap_ie = 610 wlan_get_ie_ptr_from_eid(WLAN_ELEMID_XCAPS, 611 connect_ies->assoc_req.ptr + offset, 612 connect_ies->assoc_req.len - offset); 613 614 if (!ext_cap_ie) { 615 mlme_debug("Ext cap is not present, disable btm"); 616 wlan_cm_set_assoc_btm_cap(vdev, false); 617 return; 618 } 619 extcap = (struct s_ext_cap *)&ext_cap_ie[2]; 620 wlan_cm_set_assoc_btm_cap(vdev, extcap->bss_transition); 621 } 622 623 #ifdef WLAN_FEATURE_11BE_MLO 624 static inline void 625 cm_fill_num_roam_links_info(struct wlan_roam_sync_info *roam_info, 626 struct roam_offload_synch_ind *roam_synch_ind) 627 { 628 roam_info->num_setup_links = roam_synch_ind->num_setup_links; 629 } 630 #else 631 static inline void 632 cm_fill_num_roam_links_info(struct wlan_roam_sync_info *roam_info, 633 struct roam_offload_synch_ind *roam_synch_ind) 634 { 635 } 636 #endif 637 638 static QDF_STATUS 639 cm_fill_roam_info(struct wlan_objmgr_vdev *vdev, 640 struct roam_offload_synch_ind *roam_synch_data, 641 struct cm_vdev_join_rsp *rsp, wlan_cm_id cm_id) 642 { 643 struct wlan_roam_sync_info *roaming_info; 644 QDF_STATUS status = QDF_STATUS_SUCCESS; 645 646 rsp->connect_rsp.roaming_info = qdf_mem_malloc(sizeof(*roaming_info)); 647 if (!rsp->connect_rsp.roaming_info) 648 return QDF_STATUS_E_NOMEM; 649 650 rsp->connect_rsp.vdev_id = wlan_vdev_get_id(vdev); 651 status = cm_fill_bssid_freq_info(wlan_vdev_get_id(vdev), 652 roam_synch_data, rsp); 653 if (QDF_IS_STATUS_ERROR(status)) { 654 mlme_err(CM_PREFIX_FMT "Failed to get bssid and freq", 655 CM_PREFIX_REF(rsp->connect_rsp.vdev_id, cm_id)); 656 return QDF_STATUS_E_FAILURE; 657 } 658 659 if (!util_scan_is_null_ssid(&roam_synch_data->ssid)) 660 wlan_vdev_mlme_set_ssid(vdev, 661 roam_synch_data->ssid.ssid, 662 roam_synch_data->ssid.length); 663 664 status = wlan_vdev_mlme_get_ssid(vdev, 665 rsp->connect_rsp.ssid.ssid, 666 &rsp->connect_rsp.ssid.length); 667 if (QDF_IS_STATUS_ERROR(status)) { 668 mlme_err(CM_PREFIX_FMT "Failed to get ssid", 669 CM_PREFIX_REF(rsp->connect_rsp.vdev_id, cm_id)); 670 return QDF_STATUS_E_FAILURE; 671 } 672 673 rsp->connect_rsp.is_reassoc = true; 674 rsp->connect_rsp.connect_status = QDF_STATUS_SUCCESS; 675 rsp->connect_rsp.cm_id = cm_id; 676 rsp->nss = roam_synch_data->nss; 677 678 if (roam_synch_data->ric_data_len) { 679 rsp->ric_resp_ie.len = roam_synch_data->ric_data_len; 680 rsp->ric_resp_ie.ptr = 681 qdf_mem_malloc(rsp->ric_resp_ie.len); 682 if (!rsp->ric_resp_ie.ptr) 683 return QDF_STATUS_E_NOMEM; 684 685 qdf_mem_copy(rsp->ric_resp_ie.ptr, 686 roam_synch_data->ric_tspec_data, 687 rsp->ric_resp_ie.len); 688 } 689 cm_copy_tspec_ie(rsp, roam_synch_data); 690 691 status = cm_populate_connect_ies(roam_synch_data, rsp); 692 if (QDF_IS_STATUS_ERROR(status)) 693 return status; 694 695 roaming_info = rsp->connect_rsp.roaming_info; 696 roaming_info->auth_status = roam_synch_data->auth_status; 697 cm_fill_num_roam_links_info(roaming_info, roam_synch_data); 698 roaming_info->kck_len = roam_synch_data->kck_len; 699 if (roaming_info->kck_len) 700 qdf_mem_copy(roaming_info->kck, roam_synch_data->kck, 701 roam_synch_data->kck_len); 702 roaming_info->kek_len = roam_synch_data->kek_len; 703 if (roaming_info->kek_len) 704 qdf_mem_copy(roaming_info->kek, roam_synch_data->kek, 705 roam_synch_data->kek_len); 706 qdf_mem_copy(roaming_info->replay_ctr, roam_synch_data->replay_ctr, 707 REPLAY_CTR_LEN); 708 roaming_info->roam_reason = 709 roam_synch_data->roam_reason & ROAM_REASON_MASK; 710 roaming_info->subnet_change_status = 711 CM_GET_SUBNET_STATUS(roam_synch_data->roam_reason); 712 roaming_info->pmk_len = roam_synch_data->pmk_len; 713 if (roaming_info->pmk_len) 714 qdf_mem_copy(roaming_info->pmk, roam_synch_data->pmk, 715 roaming_info->pmk_len); 716 717 qdf_mem_copy(roaming_info->pmkid, roam_synch_data->pmkid, 718 PMKID_LEN); 719 roaming_info->update_erp_next_seq_num = 720 roam_synch_data->update_erp_next_seq_num; 721 roaming_info->next_erp_seq_num = roam_synch_data->next_erp_seq_num; 722 723 cm_fils_update_erp_seq_num(vdev, roaming_info->next_erp_seq_num, cm_id); 724 cm_update_assoc_btm_cap(vdev, rsp); 725 726 return status; 727 } 728 729 static QDF_STATUS cm_process_roam_keys(struct wlan_objmgr_vdev *vdev, 730 struct cm_vdev_join_rsp *rsp, 731 wlan_cm_id cm_id) 732 { 733 struct wlan_objmgr_psoc *psoc; 734 struct wlan_objmgr_pdev *pdev; 735 struct wlan_roam_sync_info *roaming_info; 736 uint8_t vdev_id = wlan_vdev_get_id(vdev); 737 struct cm_roam_values_copy config; 738 uint8_t mdie_present; 739 struct wlan_mlme_psoc_ext_obj *mlme_obj; 740 QDF_STATUS status = QDF_STATUS_SUCCESS; 741 int32_t akm; 742 743 pdev = wlan_vdev_get_pdev(vdev); 744 if (!pdev) { 745 mlme_err(CM_PREFIX_FMT "Failed to find pdev", 746 CM_PREFIX_REF(vdev_id, cm_id)); 747 status = QDF_STATUS_E_FAILURE; 748 goto end; 749 } 750 psoc = wlan_pdev_get_psoc(pdev); 751 if (!psoc) { 752 mlme_err(CM_PREFIX_FMT "Failed to find psoc", 753 CM_PREFIX_REF(vdev_id, cm_id)); 754 status = QDF_STATUS_E_FAILURE; 755 goto end; 756 } 757 mlme_obj = mlme_get_psoc_ext_obj(psoc); 758 if (!mlme_obj) { 759 mlme_err(CM_PREFIX_FMT "Failed to mlme psoc obj", 760 CM_PREFIX_REF(vdev_id, cm_id)); 761 status = QDF_STATUS_E_FAILURE; 762 goto end; 763 } 764 765 roaming_info = rsp->connect_rsp.roaming_info; 766 akm = wlan_crypto_get_param(vdev, 767 WLAN_CRYPTO_PARAM_KEY_MGMT); 768 769 /* 770 * Encryption keys for new connection are obtained as follows: 771 * auth_status = CSR_ROAM_AUTH_STATUS_AUTHENTICATED 772 * Open - No keys required. 773 * Static WEP - Firmware copies keys from old AP to new AP. 774 * Fast roaming authentications e.g. PSK, FT, CCKM - firmware 775 * supplicant obtains them through 4-way handshake. 776 * 777 * auth_status = CSR_ROAM_AUTH_STATUS_CONNECTED 778 * All other authentications - Host supplicant performs EAPOL 779 * with AP after this point and sends new keys to the driver. 780 * Driver starts wait_for_key timer for that purpose. 781 * Allow cm_lookup_pmkid_using_bssid() if akm is SAE/OWE since 782 * SAE/OWE roaming uses hybrid model and eapol is offloaded to 783 * supplicant unlike in WPA2 802.1x case, after 8 way handshake 784 * the __wlan_hdd_cfg80211_keymgmt_set_key ->sme_roam_set_psk_pmk() 785 * will get called after roam synch complete to update the 786 * session->psk_pmk, but in SAE/OWE roaming this sequence is not 787 * present and set_pmksa will come before roam synch indication & 788 * eapol. So the session->psk_pmk will be stale in PMKSA cached 789 * SAE/OWE roaming case. 790 */ 791 792 if (roaming_info->auth_status == ROAM_AUTH_STATUS_AUTHENTICATED || 793 QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE) || 794 QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_SAE) || 795 QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_OWE) || 796 QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_SAE_EXT_KEY) || 797 QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE_EXT_KEY)) { 798 struct wlan_crypto_pmksa *pmkid_cache, *pmksa; 799 800 cm_csr_set_ss_none(vdev_id); 801 /* 802 * If authStatus is AUTHENTICATED, then we have done successful 803 * 4 way handshake in FW using the cached PMKID. 804 * However, the session->psk_pmk has the PMK of the older AP 805 * as set_key is not received from supplicant. 806 * When any RSO command is sent for the current AP, the older 807 * AP's PMK is sent to the FW which leads to incorrect PMK and 808 * leads to 4 way handshake failure when roaming happens to 809 * this AP again. 810 * Check if a PMK cache exists for the roamed AP and update 811 * it into the session pmk. 812 */ 813 pmkid_cache = qdf_mem_malloc(sizeof(*pmkid_cache)); 814 if (!pmkid_cache) { 815 status = QDF_STATUS_E_NOMEM; 816 mlme_err(CM_PREFIX_FMT "Mem alloc failed", 817 CM_PREFIX_REF(vdev_id, cm_id)); 818 goto end; 819 } 820 wlan_vdev_get_bss_peer_mac_for_pmksa(vdev, &pmkid_cache->bssid); 821 mlme_debug(CM_PREFIX_FMT "Trying to find PMKID for " 822 QDF_MAC_ADDR_FMT " AKM Type:%d", 823 CM_PREFIX_REF(vdev_id, cm_id), 824 QDF_MAC_ADDR_REF(pmkid_cache->bssid.bytes), akm); 825 826 wlan_cm_roam_cfg_get_value(psoc, vdev_id, 827 MOBILITY_DOMAIN, &config); 828 mdie_present = config.bool_value; 829 830 if (cm_lookup_pmkid_using_bssid(psoc, 831 vdev_id, 832 pmkid_cache)) { 833 /* 834 * Consider two APs: AP1, AP2 835 * Both APs configured with EAP 802.1x security mode 836 * and OKC is enabled in both APs by default. Initially 837 * DUT successfully associated with AP1, and generated 838 * PMK1 by performing full EAP and added an entry for 839 * AP1 in pmk table. At this stage, pmk table has only 840 * one entry for PMK1 (1. AP1-->PMK1). Now DUT try to 841 * roam to AP2 using PMK1 (as OKC is enabled) but 842 * session timeout happens on AP2 just before 4 way 843 * handshake completion in FW. At this point of time 844 * DUT not in authenticated state. Due to this DUT 845 * performs full EAP with AP2 and generates PMK2. As 846 * there is no previous entry of AP2 (AP2-->PMK1) in pmk 847 * table. When host gets pmk delete command for BSSID of 848 * AP2, the BSSID match fails. Hence host will not 849 * delete pmk entry of AP1 as well. 850 * At this point of time, the PMK table has two entry 851 * 1. AP1-->PMK1 and 2. AP2 --> PMK2. 852 * Ideally, if OKC is enabled then whenever timeout 853 * occurs in a mobility domain, then the driver should 854 * clear all APs cache entries related to that domain 855 * but as the BSSID doesn't exist yet in the driver 856 * cache there is no way of clearing the cache entries, 857 * without disturbing the legacy roaming. 858 * Now security profile for both APs changed to FT-RSN. 859 * DUT first disassociate with AP2 and successfully 860 * associated with AP2 and perform full EAP and 861 * generates PMK3. DUT first deletes PMK entry for AP2 862 * and then adds a new entry for AP2. 863 * At this point of time pmk table has two entry 864 * AP2--> PMK3 and AP1-->PMK1. Now DUT roamed to AP1 865 * using PMK3 but sends stale entry of AP1 (PMK1) to 866 * fw via RSO command. This override PMK for both APs 867 * with PMK1 (as FW uses mlme session PMK for both APs 868 * in case of FT roaming) and next time when FW try to 869 * roam to AP2 using PMK1, AP2 rejects PMK1 (As AP2 is 870 * expecting PMK3) and initiates full EAP with AP2, 871 * which is wrong. 872 * To address this issue update pmk table entry for 873 * roamed AP1 with pmk3 value comes to host via roam 874 * sync indication event. By this host override stale 875 * entry (if any) with the latest valid pmk for that AP 876 * at a point of time. 877 */ 878 if (roaming_info->pmk_len) { 879 pmksa = qdf_mem_malloc(sizeof(*pmksa)); 880 if (!pmksa) { 881 status = QDF_STATUS_E_NOMEM; 882 qdf_mem_zero(pmkid_cache, 883 sizeof(*pmkid_cache)); 884 qdf_mem_free(pmkid_cache); 885 goto end; 886 } 887 888 /* 889 * This pmksa buffer is to update the 890 * crypto table 891 */ 892 wlan_vdev_get_bss_peer_mac_for_pmksa(vdev, 893 &pmksa->bssid); 894 qdf_mem_copy(pmksa->pmkid, 895 roaming_info->pmkid, PMKID_LEN); 896 qdf_mem_copy(pmksa->pmk, roaming_info->pmk, 897 roaming_info->pmk_len); 898 pmksa->pmk_len = roaming_info->pmk_len; 899 status = wlan_crypto_set_del_pmksa(vdev, 900 pmksa, true); 901 if (QDF_IS_STATUS_ERROR(status)) { 902 qdf_mem_zero(pmksa, sizeof(*pmksa)); 903 qdf_mem_free(pmksa); 904 } 905 906 /* update the pmkid_cache buffer to 907 * update the global session pmk 908 */ 909 qdf_mem_copy(pmkid_cache->pmkid, 910 roaming_info->pmkid, PMKID_LEN); 911 qdf_mem_copy(pmkid_cache->pmk, 912 roaming_info->pmk, 913 roaming_info->pmk_len); 914 pmkid_cache->pmk_len = roaming_info->pmk_len; 915 } else { 916 mlme_debug("PMK not received from fw"); 917 } 918 919 wlan_cm_set_psk_pmk(pdev, vdev_id, 920 pmkid_cache->pmk, 921 pmkid_cache->pmk_len); 922 mlme_debug(CM_PREFIX_FMT "pmkid found for " 923 QDF_MAC_ADDR_FMT " len %d", 924 CM_PREFIX_REF(vdev_id, cm_id), 925 QDF_MAC_ADDR_REF(pmkid_cache->bssid.bytes), 926 pmkid_cache->pmk_len); 927 } else { 928 mlme_debug(CM_PREFIX_FMT "PMKID Not found in cache for " 929 QDF_MAC_ADDR_FMT, 930 CM_PREFIX_REF(vdev_id, cm_id), 931 QDF_MAC_ADDR_REF(pmkid_cache->bssid.bytes)); 932 /* 933 * In FT roam when the CSR lookup fails then the PMK 934 * details from the roam sync indication will be 935 * updated to Session/PMK cache. This will result in 936 * having multiple PMK cache entries for the same MDID, 937 * So do not add the PMKSA cache entry in all the 938 * FT-Roam cases. 939 */ 940 if (!cm_is_auth_type_11r(mlme_obj, vdev, 941 mdie_present) && 942 roaming_info->pmk_len) { 943 /* 944 * This pmksa buffer is to update the 945 * crypto table 946 */ 947 pmksa = qdf_mem_malloc(sizeof(*pmksa)); 948 if (!pmksa) { 949 status = QDF_STATUS_E_NOMEM; 950 qdf_mem_zero(pmkid_cache, 951 sizeof(*pmkid_cache)); 952 qdf_mem_free(pmkid_cache); 953 goto end; 954 } 955 wlan_cm_set_psk_pmk(pdev, vdev_id, 956 roaming_info->pmk, 957 roaming_info->pmk_len); 958 wlan_vdev_get_bss_peer_mac_for_pmksa(vdev, 959 &pmksa->bssid); 960 qdf_mem_copy(pmksa->pmkid, 961 roaming_info->pmkid, PMKID_LEN); 962 qdf_mem_copy(pmksa->pmk, 963 roaming_info->pmk, 964 roaming_info->pmk_len); 965 pmksa->pmk_len = roaming_info->pmk_len; 966 967 status = wlan_crypto_set_del_pmksa(vdev, 968 pmksa, 969 true); 970 if (QDF_IS_STATUS_ERROR(status)) { 971 qdf_mem_zero(pmksa, sizeof(*pmksa)); 972 qdf_mem_free(pmksa); 973 } 974 } 975 } 976 qdf_mem_zero(pmkid_cache, sizeof(*pmkid_cache)); 977 qdf_mem_free(pmkid_cache); 978 } 979 980 if (roaming_info->auth_status != ROAM_AUTH_STATUS_AUTHENTICATED) 981 cm_update_wait_for_key_timer(vdev, vdev_id, 982 WAIT_FOR_KEY_TIMEOUT_PERIOD); 983 end: 984 return status; 985 } 986 987 static void 988 cm_update_scan_db_on_roam_success(struct wlan_objmgr_vdev *vdev, 989 struct wlan_cm_connect_resp *resp, 990 struct roam_offload_synch_ind *roam_synch_ind, 991 wlan_cm_id cm_id) 992 { 993 struct cnx_mgr *cm_ctx; 994 qdf_freq_t frame_freq; 995 struct wlan_connect_rsp_ies *ies = &resp->connect_ies; 996 997 cm_ctx = cm_get_cm_ctx(vdev); 998 if (!cm_ctx) 999 return; 1000 1001 if (ies->link_bcn_probe_rsp.len) { 1002 frame_freq = mlo_roam_get_link_freq_from_mac_addr( 1003 roam_synch_ind, 1004 wlan_mlme_get_src_addr_from_frame( 1005 &ies->link_bcn_probe_rsp)); 1006 cm_inform_bcn_probe(cm_ctx, 1007 ies->link_bcn_probe_rsp.ptr, 1008 ies->link_bcn_probe_rsp.len, 1009 frame_freq, 1010 roam_synch_ind->rssi, 1011 cm_id); 1012 } 1013 1014 frame_freq = mlo_roam_get_link_freq_from_mac_addr( 1015 roam_synch_ind, 1016 wlan_mlme_get_src_addr_from_frame( 1017 &ies->bcn_probe_rsp)); 1018 /* 1019 * Firmware might have roamed to a link but got ML probe 1020 * response from the other link. Then the link freq is not 1021 * present in roam link info and it returns 0. No need to add 1022 * the original probe rsp in such cases as roam sync indication 1023 * handling would add it to scan db. Add the entry to scan 1024 * db only if valid link freq is found. 1025 */ 1026 if (frame_freq) 1027 cm_inform_bcn_probe(cm_ctx, 1028 ies->bcn_probe_rsp.ptr, 1029 ies->bcn_probe_rsp.len, 1030 frame_freq, 1031 roam_synch_ind->rssi, 1032 cm_id); 1033 1034 cm_update_scan_mlme_on_roam(vdev, &resp->bssid, 1035 SCAN_ENTRY_CON_STATE_ASSOC); 1036 1037 cm_standby_link_update_mlme_by_bssid(vdev, SCAN_ENTRY_CON_STATE_ASSOC, 1038 resp->ssid); 1039 } 1040 1041 #ifdef WLAN_FEATURE_11BE_MLO 1042 static void 1043 cm_roam_ml_clear_prev_ap_keys(struct wlan_objmgr_vdev *vdev) 1044 { 1045 struct wlan_mlo_dev_context *ml_dev; 1046 struct mlo_link_info *link_info; 1047 uint8_t i; 1048 1049 ml_dev = vdev->mlo_dev_ctx; 1050 if (!ml_dev || !ml_dev->link_ctx) 1051 return; 1052 1053 link_info = &ml_dev->link_ctx->links_info[0]; 1054 for (i = 0; i < WLAN_MAX_ML_BSS_LINKS; i++) { 1055 if (qdf_is_macaddr_zero(&link_info->ap_link_addr)) 1056 continue; 1057 1058 if (qdf_is_macaddr_zero(&link_info->link_addr)) 1059 continue; 1060 1061 wlan_crypto_free_key_by_link_id(wlan_vdev_get_psoc(vdev), 1062 &link_info->link_addr, 1063 link_info->link_id); 1064 link_info++; 1065 } 1066 } 1067 #else 1068 static void 1069 cm_roam_ml_clear_prev_ap_keys(struct wlan_objmgr_vdev *vdev) 1070 {} 1071 #endif 1072 1073 QDF_STATUS 1074 cm_fw_roam_sync_propagation(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, 1075 struct roam_offload_synch_ind *roam_synch_data) 1076 { 1077 QDF_STATUS status; 1078 struct wlan_objmgr_vdev *vdev; 1079 struct cnx_mgr *cm_ctx; 1080 struct cm_roam_req *roam_req = NULL; 1081 struct cm_vdev_join_rsp *rsp = NULL; 1082 wlan_cm_id cm_id; 1083 struct wlan_objmgr_pdev *pdev; 1084 struct wlan_cm_connect_resp *connect_rsp; 1085 bool eht_capab = false; 1086 1087 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 1088 WLAN_MLME_SB_ID); 1089 1090 if (!vdev) { 1091 mlme_err("vdev object is NULL"); 1092 return QDF_STATUS_E_NULL_VALUE; 1093 } 1094 1095 pdev = wlan_vdev_get_pdev(vdev); 1096 if (!pdev) { 1097 status = QDF_STATUS_E_FAILURE; 1098 goto rel_ref; 1099 } 1100 1101 cm_ctx = cm_get_cm_ctx(vdev); 1102 if (!cm_ctx) { 1103 status = QDF_STATUS_E_FAILURE; 1104 goto rel_ref; 1105 } 1106 1107 roam_req = cm_get_first_roam_command(vdev); 1108 if (!roam_req) { 1109 mlme_err("Failed to find roam req from list"); 1110 cm_id = CM_ID_INVALID; 1111 status = QDF_STATUS_E_FAILURE; 1112 goto error; 1113 } 1114 wlan_rec_conn_info(vdev_id, DEBUG_CONN_ROAMING, 1115 roam_synch_data->bssid.bytes, 0, 0); 1116 1117 cm_roam_update_mlo_mgr_info(vdev, roam_synch_data); 1118 cm_roam_ml_clear_prev_ap_keys(vdev); 1119 1120 cm_id = roam_req->cm_id; 1121 rsp = qdf_mem_malloc(sizeof(struct cm_vdev_join_rsp)); 1122 if (!rsp) { 1123 status = QDF_STATUS_E_NOMEM; 1124 goto error; 1125 } 1126 status = cm_fill_roam_info(vdev, roam_synch_data, rsp, cm_id); 1127 if (QDF_IS_STATUS_ERROR(status)) { 1128 mlme_err(CM_PREFIX_FMT " fail to prepare rsp", 1129 CM_PREFIX_REF(vdev_id, cm_id)); 1130 goto error; 1131 } 1132 1133 connect_rsp = &rsp->connect_rsp; 1134 cm_update_scan_db_on_roam_success(vdev, connect_rsp, 1135 roam_synch_data, cm_id); 1136 1137 status = cm_csr_connect_rsp(vdev, rsp); 1138 if (QDF_IS_STATUS_ERROR(status)) { 1139 mlme_err("Roam sync propagation failed, abort roaming"); 1140 goto error; 1141 } 1142 1143 cm_process_roam_keys(vdev, rsp, cm_id); 1144 /* 1145 * Re-enable the disabled link on roaming as decision 1146 * will be taken again to disable the link on roam sync completion. 1147 */ 1148 if (wlan_vdev_mlme_is_mlo_vdev(vdev)) 1149 policy_mgr_move_vdev_from_disabled_to_connection_tbl(psoc, 1150 vdev_id); 1151 cm_mlo_roam_copy_partner_info(connect_rsp, roam_synch_data); 1152 mlo_roam_init_cu_bpcc(vdev, roam_synch_data); 1153 mlo_roam_set_link_id(vdev, roam_synch_data); 1154 1155 /** 1156 * Don't send roam_sync complete for MLO link vdevs. 1157 * Send only for legacy STA/MLO STA vdev. 1158 */ 1159 if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev)) { 1160 cm_inform_dlm_connect_complete(cm_ctx->vdev, connect_rsp); 1161 wlan_p2p_status_connect(vdev); 1162 1163 if (!cm_csr_is_ss_wait_for_key(vdev_id)) { 1164 mlme_debug(CM_PREFIX_FMT "WLAN link up with AP = " 1165 QDF_MAC_ADDR_FMT, 1166 CM_PREFIX_REF(vdev_id, cm_id), 1167 QDF_MAC_ADDR_REF(connect_rsp->bssid.bytes)); 1168 cm_roam_start_init_on_connect(pdev, vdev_id); 1169 } 1170 wlan_cm_tgt_send_roam_sync_complete_cmd(psoc, vdev_id); 1171 mlo_roam_update_connected_links(vdev, connect_rsp); 1172 mlo_set_single_link_ml_roaming(psoc, vdev_id, 1173 false); 1174 } 1175 cm_connect_info(vdev, true, &connect_rsp->bssid, &connect_rsp->ssid, 1176 connect_rsp->freq); 1177 wlan_tdls_notify_sta_connect(vdev_id, 1178 mlme_get_tdls_chan_switch_prohibited(vdev), 1179 mlme_get_tdls_prohibited(vdev), vdev); 1180 1181 wlan_cm_update_scan_mlme_info(vdev, connect_rsp); 1182 cm_update_associated_ch_info(vdev, true); 1183 1184 status = cm_sm_deliver_event_sync(cm_ctx, WLAN_CM_SM_EV_ROAM_DONE, 1185 sizeof(*roam_synch_data), 1186 roam_synch_data); 1187 if (QDF_IS_STATUS_ERROR(status)) { 1188 mlme_err(CM_PREFIX_FMT " fail to post WLAN_CM_SM_EV_ROAM_DONE", 1189 CM_PREFIX_REF(vdev_id, cm_id)); 1190 goto error; 1191 } 1192 1193 if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev)) 1194 mlo_roam_update_connected_links(vdev, connect_rsp); 1195 mlme_cm_osif_connect_complete(vdev, connect_rsp); 1196 mlme_cm_osif_roam_complete(vdev); 1197 1198 if (wlan_vdev_mlme_is_mlo_vdev(vdev)) 1199 mlo_roam_copy_reassoc_rsp(vdev, connect_rsp); 1200 1201 mlme_debug(CM_PREFIX_FMT, CM_PREFIX_REF(vdev_id, cm_id)); 1202 cm_remove_cmd(cm_ctx, &cm_id); 1203 1204 wlan_psoc_mlme_get_11be_capab(psoc, &eht_capab); 1205 if (eht_capab) { 1206 status = policy_mgr_current_connections_update( 1207 psoc, vdev_id, 1208 connect_rsp->freq, 1209 POLICY_MGR_UPDATE_REASON_LFR3_ROAM, 1210 POLICY_MGR_DEF_REQ_ID); 1211 if (status == QDF_STATUS_E_NOSUPPORT) 1212 status = QDF_STATUS_SUCCESS; 1213 else if (status == QDF_STATUS_E_FAILURE) 1214 mlme_err("Failed to take next action LFR3_ROAM"); 1215 } 1216 1217 error: 1218 if (rsp) 1219 wlan_cm_free_connect_rsp(rsp); 1220 1221 if (QDF_IS_STATUS_ERROR(status)) 1222 mlo_update_connected_links(vdev, 0); 1223 rel_ref: 1224 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID); 1225 1226 return status; 1227 } 1228 1229 #ifdef WLAN_FEATURE_11BE_MLO 1230 static void 1231 cm_get_and_disable_link_from_roam_ind(struct wlan_objmgr_psoc *psoc, 1232 uint8_t vdev_id, 1233 struct roam_offload_synch_ind *synch_data) 1234 { 1235 uint8_t i; 1236 struct wlan_objmgr_vdev *vdev; 1237 1238 for (i = 0; i < synch_data->num_setup_links; i++) { 1239 if (synch_data->ml_link[i].vdev_id == vdev_id && 1240 synch_data->ml_link[i].flags & CM_ROAM_LINK_FLAG_DISABLE) { 1241 mlme_info("Vdev %d: link id %d flags 0x%x, indicate link disable", 1242 vdev_id, synch_data->ml_link[i].link_id, 1243 synch_data->ml_link[i].flags); 1244 policy_mgr_move_vdev_from_connection_to_disabled_tbl( 1245 psoc, vdev_id); 1246 1247 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, 1248 vdev_id, 1249 WLAN_MLME_SB_ID); 1250 if (!vdev) { 1251 mlme_debug("no vdev for id %d", vdev_id); 1252 break; 1253 } 1254 ml_nlink_set_curr_force_inactive_state( 1255 psoc, vdev, 1 << synch_data->ml_link[i].link_id, 1256 LINK_ADD); 1257 ml_nlink_init_concurrency_link_request(psoc, vdev); 1258 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID); 1259 break; 1260 } 1261 } 1262 } 1263 #else 1264 static inline void 1265 cm_get_and_disable_link_from_roam_ind(struct wlan_objmgr_psoc *psoc, 1266 uint8_t vdev_id, 1267 struct roam_offload_synch_ind *synch_data) 1268 {} 1269 #endif 1270 QDF_STATUS cm_fw_roam_complete(struct cnx_mgr *cm_ctx, void *data) 1271 { 1272 struct roam_offload_synch_ind *roam_synch_data; 1273 struct wlan_objmgr_pdev *pdev; 1274 struct wlan_objmgr_psoc *psoc; 1275 QDF_STATUS status = QDF_STATUS_SUCCESS; 1276 uint8_t vdev_id; 1277 1278 roam_synch_data = (struct roam_offload_synch_ind *)data; 1279 vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 1280 1281 pdev = wlan_vdev_get_pdev(cm_ctx->vdev); 1282 if (!pdev) { 1283 mlme_err("Failed to find pdev"); 1284 status = QDF_STATUS_E_FAILURE; 1285 goto end; 1286 } 1287 1288 psoc = wlan_pdev_get_psoc(pdev); 1289 if (!pdev) { 1290 mlme_err("Failed to find psoc"); 1291 status = QDF_STATUS_E_FAILURE; 1292 goto end; 1293 } 1294 1295 /* Handle one race condition that if candidate is already 1296 *selected & FW has gone ahead with roaming or about to go 1297 * ahead when set_band comes, it will be complicated for FW 1298 * to stop the current roaming. Instead, host will check the 1299 * roam sync to make sure the new AP is not on disable freq 1300 * or disconnect the AP. 1301 */ 1302 if (wlan_reg_is_disable_for_pwrmode(pdev, roam_synch_data->chan_freq, 1303 REG_CURRENT_PWR_MODE)) { 1304 mlo_disconnect(cm_ctx->vdev, CM_ROAM_DISCONNECT, 1305 REASON_OPER_CHANNEL_BAND_CHANGE, NULL); 1306 status = QDF_STATUS_E_FAILURE; 1307 goto end; 1308 } 1309 1310 /* 1311 * Following operations need to be done once roam sync 1312 * completion is sent to FW, hence called here: 1313 * 1) Firmware has already updated DBS policy. Update connection 1314 * table in the host driver. 1315 * 2) Force SCC switch if needed 1316 */ 1317 /* first update connection info from wma interface */ 1318 status = policy_mgr_update_connection_info(psoc, vdev_id); 1319 if (status == QDF_STATUS_NOT_INITIALIZED) 1320 policy_mgr_incr_active_session(psoc, QDF_STA_MODE, vdev_id); 1321 1322 /* Check if FW as indicated this link as disabled */ 1323 cm_get_and_disable_link_from_roam_ind(psoc, vdev_id, roam_synch_data); 1324 1325 /* then update remaining parameters from roam sync ctx */ 1326 if (roam_synch_data->hw_mode_trans_present) 1327 policy_mgr_hw_mode_transition_cb( 1328 roam_synch_data->hw_mode_trans_ind.old_hw_mode_index, 1329 roam_synch_data->hw_mode_trans_ind.new_hw_mode_index, 1330 roam_synch_data->hw_mode_trans_ind.num_vdev_mac_entries, 1331 roam_synch_data->hw_mode_trans_ind.vdev_mac_map, 1332 0, NULL, psoc); 1333 ml_nlink_conn_change_notify( 1334 psoc, vdev_id, 1335 ml_nlink_roam_sync_completion_evt, NULL); 1336 1337 if (roam_synch_data->pmk_len) { 1338 mlme_debug("Received pmk in roam sync. Length: %d", 1339 roam_synch_data->pmk_len); 1340 cm_check_and_set_sae_single_pmk_cap(psoc, vdev_id, 1341 roam_synch_data->pmk, 1342 roam_synch_data->pmk_len); 1343 } 1344 1345 cm_csr_send_set_ie(cm_ctx->vdev); 1346 1347 if (ucfg_pkt_capture_get_pktcap_mode(psoc)) 1348 ucfg_pkt_capture_record_channel(cm_ctx->vdev); 1349 1350 /* 1351 * Firmware will take care of checking hi_scan rssi delta, take care of 1352 * legacy -> legacy hi-rssi roam also if self mld roam supported. 1353 */ 1354 if (!wlan_cm_is_self_mld_roam_supported(psoc)) { 1355 if (WLAN_REG_IS_24GHZ_CH_FREQ(roam_synch_data->chan_freq)) { 1356 wlan_cm_set_disable_hi_rssi(pdev, 1357 vdev_id, false); 1358 } else { 1359 wlan_cm_set_disable_hi_rssi(pdev, 1360 vdev_id, true); 1361 mlme_debug("Disabling HI_RSSI, AP freq=%d rssi %d vdev id %d", 1362 roam_synch_data->chan_freq, 1363 roam_synch_data->rssi, vdev_id); 1364 } 1365 } 1366 policy_mgr_check_n_start_opportunistic_timer(psoc); 1367 1368 wlan_cm_handle_sta_sta_roaming_enablement(psoc, vdev_id); 1369 1370 if (wlan_vdev_mlme_is_mlo_link_vdev(cm_ctx->vdev)) { 1371 status = wlan_cm_roam_state_change(pdev, 1372 vdev_id, 1373 WLAN_ROAM_DEINIT, 1374 REASON_ROAM_HANDOFF_DONE); 1375 } 1376 1377 if (roam_synch_data->auth_status == ROAM_AUTH_STATUS_AUTHENTICATED) 1378 wlan_cm_roam_state_change(pdev, vdev_id, 1379 WLAN_ROAM_RSO_ENABLED, 1380 REASON_CONNECT); 1381 else 1382 /* 1383 * STA is just in associated state here, RSO 1384 * enable will be sent once EAP & EAPOL will be done by 1385 * user-space and after set key response is received. 1386 * 1387 * When firmware roaming state is connected, EAP/EAPOL will be 1388 * done at the supplicant. If EAP/EAPOL fails and supplicant 1389 * sends disconnect, then the RSO state machine sends 1390 * deinit directly to firmware without RSO stop with roam 1391 * scan mode value 0. So to avoid this move state to RSO 1392 * stop. 1393 */ 1394 wlan_cm_roam_state_change(pdev, vdev_id, 1395 WLAN_ROAM_RSO_STOPPED, 1396 REASON_DISCONNECTED); 1397 policy_mgr_check_concurrent_intf_and_restart_sap(psoc, 1398 wlan_util_vdev_mgr_get_acs_mode_for_vdev(cm_ctx->vdev)); 1399 end: 1400 return status; 1401 } 1402 1403 static QDF_STATUS 1404 cm_disconnect_roam_invoke_fail(struct wlan_objmgr_vdev *vdev, 1405 wlan_cm_id cm_id) 1406 { 1407 QDF_STATUS status = QDF_STATUS_SUCCESS; 1408 struct wlan_mlme_psoc_ext_obj *mlme_obj; 1409 bool nud_disconnect; 1410 struct wlan_objmgr_psoc *psoc; 1411 uint8_t vdev_id = wlan_vdev_get_id(vdev); 1412 struct rso_config *rso_cfg; 1413 1414 psoc = wlan_vdev_get_psoc(vdev); 1415 if (!psoc) { 1416 mlme_err(CM_PREFIX_FMT "psoc not found", 1417 CM_PREFIX_REF(vdev_id, cm_id)); 1418 return QDF_STATUS_E_INVAL; 1419 } 1420 1421 mlme_obj = mlme_get_psoc_ext_obj(psoc); 1422 if (!mlme_obj) 1423 return QDF_STATUS_E_NULL_VALUE; 1424 1425 rso_cfg = wlan_cm_get_rso_config(vdev); 1426 if (!rso_cfg) { 1427 mlme_err(CM_PREFIX_FMT "rso cfg not found", 1428 CM_PREFIX_REF(vdev_id, cm_id)); 1429 return QDF_STATUS_E_NULL_VALUE; 1430 } 1431 1432 nud_disconnect = mlme_obj->cfg.lfr.disconnect_on_nud_roam_invoke_fail; 1433 mlme_debug(CM_PREFIX_FMT "disconnect on NUD %d, source %d forced roaming %d", 1434 CM_PREFIX_REF(vdev_id, cm_id), 1435 nud_disconnect, rso_cfg->roam_invoke_source, 1436 rso_cfg->is_forced_roaming); 1437 1438 /* 1439 * If reassoc MAC from user space is broadcast MAC as: 1440 * "wpa_cli DRIVER FASTREASSOC ff:ff:ff:ff:ff:ff 0", 1441 * user space invoked roaming candidate selection will base on firmware 1442 * score algorithm, current connection will be kept if current AP has 1443 * highest score. It is requirement from customer which can avoid 1444 * ping-pong roaming. 1445 */ 1446 if (qdf_is_macaddr_broadcast(&rso_cfg->roam_invoke_bssid)) { 1447 qdf_zero_macaddr(&rso_cfg->roam_invoke_bssid); 1448 return status; 1449 } 1450 1451 if (rso_cfg->roam_invoke_source == CM_ROAMING_HOST || 1452 (rso_cfg->roam_invoke_source == CM_ROAMING_NUD_FAILURE && 1453 (nud_disconnect || rso_cfg->is_forced_roaming)) || 1454 rso_cfg->roam_invoke_source == CM_ROAMING_LINK_REMOVAL) { 1455 rso_cfg->roam_invoke_source = CM_SOURCE_INVALID; 1456 if (rso_cfg->is_forced_roaming) 1457 rso_cfg->is_forced_roaming = false; 1458 status = mlo_disconnect(vdev, CM_ROAM_DISCONNECT, 1459 REASON_USER_TRIGGERED_ROAM_FAILURE, 1460 NULL); 1461 } 1462 1463 return status; 1464 } 1465 1466 QDF_STATUS cm_fw_roam_invoke_fail(struct wlan_objmgr_psoc *psoc, 1467 uint8_t vdev_id) 1468 { 1469 QDF_STATUS status; 1470 struct wlan_objmgr_vdev *vdev; 1471 wlan_cm_id cm_id = CM_ID_INVALID; 1472 struct cnx_mgr *cm_ctx; 1473 struct cm_roam_req *roam_req = NULL; 1474 1475 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, 1476 vdev_id, 1477 WLAN_MLME_SB_ID); 1478 if (!vdev) { 1479 mlme_err("vdev object is NULL"); 1480 return QDF_STATUS_E_NULL_VALUE; 1481 } 1482 1483 cm_ctx = cm_get_cm_ctx(vdev); 1484 if (!cm_ctx) { 1485 status = QDF_STATUS_E_NULL_VALUE; 1486 goto error; 1487 } 1488 1489 roam_req = cm_get_first_roam_command(vdev); 1490 if (roam_req) 1491 cm_id = roam_req->cm_id; 1492 1493 status = cm_sm_deliver_event(vdev, WLAN_CM_SM_EV_ROAM_INVOKE_FAIL, 1494 sizeof(wlan_cm_id), &cm_id); 1495 if (QDF_IS_STATUS_ERROR(status)) 1496 cm_remove_cmd(cm_ctx, &cm_id); 1497 1498 cm_disconnect_roam_invoke_fail(vdev, cm_id); 1499 error: 1500 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID); 1501 return status; 1502 } 1503 1504 #ifdef FEATURE_WLAN_DIAG_SUPPORT 1505 static void cm_ho_fail_diag_event(void) 1506 { 1507 WLAN_HOST_DIAG_EVENT_DEF(roam_connection, 1508 host_event_wlan_status_payload_type); 1509 qdf_mem_zero(&roam_connection, 1510 sizeof(host_event_wlan_status_payload_type)); 1511 1512 roam_connection.eventId = DIAG_WLAN_STATUS_DISCONNECT; 1513 roam_connection.reason = DIAG_REASON_ROAM_HO_FAIL; 1514 WLAN_HOST_DIAG_EVENT_REPORT(&roam_connection, EVENT_WLAN_STATUS_V2); 1515 } 1516 #else 1517 static inline void cm_ho_fail_diag_event(void) {} 1518 #endif 1519 1520 #ifdef WLAN_FEATURE_11BE_MLO 1521 static bool 1522 cm_ho_fail_is_avoid_list_candidate(struct wlan_objmgr_vdev *vdev, 1523 struct cm_ho_fail_ind *ho_fail_ind) 1524 { 1525 uint8_t link_info_iter = 0; 1526 struct qdf_mac_addr peer_macaddr = {0}; 1527 struct mlo_link_info *mlo_link_info; 1528 uint32_t akm; 1529 1530 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) { 1531 wlan_vdev_get_bss_peer_mac(vdev, &peer_macaddr); 1532 akm = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT); 1533 if (WLAN_CRYPTO_IS_WPA_WPA2(akm)) 1534 return true; 1535 1536 if (qdf_is_macaddr_equal(&peer_macaddr, &ho_fail_ind->bssid)) 1537 return false; 1538 else 1539 return true; 1540 } 1541 1542 mlo_link_info = &vdev->mlo_dev_ctx->link_ctx->links_info[0]; 1543 for (link_info_iter = 0; link_info_iter < WLAN_MAX_ML_BSS_LINKS; 1544 link_info_iter++, mlo_link_info++) { 1545 if (qdf_is_macaddr_equal(&mlo_link_info->ap_link_addr, 1546 &ho_fail_ind->bssid)) 1547 return false; 1548 } 1549 1550 return true; 1551 } 1552 #else 1553 static bool 1554 cm_ho_fail_is_avoid_list_candidate(struct wlan_objmgr_vdev *vdev, 1555 struct cm_ho_fail_ind *ho_fail_ind) 1556 { 1557 struct qdf_mac_addr peer_macaddr = {0}; 1558 uint32_t akm; 1559 1560 akm = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT); 1561 if (WLAN_CRYPTO_IS_WPA_WPA2(akm)) 1562 return true; 1563 1564 wlan_vdev_get_bss_peer_mac(vdev, &peer_macaddr); 1565 if (qdf_is_macaddr_equal(&peer_macaddr, &ho_fail_ind->bssid)) 1566 return false; 1567 else 1568 return true; 1569 } 1570 #endif 1571 1572 static QDF_STATUS cm_handle_ho_fail(struct scheduler_msg *msg) 1573 { 1574 QDF_STATUS status; 1575 struct cm_ho_fail_ind *ind = NULL; 1576 struct wlan_objmgr_vdev *vdev; 1577 struct wlan_objmgr_pdev *pdev; 1578 struct cnx_mgr *cm_ctx; 1579 wlan_cm_id cm_id = CM_ID_INVALID; 1580 struct reject_ap_info ap_info; 1581 struct cm_roam_req *roam_req = NULL; 1582 struct wlan_mlme_psoc_ext_obj *mlme_obj; 1583 struct wlan_objmgr_psoc *psoc; 1584 1585 if (!msg || !msg->bodyptr) 1586 return QDF_STATUS_E_FAILURE; 1587 1588 ind = msg->bodyptr; 1589 1590 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(ind->psoc, ind->vdev_id, 1591 WLAN_MLME_CM_ID); 1592 if (!vdev) { 1593 mlme_err("vdev_id: %d : vdev not found", ind->vdev_id); 1594 qdf_mem_free(ind); 1595 return QDF_STATUS_E_INVAL; 1596 } 1597 1598 pdev = wlan_vdev_get_pdev(vdev); 1599 if (!pdev) { 1600 mlme_err("pdev object is NULL"); 1601 status = QDF_STATUS_E_NULL_VALUE; 1602 goto error; 1603 } 1604 1605 psoc = wlan_pdev_get_psoc(pdev); 1606 if (!psoc) { 1607 mlme_err("psoc object is NULL"); 1608 status = QDF_STATUS_E_NULL_VALUE; 1609 goto error; 1610 } 1611 mlme_obj = mlme_get_psoc_ext_obj(psoc); 1612 if (!mlme_obj) { 1613 mlme_err("Failed to mlme psoc obj"); 1614 status = QDF_STATUS_E_FAILURE; 1615 goto error; 1616 } 1617 1618 cm_ctx = cm_get_cm_ctx(vdev); 1619 if (!cm_ctx) { 1620 status = QDF_STATUS_E_NULL_VALUE; 1621 goto error; 1622 } 1623 1624 roam_req = cm_get_first_roam_command(vdev); 1625 if (roam_req) { 1626 mlme_debug("Roam req found, get cm id to remove it, before disconnect"); 1627 cm_id = roam_req->cm_id; 1628 } 1629 /* CPU freq is boosted during roam sync to improve roam latency, 1630 * upon HO failure reset that request to restore cpu freq back to normal 1631 */ 1632 mlme_cm_osif_perfd_reset_cpufreq(); 1633 1634 cm_sm_deliver_event(vdev, WLAN_CM_SM_EV_ROAM_HO_FAIL, 1635 sizeof(wlan_cm_id), &cm_id); 1636 1637 qdf_mem_zero(&ap_info, sizeof(struct reject_ap_info)); 1638 if (cm_ho_fail_is_avoid_list_candidate(vdev, ind)) { 1639 ap_info.bssid = ind->bssid; 1640 ap_info.reject_ap_type = DRIVER_AVOID_TYPE; 1641 ap_info.reject_reason = REASON_ROAM_HO_FAILURE; 1642 ap_info.source = ADDED_BY_DRIVER; 1643 wlan_dlm_add_bssid_to_reject_list(pdev, &ap_info); 1644 } 1645 1646 cm_ho_fail_diag_event(); 1647 wlan_roam_debug_log(ind->vdev_id, 1648 DEBUG_ROAM_SYNCH_FAIL, 1649 DEBUG_INVALID_PEER_ID, NULL, NULL, 0, 0); 1650 1651 status = mlo_disconnect(vdev, CM_MLME_DISCONNECT, 1652 REASON_FW_TRIGGERED_ROAM_FAILURE, NULL); 1653 1654 if (mlme_obj->cfg.gen.fatal_event_trigger) 1655 cds_flush_logs(WLAN_LOG_TYPE_FATAL, 1656 WLAN_LOG_INDICATOR_HOST_DRIVER, 1657 WLAN_LOG_REASON_ROAM_HO_FAILURE, false, false); 1658 1659 if (QDF_IS_STATUS_ERROR(status)) 1660 cm_remove_cmd(cm_ctx, &cm_id); 1661 1662 error: 1663 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 1664 qdf_mem_free(ind); 1665 1666 return QDF_STATUS_SUCCESS; 1667 } 1668 1669 void cm_fw_ho_fail_req(struct wlan_objmgr_psoc *psoc, 1670 uint8_t vdev_id, struct qdf_mac_addr bssid) 1671 { 1672 QDF_STATUS status; 1673 struct scheduler_msg ind_msg = {0}; 1674 struct cm_ho_fail_ind *ind = NULL; 1675 1676 ind = qdf_mem_malloc(sizeof(*ind)); 1677 if (!ind) 1678 return; 1679 1680 ind->vdev_id = vdev_id; 1681 ind->psoc = psoc; 1682 ind->bssid = bssid; 1683 1684 ind_msg.bodyptr = ind; 1685 ind_msg.callback = cm_handle_ho_fail; 1686 1687 status = scheduler_post_message(QDF_MODULE_ID_MLME, QDF_MODULE_ID_OS_IF, 1688 QDF_MODULE_ID_OS_IF, &ind_msg); 1689 1690 if (QDF_IS_STATUS_ERROR(status)) { 1691 mlme_err("Failed to post HO fail indication on vdev_id %d", 1692 vdev_id); 1693 qdf_mem_free(ind); 1694 return; 1695 } 1696 } 1697 1698 QDF_STATUS wlan_cm_free_roam_synch_frame_ind(struct rso_config *rso_cfg) 1699 { 1700 struct roam_synch_frame_ind *frame_ind; 1701 1702 if (!rso_cfg) 1703 return QDF_STATUS_E_FAILURE; 1704 1705 frame_ind = &rso_cfg->roam_sync_frame_ind; 1706 1707 if (frame_ind->bcn_probe_rsp) { 1708 qdf_mem_free(frame_ind->bcn_probe_rsp); 1709 frame_ind->bcn_probe_rsp_len = 0; 1710 frame_ind->bcn_probe_rsp = NULL; 1711 } 1712 if (frame_ind->link_bcn_probe_rsp) { 1713 qdf_mem_free(frame_ind->link_bcn_probe_rsp); 1714 frame_ind->link_bcn_probe_rsp_len = 0; 1715 frame_ind->link_bcn_probe_rsp = NULL; 1716 } 1717 if (frame_ind->reassoc_req) { 1718 qdf_mem_free(frame_ind->reassoc_req); 1719 frame_ind->reassoc_req_len = 0; 1720 frame_ind->reassoc_req = NULL; 1721 } 1722 if (frame_ind->reassoc_rsp) { 1723 qdf_mem_free(frame_ind->reassoc_rsp); 1724 frame_ind->reassoc_rsp_len = 0; 1725 frame_ind->reassoc_rsp = NULL; 1726 } 1727 1728 return QDF_STATUS_SUCCESS; 1729 } 1730