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