xref: /wlan-dirver/qca-wifi-host-cmn/os_if/linux/mlme/src/osif_cm_connect_rsp.c (revision 8b3dca18206e1a0461492f082fa6e270b092c035)
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 doesnt 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 	/* Increament 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 
500 	peer_obj = wlan_objmgr_get_peer_by_mac(wlan_vdev_get_psoc(vdev),
501 					       rsp->bssid.bytes, WLAN_OSIF_ID);
502 	if (!peer_obj)
503 		return QDF_STATUS_E_INVAL;
504 
505 	conn_rsp_params->ap_mld_addr = wlan_peer_mlme_get_mldaddr(peer_obj);
506 
507 	wlan_objmgr_peer_release_ref(peer_obj, WLAN_OSIF_ID);
508 
509 	return QDF_STATUS_SUCCESS;
510 }
511 
512 static void
513 osif_populate_partner_links_mlo_params(struct wlan_objmgr_pdev *pdev,
514 				       struct wlan_cm_connect_resp *rsp,
515 				       struct cfg80211_connect_resp_params *conn_rsp_params)
516 {
517 	struct wlan_objmgr_vdev *partner_vdev;
518 	struct mlo_link_info *rsp_partner_info;
519 	struct mlo_partner_info assoc_partner_info = {0};
520 	struct cfg80211_bss *bss = NULL;
521 	QDF_STATUS qdf_status;
522 	uint8_t link_id = 0, num_links;
523 	int i;
524 
525 	qdf_status = osif_get_partner_info_from_mlie(rsp, &assoc_partner_info);
526 	if (QDF_IS_STATUS_ERROR(qdf_status))
527 		return;
528 
529 	num_links = rsp->ml_parnter_info.num_partner_links;
530 	for (i = 0 ; i < num_links; i++) {
531 		rsp_partner_info = &rsp->ml_parnter_info.partner_link_info[i];
532 
533 		qdf_status = osif_get_link_id_from_assoc_ml_ie(rsp_partner_info,
534 							    &assoc_partner_info,
535 							    &link_id);
536 		if (QDF_IS_STATUS_ERROR(qdf_status))
537 			continue;
538 
539 		partner_vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev,
540 						      rsp_partner_info->vdev_id,
541 						      WLAN_MLO_MGR_ID);
542 		if (!partner_vdev)
543 			continue;
544 
545 		bss = osif_get_chan_bss_from_kernel(partner_vdev,
546 						    rsp_partner_info, rsp);
547 		if (!bss) {
548 			wlan_objmgr_vdev_release_ref(partner_vdev,
549 						     WLAN_MLO_MGR_ID);
550 			continue;
551 		}
552 
553 		osif_populate_connect_response_for_link(partner_vdev,
554 							conn_rsp_params,
555 							link_id, bss);
556 		wlan_objmgr_vdev_release_ref(partner_vdev, WLAN_MLO_MGR_ID);
557 	}
558 }
559 
560 static void osif_fill_connect_resp_mlo_params(struct wlan_objmgr_vdev *vdev,
561 					      struct wlan_cm_connect_resp *rsp,
562 					      struct cfg80211_bss *bss,
563 					      struct cfg80211_connect_resp_params *conn_rsp_params)
564 {
565 	uint8_t assoc_link_id;
566 	QDF_STATUS qdf_status;
567 
568 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
569 		return;
570 
571 	qdf_status = osif_fill_peer_mld_mac_connect_resp(vdev, rsp,
572 							 conn_rsp_params);
573 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
574 		osif_err("Unable to fill peer mld address: %d", qdf_status);
575 		return;
576 	}
577 
578 	assoc_link_id = wlan_vdev_get_link_id(vdev);
579 	osif_populate_connect_response_for_link(vdev, conn_rsp_params,
580 						assoc_link_id, bss);
581 
582 	osif_populate_partner_links_mlo_params(wlan_vdev_get_pdev(vdev), rsp,
583 					       conn_rsp_params);
584 }
585 
586 static void
587 osif_free_ml_link_params(struct cfg80211_connect_resp_params *conn_rsp_params)
588 {
589 }
590 #elif defined(CFG80211_IFTYPE_MLO_LINK_SUPPORT) && defined(WLAN_FEATURE_11BE_MLO)
591 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
592 static struct wlan_objmgr_vdev *osif_get_partner_vdev(
593 					struct wlan_objmgr_vdev *vdev,
594 					struct mlo_link_info rsp_partner_info)
595 {
596 	return wlan_objmgr_get_vdev_by_id_from_pdev(
597 						vdev->vdev_objmgr.wlan_pdev,
598 						rsp_partner_info.vdev_id,
599 						WLAN_MLO_MGR_ID);
600 }
601 #else
602 static struct wlan_objmgr_vdev *osif_get_partner_vdev(
603 					struct wlan_objmgr_vdev *vdev,
604 					struct mlo_link_info rsp_partner_info)
605 {
606 	return mlo_get_vdev_by_link_id(vdev, rsp_partner_info.link_id);
607 }
608 #endif
609 static void osif_fill_connect_resp_mlo_params(
610 			struct wlan_objmgr_vdev *vdev,
611 			struct wlan_cm_connect_resp *rsp,
612 			struct cfg80211_bss *bss,
613 			struct cfg80211_connect_resp_params *conn_rsp_params)
614 {
615 	uint8_t i, num_mlo_links = rsp->ml_parnter_info.num_partner_links + 1;
616 	struct wlan_objmgr_vdev *ml_vdev = vdev;
617 	struct vdev_osif_priv *osif_priv;
618 	struct ieee80211_channel *chan;
619 	struct cfg80211_mlo_link_params *ml_link_params;
620 	struct mlo_link_info *rsp_partner_info;
621 
622 	if (num_mlo_links == 1)
623 		return;
624 
625 	ml_link_params = qdf_mem_malloc(
626 				num_mlo_links * sizeof(*ml_link_params));
627 	if (!ml_link_params)
628 		return;
629 
630 	rsp_partner_info = rsp->ml_parnter_info.partner_link_info;
631 	if (rsp->ml_parnter_info.num_partner_links) {
632 		conn_rsp_params->n_mlo_links = num_mlo_links;
633 		osif_priv = wlan_vdev_get_ospriv(ml_vdev);
634 		for (i = 0; i < conn_rsp_params->n_mlo_links; i++) {
635 			ml_link_params[i].wdev = osif_priv->wdev;
636 
637 			if (i != 0) {
638 				chan = ieee80211_get_channel(
639 					   osif_priv->wdev->wiphy,
640 					   rsp_partner_info[i - 1].chan_freq);
641 				if (!chan) {
642 					osif_err("Invalid partner channel");
643 					goto end;
644 				}
645 
646 				bss = wlan_cfg80211_get_bss(
647 					osif_priv->wdev->wiphy, chan,
648 					rsp_partner_info[i - 1].link_addr.bytes,
649 					rsp->ssid.ssid, rsp->ssid.length);
650 				if (!bss) {
651 					osif_err("Partner bss is null");
652 					goto end;
653 				}
654 			}
655 			qdf_mem_copy(ml_link_params[i].bssid, bss->bssid,
656 				     QDF_MAC_ADDR_SIZE);
657 
658 			if (i == rsp->ml_parnter_info.num_partner_links)
659 				break;
660 
661 			ml_vdev = osif_get_partner_vdev(vdev,
662 							rsp_partner_info[i]);
663 
664 			if (ml_vdev) {
665 				osif_priv = wlan_vdev_get_ospriv(ml_vdev);
666 				wlan_objmgr_vdev_release_ref(ml_vdev,
667 							     WLAN_MLO_MGR_ID);
668 			} else {
669 				osif_err("Partner vdev not found with vdev_id:%d",
670 					 rsp_partner_info[i].vdev_id);
671 				goto end;
672 			}
673 		}
674 	}
675 end:
676 	conn_rsp_params->mlo_links = ml_link_params;
677 }
678 
679 static void
680 osif_free_ml_link_params(struct cfg80211_connect_resp_params *conn_rsp_params)
681 {
682 	struct cfg80211_mlo_link_params *ml_links;
683 
684 	ml_links =
685 		(struct cfg80211_mlo_link_params *)conn_rsp_params->mlo_links;
686 	if (ml_links)
687 		qdf_mem_free(ml_links);
688 }
689 
690 #else
691 static void osif_fill_connect_resp_mlo_params(
692 			struct wlan_objmgr_vdev *vdev,
693 			struct wlan_cm_connect_resp *rsp,
694 			struct cfg80211_bss *bss,
695 			struct cfg80211_connect_resp_params *conn_rsp_params)
696 {
697 }
698 
699 static void
700 osif_free_ml_link_params(struct cfg80211_connect_resp_params *conn_rsp_params)
701 {
702 }
703 #endif
704 
705 #ifdef CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT
706 static
707 void osif_copy_connected_info(struct cfg80211_connect_resp_params *conn_rsp,
708 			      struct wlan_cm_connect_resp *rsp,
709 			      struct cfg80211_bss *bss,
710 			      struct wlan_objmgr_vdev *vdev)
711 {
712 	if (wlan_vdev_mlme_is_mlo_vdev(vdev)) {
713 		qdf_debug("MLO vdev fill everything in mlo fill params");
714 		return;
715 	}
716 
717 	conn_rsp->links[0].bssid = rsp->bssid.bytes;
718 	conn_rsp->links[0].bss = bss;
719 }
720 #else
721 static
722 void osif_copy_connected_info(struct cfg80211_connect_resp_params *conn_rsp,
723 			      struct wlan_cm_connect_resp *rsp,
724 			      struct cfg80211_bss *bss,
725 			      struct wlan_objmgr_vdev *vdev)
726 {
727 	conn_rsp->bssid = rsp->bssid.bytes;
728 	conn_rsp->bss = bss;
729 }
730 #endif
731 
732 /**
733  * osif_connect_done() - Wrapper API to call cfg80211_connect_done
734  * @dev: network device
735  * @bss: bss info
736  * @rsp: Connection manager connect response
737  * @vdev: pointer to vdev
738  *
739  * This API is used as wrapper to send connect status and params to
740  * supplicant.
741  *
742  * Context: Any context.
743  * Return: 0 if success. Error code for failure
744  */
745 static int osif_connect_done(struct net_device *dev, struct cfg80211_bss *bss,
746 			     struct wlan_cm_connect_resp *rsp,
747 			     struct wlan_objmgr_vdev *vdev)
748 {
749 	struct cfg80211_connect_resp_params conn_rsp_params;
750 	enum ieee80211_statuscode status;
751 
752 	osif_enter_dev(dev);
753 
754 	status = osif_get_connect_status_code(rsp);
755 	qdf_mem_zero(&conn_rsp_params, sizeof(conn_rsp_params));
756 
757 	conn_rsp_params.status = status;
758 	osif_copy_connected_info(&conn_rsp_params, rsp, bss, vdev);
759 	conn_rsp_params.timeout_reason =
760 			osif_convert_timeout_reason(rsp->reason);
761 	osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req,
762 				      &conn_rsp_params.req_ie_len,
763 				      &conn_rsp_params.req_ie);
764 	osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp,
765 				      &conn_rsp_params.resp_ie_len,
766 				      &conn_rsp_params.resp_ie);
767 	osif_populate_fils_params(&conn_rsp_params, &rsp->connect_ies);
768 	osif_cm_save_gtk(vdev, rsp);
769 
770 	if (status == WLAN_STATUS_SUCCESS)
771 		osif_fill_connect_resp_mlo_params(vdev, rsp, bss,
772 						  &conn_rsp_params);
773 
774 	osif_debug("Connect resp status  %d", conn_rsp_params.status);
775 
776 	cfg80211_connect_done(dev, &conn_rsp_params, qdf_mem_malloc_flags());
777 	osif_cm_set_hlp_data(dev, vdev, rsp);
778 
779 	osif_free_ml_link_params(&conn_rsp_params);
780 
781 	return 0;
782 }
783 #else /* CFG80211_CONNECT_DONE */
784 static inline int
785 osif_connect_done(struct net_device *dev, struct cfg80211_bss *bss,
786 		  struct wlan_cm_connect_resp *rsp,
787 		  struct wlan_objmgr_vdev *vdev)
788 {
789 	return -EINVAL;
790 }
791 #endif
792 
793 #if (defined(CFG80211_CONNECT_DONE) || \
794 	(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)))
795 /**
796  * osif_update_connect_results() - API to send connection status to
797  * supplicant.
798  * @dev: network device
799  * @bss: bss info
800  * @connect_rsp: Connection manager connect response
801  * @vdev: pointer to vdev
802  *
803  * The API is a wrapper to send connection status to supplicant
804  *
805  * Context: Any context.
806  * Return: 0 if success else failure
807  */
808 static int osif_update_connect_results(struct net_device *dev,
809 				       struct cfg80211_bss *bss,
810 				       struct wlan_cm_connect_resp *rsp,
811 				       struct wlan_objmgr_vdev *vdev)
812 {
813 	return osif_connect_done(dev, bss, rsp, vdev);
814 }
815 #else /* CFG80211_CONNECT_DONE */
816 
817 static inline int osif_update_connect_results(struct net_device *dev,
818 					      struct cfg80211_bss *bss,
819 					      struct wlan_cm_connect_resp *rsp,
820 					      struct wlan_objmgr_vdev *vdev)
821 {
822 	return -EINVAL;
823 }
824 #endif /* CFG80211_CONNECT_DONE */
825 
826 #ifdef WLAN_FEATURE_11BE_MLO
827 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
828 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev,
829 					 struct vdev_osif_priv *osif_priv,
830 					 struct wlan_cm_connect_resp *rsp)
831 {
832 	struct cfg80211_bss *bss = NULL;
833 	struct ieee80211_channel *chan;
834 
835 	if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) {
836 		chan = ieee80211_get_channel(osif_priv->wdev->wiphy,
837 					     rsp->freq);
838 		bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan,
839 					    rsp->bssid.bytes,
840 					    rsp->ssid.ssid,
841 					    rsp->ssid.length);
842 	}
843 
844 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
845 		if (osif_update_connect_results(osif_priv->wdev->netdev, bss,
846 						rsp, vdev))
847 			osif_connect_bss(osif_priv->wdev->netdev, bss, rsp);
848 		return;
849 	}
850 
851 	if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev)) {
852 		if (osif_update_connect_results(
853 				osif_priv->wdev->netdev, bss,
854 				rsp, vdev))
855 			osif_connect_bss(osif_priv->wdev->netdev,
856 					 bss, rsp);
857 	}
858 
859 }
860 #else /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */
861 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev,
862 					 struct vdev_osif_priv *osif_priv,
863 					 struct wlan_cm_connect_resp *rsp)
864 {
865 	struct cfg80211_bss *bss = NULL;
866 	struct ieee80211_channel *chan;
867 	struct wlan_objmgr_vdev *assoc_vdev = NULL;
868 	struct vdev_osif_priv *tmp_osif_priv = NULL;
869 	qdf_freq_t freq;
870 	struct qdf_mac_addr macaddr = {0};
871 	struct wlan_cm_connect_resp resp = {0};
872 
873 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
874 		if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) {
875 			chan = ieee80211_get_channel(osif_priv->wdev->wiphy,
876 						     rsp->freq);
877 			bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy,
878 						    chan,
879 						    rsp->bssid.bytes,
880 						    rsp->ssid.ssid,
881 						    rsp->ssid.length);
882 		}
883 		if (osif_update_connect_results(osif_priv->wdev->netdev, bss,
884 						rsp, vdev))
885 			osif_connect_bss(osif_priv->wdev->netdev, bss, rsp);
886 		return;
887 	}
888 
889 	if ((QDF_IS_STATUS_SUCCESS(rsp->connect_status) &&
890 	    ucfg_mlo_is_mld_connected(vdev)) ||
891 	    (QDF_IS_STATUS_ERROR(rsp->connect_status) &&
892 	    ucfg_mlo_is_mld_disconnected(vdev))) {
893 		assoc_vdev = ucfg_mlo_get_assoc_link_vdev(vdev);
894 		if (!assoc_vdev)
895 			return;
896 		qdf_mem_copy(&resp, rsp, sizeof(struct wlan_cm_connect_resp));
897 		tmp_osif_priv  = wlan_vdev_get_ospriv(assoc_vdev);
898 		freq = vdev->vdev_mlme.bss_chan->ch_freq;
899 		wlan_vdev_get_bss_peer_mac(assoc_vdev, &macaddr);
900 		if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) {
901 			chan = ieee80211_get_channel(tmp_osif_priv->wdev->wiphy,
902 						     freq);
903 			bss = wlan_cfg80211_get_bss(tmp_osif_priv->wdev->wiphy,
904 						    chan,
905 						    macaddr.bytes,
906 						    rsp->ssid.ssid,
907 						    rsp->ssid.length);
908 		}
909 		qdf_mem_copy(resp.bssid.bytes, macaddr.bytes,
910 			     QDF_MAC_ADDR_SIZE);
911 		resp.freq = freq;
912 		resp.connect_ies.assoc_req.ptr = rsp->connect_ies.assoc_req.ptr;
913 		resp.connect_ies.assoc_req.len = rsp->connect_ies.assoc_req.len;
914 		resp.connect_ies.assoc_rsp.ptr = rsp->connect_ies.assoc_rsp.ptr;
915 		resp.connect_ies.assoc_rsp.len = rsp->connect_ies.assoc_rsp.len;
916 		if (osif_update_connect_results(tmp_osif_priv->wdev->netdev, bss,
917 						&resp, assoc_vdev))
918 			osif_connect_bss(tmp_osif_priv->wdev->netdev, bss, &resp);
919 	}
920 }
921 #endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */
922 #else /* WLAN_FEATURE_11BE_MLO */
923 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev,
924 					 struct vdev_osif_priv *osif_priv,
925 					 struct wlan_cm_connect_resp *rsp)
926 {
927 	struct cfg80211_bss *bss = NULL;
928 	struct ieee80211_channel *chan;
929 
930 	if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) {
931 		chan = ieee80211_get_channel(osif_priv->wdev->wiphy,
932 					     rsp->freq);
933 		bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan,
934 					    rsp->bssid.bytes,
935 					    rsp->ssid.ssid,
936 					    rsp->ssid.length);
937 	}
938 
939 	if (osif_update_connect_results(osif_priv->wdev->netdev, bss,
940 					rsp, vdev))
941 		osif_connect_bss(osif_priv->wdev->netdev, bss, rsp);
942 }
943 #endif /* WLAN_FEATURE_11BE_MLO */
944 #else  /* CFG80211_CONNECT_BSS */
945 #ifdef WLAN_FEATURE_11BE_MLO
946 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
947 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev,
948 					 struct vdev_osif_priv *osif_priv,
949 					 struct wlan_cm_connect_resp *rsp)
950 {
951 	enum ieee80211_statuscode status;
952 	size_t req_len = 0;
953 	const uint8_t *req_ptr = NULL;
954 	size_t rsp_len = 0;
955 	const uint8_t *rsp_ptr = NULL;
956 	struct wlan_objmgr_vdev *assoc_vdev = NULL;
957 	struct vdev_osif_priv *tmp_osif_priv = NULL;
958 
959 	status = osif_get_connect_status_code(rsp);
960 	osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req,
961 				      &req_len, &req_ptr);
962 	osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp,
963 				      &rsp_len, &rsp_ptr);
964 	if (wlan_vdev_mlme_is_mlo_vdev(vdev)) {
965 		if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev))
966 			cfg80211_connect_result(
967 				osif_priv->wdev->netdev,
968 				rsp->bssid.bytes, req_ptr, req_len,
969 				rsp_ptr, rsp_len, status,
970 				qdf_mem_malloc_flags());
971 	} else {
972 		cfg80211_connect_result(osif_priv->wdev->netdev,
973 					rsp->bssid.bytes, req_ptr, req_len,
974 					rsp_ptr, rsp_len, status,
975 					qdf_mem_malloc_flags());
976 	}
977 }
978 #else /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */
979 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev,
980 					 struct vdev_osif_priv *osif_priv,
981 					 struct wlan_cm_connect_resp *rsp)
982 {
983 	enum ieee80211_statuscode status;
984 	size_t req_len = 0;
985 	const uint8_t *req_ptr = NULL;
986 	size_t rsp_len = 0;
987 	const uint8_t *rsp_ptr = NULL;
988 	struct wlan_objmgr_vdev *assoc_vdev = NULL;
989 	struct vdev_osif_priv *tmp_osif_priv = NULL;
990 	struct qdf_mac_addr macaddr = {0};
991 
992 	status = osif_get_connect_status_code(rsp);
993 	osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req,
994 				      &req_len, &req_ptr);
995 	osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp,
996 				      &rsp_len, &rsp_ptr);
997 	if (wlan_vdev_mlme_is_mlo_vdev(vdev)) {
998 		if ((QDF_IS_STATUS_SUCCESS(rsp->connect_status) &&
999 		    ucfg_mlo_is_mld_connected(vdev)) ||
1000 		    (QDF_IS_STATUS_ERROR(rsp->connect_status) &&
1001 		    ucfg_mlo_is_mld_disconnected(vdev))) {
1002 			assoc_vdev = ucfg_mlo_get_assoc_link_vdev(vdev);
1003 			if (!assoc_vdev)
1004 				return;
1005 			tmp_osif_priv  = wlan_vdev_get_ospriv(assoc_vdev);
1006 			wlan_vdev_get_bss_peer_mac(assoc_vdev, &macaddr);
1007 			cfg80211_connect_result(tmp_osif_priv->wdev->netdev,
1008 						macaddr.bytes, req_ptr,
1009 						req_len, rsp_ptr, rsp_len,
1010 						status, qdf_mem_malloc_flags());
1011 		}
1012 	} else {
1013 		cfg80211_connect_result(osif_priv->wdev->netdev,
1014 					rsp->bssid.bytes, req_ptr, req_len,
1015 					rsp_ptr, rsp_len, status,
1016 					qdf_mem_malloc_flags());
1017 	}
1018 }
1019 #endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */
1020 #else /* WLAN_FEATURE_11BE_MLO */
1021 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev,
1022 					 struct vdev_osif_priv *osif_priv,
1023 					 struct wlan_cm_connect_resp *rsp)
1024 {
1025 	enum ieee80211_statuscode status;
1026 	size_t req_len = 0;
1027 	const uint8_t *req_ptr = NULL;
1028 	size_t rsp_len = 0;
1029 	const uint8_t *rsp_ptr = NULL;
1030 
1031 	status = osif_get_connect_status_code(rsp);
1032 	osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req,
1033 				      &req_len, &req_ptr);
1034 	osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp,
1035 				      &rsp_len, &rsp_ptr);
1036 	cfg80211_connect_result(osif_priv->wdev->netdev,
1037 				rsp->bssid.bytes, req_ptr, req_len,
1038 				rsp_ptr, rsp_len, status,
1039 				qdf_mem_malloc_flags());
1040 }
1041 #endif /* WLAN_FEATURE_11BE_MLO */
1042 #endif /* CFG80211_CONNECT_BSS */
1043 
1044 #ifdef CONN_MGR_ADV_FEATURE
1045 static inline
1046 bool osif_cm_is_unlink_bss_required(struct wlan_cm_connect_resp *rsp)
1047 {
1048 	if (QDF_IS_STATUS_SUCCESS(rsp->connect_status))
1049 		return false;
1050 
1051 	if (rsp->reason == CM_NO_CANDIDATE_FOUND ||
1052 	    rsp->reason == CM_JOIN_TIMEOUT ||
1053 	    rsp->reason == CM_AUTH_TIMEOUT ||
1054 	    rsp->reason == CM_ASSOC_TIMEOUT)
1055 		return true;
1056 
1057 	return false;
1058 }
1059 static inline void osif_check_and_unlink_bss(struct wlan_objmgr_vdev *vdev,
1060 					     struct vdev_osif_priv *osif_priv,
1061 					     struct wlan_cm_connect_resp *rsp)
1062 {
1063 	if (osif_cm_is_unlink_bss_required(rsp))
1064 		osif_cm_unlink_bss(vdev, osif_priv, &rsp->bssid, rsp->ssid.ssid,
1065 				   rsp->ssid.length);
1066 }
1067 #else
1068 static inline void osif_check_and_unlink_bss(struct wlan_objmgr_vdev *vdev,
1069 					     struct vdev_osif_priv *osif_priv,
1070 					     struct wlan_cm_connect_resp *rsp)
1071 {}
1072 #endif
1073 
1074 QDF_STATUS osif_connect_handler(struct wlan_objmgr_vdev *vdev,
1075 				struct wlan_cm_connect_resp *rsp)
1076 {
1077 	struct vdev_osif_priv *osif_priv  = wlan_vdev_get_ospriv(vdev);
1078 	QDF_STATUS status;
1079 
1080 	osif_nofl_info("%s(vdevid-%d): " QDF_MAC_ADDR_FMT " Connect with " QDF_MAC_ADDR_FMT " SSID \"%.*s\" is %s cm_id 0x%x cm_reason %d status_code %d is_reassoc %d send discon %d",
1081 		       osif_priv->wdev->netdev->name, rsp->vdev_id,
1082 		       QDF_MAC_ADDR_REF(wlan_vdev_mlme_get_macaddr(vdev)),
1083 		       QDF_MAC_ADDR_REF(rsp->bssid.bytes),
1084 		       rsp->ssid.length, rsp->ssid.ssid,
1085 		       rsp->connect_status ? "FAILURE" : "SUCCESS", rsp->cm_id,
1086 		       rsp->reason, rsp->status_code, rsp->is_reassoc,
1087 		       rsp->send_disconnect);
1088 
1089 	osif_check_and_unlink_bss(vdev, osif_priv, rsp);
1090 
1091 	status = osif_validate_connect_and_reset_src_id(osif_priv, rsp);
1092 	if (QDF_IS_STATUS_ERROR(status)) {
1093 		osif_cm_connect_comp_ind(vdev, rsp, OSIF_NOT_HANDLED);
1094 		return status;
1095 	}
1096 
1097 	osif_cm_connect_comp_ind(vdev, rsp, OSIF_PRE_USERSPACE_UPDATE);
1098 
1099 	/*
1100 	 * To fix issue that scan with random address failed since wdev keeps
1101 	 * connected, rsp->send_disconnect is added.
1102 	 * Reproduce steps:
1103 	 *  1.  Connect from OSIF success, wdev->connected = true;
1104 	 *  2.  Disconnect from target if and reassoc from OSIF happens back to
1105 	 *	back.
1106 	 *  3.  Disconnect event is not sent to kernel, wdev->connected keeps
1107 	 *	true, isn't cleared.
1108 	 *  4.  Connect from OSIF failed too, wdev->connected keeps true,  isn't
1109 	 *	cleared.
1110 	 *  5.  Scan with random address failed since wdev->connected is true.
1111 	 *
1112 	 * To fix it, if connect req was a reassoc req and received in not
1113 	 * connected state for race between disconnect from target if and
1114 	 * reassoc connect from OSIF, set reassoc_in_non_connected to send
1115 	 * disconnect instead of connect rsp to kernel to cleanup kernel flags
1116 	 * like: wdev->connected.
1117 	 */
1118 	if (rsp->is_reassoc)
1119 		osif_indicate_reassoc_results(vdev, osif_priv, rsp);
1120 	else if (rsp->send_disconnect &&
1121 		 QDF_IS_STATUS_ERROR(rsp->connect_status))
1122 		osif_cm_indicate_disconnect(vdev, osif_priv->wdev->netdev,
1123 					    WLAN_REASON_UNSPECIFIED,
1124 					    false, NULL, 0,
1125 					    qdf_mem_malloc_flags());
1126 	else
1127 		osif_indcate_connect_results(vdev, osif_priv, rsp);
1128 	osif_cm_connect_comp_ind(vdev, rsp, OSIF_POST_USERSPACE_UPDATE);
1129 
1130 	return QDF_STATUS_SUCCESS;
1131 }
1132 
1133 QDF_STATUS osif_failed_candidate_handler(struct wlan_objmgr_vdev *vdev,
1134 					 struct wlan_cm_connect_resp *rsp)
1135 {
1136 	struct vdev_osif_priv *osif_priv  = wlan_vdev_get_ospriv(vdev);
1137 
1138 	osif_nofl_info("%s(vdevid-%d): " QDF_MAC_ADDR_FMT " Connect with " QDF_MAC_ADDR_FMT " SSID \"%.*s\" FAILED cm_id 0x%x cm_reason %d reason_code %d",
1139 		       osif_priv->wdev->netdev->name, rsp->vdev_id,
1140 		       QDF_MAC_ADDR_REF(wlan_vdev_mlme_get_macaddr(vdev)),
1141 		       QDF_MAC_ADDR_REF(rsp->bssid.bytes),
1142 		       rsp->ssid.length, rsp->ssid.ssid, rsp->cm_id,
1143 		       rsp->reason, rsp->status_code);
1144 
1145 	/**
1146 	 * Do not unlink the BSS if it is an ML candidate. In case of ML,
1147 	 * failed candidate may be used as partner link while trying the
1148 	 * connection on other links.
1149 	 */
1150 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
1151 		osif_check_and_unlink_bss(vdev, osif_priv, rsp);
1152 
1153 	return QDF_STATUS_SUCCESS;
1154 }
1155