1 /* 2 * Copyright (c) 2012-2015, 2020-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /** 19 * DOC: Implements connect specific APIs of connection manager 20 */ 21 22 #include "wlan_cm_main_api.h" 23 #include "wlan_scan_api.h" 24 #include "wlan_cm_roam.h" 25 #include "wlan_cm_sm.h" 26 #ifdef WLAN_POLICY_MGR_ENABLE 27 #include "wlan_policy_mgr_api.h" 28 #endif 29 #include <wlan_serialization_api.h> 30 #ifdef CONN_MGR_ADV_FEATURE 31 #include "wlan_dlm_api.h" 32 #include "wlan_cm_roam_api.h" 33 #include "wlan_tdls_api.h" 34 #include "wlan_mlo_t2lm.h" 35 #include "wlan_t2lm_api.h" 36 #endif 37 #include <wlan_utility.h> 38 #ifdef WLAN_FEATURE_11BE_MLO 39 #include <wlan_mlo_mgr_peer.h> 40 #endif 41 #include <wlan_mlo_mgr_link_switch.h> 42 #include <wlan_mlo_mgr_sta.h> 43 #include "wlan_mlo_mgr_op.h" 44 #include <wlan_objmgr_vdev_obj.h> 45 #include "wlan_psoc_mlme_api.h" 46 #include "wlan_scan_public_structs.h" 47 48 void 49 cm_fill_failure_resp_from_cm_id(struct cnx_mgr *cm_ctx, 50 struct wlan_cm_connect_resp *resp, 51 wlan_cm_id cm_id, 52 enum wlan_cm_connect_fail_reason reason) 53 { 54 resp->connect_status = QDF_STATUS_E_FAILURE; 55 resp->cm_id = cm_id; 56 resp->vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 57 resp->reason = reason; 58 /* Get bssid and ssid and freq for the cm id from the req list */ 59 cm_fill_bss_info_in_connect_rsp_by_cm_id(cm_ctx, cm_id, resp); 60 } 61 62 static QDF_STATUS cm_connect_cmd_timeout(struct cnx_mgr *cm_ctx, 63 wlan_cm_id cm_id) 64 { 65 struct wlan_cm_connect_resp *resp; 66 QDF_STATUS status; 67 68 resp = qdf_mem_malloc(sizeof(*resp)); 69 if (!resp) 70 return QDF_STATUS_E_NOMEM; 71 72 cm_fill_failure_resp_from_cm_id(cm_ctx, resp, cm_id, CM_SER_TIMEOUT); 73 status = cm_sm_deliver_event(cm_ctx->vdev, 74 WLAN_CM_SM_EV_CONNECT_FAILURE, 75 sizeof(*resp), resp); 76 qdf_mem_free(resp); 77 78 if (QDF_IS_STATUS_ERROR(status)) 79 cm_connect_handle_event_post_fail(cm_ctx, cm_id); 80 81 return status; 82 } 83 84 #ifdef WLAN_CM_USE_SPINLOCK 85 static QDF_STATUS cm_activate_connect_req_sched_cb(struct scheduler_msg *msg) 86 { 87 struct wlan_serialization_command *cmd = msg->bodyptr; 88 struct wlan_objmgr_vdev *vdev; 89 struct cnx_mgr *cm_ctx; 90 QDF_STATUS ret = QDF_STATUS_E_FAILURE; 91 92 if (!cmd) { 93 mlme_err("cmd is null"); 94 return QDF_STATUS_E_INVAL; 95 } 96 97 vdev = cmd->vdev; 98 if (!vdev) { 99 mlme_err("vdev is null"); 100 return QDF_STATUS_E_INVAL; 101 } 102 103 cm_ctx = cm_get_cm_ctx(vdev); 104 if (!cm_ctx) 105 return QDF_STATUS_E_INVAL; 106 107 ret = cm_sm_deliver_event(vdev, 108 WLAN_CM_SM_EV_CONNECT_ACTIVE, 109 sizeof(wlan_cm_id), 110 &cmd->cmd_id); 111 112 /* 113 * Called from scheduler context hence posting failure 114 */ 115 if (QDF_IS_STATUS_ERROR(ret)) { 116 mlme_err(CM_PREFIX_FMT "Activation failed for cmd:%d", 117 CM_PREFIX_REF(wlan_vdev_get_id(vdev), cmd->cmd_id), 118 cmd->cmd_type); 119 cm_connect_handle_event_post_fail(cm_ctx, cmd->cmd_id); 120 } 121 122 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 123 return ret; 124 } 125 126 static QDF_STATUS 127 cm_activate_connect_req(struct wlan_serialization_command *cmd) 128 { 129 struct wlan_objmgr_vdev *vdev = cmd->vdev; 130 struct scheduler_msg msg = {0}; 131 QDF_STATUS ret; 132 133 msg.bodyptr = cmd; 134 msg.callback = cm_activate_connect_req_sched_cb; 135 msg.flush_callback = cm_activate_cmd_req_flush_cb; 136 137 ret = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_MLME_CM_ID); 138 if (QDF_IS_STATUS_ERROR(ret)) 139 return ret; 140 141 ret = scheduler_post_message(QDF_MODULE_ID_MLME, 142 QDF_MODULE_ID_MLME, 143 QDF_MODULE_ID_MLME, &msg); 144 145 if (QDF_IS_STATUS_ERROR(ret)) { 146 mlme_err(CM_PREFIX_FMT "Failed to post scheduler_msg", 147 CM_PREFIX_REF(wlan_vdev_get_id(vdev), cmd->cmd_id)); 148 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 149 return ret; 150 } 151 mlme_debug(CM_PREFIX_FMT "Cmd act in sched cmd type:%d", 152 CM_PREFIX_REF(wlan_vdev_get_id(vdev), cmd->cmd_id), 153 cmd->cmd_type); 154 155 return ret; 156 } 157 #else 158 static QDF_STATUS 159 cm_activate_connect_req(struct wlan_serialization_command *cmd) 160 { 161 return cm_sm_deliver_event(cmd->vdev, 162 WLAN_CM_SM_EV_CONNECT_ACTIVE, 163 sizeof(wlan_cm_id), 164 &cmd->cmd_id); 165 } 166 #endif 167 168 static QDF_STATUS 169 cm_ser_connect_cb(struct wlan_serialization_command *cmd, 170 enum wlan_serialization_cb_reason reason) 171 { 172 QDF_STATUS status = QDF_STATUS_SUCCESS; 173 struct wlan_objmgr_vdev *vdev; 174 struct cnx_mgr *cm_ctx; 175 176 if (!cmd) { 177 mlme_err("cmd is NULL, reason: %d", reason); 178 QDF_ASSERT(0); 179 return QDF_STATUS_E_NULL_VALUE; 180 } 181 182 vdev = cmd->vdev; 183 184 cm_ctx = cm_get_cm_ctx(vdev); 185 if (!cm_ctx) 186 return QDF_STATUS_E_NULL_VALUE; 187 188 switch (reason) { 189 case WLAN_SER_CB_ACTIVATE_CMD: 190 /* 191 * For pending to active reason, use async api to take lock. 192 * For direct activation use sync api to avoid taking lock 193 * as lock is already acquired by the requester. 194 */ 195 if (cmd->activation_reason == SER_PENDING_TO_ACTIVE) 196 status = cm_activate_connect_req(cmd); 197 else 198 status = cm_sm_deliver_event_sync(cm_ctx, 199 WLAN_CM_SM_EV_CONNECT_ACTIVE, 200 sizeof(wlan_cm_id), 201 &cmd->cmd_id); 202 if (QDF_IS_STATUS_SUCCESS(status)) 203 break; 204 /* 205 * Handle failure if posting fails, i.e. the SM state has 206 * changed or head cm_id doesn't match the active cm_id. 207 * connect active should be handled only in JOIN_PENDING. If 208 * new command has been received connect activation should be 209 * aborted from here with connect req cleanup. 210 */ 211 cm_connect_handle_event_post_fail(cm_ctx, cmd->cmd_id); 212 break; 213 case WLAN_SER_CB_CANCEL_CMD: 214 /* command removed from pending list. */ 215 break; 216 case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT: 217 mlme_err(CM_PREFIX_FMT "Active command timeout", 218 CM_PREFIX_REF(wlan_vdev_get_id(vdev), cmd->cmd_id)); 219 cm_trigger_panic_on_cmd_timeout(cm_ctx->vdev); 220 cm_connect_cmd_timeout(cm_ctx, cmd->cmd_id); 221 break; 222 case WLAN_SER_CB_RELEASE_MEM_CMD: 223 cm_reset_active_cm_id(vdev, cmd->cmd_id); 224 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 225 break; 226 default: 227 QDF_ASSERT(0); 228 status = QDF_STATUS_E_INVAL; 229 break; 230 } 231 232 return status; 233 } 234 235 static QDF_STATUS cm_ser_connect_req(struct wlan_objmgr_pdev *pdev, 236 struct cnx_mgr *cm_ctx, 237 struct cm_connect_req *cm_req) 238 { 239 struct wlan_serialization_command cmd = {0, }; 240 enum wlan_serialization_status ser_cmd_status; 241 QDF_STATUS status; 242 uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 243 244 status = wlan_objmgr_vdev_try_get_ref(cm_ctx->vdev, WLAN_MLME_CM_ID); 245 if (QDF_IS_STATUS_ERROR(status)) { 246 mlme_err(CM_PREFIX_FMT "unable to get reference", 247 CM_PREFIX_REF(vdev_id, cm_req->cm_id)); 248 return status; 249 } 250 251 cmd.cmd_type = WLAN_SER_CMD_VDEV_CONNECT; 252 cmd.cmd_id = cm_req->cm_id; 253 cmd.cmd_cb = cm_ser_connect_cb; 254 cmd.source = WLAN_UMAC_COMP_MLME; 255 cmd.is_high_priority = false; 256 cmd.cmd_timeout_duration = cm_ctx->connect_timeout; 257 cmd.vdev = cm_ctx->vdev; 258 cmd.is_blocking = true; 259 260 ser_cmd_status = wlan_serialization_request(&cmd); 261 switch (ser_cmd_status) { 262 case WLAN_SER_CMD_PENDING: 263 /* command moved to pending list.Do nothing */ 264 break; 265 case WLAN_SER_CMD_ACTIVE: 266 /* command moved to active list. Do nothing */ 267 break; 268 default: 269 mlme_err(CM_PREFIX_FMT "ser cmd status %d", 270 CM_PREFIX_REF(vdev_id, cm_req->cm_id), ser_cmd_status); 271 wlan_objmgr_vdev_release_ref(cm_ctx->vdev, WLAN_MLME_CM_ID); 272 273 return QDF_STATUS_E_FAILURE; 274 } 275 276 return QDF_STATUS_SUCCESS; 277 } 278 279 void 280 cm_connect_handle_event_post_fail(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id) 281 { 282 struct wlan_cm_connect_resp *resp; 283 284 resp = qdf_mem_malloc(sizeof(*resp)); 285 if (!resp) 286 return; 287 288 cm_fill_failure_resp_from_cm_id(cm_ctx, resp, cm_id, 289 CM_ABORT_DUE_TO_NEW_REQ_RECVD); 290 cm_connect_complete(cm_ctx, resp); 291 qdf_mem_free(resp); 292 } 293 294 QDF_STATUS 295 cm_send_connect_start_fail(struct cnx_mgr *cm_ctx, 296 struct cm_connect_req *req, 297 enum wlan_cm_connect_fail_reason reason) 298 { 299 struct wlan_cm_connect_resp *resp; 300 QDF_STATUS status; 301 302 resp = qdf_mem_malloc(sizeof(*resp)); 303 if (!resp) 304 return QDF_STATUS_E_NOMEM; 305 306 cm_fill_failure_resp_from_cm_id(cm_ctx, resp, req->cm_id, reason); 307 308 status = cm_sm_deliver_event_sync(cm_ctx, WLAN_CM_SM_EV_CONNECT_FAILURE, 309 sizeof(*resp), resp); 310 qdf_mem_free(resp); 311 312 return status; 313 } 314 315 #ifdef WLAN_POLICY_MGR_ENABLE 316 317 QDF_STATUS cm_handle_hw_mode_change(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id, 318 enum wlan_cm_sm_evt event) 319 { 320 struct cm_req *cm_req; 321 enum wlan_cm_connect_fail_reason reason = CM_GENERIC_FAILURE; 322 struct wlan_objmgr_pdev *pdev; 323 QDF_STATUS status; 324 325 if (!cm_id) 326 return QDF_STATUS_E_FAILURE; 327 328 cm_req = cm_get_req_by_cm_id(cm_ctx, *cm_id); 329 if (!cm_req) 330 return QDF_STATUS_E_INVAL; 331 332 pdev = wlan_vdev_get_pdev(cm_ctx->vdev); 333 if (!pdev) { 334 mlme_err(CM_PREFIX_FMT "Failed to find pdev", 335 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), 336 cm_req->cm_id)); 337 goto send_failure; 338 } 339 340 if (event == WLAN_CM_SM_EV_HW_MODE_SUCCESS) { 341 status = cm_ser_connect_req(pdev, cm_ctx, &cm_req->connect_req); 342 if (QDF_IS_STATUS_ERROR(status)) { 343 reason = CM_SER_FAILURE; 344 goto send_failure; 345 } 346 return status; 347 } 348 349 /* Set reason HW mode fail for event WLAN_CM_SM_EV_HW_MODE_FAILURE */ 350 reason = CM_HW_MODE_FAILURE; 351 352 send_failure: 353 return cm_send_connect_start_fail(cm_ctx, &cm_req->connect_req, reason); 354 } 355 356 void cm_hw_mode_change_resp(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, 357 wlan_cm_id cm_id, QDF_STATUS status) 358 { 359 struct wlan_objmgr_vdev *vdev; 360 QDF_STATUS qdf_status; 361 enum wlan_cm_sm_evt event = WLAN_CM_SM_EV_HW_MODE_SUCCESS; 362 struct cnx_mgr *cm_ctx; 363 364 mlme_debug(CM_PREFIX_FMT "Continue connect after HW mode change, status %d", 365 CM_PREFIX_REF(vdev_id, cm_id), status); 366 367 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, 368 WLAN_MLME_CM_ID); 369 if (!vdev) 370 return; 371 372 cm_ctx = cm_get_cm_ctx(vdev); 373 if (!cm_ctx) { 374 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 375 return; 376 } 377 378 if (QDF_IS_STATUS_ERROR(status)) 379 event = WLAN_CM_SM_EV_HW_MODE_FAILURE; 380 qdf_status = cm_sm_deliver_event(vdev, event, sizeof(wlan_cm_id), 381 &cm_id); 382 383 /* 384 * Handle failure if posting fails, i.e. the SM state has 385 * changed or head cm_id doesn't match the active cm_id. 386 * hw mode change resp should be handled only in JOIN_PENDING. If 387 * new command has been received connect should be 388 * aborted from here with connect req cleanup. 389 */ 390 if (QDF_IS_STATUS_ERROR(status)) 391 cm_connect_handle_event_post_fail(cm_ctx, cm_id); 392 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID); 393 } 394 395 static QDF_STATUS cm_check_for_hw_mode_change(struct wlan_objmgr_psoc *psoc, 396 qdf_list_t *scan_list, 397 uint8_t vdev_id, 398 wlan_cm_id connect_id) 399 { 400 return policy_mgr_change_hw_mode_sta_connect(psoc, scan_list, vdev_id, 401 connect_id); 402 } 403 404 405 #else 406 407 static inline 408 QDF_STATUS cm_check_for_hw_mode_change(struct wlan_objmgr_psoc *psoc, 409 qdf_list_t *scan_list, uint8_t vdev_id, 410 uint8_t connect_id) 411 { 412 return QDF_STATUS_E_ALREADY; 413 } 414 415 #endif /* WLAN_POLICY_MGR_ENABLE */ 416 417 static inline void cm_delete_pmksa_for_bssid(struct cnx_mgr *cm_ctx, 418 struct qdf_mac_addr *bssid) 419 { 420 struct wlan_crypto_pmksa pmksa; 421 422 qdf_mem_zero(&pmksa, sizeof(pmksa)); 423 qdf_copy_macaddr(&pmksa.bssid, bssid); 424 wlan_crypto_set_del_pmksa(cm_ctx->vdev, &pmksa, false); 425 } 426 427 #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD) 428 static inline 429 void cm_delete_pmksa_for_single_pmk_bssid(struct cnx_mgr *cm_ctx, 430 struct qdf_mac_addr *bssid) 431 { 432 cm_delete_pmksa_for_bssid(cm_ctx, bssid); 433 } 434 #else 435 static inline 436 void cm_delete_pmksa_for_single_pmk_bssid(struct cnx_mgr *cm_ctx, 437 struct qdf_mac_addr *bssid) 438 { 439 } 440 #endif /* WLAN_SAE_SINGLE_PMK && WLAN_FEATURE_ROAM_OFFLOAD */ 441 442 static inline void 443 cm_set_pmf_caps(struct wlan_cm_connect_req *req, struct scan_filter *filter) 444 { 445 if (req->crypto.rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED) 446 filter->pmf_cap = WLAN_PMF_REQUIRED; 447 else if (req->crypto.rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED) 448 filter->pmf_cap = WLAN_PMF_CAPABLE; 449 else 450 filter->pmf_cap = WLAN_PMF_DISABLED; 451 } 452 453 #ifdef WLAN_FEATURE_11BE_MLO 454 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 455 static inline 456 void cm_set_vdev_link_id(struct cnx_mgr *cm_ctx, 457 struct cm_connect_req *req) 458 { 459 uint8_t link_id; 460 461 link_id = req->cur_candidate->entry->ml_info.self_link_id; 462 mlme_debug(CM_PREFIX_FMT "setting link ID to %d", 463 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), req->cm_id), 464 link_id); 465 wlan_vdev_set_link_id(cm_ctx->vdev, link_id); 466 } 467 468 static QDF_STATUS cm_update_vdev_mlme_macaddr(struct cnx_mgr *cm_ctx, 469 struct cm_connect_req *req) 470 { 471 struct qdf_mac_addr *mac; 472 bool eht_capab; 473 uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 474 475 if (wlan_vdev_mlme_get_opmode(cm_ctx->vdev) != QDF_STA_MODE) 476 return QDF_STATUS_SUCCESS; 477 478 wlan_psoc_mlme_get_11be_capab(wlan_vdev_get_psoc(cm_ctx->vdev), 479 &eht_capab); 480 if (!eht_capab) 481 return QDF_STATUS_SUCCESS; 482 483 mac = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(cm_ctx->vdev); 484 485 if (req->cur_candidate->entry->ie_list.multi_link_bv && 486 !qdf_is_macaddr_zero(mac) && 487 wlan_cm_is_eht_allowed_for_current_security( 488 req->cur_candidate->entry)) { 489 wlan_vdev_obj_lock(cm_ctx->vdev); 490 /* Use link address for ML connection */ 491 wlan_vdev_mlme_set_macaddr(cm_ctx->vdev, 492 cm_ctx->vdev->vdev_mlme.linkaddr); 493 wlan_vdev_obj_unlock(cm_ctx->vdev); 494 wlan_vdev_mlme_set_mlo_vdev(cm_ctx->vdev); 495 mlme_debug(CM_PREFIX_FMT "setting ML link address " QDF_MAC_ADDR_FMT, 496 CM_PREFIX_REF(vdev_id, req->cm_id), 497 QDF_MAC_ADDR_REF(mac->bytes)); 498 } else { 499 if (wlan_vdev_mlme_is_mlo_link_vdev(cm_ctx->vdev)) { 500 mlme_debug(CM_PREFIX_FMT "MLIE is not present for partner" QDF_MAC_ADDR_FMT, 501 CM_PREFIX_REF(vdev_id, req->cm_id), 502 QDF_MAC_ADDR_REF(mac->bytes)); 503 return QDF_STATUS_E_INVAL; 504 } 505 506 /* Use net_dev address for non-ML connection */ 507 if (!qdf_is_macaddr_zero(mac)) { 508 wlan_vdev_obj_lock(cm_ctx->vdev); 509 wlan_vdev_mlme_set_macaddr(cm_ctx->vdev, mac->bytes); 510 wlan_vdev_obj_unlock(cm_ctx->vdev); 511 mlme_debug(CM_PREFIX_FMT "setting non-ML address " QDF_MAC_ADDR_FMT, 512 CM_PREFIX_REF(vdev_id, req->cm_id), 513 QDF_MAC_ADDR_REF(mac->bytes)); 514 } 515 wlan_vdev_mlme_clear_mlo_vdev(cm_ctx->vdev); 516 } 517 518 return QDF_STATUS_SUCCESS; 519 } 520 #else 521 static inline 522 void cm_set_vdev_link_id(struct cnx_mgr *cm_ctx, 523 struct cm_connect_req *req) 524 { } 525 526 static QDF_STATUS cm_update_vdev_mlme_macaddr(struct cnx_mgr *cm_ctx, 527 struct cm_connect_req *req) 528 { 529 return QDF_STATUS_SUCCESS; 530 } 531 #endif 532 /** 533 * cm_get_bss_peer_mld_addr() - get bss peer mld mac address 534 * @req: pointer to cm_connect_req 535 * 536 * Return: mld mac address 537 */ 538 static struct qdf_mac_addr *cm_get_bss_peer_mld_addr(struct cm_connect_req *req) 539 { 540 if (req && req->cur_candidate && req->cur_candidate->entry) 541 return &req->cur_candidate->entry->ml_info.mld_mac_addr; 542 else 543 return NULL; 544 } 545 546 /** 547 * cm_bss_peer_is_assoc_peer() - is the bss peer to be created assoc peer or not 548 * @req: pointer to cm_connect_req 549 * 550 * Return: true if the bss peer to be created is assoc peer 551 */ 552 static bool cm_bss_peer_is_assoc_peer(struct cm_connect_req *req) 553 { 554 if (req) 555 return !req->req.is_non_assoc_link; 556 557 return false; 558 } 559 560 /** 561 * cm_candidate_mlo_update() - handle mlo scenario for candidate validating 562 * @scan_entry: scan result of the candidate 563 * @validate_bss_info: candidate info to be updated 564 * 565 * Return: None 566 */ 567 static void 568 cm_candidate_mlo_update(struct scan_cache_entry *scan_entry, 569 struct validate_bss_data *validate_bss_info) 570 { 571 validate_bss_info->is_mlo = !!scan_entry->ie_list.multi_link_bv; 572 validate_bss_info->scan_entry = scan_entry; 573 } 574 575 #else 576 static inline 577 void cm_set_vdev_link_id(struct cnx_mgr *cm_ctx, 578 struct cm_connect_req *req) 579 { } 580 581 static QDF_STATUS cm_update_vdev_mlme_macaddr(struct cnx_mgr *cm_ctx, 582 struct cm_connect_req *req) 583 { 584 return QDF_STATUS_SUCCESS; 585 } 586 587 static struct qdf_mac_addr *cm_get_bss_peer_mld_addr(struct cm_connect_req *req) 588 { 589 return NULL; 590 } 591 592 static bool cm_bss_peer_is_assoc_peer(struct cm_connect_req *req) 593 { 594 return false; 595 } 596 597 static inline void 598 cm_candidate_mlo_update(struct scan_cache_entry *scan_entry, 599 struct validate_bss_data *validate_bss_info) 600 { 601 } 602 #endif 603 604 static void cm_create_bss_peer(struct cnx_mgr *cm_ctx, 605 struct cm_connect_req *req) 606 { 607 QDF_STATUS status; 608 struct qdf_mac_addr *bssid; 609 struct qdf_mac_addr *mld_mac = NULL; 610 bool is_assoc_link = false; 611 bool eht_capab; 612 613 if (!cm_ctx) { 614 mlme_err("invalid cm_ctx"); 615 return; 616 } 617 618 if (mlo_is_sta_bridge_vdev(cm_ctx->vdev) && req) { 619 /* Acquire lock as required by wlan_vdev_mlme_get_mldaddr() */ 620 wlan_vdev_obj_lock(cm_ctx->vdev); 621 bssid = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(cm_ctx->vdev); 622 wlan_vdev_obj_unlock(cm_ctx->vdev); 623 mld_mac = mlo_get_sta_ctx_bss_mld_addr(cm_ctx->vdev); 624 status = mlme_cm_bss_peer_create_req(cm_ctx->vdev, 625 bssid, 626 mld_mac, 627 is_assoc_link); 628 goto peer_create_fail; 629 } 630 631 if (!req || !req->cur_candidate || !req->cur_candidate->entry) { 632 mlme_err("invalid req"); 633 return; 634 } 635 636 wlan_psoc_mlme_get_11be_capab(wlan_vdev_get_psoc(cm_ctx->vdev), 637 &eht_capab); 638 if (eht_capab && wlan_vdev_mlme_is_mlo_vdev(cm_ctx->vdev) && 639 wlan_cm_is_eht_allowed_for_current_security( 640 req->cur_candidate->entry)) { 641 cm_set_vdev_link_id(cm_ctx, req); 642 wlan_mlo_init_cu_bpcc(cm_ctx->vdev); 643 mld_mac = cm_get_bss_peer_mld_addr(req); 644 mlo_set_sta_ctx_bss_mld_addr(cm_ctx->vdev, mld_mac); 645 is_assoc_link = cm_bss_peer_is_assoc_peer(req); 646 } 647 648 bssid = &req->cur_candidate->entry->bssid; 649 status = mlme_cm_bss_peer_create_req(cm_ctx->vdev, bssid, 650 mld_mac, is_assoc_link); 651 peer_create_fail: 652 if (QDF_IS_STATUS_ERROR(status)) { 653 struct wlan_cm_connect_resp *resp; 654 uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 655 656 /* In case of failure try with next candidate */ 657 mlme_err(CM_PREFIX_FMT "peer create request failed %d", 658 CM_PREFIX_REF(vdev_id, req->cm_id), status); 659 660 resp = qdf_mem_malloc(sizeof(*resp)); 661 if (!resp) 662 return; 663 664 cm_fill_failure_resp_from_cm_id(cm_ctx, resp, req->cm_id, 665 CM_PEER_CREATE_FAILED); 666 cm_sm_deliver_event_sync(cm_ctx, 667 WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE, 668 sizeof(*resp), resp); 669 qdf_mem_free(resp); 670 } 671 } 672 673 #if defined(CONN_MGR_ADV_FEATURE) && defined(WLAN_FEATURE_11BE_MLO) 674 static QDF_STATUS 675 cm_t2lm_validate_candidate(struct cnx_mgr *cm_ctx, 676 struct scan_cache_entry *scan_entry) 677 { 678 return wlan_t2lm_validate_candidate(cm_ctx, scan_entry); 679 } 680 #else 681 static inline QDF_STATUS 682 cm_t2lm_validate_candidate(struct cnx_mgr *cm_ctx, 683 struct scan_cache_entry *scan_entry) 684 { 685 return QDF_STATUS_SUCCESS; 686 } 687 #endif 688 689 static 690 QDF_STATUS cm_if_mgr_validate_candidate(struct cnx_mgr *cm_ctx, 691 struct scan_cache_entry *scan_entry) 692 { 693 struct if_mgr_event_data event_data = {0}; 694 QDF_STATUS status = QDF_STATUS_SUCCESS; 695 696 event_data.validate_bss_info.chan_freq = scan_entry->channel.chan_freq; 697 event_data.validate_bss_info.beacon_interval = scan_entry->bcn_int; 698 qdf_copy_macaddr(&event_data.validate_bss_info.peer_addr, 699 &scan_entry->bssid); 700 cm_candidate_mlo_update(scan_entry, &event_data.validate_bss_info); 701 702 status = cm_t2lm_validate_candidate(cm_ctx, scan_entry); 703 if (QDF_IS_STATUS_ERROR(status)) 704 return status; 705 706 return if_mgr_deliver_event(cm_ctx->vdev, 707 WLAN_IF_MGR_EV_VALIDATE_CANDIDATE, 708 &event_data); 709 } 710 711 #ifdef CONN_MGR_ADV_FEATURE 712 #ifdef WLAN_FEATURE_FILS_SK 713 /* 714 * cm_create_fils_realm_hash: API to create hash using realm 715 * @fils_info: fils connection info obtained from supplicant 716 * @tmp_hash: pointer to new hash 717 * 718 * Return: QDF_STATUS 719 */ 720 static QDF_STATUS 721 cm_create_fils_realm_hash(struct wlan_fils_con_info *fils_info, 722 uint8_t *tmp_hash) 723 { 724 uint8_t *hash; 725 uint8_t *data; 726 727 if (!fils_info->realm_len) 728 return QDF_STATUS_E_NOSUPPORT; 729 730 hash = qdf_mem_malloc(SHA256_DIGEST_SIZE); 731 if (!hash) 732 return QDF_STATUS_E_NOMEM; 733 734 data = fils_info->realm; 735 qdf_get_hash(SHA256_CRYPTO_TYPE, 1, &data, &fils_info->realm_len, hash); 736 qdf_mem_copy(tmp_hash, hash, REALM_HASH_LEN); 737 qdf_mem_free(hash); 738 739 return QDF_STATUS_SUCCESS; 740 } 741 742 static void cm_update_fils_scan_filter(struct scan_filter *filter, 743 struct cm_connect_req *cm_req) 744 745 { 746 uint8_t realm_hash[REALM_HASH_LEN]; 747 QDF_STATUS status; 748 749 if (!cm_req->req.fils_info.is_fils_connection) 750 return; 751 752 status = cm_create_fils_realm_hash(&cm_req->req.fils_info, realm_hash); 753 if (QDF_IS_STATUS_ERROR(status)) 754 return; 755 756 filter->fils_scan_filter.realm_check = true; 757 mlme_debug(CM_PREFIX_FMT "creating realm based on fils info", 758 CM_PREFIX_REF(cm_req->req.vdev_id, cm_req->cm_id)); 759 qdf_mem_copy(filter->fils_scan_filter.fils_realm, realm_hash, 760 REALM_HASH_LEN); 761 } 762 763 static inline bool cm_is_fils_connection(struct wlan_cm_connect_resp *resp) 764 { 765 return resp->is_fils_connection; 766 } 767 768 static QDF_STATUS cm_set_fils_key(struct cnx_mgr *cm_ctx, 769 struct wlan_cm_connect_resp *resp) 770 { 771 struct fils_connect_rsp_params *fils_ie; 772 773 fils_ie = resp->connect_ies.fils_ie; 774 775 if (!fils_ie) 776 return QDF_STATUS_E_INVAL; 777 778 cm_store_fils_key(cm_ctx, true, 0, fils_ie->tk_len, fils_ie->tk, 779 &resp->bssid, resp->cm_id); 780 cm_store_fils_key(cm_ctx, false, 2, fils_ie->gtk_len, fils_ie->gtk, 781 &resp->bssid, resp->cm_id); 782 cm_set_key(cm_ctx, true, 0, &resp->bssid); 783 cm_set_key(cm_ctx, false, 2, &resp->bssid); 784 785 return QDF_STATUS_SUCCESS; 786 } 787 788 #else 789 static inline void cm_update_fils_scan_filter(struct scan_filter *filter, 790 struct cm_connect_req *cm_req) 791 { } 792 793 static inline bool cm_is_fils_connection(struct wlan_cm_connect_resp *resp) 794 { 795 return false; 796 } 797 798 static inline QDF_STATUS cm_set_fils_key(struct cnx_mgr *cm_ctx, 799 struct wlan_cm_connect_resp *resp) 800 { 801 return QDF_STATUS_SUCCESS; 802 } 803 #endif /* WLAN_FEATURE_FILS_SK */ 804 805 /** 806 * cm_get_vdev_id_with_active_vdev_op() - Get vdev id from serialization 807 * pending queue for which disconnect or connect is ongoing 808 * @pdev: pdev common object 809 * @object: vdev object 810 * @arg: vdev operation search arg 811 * 812 * Return: None 813 */ 814 static void cm_get_vdev_id_with_active_vdev_op(struct wlan_objmgr_pdev *pdev, 815 void *object, void *arg) 816 { 817 struct vdev_op_search_arg *vdev_arg = arg; 818 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object; 819 uint8_t vdev_id = wlan_vdev_get_id(vdev); 820 enum QDF_OPMODE opmode = wlan_vdev_mlme_get_opmode(vdev); 821 822 if (!vdev_arg) 823 return; 824 825 /* Avoid same vdev id check */ 826 if (vdev_arg->current_vdev_id == vdev_id) 827 return; 828 829 if (opmode == QDF_STA_MODE || opmode == QDF_P2P_CLIENT_MODE) { 830 if (cm_is_vdev_disconnecting(vdev)) 831 vdev_arg->sta_cli_vdev_id = vdev_id; 832 return; 833 } 834 835 if (opmode == QDF_SAP_MODE || opmode == QDF_P2P_GO_MODE || 836 opmode == QDF_NDI_MODE) { 837 /* Check if START/STOP AP OP is in progress */ 838 if (wlan_ser_is_non_scan_cmd_type_in_vdev_queue(vdev, 839 WLAN_SER_CMD_VDEV_START_BSS) || 840 wlan_ser_is_non_scan_cmd_type_in_vdev_queue(vdev, 841 WLAN_SER_CMD_VDEV_STOP_BSS)) 842 vdev_arg->sap_go_vdev_id = vdev_id; 843 return; 844 } 845 } 846 847 /** 848 * cm_is_any_other_vdev_connecting_disconnecting() - check whether any other 849 * vdev is in waiting for vdev operations (connect/disconnect or start/stop AP) 850 * @cm_ctx: connection manager context 851 * @cm_req: Connect request. 852 * 853 * As Connect is a blocking call this API will make sure the vdev operations on 854 * other vdev doesn't starve 855 * 856 * Return : true if any other vdev has pending operation 857 */ 858 static bool 859 cm_is_any_other_vdev_connecting_disconnecting(struct cnx_mgr *cm_ctx, 860 struct cm_req *cm_req) 861 { 862 struct wlan_objmgr_pdev *pdev; 863 uint8_t cur_vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 864 struct vdev_op_search_arg vdev_arg; 865 866 pdev = wlan_vdev_get_pdev(cm_ctx->vdev); 867 if (!pdev) { 868 mlme_err(CM_PREFIX_FMT "Failed to find pdev", 869 CM_PREFIX_REF(cur_vdev_id, cm_req->cm_id)); 870 return false; 871 } 872 873 vdev_arg.current_vdev_id = cur_vdev_id; 874 vdev_arg.sap_go_vdev_id = WLAN_INVALID_VDEV_ID; 875 vdev_arg.sta_cli_vdev_id = WLAN_INVALID_VDEV_ID; 876 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, 877 cm_get_vdev_id_with_active_vdev_op, 878 &vdev_arg, 0, 879 WLAN_MLME_CM_ID); 880 881 /* For STA/CLI avoid the fist candidate itself if possible */ 882 if (vdev_arg.sta_cli_vdev_id != WLAN_INVALID_VDEV_ID) { 883 mlme_info(CM_PREFIX_FMT "Abort connection as sta/cli vdev %d is disconnecting", 884 CM_PREFIX_REF(cur_vdev_id, cm_req->cm_id), 885 vdev_arg.sta_cli_vdev_id); 886 return true; 887 } 888 889 /* 890 * For SAP/GO ops pending avoid the next candidate, this is to support 891 * wifi sharing etc use case where we need to connect to AP in parallel 892 * to SAP operation, so try atleast one candidate. 893 */ 894 if (cm_req->connect_req.cur_candidate && 895 vdev_arg.sap_go_vdev_id != WLAN_INVALID_VDEV_ID) { 896 mlme_info(CM_PREFIX_FMT "Avoid next candidate as SAP/GO/NDI vdev %d has pending vdev op", 897 CM_PREFIX_REF(cur_vdev_id, cm_req->cm_id), 898 vdev_arg.sap_go_vdev_id); 899 return true; 900 } 901 902 return false; 903 } 904 905 QDF_STATUS 906 cm_inform_dlm_connect_complete(struct wlan_objmgr_vdev *vdev, 907 struct wlan_cm_connect_resp *resp) 908 { 909 struct wlan_objmgr_pdev *pdev; 910 911 pdev = wlan_vdev_get_pdev(vdev); 912 if (!pdev) { 913 mlme_err(CM_PREFIX_FMT "Failed to find pdev", 914 CM_PREFIX_REF(wlan_vdev_get_id(vdev), resp->cm_id)); 915 return QDF_STATUS_E_FAILURE; 916 } 917 918 if (QDF_IS_STATUS_SUCCESS(resp->connect_status)) 919 wlan_dlm_update_bssid_connect_params(pdev, resp->bssid, 920 DLM_AP_CONNECTED); 921 922 return QDF_STATUS_SUCCESS; 923 } 924 925 #ifdef WLAN_FEATURE_11BE_MLO 926 static bool 927 cm_update_mlo_links_for_retry_with_same_candidate(struct wlan_objmgr_psoc *psoc, 928 struct cm_connect_req *cm_req) 929 { 930 uint8_t mlo_link_num; 931 struct scan_cache_entry *entry; 932 933 if (!cm_req->req.ml_parnter_info.num_partner_links) 934 return false; 935 936 entry = cm_req->cur_candidate->entry; 937 938 mlo_link_num = wlan_mlme_get_sta_mlo_conn_max_num(psoc); 939 if (cm_req->req.ml_parnter_info.num_partner_links > mlo_link_num) 940 cm_req->req.ml_parnter_info.num_partner_links = mlo_link_num; 941 942 /* 943 * Try next candidate for non-ML AP 944 */ 945 if (!entry->ie_list.multi_link_bv || !entry->ml_info.num_links) { 946 cm_req->req.ml_parnter_info.num_partner_links = NO_LINK; 947 return false; 948 } 949 950 if (cm_req->req.ml_parnter_info.num_partner_links > NO_LINK) { 951 /* 952 * Try to same AP exhaustively till single link ML connection 953 * is tried with the AP 954 */ 955 cm_req->req.ml_parnter_info.num_partner_links--; 956 } 957 958 mlme_debug(CM_PREFIX_FMT "try ML connection with %d partner links", 959 CM_PREFIX_REF(cm_req->req.vdev_id, cm_req->cm_id), 960 cm_req->req.ml_parnter_info.num_partner_links); 961 962 return true; 963 } 964 #else 965 static inline bool 966 cm_update_mlo_links_for_retry_with_same_candidate(struct wlan_objmgr_psoc *psoc, 967 struct cm_connect_req *cm_req) 968 { 969 return false; 970 } 971 #endif 972 973 /** 974 * cm_is_retry_with_same_candidate() - This API check if reconnect attempt is 975 * required with the same candidate again 976 * @cm_ctx: connection manager context 977 * @req: Connect request. 978 * @resp: connect resp from previous connection attempt 979 * 980 * This function return true if same candidate needs to be tried again 981 * 982 * Return: bool 983 */ 984 static bool cm_is_retry_with_same_candidate(struct cnx_mgr *cm_ctx, 985 struct cm_connect_req *req, 986 struct wlan_cm_connect_resp *resp) 987 { 988 uint8_t max_retry_count = CM_MAX_CANDIDATE_RETRIES; 989 uint32_t key_mgmt; 990 struct wlan_objmgr_psoc *psoc; 991 bool sae_connection; 992 QDF_STATUS status; 993 qdf_freq_t freq; 994 struct scoring_cfg *score_config; 995 struct psoc_mlme_obj *mlme_psoc_obj; 996 997 psoc = wlan_pdev_get_psoc(wlan_vdev_get_pdev(cm_ctx->vdev)); 998 mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc); 999 if (!mlme_psoc_obj) 1000 return false; 1001 1002 score_config = &mlme_psoc_obj->psoc_cfg.score_config; 1003 key_mgmt = req->cur_candidate->entry->neg_sec_info.key_mgmt; 1004 freq = req->cur_candidate->entry->channel.chan_freq; 1005 1006 /* Try once again for the invalid PMKID case without PMKID */ 1007 if (resp->status_code == STATUS_INVALID_PMKID) { 1008 if (score_config->vendor_roam_score_algorithm) 1009 cm_update_mlo_links_for_retry_with_same_candidate(psoc, 1010 req); 1011 goto use_same_candidate; 1012 } 1013 1014 /* Try again for the JOIN timeout if only one candidate */ 1015 if (resp->reason == CM_JOIN_TIMEOUT && 1016 qdf_list_size(req->candidate_list) == 1) { 1017 /* 1018 * If there is a interface connected which can lead to MCC, 1019 * do not retry as it can lead to beacon miss on that interface. 1020 * Coz as part of vdev start mac remain on candidate freq for 3 1021 * sec. 1022 */ 1023 if (policy_mgr_will_freq_lead_to_mcc(psoc, freq)) 1024 return false; 1025 1026 wlan_mlme_get_sae_assoc_retry_count(psoc, &max_retry_count); 1027 if (score_config->vendor_roam_score_algorithm) 1028 cm_update_mlo_links_for_retry_with_same_candidate(psoc, 1029 req); 1030 goto use_same_candidate; 1031 } 1032 1033 /* 1034 * Try again for the ASSOC timeout in SAE connection or 1035 * AP has reconnect on assoc timeout OUI. 1036 */ 1037 sae_connection = key_mgmt & (1 << WLAN_CRYPTO_KEY_MGMT_SAE | 1038 1 << WLAN_CRYPTO_KEY_MGMT_FT_SAE | 1039 1 << WLAN_CRYPTO_KEY_MGMT_SAE_EXT_KEY | 1040 1 << WLAN_CRYPTO_KEY_MGMT_FT_SAE_EXT_KEY); 1041 if (resp->reason == CM_ASSOC_TIMEOUT && (sae_connection || 1042 (mlme_get_reconn_after_assoc_timeout_flag(psoc, resp->vdev_id)))) { 1043 /* For SAE use max retry count from INI */ 1044 if (sae_connection) 1045 wlan_mlme_get_sae_assoc_retry_count(psoc, 1046 &max_retry_count); 1047 1048 if (score_config->vendor_roam_score_algorithm) 1049 cm_update_mlo_links_for_retry_with_same_candidate(psoc, 1050 req); 1051 goto use_same_candidate; 1052 } 1053 1054 /* 1055 * When vendor roam score algorithm is enabled and association failure 1056 * happens while trying MLO connection with multiple link, then 1057 * retry with same candidate with same primary link and other band as 1058 * secondary link. If still failure happens, then try standlone single 1059 * link MLO mode with the same candidate AP. Ex: 1060 * Priority 1(candidate AP’s 6 GHz case) – 6 GHz (Associating link) + 1061 * 5 GHz + 2.4 GHz 1062 * Priority 2(candidate AP’s 6 GHz case) – 6 GHz (Associating link) + 1063 * 2.4 GHz 1064 * Priority 3(AP’s 6 GHz case) – 6 GHz (single Link) 1065 */ 1066 if (resp->status_code && score_config->vendor_roam_score_algorithm && 1067 cm_update_mlo_links_for_retry_with_same_candidate(psoc, req)) 1068 goto use_same_candidate; 1069 1070 return false; 1071 1072 use_same_candidate: 1073 if (req->cur_candidate_retries >= max_retry_count) 1074 return false; 1075 1076 status = cm_if_mgr_validate_candidate(cm_ctx, 1077 req->cur_candidate->entry); 1078 if (QDF_IS_STATUS_ERROR(status)) 1079 return false; 1080 1081 mlme_info(CM_PREFIX_FMT "Retry again with " QDF_MAC_ADDR_FMT ", status code %d reason %d key_mgmt 0x%x retry count %d max retry %d", 1082 CM_PREFIX_REF(resp->vdev_id, resp->cm_id), 1083 QDF_MAC_ADDR_REF(resp->bssid.bytes), resp->status_code, 1084 resp->reason, key_mgmt, req->cur_candidate_retries, 1085 max_retry_count); 1086 1087 req->cur_candidate_retries++; 1088 1089 return true; 1090 } 1091 1092 /* 1093 * Do not allow last connect attempt after 25 sec, assuming last attempt will 1094 * complete in max 10 sec, total connect time will not be more than 35 sec. 1095 * Do not confuse this with active command timeout, that is taken care by 1096 * CM_MAX_PER_CANDIDATE_CONNECT_TIMEOUT 1097 */ 1098 #define CM_CONNECT_MAX_ACTIVE_TIME 25000 1099 1100 /** 1101 * cm_is_time_allowed_for_connect_attempt() - This API check if next connect 1102 * attempt can be tried within allocated time. 1103 * @cm_ctx: connection manager context 1104 * @req: Connect request. 1105 * 1106 * This function return true if connect attempt can be tried so that total time 1107 * taken by connect req do not exceed 30-35 seconds. 1108 * 1109 * Return: bool 1110 */ 1111 static bool cm_is_time_allowed_for_connect_attempt(struct cnx_mgr *cm_ctx, 1112 struct cm_connect_req *req) 1113 { 1114 qdf_time_t time_since_connect_active; 1115 uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 1116 1117 time_since_connect_active = qdf_mc_timer_get_system_time() - 1118 req->connect_active_time; 1119 if (time_since_connect_active >= CM_CONNECT_MAX_ACTIVE_TIME) { 1120 mlme_info(CM_PREFIX_FMT "Max time allocated (%d ms) for connect completed, cur time %lu, active time %lu and diff %lu", 1121 CM_PREFIX_REF(vdev_id, req->cm_id), 1122 CM_CONNECT_MAX_ACTIVE_TIME, 1123 qdf_mc_timer_get_system_time(), 1124 req->connect_active_time, 1125 time_since_connect_active); 1126 return false; 1127 } 1128 1129 return true; 1130 } 1131 1132 static inline void cm_update_advance_filter(struct wlan_objmgr_pdev *pdev, 1133 struct cnx_mgr *cm_ctx, 1134 struct scan_filter *filter, 1135 struct cm_connect_req *cm_req) 1136 { 1137 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); 1138 1139 /* Select only ESS type */ 1140 filter->bss_type = WLAN_TYPE_BSS; 1141 filter->enable_adaptive_11r = 1142 wlan_mlme_adaptive_11r_enabled(psoc); 1143 if (wlan_vdev_mlme_get_opmode(cm_ctx->vdev) != QDF_STA_MODE) 1144 return; 1145 /* For link vdev, we don't filter any channels. 1146 * Dual STA mode, one link can be disabled in post connection 1147 * if needed. 1148 */ 1149 if (!cm_req->req.is_non_assoc_link) 1150 wlan_cm_dual_sta_roam_update_connect_channels(psoc, filter); 1151 filter->dot11mode = cm_req->req.dot11mode_filter; 1152 cm_update_fils_scan_filter(filter, cm_req); 1153 } 1154 1155 static void cm_update_security_filter(struct scan_filter *filter, 1156 struct wlan_cm_connect_req *req) 1157 { 1158 /* Ignore security match for rsn override, OSEN and WPS connection */ 1159 if (req->force_rsne_override || req->is_wps_connection || 1160 req->is_osen_connection) { 1161 filter->ignore_auth_enc_type = 1; 1162 return; 1163 } 1164 1165 filter->authmodeset = req->crypto.auth_type; 1166 filter->ucastcipherset = req->crypto.ciphers_pairwise; 1167 filter->key_mgmt = req->crypto.akm_suites; 1168 filter->mcastcipherset = req->crypto.group_cipher; 1169 filter->mgmtcipherset = req->crypto.mgmt_ciphers; 1170 cm_set_pmf_caps(req, filter); 1171 } 1172 1173 /** 1174 * cm_set_fils_wep_key() - check and set wep or fils keys if required 1175 * @cm_ctx: connection manager context 1176 * @resp: connect resp 1177 * 1178 * Context: Can be called from any context and to be used only after posting a 1179 * msg to SM (ie holding the SM lock) i.e. on successful connection. 1180 */ 1181 static void cm_set_fils_wep_key(struct cnx_mgr *cm_ctx, 1182 struct wlan_cm_connect_resp *resp) 1183 { 1184 int32_t cipher; 1185 struct qdf_mac_addr broadcast_mac = QDF_MAC_ADDR_BCAST_INIT; 1186 1187 /* Check and set FILS keys */ 1188 if (cm_is_fils_connection(resp)) { 1189 cm_set_fils_key(cm_ctx, resp); 1190 return; 1191 } 1192 /* Check and set WEP keys */ 1193 cipher = wlan_crypto_get_param(cm_ctx->vdev, 1194 WLAN_CRYPTO_PARAM_UCAST_CIPHER); 1195 if (cipher < 0) 1196 return; 1197 1198 if (!(cipher & (1 << WLAN_CRYPTO_CIPHER_WEP_40 | 1199 1 << WLAN_CRYPTO_CIPHER_WEP_104))) 1200 return; 1201 1202 cm_set_key(cm_ctx, true, 0, &resp->bssid); 1203 cm_set_key(cm_ctx, false, 0, &broadcast_mac); 1204 } 1205 1206 static void cm_teardown_tdls(struct wlan_objmgr_vdev *vdev) 1207 { 1208 struct wlan_objmgr_psoc *psoc; 1209 1210 psoc = wlan_vdev_get_psoc(vdev); 1211 if (!psoc) 1212 return; 1213 1214 wlan_tdls_check_and_teardown_links_sync(psoc, vdev); 1215 } 1216 1217 #else 1218 static inline bool 1219 cm_is_any_other_vdev_connecting_disconnecting(struct cnx_mgr *cm_ctx, 1220 struct cm_req *cm_req) 1221 { 1222 return false; 1223 } 1224 1225 static inline 1226 bool cm_is_retry_with_same_candidate(struct cnx_mgr *cm_ctx, 1227 struct cm_connect_req *req, 1228 struct wlan_cm_connect_resp *resp) 1229 { 1230 return false; 1231 } 1232 1233 static inline 1234 bool cm_is_time_allowed_for_connect_attempt(struct cnx_mgr *cm_ctx, 1235 struct cm_connect_req *req) 1236 { 1237 return true; 1238 } 1239 1240 static inline void cm_update_advance_filter(struct wlan_objmgr_pdev *pdev, 1241 struct cnx_mgr *cm_ctx, 1242 struct scan_filter *filter, 1243 struct cm_connect_req *cm_req) 1244 { 1245 struct wlan_objmgr_vdev *vdev = cm_ctx->vdev; 1246 1247 if (cm_ctx->cm_candidate_advance_filter) 1248 cm_ctx->cm_candidate_advance_filter(vdev, filter); 1249 } 1250 1251 static void cm_update_security_filter(struct scan_filter *filter, 1252 struct wlan_cm_connect_req *req) 1253 { 1254 if (!QDF_HAS_PARAM(req->crypto.auth_type, WLAN_CRYPTO_AUTH_WAPI) && 1255 !QDF_HAS_PARAM(req->crypto.auth_type, WLAN_CRYPTO_AUTH_RSNA) && 1256 !QDF_HAS_PARAM(req->crypto.auth_type, WLAN_CRYPTO_AUTH_WPA)) { 1257 filter->ignore_auth_enc_type = 1; 1258 return; 1259 } 1260 1261 filter->authmodeset = req->crypto.auth_type; 1262 filter->ucastcipherset = req->crypto.ciphers_pairwise; 1263 filter->key_mgmt = req->crypto.akm_suites; 1264 filter->mcastcipherset = req->crypto.group_cipher; 1265 filter->mgmtcipherset = req->crypto.mgmt_ciphers; 1266 cm_set_pmf_caps(req, filter); 1267 } 1268 1269 static inline void cm_set_fils_wep_key(struct cnx_mgr *cm_ctx, 1270 struct wlan_cm_connect_resp *resp) 1271 {} 1272 1273 QDF_STATUS 1274 cm_peer_create_on_bss_select_ind_resp(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id) 1275 { 1276 struct cm_req *cm_req; 1277 1278 cm_req = cm_get_req_by_cm_id(cm_ctx, *cm_id); 1279 if (!cm_req) 1280 return QDF_STATUS_E_FAILURE; 1281 1282 /* Update vdev mlme mac address based on connection type */ 1283 cm_update_vdev_mlme_macaddr(cm_ctx, &cm_req->connect_req); 1284 1285 cm_create_bss_peer(cm_ctx, &cm_req->connect_req); 1286 1287 return QDF_STATUS_SUCCESS; 1288 } 1289 1290 QDF_STATUS cm_bss_select_ind_rsp(struct wlan_objmgr_vdev *vdev, 1291 QDF_STATUS status) 1292 { 1293 struct cnx_mgr *cm_ctx; 1294 QDF_STATUS qdf_status; 1295 wlan_cm_id cm_id; 1296 uint32_t prefix; 1297 struct wlan_cm_connect_resp *resp; 1298 1299 cm_ctx = cm_get_cm_ctx(vdev); 1300 if (!cm_ctx) 1301 return QDF_STATUS_E_INVAL; 1302 1303 cm_id = cm_ctx->active_cm_id; 1304 prefix = CM_ID_GET_PREFIX(cm_id); 1305 1306 if (prefix != CONNECT_REQ_PREFIX) { 1307 mlme_err(CM_PREFIX_FMT "active req is not connect req", 1308 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), cm_id)); 1309 return QDF_STATUS_E_INVAL; 1310 } 1311 1312 if (QDF_IS_STATUS_SUCCESS(status)) { 1313 qdf_status = 1314 cm_sm_deliver_event(vdev, 1315 WLAN_CM_SM_EV_BSS_SELECT_IND_SUCCESS, 1316 sizeof(wlan_cm_id), &cm_id); 1317 if (QDF_IS_STATUS_SUCCESS(qdf_status)) 1318 return qdf_status; 1319 1320 goto post_err; 1321 } 1322 1323 /* In case of failure try with next candidate */ 1324 resp = qdf_mem_malloc(sizeof(*resp)); 1325 if (!resp) { 1326 qdf_status = QDF_STATUS_E_NOMEM; 1327 goto post_err; 1328 } 1329 1330 cm_fill_failure_resp_from_cm_id(cm_ctx, resp, cm_id, 1331 CM_BSS_SELECT_IND_FAILED); 1332 qdf_status = 1333 cm_sm_deliver_event(vdev, 1334 WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE, 1335 sizeof(*resp), resp); 1336 qdf_mem_free(resp); 1337 if (QDF_IS_STATUS_SUCCESS(qdf_status)) 1338 return qdf_status; 1339 1340 post_err: 1341 /* 1342 * If there is a event posting error it means the SM state is not in 1343 * JOIN ACTIVE (some new cmd has changed the state of SM), so just 1344 * complete the connect command. 1345 */ 1346 cm_connect_handle_event_post_fail(cm_ctx, cm_id); 1347 return qdf_status; 1348 } 1349 1350 static inline void cm_teardown_tdls(struct wlan_objmgr_vdev *vdev) {} 1351 1352 #endif /* CONN_MGR_ADV_FEATURE */ 1353 1354 static void cm_connect_prepare_scan_filter(struct wlan_objmgr_pdev *pdev, 1355 struct cnx_mgr *cm_ctx, 1356 struct cm_connect_req *cm_req, 1357 struct scan_filter *filter, 1358 bool security_valid_for_6ghz) 1359 { 1360 if (!qdf_is_macaddr_zero(&cm_req->req.bssid)) { 1361 filter->num_of_bssid = 1; 1362 qdf_copy_macaddr(&filter->bssid_list[0], &cm_req->req.bssid); 1363 } 1364 1365 qdf_copy_macaddr(&filter->bssid_hint, &cm_req->req.bssid_hint); 1366 filter->num_of_ssid = 1; 1367 qdf_mem_copy(&filter->ssid_list[0], &cm_req->req.ssid, 1368 sizeof(struct wlan_ssid)); 1369 1370 if (cm_req->req.chan_freq) { 1371 filter->num_of_channels = 1; 1372 filter->chan_freq_list[0] = cm_req->req.chan_freq; 1373 } 1374 1375 /* Security is not valid for 6Ghz so ignore 6Ghz APs */ 1376 if (!security_valid_for_6ghz) 1377 filter->ignore_6ghz_channel = true; 1378 1379 if (cm_req->req.is_non_assoc_link) 1380 filter->ignore_6ghz_channel = false; 1381 1382 cm_update_security_filter(filter, &cm_req->req); 1383 cm_update_advance_filter(pdev, cm_ctx, filter, cm_req); 1384 } 1385 1386 #ifdef WLAN_FEATURE_11BE_MLO 1387 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 1388 static QDF_STATUS cm_is_scan_support(struct cm_connect_req *cm_req) 1389 { 1390 if (cm_req->req.is_non_assoc_link) 1391 return QDF_STATUS_E_FAILURE; 1392 1393 return QDF_STATUS_SUCCESS; 1394 } 1395 #else 1396 static QDF_STATUS cm_is_scan_support(struct cm_connect_req *cm_req) 1397 { 1398 if (cm_req->req.ml_parnter_info.num_partner_links) 1399 return QDF_STATUS_E_FAILURE; 1400 1401 return QDF_STATUS_SUCCESS; 1402 } 1403 #endif 1404 #else 1405 static QDF_STATUS cm_is_scan_support(struct cm_connect_req *cm_req) 1406 { 1407 return QDF_STATUS_SUCCESS; 1408 } 1409 #endif 1410 1411 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_FEATURE_11BE_MLO_ADV_FEATURE) 1412 #define CFG_MLO_ASSOC_LINK_BAND_MAX 0x70 1413 1414 static QDF_STATUS cm_update_mlo_filter(struct wlan_objmgr_pdev *pdev, 1415 struct cm_connect_req *cm_req, 1416 struct scan_filter *filter) 1417 { 1418 struct wlan_objmgr_psoc *psoc; 1419 1420 psoc = wlan_pdev_get_psoc(pdev); 1421 filter->band_bitmap = wlan_mlme_get_sta_mlo_conn_band_bmp(psoc); 1422 /* Apply assoc band filter only for assoc link */ 1423 if (cm_req->req.is_non_assoc_link) 1424 filter->band_bitmap = 1425 filter->band_bitmap | CFG_MLO_ASSOC_LINK_BAND_MAX; 1426 1427 mlme_debug(CM_PREFIX_FMT "band bitmap: 0x%x", 1428 CM_PREFIX_REF(cm_req->req.vdev_id, cm_req->cm_id), 1429 filter->band_bitmap); 1430 1431 return QDF_STATUS_SUCCESS; 1432 } 1433 #else 1434 static QDF_STATUS cm_update_mlo_filter(struct wlan_objmgr_pdev *pdev, 1435 struct cm_connect_req *cm_req, 1436 struct scan_filter *filter) 1437 { 1438 return QDF_STATUS_SUCCESS; 1439 } 1440 #endif 1441 1442 static QDF_STATUS 1443 cm_connect_fetch_candidates(struct wlan_objmgr_pdev *pdev, 1444 struct cnx_mgr *cm_ctx, 1445 struct cm_connect_req *cm_req, 1446 qdf_list_t **fetched_candidate_list, 1447 uint32_t *num_bss_found) 1448 { 1449 struct scan_filter *filter; 1450 uint32_t num_bss = 0; 1451 enum QDF_OPMODE op_mode; 1452 qdf_list_t *candidate_list; 1453 uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 1454 bool security_valid_for_6ghz; 1455 const uint8_t *rsnxe; 1456 1457 rsnxe = wlan_get_ie_ptr_from_eid(WLAN_ELEMID_RSNXE, 1458 cm_req->req.assoc_ie.ptr, 1459 cm_req->req.assoc_ie.len); 1460 security_valid_for_6ghz = 1461 wlan_cm_6ghz_allowed_for_akm(wlan_pdev_get_psoc(pdev), 1462 cm_req->req.crypto.akm_suites, 1463 cm_req->req.crypto.rsn_caps, 1464 rsnxe, cm_req->req.sae_pwe, 1465 cm_req->req.is_wps_connection); 1466 1467 /* 1468 * Ignore connect req if the freq is provided and its 6Ghz and 1469 * security is not valid for 6Ghz 1470 */ 1471 if (cm_req->req.chan_freq && !security_valid_for_6ghz && 1472 WLAN_REG_IS_6GHZ_CHAN_FREQ(cm_req->req.chan_freq)) { 1473 mlme_info(CM_PREFIX_FMT "6ghz freq (%d) given and 6Ghz not allowed for the security in connect req", 1474 CM_PREFIX_REF(vdev_id, cm_req->cm_id), 1475 cm_req->req.chan_freq); 1476 return QDF_STATUS_E_INVAL; 1477 } 1478 filter = qdf_mem_malloc(sizeof(*filter)); 1479 if (!filter) 1480 return QDF_STATUS_E_NOMEM; 1481 1482 cm_connect_prepare_scan_filter(pdev, cm_ctx, cm_req, filter, 1483 security_valid_for_6ghz); 1484 1485 cm_update_mlo_filter(pdev, cm_req, filter); 1486 1487 candidate_list = wlan_scan_get_result(pdev, filter); 1488 if (candidate_list) { 1489 num_bss = qdf_list_size(candidate_list); 1490 mlme_debug(CM_PREFIX_FMT "num_entries found %d", 1491 CM_PREFIX_REF(vdev_id, cm_req->cm_id), num_bss); 1492 } 1493 *num_bss_found = num_bss; 1494 op_mode = wlan_vdev_mlme_get_opmode(cm_ctx->vdev); 1495 if (num_bss && op_mode == QDF_STA_MODE && 1496 !cm_req->req.is_non_assoc_link) 1497 cm_calculate_scores(cm_ctx, pdev, filter, candidate_list); 1498 qdf_mem_free(filter); 1499 1500 if (!candidate_list || !qdf_list_size(candidate_list)) { 1501 if (candidate_list) 1502 wlan_scan_purge_results(candidate_list); 1503 return QDF_STATUS_E_EMPTY; 1504 } 1505 *fetched_candidate_list = candidate_list; 1506 1507 return QDF_STATUS_SUCCESS; 1508 } 1509 1510 static QDF_STATUS cm_connect_get_candidates(struct wlan_objmgr_pdev *pdev, 1511 struct cnx_mgr *cm_ctx, 1512 struct cm_connect_req *cm_req) 1513 { 1514 uint32_t num_bss = 0; 1515 qdf_list_t *candidate_list = NULL; 1516 uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 1517 QDF_STATUS status; 1518 1519 status = cm_connect_fetch_candidates(pdev, cm_ctx, cm_req, 1520 &candidate_list, &num_bss); 1521 if (QDF_IS_STATUS_ERROR(status)) { 1522 if (candidate_list) 1523 wlan_scan_purge_results(candidate_list); 1524 mlme_info(CM_PREFIX_FMT "no valid candidate found, num_bss %d scan_id %d", 1525 CM_PREFIX_REF(vdev_id, cm_req->cm_id), num_bss, 1526 cm_req->scan_id); 1527 1528 /* 1529 * If connect scan was already done OR candidate were found 1530 * but none of them were valid OR if ML link connection 1531 * return QDF_STATUS_E_EMPTY. 1532 */ 1533 if (cm_req->scan_id || num_bss || 1534 QDF_IS_STATUS_ERROR(cm_is_scan_support(cm_req))) 1535 return QDF_STATUS_E_EMPTY; 1536 1537 /* Try connect scan to search for any valid candidate */ 1538 status = cm_sm_deliver_event_sync(cm_ctx, WLAN_CM_SM_EV_SCAN, 1539 sizeof(*cm_req), cm_req); 1540 /* 1541 * If connect scan is initiated, return pending, so that 1542 * connect start after scan complete 1543 */ 1544 if (QDF_IS_STATUS_SUCCESS(status)) 1545 status = QDF_STATUS_E_PENDING; 1546 1547 return status; 1548 } 1549 cm_req->candidate_list = candidate_list; 1550 1551 return status; 1552 } 1553 1554 #ifdef CONN_MGR_ADV_FEATURE 1555 static void cm_update_candidate_list(struct cnx_mgr *cm_ctx, 1556 struct cm_connect_req *cm_req, 1557 struct scan_cache_node *prev_candidate) 1558 { 1559 struct wlan_objmgr_pdev *pdev; 1560 uint32_t num_bss = 0; 1561 qdf_list_t *candidate_list = NULL; 1562 uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 1563 QDF_STATUS status; 1564 struct scan_cache_node *scan_entry; 1565 qdf_list_node_t *cur_node = NULL, *next_node = NULL; 1566 struct qdf_mac_addr *bssid; 1567 bool found; 1568 1569 pdev = wlan_vdev_get_pdev(cm_ctx->vdev); 1570 if (!pdev) { 1571 mlme_err(CM_PREFIX_FMT "Failed to find pdev", 1572 CM_PREFIX_REF(vdev_id, cm_req->cm_id)); 1573 return; 1574 } 1575 1576 status = cm_connect_fetch_candidates(pdev, cm_ctx, cm_req, 1577 &candidate_list, &num_bss); 1578 if (QDF_IS_STATUS_ERROR(status)) { 1579 mlme_debug(CM_PREFIX_FMT "failed to fetch bss: %d", 1580 CM_PREFIX_REF(vdev_id, cm_req->cm_id), num_bss); 1581 goto free_list; 1582 } 1583 1584 if (qdf_list_peek_front(candidate_list, &cur_node) != 1585 QDF_STATUS_SUCCESS) { 1586 mlme_err(CM_PREFIX_FMT "failed to peer front of candidate_list", 1587 CM_PREFIX_REF(vdev_id, cm_req->cm_id)); 1588 goto free_list; 1589 } 1590 1591 while (cur_node) { 1592 qdf_list_peek_next(candidate_list, cur_node, &next_node); 1593 1594 scan_entry = qdf_container_of(cur_node, struct scan_cache_node, 1595 node); 1596 bssid = &scan_entry->entry->bssid; 1597 if (qdf_is_macaddr_zero(bssid) || 1598 qdf_is_macaddr_broadcast(bssid)) 1599 goto next; 1600 found = cm_find_bss_from_candidate_list(cm_req->candidate_list, 1601 bssid, NULL); 1602 if (found) 1603 goto next; 1604 status = qdf_list_remove_node(candidate_list, cur_node); 1605 if (QDF_IS_STATUS_ERROR(status)) { 1606 mlme_err(CM_PREFIX_FMT "failed to remove node for " QDF_MAC_ADDR_FMT " from candidate list", 1607 CM_PREFIX_REF(vdev_id, cm_req->cm_id), 1608 QDF_MAC_ADDR_REF(scan_entry->entry->bssid.bytes)); 1609 goto free_list; 1610 } 1611 1612 status = qdf_list_insert_after(cm_req->candidate_list, 1613 &scan_entry->node, 1614 &prev_candidate->node); 1615 if (QDF_IS_STATUS_ERROR(status)) { 1616 mlme_err(CM_PREFIX_FMT "failed to insert node for " QDF_MAC_ADDR_FMT " to candidate list", 1617 CM_PREFIX_REF(vdev_id, cm_req->cm_id), 1618 QDF_MAC_ADDR_REF(scan_entry->entry->bssid.bytes)); 1619 util_scan_free_cache_entry(scan_entry->entry); 1620 qdf_mem_free(scan_entry); 1621 goto free_list; 1622 } 1623 prev_candidate = scan_entry; 1624 mlme_debug(CM_PREFIX_FMT "insert new node " QDF_MAC_ADDR_FMT " to candidate list", 1625 CM_PREFIX_REF(vdev_id, cm_req->cm_id), 1626 QDF_MAC_ADDR_REF(scan_entry->entry->bssid.bytes)); 1627 next: 1628 cur_node = next_node; 1629 next_node = NULL; 1630 } 1631 1632 free_list: 1633 if (candidate_list) 1634 wlan_scan_purge_results(candidate_list); 1635 } 1636 #else 1637 static inline void 1638 cm_update_candidate_list(struct cnx_mgr *cm_ctx, 1639 struct cm_connect_req *cm_req, 1640 struct scan_cache_node *prev_candidate) 1641 { 1642 } 1643 #endif 1644 1645 QDF_STATUS cm_if_mgr_inform_connect_complete(struct wlan_objmgr_vdev *vdev, 1646 QDF_STATUS connect_status) 1647 { 1648 struct if_mgr_event_data *connect_complete; 1649 1650 connect_complete = qdf_mem_malloc(sizeof(*connect_complete)); 1651 if (!connect_complete) 1652 return QDF_STATUS_E_NOMEM; 1653 1654 connect_complete->status = connect_status; 1655 if_mgr_deliver_event(vdev, WLAN_IF_MGR_EV_CONNECT_COMPLETE, 1656 connect_complete); 1657 qdf_mem_free(connect_complete); 1658 1659 return QDF_STATUS_SUCCESS; 1660 } 1661 1662 static QDF_STATUS 1663 cm_if_mgr_inform_connect_start(struct wlan_objmgr_vdev *vdev) 1664 { 1665 return if_mgr_deliver_event(vdev, WLAN_IF_MGR_EV_CONNECT_START, NULL); 1666 } 1667 1668 QDF_STATUS 1669 cm_handle_connect_req_in_non_init_state(struct cnx_mgr *cm_ctx, 1670 struct cm_connect_req *cm_req, 1671 enum wlan_cm_sm_state cm_state_substate) 1672 { 1673 uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 1674 1675 /* 1676 * Connect re-assoc req should have been received in one of the 1677 * following states: 1678 * a) SB disconnect in progress 1679 * b) Roam start/Roam sync in progress 1680 * c) Reassoc 1681 * d) Connected state with LFR3 disabled 1682 * e) Invalid Roam request 1683 * 1684 * In this case, set reassoc_in_non_init flag, so that disconnect can 1685 * be notified to the upper layers if connect request fails. This is 1686 * required by upper layers to clear the connection state of the 1687 * previous connection. 1688 */ 1689 if (cm_is_connect_req_reassoc(&cm_req->req)) { 1690 cm_req->req.reassoc_in_non_init = true; 1691 mlme_debug(CM_PREFIX_FMT "Reassoc received in %d state", 1692 CM_PREFIX_REF(vdev_id, cm_req->cm_id), 1693 cm_state_substate); 1694 } 1695 1696 /* Reject any link switch connect request while in non-init state */ 1697 if (cm_req->req.source == CM_MLO_LINK_SWITCH_CONNECT) { 1698 mlme_info(CM_PREFIX_FMT "Ignore connect req from source %d state %d", 1699 CM_PREFIX_REF(vdev_id, cm_req->cm_id), 1700 cm_req->req.source, cm_state_substate); 1701 return QDF_STATUS_E_INVAL; 1702 } 1703 1704 switch (cm_state_substate) { 1705 case WLAN_CM_S_ROAMING: 1706 /* for FW roam/LFR3 remove the req from the list */ 1707 if (cm_roam_offload_enabled(wlan_vdev_get_psoc(cm_ctx->vdev))) 1708 cm_flush_pending_request(cm_ctx, ROAM_REQ_PREFIX, 1709 false); 1710 fallthrough; 1711 case WLAN_CM_S_CONNECTED: 1712 case WLAN_CM_SS_JOIN_ACTIVE: 1713 /* 1714 * In roaming state, there would be no 1715 * pending command, so for new connect request, queue internal 1716 * disconnect. The preauth and reassoc process will be aborted 1717 * as the state machine will be moved to connecting state and 1718 * preauth/reassoc/roam start event posting will fail. 1719 * 1720 * In connected state, there would be no pending command, so 1721 * for new connect request, queue internal disconnect 1722 * 1723 * In join active state there would be only one active connect 1724 * request in the cm req list, so to abort at certain stages and 1725 * to cleanup after its completion, queue internal disconnect. 1726 */ 1727 cm_initiate_internal_disconnect(cm_ctx); 1728 break; 1729 case WLAN_CM_SS_SCAN: 1730 /* In the scan state abort the ongoing scan */ 1731 cm_vdev_scan_cancel(wlan_vdev_get_pdev(cm_ctx->vdev), 1732 cm_ctx->vdev); 1733 fallthrough; 1734 case WLAN_CM_SS_JOIN_PENDING: 1735 /* 1736 * In case of scan or join pending there could be 2 scenarios:- 1737 * 1738 * 1. There is a connect request pending, so just remove 1739 * the pending connect req. As we will queue a new connect 1740 * req, all resp for pending connect req will be dropped. 1741 * 2. There is a connect request in active and 1742 * and a internal disconnect followed by a connect req in 1743 * pending. In this case the disconnect will take care of 1744 * cleaning up the active connect request and thus only 1745 * remove the pending connect. 1746 */ 1747 cm_flush_pending_request(cm_ctx, CONNECT_REQ_PREFIX, false); 1748 break; 1749 case WLAN_CM_S_DISCONNECTING: 1750 /* 1751 * Flush failed pending connect req as new req is received 1752 * and its no longer the latest one. 1753 */ 1754 if (cm_ctx->connect_count) 1755 cm_flush_pending_request(cm_ctx, CONNECT_REQ_PREFIX, 1756 true); 1757 /* 1758 * In case of disconnecting state, there could be 2 scenarios:- 1759 * In both case no state specific action is required. 1760 * 1. There is disconnect request in the cm_req list, no action 1761 * required to cleanup. 1762 * so just add the connect request to the list. 1763 * 2. There is a connect request activated, followed by 1764 * disconnect in pending queue. So keep the disconnect 1765 * to cleanup the active connect and no action required to 1766 * cleanup. 1767 */ 1768 break; 1769 default: 1770 mlme_err(CM_PREFIX_FMT "Connect req in invalid state %d", 1771 CM_PREFIX_REF(vdev_id, cm_req->cm_id), 1772 cm_state_substate); 1773 return QDF_STATUS_E_FAILURE; 1774 }; 1775 1776 /* Queue the new connect request after state specific actions */ 1777 return cm_add_connect_req_to_list(cm_ctx, cm_req); 1778 } 1779 1780 QDF_STATUS cm_connect_start(struct cnx_mgr *cm_ctx, 1781 struct cm_connect_req *cm_req) 1782 { 1783 struct wlan_objmgr_pdev *pdev; 1784 struct wlan_objmgr_psoc *psoc; 1785 enum wlan_cm_connect_fail_reason reason = CM_GENERIC_FAILURE; 1786 QDF_STATUS status; 1787 uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 1788 1789 /* Interface event */ 1790 pdev = wlan_vdev_get_pdev(cm_ctx->vdev); 1791 if (!pdev) { 1792 mlme_err(CM_PREFIX_FMT "Failed to find pdev", 1793 CM_PREFIX_REF(vdev_id, cm_req->cm_id)); 1794 goto connect_err; 1795 } 1796 1797 psoc = wlan_pdev_get_psoc(pdev); 1798 if (!psoc) { 1799 mlme_err(CM_PREFIX_FMT "Failed to find psoc", 1800 CM_PREFIX_REF(vdev_id, cm_req->cm_id)); 1801 goto connect_err; 1802 } 1803 1804 /* 1805 * Do not initiate the duplicate ifmanager and connect start ind if 1806 * this is called from Scan for ssid 1807 */ 1808 if (!cm_req->scan_id) { 1809 cm_if_mgr_inform_connect_start(cm_ctx->vdev); 1810 status = mlme_cm_connect_start_ind(cm_ctx->vdev, &cm_req->req); 1811 if (QDF_IS_STATUS_ERROR(status)) { 1812 reason = CM_NO_CANDIDATE_FOUND; 1813 goto connect_err; 1814 } 1815 } 1816 1817 if (mlo_is_sta_bridge_vdev(cm_ctx->vdev)) { 1818 status = cm_ser_connect_req(pdev, cm_ctx, cm_req); 1819 if (QDF_IS_STATUS_ERROR(status)) { 1820 reason = CM_SER_FAILURE; 1821 goto connect_err; 1822 } 1823 1824 return QDF_STATUS_SUCCESS; 1825 } 1826 status = cm_connect_get_candidates(pdev, cm_ctx, cm_req); 1827 1828 /* In case of status pending connect will continue after scan */ 1829 if (status == QDF_STATUS_E_PENDING) 1830 return QDF_STATUS_SUCCESS; 1831 if (QDF_IS_STATUS_ERROR(status)) { 1832 reason = CM_NO_CANDIDATE_FOUND; 1833 goto connect_err; 1834 } 1835 1836 status = cm_check_for_hw_mode_change(psoc, cm_req->candidate_list, 1837 vdev_id, cm_req->cm_id); 1838 if (QDF_IS_STATUS_ERROR(status) && status != QDF_STATUS_E_ALREADY) { 1839 reason = CM_HW_MODE_FAILURE; 1840 mlme_err(CM_PREFIX_FMT "Failed to set HW mode change", 1841 CM_PREFIX_REF(vdev_id, cm_req->cm_id)); 1842 goto connect_err; 1843 } else if (QDF_IS_STATUS_SUCCESS(status)) { 1844 mlme_debug(CM_PREFIX_FMT "Connect will continue after HW mode change", 1845 CM_PREFIX_REF(vdev_id, cm_req->cm_id)); 1846 return QDF_STATUS_SUCCESS; 1847 } 1848 1849 if (cm_req->req.source == CM_MLO_LINK_SWITCH_CONNECT) { 1850 /* The error handling has to be different here.not corresponds 1851 * to connect req serialization now. 1852 */ 1853 status = cm_sm_deliver_event_sync(cm_ctx, 1854 WLAN_CM_SM_EV_CONNECT_ACTIVE, 1855 sizeof(wlan_cm_id), 1856 &cm_req->cm_id); 1857 } else { 1858 status = cm_ser_connect_req(pdev, cm_ctx, cm_req); 1859 } 1860 1861 if (QDF_IS_STATUS_ERROR(status)) { 1862 reason = CM_SER_FAILURE; 1863 goto connect_err; 1864 } 1865 1866 return QDF_STATUS_SUCCESS; 1867 1868 connect_err: 1869 return cm_send_connect_start_fail(cm_ctx, cm_req, reason); 1870 } 1871 1872 #if defined(CONN_MGR_ADV_FEATURE) && defined(WLAN_FEATURE_11BE_MLO) 1873 static void 1874 cm_modify_partner_info_based_on_dbs_or_sbs_mode(struct wlan_objmgr_vdev *vdev, 1875 wlan_cm_id cm_id, 1876 struct scan_cache_entry *scan_entry, 1877 struct mlo_partner_info *partner_info) 1878 { 1879 struct wlan_objmgr_psoc *psoc = NULL; 1880 uint16_t i; 1881 qdf_freq_t assoc_freq, partner_freq; 1882 struct mlo_link_info tmp_link_info; 1883 uint8_t best_partner_idx, best_partner_idx_2g, best_partner_idx_5g; 1884 1885 psoc = wlan_vdev_get_psoc(vdev); 1886 if (!psoc) 1887 return; 1888 1889 assoc_freq = scan_entry->channel.chan_freq; 1890 best_partner_idx_2g = partner_info->num_partner_links; 1891 best_partner_idx_5g = partner_info->num_partner_links; 1892 1893 for (i = 0; i < partner_info->num_partner_links; i++) { 1894 partner_freq = partner_info->partner_link_info[i].chan_freq; 1895 if (!policy_mgr_2_freq_always_on_same_mac(psoc, assoc_freq, 1896 partner_freq)) { 1897 if (wlan_reg_is_24ghz_ch_freq(partner_freq)) 1898 best_partner_idx_2g = i; 1899 else 1900 best_partner_idx_5g = i; 1901 } 1902 } 1903 1904 if (best_partner_idx_5g == partner_info->num_partner_links && 1905 best_partner_idx_2g == partner_info->num_partner_links) 1906 return; 1907 1908 if (best_partner_idx_5g != partner_info->num_partner_links) 1909 best_partner_idx = best_partner_idx_5g; 1910 else if (best_partner_idx_2g != partner_info->num_partner_links) 1911 best_partner_idx = best_partner_idx_2g; 1912 else 1913 return; 1914 1915 if (best_partner_idx == 0) 1916 return; 1917 1918 /* Based on DBS or SBS mode, reorder the partner_link_info */ 1919 tmp_link_info = partner_info->partner_link_info[0]; 1920 partner_info->partner_link_info[0] = 1921 partner_info->partner_link_info[best_partner_idx]; 1922 partner_info->partner_link_info[best_partner_idx] = tmp_link_info; 1923 1924 mlme_debug(CM_PREFIX_FMT "Updated no. of partner links: %d", 1925 CM_PREFIX_REF(wlan_vdev_get_id(vdev), cm_id), 1926 partner_info->num_partner_links); 1927 1928 for (i = 0; i < partner_info->num_partner_links; i++) 1929 mlme_debug(CM_PREFIX_FMT "Partner link id: %d mac:" QDF_MAC_ADDR_FMT " freq: %d", 1930 CM_PREFIX_REF(wlan_vdev_get_id(vdev), cm_id), 1931 partner_info->partner_link_info[i].link_id, 1932 QDF_MAC_ADDR_REF(partner_info->partner_link_info[i].link_addr.bytes), 1933 partner_info->partner_link_info[i].chan_freq); 1934 } 1935 1936 static void 1937 cm_connect_req_update_ml_partner_info(struct cnx_mgr *cm_ctx, 1938 struct cm_req *cm_req, 1939 bool same_candidate_used) 1940 { 1941 bool eht_capable = false; 1942 struct cm_connect_req *conn_req = &cm_req->connect_req; 1943 struct wlan_objmgr_pdev *pdev; 1944 uint8_t cur_vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 1945 1946 pdev = wlan_vdev_get_pdev(cm_ctx->vdev); 1947 if (!pdev) { 1948 mlme_err(CM_PREFIX_FMT "Failed to find pdev", 1949 CM_PREFIX_REF(cur_vdev_id, cm_req->cm_id)); 1950 return; 1951 } 1952 1953 wlan_psoc_mlme_get_11be_capab(wlan_vdev_get_psoc(cm_ctx->vdev), 1954 &eht_capable); 1955 if (!same_candidate_used && eht_capable && 1956 cm_bss_peer_is_assoc_peer(conn_req)) { 1957 cm_get_ml_partner_info(pdev, 1958 conn_req->cur_candidate->entry, 1959 &conn_req->req.ml_parnter_info); 1960 cm_modify_partner_info_based_on_dbs_or_sbs_mode( 1961 cm_ctx->vdev, cm_req->cm_id, 1962 conn_req->cur_candidate->entry, 1963 &conn_req->req.ml_parnter_info); 1964 } 1965 } 1966 #else 1967 static void 1968 cm_connect_req_update_ml_partner_info(struct cnx_mgr *cm_ctx, 1969 struct cm_req *cm_req, 1970 bool same_candidate_used) 1971 {} 1972 #endif 1973 1974 /** 1975 * cm_get_valid_candidate() - This API will be called to get the next valid 1976 * candidate 1977 * @cm_ctx: connection manager context 1978 * @cm_req: Connect request. 1979 * @resp: connect resp from previous connection attempt 1980 * @same_candidate_used: this will be set if same candidate used 1981 * 1982 * This function return a valid candidate to try connection. It return failure 1983 * if no valid candidate is present or all valid candidate are tried. 1984 * 1985 * Return: QDF status 1986 */ 1987 static QDF_STATUS cm_get_valid_candidate(struct cnx_mgr *cm_ctx, 1988 struct cm_req *cm_req, 1989 struct wlan_cm_connect_resp *resp, 1990 bool *same_candidate_used) 1991 { 1992 struct wlan_objmgr_psoc *psoc; 1993 struct scan_cache_node *scan_node = NULL; 1994 qdf_list_node_t *cur_node = NULL, *next_node = NULL; 1995 struct scan_cache_node *new_candidate = NULL, *prev_candidate; 1996 QDF_STATUS status = QDF_STATUS_SUCCESS; 1997 uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 1998 bool use_same_candidate = false; 1999 int32_t akm; 2000 struct qdf_mac_addr *pmksa_mac; 2001 2002 psoc = wlan_vdev_get_psoc(cm_ctx->vdev); 2003 if (!psoc) { 2004 mlme_err(CM_PREFIX_FMT "Failed to find psoc", 2005 CM_PREFIX_REF(vdev_id, cm_req->cm_id)); 2006 return QDF_STATUS_E_FAILURE; 2007 } 2008 2009 prev_candidate = cm_req->connect_req.cur_candidate; 2010 /* 2011 * In case of STA/CLI + STA/CLI, if a STA/CLI is in connecting state and 2012 * a disconnect is received on any other STA/CLI, the disconnect can 2013 * timeout waiting for the connection on first STA/CLI to get completed. 2014 * This is because the connect is a blocking serialization command and 2015 * it can try multiple candidates and thus can take upto 30+ sec to 2016 * complete. 2017 * 2018 * Now osif will proceed with vdev delete after disconnect timeout. 2019 * This can lead to vdev delete sent without vdev down/stop/peer delete 2020 * for the vdev. 2021 * 2022 * Same way if a SAP/GO has start/stop command or peer disconnect in 2023 * pending queue, delay in processing it can cause timeouts and other 2024 * issues. 2025 * 2026 * So abort the next connection attempt if any of the vdev is waiting 2027 * for vdev operation to avoid timeouts 2028 */ 2029 if (cm_is_any_other_vdev_connecting_disconnecting(cm_ctx, cm_req)) { 2030 status = QDF_STATUS_E_FAILURE; 2031 goto flush_single_pmk; 2032 } 2033 2034 if (cm_req->connect_req.connect_attempts >= 2035 cm_ctx->max_connect_attempts) { 2036 mlme_info(CM_PREFIX_FMT "%d attempts tried, max %d", 2037 CM_PREFIX_REF(vdev_id, cm_req->cm_id), 2038 cm_req->connect_req.connect_attempts, 2039 cm_ctx->max_connect_attempts); 2040 status = QDF_STATUS_E_FAILURE; 2041 goto flush_single_pmk; 2042 } 2043 2044 /* From 2nd attempt onward, check if time allows for a new attempt */ 2045 if (cm_req->connect_req.connect_attempts && 2046 !cm_is_time_allowed_for_connect_attempt(cm_ctx, 2047 &cm_req->connect_req)) { 2048 status = QDF_STATUS_E_FAILURE; 2049 goto flush_single_pmk; 2050 } 2051 2052 if (prev_candidate && resp && 2053 cm_is_retry_with_same_candidate(cm_ctx, &cm_req->connect_req, 2054 resp)) { 2055 new_candidate = prev_candidate; 2056 use_same_candidate = true; 2057 goto try_same_candidate; 2058 } 2059 2060 /* 2061 * Get next candidate if prev_candidate is not NULL, else get 2062 * the first candidate 2063 */ 2064 if (prev_candidate) { 2065 /* Fetch new candidate list and append new entries to the 2066 * current candidate list. 2067 */ 2068 cm_update_candidate_list(cm_ctx, &cm_req->connect_req, 2069 prev_candidate); 2070 qdf_list_peek_next(cm_req->connect_req.candidate_list, 2071 &prev_candidate->node, &cur_node); 2072 } else { 2073 qdf_list_peek_front(cm_req->connect_req.candidate_list, 2074 &cur_node); 2075 } 2076 2077 while (cur_node) { 2078 qdf_list_peek_next(cm_req->connect_req.candidate_list, 2079 cur_node, &next_node); 2080 scan_node = qdf_container_of(cur_node, struct scan_cache_node, 2081 node); 2082 status = cm_if_mgr_validate_candidate(cm_ctx, scan_node->entry); 2083 if (QDF_IS_STATUS_SUCCESS(status)) { 2084 new_candidate = scan_node; 2085 break; 2086 } 2087 2088 /* 2089 * stored failure response for first candidate only but 2090 * indicate the failure response to osif for all candidates. 2091 */ 2092 cm_store_n_send_failed_candidate(cm_ctx, cm_req->cm_id); 2093 2094 cur_node = next_node; 2095 next_node = NULL; 2096 } 2097 2098 /* 2099 * If cur_node is NULL prev candidate was last to be tried so no more 2100 * candidates left for connect now. 2101 */ 2102 if (!cur_node) { 2103 mlme_debug(CM_PREFIX_FMT "No more candidates left", 2104 CM_PREFIX_REF(vdev_id, cm_req->cm_id)); 2105 cm_req->connect_req.cur_candidate = NULL; 2106 status = QDF_STATUS_E_FAILURE; 2107 goto flush_single_pmk; 2108 } 2109 2110 /* Reset current candidate retries when a new candidate is tried */ 2111 cm_req->connect_req.cur_candidate_retries = 0; 2112 2113 try_same_candidate: 2114 cm_req->connect_req.connect_attempts++; 2115 cm_req->connect_req.cur_candidate = new_candidate; 2116 2117 cm_connect_req_update_ml_partner_info(cm_ctx, cm_req, 2118 use_same_candidate); 2119 2120 flush_single_pmk: 2121 akm = wlan_crypto_get_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_KEY_MGMT); 2122 /* 2123 * If connection fails with Single PMK bssid (prev candidate), 2124 * clear the pmk entry. Flush only in case if we are not trying again 2125 * with same candidate again. 2126 */ 2127 if (prev_candidate && !use_same_candidate && 2128 util_scan_entry_single_pmk(psoc, prev_candidate->entry) && 2129 QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE)) { 2130 pmksa_mac = &prev_candidate->entry->bssid; 2131 cm_delete_pmksa_for_single_pmk_bssid(cm_ctx, pmksa_mac); 2132 2133 /* If the candidate is ML capable, the PMKSA entry might 2134 * exist with it's MLD address, so check and purge the 2135 * PMKSA entry with MLD address for ML candidate. 2136 */ 2137 pmksa_mac = (struct qdf_mac_addr *) 2138 util_scan_entry_mldaddr(prev_candidate->entry); 2139 if (pmksa_mac) 2140 cm_delete_pmksa_for_single_pmk_bssid(cm_ctx, pmksa_mac); 2141 } 2142 2143 if (same_candidate_used) 2144 *same_candidate_used = use_same_candidate; 2145 2146 return status; 2147 } 2148 2149 static QDF_STATUS 2150 cm_send_bss_select_ind(struct cnx_mgr *cm_ctx, struct cm_connect_req *req) 2151 { 2152 QDF_STATUS status; 2153 struct wlan_cm_vdev_connect_req vdev_req; 2154 struct wlan_cm_connect_resp *resp; 2155 2156 vdev_req.vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 2157 vdev_req.cm_id = req->cm_id; 2158 vdev_req.bss = req->cur_candidate; 2159 2160 status = mlme_cm_bss_select_ind(cm_ctx->vdev, &vdev_req); 2161 if (QDF_IS_STATUS_SUCCESS(status) || 2162 status == QDF_STATUS_E_NOSUPPORT) 2163 return status; 2164 2165 /* In supported and failure try with next candidate */ 2166 mlme_err(CM_PREFIX_FMT "mlme candidate select indication failed %d", 2167 CM_PREFIX_REF(vdev_req.vdev_id, req->cm_id), status); 2168 resp = qdf_mem_malloc(sizeof(*resp)); 2169 if (!resp) 2170 return QDF_STATUS_E_FAILURE; 2171 2172 cm_fill_failure_resp_from_cm_id(cm_ctx, resp, req->cm_id, 2173 CM_BSS_SELECT_IND_FAILED); 2174 cm_sm_deliver_event_sync(cm_ctx, 2175 WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE, 2176 sizeof(*resp), resp); 2177 qdf_mem_free(resp); 2178 2179 return QDF_STATUS_SUCCESS; 2180 } 2181 2182 static void cm_update_ser_timer_for_new_candidate(struct cnx_mgr *cm_ctx, 2183 wlan_cm_id cm_id) 2184 { 2185 struct wlan_serialization_command cmd; 2186 2187 cmd.cmd_type = WLAN_SER_CMD_VDEV_CONNECT; 2188 cmd.cmd_id = cm_id; 2189 cmd.cmd_timeout_duration = cm_ctx->connect_timeout; 2190 cmd.vdev = cm_ctx->vdev; 2191 2192 wlan_serialization_update_timer(&cmd); 2193 } 2194 2195 QDF_STATUS cm_try_next_candidate(struct cnx_mgr *cm_ctx, 2196 struct wlan_cm_connect_resp *resp) 2197 { 2198 QDF_STATUS status; 2199 struct cm_req *cm_req; 2200 bool same_candidate_used = false; 2201 2202 cm_req = cm_get_req_by_cm_id(cm_ctx, resp->cm_id); 2203 if (!cm_req) 2204 return QDF_STATUS_E_FAILURE; 2205 2206 status = cm_get_valid_candidate(cm_ctx, cm_req, resp, 2207 &same_candidate_used); 2208 if (QDF_IS_STATUS_ERROR(status)) 2209 goto connect_err; 2210 2211 /* 2212 * cached the first failure response if candidate is different from 2213 * previous. 2214 * Do not indicate to OSIF if same candidate is used again as we are not 2215 * done with this candidate. So inform once we move to next candidate. 2216 * This will also avoid flush for the scan entry. 2217 */ 2218 if (!same_candidate_used) { 2219 cm_store_first_candidate_rsp(cm_ctx, resp->cm_id, resp); 2220 mlme_cm_osif_failed_candidate_ind(cm_ctx->vdev, resp); 2221 } 2222 2223 cm_update_ser_timer_for_new_candidate(cm_ctx, resp->cm_id); 2224 2225 status = cm_send_bss_select_ind(cm_ctx, &cm_req->connect_req); 2226 2227 /* 2228 * If candidate select indication is not supported continue with bss 2229 * peer create, else peer will be created after resp. 2230 */ 2231 if (status == QDF_STATUS_E_NOSUPPORT) { 2232 /* Update vdev mlme mac address based on connection type */ 2233 status = cm_update_vdev_mlme_macaddr(cm_ctx, 2234 &cm_req->connect_req); 2235 if (QDF_IS_STATUS_ERROR(status)) 2236 goto connect_err; 2237 2238 cm_create_bss_peer(cm_ctx, &cm_req->connect_req); 2239 } else if (QDF_IS_STATUS_ERROR(status)) { 2240 goto connect_err; 2241 } 2242 2243 return QDF_STATUS_SUCCESS; 2244 2245 connect_err: 2246 return cm_sm_deliver_event_sync(cm_ctx, WLAN_CM_SM_EV_CONNECT_FAILURE, 2247 sizeof(*resp), resp); 2248 2249 } 2250 2251 bool cm_connect_resp_cmid_match_list_head(struct cnx_mgr *cm_ctx, 2252 struct wlan_cm_connect_resp *resp) 2253 { 2254 return cm_check_cmid_match_list_head(cm_ctx, &resp->cm_id); 2255 } 2256 2257 void cm_fill_vdev_crypto_params(struct cnx_mgr *cm_ctx, 2258 struct wlan_cm_connect_req *req) 2259 { 2260 /* fill vdev crypto from the connect req */ 2261 wlan_crypto_set_vdev_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_AUTH_MODE, 2262 req->crypto.auth_type); 2263 wlan_crypto_set_vdev_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_KEY_MGMT, 2264 req->crypto.akm_suites); 2265 wlan_crypto_set_vdev_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_UCAST_CIPHER, 2266 req->crypto.ciphers_pairwise); 2267 wlan_crypto_set_vdev_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_MCAST_CIPHER, 2268 req->crypto.group_cipher); 2269 wlan_crypto_set_vdev_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_MGMT_CIPHER, 2270 req->crypto.mgmt_ciphers); 2271 wlan_crypto_set_vdev_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_RSN_CAP, 2272 req->crypto.rsn_caps); 2273 } 2274 2275 static QDF_STATUS 2276 cm_if_mgr_inform_connect_active(struct wlan_objmgr_vdev *vdev) 2277 { 2278 return if_mgr_deliver_event(vdev, WLAN_IF_MGR_EV_CONNECT_ACTIVE, NULL); 2279 } 2280 2281 QDF_STATUS cm_connect_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id) 2282 { 2283 struct cm_req *cm_req; 2284 QDF_STATUS status; 2285 struct wlan_cm_connect_req *req; 2286 2287 cm_if_mgr_inform_connect_active(cm_ctx->vdev); 2288 2289 cm_ctx->active_cm_id = *cm_id; 2290 cm_req = cm_get_req_by_cm_id(cm_ctx, *cm_id); 2291 if (!cm_req) { 2292 /* 2293 * Remove the command from serialization active queue, if 2294 * connect req was not found, to avoid active cmd timeout. 2295 * This can happen if a thread tried to flush the pending 2296 * connect request and while doing so, it removed the 2297 * CM pending request, but before it tried to remove pending 2298 * command from serialization, the command becomes active in 2299 * another thread. 2300 */ 2301 cm_remove_cmd_from_serialization(cm_ctx, *cm_id); 2302 return QDF_STATUS_E_INVAL; 2303 } 2304 2305 cm_req->connect_req.connect_active_time = 2306 qdf_mc_timer_get_system_time(); 2307 req = &cm_req->connect_req.req; 2308 wlan_vdev_mlme_set_ssid(cm_ctx->vdev, req->ssid.ssid, req->ssid.length); 2309 /* 2310 * free vdev keys before setting crypto params for 1x/ owe roaming, 2311 * link vdev keys would be cleaned in osif 2312 */ 2313 if (!wlan_vdev_mlme_is_mlo_link_vdev(cm_ctx->vdev) && 2314 !wlan_cm_check_mlo_roam_auth_status(cm_ctx->vdev)) 2315 wlan_crypto_free_vdev_key(cm_ctx->vdev); 2316 cm_fill_vdev_crypto_params(cm_ctx, req); 2317 cm_store_wep_key(cm_ctx, &req->crypto, *cm_id); 2318 2319 if (mlo_is_sta_bridge_vdev(cm_ctx->vdev)) 2320 status = QDF_STATUS_SUCCESS; 2321 else 2322 status = cm_get_valid_candidate(cm_ctx, cm_req, NULL, NULL); 2323 2324 if (QDF_IS_STATUS_ERROR(status)) 2325 goto connect_err; 2326 2327 status = cm_send_bss_select_ind(cm_ctx, &cm_req->connect_req); 2328 /* 2329 * If candidate select indication is not supported continue with bss 2330 * peer create, else peer will be created after resp. 2331 */ 2332 if (status == QDF_STATUS_E_NOSUPPORT) { 2333 /* Update vdev mlme mac address based on connection type */ 2334 status = cm_update_vdev_mlme_macaddr(cm_ctx, 2335 &cm_req->connect_req); 2336 if (QDF_IS_STATUS_ERROR(status)) 2337 goto connect_err; 2338 2339 cm_create_bss_peer(cm_ctx, &cm_req->connect_req); 2340 } else if (QDF_IS_STATUS_ERROR(status)) { 2341 goto connect_err; 2342 } 2343 2344 return QDF_STATUS_SUCCESS; 2345 2346 connect_err: 2347 return cm_send_connect_start_fail(cm_ctx, 2348 &cm_req->connect_req, CM_JOIN_FAILED); 2349 } 2350 2351 #ifdef WLAN_FEATURE_FILS_SK 2352 static void cm_copy_fils_info(struct wlan_cm_vdev_connect_req *req, 2353 struct cm_req *cm_req) 2354 { 2355 req->fils_info = &cm_req->connect_req.req.fils_info; 2356 } 2357 2358 static inline void cm_set_fils_connection(struct cnx_mgr *cm_ctx, 2359 struct wlan_cm_connect_resp *resp) 2360 { 2361 int32_t key_mgmt; 2362 2363 /* 2364 * Check and set only in case of failure and when 2365 * resp->is_fils_connection is not already set, else return. 2366 */ 2367 if (QDF_IS_STATUS_SUCCESS(resp->connect_status) || 2368 resp->is_fils_connection) 2369 return; 2370 2371 key_mgmt = wlan_crypto_get_param(cm_ctx->vdev, 2372 WLAN_CRYPTO_PARAM_KEY_MGMT); 2373 2374 if (key_mgmt & (1 << WLAN_CRYPTO_KEY_MGMT_FILS_SHA256 | 2375 1 << WLAN_CRYPTO_KEY_MGMT_FILS_SHA384 | 2376 1 << WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA256 | 2377 1 << WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA384)) 2378 resp->is_fils_connection = true; 2379 } 2380 #else 2381 static inline void cm_copy_fils_info(struct wlan_cm_vdev_connect_req *req, 2382 struct cm_req *cm_req) 2383 { 2384 } 2385 2386 static inline void cm_set_fils_connection(struct cnx_mgr *cm_ctx, 2387 struct wlan_cm_connect_resp *resp) 2388 { 2389 } 2390 #endif 2391 2392 #ifdef WLAN_FEATURE_11BE_MLO 2393 static inline 2394 void cm_update_ml_partner_info(struct wlan_objmgr_vdev *vdev, 2395 struct wlan_cm_connect_req *req, 2396 struct wlan_cm_vdev_connect_req *connect_req) 2397 { 2398 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) 2399 return; 2400 2401 qdf_mem_copy(&connect_req->ml_parnter_info, 2402 &req->ml_parnter_info, 2403 sizeof(struct mlo_partner_info)); 2404 } 2405 #else 2406 static inline 2407 void cm_update_ml_partner_info(struct wlan_objmgr_vdev *vdev, 2408 struct wlan_cm_connect_req *req, 2409 struct wlan_cm_vdev_connect_req *connect_req) 2410 { 2411 } 2412 #endif 2413 2414 static 2415 void cm_update_per_peer_key_mgmt_crypto_params(struct wlan_objmgr_vdev *vdev, 2416 struct security_info *neg_sec_info) 2417 { 2418 int32_t key_mgmt = 0; 2419 int32_t neg_akm = neg_sec_info->key_mgmt; 2420 2421 /* 2422 * As there can be multiple AKM present select the most secured AKM 2423 * present 2424 */ 2425 if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA384)) 2426 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA384); 2427 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA256)) 2428 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA256); 2429 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FILS_SHA384)) 2430 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FILS_SHA384); 2431 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FILS_SHA256)) 2432 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FILS_SHA256); 2433 else if (QDF_HAS_PARAM(neg_akm, 2434 WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384)) 2435 QDF_SET_PARAM(key_mgmt, 2436 WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384); 2437 else if (QDF_HAS_PARAM(neg_akm, 2438 WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B_192)) 2439 QDF_SET_PARAM(key_mgmt, 2440 WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B_192); 2441 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B)) 2442 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B); 2443 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FT_SAE_EXT_KEY)) 2444 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_SAE_EXT_KEY); 2445 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FT_SAE)) 2446 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_SAE); 2447 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_SAE_EXT_KEY)) 2448 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_SAE_EXT_KEY); 2449 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_SAE)) 2450 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_SAE); 2451 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_OWE)) 2452 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_OWE); 2453 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_DPP)) 2454 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_DPP); 2455 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X)) 2456 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X); 2457 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256)) 2458 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256); 2459 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X)) 2460 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_IEEE8021X); 2461 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FT_PSK_SHA384)) 2462 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_PSK_SHA384); 2463 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_PSK_SHA384)) 2464 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_PSK_SHA384); 2465 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_PSK_SHA256)) 2466 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_PSK_SHA256); 2467 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FT_PSK)) 2468 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_PSK); 2469 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_PSK)) 2470 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_PSK); 2471 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_WAPI_PSK)) 2472 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_WAPI_PSK); 2473 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_WAPI_CERT)) 2474 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_WAPI_CERT); 2475 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_CCKM)) 2476 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_CCKM); 2477 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_OSEN)) 2478 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_OSEN); 2479 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_WPS)) 2480 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_WPS); 2481 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_NO_WPA)) 2482 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_NO_WPA); 2483 else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_WPA_NONE)) 2484 QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_WPA_NONE); 2485 else /* use original if no akm match */ 2486 key_mgmt = neg_akm; 2487 2488 wlan_crypto_set_vdev_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT, key_mgmt); 2489 /* 2490 * Overwrite the key mgmt with single key_mgmt if multiple are present 2491 */ 2492 neg_sec_info->key_mgmt = key_mgmt; 2493 } 2494 2495 static 2496 void cm_update_per_peer_ucastcipher_crypto_params(struct wlan_objmgr_vdev *vdev, 2497 struct security_info *neg_sec_info) 2498 { 2499 int32_t ucastcipherset = 0; 2500 2501 /* 2502 * As there can be multiple ucastcipher present select the most secured 2503 * ucastcipher present. 2504 */ 2505 if (QDF_HAS_PARAM(neg_sec_info->ucastcipherset, 2506 WLAN_CRYPTO_CIPHER_AES_GCM_256)) 2507 QDF_SET_PARAM(ucastcipherset, WLAN_CRYPTO_CIPHER_AES_GCM_256); 2508 else if (QDF_HAS_PARAM(neg_sec_info->ucastcipherset, 2509 WLAN_CRYPTO_CIPHER_AES_CCM_256)) 2510 QDF_SET_PARAM(ucastcipherset, WLAN_CRYPTO_CIPHER_AES_CCM_256); 2511 else if (QDF_HAS_PARAM(neg_sec_info->ucastcipherset, 2512 WLAN_CRYPTO_CIPHER_AES_GCM)) 2513 QDF_SET_PARAM(ucastcipherset, WLAN_CRYPTO_CIPHER_AES_GCM); 2514 else if (QDF_HAS_PARAM(neg_sec_info->ucastcipherset, 2515 WLAN_CRYPTO_CIPHER_AES_CCM)) 2516 QDF_SET_PARAM(ucastcipherset, WLAN_CRYPTO_CIPHER_AES_CCM); 2517 else if (QDF_HAS_PARAM(neg_sec_info->ucastcipherset, 2518 WLAN_CRYPTO_CIPHER_TKIP)) 2519 QDF_SET_PARAM(ucastcipherset, WLAN_CRYPTO_CIPHER_TKIP); 2520 else 2521 ucastcipherset = neg_sec_info->ucastcipherset; 2522 2523 wlan_crypto_set_vdev_param(vdev, WLAN_CRYPTO_PARAM_UCAST_CIPHER, 2524 ucastcipherset); 2525 /* 2526 * Overwrite the ucastcipher with single ucast cipher if multiple are 2527 * present 2528 */ 2529 neg_sec_info->ucastcipherset = ucastcipherset; 2530 } 2531 2532 static 2533 void cm_update_per_peer_crypto_params(struct wlan_objmgr_vdev *vdev, 2534 struct cm_connect_req *connect_req) 2535 { 2536 struct security_info *neg_sec_info; 2537 uint16_t rsn_caps; 2538 2539 /* Do only for WPA/WPA2/WPA3 */ 2540 if (!connect_req->req.crypto.wpa_versions) 2541 return; 2542 2543 /* 2544 * Some non PMF AP misbehave if in assoc req RSN IE contain PMF capable 2545 * bit set. Thus only if AP and self are capable, try PMF connection 2546 * else set PMF as 0. The PMF filtering is already taken care in 2547 * get scan results. 2548 */ 2549 neg_sec_info = &connect_req->cur_candidate->entry->neg_sec_info; 2550 rsn_caps = connect_req->req.crypto.rsn_caps; 2551 if (!(neg_sec_info->rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED && 2552 rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED)) { 2553 rsn_caps &= ~WLAN_CRYPTO_RSN_CAP_MFP_ENABLED; 2554 rsn_caps &= ~WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED; 2555 rsn_caps &= ~WLAN_CRYPTO_RSN_CAP_OCV_SUPPORTED; 2556 } 2557 2558 /* Update the new rsn caps */ 2559 wlan_crypto_set_vdev_param(vdev, WLAN_CRYPTO_PARAM_RSN_CAP, 2560 rsn_caps); 2561 2562 cm_update_per_peer_key_mgmt_crypto_params(vdev, neg_sec_info); 2563 cm_update_per_peer_ucastcipher_crypto_params(vdev, neg_sec_info); 2564 } 2565 2566 QDF_STATUS 2567 cm_resume_connect_after_peer_create(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id) 2568 { 2569 struct wlan_cm_vdev_connect_req req; 2570 struct cm_req *cm_req; 2571 QDF_STATUS status; 2572 struct security_info *neg_sec_info; 2573 uint8_t country_code[REG_ALPHA2_LEN + 1] = {0}; 2574 struct wlan_objmgr_psoc *psoc; 2575 struct cm_connect_req *conn_req = NULL; 2576 2577 psoc = wlan_pdev_get_psoc(wlan_vdev_get_pdev(cm_ctx->vdev)); 2578 2579 cm_req = cm_get_req_by_cm_id(cm_ctx, *cm_id); 2580 if (!cm_req) 2581 return QDF_STATUS_E_FAILURE; 2582 2583 conn_req = &cm_req->connect_req; 2584 /* Handle WDS bridge vdev */ 2585 if (mlo_is_sta_bridge_vdev(cm_ctx->vdev) && conn_req) { 2586 req.vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 2587 req.cm_id = *cm_id; 2588 req.force_rsne_override = conn_req->req.force_rsne_override; 2589 req.is_wps_connection = conn_req->req.is_wps_connection; 2590 req.is_osen_connection = conn_req->req.is_osen_connection; 2591 req.assoc_ie = conn_req->req.assoc_ie; 2592 req.scan_ie = conn_req->req.scan_ie; 2593 cm_copy_fils_info(&req, cm_req); 2594 req.ht_caps = conn_req->req.ht_caps; 2595 req.ht_caps_mask = conn_req->req.ht_caps_mask; 2596 req.vht_caps = conn_req->req.vht_caps; 2597 req.vht_caps_mask = conn_req->req.vht_caps_mask; 2598 req.is_non_assoc_link = conn_req->req.is_non_assoc_link; 2599 cm_update_ml_partner_info(cm_ctx->vdev, &conn_req->req, &req); 2600 wlan_reg_get_cc_and_src(psoc, country_code); 2601 goto connect_req; 2602 } 2603 2604 /* 2605 * As keymgmt and ucast cipher can be multiple. 2606 * Choose one keymgmt and one ucastcipherset based on higher security. 2607 */ 2608 cm_update_per_peer_crypto_params(cm_ctx->vdev, &cm_req->connect_req); 2609 2610 req.vdev_id = wlan_vdev_get_id(cm_ctx->vdev); 2611 req.cm_id = *cm_id; 2612 req.force_rsne_override = cm_req->connect_req.req.force_rsne_override; 2613 req.is_wps_connection = cm_req->connect_req.req.is_wps_connection; 2614 req.is_osen_connection = cm_req->connect_req.req.is_osen_connection; 2615 req.assoc_ie = cm_req->connect_req.req.assoc_ie; 2616 req.scan_ie = cm_req->connect_req.req.scan_ie; 2617 req.bss = cm_req->connect_req.cur_candidate; 2618 cm_copy_fils_info(&req, cm_req); 2619 req.ht_caps = cm_req->connect_req.req.ht_caps; 2620 req.ht_caps_mask = cm_req->connect_req.req.ht_caps_mask; 2621 req.vht_caps = cm_req->connect_req.req.vht_caps; 2622 req.vht_caps_mask = cm_req->connect_req.req.vht_caps_mask; 2623 req.is_non_assoc_link = cm_req->connect_req.req.is_non_assoc_link; 2624 cm_update_ml_partner_info(cm_ctx->vdev, &cm_req->connect_req.req, &req); 2625 2626 neg_sec_info = &cm_req->connect_req.cur_candidate->entry->neg_sec_info; 2627 if (util_scan_entry_is_hidden_ap(req.bss->entry) && 2628 QDF_HAS_PARAM(neg_sec_info->key_mgmt, WLAN_CRYPTO_KEY_MGMT_OWE)) { 2629 mlme_debug(CM_PREFIX_FMT "OWE transition candidate has wildcard ssid", 2630 CM_PREFIX_REF(req.vdev_id, req.cm_id)); 2631 req.owe_trans_ssid = cm_req->connect_req.req.ssid; 2632 } 2633 2634 wlan_reg_get_cc_and_src(psoc, country_code); 2635 mlme_nofl_info(CM_PREFIX_FMT "Connecting to " QDF_SSID_FMT " " QDF_MAC_ADDR_FMT " rssi: %d freq: %d akm 0x%x cipher: uc 0x%x mc 0x%x, wps %d osen %d force RSN %d CC: %c%c", 2636 CM_PREFIX_REF(req.vdev_id, req.cm_id), 2637 QDF_SSID_REF(cm_req->connect_req.req.ssid.length, 2638 cm_req->connect_req.req.ssid.ssid), 2639 QDF_MAC_ADDR_REF(req.bss->entry->bssid.bytes), 2640 req.bss->entry->rssi_raw, 2641 req.bss->entry->channel.chan_freq, 2642 neg_sec_info->key_mgmt, neg_sec_info->ucastcipherset, 2643 neg_sec_info->mcastcipherset, req.is_wps_connection, 2644 req.is_osen_connection, req.force_rsne_override, 2645 country_code[0], 2646 country_code[1]); 2647 connect_req: 2648 status = mlme_cm_connect_req(cm_ctx->vdev, &req); 2649 if (QDF_IS_STATUS_ERROR(status)) { 2650 mlme_err(CM_PREFIX_FMT "connect request failed", 2651 CM_PREFIX_REF(req.vdev_id, req.cm_id)); 2652 /* try delete bss peer if req fails */ 2653 mlme_cm_bss_peer_delete_req(cm_ctx->vdev); 2654 status = cm_send_connect_start_fail(cm_ctx, 2655 &cm_req->connect_req, 2656 CM_JOIN_FAILED); 2657 } 2658 2659 return status; 2660 } 2661 2662 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_FEATURE_11BE_MLO_ADV_FEATURE) 2663 static void cm_inform_bcn_probe_handler(struct cnx_mgr *cm_ctx, 2664 struct scan_cache_entry *bss, 2665 wlan_cm_id cm_id) 2666 { 2667 struct element_info *bcn_probe_rsp; 2668 int32_t rssi; 2669 qdf_freq_t freq; 2670 2671 bcn_probe_rsp = &bss->raw_frame; 2672 rssi = bss->rssi_raw; 2673 freq = util_scan_entry_channel_frequency(bss); 2674 2675 cm_inform_bcn_probe(cm_ctx, bcn_probe_rsp->ptr, bcn_probe_rsp->len, 2676 freq, rssi, cm_id); 2677 } 2678 2679 static void cm_update_partner_link_scan_db(struct cnx_mgr *cm_ctx, 2680 wlan_cm_id cm_id, 2681 qdf_list_t *candidate_list, 2682 struct scan_cache_entry *cur_bss) 2683 { 2684 qdf_list_node_t *cur_node = NULL, *next_node = NULL; 2685 struct scan_cache_node *candidate; 2686 struct scan_cache_entry *bss; 2687 2688 qdf_list_peek_front(candidate_list, &cur_node); 2689 2690 while (cur_node) { 2691 qdf_list_peek_next(candidate_list, cur_node, &next_node); 2692 candidate = qdf_container_of(cur_node, struct scan_cache_node, 2693 node); 2694 bss = candidate->entry; 2695 /* 2696 * If BSS is ML and not current bss and BSS mld mac is same as 2697 * cur bss then inform it to scan cache to avoid scan cache 2698 * ageing out. 2699 */ 2700 if (!qdf_is_macaddr_equal(&bss->bssid, &cur_bss->bssid) && 2701 bss->ml_info.num_links && 2702 cur_bss->ml_info.num_links && 2703 qdf_is_macaddr_equal(&bss->ml_info.mld_mac_addr, 2704 &cur_bss->ml_info.mld_mac_addr)) { 2705 mlme_debug(CM_PREFIX_FMT "Inform Partner bssid: " QDF_MAC_ADDR_FMT " to kernel", 2706 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), 2707 cm_id), 2708 QDF_MAC_ADDR_REF(bss->bssid.bytes)); 2709 cm_inform_bcn_probe_handler(cm_ctx, bss, cm_id); 2710 } 2711 cur_node = next_node; 2712 next_node = NULL; 2713 } 2714 } 2715 #else 2716 static 2717 inline void cm_update_partner_link_scan_db(struct cnx_mgr *cm_ctx, 2718 wlan_cm_id cm_id, 2719 qdf_list_t *candidate_list, 2720 struct scan_cache_entry *cur_bss) 2721 { 2722 } 2723 #endif 2724 2725 /** 2726 * cm_update_scan_db_on_connect_success() - update scan db with beacon or 2727 * probe resp 2728 * @cm_ctx: connection manager context 2729 * @resp: connect resp 2730 * 2731 * update scan db, so that kernel and driver do not age out 2732 * the connected AP entry. 2733 * 2734 * Context: Can be called from any context and to be used only if connect 2735 * is successful and SM is in connected state. i.e. SM lock is hold. 2736 * 2737 * Return: void 2738 */ 2739 static void 2740 cm_update_scan_db_on_connect_success(struct cnx_mgr *cm_ctx, 2741 struct wlan_cm_connect_resp *resp) 2742 { 2743 struct element_info *bcn_probe_rsp; 2744 struct cm_req *cm_req; 2745 int32_t rssi; 2746 struct scan_cache_node *cur_candidate; 2747 2748 if (!cm_is_vdev_connected(cm_ctx->vdev)) 2749 return; 2750 2751 cm_req = cm_get_req_by_cm_id(cm_ctx, resp->cm_id); 2752 if (!cm_req) 2753 return; 2754 /* if reassoc get from roam req else from connect req */ 2755 if (resp->is_reassoc) 2756 cur_candidate = cm_req->roam_req.cur_candidate; 2757 else 2758 cur_candidate = cm_req->connect_req.cur_candidate; 2759 2760 if (!cur_candidate) 2761 return; 2762 2763 /* 2764 * Get beacon or probe resp from connect response, and if not present 2765 * use cur candidate to get beacon or probe resp 2766 */ 2767 if (resp->connect_ies.bcn_probe_rsp.ptr) 2768 bcn_probe_rsp = &resp->connect_ies.bcn_probe_rsp; 2769 else 2770 bcn_probe_rsp = &cur_candidate->entry->raw_frame; 2771 2772 rssi = cur_candidate->entry->rssi_raw; 2773 2774 cm_inform_bcn_probe(cm_ctx, bcn_probe_rsp->ptr, bcn_probe_rsp->len, 2775 resp->freq, rssi, resp->cm_id); 2776 2777 /* 2778 * If vdev is an MLO vdev and not reassoc then use partner link info to 2779 * inform partner link scan entry to kernel. 2780 */ 2781 if (!resp->is_reassoc && wlan_vdev_mlme_is_mlo_vdev(cm_ctx->vdev)) 2782 cm_update_partner_link_scan_db(cm_ctx, resp->cm_id, 2783 cm_req->connect_req.candidate_list, 2784 cur_candidate->entry); 2785 } 2786 2787 #ifdef WLAN_FEATURE_11BE_MLO 2788 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 2789 static inline void 2790 cm_clear_vdev_mlo_cap(struct wlan_objmgr_vdev *vdev) 2791 { 2792 wlan_vdev_mlme_clear_mlo_vdev(vdev); 2793 } 2794 #else /*WLAN_FEATURE_11BE_MLO_ADV_FEATURE*/ 2795 static inline void 2796 cm_clear_vdev_mlo_cap(struct wlan_objmgr_vdev *vdev) 2797 { 2798 /* If the connect req fails on assoc link, reset 2799 * the MLO cap flags. The flags will be updated based 2800 * on next connect req 2801 */ 2802 if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev)) 2803 ucfg_mlo_mld_clear_mlo_cap(vdev); 2804 2805 wlan_vdev_set_link_id(vdev, WLAN_LINK_ID_INVALID); 2806 } 2807 #endif /*WLAN_FEATURE_11BE_MLO_ADV_FEATURE*/ 2808 #else /*WLAN_FEATURE_11BE_MLO*/ 2809 static inline void 2810 cm_clear_vdev_mlo_cap(struct wlan_objmgr_vdev *vdev) 2811 { } 2812 #endif /*WLAN_FEATURE_11BE_MLO*/ 2813 2814 /** 2815 * cm_is_connect_id_reassoc_in_non_init() 2816 * @cm_ctx: connection manager context 2817 * @cm_id: cm id 2818 * 2819 * If connect req is a reassoc req and received in non init state. 2820 * Caller should take cm_ctx lock. 2821 * 2822 * Return: bool 2823 */ 2824 static bool cm_is_connect_id_reassoc_in_non_init(struct cnx_mgr *cm_ctx, 2825 wlan_cm_id cm_id) 2826 { 2827 qdf_list_node_t *cur_node = NULL, *next_node = NULL; 2828 struct cm_req *cm_req; 2829 uint32_t prefix = CM_ID_GET_PREFIX(cm_id); 2830 bool is_reassoc = false; 2831 2832 if (prefix != CONNECT_REQ_PREFIX) 2833 return is_reassoc; 2834 2835 qdf_list_peek_front(&cm_ctx->req_list, &cur_node); 2836 while (cur_node) { 2837 qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node); 2838 cm_req = qdf_container_of(cur_node, struct cm_req, node); 2839 2840 if (cm_req->cm_id == cm_id) { 2841 if (cm_req->connect_req.req.reassoc_in_non_init) 2842 is_reassoc = true; 2843 return is_reassoc; 2844 } 2845 2846 cur_node = next_node; 2847 next_node = NULL; 2848 } 2849 2850 return is_reassoc; 2851 } 2852 2853 #ifdef CONN_MGR_ADV_FEATURE 2854 /** 2855 * cm_osif_connect_complete() - This API will send the response to osif layer 2856 * @cm_ctx: connection manager context 2857 * @resp: connect resp sent to osif 2858 * 2859 * This function fetches the first response in case of connect failure and sent 2860 * it to the osif layer, otherwise, sent the provided response to osif. 2861 * 2862 * Return:void 2863 */ 2864 static void cm_osif_connect_complete(struct cnx_mgr *cm_ctx, 2865 struct wlan_cm_connect_resp *resp) 2866 { 2867 struct wlan_cm_connect_resp first_failure_resp = {0}; 2868 QDF_STATUS status = QDF_STATUS_E_FAILURE; 2869 struct wlan_cm_connect_resp *connect_rsp = resp; 2870 2871 if (QDF_IS_STATUS_ERROR(resp->connect_status)) { 2872 status = cm_get_first_candidate_rsp(cm_ctx, resp->cm_id, 2873 &first_failure_resp); 2874 if (QDF_IS_STATUS_SUCCESS(status)) 2875 connect_rsp = &first_failure_resp; 2876 } 2877 2878 mlme_cm_osif_connect_complete(cm_ctx->vdev, connect_rsp); 2879 2880 if (QDF_IS_STATUS_SUCCESS(status)) 2881 cm_free_connect_rsp_ies(connect_rsp); 2882 } 2883 #else 2884 static void cm_osif_connect_complete(struct cnx_mgr *cm_ctx, 2885 struct wlan_cm_connect_resp *resp) 2886 { 2887 mlme_cm_osif_connect_complete(cm_ctx->vdev, resp); 2888 } 2889 #endif 2890 2891 QDF_STATUS cm_notify_connect_complete(struct cnx_mgr *cm_ctx, 2892 struct wlan_cm_connect_resp *resp, 2893 bool acquire_lock) 2894 { 2895 enum wlan_cm_sm_state sm_state; 2896 2897 sm_state = cm_get_state(cm_ctx); 2898 2899 mlme_cm_connect_complete_ind(cm_ctx->vdev, resp); 2900 mlo_sta_link_connect_notify(cm_ctx->vdev, resp); 2901 /* 2902 * If connect req was a reassoc req and was received in not connected 2903 * state send disconnect instead of connect resp to kernel to cleanup 2904 * kernel flags 2905 */ 2906 if (QDF_IS_STATUS_ERROR(resp->connect_status) && 2907 sm_state == WLAN_CM_S_INIT) { 2908 if (acquire_lock) 2909 cm_req_lock_acquire(cm_ctx); 2910 if (cm_is_connect_id_reassoc_in_non_init(cm_ctx, resp->cm_id)) { 2911 resp->send_disconnect = true; 2912 mlme_debug(CM_PREFIX_FMT "Set send disconnect to true to indicate disconnect instead of connect resp", 2913 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), 2914 resp->cm_id)); 2915 } 2916 if (acquire_lock) 2917 cm_req_lock_release(cm_ctx); 2918 } 2919 cm_osif_connect_complete(cm_ctx, resp); 2920 cm_if_mgr_inform_connect_complete(cm_ctx->vdev, 2921 resp->connect_status); 2922 cm_inform_dlm_connect_complete(cm_ctx->vdev, resp); 2923 if (QDF_IS_STATUS_ERROR(resp->connect_status) && 2924 sm_state == WLAN_CM_S_INIT && !(resp->cm_id & CM_ID_LSWITCH_BIT)) 2925 cm_clear_vdev_mlo_cap(cm_ctx->vdev); 2926 2927 return QDF_STATUS_SUCCESS; 2928 } 2929 2930 QDF_STATUS cm_connect_complete(struct cnx_mgr *cm_ctx, 2931 struct wlan_cm_connect_resp *resp) 2932 { 2933 enum wlan_cm_sm_state sm_state; 2934 struct bss_info bss_info; 2935 struct mlme_info mlme_info = {0}; 2936 bool send_ind = true; 2937 2938 /* 2939 * If the entry is not present in the list, it must have been cleared 2940 * already. 2941 */ 2942 if (!cm_get_req_by_cm_id(cm_ctx, resp->cm_id)) 2943 return QDF_STATUS_SUCCESS; 2944 2945 sm_state = cm_get_state(cm_ctx); 2946 cm_set_fils_connection(cm_ctx, resp); 2947 if (QDF_IS_STATUS_SUCCESS(resp->connect_status) && 2948 sm_state == WLAN_CM_S_CONNECTED) { 2949 cm_update_scan_db_on_connect_success(cm_ctx, resp); 2950 /* set WEP and FILS key on success */ 2951 cm_set_fils_wep_key(cm_ctx, resp); 2952 } 2953 2954 /* In case of reassoc failure no need to inform osif/legacy/ifmanager */ 2955 if (resp->is_reassoc && QDF_IS_STATUS_ERROR(resp->connect_status)) 2956 send_ind = false; 2957 2958 if (send_ind) 2959 cm_notify_connect_complete(cm_ctx, resp, 1); 2960 2961 /* Update scan entry in case connect is success or fails with bssid */ 2962 if (!qdf_is_macaddr_zero(&resp->bssid)) { 2963 if (QDF_IS_STATUS_SUCCESS(resp->connect_status)) 2964 mlme_info.assoc_state = SCAN_ENTRY_CON_STATE_ASSOC; 2965 else 2966 mlme_info.assoc_state = SCAN_ENTRY_CON_STATE_NONE; 2967 qdf_copy_macaddr(&bss_info.bssid, &resp->bssid); 2968 bss_info.freq = resp->freq; 2969 bss_info.ssid.length = resp->ssid.length; 2970 qdf_mem_copy(&bss_info.ssid.ssid, resp->ssid.ssid, 2971 bss_info.ssid.length); 2972 wlan_scan_update_mlme_by_bssinfo( 2973 wlan_vdev_get_pdev(cm_ctx->vdev), 2974 &bss_info, &mlme_info); 2975 } 2976 2977 cm_standby_link_update_mlme_by_bssid(cm_ctx->vdev, 2978 mlme_info.assoc_state, 2979 resp->ssid); 2980 2981 mlme_debug(CM_PREFIX_FMT, 2982 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), 2983 resp->cm_id)); 2984 cm_remove_cmd(cm_ctx, &resp->cm_id); 2985 2986 if (resp->cm_id & CM_ID_LSWITCH_BIT) { 2987 cm_reset_active_cm_id(cm_ctx->vdev, resp->cm_id); 2988 mlo_mgr_link_switch_connect_done(cm_ctx->vdev, 2989 resp->connect_status); 2990 } 2991 2992 return QDF_STATUS_SUCCESS; 2993 } 2994 2995 QDF_STATUS cm_add_connect_req_to_list(struct cnx_mgr *cm_ctx, 2996 struct cm_connect_req *req) 2997 { 2998 QDF_STATUS status; 2999 struct cm_req *cm_req; 3000 3001 cm_req = qdf_container_of(req, struct cm_req, connect_req); 3002 req->cm_id = cm_get_cm_id(cm_ctx, req->req.source); 3003 cm_req->cm_id = req->cm_id; 3004 status = cm_add_req_to_list_and_indicate_osif(cm_ctx, cm_req, 3005 req->req.source); 3006 3007 return status; 3008 } 3009 3010 QDF_STATUS cm_connect_rsp(struct wlan_objmgr_vdev *vdev, 3011 struct wlan_cm_connect_resp *resp) 3012 { 3013 struct cnx_mgr *cm_ctx; 3014 QDF_STATUS qdf_status; 3015 wlan_cm_id cm_id; 3016 uint32_t prefix; 3017 struct qdf_mac_addr pmksa_mac = QDF_MAC_ADDR_ZERO_INIT; 3018 3019 cm_ctx = cm_get_cm_ctx(vdev); 3020 if (!cm_ctx) 3021 return QDF_STATUS_E_INVAL; 3022 3023 cm_id = cm_ctx->active_cm_id; 3024 prefix = CM_ID_GET_PREFIX(cm_id); 3025 3026 if (prefix != CONNECT_REQ_PREFIX || cm_id != resp->cm_id) { 3027 mlme_err(CM_PREFIX_FMT " Active cm_id 0x%x is different", 3028 CM_PREFIX_REF(wlan_vdev_get_id(vdev), resp->cm_id), 3029 cm_id); 3030 qdf_status = QDF_STATUS_E_FAILURE; 3031 goto post_err; 3032 } 3033 3034 cm_connect_rsp_get_mld_addr_or_bssid(resp, &pmksa_mac); 3035 3036 if (QDF_IS_STATUS_SUCCESS(resp->connect_status)) { 3037 /* 3038 * On successful connection to sae single pmk AP, 3039 * clear all the single pmk AP. 3040 */ 3041 if (cm_is_cm_id_current_candidate_single_pmk(cm_ctx, cm_id)) 3042 wlan_crypto_selective_clear_sae_single_pmk_entries(vdev, 3043 &pmksa_mac); 3044 qdf_status = 3045 cm_sm_deliver_event(vdev, 3046 WLAN_CM_SM_EV_CONNECT_SUCCESS, 3047 sizeof(*resp), resp); 3048 if (QDF_IS_STATUS_SUCCESS(qdf_status)) 3049 return qdf_status; 3050 /* 3051 * failure mean that the new connect/disconnect is received so 3052 * cleanup. 3053 */ 3054 goto post_err; 3055 } 3056 3057 /* 3058 * Delete the PMKID of the BSSID for which the assoc reject is 3059 * received from the AP due to invalid PMKID reason. 3060 * This will avoid the driver trying to connect to same AP with 3061 * the same stale PMKID. when connection is tried again with this AP. 3062 */ 3063 if (resp->status_code == STATUS_INVALID_PMKID) 3064 cm_delete_pmksa_for_bssid(cm_ctx, &pmksa_mac); 3065 3066 /* In case of failure try with next candidate */ 3067 qdf_status = 3068 cm_sm_deliver_event(vdev, 3069 WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE, 3070 sizeof(*resp), resp); 3071 3072 if (QDF_IS_STATUS_SUCCESS(qdf_status)) 3073 return qdf_status; 3074 /* 3075 * If connection fails with Single PMK bssid, clear this pmk 3076 * entry in case of post failure. 3077 */ 3078 if (cm_is_cm_id_current_candidate_single_pmk(cm_ctx, cm_id)) 3079 cm_delete_pmksa_for_single_pmk_bssid(cm_ctx, &pmksa_mac); 3080 post_err: 3081 /* 3082 * If there is a event posting error it means the SM state is not in 3083 * JOIN ACTIVE (some new cmd has changed the state of SM), so just 3084 * complete the connect command. 3085 */ 3086 cm_connect_complete(cm_ctx, resp); 3087 3088 return qdf_status; 3089 } 3090 3091 QDF_STATUS cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev, 3092 QDF_STATUS status, 3093 struct qdf_mac_addr *peer_mac) 3094 { 3095 struct cnx_mgr *cm_ctx; 3096 QDF_STATUS qdf_status; 3097 wlan_cm_id cm_id; 3098 uint32_t prefix; 3099 struct wlan_cm_connect_resp *resp; 3100 3101 cm_ctx = cm_get_cm_ctx(vdev); 3102 if (!cm_ctx) 3103 return QDF_STATUS_E_INVAL; 3104 3105 cm_id = cm_ctx->active_cm_id; 3106 prefix = CM_ID_GET_PREFIX(cm_id); 3107 3108 if (prefix != CONNECT_REQ_PREFIX) { 3109 mlme_err(CM_PREFIX_FMT "active req is not connect req", 3110 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), cm_id)); 3111 mlme_cm_bss_peer_delete_req(vdev); 3112 return QDF_STATUS_E_INVAL; 3113 } 3114 3115 if (QDF_IS_STATUS_SUCCESS(status)) { 3116 qdf_status = 3117 cm_sm_deliver_event(vdev, 3118 WLAN_CM_SM_EV_BSS_CREATE_PEER_SUCCESS, 3119 sizeof(wlan_cm_id), &cm_id); 3120 if (QDF_IS_STATUS_SUCCESS(qdf_status)) 3121 return qdf_status; 3122 3123 mlme_cm_bss_peer_delete_req(vdev); 3124 goto post_err; 3125 } 3126 3127 /* In case of failure try with next candidate */ 3128 resp = qdf_mem_malloc(sizeof(*resp)); 3129 if (!resp) { 3130 qdf_status = QDF_STATUS_E_NOMEM; 3131 goto post_err; 3132 } 3133 3134 cm_fill_failure_resp_from_cm_id(cm_ctx, resp, cm_id, 3135 CM_PEER_CREATE_FAILED); 3136 qdf_status = 3137 cm_sm_deliver_event(vdev, 3138 WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE, 3139 sizeof(*resp), resp); 3140 qdf_mem_free(resp); 3141 if (QDF_IS_STATUS_SUCCESS(qdf_status)) 3142 return qdf_status; 3143 3144 post_err: 3145 /* 3146 * If there is a event posting error it means the SM state is not in 3147 * JOIN ACTIVE (some new cmd has changed the state of SM), so just 3148 * complete the connect command. 3149 */ 3150 cm_connect_handle_event_post_fail(cm_ctx, cm_id); 3151 return qdf_status; 3152 } 3153 3154 static void 3155 cm_copy_crypto_prarams(struct wlan_cm_connect_crypto_info *dst_params, 3156 struct wlan_crypto_params *src_params) 3157 { 3158 /* 3159 * As akm suites and ucast ciphers can be multiple. So, do ORing to 3160 * keep it along with newly added one's (newly added one will anyway 3161 * be part of it) 3162 */ 3163 dst_params->akm_suites |= src_params->key_mgmt; 3164 dst_params->auth_type = src_params->authmodeset; 3165 dst_params->ciphers_pairwise |= src_params->ucastcipherset; 3166 dst_params->group_cipher = src_params->mcastcipherset; 3167 dst_params->mgmt_ciphers = src_params->mgmtcipherset; 3168 dst_params->rsn_caps = src_params->rsn_caps; 3169 } 3170 3171 static void 3172 cm_set_crypto_params_from_ie(struct wlan_cm_connect_req *req) 3173 { 3174 struct wlan_crypto_params crypto_params; 3175 QDF_STATUS status; 3176 uint8_t wsc_oui[OUI_LENGTH]; 3177 uint8_t osen_oui[OUI_LENGTH]; 3178 uint32_t oui_cpu; 3179 3180 if (!req->assoc_ie.ptr) 3181 return; 3182 3183 oui_cpu = qdf_be32_to_cpu(WSC_OUI); 3184 qdf_mem_copy(wsc_oui, &oui_cpu, OUI_LENGTH); 3185 oui_cpu = qdf_be32_to_cpu(OSEN_OUI); 3186 qdf_mem_copy(osen_oui, &oui_cpu, OUI_LENGTH); 3187 if (wlan_get_vendor_ie_ptr_from_oui(osen_oui, OUI_LENGTH, 3188 req->assoc_ie.ptr, 3189 req->assoc_ie.len)) 3190 req->is_osen_connection = true; 3191 3192 if (wlan_get_vendor_ie_ptr_from_oui(wsc_oui, OUI_LENGTH, 3193 req->assoc_ie.ptr, 3194 req->assoc_ie.len)) 3195 req->is_wps_connection = true; 3196 3197 status = wlan_get_crypto_params_from_rsn_ie(&crypto_params, 3198 req->assoc_ie.ptr, 3199 req->assoc_ie.len); 3200 if (QDF_IS_STATUS_SUCCESS(status)) { 3201 cm_copy_crypto_prarams(&req->crypto, &crypto_params); 3202 return; 3203 } 3204 3205 status = wlan_get_crypto_params_from_wpa_ie(&crypto_params, 3206 req->assoc_ie.ptr, 3207 req->assoc_ie.len); 3208 if (QDF_IS_STATUS_SUCCESS(status)) { 3209 cm_copy_crypto_prarams(&req->crypto, &crypto_params); 3210 return; 3211 } 3212 3213 status = wlan_get_crypto_params_from_wapi_ie(&crypto_params, 3214 req->assoc_ie.ptr, 3215 req->assoc_ie.len); 3216 if (QDF_IS_STATUS_SUCCESS(status)) 3217 cm_copy_crypto_prarams(&req->crypto, &crypto_params); 3218 } 3219 3220 static QDF_STATUS 3221 cm_allocate_and_copy_ies_and_keys(struct wlan_cm_connect_req *target, 3222 struct wlan_cm_connect_req *source) 3223 { 3224 /* Reset the copied pointers of target */ 3225 target->assoc_ie.ptr = NULL; 3226 target->crypto.wep_keys.key = NULL; 3227 target->crypto.wep_keys.seq = NULL; 3228 target->scan_ie.ptr = NULL; 3229 3230 if (source->scan_ie.ptr) { 3231 target->scan_ie.ptr = qdf_mem_malloc(source->scan_ie.len); 3232 if (!target->scan_ie.ptr) 3233 target->scan_ie.len = 0; 3234 else 3235 qdf_mem_copy(target->scan_ie.ptr, 3236 source->scan_ie.ptr, source->scan_ie.len); 3237 } 3238 3239 if (source->assoc_ie.ptr) { 3240 target->assoc_ie.ptr = qdf_mem_malloc(source->assoc_ie.len); 3241 if (!target->assoc_ie.ptr) 3242 return QDF_STATUS_E_NOMEM; 3243 3244 qdf_mem_copy(target->assoc_ie.ptr, source->assoc_ie.ptr, 3245 source->assoc_ie.len); 3246 } 3247 3248 if (source->crypto.wep_keys.key) { 3249 target->crypto.wep_keys.key = 3250 qdf_mem_malloc(source->crypto.wep_keys.key_len); 3251 if (!target->crypto.wep_keys.key) 3252 return QDF_STATUS_E_NOMEM; 3253 3254 qdf_mem_copy(target->crypto.wep_keys.key, 3255 source->crypto.wep_keys.key, 3256 source->crypto.wep_keys.key_len); 3257 } 3258 3259 if (source->crypto.wep_keys.seq) { 3260 target->crypto.wep_keys.seq = 3261 qdf_mem_malloc(source->crypto.wep_keys.seq_len); 3262 if (!target->crypto.wep_keys.seq) 3263 return QDF_STATUS_E_NOMEM; 3264 3265 qdf_mem_copy(target->crypto.wep_keys.seq, 3266 source->crypto.wep_keys.seq, 3267 source->crypto.wep_keys.seq_len); 3268 } 3269 3270 return QDF_STATUS_SUCCESS; 3271 } 3272 3273 QDF_STATUS cm_connect_start_req(struct wlan_objmgr_vdev *vdev, 3274 struct wlan_cm_connect_req *req) 3275 { 3276 struct cnx_mgr *cm_ctx; 3277 struct cm_req *cm_req; 3278 struct cm_connect_req *connect_req; 3279 QDF_STATUS status; 3280 3281 cm_ctx = cm_get_cm_ctx(vdev); 3282 if (!cm_ctx) 3283 return QDF_STATUS_E_INVAL; 3284 3285 cm_vdev_scan_cancel(wlan_vdev_get_pdev(cm_ctx->vdev), cm_ctx->vdev); 3286 3287 /* 3288 * This would be freed as part of removal from cm req list if adding 3289 * to list is success after posting WLAN_CM_SM_EV_CONNECT_REQ. 3290 */ 3291 cm_req = qdf_mem_malloc(sizeof(*cm_req)); 3292 if (!cm_req) 3293 return QDF_STATUS_E_NOMEM; 3294 3295 if (wlan_vdev_mlme_is_mlo_vdev(vdev) && 3296 wlan_vdev_mlme_is_mlo_link_vdev(vdev)) 3297 req->is_non_assoc_link = 1; 3298 3299 connect_req = &cm_req->connect_req; 3300 connect_req->req = *req; 3301 3302 status = cm_allocate_and_copy_ies_and_keys(&connect_req->req, req); 3303 if (QDF_IS_STATUS_ERROR(status)) 3304 goto err; 3305 3306 cm_set_crypto_params_from_ie(&connect_req->req); 3307 3308 if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev)) 3309 cm_teardown_tdls(vdev); 3310 3311 status = cm_sm_deliver_event(vdev, WLAN_CM_SM_EV_CONNECT_REQ, 3312 sizeof(*connect_req), connect_req); 3313 3314 err: 3315 /* free the req if connect is not handled */ 3316 if (QDF_IS_STATUS_ERROR(status)) { 3317 cm_free_connect_req_mem(connect_req); 3318 qdf_mem_free(cm_req); 3319 } 3320 3321 return status; 3322 } 3323