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