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