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