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