1 /* 2 * Copyright (c) 2012-2015, 2020-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /** 19 * DOC: 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 vdev id %d freq %d ssid:" QDF_SSID_FMT " and BSSID " QDF_MAC_ADDR_FMT, 466 wlan_vdev_get_id(vdev), rsp_link_info->chan_freq, 467 QDF_SSID_REF(rsp->ssid.length, rsp->ssid.ssid), 468 QDF_MAC_ADDR_REF(rsp->bssid.bytes)); 469 return NULL; 470 } 471 472 return partner_bss; 473 } 474 #endif 475 476 #if defined(CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT) && defined(WLAN_FEATURE_11BE_MLO) 477 #ifndef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 478 static struct wlan_objmgr_vdev *osif_get_partner_vdev( 479 struct wlan_objmgr_vdev *vdev, 480 struct mlo_link_info rsp_partner_info, 481 wlan_objmgr_ref_dbgid id) 482 { 483 return mlo_get_vdev_by_link_id(vdev, rsp_partner_info.link_id, id); 484 } 485 #endif 486 487 static 488 void osif_populate_connect_response_for_link(struct wlan_objmgr_vdev *vdev, 489 struct cfg80211_connect_resp_params *conn_rsp_params, 490 uint8_t link_id, 491 uint8_t *link_addr, 492 struct cfg80211_bss *bss) 493 { 494 if (bss) { 495 osif_debug("Link_id :%d", link_id); 496 conn_rsp_params->valid_links |= BIT(link_id); 497 conn_rsp_params->links[link_id].bssid = bss->bssid; 498 conn_rsp_params->links[link_id].bss = bss; 499 conn_rsp_params->links[link_id].addr = link_addr; 500 } 501 502 mlo_mgr_osif_update_connect_info(vdev, link_id); 503 } 504 505 static QDF_STATUS 506 osif_fill_peer_mld_mac_connect_resp(struct wlan_objmgr_vdev *vdev, 507 struct wlan_cm_connect_resp *rsp, 508 struct cfg80211_connect_resp_params *conn_rsp_params) 509 { 510 struct wlan_objmgr_peer *peer_obj; 511 struct wlan_objmgr_psoc *psoc; 512 513 psoc = wlan_vdev_get_psoc(vdev); 514 if (!psoc) 515 return QDF_STATUS_E_INVAL; 516 517 peer_obj = wlan_objmgr_get_peer_by_mac(psoc, rsp->bssid.bytes, 518 WLAN_OSIF_ID); 519 if (!peer_obj) 520 return QDF_STATUS_E_INVAL; 521 522 conn_rsp_params->ap_mld_addr = wlan_peer_mlme_get_mldaddr(peer_obj); 523 524 wlan_objmgr_peer_release_ref(peer_obj, WLAN_OSIF_ID); 525 526 return QDF_STATUS_SUCCESS; 527 } 528 529 static void 530 osif_populate_partner_links_mlo_params(struct wlan_objmgr_vdev *vdev, 531 struct wlan_cm_connect_resp *rsp, 532 struct cfg80211_connect_resp_params *conn_rsp_params) 533 { 534 struct mlo_link_info *rsp_partner_info; 535 struct cfg80211_bss *bss = NULL; 536 uint8_t link_id = 0, num_links; 537 int i; 538 struct mlo_link_info *link_info; 539 540 num_links = rsp->ml_parnter_info.num_partner_links; 541 for (i = 0 ; i < num_links; i++) { 542 rsp_partner_info = &rsp->ml_parnter_info.partner_link_info[i]; 543 link_id = rsp_partner_info->link_id; 544 545 link_info = mlo_mgr_get_ap_link_by_link_id(vdev->mlo_dev_ctx, 546 link_id); 547 if (!link_info) 548 continue; 549 550 bss = osif_get_chan_bss_from_kernel(vdev, rsp_partner_info, 551 rsp); 552 553 osif_populate_connect_response_for_link(vdev, conn_rsp_params, 554 link_id, 555 link_info->link_addr.bytes, 556 bss); 557 } 558 } 559 560 static void osif_fill_connect_resp_mlo_params(struct wlan_objmgr_vdev *vdev, 561 struct wlan_cm_connect_resp *rsp, 562 struct cfg80211_bss *bss, 563 struct cfg80211_connect_resp_params *conn_rsp_params) 564 { 565 uint8_t assoc_link_id; 566 QDF_STATUS qdf_status; 567 struct mlo_link_info *link_info = NULL; 568 569 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) 570 return; 571 572 qdf_status = osif_fill_peer_mld_mac_connect_resp(vdev, rsp, 573 conn_rsp_params); 574 if (QDF_IS_STATUS_ERROR(qdf_status)) { 575 osif_err("Unable to fill peer mld address: %d", qdf_status); 576 return; 577 } 578 579 assoc_link_id = wlan_vdev_get_link_id(vdev); 580 link_info = mlo_mgr_get_ap_link_by_link_id(vdev->mlo_dev_ctx, 581 assoc_link_id); 582 if (!link_info) { 583 osif_err("Unable to find link_info for link_id: %d", 584 assoc_link_id); 585 return; 586 } 587 588 osif_populate_connect_response_for_link(vdev, conn_rsp_params, 589 assoc_link_id, 590 link_info->link_addr.bytes, 591 bss); 592 osif_populate_partner_links_mlo_params(vdev, rsp, conn_rsp_params); 593 } 594 595 static void 596 osif_free_ml_link_params(struct cfg80211_connect_resp_params *conn_rsp_params) 597 { 598 } 599 #elif defined(CFG80211_IFTYPE_MLO_LINK_SUPPORT) && defined(WLAN_FEATURE_11BE_MLO) 600 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 601 static struct wlan_objmgr_vdev *osif_get_partner_vdev( 602 struct wlan_objmgr_vdev *vdev, 603 struct mlo_link_info rsp_partner_info, 604 wlan_objmgr_ref_dbgid id) 605 { 606 return wlan_objmgr_get_vdev_by_id_from_pdev( 607 vdev->vdev_objmgr.wlan_pdev, 608 rsp_partner_info.vdev_id, id); 609 } 610 #else 611 static struct wlan_objmgr_vdev *osif_get_partner_vdev( 612 struct wlan_objmgr_vdev *vdev, 613 struct mlo_link_info rsp_partner_info, 614 wlan_objmgr_ref_dbgid id) 615 { 616 return mlo_get_vdev_by_link_id(vdev, rsp_partner_info.link_id, id); 617 } 618 #endif 619 static void osif_fill_connect_resp_mlo_params( 620 struct wlan_objmgr_vdev *vdev, 621 struct wlan_cm_connect_resp *rsp, 622 struct cfg80211_bss *bss, 623 struct cfg80211_connect_resp_params *conn_rsp_params) 624 { 625 uint8_t i, num_mlo_links = rsp->ml_parnter_info.num_partner_links + 1; 626 struct wlan_objmgr_vdev *ml_vdev = vdev; 627 struct vdev_osif_priv *osif_priv; 628 struct ieee80211_channel *chan; 629 struct cfg80211_mlo_link_params *ml_link_params; 630 struct mlo_link_info *rsp_partner_info; 631 632 if (num_mlo_links == 1) 633 return; 634 635 ml_link_params = qdf_mem_malloc( 636 num_mlo_links * sizeof(*ml_link_params)); 637 if (!ml_link_params) 638 return; 639 640 rsp_partner_info = rsp->ml_parnter_info.partner_link_info; 641 if (rsp->ml_parnter_info.num_partner_links) { 642 conn_rsp_params->n_mlo_links = num_mlo_links; 643 osif_priv = wlan_vdev_get_ospriv(ml_vdev); 644 for (i = 0; i < conn_rsp_params->n_mlo_links; i++) { 645 ml_link_params[i].wdev = osif_priv->wdev; 646 647 if (i != 0) { 648 chan = ieee80211_get_channel( 649 osif_priv->wdev->wiphy, 650 rsp_partner_info[i - 1].chan_freq); 651 if (!chan) { 652 osif_err("Invalid partner channel"); 653 goto end; 654 } 655 656 bss = wlan_cfg80211_get_bss( 657 osif_priv->wdev->wiphy, chan, 658 rsp_partner_info[i - 1].link_addr.bytes, 659 rsp->ssid.ssid, rsp->ssid.length); 660 if (!bss) { 661 osif_err("Partner bss is null"); 662 goto end; 663 } 664 } 665 qdf_mem_copy(ml_link_params[i].bssid, bss->bssid, 666 QDF_MAC_ADDR_SIZE); 667 668 if (i == rsp->ml_parnter_info.num_partner_links) 669 break; 670 671 ml_vdev = osif_get_partner_vdev(vdev, 672 rsp_partner_info[i], 673 WLAN_OSIF_CM_ID); 674 675 if (ml_vdev) { 676 osif_priv = wlan_vdev_get_ospriv(ml_vdev); 677 wlan_objmgr_vdev_release_ref(ml_vdev, 678 WLAN_OSIF_CM_ID); 679 } else { 680 osif_err("Partner vdev not found with vdev_id:%d", 681 rsp_partner_info[i].vdev_id); 682 goto end; 683 } 684 } 685 } 686 end: 687 conn_rsp_params->mlo_links = ml_link_params; 688 } 689 690 static void 691 osif_free_ml_link_params(struct cfg80211_connect_resp_params *conn_rsp_params) 692 { 693 struct cfg80211_mlo_link_params *ml_links; 694 695 ml_links = 696 (struct cfg80211_mlo_link_params *)conn_rsp_params->mlo_links; 697 if (ml_links) 698 qdf_mem_free(ml_links); 699 } 700 701 #else 702 static void osif_fill_connect_resp_mlo_params( 703 struct wlan_objmgr_vdev *vdev, 704 struct wlan_cm_connect_resp *rsp, 705 struct cfg80211_bss *bss, 706 struct cfg80211_connect_resp_params *conn_rsp_params) 707 { 708 } 709 710 static void 711 osif_free_ml_link_params(struct cfg80211_connect_resp_params *conn_rsp_params) 712 { 713 } 714 #endif 715 716 #ifdef CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT 717 static 718 void osif_copy_connected_info(struct cfg80211_connect_resp_params *conn_rsp, 719 struct wlan_cm_connect_resp *rsp, 720 struct cfg80211_bss *bss, 721 struct wlan_objmgr_vdev *vdev) 722 { 723 if (wlan_vdev_mlme_is_mlo_vdev(vdev)) { 724 qdf_debug("MLO vdev fill everything in mlo fill params"); 725 return; 726 } 727 728 conn_rsp->links[0].bssid = rsp->bssid.bytes; 729 conn_rsp->links[0].bss = bss; 730 } 731 #else 732 static 733 void osif_copy_connected_info(struct cfg80211_connect_resp_params *conn_rsp, 734 struct wlan_cm_connect_resp *rsp, 735 struct cfg80211_bss *bss, 736 struct wlan_objmgr_vdev *vdev) 737 { 738 conn_rsp->bssid = rsp->bssid.bytes; 739 conn_rsp->bss = bss; 740 } 741 #endif 742 743 /** 744 * osif_connect_done() - Wrapper API to call cfg80211_connect_done 745 * @dev: network device 746 * @bss: bss info 747 * @rsp: Connection manager connect response 748 * @vdev: pointer to vdev 749 * 750 * This API is used as wrapper to send connect status and params to 751 * supplicant. 752 * 753 * Context: Any context. 754 * Return: 0 if success. Error code for failure 755 */ 756 static int osif_connect_done(struct net_device *dev, struct cfg80211_bss *bss, 757 struct wlan_cm_connect_resp *rsp, 758 struct wlan_objmgr_vdev *vdev) 759 { 760 struct cfg80211_connect_resp_params conn_rsp_params; 761 enum ieee80211_statuscode status; 762 763 osif_enter_dev(dev); 764 765 status = osif_get_connect_status_code(rsp); 766 qdf_mem_zero(&conn_rsp_params, sizeof(conn_rsp_params)); 767 768 conn_rsp_params.status = status; 769 osif_copy_connected_info(&conn_rsp_params, rsp, bss, vdev); 770 conn_rsp_params.timeout_reason = 771 osif_convert_timeout_reason(rsp->reason); 772 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 773 &conn_rsp_params.req_ie_len, 774 &conn_rsp_params.req_ie); 775 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 776 &conn_rsp_params.resp_ie_len, 777 &conn_rsp_params.resp_ie); 778 osif_populate_fils_params(&conn_rsp_params, &rsp->connect_ies); 779 osif_cm_save_gtk(vdev, rsp); 780 781 if (status == WLAN_STATUS_SUCCESS) 782 osif_fill_connect_resp_mlo_params(vdev, rsp, bss, 783 &conn_rsp_params); 784 785 osif_debug("Connect resp status %d", conn_rsp_params.status); 786 787 cfg80211_connect_done(dev, &conn_rsp_params, qdf_mem_malloc_flags()); 788 osif_cm_set_hlp_data(dev, vdev, rsp); 789 790 osif_free_ml_link_params(&conn_rsp_params); 791 792 return 0; 793 } 794 #else /* CFG80211_CONNECT_DONE */ 795 static inline int 796 osif_connect_done(struct net_device *dev, struct cfg80211_bss *bss, 797 struct wlan_cm_connect_resp *rsp, 798 struct wlan_objmgr_vdev *vdev) 799 { 800 return -EINVAL; 801 } 802 #endif 803 804 #if (defined(CFG80211_CONNECT_DONE) || \ 805 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))) 806 /** 807 * osif_update_connect_results() - API to send connection status to 808 * supplicant. 809 * @dev: network device 810 * @bss: bss info 811 * @rsp: Connection manager connect response 812 * @vdev: pointer to vdev 813 * 814 * The API is a wrapper to send connection status to supplicant 815 * 816 * Context: Any context. 817 * Return: 0 if success else failure 818 */ 819 static int osif_update_connect_results(struct net_device *dev, 820 struct cfg80211_bss *bss, 821 struct wlan_cm_connect_resp *rsp, 822 struct wlan_objmgr_vdev *vdev) 823 { 824 return osif_connect_done(dev, bss, rsp, vdev); 825 } 826 #else /* CFG80211_CONNECT_DONE */ 827 828 static inline int osif_update_connect_results(struct net_device *dev, 829 struct cfg80211_bss *bss, 830 struct wlan_cm_connect_resp *rsp, 831 struct wlan_objmgr_vdev *vdev) 832 { 833 return -EINVAL; 834 } 835 #endif /* CFG80211_CONNECT_DONE */ 836 837 #ifdef WLAN_FEATURE_11BE_MLO 838 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 839 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 840 struct vdev_osif_priv *osif_priv, 841 struct wlan_cm_connect_resp *rsp) 842 { 843 struct cfg80211_bss *bss = NULL; 844 struct ieee80211_channel *chan; 845 int32_t akm; 846 847 if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) { 848 chan = ieee80211_get_channel(osif_priv->wdev->wiphy, 849 rsp->freq); 850 bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan, 851 rsp->bssid.bytes, 852 rsp->ssid.ssid, 853 rsp->ssid.length); 854 } 855 856 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) { 857 if (osif_update_connect_results(osif_priv->wdev->netdev, bss, 858 rsp, vdev)) 859 osif_connect_bss(osif_priv->wdev->netdev, bss, rsp); 860 return; 861 } 862 863 akm = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT); 864 if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev)) { 865 if (osif_update_connect_results( 866 osif_priv->wdev->netdev, bss, 867 rsp, vdev)) 868 osif_connect_bss(osif_priv->wdev->netdev, 869 bss, rsp); 870 } else if (osif_get_connect_status_code(rsp) == WLAN_STATUS_SUCCESS && 871 QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_OWE)) { 872 /* 873 * For OWE roaming, link vdev is disconnected on receiving 874 * roam synch indication. As part of the disconnect osif link 875 * info will be cleared and connect request is prepared from 876 * mlo roam module. 877 * So update OSIF Link info for that case here. 878 */ 879 mlo_mgr_osif_update_connect_info(vdev, 880 wlan_vdev_get_link_id(vdev)); 881 } 882 883 } 884 #else /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */ 885 886 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 213)) && \ 887 (LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0)) 888 /** 889 * osif_update_current_bss() - Wrapper API to call cfg80211_update_current_bss 890 * @dev: network device 891 * @bss: bss info 892 * @rsp: Connection manager connect response 893 * @vdev: pointer to vdev 894 * 895 * This API is used as wrapper to update the current bss param of non-assoc link 896 * sta vdev. 897 * 898 * Context: Any context. 899 * Return: QDF_STATUS. 900 */ 901 static QDF_STATUS osif_update_current_bss(struct net_device *dev, 902 struct cfg80211_bss *bss, 903 struct wlan_cm_connect_resp *rsp, 904 struct wlan_objmgr_vdev *vdev) 905 { 906 struct cfg80211_connect_resp_params conn_rsp_params; 907 enum ieee80211_statuscode status; 908 int ret; 909 910 osif_enter_dev(dev); 911 912 qdf_mem_zero(&conn_rsp_params, sizeof(conn_rsp_params)); 913 914 status = osif_get_connect_status_code(rsp); 915 conn_rsp_params.status = status; 916 osif_copy_connected_info(&conn_rsp_params, rsp, bss, vdev); 917 918 osif_debug("Connect resp status %d", conn_rsp_params.status); 919 ret = cfg80211_update_current_bss(dev, &conn_rsp_params, rsp->ssid.ssid, 920 rsp->ssid.length); 921 if (ret) 922 osif_err("cfg80211_update_current_bss failed for psoc:%d pdev:%d vdev:%d", 923 wlan_vdev_get_psoc_id(vdev), 924 wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev)), 925 wlan_vdev_get_id(vdev)); 926 927 return qdf_status_from_os_return(ret); 928 } 929 930 /** 931 * osif_update_current_bss_for_non_assoc_link_vdevs() - API to update the 932 * current_bss param of non-assoc link STA vdev. 933 * @vdev: Pointer to vdev 934 * @arg: Connection manager connect response 935 * 936 * Return: None. 937 */ 938 static void osif_update_current_bss_for_non_assoc_link_vdevs( 939 struct wlan_objmgr_vdev *vdev, void *arg) 940 { 941 struct wlan_objmgr_vdev *assoc_vdev; 942 struct wlan_cm_connect_resp resp = {0}; 943 struct qdf_mac_addr macaddr = {0}; 944 struct vdev_osif_priv *osif_priv = NULL; 945 struct wlan_cm_connect_resp *assoc_link_rsp; 946 947 assoc_link_rsp = (struct wlan_cm_connect_resp *)arg; 948 if (!assoc_link_rsp) { 949 osif_err("assoc_link_rsp is null"); 950 return; 951 } 952 953 assoc_vdev = wlan_mlo_get_assoc_link_vdev(vdev); 954 955 /* For assoc vdev cfg80211_connect_done() is called to update the 956 * current bss param. Hence, skip the assoc vdev here. 957 */ 958 if (vdev == assoc_vdev) 959 return; 960 961 wlan_vdev_mlme_get_ssid(vdev, resp.ssid.ssid, &resp.ssid.length); 962 963 wlan_vdev_get_bss_peer_mac(vdev, &macaddr); 964 qdf_mem_copy(resp.bssid.bytes, macaddr.bytes, QDF_MAC_ADDR_SIZE); 965 966 resp.connect_status = assoc_link_rsp->connect_status; 967 968 osif_debug("vdev:%p bssid:" QDF_MAC_ADDR_FMT " ssid.length:%d ssid: " QDF_SSID_FMT, 969 vdev, QDF_MAC_ADDR_REF(macaddr.bytes), resp.ssid.length, 970 QDF_SSID_REF(resp.ssid.length, resp.ssid.ssid)); 971 972 osif_priv = wlan_vdev_get_ospriv(vdev); 973 osif_update_current_bss(osif_priv->wdev->netdev, NULL, &resp, vdev); 974 } 975 976 /** 977 * osif_update_current_bss_for_non_assoc_links() - API to update the 978 * current_bss param of non-assoc link STA vdev. 979 * @assoc_vdev: Pointer to assoc vdev 980 * @rsp: Connection manager connect response 981 * 982 * Return: None. 983 */ 984 static void osif_update_current_bss_for_non_assoc_links( 985 struct wlan_objmgr_vdev *assoc_vdev, 986 struct wlan_cm_connect_resp *rsp) 987 { 988 mlo_iterate_connected_vdev_list( 989 assoc_vdev, 990 osif_update_current_bss_for_non_assoc_link_vdevs, 991 rsp); 992 } 993 #else 994 static void osif_update_current_bss_for_non_assoc_links( 995 struct wlan_objmgr_vdev *assoc_vdev, 996 struct wlan_cm_connect_resp *rsp) 997 { 998 } 999 #endif 1000 1001 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 1002 struct vdev_osif_priv *osif_priv, 1003 struct wlan_cm_connect_resp *rsp) 1004 { 1005 struct cfg80211_bss *bss = NULL; 1006 struct ieee80211_channel *chan; 1007 struct wlan_objmgr_vdev *assoc_vdev = NULL; 1008 struct vdev_osif_priv *tmp_osif_priv = NULL; 1009 qdf_freq_t freq; 1010 struct qdf_mac_addr macaddr = {0}; 1011 struct wlan_cm_connect_resp resp = {0}; 1012 1013 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) { 1014 if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) { 1015 chan = ieee80211_get_channel(osif_priv->wdev->wiphy, 1016 rsp->freq); 1017 bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, 1018 chan, 1019 rsp->bssid.bytes, 1020 rsp->ssid.ssid, 1021 rsp->ssid.length); 1022 } 1023 if (osif_update_connect_results(osif_priv->wdev->netdev, bss, 1024 rsp, vdev)) 1025 osif_connect_bss(osif_priv->wdev->netdev, bss, rsp); 1026 return; 1027 } 1028 1029 if ((QDF_IS_STATUS_SUCCESS(rsp->connect_status) && 1030 ucfg_mlo_is_mld_connected(vdev)) || 1031 (QDF_IS_STATUS_ERROR(rsp->connect_status) && 1032 ucfg_mlo_is_mld_disconnected(vdev))) { 1033 assoc_vdev = ucfg_mlo_get_assoc_link_vdev(vdev); 1034 if (!assoc_vdev) 1035 return; 1036 qdf_mem_copy(&resp, rsp, sizeof(struct wlan_cm_connect_resp)); 1037 tmp_osif_priv = wlan_vdev_get_ospriv(assoc_vdev); 1038 freq = assoc_vdev->vdev_mlme.bss_chan->ch_freq; 1039 qdf_mem_copy(macaddr.bytes, rsp->bssid.bytes, 1040 QDF_MAC_ADDR_SIZE); 1041 if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) { 1042 wlan_vdev_get_bss_peer_mac(assoc_vdev, &macaddr); 1043 chan = ieee80211_get_channel(tmp_osif_priv->wdev->wiphy, 1044 freq); 1045 bss = wlan_cfg80211_get_bss(tmp_osif_priv->wdev->wiphy, 1046 chan, 1047 macaddr.bytes, 1048 rsp->ssid.ssid, 1049 rsp->ssid.length); 1050 } 1051 qdf_mem_copy(resp.bssid.bytes, macaddr.bytes, 1052 QDF_MAC_ADDR_SIZE); 1053 resp.freq = freq; 1054 resp.connect_ies.assoc_req.ptr = rsp->connect_ies.assoc_req.ptr; 1055 resp.connect_ies.assoc_req.len = rsp->connect_ies.assoc_req.len; 1056 resp.connect_ies.assoc_rsp.ptr = rsp->connect_ies.assoc_rsp.ptr; 1057 resp.connect_ies.assoc_rsp.len = rsp->connect_ies.assoc_rsp.len; 1058 if (osif_update_connect_results(tmp_osif_priv->wdev->netdev, bss, 1059 &resp, assoc_vdev)) 1060 osif_connect_bss(tmp_osif_priv->wdev->netdev, bss, &resp); 1061 1062 if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) 1063 osif_update_current_bss_for_non_assoc_links(assoc_vdev, 1064 rsp); 1065 } 1066 } 1067 #endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */ 1068 #else /* WLAN_FEATURE_11BE_MLO */ 1069 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 1070 struct vdev_osif_priv *osif_priv, 1071 struct wlan_cm_connect_resp *rsp) 1072 { 1073 struct cfg80211_bss *bss = NULL; 1074 struct ieee80211_channel *chan; 1075 1076 if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) { 1077 chan = ieee80211_get_channel(osif_priv->wdev->wiphy, 1078 rsp->freq); 1079 bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan, 1080 rsp->bssid.bytes, 1081 rsp->ssid.ssid, 1082 rsp->ssid.length); 1083 } 1084 1085 if (osif_update_connect_results(osif_priv->wdev->netdev, bss, 1086 rsp, vdev)) 1087 osif_connect_bss(osif_priv->wdev->netdev, bss, rsp); 1088 } 1089 #endif /* WLAN_FEATURE_11BE_MLO */ 1090 #else /* CFG80211_CONNECT_BSS */ 1091 #ifdef WLAN_FEATURE_11BE_MLO 1092 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 1093 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 1094 struct vdev_osif_priv *osif_priv, 1095 struct wlan_cm_connect_resp *rsp) 1096 { 1097 enum ieee80211_statuscode status; 1098 size_t req_len = 0; 1099 const uint8_t *req_ptr = NULL; 1100 size_t rsp_len = 0; 1101 const uint8_t *rsp_ptr = NULL; 1102 struct wlan_objmgr_vdev *assoc_vdev = NULL; 1103 struct vdev_osif_priv *tmp_osif_priv = NULL; 1104 1105 status = osif_get_connect_status_code(rsp); 1106 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 1107 &req_len, &req_ptr); 1108 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 1109 &rsp_len, &rsp_ptr); 1110 if (wlan_vdev_mlme_is_mlo_vdev(vdev)) { 1111 if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev)) 1112 cfg80211_connect_result( 1113 osif_priv->wdev->netdev, 1114 rsp->bssid.bytes, req_ptr, req_len, 1115 rsp_ptr, rsp_len, status, 1116 qdf_mem_malloc_flags()); 1117 } else { 1118 cfg80211_connect_result(osif_priv->wdev->netdev, 1119 rsp->bssid.bytes, req_ptr, req_len, 1120 rsp_ptr, rsp_len, status, 1121 qdf_mem_malloc_flags()); 1122 } 1123 } 1124 #else /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */ 1125 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 1126 struct vdev_osif_priv *osif_priv, 1127 struct wlan_cm_connect_resp *rsp) 1128 { 1129 enum ieee80211_statuscode status; 1130 size_t req_len = 0; 1131 const uint8_t *req_ptr = NULL; 1132 size_t rsp_len = 0; 1133 const uint8_t *rsp_ptr = NULL; 1134 struct wlan_objmgr_vdev *assoc_vdev = NULL; 1135 struct vdev_osif_priv *tmp_osif_priv = NULL; 1136 struct qdf_mac_addr macaddr = {0}; 1137 1138 status = osif_get_connect_status_code(rsp); 1139 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 1140 &req_len, &req_ptr); 1141 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 1142 &rsp_len, &rsp_ptr); 1143 if (wlan_vdev_mlme_is_mlo_vdev(vdev)) { 1144 if ((QDF_IS_STATUS_SUCCESS(rsp->connect_status) && 1145 ucfg_mlo_is_mld_connected(vdev)) || 1146 (QDF_IS_STATUS_ERROR(rsp->connect_status) && 1147 ucfg_mlo_is_mld_disconnected(vdev))) { 1148 assoc_vdev = ucfg_mlo_get_assoc_link_vdev(vdev); 1149 if (!assoc_vdev) 1150 return; 1151 tmp_osif_priv = wlan_vdev_get_ospriv(assoc_vdev); 1152 wlan_vdev_get_bss_peer_mac(assoc_vdev, &macaddr); 1153 cfg80211_connect_result(tmp_osif_priv->wdev->netdev, 1154 macaddr.bytes, req_ptr, 1155 req_len, rsp_ptr, rsp_len, 1156 status, qdf_mem_malloc_flags()); 1157 } 1158 } else { 1159 cfg80211_connect_result(osif_priv->wdev->netdev, 1160 rsp->bssid.bytes, req_ptr, req_len, 1161 rsp_ptr, rsp_len, status, 1162 qdf_mem_malloc_flags()); 1163 } 1164 } 1165 #endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */ 1166 #else /* WLAN_FEATURE_11BE_MLO */ 1167 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev, 1168 struct vdev_osif_priv *osif_priv, 1169 struct wlan_cm_connect_resp *rsp) 1170 { 1171 enum ieee80211_statuscode status; 1172 size_t req_len = 0; 1173 const uint8_t *req_ptr = NULL; 1174 size_t rsp_len = 0; 1175 const uint8_t *rsp_ptr = NULL; 1176 1177 status = osif_get_connect_status_code(rsp); 1178 osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req, 1179 &req_len, &req_ptr); 1180 osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp, 1181 &rsp_len, &rsp_ptr); 1182 cfg80211_connect_result(osif_priv->wdev->netdev, 1183 rsp->bssid.bytes, req_ptr, req_len, 1184 rsp_ptr, rsp_len, status, 1185 qdf_mem_malloc_flags()); 1186 } 1187 #endif /* WLAN_FEATURE_11BE_MLO */ 1188 #endif /* CFG80211_CONNECT_BSS */ 1189 1190 #ifdef CONN_MGR_ADV_FEATURE 1191 static inline 1192 bool osif_cm_is_unlink_bss_required(struct wlan_cm_connect_resp *rsp) 1193 { 1194 if (QDF_IS_STATUS_SUCCESS(rsp->connect_status) || 1195 ucfg_cm_is_link_switch_connect_resp(rsp)) 1196 return false; 1197 1198 if (rsp->reason == CM_NO_CANDIDATE_FOUND || 1199 rsp->reason == CM_JOIN_TIMEOUT || 1200 rsp->reason == CM_AUTH_TIMEOUT || 1201 rsp->reason == CM_ASSOC_TIMEOUT) 1202 return true; 1203 1204 return false; 1205 } 1206 static inline void osif_check_and_unlink_bss(struct wlan_objmgr_vdev *vdev, 1207 struct wlan_cm_connect_resp *rsp) 1208 { 1209 if (osif_cm_is_unlink_bss_required(rsp)) 1210 osif_cm_unlink_bss(vdev, &rsp->bssid); 1211 } 1212 #else 1213 static inline void osif_check_and_unlink_bss(struct wlan_objmgr_vdev *vdev, 1214 struct wlan_cm_connect_resp *rsp) 1215 {} 1216 #endif 1217 1218 #define OSIF_CM_FAIL_INFO_STRING_SIZE 50 1219 1220 static inline void 1221 osif_dump_connect_rsp(struct wlan_objmgr_vdev *vdev, 1222 struct vdev_osif_priv *osif_priv, 1223 struct wlan_cm_connect_resp *rsp) 1224 { 1225 char fail_info[OSIF_CM_FAIL_INFO_STRING_SIZE] = {0}; 1226 1227 /* Fill status code and reason only on failure */ 1228 if (QDF_IS_STATUS_ERROR(rsp->connect_status)) 1229 qdf_scnprintf(fail_info, sizeof(fail_info), 1230 "reason %d status %d %s", 1231 rsp->reason, rsp->status_code, 1232 rsp->send_disconnect ? 1233 ", Send disconnect" : ""); 1234 1235 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", 1236 osif_priv->wdev->netdev->name, rsp->vdev_id, 1237 QDF_MAC_ADDR_REF(wlan_vdev_mlme_get_macaddr(vdev)), 1238 rsp->is_reassoc ? "Roam" : "Connect", 1239 QDF_MAC_ADDR_REF(rsp->bssid.bytes), 1240 QDF_SSID_REF(rsp->ssid.length, rsp->ssid.ssid), 1241 rsp->connect_status ? "FAILURE" : "SUCCESS", rsp->cm_id, 1242 fail_info); 1243 } 1244 1245 QDF_STATUS osif_connect_handler(struct wlan_objmgr_vdev *vdev, 1246 struct wlan_cm_connect_resp *rsp) 1247 { 1248 struct vdev_osif_priv *osif_priv = wlan_vdev_get_ospriv(vdev); 1249 QDF_STATUS status; 1250 1251 osif_dump_connect_rsp(vdev, osif_priv, rsp); 1252 osif_check_and_unlink_bss(vdev, rsp); 1253 1254 status = osif_validate_connect_and_reset_src_id(osif_priv, rsp); 1255 if (QDF_IS_STATUS_ERROR(status) || 1256 ucfg_cm_is_link_switch_connect_resp(rsp)) { 1257 osif_cm_connect_comp_ind(vdev, rsp, OSIF_NOT_HANDLED); 1258 return status; 1259 } 1260 1261 osif_cm_connect_comp_ind(vdev, rsp, OSIF_PRE_USERSPACE_UPDATE); 1262 1263 /* 1264 * To fix issue that scan with random address failed since wdev keeps 1265 * connected, rsp->send_disconnect is added. 1266 * Reproduce steps: 1267 * 1. Connect from OSIF success, wdev->connected = true; 1268 * 2. Disconnect from target if and reassoc from OSIF happens back to 1269 * back. 1270 * 3. Disconnect event is not sent to kernel, wdev->connected keeps 1271 * true, isn't cleared. 1272 * 4. Connect from OSIF failed too, wdev->connected keeps true, isn't 1273 * cleared. 1274 * 5. Scan with random address failed since wdev->connected is true. 1275 * 1276 * To fix it, if connect req was a reassoc req and received in not 1277 * connected state for race between disconnect from target if and 1278 * reassoc connect from OSIF, set reassoc_in_non_connected to send 1279 * disconnect instead of connect rsp to kernel to cleanup kernel flags 1280 * like: wdev->connected. 1281 */ 1282 if (rsp->is_reassoc) 1283 osif_indicate_reassoc_results(vdev, osif_priv, rsp); 1284 else if (rsp->send_disconnect && 1285 QDF_IS_STATUS_ERROR(rsp->connect_status)) 1286 osif_cm_indicate_disconnect(vdev, osif_priv->wdev->netdev, 1287 WLAN_REASON_UNSPECIFIED, 1288 false, NULL, 0, -1, 1289 qdf_mem_malloc_flags()); 1290 else 1291 osif_indcate_connect_results(vdev, osif_priv, rsp); 1292 osif_cm_connect_comp_ind(vdev, rsp, OSIF_POST_USERSPACE_UPDATE); 1293 1294 return QDF_STATUS_SUCCESS; 1295 } 1296 1297 QDF_STATUS osif_failed_candidate_handler(struct wlan_objmgr_vdev *vdev, 1298 struct wlan_cm_connect_resp *rsp) 1299 { 1300 struct vdev_osif_priv *osif_priv = wlan_vdev_get_ospriv(vdev); 1301 1302 osif_dump_connect_rsp(vdev, osif_priv, rsp); 1303 1304 /** 1305 * Do not unlink the BSS if it is an ML candidate. In case of ML, 1306 * failed candidate may be used as partner link while trying the 1307 * connection on other links. 1308 */ 1309 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) 1310 osif_check_and_unlink_bss(vdev, rsp); 1311 1312 return QDF_STATUS_SUCCESS; 1313 } 1314