1 /* 2 * Copyright (c) 2012-2015, 2020-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /** 19 * DOC: osif_cm_connect_rsp.c 20 * 21 * This file maintains definitaions of connect response apis. 22 */ 23 24 #include <linux/version.h> 25 #include <linux/nl80211.h> 26 #include <net/cfg80211.h> 27 #include "wlan_osif_priv.h" 28 #include "osif_cm_rsp.h" 29 #include "osif_cm_util.h" 30 #include "wlan_cfg80211.h" 31 #include "wlan_cfg80211_scan.h" 32 #include "wlan_mlo_mgr_sta.h" 33 #include "wlan_mlo_mgr_cmn.h" 34 #include "wlan_objmgr_vdev_obj.h" 35 #include "wlan_objmgr_peer_obj.h" 36 #include "utils_mlo.h" 37 38 #ifdef CONN_MGR_ADV_FEATURE 39 void osif_cm_get_assoc_req_ie_data(struct element_info *assoc_req, 40 size_t *ie_data_len, 41 const uint8_t **ie_data_ptr) 42 { 43 /* Validate IE and length */ 44 if (!assoc_req->len || !assoc_req->ptr || 45 assoc_req->len <= WLAN_ASSOC_REQ_IES_OFFSET) 46 return; 47 48 *ie_data_len = assoc_req->len - WLAN_ASSOC_REQ_IES_OFFSET; 49 *ie_data_ptr = assoc_req->ptr + WLAN_ASSOC_REQ_IES_OFFSET; 50 } 51 #else 52 void osif_cm_get_assoc_req_ie_data(struct element_info *assoc_req, 53 size_t *ie_data_len, 54 const uint8_t **ie_data_ptr) 55 { 56 /* Validate IE and length */ 57 if (!assoc_req->len || !assoc_req->ptr) 58 return; 59 60 *ie_data_len = assoc_req->len; 61 *ie_data_ptr = assoc_req->ptr; 62 } 63 #endif 64 65 void osif_cm_get_assoc_rsp_ie_data(struct element_info *assoc_rsp, 66 size_t *ie_data_len, 67 const uint8_t **ie_data_ptr) 68 { 69 /* Validate IE and length */ 70 if (!assoc_rsp->len || !assoc_rsp->ptr || 71 assoc_rsp->len <= WLAN_ASSOC_RSP_IES_OFFSET) 72 return; 73 74 *ie_data_len = assoc_rsp->len - WLAN_ASSOC_RSP_IES_OFFSET; 75 *ie_data_ptr = assoc_rsp->ptr + WLAN_ASSOC_RSP_IES_OFFSET; 76 } 77 78 /** 79 * osif_validate_connect_and_reset_src_id() - Validate connect response and 80 * resets source and id 81 * @osif_priv: Pointer to vdev osif priv 82 * @rsp: Connection manager connect response 83 * 84 * This function validates connect response and if the connect 85 * response is valid, resets the source and id of the command 86 * 87 * Context: Any context. Takes and releases cmd id spinlock. 88 * Return: QDF_STATUS 89 */ 90 static QDF_STATUS 91 osif_validate_connect_and_reset_src_id(struct vdev_osif_priv *osif_priv, 92 struct wlan_cm_connect_resp *rsp) 93 { 94 QDF_STATUS status = QDF_STATUS_SUCCESS; 95 96 /* 97 * Do not send to kernel if last osif cookie doesnt match or 98 * or source is CM_OSIF_CFG_CONNECT with success status. 99 * If cookie matches reset the cookie and source. 100 */ 101 qdf_spinlock_acquire(&osif_priv->cm_info.cmd_id_lock); 102 if (rsp->cm_id != osif_priv->cm_info.last_id || 103 (osif_priv->cm_info.last_source == CM_OSIF_CFG_CONNECT && 104 QDF_IS_STATUS_SUCCESS(rsp->connect_status))) { 105 osif_debug("Ignore as cm_id(0x%x)/src(%d) != cm_id(0x%x)/src(%d) OR source is CFG connect with status %d", 106 rsp->cm_id, CM_OSIF_CONNECT, 107 osif_priv->cm_info.last_id, 108 osif_priv->cm_info.last_source, 109 rsp->connect_status); 110 status = QDF_STATUS_E_INVAL; 111 goto rel_lock; 112 } 113 114 osif_cm_reset_id_and_src_no_lock(osif_priv); 115 rel_lock: 116 qdf_spinlock_release(&osif_priv->cm_info.cmd_id_lock); 117 118 return status; 119 } 120 121 static enum ieee80211_statuscode 122 osif_get_statuscode(enum wlan_status_code status) 123 { 124 return (enum ieee80211_statuscode)status; 125 } 126 127 static enum ieee80211_statuscode 128 osif_get_connect_status_code(struct wlan_cm_connect_resp *rsp) 129 { 130 enum ieee80211_statuscode status = WLAN_STATUS_SUCCESS; 131 132 if (QDF_IS_STATUS_ERROR(rsp->connect_status)) { 133 if (rsp->status_code) 134 status = osif_get_statuscode(rsp->status_code); 135 else 136 status = WLAN_STATUS_UNSPECIFIED_FAILURE; 137 } 138 139 return status; 140 } 141 142 /** 143 * osif_convert_timeout_reason() - Convert to kernel specific enum 144 * @timeout_reason: reason for connect timeout 145 * 146 * This function is used to convert host timeout 147 * reason enum to kernel specific enum. 148 * 149 * Context: Any context. 150 * Return: nl timeout enum 151 */ 152 153 static enum nl80211_timeout_reason 154 osif_convert_timeout_reason(enum wlan_cm_connect_fail_reason reason) 155 { 156 switch (reason) { 157 case CM_JOIN_TIMEOUT: 158 return NL80211_TIMEOUT_SCAN; 159 case CM_AUTH_TIMEOUT: 160 return NL80211_TIMEOUT_AUTH; 161 case CM_ASSOC_TIMEOUT: 162 return NL80211_TIMEOUT_ASSOC; 163 default: 164 return NL80211_TIMEOUT_UNSPECIFIED; 165 } 166 } 167 168 #if defined CFG80211_CONNECT_BSS || \ 169 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)) 170 171 #if defined CFG80211_CONNECT_TIMEOUT_REASON_CODE || \ 172 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) 173 /** 174 * osif_connect_timeout() - API to send connection timeout reason 175 * @dev: network device 176 * @bssid: bssid to which we want to associate 177 * @reason: reason for connect timeout 178 * 179 * This API is used to send connection timeout reason to supplicant 180 * 181 * Context: Any context. 182 * Return: Void 183 */ 184 static void 185 osif_connect_timeout(struct net_device *dev, const u8 *bssid, 186 enum wlan_cm_connect_fail_reason reason) 187 { 188 enum nl80211_timeout_reason nl_timeout_reason; 189 190 nl_timeout_reason = osif_convert_timeout_reason(reason); 191 192 osif_debug("nl_timeout_reason %d", nl_timeout_reason); 193 194 cfg80211_connect_timeout(dev, bssid, NULL, 0, qdf_mem_malloc_flags(), 195 nl_timeout_reason); 196 } 197 198 /** 199 * __osif_connect_bss() - API to send connection status to supplicant 200 * @dev: network device 201 * @bss: bss info 202 * @connect_rsp: Connection manager connect response 203 * 204 * Context: Any context. 205 * Return: void 206 */ 207 static void __osif_connect_bss(struct net_device *dev, 208 struct cfg80211_bss *bss, 209 struct wlan_cm_connect_resp *rsp, 210 enum ieee80211_statuscode status) 211 { 212 enum nl80211_timeout_reason nl_timeout_reason; 213 size_t req_len = 0; 214 const uint8_t *req_ptr = NULL; 215 size_t rsp_len = 0; 216 const uint8_t *rsp_ptr = NULL; 217 218 nl_timeout_reason = osif_convert_timeout_reason(rsp->reason); 219 220 osif_debug("nl_timeout_reason %d", nl_timeout_reason); 221 222 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 223 &req_len, &req_ptr); 224 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 225 &rsp_len, &rsp_ptr); 226 227 cfg80211_connect_bss(dev, rsp->bssid.bytes, bss, 228 req_ptr, req_len, rsp_ptr, rsp_len, status, 229 qdf_mem_malloc_flags(), nl_timeout_reason); 230 } 231 #else /* CFG80211_CONNECT_TIMEOUT_REASON_CODE */ 232 233 #if defined CFG80211_CONNECT_TIMEOUT || \ 234 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) 235 static void osif_connect_timeout( 236 struct net_device *dev, 237 const u8 *bssid, 238 enum wlan_cm_connect_fail_reason reason) 239 { 240 cfg80211_connect_timeout(dev, bssid, NULL, 0, qdf_mem_malloc_flags()); 241 } 242 #endif 243 244 static void __osif_connect_bss(struct net_device *dev, 245 struct cfg80211_bss *bss, 246 struct wlan_cm_connect_resp *rsp, 247 ieee80211_statuscode status) 248 { 249 size_t req_len = 0; 250 const uint8_t *req_ptr = NULL; 251 size_t rsp_len = 0; 252 const uint8_t *rsp_ptr = NULL; 253 254 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 255 &req_len, &req_ptr); 256 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 257 &rsp_len, &rsp_ptr); 258 259 cfg80211_connect_bss(dev, rsp->bssid.bytes, bss, 260 req_ptr, req_len, rsp_ptr, rsp_len, 261 status, qdf_mem_malloc_flags()); 262 } 263 #endif /* CFG80211_CONNECT_TIMEOUT_REASON_CODE */ 264 265 /** 266 * osif_connect_bss() - API to send connection status to supplicant 267 * @dev: network device 268 * @bss: bss info 269 * @connect_rsp: Connection manager connect response 270 * 271 * The API is a wrapper to send connection status to supplicant 272 * 273 * Context: Any context. 274 * Return: Void 275 */ 276 #if defined CFG80211_CONNECT_TIMEOUT || \ 277 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) 278 static void osif_connect_bss(struct net_device *dev, struct cfg80211_bss *bss, 279 struct wlan_cm_connect_resp *rsp) 280 { 281 enum ieee80211_statuscode status = WLAN_STATUS_SUCCESS; 282 283 osif_enter_dev(dev); 284 285 if (rsp->reason == CM_JOIN_TIMEOUT || 286 rsp->reason == CM_AUTH_TIMEOUT || 287 rsp->reason == CM_ASSOC_TIMEOUT) { 288 osif_connect_timeout(dev, rsp->bssid.bytes, 289 rsp->reason); 290 } else { 291 status = osif_get_connect_status_code(rsp); 292 293 __osif_connect_bss(dev, bss, rsp, status); 294 } 295 } 296 #else /* CFG80211_CONNECT_TIMEOUT */ 297 static void osif_connect_bss(struct net_device *dev, struct cfg80211_bss *bss, 298 struct wlan_cm_connect_resp *rsp) 299 { 300 enum ieee80211_statuscode status; 301 302 osif_enter_dev(dev); 303 304 status = osif_get_connect_status_code(rsp); 305 __osif_connect_bss(dev, bss, rsp, status); 306 } 307 #endif /* CFG80211_CONNECT_TIMEOUT */ 308 309 #if defined(CFG80211_CONNECT_DONE) || \ 310 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) 311 312 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)) 313 314 #if defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) 315 /** 316 * osif_populate_fils_params() - Populate FILS keys to connect response 317 * @conn_rsp_params: connect response to supplicant 318 * @connect_ies: Connect response IEs 319 * 320 * Context: Any context. 321 * Return: None 322 */ 323 static void 324 osif_populate_fils_params(struct cfg80211_connect_resp_params *rsp_params, 325 struct wlan_connect_rsp_ies *connect_ies) 326 { 327 if (!connect_ies->fils_ie) 328 return; 329 330 /* Increment seq number to be used for next FILS */ 331 rsp_params->fils_erp_next_seq_num = 332 connect_ies->fils_ie->fils_seq_num + 1; 333 rsp_params->update_erp_next_seq_num = true; 334 rsp_params->fils_kek = connect_ies->fils_ie->kek; 335 rsp_params->fils_kek_len = connect_ies->fils_ie->kek_len; 336 rsp_params->pmk = connect_ies->fils_ie->fils_pmk; 337 rsp_params->pmk_len = connect_ies->fils_ie->fils_pmk_len; 338 rsp_params->pmkid = connect_ies->fils_ie->fils_pmkid; 339 osif_debug("erp_next_seq_num:%d", rsp_params->fils_erp_next_seq_num); 340 } 341 #else /* CFG80211_FILS_SK_OFFLOAD_SUPPORT */ 342 static inline void 343 osif_populate_fils_params(struct cfg80211_connect_resp_params *rsp_params, 344 struct wlan_connect_rsp_ies *connect_ies) 345 { } 346 #endif /* CFG80211_FILS_SK_OFFLOAD_SUPPORT */ 347 348 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) 349 #if defined(WLAN_FEATURE_FILS_SK) 350 /** 351 * osif_populate_fils_params() - Populate FILS keys to connect response 352 * @conn_rsp_params: connect response to supplicant 353 * @connect_ies: Connect response IEs 354 * 355 * Context: Any context. 356 * Return: None 357 */ 358 static void 359 osif_populate_fils_params(struct cfg80211_connect_resp_params *rsp_params, 360 struct wlan_connect_rsp_ies *connect_ies) 361 362 { 363 if (!connect_ies->fils_ie) 364 return; 365 366 /* Increament seq number to be used for next FILS */ 367 rsp_params->fils.erp_next_seq_num = 368 connect_ies->fils_ie->fils_seq_num + 1; 369 rsp_params->fils.update_erp_next_seq_num = true; 370 rsp_params->fils.kek = connect_ies->fils_ie->kek; 371 rsp_params->fils.kek_len = connect_ies->fils_ie->kek_len; 372 rsp_params->fils.pmk = connect_ies->fils_ie->fils_pmk; 373 rsp_params->fils.pmk_len = connect_ies->fils_ie->fils_pmk_len; 374 rsp_params->fils.pmkid = connect_ies->fils_ie->fils_pmkid; 375 osif_debug("erp_next_seq_num:%d", rsp_params->fils.erp_next_seq_num); 376 } 377 #else /* WLAN_FEATURE_FILS_SK */ 378 static inline void 379 osif_populate_fils_params(struct cfg80211_connect_resp_params *rsp_params, 380 struct wlan_connect_rsp_ies *connect_ies) 381 { } 382 #endif /* WLAN_FEATURE_FILS_SK */ 383 #endif 384 385 #ifdef WLAN_FEATURE_11BE_MLO 386 QDF_STATUS 387 osif_get_partner_info_from_mlie(struct wlan_cm_connect_resp *connect_rsp, 388 struct mlo_partner_info *partner_info) 389 { 390 qdf_size_t connect_resp_len = 0, ml_ie_len = 0; 391 const uint8_t *connect_resp_ptr = NULL; 392 QDF_STATUS qdf_status; 393 uint8_t *ml_ie = NULL; 394 395 osif_cm_get_assoc_rsp_ie_data(&connect_rsp->connect_ies.assoc_rsp, 396 &connect_resp_len, &connect_resp_ptr); 397 398 if (!connect_resp_len) { 399 osif_err("Connect response is null return error"); 400 return QDF_STATUS_E_INVAL; 401 } 402 403 qdf_status = util_find_mlie((uint8_t *)connect_resp_ptr, 404 connect_resp_len, &ml_ie, &ml_ie_len); 405 if (QDF_IS_STATUS_ERROR(qdf_status) || !ml_ie) { 406 osif_debug("ML IE not found %d", qdf_status); 407 return qdf_status; 408 } 409 410 osif_debug("ML IE found length %d", (int)ml_ie_len); 411 412 qdf_status = util_get_bvmlie_persta_partner_info(ml_ie, ml_ie_len, 413 partner_info); 414 if (QDF_IS_STATUS_ERROR(qdf_status)) { 415 osif_err("Unable to find per-sta profile in ML IE"); 416 return qdf_status; 417 } 418 419 return qdf_status; 420 } 421 422 QDF_STATUS 423 osif_get_link_id_from_assoc_ml_ie(struct mlo_link_info *rsp_link_info, 424 struct mlo_partner_info *assoc_partner_info, 425 uint8_t *link_id) 426 { 427 int j; 428 429 for (j = 0; j < assoc_partner_info->num_partner_links; j++) { 430 if (!qdf_mem_cmp(rsp_link_info->link_addr.bytes, 431 assoc_partner_info->partner_link_info[j].link_addr.bytes, 432 QDF_MAC_ADDR_SIZE)) { 433 *link_id = assoc_partner_info->partner_link_info[j].link_id; 434 return QDF_STATUS_SUCCESS; 435 } 436 } 437 438 return QDF_STATUS_E_INVAL; 439 } 440 441 struct cfg80211_bss * 442 osif_get_chan_bss_from_kernel(struct wlan_objmgr_vdev *vdev, 443 struct mlo_link_info *rsp_link_info, 444 struct wlan_cm_connect_resp *rsp) 445 { 446 struct vdev_osif_priv *osif_priv; 447 struct cfg80211_bss *partner_bss; 448 struct ieee80211_channel *chan; 449 450 osif_priv = wlan_vdev_get_ospriv(vdev); 451 chan = ieee80211_get_channel(osif_priv->wdev->wiphy, 452 rsp_link_info->chan_freq); 453 if (!chan) { 454 osif_err("Invalid partner channel"); 455 return NULL; 456 } 457 458 partner_bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan, 459 rsp_link_info->link_addr.bytes, 460 rsp->ssid.ssid, rsp->ssid.length); 461 if (!partner_bss) { 462 osif_err("could not fetch partner bss from kernel"); 463 return NULL; 464 } 465 466 return partner_bss; 467 } 468 #endif 469 470 #if defined(CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT) && defined(WLAN_FEATURE_11BE_MLO) 471 #ifndef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 472 static struct wlan_objmgr_vdev *osif_get_partner_vdev(struct wlan_objmgr_vdev *vdev, 473 struct mlo_link_info rsp_partner_info) 474 { 475 return mlo_get_vdev_by_link_id(vdev, rsp_partner_info.link_id); 476 } 477 #endif 478 479 static 480 void osif_populate_connect_response_for_link(struct wlan_objmgr_vdev *vdev, 481 struct cfg80211_connect_resp_params *conn_rsp_params, 482 uint8_t link_id, 483 struct cfg80211_bss *bss) 484 { 485 osif_debug("Link_id :%d", link_id); 486 conn_rsp_params->valid_links |= BIT(link_id); 487 conn_rsp_params->links[link_id].bssid = bss->bssid; 488 conn_rsp_params->links[link_id].bss = bss; 489 conn_rsp_params->links[link_id].addr = 490 wlan_vdev_mlme_get_macaddr(vdev); 491 } 492 493 static QDF_STATUS 494 osif_fill_peer_mld_mac_connect_resp(struct wlan_objmgr_vdev *vdev, 495 struct wlan_cm_connect_resp *rsp, 496 struct cfg80211_connect_resp_params *conn_rsp_params) 497 { 498 struct wlan_objmgr_peer *peer_obj; 499 500 peer_obj = wlan_objmgr_get_peer_by_mac(wlan_vdev_get_psoc(vdev), 501 rsp->bssid.bytes, WLAN_OSIF_ID); 502 if (!peer_obj) 503 return QDF_STATUS_E_INVAL; 504 505 conn_rsp_params->ap_mld_addr = wlan_peer_mlme_get_mldaddr(peer_obj); 506 507 wlan_objmgr_peer_release_ref(peer_obj, WLAN_OSIF_ID); 508 509 return QDF_STATUS_SUCCESS; 510 } 511 512 static void 513 osif_populate_partner_links_mlo_params(struct wlan_objmgr_pdev *pdev, 514 struct wlan_cm_connect_resp *rsp, 515 struct cfg80211_connect_resp_params *conn_rsp_params) 516 { 517 struct wlan_objmgr_vdev *partner_vdev; 518 struct mlo_link_info *rsp_partner_info; 519 struct mlo_partner_info assoc_partner_info = {0}; 520 struct cfg80211_bss *bss = NULL; 521 QDF_STATUS qdf_status; 522 uint8_t link_id = 0, num_links; 523 int i; 524 525 qdf_status = osif_get_partner_info_from_mlie(rsp, &assoc_partner_info); 526 if (QDF_IS_STATUS_ERROR(qdf_status)) 527 return; 528 529 num_links = rsp->ml_parnter_info.num_partner_links; 530 for (i = 0 ; i < num_links; i++) { 531 rsp_partner_info = &rsp->ml_parnter_info.partner_link_info[i]; 532 533 qdf_status = osif_get_link_id_from_assoc_ml_ie(rsp_partner_info, 534 &assoc_partner_info, 535 &link_id); 536 if (QDF_IS_STATUS_ERROR(qdf_status)) 537 continue; 538 539 partner_vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, 540 rsp_partner_info->vdev_id, 541 WLAN_MLO_MGR_ID); 542 if (!partner_vdev) 543 continue; 544 545 bss = osif_get_chan_bss_from_kernel(partner_vdev, 546 rsp_partner_info, rsp); 547 if (!bss) { 548 wlan_objmgr_vdev_release_ref(partner_vdev, 549 WLAN_MLO_MGR_ID); 550 continue; 551 } 552 553 osif_populate_connect_response_for_link(partner_vdev, 554 conn_rsp_params, 555 link_id, bss); 556 wlan_objmgr_vdev_release_ref(partner_vdev, WLAN_MLO_MGR_ID); 557 } 558 } 559 560 static void osif_fill_connect_resp_mlo_params(struct wlan_objmgr_vdev *vdev, 561 struct wlan_cm_connect_resp *rsp, 562 struct cfg80211_bss *bss, 563 struct cfg80211_connect_resp_params *conn_rsp_params) 564 { 565 uint8_t assoc_link_id; 566 QDF_STATUS qdf_status; 567 568 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) 569 return; 570 571 qdf_status = osif_fill_peer_mld_mac_connect_resp(vdev, rsp, 572 conn_rsp_params); 573 if (QDF_IS_STATUS_ERROR(qdf_status)) { 574 osif_err("Unable to fill peer mld address: %d", qdf_status); 575 return; 576 } 577 578 assoc_link_id = wlan_vdev_get_link_id(vdev); 579 osif_populate_connect_response_for_link(vdev, conn_rsp_params, 580 assoc_link_id, bss); 581 582 osif_populate_partner_links_mlo_params(wlan_vdev_get_pdev(vdev), rsp, 583 conn_rsp_params); 584 } 585 586 static void 587 osif_free_ml_link_params(struct cfg80211_connect_resp_params *conn_rsp_params) 588 { 589 } 590 #elif defined(CFG80211_IFTYPE_MLO_LINK_SUPPORT) && defined(WLAN_FEATURE_11BE_MLO) 591 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 592 static struct wlan_objmgr_vdev *osif_get_partner_vdev( 593 struct wlan_objmgr_vdev *vdev, 594 struct mlo_link_info rsp_partner_info) 595 { 596 return wlan_objmgr_get_vdev_by_id_from_pdev( 597 vdev->vdev_objmgr.wlan_pdev, 598 rsp_partner_info.vdev_id, 599 WLAN_MLO_MGR_ID); 600 } 601 #else 602 static struct wlan_objmgr_vdev *osif_get_partner_vdev( 603 struct wlan_objmgr_vdev *vdev, 604 struct mlo_link_info rsp_partner_info) 605 { 606 return mlo_get_vdev_by_link_id(vdev, rsp_partner_info.link_id); 607 } 608 #endif 609 static void osif_fill_connect_resp_mlo_params( 610 struct wlan_objmgr_vdev *vdev, 611 struct wlan_cm_connect_resp *rsp, 612 struct cfg80211_bss *bss, 613 struct cfg80211_connect_resp_params *conn_rsp_params) 614 { 615 uint8_t i, num_mlo_links = rsp->ml_parnter_info.num_partner_links + 1; 616 struct wlan_objmgr_vdev *ml_vdev = vdev; 617 struct vdev_osif_priv *osif_priv; 618 struct ieee80211_channel *chan; 619 struct cfg80211_mlo_link_params *ml_link_params; 620 struct mlo_link_info *rsp_partner_info; 621 622 if (num_mlo_links == 1) 623 return; 624 625 ml_link_params = qdf_mem_malloc( 626 num_mlo_links * sizeof(*ml_link_params)); 627 if (!ml_link_params) 628 return; 629 630 rsp_partner_info = rsp->ml_parnter_info.partner_link_info; 631 if (rsp->ml_parnter_info.num_partner_links) { 632 conn_rsp_params->n_mlo_links = num_mlo_links; 633 osif_priv = wlan_vdev_get_ospriv(ml_vdev); 634 for (i = 0; i < conn_rsp_params->n_mlo_links; i++) { 635 ml_link_params[i].wdev = osif_priv->wdev; 636 637 if (i != 0) { 638 chan = ieee80211_get_channel( 639 osif_priv->wdev->wiphy, 640 rsp_partner_info[i - 1].chan_freq); 641 if (!chan) { 642 osif_err("Invalid partner channel"); 643 goto end; 644 } 645 646 bss = wlan_cfg80211_get_bss( 647 osif_priv->wdev->wiphy, chan, 648 rsp_partner_info[i - 1].link_addr.bytes, 649 rsp->ssid.ssid, rsp->ssid.length); 650 if (!bss) { 651 osif_err("Partner bss is null"); 652 goto end; 653 } 654 } 655 qdf_mem_copy(ml_link_params[i].bssid, bss->bssid, 656 QDF_MAC_ADDR_SIZE); 657 658 if (i == rsp->ml_parnter_info.num_partner_links) 659 break; 660 661 ml_vdev = osif_get_partner_vdev(vdev, 662 rsp_partner_info[i]); 663 664 if (ml_vdev) { 665 osif_priv = wlan_vdev_get_ospriv(ml_vdev); 666 wlan_objmgr_vdev_release_ref(ml_vdev, 667 WLAN_MLO_MGR_ID); 668 } else { 669 osif_err("Partner vdev not found with vdev_id:%d", 670 rsp_partner_info[i].vdev_id); 671 goto end; 672 } 673 } 674 } 675 end: 676 conn_rsp_params->mlo_links = ml_link_params; 677 } 678 679 static void 680 osif_free_ml_link_params(struct cfg80211_connect_resp_params *conn_rsp_params) 681 { 682 struct cfg80211_mlo_link_params *ml_links; 683 684 ml_links = 685 (struct cfg80211_mlo_link_params *)conn_rsp_params->mlo_links; 686 if (ml_links) 687 qdf_mem_free(ml_links); 688 } 689 690 #else 691 static void osif_fill_connect_resp_mlo_params( 692 struct wlan_objmgr_vdev *vdev, 693 struct wlan_cm_connect_resp *rsp, 694 struct cfg80211_bss *bss, 695 struct cfg80211_connect_resp_params *conn_rsp_params) 696 { 697 } 698 699 static void 700 osif_free_ml_link_params(struct cfg80211_connect_resp_params *conn_rsp_params) 701 { 702 } 703 #endif 704 705 #ifdef CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT 706 static 707 void osif_copy_connected_info(struct cfg80211_connect_resp_params *conn_rsp, 708 struct wlan_cm_connect_resp *rsp, 709 struct cfg80211_bss *bss, 710 struct wlan_objmgr_vdev *vdev) 711 { 712 if (wlan_vdev_mlme_is_mlo_vdev(vdev)) { 713 qdf_debug("MLO vdev fill everything in mlo fill params"); 714 return; 715 } 716 717 conn_rsp->links[0].bssid = rsp->bssid.bytes; 718 conn_rsp->links[0].bss = bss; 719 } 720 #else 721 static 722 void osif_copy_connected_info(struct cfg80211_connect_resp_params *conn_rsp, 723 struct wlan_cm_connect_resp *rsp, 724 struct cfg80211_bss *bss, 725 struct wlan_objmgr_vdev *vdev) 726 { 727 conn_rsp->bssid = rsp->bssid.bytes; 728 conn_rsp->bss = bss; 729 } 730 #endif 731 732 /** 733 * osif_connect_done() - Wrapper API to call cfg80211_connect_done 734 * @dev: network device 735 * @bss: bss info 736 * @rsp: Connection manager connect response 737 * @vdev: pointer to vdev 738 * 739 * This API is used as wrapper to send connect status and params to 740 * supplicant. 741 * 742 * Context: Any context. 743 * Return: 0 if success. Error code for failure 744 */ 745 static int osif_connect_done(struct net_device *dev, struct cfg80211_bss *bss, 746 struct wlan_cm_connect_resp *rsp, 747 struct wlan_objmgr_vdev *vdev) 748 { 749 struct cfg80211_connect_resp_params conn_rsp_params; 750 enum ieee80211_statuscode status; 751 752 osif_enter_dev(dev); 753 754 status = osif_get_connect_status_code(rsp); 755 qdf_mem_zero(&conn_rsp_params, sizeof(conn_rsp_params)); 756 757 conn_rsp_params.status = status; 758 osif_copy_connected_info(&conn_rsp_params, rsp, bss, vdev); 759 conn_rsp_params.timeout_reason = 760 osif_convert_timeout_reason(rsp->reason); 761 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 762 &conn_rsp_params.req_ie_len, 763 &conn_rsp_params.req_ie); 764 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 765 &conn_rsp_params.resp_ie_len, 766 &conn_rsp_params.resp_ie); 767 osif_populate_fils_params(&conn_rsp_params, &rsp->connect_ies); 768 osif_cm_save_gtk(vdev, rsp); 769 770 if (status == WLAN_STATUS_SUCCESS) 771 osif_fill_connect_resp_mlo_params(vdev, rsp, bss, 772 &conn_rsp_params); 773 774 osif_debug("Connect resp status %d", conn_rsp_params.status); 775 776 cfg80211_connect_done(dev, &conn_rsp_params, qdf_mem_malloc_flags()); 777 osif_cm_set_hlp_data(dev, vdev, rsp); 778 779 osif_free_ml_link_params(&conn_rsp_params); 780 781 return 0; 782 } 783 #else /* CFG80211_CONNECT_DONE */ 784 static inline int 785 osif_connect_done(struct net_device *dev, struct cfg80211_bss *bss, 786 struct wlan_cm_connect_resp *rsp, 787 struct wlan_objmgr_vdev *vdev) 788 { 789 return -EINVAL; 790 } 791 #endif 792 793 #if (defined(CFG80211_CONNECT_DONE) || \ 794 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))) 795 /** 796 * osif_update_connect_results() - API to send connection status to 797 * supplicant. 798 * @dev: network device 799 * @bss: bss info 800 * @connect_rsp: Connection manager connect response 801 * @vdev: pointer to vdev 802 * 803 * The API is a wrapper to send connection status to supplicant 804 * 805 * Context: Any context. 806 * Return: 0 if success else failure 807 */ 808 static int osif_update_connect_results(struct net_device *dev, 809 struct cfg80211_bss *bss, 810 struct wlan_cm_connect_resp *rsp, 811 struct wlan_objmgr_vdev *vdev) 812 { 813 return osif_connect_done(dev, bss, rsp, vdev); 814 } 815 #else /* CFG80211_CONNECT_DONE */ 816 817 static inline int osif_update_connect_results(struct net_device *dev, 818 struct cfg80211_bss *bss, 819 struct wlan_cm_connect_resp *rsp, 820 struct wlan_objmgr_vdev *vdev) 821 { 822 return -EINVAL; 823 } 824 #endif /* CFG80211_CONNECT_DONE */ 825 826 #ifdef WLAN_FEATURE_11BE_MLO 827 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 828 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 829 struct vdev_osif_priv *osif_priv, 830 struct wlan_cm_connect_resp *rsp) 831 { 832 struct cfg80211_bss *bss = NULL; 833 struct ieee80211_channel *chan; 834 835 if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) { 836 chan = ieee80211_get_channel(osif_priv->wdev->wiphy, 837 rsp->freq); 838 bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan, 839 rsp->bssid.bytes, 840 rsp->ssid.ssid, 841 rsp->ssid.length); 842 } 843 844 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) { 845 if (osif_update_connect_results(osif_priv->wdev->netdev, bss, 846 rsp, vdev)) 847 osif_connect_bss(osif_priv->wdev->netdev, bss, rsp); 848 return; 849 } 850 851 if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev)) { 852 if (osif_update_connect_results( 853 osif_priv->wdev->netdev, bss, 854 rsp, vdev)) 855 osif_connect_bss(osif_priv->wdev->netdev, 856 bss, rsp); 857 } 858 859 } 860 #else /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */ 861 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 862 struct vdev_osif_priv *osif_priv, 863 struct wlan_cm_connect_resp *rsp) 864 { 865 struct cfg80211_bss *bss = NULL; 866 struct ieee80211_channel *chan; 867 struct wlan_objmgr_vdev *assoc_vdev = NULL; 868 struct vdev_osif_priv *tmp_osif_priv = NULL; 869 qdf_freq_t freq; 870 struct qdf_mac_addr macaddr = {0}; 871 struct wlan_cm_connect_resp resp = {0}; 872 873 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) { 874 if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) { 875 chan = ieee80211_get_channel(osif_priv->wdev->wiphy, 876 rsp->freq); 877 bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, 878 chan, 879 rsp->bssid.bytes, 880 rsp->ssid.ssid, 881 rsp->ssid.length); 882 } 883 if (osif_update_connect_results(osif_priv->wdev->netdev, bss, 884 rsp, vdev)) 885 osif_connect_bss(osif_priv->wdev->netdev, bss, rsp); 886 return; 887 } 888 889 if ((QDF_IS_STATUS_SUCCESS(rsp->connect_status) && 890 ucfg_mlo_is_mld_connected(vdev)) || 891 (QDF_IS_STATUS_ERROR(rsp->connect_status) && 892 ucfg_mlo_is_mld_disconnected(vdev))) { 893 assoc_vdev = ucfg_mlo_get_assoc_link_vdev(vdev); 894 if (!assoc_vdev) 895 return; 896 qdf_mem_copy(&resp, rsp, sizeof(struct wlan_cm_connect_resp)); 897 tmp_osif_priv = wlan_vdev_get_ospriv(assoc_vdev); 898 freq = vdev->vdev_mlme.bss_chan->ch_freq; 899 wlan_vdev_get_bss_peer_mac(assoc_vdev, &macaddr); 900 if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) { 901 chan = ieee80211_get_channel(tmp_osif_priv->wdev->wiphy, 902 freq); 903 bss = wlan_cfg80211_get_bss(tmp_osif_priv->wdev->wiphy, 904 chan, 905 macaddr.bytes, 906 rsp->ssid.ssid, 907 rsp->ssid.length); 908 } 909 qdf_mem_copy(resp.bssid.bytes, macaddr.bytes, 910 QDF_MAC_ADDR_SIZE); 911 resp.freq = freq; 912 resp.connect_ies.assoc_req.ptr = rsp->connect_ies.assoc_req.ptr; 913 resp.connect_ies.assoc_req.len = rsp->connect_ies.assoc_req.len; 914 resp.connect_ies.assoc_rsp.ptr = rsp->connect_ies.assoc_rsp.ptr; 915 resp.connect_ies.assoc_rsp.len = rsp->connect_ies.assoc_rsp.len; 916 if (osif_update_connect_results(tmp_osif_priv->wdev->netdev, bss, 917 &resp, assoc_vdev)) 918 osif_connect_bss(tmp_osif_priv->wdev->netdev, bss, &resp); 919 } 920 } 921 #endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */ 922 #else /* WLAN_FEATURE_11BE_MLO */ 923 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 924 struct vdev_osif_priv *osif_priv, 925 struct wlan_cm_connect_resp *rsp) 926 { 927 struct cfg80211_bss *bss = NULL; 928 struct ieee80211_channel *chan; 929 930 if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) { 931 chan = ieee80211_get_channel(osif_priv->wdev->wiphy, 932 rsp->freq); 933 bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan, 934 rsp->bssid.bytes, 935 rsp->ssid.ssid, 936 rsp->ssid.length); 937 } 938 939 if (osif_update_connect_results(osif_priv->wdev->netdev, bss, 940 rsp, vdev)) 941 osif_connect_bss(osif_priv->wdev->netdev, bss, rsp); 942 } 943 #endif /* WLAN_FEATURE_11BE_MLO */ 944 #else /* CFG80211_CONNECT_BSS */ 945 #ifdef WLAN_FEATURE_11BE_MLO 946 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 947 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 948 struct vdev_osif_priv *osif_priv, 949 struct wlan_cm_connect_resp *rsp) 950 { 951 enum ieee80211_statuscode status; 952 size_t req_len = 0; 953 const uint8_t *req_ptr = NULL; 954 size_t rsp_len = 0; 955 const uint8_t *rsp_ptr = NULL; 956 struct wlan_objmgr_vdev *assoc_vdev = NULL; 957 struct vdev_osif_priv *tmp_osif_priv = NULL; 958 959 status = osif_get_connect_status_code(rsp); 960 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 961 &req_len, &req_ptr); 962 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 963 &rsp_len, &rsp_ptr); 964 if (wlan_vdev_mlme_is_mlo_vdev(vdev)) { 965 if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev)) 966 cfg80211_connect_result( 967 osif_priv->wdev->netdev, 968 rsp->bssid.bytes, req_ptr, req_len, 969 rsp_ptr, rsp_len, status, 970 qdf_mem_malloc_flags()); 971 } else { 972 cfg80211_connect_result(osif_priv->wdev->netdev, 973 rsp->bssid.bytes, req_ptr, req_len, 974 rsp_ptr, rsp_len, status, 975 qdf_mem_malloc_flags()); 976 } 977 } 978 #else /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */ 979 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 980 struct vdev_osif_priv *osif_priv, 981 struct wlan_cm_connect_resp *rsp) 982 { 983 enum ieee80211_statuscode status; 984 size_t req_len = 0; 985 const uint8_t *req_ptr = NULL; 986 size_t rsp_len = 0; 987 const uint8_t *rsp_ptr = NULL; 988 struct wlan_objmgr_vdev *assoc_vdev = NULL; 989 struct vdev_osif_priv *tmp_osif_priv = NULL; 990 struct qdf_mac_addr macaddr = {0}; 991 992 status = osif_get_connect_status_code(rsp); 993 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 994 &req_len, &req_ptr); 995 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 996 &rsp_len, &rsp_ptr); 997 if (wlan_vdev_mlme_is_mlo_vdev(vdev)) { 998 if ((QDF_IS_STATUS_SUCCESS(rsp->connect_status) && 999 ucfg_mlo_is_mld_connected(vdev)) || 1000 (QDF_IS_STATUS_ERROR(rsp->connect_status) && 1001 ucfg_mlo_is_mld_disconnected(vdev))) { 1002 assoc_vdev = ucfg_mlo_get_assoc_link_vdev(vdev); 1003 if (!assoc_vdev) 1004 return; 1005 tmp_osif_priv = wlan_vdev_get_ospriv(assoc_vdev); 1006 wlan_vdev_get_bss_peer_mac(assoc_vdev, &macaddr); 1007 cfg80211_connect_result(tmp_osif_priv->wdev->netdev, 1008 macaddr.bytes, req_ptr, 1009 req_len, rsp_ptr, rsp_len, 1010 status, qdf_mem_malloc_flags()); 1011 } 1012 } else { 1013 cfg80211_connect_result(osif_priv->wdev->netdev, 1014 rsp->bssid.bytes, req_ptr, req_len, 1015 rsp_ptr, rsp_len, status, 1016 qdf_mem_malloc_flags()); 1017 } 1018 } 1019 #endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */ 1020 #else /* WLAN_FEATURE_11BE_MLO */ 1021 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 1022 struct vdev_osif_priv *osif_priv, 1023 struct wlan_cm_connect_resp *rsp) 1024 { 1025 enum ieee80211_statuscode status; 1026 size_t req_len = 0; 1027 const uint8_t *req_ptr = NULL; 1028 size_t rsp_len = 0; 1029 const uint8_t *rsp_ptr = NULL; 1030 1031 status = osif_get_connect_status_code(rsp); 1032 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 1033 &req_len, &req_ptr); 1034 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 1035 &rsp_len, &rsp_ptr); 1036 cfg80211_connect_result(osif_priv->wdev->netdev, 1037 rsp->bssid.bytes, req_ptr, req_len, 1038 rsp_ptr, rsp_len, status, 1039 qdf_mem_malloc_flags()); 1040 } 1041 #endif /* WLAN_FEATURE_11BE_MLO */ 1042 #endif /* CFG80211_CONNECT_BSS */ 1043 1044 #ifdef CONN_MGR_ADV_FEATURE 1045 static inline 1046 bool osif_cm_is_unlink_bss_required(struct wlan_cm_connect_resp *rsp) 1047 { 1048 if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) 1049 return false; 1050 1051 if (rsp->reason == CM_NO_CANDIDATE_FOUND || 1052 rsp->reason == CM_JOIN_TIMEOUT || 1053 rsp->reason == CM_AUTH_TIMEOUT || 1054 rsp->reason == CM_ASSOC_TIMEOUT) 1055 return true; 1056 1057 return false; 1058 } 1059 static inline void osif_check_and_unlink_bss(struct wlan_objmgr_vdev *vdev, 1060 struct vdev_osif_priv *osif_priv, 1061 struct wlan_cm_connect_resp *rsp) 1062 { 1063 if (osif_cm_is_unlink_bss_required(rsp)) 1064 osif_cm_unlink_bss(vdev, osif_priv, &rsp->bssid, rsp->ssid.ssid, 1065 rsp->ssid.length); 1066 } 1067 #else 1068 static inline void osif_check_and_unlink_bss(struct wlan_objmgr_vdev *vdev, 1069 struct vdev_osif_priv *osif_priv, 1070 struct wlan_cm_connect_resp *rsp) 1071 {} 1072 #endif 1073 1074 QDF_STATUS osif_connect_handler(struct wlan_objmgr_vdev *vdev, 1075 struct wlan_cm_connect_resp *rsp) 1076 { 1077 struct vdev_osif_priv *osif_priv = wlan_vdev_get_ospriv(vdev); 1078 QDF_STATUS status; 1079 1080 osif_nofl_info("%s(vdevid-%d): " QDF_MAC_ADDR_FMT " Connect with " QDF_MAC_ADDR_FMT " SSID \"%.*s\" is %s cm_id 0x%x cm_reason %d status_code %d is_reassoc %d send discon %d", 1081 osif_priv->wdev->netdev->name, rsp->vdev_id, 1082 QDF_MAC_ADDR_REF(wlan_vdev_mlme_get_macaddr(vdev)), 1083 QDF_MAC_ADDR_REF(rsp->bssid.bytes), 1084 rsp->ssid.length, rsp->ssid.ssid, 1085 rsp->connect_status ? "FAILURE" : "SUCCESS", rsp->cm_id, 1086 rsp->reason, rsp->status_code, rsp->is_reassoc, 1087 rsp->send_disconnect); 1088 1089 osif_check_and_unlink_bss(vdev, osif_priv, rsp); 1090 1091 status = osif_validate_connect_and_reset_src_id(osif_priv, rsp); 1092 if (QDF_IS_STATUS_ERROR(status)) { 1093 osif_cm_connect_comp_ind(vdev, rsp, OSIF_NOT_HANDLED); 1094 return status; 1095 } 1096 1097 osif_cm_connect_comp_ind(vdev, rsp, OSIF_PRE_USERSPACE_UPDATE); 1098 1099 /* 1100 * To fix issue that scan with random address failed since wdev keeps 1101 * connected, rsp->send_disconnect is added. 1102 * Reproduce steps: 1103 * 1. Connect from OSIF success, wdev->connected = true; 1104 * 2. Disconnect from target if and reassoc from OSIF happens back to 1105 * back. 1106 * 3. Disconnect event is not sent to kernel, wdev->connected keeps 1107 * true, isn't cleared. 1108 * 4. Connect from OSIF failed too, wdev->connected keeps true, isn't 1109 * cleared. 1110 * 5. Scan with random address failed since wdev->connected is true. 1111 * 1112 * To fix it, if connect req was a reassoc req and received in not 1113 * connected state for race between disconnect from target if and 1114 * reassoc connect from OSIF, set reassoc_in_non_connected to send 1115 * disconnect instead of connect rsp to kernel to cleanup kernel flags 1116 * like: wdev->connected. 1117 */ 1118 if (rsp->is_reassoc) 1119 osif_indicate_reassoc_results(vdev, osif_priv, rsp); 1120 else if (rsp->send_disconnect && 1121 QDF_IS_STATUS_ERROR(rsp->connect_status)) 1122 osif_cm_indicate_disconnect(vdev, osif_priv->wdev->netdev, 1123 WLAN_REASON_UNSPECIFIED, 1124 false, NULL, 0, 1125 qdf_mem_malloc_flags()); 1126 else 1127 osif_indcate_connect_results(vdev, osif_priv, rsp); 1128 osif_cm_connect_comp_ind(vdev, rsp, OSIF_POST_USERSPACE_UPDATE); 1129 1130 return QDF_STATUS_SUCCESS; 1131 } 1132 1133 QDF_STATUS osif_failed_candidate_handler(struct wlan_objmgr_vdev *vdev, 1134 struct wlan_cm_connect_resp *rsp) 1135 { 1136 struct vdev_osif_priv *osif_priv = wlan_vdev_get_ospriv(vdev); 1137 1138 osif_nofl_info("%s(vdevid-%d): " QDF_MAC_ADDR_FMT " Connect with " QDF_MAC_ADDR_FMT " SSID \"%.*s\" FAILED cm_id 0x%x cm_reason %d reason_code %d", 1139 osif_priv->wdev->netdev->name, rsp->vdev_id, 1140 QDF_MAC_ADDR_REF(wlan_vdev_mlme_get_macaddr(vdev)), 1141 QDF_MAC_ADDR_REF(rsp->bssid.bytes), 1142 rsp->ssid.length, rsp->ssid.ssid, rsp->cm_id, 1143 rsp->reason, rsp->status_code); 1144 1145 /** 1146 * Do not unlink the BSS if it is an ML candidate. In case of ML, 1147 * failed candidate may be used as partner link while trying the 1148 * connection on other links. 1149 */ 1150 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) 1151 osif_check_and_unlink_bss(vdev, osif_priv, rsp); 1152 1153 return QDF_STATUS_SUCCESS; 1154 } 1155