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 #include "wlan_crypto_global_api.h" 39 40 #ifdef CONN_MGR_ADV_FEATURE 41 void osif_cm_get_assoc_req_ie_data(struct element_info *assoc_req, 42 size_t *ie_data_len, 43 const uint8_t **ie_data_ptr) 44 { 45 /* Validate IE and length */ 46 if (!assoc_req->len || !assoc_req->ptr || 47 assoc_req->len <= WLAN_ASSOC_REQ_IES_OFFSET) 48 return; 49 50 *ie_data_len = assoc_req->len - WLAN_ASSOC_REQ_IES_OFFSET; 51 *ie_data_ptr = assoc_req->ptr + WLAN_ASSOC_REQ_IES_OFFSET; 52 } 53 #else 54 void osif_cm_get_assoc_req_ie_data(struct element_info *assoc_req, 55 size_t *ie_data_len, 56 const uint8_t **ie_data_ptr) 57 { 58 /* Validate IE and length */ 59 if (!assoc_req->len || !assoc_req->ptr) 60 return; 61 62 *ie_data_len = assoc_req->len; 63 *ie_data_ptr = assoc_req->ptr; 64 } 65 #endif 66 67 void osif_cm_get_assoc_rsp_ie_data(struct element_info *assoc_rsp, 68 size_t *ie_data_len, 69 const uint8_t **ie_data_ptr) 70 { 71 /* Validate IE and length */ 72 if (!assoc_rsp->len || !assoc_rsp->ptr || 73 assoc_rsp->len <= WLAN_ASSOC_RSP_IES_OFFSET) 74 return; 75 76 *ie_data_len = assoc_rsp->len - WLAN_ASSOC_RSP_IES_OFFSET; 77 *ie_data_ptr = assoc_rsp->ptr + WLAN_ASSOC_RSP_IES_OFFSET; 78 } 79 80 /** 81 * osif_validate_connect_and_reset_src_id() - Validate connect response and 82 * resets source and id 83 * @osif_priv: Pointer to vdev osif priv 84 * @rsp: Connection manager connect response 85 * 86 * This function validates connect response and if the connect 87 * response is valid, resets the source and id of the command 88 * 89 * Context: Any context. Takes and releases cmd id spinlock. 90 * Return: QDF_STATUS 91 */ 92 static QDF_STATUS 93 osif_validate_connect_and_reset_src_id(struct vdev_osif_priv *osif_priv, 94 struct wlan_cm_connect_resp *rsp) 95 { 96 QDF_STATUS status = QDF_STATUS_SUCCESS; 97 98 /* 99 * Do not send to kernel if last osif cookie doesn't match or 100 * or source is CM_OSIF_CFG_CONNECT with success status. 101 * If cookie matches reset the cookie and source. 102 */ 103 qdf_spinlock_acquire(&osif_priv->cm_info.cmd_id_lock); 104 if (rsp->cm_id != osif_priv->cm_info.last_id || 105 (osif_priv->cm_info.last_source == CM_OSIF_CFG_CONNECT && 106 QDF_IS_STATUS_SUCCESS(rsp->connect_status))) { 107 osif_debug("Ignore as cm_id(0x%x)/src(%d) != cm_id(0x%x)/src(%d) OR source is CFG connect with status %d", 108 rsp->cm_id, CM_OSIF_CONNECT, 109 osif_priv->cm_info.last_id, 110 osif_priv->cm_info.last_source, 111 rsp->connect_status); 112 status = QDF_STATUS_E_INVAL; 113 goto rel_lock; 114 } 115 116 osif_cm_reset_id_and_src_no_lock(osif_priv); 117 rel_lock: 118 qdf_spinlock_release(&osif_priv->cm_info.cmd_id_lock); 119 120 return status; 121 } 122 123 static enum ieee80211_statuscode 124 osif_get_statuscode(enum wlan_status_code status) 125 { 126 return (enum ieee80211_statuscode)status; 127 } 128 129 static enum ieee80211_statuscode 130 osif_get_connect_status_code(struct wlan_cm_connect_resp *rsp) 131 { 132 enum ieee80211_statuscode status = WLAN_STATUS_SUCCESS; 133 134 if (QDF_IS_STATUS_ERROR(rsp->connect_status)) { 135 if (rsp->status_code) 136 status = osif_get_statuscode(rsp->status_code); 137 else 138 status = WLAN_STATUS_UNSPECIFIED_FAILURE; 139 } 140 141 return status; 142 } 143 144 /** 145 * osif_convert_timeout_reason() - Convert to kernel specific enum 146 * @reason: reason for connect timeout 147 * 148 * This function is used to convert host timeout 149 * reason enum to kernel specific enum. 150 * 151 * Context: Any context. 152 * Return: nl timeout enum 153 */ 154 155 static enum nl80211_timeout_reason 156 osif_convert_timeout_reason(enum wlan_cm_connect_fail_reason reason) 157 { 158 switch (reason) { 159 case CM_JOIN_TIMEOUT: 160 return NL80211_TIMEOUT_SCAN; 161 case CM_AUTH_TIMEOUT: 162 return NL80211_TIMEOUT_AUTH; 163 case CM_ASSOC_TIMEOUT: 164 return NL80211_TIMEOUT_ASSOC; 165 default: 166 return NL80211_TIMEOUT_UNSPECIFIED; 167 } 168 } 169 170 #if defined CFG80211_CONNECT_BSS || \ 171 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)) 172 173 #if defined CFG80211_CONNECT_TIMEOUT_REASON_CODE || \ 174 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) 175 /** 176 * osif_connect_timeout() - API to send connection timeout reason 177 * @dev: network device 178 * @bssid: bssid to which we want to associate 179 * @reason: reason for connect timeout 180 * 181 * This API is used to send connection timeout reason to supplicant 182 * 183 * Context: Any context. 184 * Return: Void 185 */ 186 static void 187 osif_connect_timeout(struct net_device *dev, const u8 *bssid, 188 enum wlan_cm_connect_fail_reason reason) 189 { 190 enum nl80211_timeout_reason nl_timeout_reason; 191 192 nl_timeout_reason = osif_convert_timeout_reason(reason); 193 194 osif_debug("nl_timeout_reason %d", nl_timeout_reason); 195 196 cfg80211_connect_timeout(dev, bssid, NULL, 0, qdf_mem_malloc_flags(), 197 nl_timeout_reason); 198 } 199 200 /** 201 * __osif_connect_bss() - API to send connection status to supplicant 202 * @dev: network device 203 * @bss: bss info 204 * @rsp: Connection manager connect response 205 * @status: 802.11 status code 206 * 207 * Context: Any context. 208 * Return: void 209 */ 210 static void __osif_connect_bss(struct net_device *dev, 211 struct cfg80211_bss *bss, 212 struct wlan_cm_connect_resp *rsp, 213 enum ieee80211_statuscode status) 214 { 215 enum nl80211_timeout_reason nl_timeout_reason; 216 size_t req_len = 0; 217 const uint8_t *req_ptr = NULL; 218 size_t rsp_len = 0; 219 const uint8_t *rsp_ptr = NULL; 220 221 nl_timeout_reason = osif_convert_timeout_reason(rsp->reason); 222 223 osif_debug("nl_timeout_reason %d", nl_timeout_reason); 224 225 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 226 &req_len, &req_ptr); 227 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 228 &rsp_len, &rsp_ptr); 229 230 cfg80211_connect_bss(dev, rsp->bssid.bytes, bss, 231 req_ptr, req_len, rsp_ptr, rsp_len, status, 232 qdf_mem_malloc_flags(), nl_timeout_reason); 233 } 234 #else /* CFG80211_CONNECT_TIMEOUT_REASON_CODE */ 235 236 #if defined CFG80211_CONNECT_TIMEOUT || \ 237 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) 238 static void osif_connect_timeout( 239 struct net_device *dev, 240 const u8 *bssid, 241 enum wlan_cm_connect_fail_reason reason) 242 { 243 cfg80211_connect_timeout(dev, bssid, NULL, 0, qdf_mem_malloc_flags()); 244 } 245 #endif 246 247 static void __osif_connect_bss(struct net_device *dev, 248 struct cfg80211_bss *bss, 249 struct wlan_cm_connect_resp *rsp, 250 ieee80211_statuscode status) 251 { 252 size_t req_len = 0; 253 const uint8_t *req_ptr = NULL; 254 size_t rsp_len = 0; 255 const uint8_t *rsp_ptr = NULL; 256 257 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 258 &req_len, &req_ptr); 259 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 260 &rsp_len, &rsp_ptr); 261 262 cfg80211_connect_bss(dev, rsp->bssid.bytes, bss, 263 req_ptr, req_len, rsp_ptr, rsp_len, 264 status, qdf_mem_malloc_flags()); 265 } 266 #endif /* CFG80211_CONNECT_TIMEOUT_REASON_CODE */ 267 268 /** 269 * osif_connect_bss() - API to send connection status to supplicant 270 * @dev: network device 271 * @bss: bss info 272 * @rsp: Connection manager connect response 273 * 274 * The API is a wrapper to send connection status to supplicant 275 * 276 * Context: Any context. 277 * Return: Void 278 */ 279 #if defined CFG80211_CONNECT_TIMEOUT || \ 280 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) 281 static void osif_connect_bss(struct net_device *dev, struct cfg80211_bss *bss, 282 struct wlan_cm_connect_resp *rsp) 283 { 284 enum ieee80211_statuscode status = WLAN_STATUS_SUCCESS; 285 286 osif_enter_dev(dev); 287 288 if (rsp->reason == CM_JOIN_TIMEOUT || 289 rsp->reason == CM_AUTH_TIMEOUT || 290 rsp->reason == CM_ASSOC_TIMEOUT) { 291 osif_connect_timeout(dev, rsp->bssid.bytes, 292 rsp->reason); 293 } else { 294 status = osif_get_connect_status_code(rsp); 295 296 __osif_connect_bss(dev, bss, rsp, status); 297 } 298 } 299 #else /* CFG80211_CONNECT_TIMEOUT */ 300 static void osif_connect_bss(struct net_device *dev, struct cfg80211_bss *bss, 301 struct wlan_cm_connect_resp *rsp) 302 { 303 enum ieee80211_statuscode status; 304 305 osif_enter_dev(dev); 306 307 status = osif_get_connect_status_code(rsp); 308 __osif_connect_bss(dev, bss, rsp, status); 309 } 310 #endif /* CFG80211_CONNECT_TIMEOUT */ 311 312 #if defined(CFG80211_CONNECT_DONE) || \ 313 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) 314 315 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)) 316 317 #if defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) 318 /** 319 * osif_populate_fils_params() - Populate FILS keys to connect response 320 * @rsp_params: connect response to supplicant 321 * @connect_ies: Connect response IEs 322 * 323 * Context: Any context. 324 * Return: None 325 */ 326 static void 327 osif_populate_fils_params(struct cfg80211_connect_resp_params *rsp_params, 328 struct wlan_connect_rsp_ies *connect_ies) 329 { 330 if (!connect_ies->fils_ie) 331 return; 332 333 /* Increment seq number to be used for next FILS */ 334 rsp_params->fils_erp_next_seq_num = 335 connect_ies->fils_ie->fils_seq_num + 1; 336 rsp_params->update_erp_next_seq_num = true; 337 rsp_params->fils_kek = connect_ies->fils_ie->kek; 338 rsp_params->fils_kek_len = connect_ies->fils_ie->kek_len; 339 rsp_params->pmk = connect_ies->fils_ie->fils_pmk; 340 rsp_params->pmk_len = connect_ies->fils_ie->fils_pmk_len; 341 rsp_params->pmkid = connect_ies->fils_ie->fils_pmkid; 342 osif_debug("erp_next_seq_num:%d", rsp_params->fils_erp_next_seq_num); 343 } 344 #else /* CFG80211_FILS_SK_OFFLOAD_SUPPORT */ 345 static inline void 346 osif_populate_fils_params(struct cfg80211_connect_resp_params *rsp_params, 347 struct wlan_connect_rsp_ies *connect_ies) 348 { } 349 #endif /* CFG80211_FILS_SK_OFFLOAD_SUPPORT */ 350 351 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) 352 #if defined(WLAN_FEATURE_FILS_SK) 353 /** 354 * osif_populate_fils_params() - Populate FILS keys to connect response 355 * @rsp_params: connect response to supplicant 356 * @connect_ies: Connect response IEs 357 * 358 * Context: Any context. 359 * Return: None 360 */ 361 static void 362 osif_populate_fils_params(struct cfg80211_connect_resp_params *rsp_params, 363 struct wlan_connect_rsp_ies *connect_ies) 364 365 { 366 if (!connect_ies->fils_ie) 367 return; 368 369 /* Increment seq number to be used for next FILS */ 370 rsp_params->fils.erp_next_seq_num = 371 connect_ies->fils_ie->fils_seq_num + 1; 372 rsp_params->fils.update_erp_next_seq_num = true; 373 rsp_params->fils.kek = connect_ies->fils_ie->kek; 374 rsp_params->fils.kek_len = connect_ies->fils_ie->kek_len; 375 rsp_params->fils.pmk = connect_ies->fils_ie->fils_pmk; 376 rsp_params->fils.pmk_len = connect_ies->fils_ie->fils_pmk_len; 377 rsp_params->fils.pmkid = connect_ies->fils_ie->fils_pmkid; 378 osif_debug("erp_next_seq_num:%d", rsp_params->fils.erp_next_seq_num); 379 } 380 #else /* WLAN_FEATURE_FILS_SK */ 381 static inline void 382 osif_populate_fils_params(struct cfg80211_connect_resp_params *rsp_params, 383 struct wlan_connect_rsp_ies *connect_ies) 384 { } 385 #endif /* WLAN_FEATURE_FILS_SK */ 386 #endif 387 388 #ifdef WLAN_FEATURE_11BE_MLO 389 QDF_STATUS 390 osif_get_partner_info_from_mlie(struct wlan_cm_connect_resp *connect_rsp, 391 struct mlo_partner_info *partner_info) 392 { 393 qdf_size_t connect_resp_len = 0, ml_ie_len = 0; 394 const uint8_t *connect_resp_ptr = NULL; 395 QDF_STATUS qdf_status; 396 uint8_t *ml_ie = NULL; 397 398 osif_cm_get_assoc_rsp_ie_data(&connect_rsp->connect_ies.assoc_rsp, 399 &connect_resp_len, &connect_resp_ptr); 400 401 if (!connect_resp_len) { 402 osif_err("Connect response is null return error"); 403 return QDF_STATUS_E_INVAL; 404 } 405 406 qdf_status = util_find_mlie((uint8_t *)connect_resp_ptr, 407 connect_resp_len, &ml_ie, &ml_ie_len); 408 if (QDF_IS_STATUS_ERROR(qdf_status) || !ml_ie) { 409 osif_debug("ML IE not found %d", qdf_status); 410 return qdf_status; 411 } 412 413 osif_debug("ML IE found length %d", (int)ml_ie_len); 414 415 qdf_status = util_get_bvmlie_persta_partner_info(ml_ie, ml_ie_len, 416 partner_info); 417 if (QDF_IS_STATUS_ERROR(qdf_status)) { 418 osif_err("Unable to find per-sta profile in ML IE"); 419 return qdf_status; 420 } 421 422 return qdf_status; 423 } 424 425 QDF_STATUS 426 osif_get_link_id_from_assoc_ml_ie(struct mlo_link_info *rsp_link_info, 427 struct mlo_partner_info *assoc_partner_info, 428 uint8_t *link_id) 429 { 430 int j; 431 432 for (j = 0; j < assoc_partner_info->num_partner_links; j++) { 433 if (!qdf_mem_cmp(rsp_link_info->link_addr.bytes, 434 assoc_partner_info->partner_link_info[j].link_addr.bytes, 435 QDF_MAC_ADDR_SIZE)) { 436 *link_id = assoc_partner_info->partner_link_info[j].link_id; 437 return QDF_STATUS_SUCCESS; 438 } 439 } 440 441 return QDF_STATUS_E_INVAL; 442 } 443 444 struct cfg80211_bss * 445 osif_get_chan_bss_from_kernel(struct wlan_objmgr_vdev *vdev, 446 struct mlo_link_info *rsp_link_info, 447 struct wlan_cm_connect_resp *rsp) 448 { 449 struct vdev_osif_priv *osif_priv; 450 struct cfg80211_bss *partner_bss; 451 struct ieee80211_channel *chan; 452 453 osif_priv = wlan_vdev_get_ospriv(vdev); 454 chan = ieee80211_get_channel(osif_priv->wdev->wiphy, 455 rsp_link_info->chan_freq); 456 if (!chan) { 457 osif_err("Invalid partner channel"); 458 return NULL; 459 } 460 461 partner_bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan, 462 rsp_link_info->link_addr.bytes, 463 rsp->ssid.ssid, rsp->ssid.length); 464 if (!partner_bss) { 465 osif_err("could not fetch partner bss from kernel"); 466 return NULL; 467 } 468 469 return partner_bss; 470 } 471 #endif 472 473 #if defined(CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT) && defined(WLAN_FEATURE_11BE_MLO) 474 #ifndef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 475 static struct wlan_objmgr_vdev *osif_get_partner_vdev( 476 struct wlan_objmgr_vdev *vdev, 477 struct mlo_link_info rsp_partner_info, 478 wlan_objmgr_ref_dbgid id) 479 { 480 return mlo_get_vdev_by_link_id(vdev, rsp_partner_info.link_id, id); 481 } 482 #endif 483 484 static 485 void osif_populate_connect_response_for_link(struct wlan_objmgr_vdev *vdev, 486 struct cfg80211_connect_resp_params *conn_rsp_params, 487 uint8_t link_id, 488 uint8_t *link_addr, 489 struct cfg80211_bss *bss) 490 { 491 osif_debug("Link_id :%d", link_id); 492 conn_rsp_params->valid_links |= BIT(link_id); 493 conn_rsp_params->links[link_id].bssid = bss->bssid; 494 conn_rsp_params->links[link_id].bss = bss; 495 conn_rsp_params->links[link_id].addr = link_addr; 496 mlo_mgr_osif_update_connect_info(vdev, link_id); 497 } 498 499 static QDF_STATUS 500 osif_fill_peer_mld_mac_connect_resp(struct wlan_objmgr_vdev *vdev, 501 struct wlan_cm_connect_resp *rsp, 502 struct cfg80211_connect_resp_params *conn_rsp_params) 503 { 504 struct wlan_objmgr_peer *peer_obj; 505 struct wlan_objmgr_psoc *psoc; 506 507 psoc = wlan_vdev_get_psoc(vdev); 508 if (!psoc) 509 return QDF_STATUS_E_INVAL; 510 511 peer_obj = wlan_objmgr_get_peer_by_mac(psoc, rsp->bssid.bytes, 512 WLAN_OSIF_ID); 513 if (!peer_obj) 514 return QDF_STATUS_E_INVAL; 515 516 conn_rsp_params->ap_mld_addr = wlan_peer_mlme_get_mldaddr(peer_obj); 517 518 wlan_objmgr_peer_release_ref(peer_obj, WLAN_OSIF_ID); 519 520 return QDF_STATUS_SUCCESS; 521 } 522 523 static void 524 osif_populate_partner_links_mlo_params(struct wlan_objmgr_vdev *vdev, 525 struct wlan_cm_connect_resp *rsp, 526 struct cfg80211_connect_resp_params *conn_rsp_params) 527 { 528 struct mlo_link_info *rsp_partner_info; 529 struct cfg80211_bss *bss = NULL; 530 uint8_t link_id = 0, num_links; 531 int i; 532 struct mlo_link_info *link_info; 533 534 num_links = rsp->ml_parnter_info.num_partner_links; 535 for (i = 0 ; i < num_links; i++) { 536 rsp_partner_info = &rsp->ml_parnter_info.partner_link_info[i]; 537 link_id = rsp_partner_info->link_id; 538 539 link_info = mlo_mgr_get_ap_link_by_link_id(vdev->mlo_dev_ctx, 540 link_id); 541 if (!link_info) 542 continue; 543 544 bss = osif_get_chan_bss_from_kernel(vdev, rsp_partner_info, 545 rsp); 546 if (!bss) 547 continue; 548 549 osif_populate_connect_response_for_link(vdev, conn_rsp_params, 550 link_id, 551 link_info->link_addr.bytes, 552 bss); 553 } 554 } 555 556 static void osif_fill_connect_resp_mlo_params(struct wlan_objmgr_vdev *vdev, 557 struct wlan_cm_connect_resp *rsp, 558 struct cfg80211_bss *bss, 559 struct cfg80211_connect_resp_params *conn_rsp_params) 560 { 561 uint8_t assoc_link_id; 562 QDF_STATUS qdf_status; 563 struct mlo_link_info *link_info = NULL; 564 565 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) 566 return; 567 568 qdf_status = osif_fill_peer_mld_mac_connect_resp(vdev, rsp, 569 conn_rsp_params); 570 if (QDF_IS_STATUS_ERROR(qdf_status)) { 571 osif_err("Unable to fill peer mld address: %d", qdf_status); 572 return; 573 } 574 575 assoc_link_id = wlan_vdev_get_link_id(vdev); 576 link_info = mlo_mgr_get_ap_link_by_link_id(vdev->mlo_dev_ctx, 577 assoc_link_id); 578 if (!link_info) { 579 osif_err("Unable to find link_info for link_id: %d", 580 assoc_link_id); 581 return; 582 } 583 584 osif_populate_connect_response_for_link(vdev, conn_rsp_params, 585 assoc_link_id, 586 link_info->link_addr.bytes, 587 bss); 588 osif_populate_partner_links_mlo_params(vdev, rsp, conn_rsp_params); 589 } 590 591 static void 592 osif_free_ml_link_params(struct cfg80211_connect_resp_params *conn_rsp_params) 593 { 594 } 595 #elif defined(CFG80211_IFTYPE_MLO_LINK_SUPPORT) && defined(WLAN_FEATURE_11BE_MLO) 596 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 597 static struct wlan_objmgr_vdev *osif_get_partner_vdev( 598 struct wlan_objmgr_vdev *vdev, 599 struct mlo_link_info rsp_partner_info, 600 wlan_objmgr_ref_dbgid id) 601 { 602 return wlan_objmgr_get_vdev_by_id_from_pdev( 603 vdev->vdev_objmgr.wlan_pdev, 604 rsp_partner_info.vdev_id, id); 605 } 606 #else 607 static struct wlan_objmgr_vdev *osif_get_partner_vdev( 608 struct wlan_objmgr_vdev *vdev, 609 struct mlo_link_info rsp_partner_info, 610 wlan_objmgr_ref_dbgid id) 611 { 612 return mlo_get_vdev_by_link_id(vdev, rsp_partner_info.link_id, 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 WLAN_OSIF_CM_ID); 670 671 if (ml_vdev) { 672 osif_priv = wlan_vdev_get_ospriv(ml_vdev); 673 wlan_objmgr_vdev_release_ref(ml_vdev, 674 WLAN_OSIF_CM_ID); 675 } else { 676 osif_err("Partner vdev not found with vdev_id:%d", 677 rsp_partner_info[i].vdev_id); 678 goto end; 679 } 680 } 681 } 682 end: 683 conn_rsp_params->mlo_links = ml_link_params; 684 } 685 686 static void 687 osif_free_ml_link_params(struct cfg80211_connect_resp_params *conn_rsp_params) 688 { 689 struct cfg80211_mlo_link_params *ml_links; 690 691 ml_links = 692 (struct cfg80211_mlo_link_params *)conn_rsp_params->mlo_links; 693 if (ml_links) 694 qdf_mem_free(ml_links); 695 } 696 697 #else 698 static void osif_fill_connect_resp_mlo_params( 699 struct wlan_objmgr_vdev *vdev, 700 struct wlan_cm_connect_resp *rsp, 701 struct cfg80211_bss *bss, 702 struct cfg80211_connect_resp_params *conn_rsp_params) 703 { 704 } 705 706 static void 707 osif_free_ml_link_params(struct cfg80211_connect_resp_params *conn_rsp_params) 708 { 709 } 710 #endif 711 712 #ifdef CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT 713 static 714 void osif_copy_connected_info(struct cfg80211_connect_resp_params *conn_rsp, 715 struct wlan_cm_connect_resp *rsp, 716 struct cfg80211_bss *bss, 717 struct wlan_objmgr_vdev *vdev) 718 { 719 if (wlan_vdev_mlme_is_mlo_vdev(vdev)) { 720 qdf_debug("MLO vdev fill everything in mlo fill params"); 721 return; 722 } 723 724 conn_rsp->links[0].bssid = rsp->bssid.bytes; 725 conn_rsp->links[0].bss = bss; 726 } 727 #else 728 static 729 void osif_copy_connected_info(struct cfg80211_connect_resp_params *conn_rsp, 730 struct wlan_cm_connect_resp *rsp, 731 struct cfg80211_bss *bss, 732 struct wlan_objmgr_vdev *vdev) 733 { 734 conn_rsp->bssid = rsp->bssid.bytes; 735 conn_rsp->bss = bss; 736 } 737 #endif 738 739 /** 740 * osif_connect_done() - Wrapper API to call cfg80211_connect_done 741 * @dev: network device 742 * @bss: bss info 743 * @rsp: Connection manager connect response 744 * @vdev: pointer to vdev 745 * 746 * This API is used as wrapper to send connect status and params to 747 * supplicant. 748 * 749 * Context: Any context. 750 * Return: 0 if success. Error code for failure 751 */ 752 static int osif_connect_done(struct net_device *dev, struct cfg80211_bss *bss, 753 struct wlan_cm_connect_resp *rsp, 754 struct wlan_objmgr_vdev *vdev) 755 { 756 struct cfg80211_connect_resp_params conn_rsp_params; 757 enum ieee80211_statuscode status; 758 759 osif_enter_dev(dev); 760 761 status = osif_get_connect_status_code(rsp); 762 qdf_mem_zero(&conn_rsp_params, sizeof(conn_rsp_params)); 763 764 conn_rsp_params.status = status; 765 osif_copy_connected_info(&conn_rsp_params, rsp, bss, vdev); 766 conn_rsp_params.timeout_reason = 767 osif_convert_timeout_reason(rsp->reason); 768 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 769 &conn_rsp_params.req_ie_len, 770 &conn_rsp_params.req_ie); 771 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 772 &conn_rsp_params.resp_ie_len, 773 &conn_rsp_params.resp_ie); 774 osif_populate_fils_params(&conn_rsp_params, &rsp->connect_ies); 775 osif_cm_save_gtk(vdev, rsp); 776 777 if (status == WLAN_STATUS_SUCCESS) 778 osif_fill_connect_resp_mlo_params(vdev, rsp, bss, 779 &conn_rsp_params); 780 781 osif_debug("Connect resp status %d", conn_rsp_params.status); 782 783 cfg80211_connect_done(dev, &conn_rsp_params, qdf_mem_malloc_flags()); 784 osif_cm_set_hlp_data(dev, vdev, rsp); 785 786 osif_free_ml_link_params(&conn_rsp_params); 787 788 return 0; 789 } 790 #else /* CFG80211_CONNECT_DONE */ 791 static inline int 792 osif_connect_done(struct net_device *dev, struct cfg80211_bss *bss, 793 struct wlan_cm_connect_resp *rsp, 794 struct wlan_objmgr_vdev *vdev) 795 { 796 return -EINVAL; 797 } 798 #endif 799 800 #if (defined(CFG80211_CONNECT_DONE) || \ 801 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))) 802 /** 803 * osif_update_connect_results() - API to send connection status to 804 * supplicant. 805 * @dev: network device 806 * @bss: bss info 807 * @rsp: Connection manager connect response 808 * @vdev: pointer to vdev 809 * 810 * The API is a wrapper to send connection status to supplicant 811 * 812 * Context: Any context. 813 * Return: 0 if success else failure 814 */ 815 static int osif_update_connect_results(struct net_device *dev, 816 struct cfg80211_bss *bss, 817 struct wlan_cm_connect_resp *rsp, 818 struct wlan_objmgr_vdev *vdev) 819 { 820 return osif_connect_done(dev, bss, rsp, vdev); 821 } 822 #else /* CFG80211_CONNECT_DONE */ 823 824 static inline int osif_update_connect_results(struct net_device *dev, 825 struct cfg80211_bss *bss, 826 struct wlan_cm_connect_resp *rsp, 827 struct wlan_objmgr_vdev *vdev) 828 { 829 return -EINVAL; 830 } 831 #endif /* CFG80211_CONNECT_DONE */ 832 833 #ifdef WLAN_FEATURE_11BE_MLO 834 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 835 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 836 struct vdev_osif_priv *osif_priv, 837 struct wlan_cm_connect_resp *rsp) 838 { 839 struct cfg80211_bss *bss = NULL; 840 struct ieee80211_channel *chan; 841 int32_t akm; 842 843 if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) { 844 chan = ieee80211_get_channel(osif_priv->wdev->wiphy, 845 rsp->freq); 846 bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan, 847 rsp->bssid.bytes, 848 rsp->ssid.ssid, 849 rsp->ssid.length); 850 } 851 852 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) { 853 if (osif_update_connect_results(osif_priv->wdev->netdev, bss, 854 rsp, vdev)) 855 osif_connect_bss(osif_priv->wdev->netdev, bss, rsp); 856 return; 857 } 858 859 akm = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT); 860 if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev)) { 861 if (osif_update_connect_results( 862 osif_priv->wdev->netdev, bss, 863 rsp, vdev)) 864 osif_connect_bss(osif_priv->wdev->netdev, 865 bss, rsp); 866 } else if (osif_get_connect_status_code(rsp) == WLAN_STATUS_SUCCESS && 867 QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_OWE)) { 868 /* 869 * For OWE roaming, link vdev is disconnected on receiving 870 * roam synch indication. As part of the disconnect osif link 871 * info will be cleared and connect request is prepared from 872 * mlo roam module. 873 * So update OSIF Link info for that case here. 874 */ 875 mlo_mgr_osif_update_connect_info(vdev, 876 wlan_vdev_get_link_id(vdev)); 877 } 878 879 } 880 #else /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */ 881 882 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 213)) && \ 883 (LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0)) 884 /** 885 * osif_update_current_bss() - Wrapper API to call cfg80211_update_current_bss 886 * @dev: network device 887 * @bss: bss info 888 * @rsp: Connection manager connect response 889 * @vdev: pointer to vdev 890 * 891 * This API is used as wrapper to update the current bss param of non-assoc link 892 * sta vdev. 893 * 894 * Context: Any context. 895 * Return: QDF_STATUS. 896 */ 897 static QDF_STATUS osif_update_current_bss(struct net_device *dev, 898 struct cfg80211_bss *bss, 899 struct wlan_cm_connect_resp *rsp, 900 struct wlan_objmgr_vdev *vdev) 901 { 902 struct cfg80211_connect_resp_params conn_rsp_params; 903 enum ieee80211_statuscode status; 904 int ret; 905 906 osif_enter_dev(dev); 907 908 qdf_mem_zero(&conn_rsp_params, sizeof(conn_rsp_params)); 909 910 status = osif_get_connect_status_code(rsp); 911 conn_rsp_params.status = status; 912 osif_copy_connected_info(&conn_rsp_params, rsp, bss, vdev); 913 914 osif_debug("Connect resp status %d", conn_rsp_params.status); 915 ret = cfg80211_update_current_bss(dev, &conn_rsp_params, rsp->ssid.ssid, 916 rsp->ssid.length); 917 if (ret) 918 osif_err("cfg80211_update_current_bss failed for psoc:%d pdev:%d vdev:%d", 919 wlan_vdev_get_psoc_id(vdev), 920 wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev)), 921 wlan_vdev_get_id(vdev)); 922 923 return qdf_status_from_os_return(ret); 924 } 925 926 /** 927 * osif_update_current_bss_for_non_assoc_link_vdevs() - API to update the 928 * current_bss param of non-assoc link STA vdev. 929 * @vdev: Pointer to vdev 930 * @arg: Connection manager connect response 931 * 932 * Return: None. 933 */ 934 static void osif_update_current_bss_for_non_assoc_link_vdevs( 935 struct wlan_objmgr_vdev *vdev, void *arg) 936 { 937 struct wlan_objmgr_vdev *assoc_vdev; 938 struct wlan_cm_connect_resp resp = {0}; 939 struct qdf_mac_addr macaddr = {0}; 940 struct vdev_osif_priv *osif_priv = NULL; 941 struct wlan_cm_connect_resp *assoc_link_rsp; 942 943 assoc_link_rsp = (struct wlan_cm_connect_resp *)arg; 944 if (!assoc_link_rsp) { 945 osif_err("assoc_link_rsp is null"); 946 return; 947 } 948 949 assoc_vdev = wlan_mlo_get_assoc_link_vdev(vdev); 950 951 /* For assoc vdev cfg80211_connect_done() is called to update the 952 * current bss param. Hence, skip the assoc vdev here. 953 */ 954 if (vdev == assoc_vdev) 955 return; 956 957 wlan_vdev_mlme_get_ssid(vdev, resp.ssid.ssid, &resp.ssid.length); 958 959 wlan_vdev_get_bss_peer_mac(vdev, &macaddr); 960 qdf_mem_copy(resp.bssid.bytes, macaddr.bytes, QDF_MAC_ADDR_SIZE); 961 962 resp.connect_status = assoc_link_rsp->connect_status; 963 964 osif_debug("vdev:%p bssid:" QDF_MAC_ADDR_FMT " ssid.length:%d ssid: " QDF_SSID_FMT, 965 vdev, QDF_MAC_ADDR_REF(macaddr.bytes), resp.ssid.length, 966 QDF_SSID_REF(resp.ssid.length, resp.ssid.ssid)); 967 968 osif_priv = wlan_vdev_get_ospriv(vdev); 969 osif_update_current_bss(osif_priv->wdev->netdev, NULL, &resp, vdev); 970 } 971 972 /** 973 * osif_update_current_bss_for_non_assoc_links() - API to update the 974 * current_bss param of non-assoc link STA vdev. 975 * @assoc_vdev: Pointer to assoc vdev 976 * @rsp: Connection manager connect response 977 * 978 * Return: None. 979 */ 980 static void osif_update_current_bss_for_non_assoc_links( 981 struct wlan_objmgr_vdev *assoc_vdev, 982 struct wlan_cm_connect_resp *rsp) 983 { 984 mlo_iterate_connected_vdev_list( 985 assoc_vdev, 986 osif_update_current_bss_for_non_assoc_link_vdevs, 987 rsp); 988 } 989 #else 990 static void osif_update_current_bss_for_non_assoc_links( 991 struct wlan_objmgr_vdev *assoc_vdev, 992 struct wlan_cm_connect_resp *rsp) 993 { 994 } 995 #endif 996 997 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 998 struct vdev_osif_priv *osif_priv, 999 struct wlan_cm_connect_resp *rsp) 1000 { 1001 struct cfg80211_bss *bss = NULL; 1002 struct ieee80211_channel *chan; 1003 struct wlan_objmgr_vdev *assoc_vdev = NULL; 1004 struct vdev_osif_priv *tmp_osif_priv = NULL; 1005 qdf_freq_t freq; 1006 struct qdf_mac_addr macaddr = {0}; 1007 struct wlan_cm_connect_resp resp = {0}; 1008 1009 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) { 1010 if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) { 1011 chan = ieee80211_get_channel(osif_priv->wdev->wiphy, 1012 rsp->freq); 1013 bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, 1014 chan, 1015 rsp->bssid.bytes, 1016 rsp->ssid.ssid, 1017 rsp->ssid.length); 1018 } 1019 if (osif_update_connect_results(osif_priv->wdev->netdev, bss, 1020 rsp, vdev)) 1021 osif_connect_bss(osif_priv->wdev->netdev, bss, rsp); 1022 return; 1023 } 1024 1025 if ((QDF_IS_STATUS_SUCCESS(rsp->connect_status) && 1026 ucfg_mlo_is_mld_connected(vdev)) || 1027 (QDF_IS_STATUS_ERROR(rsp->connect_status) && 1028 ucfg_mlo_is_mld_disconnected(vdev))) { 1029 assoc_vdev = ucfg_mlo_get_assoc_link_vdev(vdev); 1030 if (!assoc_vdev) 1031 return; 1032 qdf_mem_copy(&resp, rsp, sizeof(struct wlan_cm_connect_resp)); 1033 tmp_osif_priv = wlan_vdev_get_ospriv(assoc_vdev); 1034 freq = assoc_vdev->vdev_mlme.bss_chan->ch_freq; 1035 qdf_mem_copy(macaddr.bytes, rsp->bssid.bytes, 1036 QDF_MAC_ADDR_SIZE); 1037 if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) { 1038 wlan_vdev_get_bss_peer_mac(assoc_vdev, &macaddr); 1039 chan = ieee80211_get_channel(tmp_osif_priv->wdev->wiphy, 1040 freq); 1041 bss = wlan_cfg80211_get_bss(tmp_osif_priv->wdev->wiphy, 1042 chan, 1043 macaddr.bytes, 1044 rsp->ssid.ssid, 1045 rsp->ssid.length); 1046 } 1047 qdf_mem_copy(resp.bssid.bytes, macaddr.bytes, 1048 QDF_MAC_ADDR_SIZE); 1049 resp.freq = freq; 1050 resp.connect_ies.assoc_req.ptr = rsp->connect_ies.assoc_req.ptr; 1051 resp.connect_ies.assoc_req.len = rsp->connect_ies.assoc_req.len; 1052 resp.connect_ies.assoc_rsp.ptr = rsp->connect_ies.assoc_rsp.ptr; 1053 resp.connect_ies.assoc_rsp.len = rsp->connect_ies.assoc_rsp.len; 1054 if (osif_update_connect_results(tmp_osif_priv->wdev->netdev, bss, 1055 &resp, assoc_vdev)) 1056 osif_connect_bss(tmp_osif_priv->wdev->netdev, bss, &resp); 1057 1058 if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) 1059 osif_update_current_bss_for_non_assoc_links(assoc_vdev, 1060 rsp); 1061 } 1062 } 1063 #endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */ 1064 #else /* WLAN_FEATURE_11BE_MLO */ 1065 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 1066 struct vdev_osif_priv *osif_priv, 1067 struct wlan_cm_connect_resp *rsp) 1068 { 1069 struct cfg80211_bss *bss = NULL; 1070 struct ieee80211_channel *chan; 1071 1072 if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) { 1073 chan = ieee80211_get_channel(osif_priv->wdev->wiphy, 1074 rsp->freq); 1075 bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan, 1076 rsp->bssid.bytes, 1077 rsp->ssid.ssid, 1078 rsp->ssid.length); 1079 } 1080 1081 if (osif_update_connect_results(osif_priv->wdev->netdev, bss, 1082 rsp, vdev)) 1083 osif_connect_bss(osif_priv->wdev->netdev, bss, rsp); 1084 } 1085 #endif /* WLAN_FEATURE_11BE_MLO */ 1086 #else /* CFG80211_CONNECT_BSS */ 1087 #ifdef WLAN_FEATURE_11BE_MLO 1088 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 1089 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 1090 struct vdev_osif_priv *osif_priv, 1091 struct wlan_cm_connect_resp *rsp) 1092 { 1093 enum ieee80211_statuscode status; 1094 size_t req_len = 0; 1095 const uint8_t *req_ptr = NULL; 1096 size_t rsp_len = 0; 1097 const uint8_t *rsp_ptr = NULL; 1098 struct wlan_objmgr_vdev *assoc_vdev = NULL; 1099 struct vdev_osif_priv *tmp_osif_priv = NULL; 1100 1101 status = osif_get_connect_status_code(rsp); 1102 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 1103 &req_len, &req_ptr); 1104 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 1105 &rsp_len, &rsp_ptr); 1106 if (wlan_vdev_mlme_is_mlo_vdev(vdev)) { 1107 if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev)) 1108 cfg80211_connect_result( 1109 osif_priv->wdev->netdev, 1110 rsp->bssid.bytes, req_ptr, req_len, 1111 rsp_ptr, rsp_len, status, 1112 qdf_mem_malloc_flags()); 1113 } else { 1114 cfg80211_connect_result(osif_priv->wdev->netdev, 1115 rsp->bssid.bytes, req_ptr, req_len, 1116 rsp_ptr, rsp_len, status, 1117 qdf_mem_malloc_flags()); 1118 } 1119 } 1120 #else /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */ 1121 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 1122 struct vdev_osif_priv *osif_priv, 1123 struct wlan_cm_connect_resp *rsp) 1124 { 1125 enum ieee80211_statuscode status; 1126 size_t req_len = 0; 1127 const uint8_t *req_ptr = NULL; 1128 size_t rsp_len = 0; 1129 const uint8_t *rsp_ptr = NULL; 1130 struct wlan_objmgr_vdev *assoc_vdev = NULL; 1131 struct vdev_osif_priv *tmp_osif_priv = NULL; 1132 struct qdf_mac_addr macaddr = {0}; 1133 1134 status = osif_get_connect_status_code(rsp); 1135 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 1136 &req_len, &req_ptr); 1137 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 1138 &rsp_len, &rsp_ptr); 1139 if (wlan_vdev_mlme_is_mlo_vdev(vdev)) { 1140 if ((QDF_IS_STATUS_SUCCESS(rsp->connect_status) && 1141 ucfg_mlo_is_mld_connected(vdev)) || 1142 (QDF_IS_STATUS_ERROR(rsp->connect_status) && 1143 ucfg_mlo_is_mld_disconnected(vdev))) { 1144 assoc_vdev = ucfg_mlo_get_assoc_link_vdev(vdev); 1145 if (!assoc_vdev) 1146 return; 1147 tmp_osif_priv = wlan_vdev_get_ospriv(assoc_vdev); 1148 wlan_vdev_get_bss_peer_mac(assoc_vdev, &macaddr); 1149 cfg80211_connect_result(tmp_osif_priv->wdev->netdev, 1150 macaddr.bytes, req_ptr, 1151 req_len, rsp_ptr, rsp_len, 1152 status, qdf_mem_malloc_flags()); 1153 } 1154 } else { 1155 cfg80211_connect_result(osif_priv->wdev->netdev, 1156 rsp->bssid.bytes, req_ptr, req_len, 1157 rsp_ptr, rsp_len, status, 1158 qdf_mem_malloc_flags()); 1159 } 1160 } 1161 #endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */ 1162 #else /* WLAN_FEATURE_11BE_MLO */ 1163 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 1164 struct vdev_osif_priv *osif_priv, 1165 struct wlan_cm_connect_resp *rsp) 1166 { 1167 enum ieee80211_statuscode status; 1168 size_t req_len = 0; 1169 const uint8_t *req_ptr = NULL; 1170 size_t rsp_len = 0; 1171 const uint8_t *rsp_ptr = NULL; 1172 1173 status = osif_get_connect_status_code(rsp); 1174 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 1175 &req_len, &req_ptr); 1176 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 1177 &rsp_len, &rsp_ptr); 1178 cfg80211_connect_result(osif_priv->wdev->netdev, 1179 rsp->bssid.bytes, req_ptr, req_len, 1180 rsp_ptr, rsp_len, status, 1181 qdf_mem_malloc_flags()); 1182 } 1183 #endif /* WLAN_FEATURE_11BE_MLO */ 1184 #endif /* CFG80211_CONNECT_BSS */ 1185 1186 #ifdef CONN_MGR_ADV_FEATURE 1187 static inline 1188 bool osif_cm_is_unlink_bss_required(struct wlan_cm_connect_resp *rsp) 1189 { 1190 if (QDF_IS_STATUS_SUCCESS(rsp->connect_status) || 1191 ucfg_cm_is_link_switch_connect_resp(rsp)) 1192 return false; 1193 1194 if (rsp->reason == CM_NO_CANDIDATE_FOUND || 1195 rsp->reason == CM_JOIN_TIMEOUT || 1196 rsp->reason == CM_AUTH_TIMEOUT || 1197 rsp->reason == CM_ASSOC_TIMEOUT) 1198 return true; 1199 1200 return false; 1201 } 1202 static inline void osif_check_and_unlink_bss(struct wlan_objmgr_vdev *vdev, 1203 struct wlan_cm_connect_resp *rsp) 1204 { 1205 if (osif_cm_is_unlink_bss_required(rsp)) 1206 osif_cm_unlink_bss(vdev, &rsp->bssid); 1207 } 1208 #else 1209 static inline void osif_check_and_unlink_bss(struct wlan_objmgr_vdev *vdev, 1210 struct wlan_cm_connect_resp *rsp) 1211 {} 1212 #endif 1213 1214 #define OSIF_CM_FAIL_INFO_STRING_SIZE 50 1215 1216 static inline void 1217 osif_dump_connect_rsp(struct wlan_objmgr_vdev *vdev, 1218 struct vdev_osif_priv *osif_priv, 1219 struct wlan_cm_connect_resp *rsp) 1220 { 1221 char fail_info[OSIF_CM_FAIL_INFO_STRING_SIZE] = {0}; 1222 1223 /* Fill status code and reason only on failure */ 1224 if (QDF_IS_STATUS_ERROR(rsp->connect_status)) 1225 qdf_scnprintf(fail_info, sizeof(fail_info), 1226 "reason %d status %d %s", 1227 rsp->reason, rsp->status_code, 1228 rsp->send_disconnect ? 1229 ", Send disconnect" : ""); 1230 1231 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", 1232 osif_priv->wdev->netdev->name, rsp->vdev_id, 1233 QDF_MAC_ADDR_REF(wlan_vdev_mlme_get_macaddr(vdev)), 1234 rsp->is_reassoc ? "Roam" : "Connect", 1235 QDF_MAC_ADDR_REF(rsp->bssid.bytes), 1236 QDF_SSID_REF(rsp->ssid.length, rsp->ssid.ssid), 1237 rsp->connect_status ? "FAILURE" : "SUCCESS", rsp->cm_id, 1238 fail_info); 1239 } 1240 1241 QDF_STATUS osif_connect_handler(struct wlan_objmgr_vdev *vdev, 1242 struct wlan_cm_connect_resp *rsp) 1243 { 1244 struct vdev_osif_priv *osif_priv = wlan_vdev_get_ospriv(vdev); 1245 QDF_STATUS status; 1246 1247 osif_dump_connect_rsp(vdev, osif_priv, rsp); 1248 osif_check_and_unlink_bss(vdev, rsp); 1249 1250 status = osif_validate_connect_and_reset_src_id(osif_priv, rsp); 1251 if (QDF_IS_STATUS_ERROR(status) || 1252 ucfg_cm_is_link_switch_connect_resp(rsp)) { 1253 osif_cm_connect_comp_ind(vdev, rsp, OSIF_NOT_HANDLED); 1254 return status; 1255 } 1256 1257 osif_cm_connect_comp_ind(vdev, rsp, OSIF_PRE_USERSPACE_UPDATE); 1258 1259 /* 1260 * To fix issue that scan with random address failed since wdev keeps 1261 * connected, rsp->send_disconnect is added. 1262 * Reproduce steps: 1263 * 1. Connect from OSIF success, wdev->connected = true; 1264 * 2. Disconnect from target if and reassoc from OSIF happens back to 1265 * back. 1266 * 3. Disconnect event is not sent to kernel, wdev->connected keeps 1267 * true, isn't cleared. 1268 * 4. Connect from OSIF failed too, wdev->connected keeps true, isn't 1269 * cleared. 1270 * 5. Scan with random address failed since wdev->connected is true. 1271 * 1272 * To fix it, if connect req was a reassoc req and received in not 1273 * connected state for race between disconnect from target if and 1274 * reassoc connect from OSIF, set reassoc_in_non_connected to send 1275 * disconnect instead of connect rsp to kernel to cleanup kernel flags 1276 * like: wdev->connected. 1277 */ 1278 if (rsp->is_reassoc) 1279 osif_indicate_reassoc_results(vdev, osif_priv, rsp); 1280 else if (rsp->send_disconnect && 1281 QDF_IS_STATUS_ERROR(rsp->connect_status)) 1282 osif_cm_indicate_disconnect(vdev, osif_priv->wdev->netdev, 1283 WLAN_REASON_UNSPECIFIED, 1284 false, NULL, 0, -1, 1285 qdf_mem_malloc_flags()); 1286 else 1287 osif_indcate_connect_results(vdev, osif_priv, rsp); 1288 osif_cm_connect_comp_ind(vdev, rsp, OSIF_POST_USERSPACE_UPDATE); 1289 1290 return QDF_STATUS_SUCCESS; 1291 } 1292 1293 QDF_STATUS osif_failed_candidate_handler(struct wlan_objmgr_vdev *vdev, 1294 struct wlan_cm_connect_resp *rsp) 1295 { 1296 struct vdev_osif_priv *osif_priv = wlan_vdev_get_ospriv(vdev); 1297 1298 osif_dump_connect_rsp(vdev, osif_priv, rsp); 1299 1300 /** 1301 * Do not unlink the BSS if it is an ML candidate. In case of ML, 1302 * failed candidate may be used as partner link while trying the 1303 * connection on other links. 1304 */ 1305 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) 1306 osif_check_and_unlink_bss(vdev, rsp); 1307 1308 return QDF_STATUS_SUCCESS; 1309 } 1310