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 #include <wlan_mlo_mgr_link_switch.h> 38 39 #ifdef CONN_MGR_ADV_FEATURE 40 void osif_cm_get_assoc_req_ie_data(struct element_info *assoc_req, 41 size_t *ie_data_len, 42 const uint8_t **ie_data_ptr) 43 { 44 /* Validate IE and length */ 45 if (!assoc_req->len || !assoc_req->ptr || 46 assoc_req->len <= WLAN_ASSOC_REQ_IES_OFFSET) 47 return; 48 49 *ie_data_len = assoc_req->len - WLAN_ASSOC_REQ_IES_OFFSET; 50 *ie_data_ptr = assoc_req->ptr + WLAN_ASSOC_REQ_IES_OFFSET; 51 } 52 #else 53 void osif_cm_get_assoc_req_ie_data(struct element_info *assoc_req, 54 size_t *ie_data_len, 55 const uint8_t **ie_data_ptr) 56 { 57 /* Validate IE and length */ 58 if (!assoc_req->len || !assoc_req->ptr) 59 return; 60 61 *ie_data_len = assoc_req->len; 62 *ie_data_ptr = assoc_req->ptr; 63 } 64 #endif 65 66 void osif_cm_get_assoc_rsp_ie_data(struct element_info *assoc_rsp, 67 size_t *ie_data_len, 68 const uint8_t **ie_data_ptr) 69 { 70 /* Validate IE and length */ 71 if (!assoc_rsp->len || !assoc_rsp->ptr || 72 assoc_rsp->len <= WLAN_ASSOC_RSP_IES_OFFSET) 73 return; 74 75 *ie_data_len = assoc_rsp->len - WLAN_ASSOC_RSP_IES_OFFSET; 76 *ie_data_ptr = assoc_rsp->ptr + WLAN_ASSOC_RSP_IES_OFFSET; 77 } 78 79 /** 80 * osif_validate_connect_and_reset_src_id() - Validate connect response and 81 * resets source and id 82 * @osif_priv: Pointer to vdev osif priv 83 * @rsp: Connection manager connect response 84 * 85 * This function validates connect response and if the connect 86 * response is valid, resets the source and id of the command 87 * 88 * Context: Any context. Takes and releases cmd id spinlock. 89 * Return: QDF_STATUS 90 */ 91 static QDF_STATUS 92 osif_validate_connect_and_reset_src_id(struct vdev_osif_priv *osif_priv, 93 struct wlan_cm_connect_resp *rsp) 94 { 95 QDF_STATUS status = QDF_STATUS_SUCCESS; 96 97 /* 98 * Do not send to kernel if last osif cookie doesn't match or 99 * or source is CM_OSIF_CFG_CONNECT with success status. 100 * If cookie matches reset the cookie and source. 101 */ 102 qdf_spinlock_acquire(&osif_priv->cm_info.cmd_id_lock); 103 if (rsp->cm_id != osif_priv->cm_info.last_id || 104 (osif_priv->cm_info.last_source == CM_OSIF_CFG_CONNECT && 105 QDF_IS_STATUS_SUCCESS(rsp->connect_status))) { 106 osif_debug("Ignore as cm_id(0x%x)/src(%d) != cm_id(0x%x)/src(%d) OR source is CFG connect with status %d", 107 rsp->cm_id, CM_OSIF_CONNECT, 108 osif_priv->cm_info.last_id, 109 osif_priv->cm_info.last_source, 110 rsp->connect_status); 111 status = QDF_STATUS_E_INVAL; 112 goto rel_lock; 113 } 114 115 osif_cm_reset_id_and_src_no_lock(osif_priv); 116 rel_lock: 117 qdf_spinlock_release(&osif_priv->cm_info.cmd_id_lock); 118 119 return status; 120 } 121 122 static enum ieee80211_statuscode 123 osif_get_statuscode(enum wlan_status_code status) 124 { 125 return (enum ieee80211_statuscode)status; 126 } 127 128 static enum ieee80211_statuscode 129 osif_get_connect_status_code(struct wlan_cm_connect_resp *rsp) 130 { 131 enum ieee80211_statuscode status = WLAN_STATUS_SUCCESS; 132 133 if (QDF_IS_STATUS_ERROR(rsp->connect_status)) { 134 if (rsp->status_code) 135 status = osif_get_statuscode(rsp->status_code); 136 else 137 status = WLAN_STATUS_UNSPECIFIED_FAILURE; 138 } 139 140 return status; 141 } 142 143 /** 144 * osif_convert_timeout_reason() - Convert to kernel specific enum 145 * @reason: reason for connect timeout 146 * 147 * This function is used to convert host timeout 148 * reason enum to kernel specific enum. 149 * 150 * Context: Any context. 151 * Return: nl timeout enum 152 */ 153 154 static enum nl80211_timeout_reason 155 osif_convert_timeout_reason(enum wlan_cm_connect_fail_reason reason) 156 { 157 switch (reason) { 158 case CM_JOIN_TIMEOUT: 159 return NL80211_TIMEOUT_SCAN; 160 case CM_AUTH_TIMEOUT: 161 return NL80211_TIMEOUT_AUTH; 162 case CM_ASSOC_TIMEOUT: 163 return NL80211_TIMEOUT_ASSOC; 164 default: 165 return NL80211_TIMEOUT_UNSPECIFIED; 166 } 167 } 168 169 #if defined CFG80211_CONNECT_BSS || \ 170 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)) 171 172 #if defined CFG80211_CONNECT_TIMEOUT_REASON_CODE || \ 173 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) 174 /** 175 * osif_connect_timeout() - API to send connection timeout reason 176 * @dev: network device 177 * @bssid: bssid to which we want to associate 178 * @reason: reason for connect timeout 179 * 180 * This API is used to send connection timeout reason to supplicant 181 * 182 * Context: Any context. 183 * Return: Void 184 */ 185 static void 186 osif_connect_timeout(struct net_device *dev, const u8 *bssid, 187 enum wlan_cm_connect_fail_reason reason) 188 { 189 enum nl80211_timeout_reason nl_timeout_reason; 190 191 nl_timeout_reason = osif_convert_timeout_reason(reason); 192 193 osif_debug("nl_timeout_reason %d", nl_timeout_reason); 194 195 cfg80211_connect_timeout(dev, bssid, NULL, 0, qdf_mem_malloc_flags(), 196 nl_timeout_reason); 197 } 198 199 /** 200 * __osif_connect_bss() - API to send connection status to supplicant 201 * @dev: network device 202 * @bss: bss info 203 * @rsp: Connection manager connect response 204 * @status: 802.11 status code 205 * 206 * Context: Any context. 207 * Return: void 208 */ 209 static void __osif_connect_bss(struct net_device *dev, 210 struct cfg80211_bss *bss, 211 struct wlan_cm_connect_resp *rsp, 212 enum ieee80211_statuscode status) 213 { 214 enum nl80211_timeout_reason nl_timeout_reason; 215 size_t req_len = 0; 216 const uint8_t *req_ptr = NULL; 217 size_t rsp_len = 0; 218 const uint8_t *rsp_ptr = NULL; 219 220 nl_timeout_reason = osif_convert_timeout_reason(rsp->reason); 221 222 osif_debug("nl_timeout_reason %d", nl_timeout_reason); 223 224 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 225 &req_len, &req_ptr); 226 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 227 &rsp_len, &rsp_ptr); 228 229 cfg80211_connect_bss(dev, rsp->bssid.bytes, bss, 230 req_ptr, req_len, rsp_ptr, rsp_len, status, 231 qdf_mem_malloc_flags(), nl_timeout_reason); 232 } 233 #else /* CFG80211_CONNECT_TIMEOUT_REASON_CODE */ 234 235 #if defined CFG80211_CONNECT_TIMEOUT || \ 236 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) 237 static void osif_connect_timeout( 238 struct net_device *dev, 239 const u8 *bssid, 240 enum wlan_cm_connect_fail_reason reason) 241 { 242 cfg80211_connect_timeout(dev, bssid, NULL, 0, qdf_mem_malloc_flags()); 243 } 244 #endif 245 246 static void __osif_connect_bss(struct net_device *dev, 247 struct cfg80211_bss *bss, 248 struct wlan_cm_connect_resp *rsp, 249 ieee80211_statuscode status) 250 { 251 size_t req_len = 0; 252 const uint8_t *req_ptr = NULL; 253 size_t rsp_len = 0; 254 const uint8_t *rsp_ptr = NULL; 255 256 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 257 &req_len, &req_ptr); 258 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 259 &rsp_len, &rsp_ptr); 260 261 cfg80211_connect_bss(dev, rsp->bssid.bytes, bss, 262 req_ptr, req_len, rsp_ptr, rsp_len, 263 status, qdf_mem_malloc_flags()); 264 } 265 #endif /* CFG80211_CONNECT_TIMEOUT_REASON_CODE */ 266 267 /** 268 * osif_connect_bss() - API to send connection status to supplicant 269 * @dev: network device 270 * @bss: bss info 271 * @rsp: Connection manager connect response 272 * 273 * The API is a wrapper to send connection status to supplicant 274 * 275 * Context: Any context. 276 * Return: Void 277 */ 278 #if defined CFG80211_CONNECT_TIMEOUT || \ 279 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) 280 static void osif_connect_bss(struct net_device *dev, struct cfg80211_bss *bss, 281 struct wlan_cm_connect_resp *rsp) 282 { 283 enum ieee80211_statuscode status = WLAN_STATUS_SUCCESS; 284 285 osif_enter_dev(dev); 286 287 if (rsp->reason == CM_JOIN_TIMEOUT || 288 rsp->reason == CM_AUTH_TIMEOUT || 289 rsp->reason == CM_ASSOC_TIMEOUT) { 290 osif_connect_timeout(dev, rsp->bssid.bytes, 291 rsp->reason); 292 } else { 293 status = osif_get_connect_status_code(rsp); 294 295 __osif_connect_bss(dev, bss, rsp, status); 296 } 297 } 298 #else /* CFG80211_CONNECT_TIMEOUT */ 299 static void osif_connect_bss(struct net_device *dev, struct cfg80211_bss *bss, 300 struct wlan_cm_connect_resp *rsp) 301 { 302 enum ieee80211_statuscode status; 303 304 osif_enter_dev(dev); 305 306 status = osif_get_connect_status_code(rsp); 307 __osif_connect_bss(dev, bss, rsp, status); 308 } 309 #endif /* CFG80211_CONNECT_TIMEOUT */ 310 311 #if defined(CFG80211_CONNECT_DONE) || \ 312 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) 313 314 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)) 315 316 #if defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) 317 /** 318 * osif_populate_fils_params() - Populate FILS keys to connect response 319 * @rsp_params: connect response to supplicant 320 * @connect_ies: Connect response IEs 321 * 322 * Context: Any context. 323 * Return: None 324 */ 325 static void 326 osif_populate_fils_params(struct cfg80211_connect_resp_params *rsp_params, 327 struct wlan_connect_rsp_ies *connect_ies) 328 { 329 if (!connect_ies->fils_ie) 330 return; 331 332 /* Increment seq number to be used for next FILS */ 333 rsp_params->fils_erp_next_seq_num = 334 connect_ies->fils_ie->fils_seq_num + 1; 335 rsp_params->update_erp_next_seq_num = true; 336 rsp_params->fils_kek = connect_ies->fils_ie->kek; 337 rsp_params->fils_kek_len = connect_ies->fils_ie->kek_len; 338 rsp_params->pmk = connect_ies->fils_ie->fils_pmk; 339 rsp_params->pmk_len = connect_ies->fils_ie->fils_pmk_len; 340 rsp_params->pmkid = connect_ies->fils_ie->fils_pmkid; 341 osif_debug("erp_next_seq_num:%d", rsp_params->fils_erp_next_seq_num); 342 } 343 #else /* CFG80211_FILS_SK_OFFLOAD_SUPPORT */ 344 static inline void 345 osif_populate_fils_params(struct cfg80211_connect_resp_params *rsp_params, 346 struct wlan_connect_rsp_ies *connect_ies) 347 { } 348 #endif /* CFG80211_FILS_SK_OFFLOAD_SUPPORT */ 349 350 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) 351 #if defined(WLAN_FEATURE_FILS_SK) 352 /** 353 * osif_populate_fils_params() - Populate FILS keys to connect response 354 * @rsp_params: connect response to supplicant 355 * @connect_ies: Connect response IEs 356 * 357 * Context: Any context. 358 * Return: None 359 */ 360 static void 361 osif_populate_fils_params(struct cfg80211_connect_resp_params *rsp_params, 362 struct wlan_connect_rsp_ies *connect_ies) 363 364 { 365 if (!connect_ies->fils_ie) 366 return; 367 368 /* Increment seq number to be used for next FILS */ 369 rsp_params->fils.erp_next_seq_num = 370 connect_ies->fils_ie->fils_seq_num + 1; 371 rsp_params->fils.update_erp_next_seq_num = true; 372 rsp_params->fils.kek = connect_ies->fils_ie->kek; 373 rsp_params->fils.kek_len = connect_ies->fils_ie->kek_len; 374 rsp_params->fils.pmk = connect_ies->fils_ie->fils_pmk; 375 rsp_params->fils.pmk_len = connect_ies->fils_ie->fils_pmk_len; 376 rsp_params->fils.pmkid = connect_ies->fils_ie->fils_pmkid; 377 osif_debug("erp_next_seq_num:%d", rsp_params->fils.erp_next_seq_num); 378 } 379 #else /* WLAN_FEATURE_FILS_SK */ 380 static inline void 381 osif_populate_fils_params(struct cfg80211_connect_resp_params *rsp_params, 382 struct wlan_connect_rsp_ies *connect_ies) 383 { } 384 #endif /* WLAN_FEATURE_FILS_SK */ 385 #endif 386 387 #ifdef WLAN_FEATURE_11BE_MLO 388 QDF_STATUS 389 osif_get_partner_info_from_mlie(struct wlan_cm_connect_resp *connect_rsp, 390 struct mlo_partner_info *partner_info) 391 { 392 qdf_size_t connect_resp_len = 0, ml_ie_len = 0; 393 const uint8_t *connect_resp_ptr = NULL; 394 QDF_STATUS qdf_status; 395 uint8_t *ml_ie = NULL; 396 397 osif_cm_get_assoc_rsp_ie_data(&connect_rsp->connect_ies.assoc_rsp, 398 &connect_resp_len, &connect_resp_ptr); 399 400 if (!connect_resp_len) { 401 osif_err("Connect response is null return error"); 402 return QDF_STATUS_E_INVAL; 403 } 404 405 qdf_status = util_find_mlie((uint8_t *)connect_resp_ptr, 406 connect_resp_len, &ml_ie, &ml_ie_len); 407 if (QDF_IS_STATUS_ERROR(qdf_status) || !ml_ie) { 408 osif_debug("ML IE not found %d", qdf_status); 409 return qdf_status; 410 } 411 412 osif_debug("ML IE found length %d", (int)ml_ie_len); 413 414 qdf_status = util_get_bvmlie_persta_partner_info(ml_ie, ml_ie_len, 415 partner_info); 416 if (QDF_IS_STATUS_ERROR(qdf_status)) { 417 osif_err("Unable to find per-sta profile in ML IE"); 418 return qdf_status; 419 } 420 421 return qdf_status; 422 } 423 424 QDF_STATUS 425 osif_get_link_id_from_assoc_ml_ie(struct mlo_link_info *rsp_link_info, 426 struct mlo_partner_info *assoc_partner_info, 427 uint8_t *link_id) 428 { 429 int j; 430 431 for (j = 0; j < assoc_partner_info->num_partner_links; j++) { 432 if (!qdf_mem_cmp(rsp_link_info->link_addr.bytes, 433 assoc_partner_info->partner_link_info[j].link_addr.bytes, 434 QDF_MAC_ADDR_SIZE)) { 435 *link_id = assoc_partner_info->partner_link_info[j].link_id; 436 return QDF_STATUS_SUCCESS; 437 } 438 } 439 440 return QDF_STATUS_E_INVAL; 441 } 442 443 struct cfg80211_bss * 444 osif_get_chan_bss_from_kernel(struct wlan_objmgr_vdev *vdev, 445 struct mlo_link_info *rsp_link_info, 446 struct wlan_cm_connect_resp *rsp) 447 { 448 struct vdev_osif_priv *osif_priv; 449 struct cfg80211_bss *partner_bss; 450 struct ieee80211_channel *chan; 451 452 osif_priv = wlan_vdev_get_ospriv(vdev); 453 chan = ieee80211_get_channel(osif_priv->wdev->wiphy, 454 rsp_link_info->chan_freq); 455 if (!chan) { 456 osif_err("Invalid partner channel"); 457 return NULL; 458 } 459 460 partner_bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan, 461 rsp_link_info->link_addr.bytes, 462 rsp->ssid.ssid, rsp->ssid.length); 463 if (!partner_bss) { 464 osif_err("could not fetch partner bss from kernel"); 465 return NULL; 466 } 467 468 return partner_bss; 469 } 470 #endif 471 472 #if defined(CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT) && defined(WLAN_FEATURE_11BE_MLO) 473 #ifndef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 474 static struct wlan_objmgr_vdev *osif_get_partner_vdev( 475 struct wlan_objmgr_vdev *vdev, 476 struct mlo_link_info rsp_partner_info, 477 wlan_objmgr_ref_dbgid id) 478 { 479 return mlo_get_vdev_by_link_id(vdev, rsp_partner_info.link_id, id); 480 } 481 #endif 482 483 static 484 void osif_populate_connect_response_for_link(struct wlan_objmgr_vdev *vdev, 485 struct cfg80211_connect_resp_params *conn_rsp_params, 486 uint8_t link_id, 487 uint8_t *link_addr, 488 struct cfg80211_bss *bss) 489 { 490 osif_debug("Link_id :%d", link_id); 491 conn_rsp_params->valid_links |= BIT(link_id); 492 conn_rsp_params->links[link_id].bssid = bss->bssid; 493 conn_rsp_params->links[link_id].bss = bss; 494 conn_rsp_params->links[link_id].addr = link_addr; 495 mlo_mgr_osif_update_connect_info(vdev, link_id); 496 } 497 498 static QDF_STATUS 499 osif_fill_peer_mld_mac_connect_resp(struct wlan_objmgr_vdev *vdev, 500 struct wlan_cm_connect_resp *rsp, 501 struct cfg80211_connect_resp_params *conn_rsp_params) 502 { 503 struct wlan_objmgr_peer *peer_obj; 504 struct wlan_objmgr_psoc *psoc; 505 506 psoc = wlan_vdev_get_psoc(vdev); 507 if (!psoc) 508 return QDF_STATUS_E_INVAL; 509 510 peer_obj = wlan_objmgr_get_peer_by_mac(psoc, rsp->bssid.bytes, 511 WLAN_OSIF_ID); 512 if (!peer_obj) 513 return QDF_STATUS_E_INVAL; 514 515 conn_rsp_params->ap_mld_addr = wlan_peer_mlme_get_mldaddr(peer_obj); 516 517 wlan_objmgr_peer_release_ref(peer_obj, WLAN_OSIF_ID); 518 519 return QDF_STATUS_SUCCESS; 520 } 521 522 static void 523 osif_populate_partner_links_mlo_params(struct wlan_objmgr_vdev *vdev, 524 struct wlan_cm_connect_resp *rsp, 525 struct cfg80211_connect_resp_params *conn_rsp_params) 526 { 527 struct mlo_link_info *rsp_partner_info; 528 struct cfg80211_bss *bss = NULL; 529 uint8_t link_id = 0, num_links; 530 int i; 531 struct mlo_link_info *link_info; 532 533 num_links = rsp->ml_parnter_info.num_partner_links; 534 for (i = 0 ; i < num_links; i++) { 535 rsp_partner_info = &rsp->ml_parnter_info.partner_link_info[i]; 536 link_id = rsp_partner_info->link_id; 537 538 link_info = mlo_mgr_get_ap_link_by_link_id(vdev->mlo_dev_ctx, 539 link_id); 540 if (!link_info) 541 continue; 542 543 bss = osif_get_chan_bss_from_kernel(vdev, rsp_partner_info, 544 rsp); 545 if (!bss) 546 continue; 547 548 osif_populate_connect_response_for_link(vdev, conn_rsp_params, 549 link_id, 550 link_info->link_addr.bytes, 551 bss); 552 } 553 } 554 555 static void osif_fill_connect_resp_mlo_params(struct wlan_objmgr_vdev *vdev, 556 struct wlan_cm_connect_resp *rsp, 557 struct cfg80211_bss *bss, 558 struct cfg80211_connect_resp_params *conn_rsp_params) 559 { 560 uint8_t assoc_link_id; 561 QDF_STATUS qdf_status; 562 struct mlo_link_info *link_info = NULL; 563 564 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) 565 return; 566 567 qdf_status = osif_fill_peer_mld_mac_connect_resp(vdev, rsp, 568 conn_rsp_params); 569 if (QDF_IS_STATUS_ERROR(qdf_status)) { 570 osif_err("Unable to fill peer mld address: %d", qdf_status); 571 return; 572 } 573 574 assoc_link_id = wlan_vdev_get_link_id(vdev); 575 link_info = mlo_mgr_get_ap_link_by_link_id(vdev->mlo_dev_ctx, 576 assoc_link_id); 577 if (!link_info) { 578 osif_err("Unable to find link_info for link_id: %d", 579 assoc_link_id); 580 return; 581 } 582 583 osif_populate_connect_response_for_link(vdev, conn_rsp_params, 584 assoc_link_id, 585 link_info->link_addr.bytes, 586 bss); 587 osif_populate_partner_links_mlo_params(vdev, rsp, conn_rsp_params); 588 } 589 590 static void 591 osif_free_ml_link_params(struct cfg80211_connect_resp_params *conn_rsp_params) 592 { 593 } 594 #elif defined(CFG80211_IFTYPE_MLO_LINK_SUPPORT) && defined(WLAN_FEATURE_11BE_MLO) 595 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 596 static struct wlan_objmgr_vdev *osif_get_partner_vdev( 597 struct wlan_objmgr_vdev *vdev, 598 struct mlo_link_info rsp_partner_info, 599 wlan_objmgr_ref_dbgid id) 600 { 601 return wlan_objmgr_get_vdev_by_id_from_pdev( 602 vdev->vdev_objmgr.wlan_pdev, 603 rsp_partner_info.vdev_id, id); 604 } 605 #else 606 static struct wlan_objmgr_vdev *osif_get_partner_vdev( 607 struct wlan_objmgr_vdev *vdev, 608 struct mlo_link_info rsp_partner_info, 609 wlan_objmgr_ref_dbgid id) 610 { 611 return mlo_get_vdev_by_link_id(vdev, rsp_partner_info.link_id, id); 612 } 613 #endif 614 static void osif_fill_connect_resp_mlo_params( 615 struct wlan_objmgr_vdev *vdev, 616 struct wlan_cm_connect_resp *rsp, 617 struct cfg80211_bss *bss, 618 struct cfg80211_connect_resp_params *conn_rsp_params) 619 { 620 uint8_t i, num_mlo_links = rsp->ml_parnter_info.num_partner_links + 1; 621 struct wlan_objmgr_vdev *ml_vdev = vdev; 622 struct vdev_osif_priv *osif_priv; 623 struct ieee80211_channel *chan; 624 struct cfg80211_mlo_link_params *ml_link_params; 625 struct mlo_link_info *rsp_partner_info; 626 627 if (num_mlo_links == 1) 628 return; 629 630 ml_link_params = qdf_mem_malloc( 631 num_mlo_links * sizeof(*ml_link_params)); 632 if (!ml_link_params) 633 return; 634 635 rsp_partner_info = rsp->ml_parnter_info.partner_link_info; 636 if (rsp->ml_parnter_info.num_partner_links) { 637 conn_rsp_params->n_mlo_links = num_mlo_links; 638 osif_priv = wlan_vdev_get_ospriv(ml_vdev); 639 for (i = 0; i < conn_rsp_params->n_mlo_links; i++) { 640 ml_link_params[i].wdev = osif_priv->wdev; 641 642 if (i != 0) { 643 chan = ieee80211_get_channel( 644 osif_priv->wdev->wiphy, 645 rsp_partner_info[i - 1].chan_freq); 646 if (!chan) { 647 osif_err("Invalid partner channel"); 648 goto end; 649 } 650 651 bss = wlan_cfg80211_get_bss( 652 osif_priv->wdev->wiphy, chan, 653 rsp_partner_info[i - 1].link_addr.bytes, 654 rsp->ssid.ssid, rsp->ssid.length); 655 if (!bss) { 656 osif_err("Partner bss is null"); 657 goto end; 658 } 659 } 660 qdf_mem_copy(ml_link_params[i].bssid, bss->bssid, 661 QDF_MAC_ADDR_SIZE); 662 663 if (i == rsp->ml_parnter_info.num_partner_links) 664 break; 665 666 ml_vdev = osif_get_partner_vdev(vdev, 667 rsp_partner_info[i], 668 WLAN_OSIF_CM_ID); 669 670 if (ml_vdev) { 671 osif_priv = wlan_vdev_get_ospriv(ml_vdev); 672 wlan_objmgr_vdev_release_ref(ml_vdev, 673 WLAN_OSIF_CM_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 qdf_mem_copy(macaddr.bytes, rsp->bssid.bytes, 906 QDF_MAC_ADDR_SIZE); 907 if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) { 908 wlan_vdev_get_bss_peer_mac(assoc_vdev, &macaddr); 909 chan = ieee80211_get_channel(tmp_osif_priv->wdev->wiphy, 910 freq); 911 bss = wlan_cfg80211_get_bss(tmp_osif_priv->wdev->wiphy, 912 chan, 913 macaddr.bytes, 914 rsp->ssid.ssid, 915 rsp->ssid.length); 916 } 917 qdf_mem_copy(resp.bssid.bytes, macaddr.bytes, 918 QDF_MAC_ADDR_SIZE); 919 resp.freq = freq; 920 resp.connect_ies.assoc_req.ptr = rsp->connect_ies.assoc_req.ptr; 921 resp.connect_ies.assoc_req.len = rsp->connect_ies.assoc_req.len; 922 resp.connect_ies.assoc_rsp.ptr = rsp->connect_ies.assoc_rsp.ptr; 923 resp.connect_ies.assoc_rsp.len = rsp->connect_ies.assoc_rsp.len; 924 if (osif_update_connect_results(tmp_osif_priv->wdev->netdev, bss, 925 &resp, assoc_vdev)) 926 osif_connect_bss(tmp_osif_priv->wdev->netdev, bss, &resp); 927 } 928 } 929 #endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */ 930 #else /* WLAN_FEATURE_11BE_MLO */ 931 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 932 struct vdev_osif_priv *osif_priv, 933 struct wlan_cm_connect_resp *rsp) 934 { 935 struct cfg80211_bss *bss = NULL; 936 struct ieee80211_channel *chan; 937 938 if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) { 939 chan = ieee80211_get_channel(osif_priv->wdev->wiphy, 940 rsp->freq); 941 bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan, 942 rsp->bssid.bytes, 943 rsp->ssid.ssid, 944 rsp->ssid.length); 945 } 946 947 if (osif_update_connect_results(osif_priv->wdev->netdev, bss, 948 rsp, vdev)) 949 osif_connect_bss(osif_priv->wdev->netdev, bss, rsp); 950 } 951 #endif /* WLAN_FEATURE_11BE_MLO */ 952 #else /* CFG80211_CONNECT_BSS */ 953 #ifdef WLAN_FEATURE_11BE_MLO 954 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 955 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 956 struct vdev_osif_priv *osif_priv, 957 struct wlan_cm_connect_resp *rsp) 958 { 959 enum ieee80211_statuscode status; 960 size_t req_len = 0; 961 const uint8_t *req_ptr = NULL; 962 size_t rsp_len = 0; 963 const uint8_t *rsp_ptr = NULL; 964 struct wlan_objmgr_vdev *assoc_vdev = NULL; 965 struct vdev_osif_priv *tmp_osif_priv = NULL; 966 967 status = osif_get_connect_status_code(rsp); 968 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 969 &req_len, &req_ptr); 970 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 971 &rsp_len, &rsp_ptr); 972 if (wlan_vdev_mlme_is_mlo_vdev(vdev)) { 973 if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev)) 974 cfg80211_connect_result( 975 osif_priv->wdev->netdev, 976 rsp->bssid.bytes, req_ptr, req_len, 977 rsp_ptr, rsp_len, status, 978 qdf_mem_malloc_flags()); 979 } else { 980 cfg80211_connect_result(osif_priv->wdev->netdev, 981 rsp->bssid.bytes, req_ptr, req_len, 982 rsp_ptr, rsp_len, status, 983 qdf_mem_malloc_flags()); 984 } 985 } 986 #else /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */ 987 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 988 struct vdev_osif_priv *osif_priv, 989 struct wlan_cm_connect_resp *rsp) 990 { 991 enum ieee80211_statuscode status; 992 size_t req_len = 0; 993 const uint8_t *req_ptr = NULL; 994 size_t rsp_len = 0; 995 const uint8_t *rsp_ptr = NULL; 996 struct wlan_objmgr_vdev *assoc_vdev = NULL; 997 struct vdev_osif_priv *tmp_osif_priv = NULL; 998 struct qdf_mac_addr macaddr = {0}; 999 1000 status = osif_get_connect_status_code(rsp); 1001 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 1002 &req_len, &req_ptr); 1003 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 1004 &rsp_len, &rsp_ptr); 1005 if (wlan_vdev_mlme_is_mlo_vdev(vdev)) { 1006 if ((QDF_IS_STATUS_SUCCESS(rsp->connect_status) && 1007 ucfg_mlo_is_mld_connected(vdev)) || 1008 (QDF_IS_STATUS_ERROR(rsp->connect_status) && 1009 ucfg_mlo_is_mld_disconnected(vdev))) { 1010 assoc_vdev = ucfg_mlo_get_assoc_link_vdev(vdev); 1011 if (!assoc_vdev) 1012 return; 1013 tmp_osif_priv = wlan_vdev_get_ospriv(assoc_vdev); 1014 wlan_vdev_get_bss_peer_mac(assoc_vdev, &macaddr); 1015 cfg80211_connect_result(tmp_osif_priv->wdev->netdev, 1016 macaddr.bytes, req_ptr, 1017 req_len, rsp_ptr, rsp_len, 1018 status, qdf_mem_malloc_flags()); 1019 } 1020 } else { 1021 cfg80211_connect_result(osif_priv->wdev->netdev, 1022 rsp->bssid.bytes, req_ptr, req_len, 1023 rsp_ptr, rsp_len, status, 1024 qdf_mem_malloc_flags()); 1025 } 1026 } 1027 #endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */ 1028 #else /* WLAN_FEATURE_11BE_MLO */ 1029 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 1030 struct vdev_osif_priv *osif_priv, 1031 struct wlan_cm_connect_resp *rsp) 1032 { 1033 enum ieee80211_statuscode status; 1034 size_t req_len = 0; 1035 const uint8_t *req_ptr = NULL; 1036 size_t rsp_len = 0; 1037 const uint8_t *rsp_ptr = NULL; 1038 1039 status = osif_get_connect_status_code(rsp); 1040 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 1041 &req_len, &req_ptr); 1042 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 1043 &rsp_len, &rsp_ptr); 1044 cfg80211_connect_result(osif_priv->wdev->netdev, 1045 rsp->bssid.bytes, req_ptr, req_len, 1046 rsp_ptr, rsp_len, status, 1047 qdf_mem_malloc_flags()); 1048 } 1049 #endif /* WLAN_FEATURE_11BE_MLO */ 1050 #endif /* CFG80211_CONNECT_BSS */ 1051 1052 #ifdef CONN_MGR_ADV_FEATURE 1053 static inline 1054 bool osif_cm_is_unlink_bss_required(struct wlan_cm_connect_resp *rsp) 1055 { 1056 if (QDF_IS_STATUS_SUCCESS(rsp->connect_status) || 1057 rsp->cm_id & CM_ID_LSWITCH_BIT) 1058 return false; 1059 1060 if (rsp->reason == CM_NO_CANDIDATE_FOUND || 1061 rsp->reason == CM_JOIN_TIMEOUT || 1062 rsp->reason == CM_AUTH_TIMEOUT || 1063 rsp->reason == CM_ASSOC_TIMEOUT) 1064 return true; 1065 1066 return false; 1067 } 1068 static inline void osif_check_and_unlink_bss(struct wlan_objmgr_vdev *vdev, 1069 struct wlan_cm_connect_resp *rsp) 1070 { 1071 if (osif_cm_is_unlink_bss_required(rsp)) 1072 osif_cm_unlink_bss(vdev, &rsp->bssid); 1073 } 1074 #else 1075 static inline void osif_check_and_unlink_bss(struct wlan_objmgr_vdev *vdev, 1076 struct wlan_cm_connect_resp *rsp) 1077 {} 1078 #endif 1079 1080 #define OSIF_CM_FAIL_INFO_STRING_SIZE 50 1081 1082 static inline void 1083 osif_dump_connect_rsp(struct wlan_objmgr_vdev *vdev, 1084 struct vdev_osif_priv *osif_priv, 1085 struct wlan_cm_connect_resp *rsp) 1086 { 1087 char fail_info[OSIF_CM_FAIL_INFO_STRING_SIZE] = {0}; 1088 1089 /* Fill status code and reason only on failure */ 1090 if (QDF_IS_STATUS_ERROR(rsp->connect_status)) 1091 qdf_scnprintf(fail_info, sizeof(fail_info), 1092 "reason %d status %d %s", 1093 rsp->reason, rsp->status_code, 1094 rsp->send_disconnect ? 1095 ", Send disconnect" : ""); 1096 1097 osif_nofl_info("%s(vdevid-%d): " QDF_MAC_ADDR_FMT " %s with " QDF_MAC_ADDR_FMT " \"" QDF_SSID_FMT "\" is %s, cmid 0x%x %s", 1098 osif_priv->wdev->netdev->name, rsp->vdev_id, 1099 QDF_MAC_ADDR_REF(wlan_vdev_mlme_get_macaddr(vdev)), 1100 rsp->is_reassoc ? "Roam" : "Connect", 1101 QDF_MAC_ADDR_REF(rsp->bssid.bytes), 1102 QDF_SSID_REF(rsp->ssid.length, rsp->ssid.ssid), 1103 rsp->connect_status ? "FAILURE" : "SUCCESS", rsp->cm_id, 1104 fail_info); 1105 } 1106 1107 QDF_STATUS osif_connect_handler(struct wlan_objmgr_vdev *vdev, 1108 struct wlan_cm_connect_resp *rsp) 1109 { 1110 struct vdev_osif_priv *osif_priv = wlan_vdev_get_ospriv(vdev); 1111 QDF_STATUS status; 1112 1113 osif_dump_connect_rsp(vdev, osif_priv, rsp); 1114 osif_check_and_unlink_bss(vdev, rsp); 1115 1116 status = osif_validate_connect_and_reset_src_id(osif_priv, rsp); 1117 if (QDF_IS_STATUS_ERROR(status) || rsp->cm_id & CM_ID_LSWITCH_BIT) { 1118 osif_cm_connect_comp_ind(vdev, rsp, OSIF_NOT_HANDLED); 1119 return status; 1120 } 1121 1122 osif_cm_connect_comp_ind(vdev, rsp, OSIF_PRE_USERSPACE_UPDATE); 1123 1124 /* 1125 * To fix issue that scan with random address failed since wdev keeps 1126 * connected, rsp->send_disconnect is added. 1127 * Reproduce steps: 1128 * 1. Connect from OSIF success, wdev->connected = true; 1129 * 2. Disconnect from target if and reassoc from OSIF happens back to 1130 * back. 1131 * 3. Disconnect event is not sent to kernel, wdev->connected keeps 1132 * true, isn't cleared. 1133 * 4. Connect from OSIF failed too, wdev->connected keeps true, isn't 1134 * cleared. 1135 * 5. Scan with random address failed since wdev->connected is true. 1136 * 1137 * To fix it, if connect req was a reassoc req and received in not 1138 * connected state for race between disconnect from target if and 1139 * reassoc connect from OSIF, set reassoc_in_non_connected to send 1140 * disconnect instead of connect rsp to kernel to cleanup kernel flags 1141 * like: wdev->connected. 1142 */ 1143 if (rsp->is_reassoc) 1144 osif_indicate_reassoc_results(vdev, osif_priv, rsp); 1145 else if (rsp->send_disconnect && 1146 QDF_IS_STATUS_ERROR(rsp->connect_status)) 1147 osif_cm_indicate_disconnect(vdev, osif_priv->wdev->netdev, 1148 WLAN_REASON_UNSPECIFIED, 1149 false, NULL, 0, -1, 1150 qdf_mem_malloc_flags()); 1151 else 1152 osif_indcate_connect_results(vdev, osif_priv, rsp); 1153 osif_cm_connect_comp_ind(vdev, rsp, OSIF_POST_USERSPACE_UPDATE); 1154 1155 return QDF_STATUS_SUCCESS; 1156 } 1157 1158 QDF_STATUS osif_failed_candidate_handler(struct wlan_objmgr_vdev *vdev, 1159 struct wlan_cm_connect_resp *rsp) 1160 { 1161 struct vdev_osif_priv *osif_priv = wlan_vdev_get_ospriv(vdev); 1162 1163 osif_dump_connect_rsp(vdev, osif_priv, rsp); 1164 1165 /** 1166 * Do not unlink the BSS if it is an ML candidate. In case of ML, 1167 * failed candidate may be used as partner link while trying the 1168 * connection on other links. 1169 */ 1170 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) 1171 osif_check_and_unlink_bss(vdev, rsp); 1172 1173 return QDF_STATUS_SUCCESS; 1174 } 1175