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