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