xref: /wlan-dirver/qca-wifi-host-cmn/os_if/linux/mlme/src/osif_cm_connect_rsp.c (revision 70a19e16789e308182f63b15c75decec7bf0b342)
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