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