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