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