xref: /wlan-dirver/qca-wifi-host-cmn/os_if/linux/mlme/src/osif_cm_connect_rsp.c (revision 2f4b444fb7e689b83a4ab0e7b3b38f0bf4def8e0)
1 /*
2  * Copyright (c) 2012-2015, 2020-2021 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /**
18  * DOC: osif_cm_connect_rsp.c
19  *
20  * This file maintains definitaions of connect response apis.
21  */
22 
23 #include <linux/version.h>
24 #include <linux/nl80211.h>
25 #include <net/cfg80211.h>
26 #include "wlan_osif_priv.h"
27 #include "osif_cm_rsp.h"
28 #include "osif_cm_util.h"
29 #include "wlan_cfg80211.h"
30 #include "wlan_cfg80211_scan.h"
31 #include "wlan_mlo_mgr_sta.h"
32 
33 #ifdef CONN_MGR_ADV_FEATURE
34 void osif_cm_get_assoc_req_ie_data(struct element_info *assoc_req,
35 				   size_t *ie_data_len,
36 				   const uint8_t **ie_data_ptr)
37 {
38 	/* Validate IE and length */
39 	if (!assoc_req->len || !assoc_req->ptr ||
40 	    assoc_req->len <= WLAN_ASSOC_REQ_IES_OFFSET)
41 		return;
42 
43 	*ie_data_len = assoc_req->len - WLAN_ASSOC_REQ_IES_OFFSET;
44 	*ie_data_ptr = assoc_req->ptr + WLAN_ASSOC_REQ_IES_OFFSET;
45 }
46 #else
47 void osif_cm_get_assoc_req_ie_data(struct element_info *assoc_req,
48 				   size_t *ie_data_len,
49 				   const uint8_t **ie_data_ptr)
50 {
51 	/* Validate IE and length */
52 	if (!assoc_req->len || !assoc_req->ptr)
53 		return;
54 
55 	*ie_data_len = assoc_req->len;
56 	*ie_data_ptr = assoc_req->ptr;
57 }
58 #endif
59 
60 void osif_cm_get_assoc_rsp_ie_data(struct element_info *assoc_rsp,
61 				   size_t *ie_data_len,
62 				   const uint8_t **ie_data_ptr)
63 {
64 	/* Validate IE and length */
65 	if (!assoc_rsp->len || !assoc_rsp->ptr ||
66 	    assoc_rsp->len <= WLAN_ASSOC_RSP_IES_OFFSET)
67 		return;
68 
69 	*ie_data_len = assoc_rsp->len - WLAN_ASSOC_RSP_IES_OFFSET;
70 	*ie_data_ptr = assoc_rsp->ptr + WLAN_ASSOC_RSP_IES_OFFSET;
71 }
72 
73 /**
74  * osif_validate_connect_and_reset_src_id() - Validate connect response and
75  * resets source and id
76  * @osif_priv: Pointer to vdev osif priv
77  * @rsp: Connection manager connect response
78  *
79  * This function validates connect response and if the connect
80  * response is valid, resets the source and id of the command
81  *
82  * Context: Any context. Takes and releases cmd id spinlock.
83  * Return: QDF_STATUS
84  */
85 static QDF_STATUS
86 osif_validate_connect_and_reset_src_id(struct vdev_osif_priv *osif_priv,
87 				       struct wlan_cm_connect_resp *rsp)
88 {
89 	QDF_STATUS status = QDF_STATUS_SUCCESS;
90 
91 	/*
92 	 * Do not send to kernel if last osif cookie doesnt match or
93 	 * or source is CM_OSIF_CFG_CONNECT with success status.
94 	 * If cookie matches reset the cookie and source.
95 	 */
96 	qdf_spinlock_acquire(&osif_priv->cm_info.cmd_id_lock);
97 	if (rsp->cm_id != osif_priv->cm_info.last_id ||
98 	    (osif_priv->cm_info.last_source == CM_OSIF_CFG_CONNECT &&
99 	     QDF_IS_STATUS_SUCCESS(rsp->connect_status))) {
100 		osif_debug("Ignore as cm_id(0x%x)/src(%d) != cm_id(0x%x)/src(%d) OR source is CFG connect with status %d",
101 			   rsp->cm_id, CM_OSIF_CONNECT,
102 			   osif_priv->cm_info.last_id,
103 			   osif_priv->cm_info.last_source,
104 			   rsp->connect_status);
105 		status = QDF_STATUS_E_INVAL;
106 		goto rel_lock;
107 	}
108 
109 	osif_cm_reset_id_and_src_no_lock(osif_priv);
110 rel_lock:
111 	qdf_spinlock_release(&osif_priv->cm_info.cmd_id_lock);
112 
113 	return status;
114 }
115 
116 static enum ieee80211_statuscode
117 osif_get_statuscode(enum wlan_status_code status)
118 {
119 	return (enum ieee80211_statuscode)status;
120 }
121 
122 static enum ieee80211_statuscode
123 osif_get_connect_status_code(struct wlan_cm_connect_resp *rsp)
124 {
125 	enum ieee80211_statuscode status = WLAN_STATUS_SUCCESS;
126 
127 	if (QDF_IS_STATUS_ERROR(rsp->connect_status)) {
128 		if (rsp->status_code)
129 			status = osif_get_statuscode(rsp->status_code);
130 		else
131 			status = WLAN_STATUS_UNSPECIFIED_FAILURE;
132 	}
133 
134 	return status;
135 }
136 
137 /**
138  * osif_convert_timeout_reason() - Convert to kernel specific enum
139  * @timeout_reason: reason for connect timeout
140  *
141  * This function is used to convert host timeout
142  * reason enum to kernel specific enum.
143  *
144  * Context: Any context.
145  * Return: nl timeout enum
146  */
147 
148 static enum nl80211_timeout_reason
149 osif_convert_timeout_reason(enum wlan_cm_connect_fail_reason reason)
150 {
151 	switch (reason) {
152 	case CM_JOIN_TIMEOUT:
153 		return NL80211_TIMEOUT_SCAN;
154 	case CM_AUTH_TIMEOUT:
155 		return NL80211_TIMEOUT_AUTH;
156 	case CM_ASSOC_TIMEOUT:
157 		return NL80211_TIMEOUT_ASSOC;
158 	default:
159 		return NL80211_TIMEOUT_UNSPECIFIED;
160 	}
161 }
162 
163 #if defined CFG80211_CONNECT_BSS || \
164 	(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
165 
166 #if defined CFG80211_CONNECT_TIMEOUT_REASON_CODE || \
167 	(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
168 /**
169  * osif_connect_timeout() - API to send connection timeout reason
170  * @dev: network device
171  * @bssid: bssid to which we want to associate
172  * @reason: reason for connect timeout
173  *
174  * This API is used to send connection timeout reason to supplicant
175  *
176  * Context: Any context.
177  * Return: Void
178  */
179 static void
180 osif_connect_timeout(struct net_device *dev, const u8 *bssid,
181 		     enum wlan_cm_connect_fail_reason reason)
182 {
183 	enum nl80211_timeout_reason nl_timeout_reason;
184 
185 	nl_timeout_reason = osif_convert_timeout_reason(reason);
186 
187 	osif_debug("nl_timeout_reason %d", nl_timeout_reason);
188 
189 	cfg80211_connect_timeout(dev, bssid, NULL, 0, qdf_mem_malloc_flags(),
190 				 nl_timeout_reason);
191 }
192 
193 /**
194  * __osif_connect_bss() - API to send connection status to supplicant
195  * @dev: network device
196  * @bss: bss info
197  * @connect_rsp: Connection manager connect response
198  *
199  * Context: Any context.
200  * Return: void
201  */
202 static void __osif_connect_bss(struct net_device *dev,
203 			       struct cfg80211_bss *bss,
204 			       struct wlan_cm_connect_resp *rsp,
205 			       enum ieee80211_statuscode status)
206 {
207 	enum nl80211_timeout_reason nl_timeout_reason;
208 	size_t req_len = 0;
209 	const uint8_t *req_ptr = NULL;
210 	size_t rsp_len = 0;
211 	const uint8_t *rsp_ptr = NULL;
212 
213 	nl_timeout_reason = osif_convert_timeout_reason(rsp->reason);
214 
215 	osif_debug("nl_timeout_reason %d", nl_timeout_reason);
216 
217 	osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req,
218 				      &req_len, &req_ptr);
219 	osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp,
220 				      &rsp_len, &rsp_ptr);
221 
222 	cfg80211_connect_bss(dev, rsp->bssid.bytes, bss,
223 			     req_ptr, req_len, rsp_ptr, rsp_len, status,
224 			     qdf_mem_malloc_flags(), nl_timeout_reason);
225 }
226 #else /* CFG80211_CONNECT_TIMEOUT_REASON_CODE */
227 
228 #if defined CFG80211_CONNECT_TIMEOUT || \
229 	(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
230 static void osif_connect_timeout(
231 			struct net_device *dev,
232 			const u8 *bssid,
233 			enum wlan_cm_connect_fail_reason reason)
234 {
235 	cfg80211_connect_timeout(dev, bssid, NULL, 0, qdf_mem_malloc_flags());
236 }
237 #endif
238 
239 static void __osif_connect_bss(struct net_device *dev,
240 			       struct cfg80211_bss *bss,
241 			       struct wlan_cm_connect_resp *rsp,
242 			       ieee80211_statuscode status)
243 {
244 	size_t req_len = 0;
245 	const uint8_t *req_ptr = NULL;
246 	size_t rsp_len = 0;
247 	const uint8_t *rsp_ptr = NULL;
248 
249 	osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req,
250 				      &req_len, &req_ptr);
251 	osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp,
252 				      &rsp_len, &rsp_ptr);
253 
254 	cfg80211_connect_bss(dev, rsp->bssid.bytes, bss,
255 			     req_ptr, req_len, rsp_ptr, rsp_len,
256 			     status, qdf_mem_malloc_flags());
257 }
258 #endif /* CFG80211_CONNECT_TIMEOUT_REASON_CODE */
259 
260 /**
261  * osif_connect_bss() - API to send connection status to supplicant
262  * @dev: network device
263  * @bss: bss info
264  * @connect_rsp: Connection manager connect response
265  *
266  * The API is a wrapper to send connection status to supplicant
267  *
268  * Context: Any context.
269  * Return: Void
270  */
271 #if defined CFG80211_CONNECT_TIMEOUT || \
272 	(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
273 static void osif_connect_bss(struct net_device *dev, struct cfg80211_bss *bss,
274 			     struct wlan_cm_connect_resp *rsp)
275 {
276 	enum ieee80211_statuscode status = WLAN_STATUS_SUCCESS;
277 
278 	osif_enter_dev(dev);
279 
280 	if (rsp->reason == CM_JOIN_TIMEOUT ||
281 	    rsp->reason == CM_AUTH_TIMEOUT ||
282 	    rsp->reason == CM_ASSOC_TIMEOUT) {
283 		osif_connect_timeout(dev, rsp->bssid.bytes,
284 				     rsp->reason);
285 	} else {
286 		status = osif_get_connect_status_code(rsp);
287 
288 		__osif_connect_bss(dev, bss, rsp, status);
289 	}
290 }
291 #else /* CFG80211_CONNECT_TIMEOUT */
292 static void osif_connect_bss(struct net_device *dev, struct cfg80211_bss *bss,
293 			     struct wlan_cm_connect_resp *rsp)
294 {
295 	enum ieee80211_statuscode status;
296 
297 	osif_enter_dev(dev);
298 
299 	status = osif_get_connect_status_code(rsp);
300 	__osif_connect_bss(dev, bss, rsp, status);
301 }
302 #endif /* CFG80211_CONNECT_TIMEOUT */
303 
304 #if defined(WLAN_FEATURE_FILS_SK)
305 
306 #if (defined(CFG80211_CONNECT_DONE) || \
307 	(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))) && \
308 	(LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0))
309 
310 #if defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
311 		 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
312 /**
313  * osif_populate_fils_params() - Populate FILS keys to connect response
314  * @conn_rsp_params: connect response to supplicant
315  * @fils_ie: Fils ie information from connection manager
316  *
317  * Context: Any context.
318  * Return: None
319  */
320 static void
321 osif_populate_fils_params(struct cfg80211_connect_resp_params *rsp_params,
322 			  struct fils_connect_rsp_params *fils_ie)
323 {
324 	/*  Increment seq number to be used for next FILS */
325 	rsp_params->fils_erp_next_seq_num = fils_ie->fils_seq_num + 1;
326 	rsp_params->update_erp_next_seq_num = true;
327 	rsp_params->fils_kek = fils_ie->kek;
328 	rsp_params->fils_kek_len = fils_ie->kek_len;
329 	rsp_params->pmk = fils_ie->fils_pmk;
330 	rsp_params->pmk_len = fils_ie->fils_pmk_len;
331 	rsp_params->pmkid = fils_ie->fils_pmkid;
332 	osif_debug("erp_next_seq_num:%d", rsp_params->fils_erp_next_seq_num);
333 }
334 #else /* CFG80211_FILS_SK_OFFLOAD_SUPPORT */
335 static inline void
336 osif_populate_fils_params(struct cfg80211_connect_resp_params *rsp_params,
337 			  struct fils_connect_rsp_params *fils_ie)
338 
339 { }
340 #endif /* CFG80211_FILS_SK_OFFLOAD_SUPPORT */
341 
342 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0))
343 /**
344  * osif_populate_fils_params() - Populate FILS keys to connect response
345  * @conn_rsp_params: connect response to supplicant
346  * @fils_ie: Fils ie information from connection manager
347  *
348  * Context: Any context.
349  * Return: None
350  */
351 static void
352 osif_populate_fils_params(struct cfg80211_connect_resp_params *rsp_params,
353 			  struct fils_connect_rsp_params *fils_ie)
354 
355 {
356 	/* Increament seq number to be used for next FILS */
357 	rsp_params->fils.erp_next_seq_num = fils_ie->fils_seq_num + 1;
358 	rsp_params->fils.update_erp_next_seq_num = true;
359 	rsp_params->fils.kek = fils_ie->kek;
360 	rsp_params->fils.kek_len = fils_ie->kek_len;
361 	rsp_params->fils.pmk = fils_ie->fils_pmk;
362 	rsp_params->fils.pmk_len = fils_ie->fils_pmk_len;
363 	rsp_params->fils.pmkid = fils_ie->fils_pmkid;
364 	osif_debug("erp_next_seq_num:%d", rsp_params->fils.erp_next_seq_num);
365 }
366 #endif /* CFG80211_CONNECT_DONE */
367 
368 #if defined(CFG80211_CONNECT_DONE) || \
369 	(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
370 
371 /**
372  * osif_connect_done() - Wrapper API to call cfg80211_connect_done
373  * @dev: network device
374  * @bss: bss info
375  * @connect_rsp: Connection manager connect response
376  * @vdev: pointer to vdev
377  *
378  * This API is used as wrapper to send FILS key/sequence number
379  * params etc. to supplicant in case of FILS connection
380  *
381  * Context: Any context.
382  * Return: None
383  */
384 static void osif_connect_done(struct net_device *dev, struct cfg80211_bss *bss,
385 			      struct wlan_cm_connect_resp *rsp,
386 			      struct wlan_objmgr_vdev *vdev)
387 {
388 	struct cfg80211_connect_resp_params conn_rsp_params;
389 	enum ieee80211_statuscode status;
390 
391 	osif_enter_dev(dev);
392 
393 	status = osif_get_connect_status_code(rsp);
394 	qdf_mem_zero(&conn_rsp_params, sizeof(conn_rsp_params));
395 
396 	if (!rsp->connect_ies.fils_ie) {
397 		conn_rsp_params.status = WLAN_STATUS_UNSPECIFIED_FAILURE;
398 	} else {
399 		conn_rsp_params.status = status;
400 		conn_rsp_params.bssid = rsp->bssid.bytes;
401 		conn_rsp_params.timeout_reason =
402 			osif_convert_timeout_reason(rsp->reason);
403 		osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req,
404 					      &conn_rsp_params.req_ie_len,
405 					      &conn_rsp_params.req_ie);
406 		osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp,
407 					      &conn_rsp_params.resp_ie_len,
408 					      &conn_rsp_params.resp_ie);
409 		conn_rsp_params.bss = bss;
410 		osif_populate_fils_params(&conn_rsp_params,
411 					  rsp->connect_ies.fils_ie);
412 		osif_cm_save_gtk(vdev, rsp);
413 	}
414 
415 	osif_debug("Connect resp status  %d", conn_rsp_params.status);
416 	cfg80211_connect_done(dev, &conn_rsp_params, qdf_mem_malloc_flags());
417 	if (rsp->connect_ies.fils_ie && rsp->connect_ies.fils_ie->hlp_data_len)
418 		osif_cm_set_hlp_data(dev, vdev, rsp);
419 }
420 #else /* CFG80211_CONNECT_DONE */
421 static inline void
422 osif_connect_done(struct net_device *dev, struct cfg80211_bss *bss,
423 		  struct wlan_cm_connect_resp *rsp,
424 		  struct wlan_objmgr_vdev *vdev)
425 { }
426 #endif /* CFG80211_CONNECT_DONE */
427 #endif /* WLAN_FEATURE_FILS_SK */
428 
429 #if defined(WLAN_FEATURE_FILS_SK) && \
430 	(defined(CFG80211_CONNECT_DONE) || \
431 	(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)))
432 /**
433  * osif_fils_update_connect_results() - API to send fils connection status to
434  * supplicant.
435  * @dev: network device
436  * @bss: bss info
437  * @connect_rsp: Connection manager connect response
438  * @vdev: pointer to vdev
439  *
440  * The API is a wrapper to send connection status to supplicant
441  *
442  * Context: Any context.
443  * Return: 0 if success else failure
444  */
445 static int osif_update_connect_results(struct net_device *dev,
446 				       struct cfg80211_bss *bss,
447 				       struct wlan_cm_connect_resp *rsp,
448 				       struct wlan_objmgr_vdev *vdev)
449 {
450 	if (!rsp->is_fils_connection) {
451 		osif_debug("fils IE is NULL");
452 		return -EINVAL;
453 	}
454 	osif_connect_done(dev, bss, rsp, vdev);
455 
456 	return 0;
457 }
458 #else /* WLAN_FEATURE_FILS_SK && CFG80211_CONNECT_DONE */
459 
460 static inline int osif_update_connect_results(struct net_device *dev,
461 					      struct cfg80211_bss *bss,
462 					      struct wlan_cm_connect_resp *rsp,
463 					      struct wlan_objmgr_vdev *vdev)
464 {
465 	return -EINVAL;
466 }
467 #endif /* WLAN_FEATURE_FILS_SK && CFG80211_CONNECT_DONE */
468 
469 #ifdef WLAN_FEATURE_11BE_MLO
470 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
471 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev,
472 					 struct vdev_osif_priv *osif_priv,
473 					 struct wlan_cm_connect_resp *rsp)
474 {
475 	struct cfg80211_bss *bss = NULL;
476 	struct ieee80211_channel *chan;
477 
478 	if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) {
479 		chan = ieee80211_get_channel(osif_priv->wdev->wiphy,
480 					     rsp->freq);
481 		bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan,
482 					    rsp->bssid.bytes,
483 					    rsp->ssid.ssid,
484 					    rsp->ssid.length);
485 	}
486 
487 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
488 		if (osif_update_connect_results(osif_priv->wdev->netdev, bss,
489 						rsp, vdev))
490 			osif_connect_bss(osif_priv->wdev->netdev, bss, rsp);
491 		return;
492 	}
493 
494 	if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev)) {
495 		if (osif_update_connect_results(
496 				osif_priv->wdev->netdev, bss,
497 				rsp, vdev))
498 			osif_connect_bss(osif_priv->wdev->netdev,
499 					 bss, rsp);
500 	}
501 
502 }
503 #else /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */
504 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev,
505 					 struct vdev_osif_priv *osif_priv,
506 					 struct wlan_cm_connect_resp *rsp)
507 {
508 	struct cfg80211_bss *bss = NULL;
509 	struct ieee80211_channel *chan;
510 	struct wlan_objmgr_vdev *assoc_vdev = NULL;
511 	struct vdev_osif_priv *tmp_osif_priv = NULL;
512 	qdf_freq_t freq;
513 	struct qdf_mac_addr macaddr = {0};
514 	struct wlan_cm_connect_resp resp = {0};
515 
516 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
517 		if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) {
518 			chan = ieee80211_get_channel(osif_priv->wdev->wiphy,
519 						     rsp->freq);
520 			bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy,
521 						    chan,
522 						    rsp->bssid.bytes,
523 						    rsp->ssid.ssid,
524 						    rsp->ssid.length);
525 		}
526 		if (osif_update_connect_results(osif_priv->wdev->netdev, bss,
527 						rsp, vdev))
528 			osif_connect_bss(osif_priv->wdev->netdev, bss, rsp);
529 		return;
530 	}
531 
532 	if ((QDF_IS_STATUS_SUCCESS(rsp->connect_status) &&
533 	    ucfg_mlo_is_mld_connected(vdev)) ||
534 	    (QDF_IS_STATUS_ERROR(rsp->connect_status) &&
535 	    ucfg_mlo_is_mld_disconnected(vdev))) {
536 		assoc_vdev = ucfg_mlo_get_assoc_link_vdev(vdev);
537 		if (!assoc_vdev)
538 			return;
539 		tmp_osif_priv  = wlan_vdev_get_ospriv(assoc_vdev);
540 		freq = vdev->vdev_mlme.bss_chan->ch_freq;
541 		wlan_vdev_get_bss_peer_mac(assoc_vdev, &macaddr);
542 		if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) {
543 			chan = ieee80211_get_channel(tmp_osif_priv->wdev->wiphy,
544 						     freq);
545 			bss = wlan_cfg80211_get_bss(tmp_osif_priv->wdev->wiphy,
546 						    chan,
547 						    macaddr.bytes,
548 						    rsp->ssid.ssid,
549 						    rsp->ssid.length);
550 		}
551 		qdf_mem_copy(resp.bssid.bytes, macaddr.bytes,
552 			     QDF_MAC_ADDR_SIZE);
553 		qdf_mem_copy(resp.ssid.ssid, rsp->ssid.ssid,
554 			     rsp->ssid.length);
555 		resp.ssid.length = rsp->ssid.length;
556 		resp.freq = freq;
557 		resp.connect_status = rsp->connect_status;
558 		resp.reason = rsp->reason;
559 		resp.status_code = rsp->status_code;
560 		resp.connect_ies.assoc_req.ptr = rsp->connect_ies.assoc_req.ptr;
561 		resp.connect_ies.assoc_req.len = rsp->connect_ies.assoc_req.len;
562 		resp.connect_ies.assoc_rsp.ptr = rsp->connect_ies.assoc_rsp.ptr;
563 		resp.connect_ies.assoc_rsp.len = rsp->connect_ies.assoc_rsp.len;
564 		if (osif_update_connect_results(tmp_osif_priv->wdev->netdev, bss,
565 						&resp, vdev))
566 			osif_connect_bss(tmp_osif_priv->wdev->netdev, bss, &resp);
567 	}
568 }
569 #endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */
570 #else /* WLAN_FEATURE_11BE_MLO */
571 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev,
572 					 struct vdev_osif_priv *osif_priv,
573 					 struct wlan_cm_connect_resp *rsp)
574 {
575 	struct cfg80211_bss *bss = NULL;
576 	struct ieee80211_channel *chan;
577 
578 	if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) {
579 		chan = ieee80211_get_channel(osif_priv->wdev->wiphy,
580 					     rsp->freq);
581 		bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan,
582 					    rsp->bssid.bytes,
583 					    rsp->ssid.ssid,
584 					    rsp->ssid.length);
585 	}
586 
587 	if (osif_update_connect_results(osif_priv->wdev->netdev, bss,
588 					rsp, vdev))
589 		osif_connect_bss(osif_priv->wdev->netdev, bss, rsp);
590 }
591 #endif /* WLAN_FEATURE_11BE_MLO */
592 #else  /* CFG80211_CONNECT_BSS */
593 #ifdef WLAN_FEATURE_11BE_MLO
594 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
595 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev,
596 					 struct vdev_osif_priv *osif_priv,
597 					 struct wlan_cm_connect_resp *rsp)
598 {
599 	enum ieee80211_statuscode status;
600 	size_t req_len = 0;
601 	const uint8_t *req_ptr = NULL;
602 	size_t rsp_len = 0;
603 	const uint8_t *rsp_ptr = NULL;
604 	struct wlan_objmgr_vdev *assoc_vdev = NULL;
605 	struct vdev_osif_priv *tmp_osif_priv = NULL;
606 
607 	status = osif_get_connect_status_code(rsp);
608 	osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req,
609 				      &req_len, &req_ptr);
610 	osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp,
611 				      &rsp_len, &rsp_ptr);
612 	if (wlan_vdev_mlme_is_mlo_vdev(vdev)) {
613 		if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev))
614 			cfg80211_connect_result(
615 				osif_priv->wdev->netdev,
616 				rsp->bssid.bytes, req_ptr, req_len,
617 				rsp_ptr, rsp_len, status,
618 				qdf_mem_malloc_flags());
619 	} else {
620 		cfg80211_connect_result(osif_priv->wdev->netdev,
621 					rsp->bssid.bytes, req_ptr, req_len,
622 					rsp_ptr, rsp_len, status,
623 					qdf_mem_malloc_flags());
624 	}
625 }
626 #else /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */
627 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev,
628 					 struct vdev_osif_priv *osif_priv,
629 					 struct wlan_cm_connect_resp *rsp)
630 {
631 	enum ieee80211_statuscode status;
632 	size_t req_len = 0;
633 	const uint8_t *req_ptr = NULL;
634 	size_t rsp_len = 0;
635 	const uint8_t *rsp_ptr = NULL;
636 	struct wlan_objmgr_vdev *assoc_vdev = NULL;
637 	struct vdev_osif_priv *tmp_osif_priv = NULL;
638 	struct qdf_mac_addr macaddr = {0};
639 
640 	status = osif_get_connect_status_code(rsp);
641 	osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req,
642 				      &req_len, &req_ptr);
643 	osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp,
644 				      &rsp_len, &rsp_ptr);
645 	if (wlan_vdev_mlme_is_mlo_vdev(vdev)) {
646 		if ((QDF_IS_STATUS_SUCCESS(rsp->connect_status) &&
647 		    ucfg_mlo_is_mld_connected(vdev)) ||
648 		    (QDF_IS_STATUS_ERROR(rsp->connect_status) &&
649 		    ucfg_mlo_is_mld_disconnected(vdev))) {
650 			assoc_vdev = ucfg_mlo_get_assoc_link_vdev(vdev);
651 			if (!assoc_vdev)
652 				return;
653 			tmp_osif_priv  = wlan_vdev_get_ospriv(assoc_vdev);
654 			wlan_vdev_get_bss_peer_mac(assoc_vdev, &macaddr);
655 			cfg80211_connect_result(tmp_osif_priv->wdev->netdev,
656 						macaddr.bytes, req_ptr,
657 						req_len, rsp_ptr, rsp_len,
658 						status, qdf_mem_malloc_flags());
659 		}
660 	} else {
661 		cfg80211_connect_result(osif_priv->wdev->netdev,
662 					rsp->bssid.bytes, req_ptr, req_len,
663 					rsp_ptr, rsp_len, status,
664 					qdf_mem_malloc_flags());
665 	}
666 }
667 #endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */
668 #else /* WLAN_FEATURE_11BE_MLO */
669 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev,
670 					 struct vdev_osif_priv *osif_priv,
671 					 struct wlan_cm_connect_resp *rsp)
672 {
673 	enum ieee80211_statuscode status;
674 	size_t req_len = 0;
675 	const uint8_t *req_ptr = NULL;
676 	size_t rsp_len = 0;
677 	const uint8_t *rsp_ptr = NULL;
678 
679 	status = osif_get_connect_status_code(rsp);
680 	osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req,
681 				      &req_len, &req_ptr);
682 	osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp,
683 				      &rsp_len, &rsp_ptr);
684 	cfg80211_connect_result(osif_priv->wdev->netdev,
685 				rsp->bssid.bytes, req_ptr, req_len,
686 				rsp_ptr, rsp_len, status,
687 				qdf_mem_malloc_flags());
688 }
689 #endif /* WLAN_FEATURE_11BE_MLO */
690 #endif /* CFG80211_CONNECT_BSS */
691 
692 #ifdef CONN_MGR_ADV_FEATURE
693 static inline
694 bool osif_cm_is_unlink_bss_required(struct wlan_cm_connect_resp *rsp)
695 {
696 	if (QDF_IS_STATUS_SUCCESS(rsp->connect_status))
697 		return false;
698 
699 	if (rsp->reason == CM_NO_CANDIDATE_FOUND ||
700 	    rsp->reason == CM_JOIN_TIMEOUT ||
701 	    rsp->reason == CM_AUTH_TIMEOUT ||
702 	    rsp->reason == CM_ASSOC_TIMEOUT)
703 		return true;
704 
705 	return false;
706 }
707 static inline void osif_check_and_unlink_bss(struct wlan_objmgr_vdev *vdev,
708 					     struct vdev_osif_priv *osif_priv,
709 					     struct wlan_cm_connect_resp *rsp)
710 {
711 	if (osif_cm_is_unlink_bss_required(rsp))
712 		osif_cm_unlink_bss(vdev, osif_priv, &rsp->bssid, rsp->ssid.ssid,
713 				   rsp->ssid.length);
714 }
715 #else
716 static inline void osif_check_and_unlink_bss(struct wlan_objmgr_vdev *vdev,
717 					     struct vdev_osif_priv *osif_priv,
718 					     struct wlan_cm_connect_resp *rsp)
719 {}
720 #endif
721 
722 QDF_STATUS osif_connect_handler(struct wlan_objmgr_vdev *vdev,
723 				struct wlan_cm_connect_resp *rsp)
724 {
725 	struct vdev_osif_priv *osif_priv  = wlan_vdev_get_ospriv(vdev);
726 	QDF_STATUS status;
727 
728 	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",
729 		       osif_priv->wdev->netdev->name, rsp->vdev_id,
730 		       QDF_MAC_ADDR_REF(wlan_vdev_mlme_get_macaddr(vdev)),
731 		       QDF_MAC_ADDR_REF(rsp->bssid.bytes),
732 		       rsp->ssid.length, rsp->ssid.ssid,
733 		       rsp->connect_status ? "FAILURE" : "SUCCESS", rsp->cm_id,
734 		       rsp->reason, rsp->status_code, rsp->is_reassoc);
735 
736 	osif_check_and_unlink_bss(vdev, osif_priv, rsp);
737 
738 	status = osif_validate_connect_and_reset_src_id(osif_priv, rsp);
739 	if (QDF_IS_STATUS_ERROR(status)) {
740 		osif_cm_connect_comp_ind(vdev, rsp, OSIF_NOT_HANDLED);
741 		return status;
742 	}
743 
744 	osif_cm_connect_comp_ind(vdev, rsp, OSIF_PRE_USERSPACE_UPDATE);
745 	if (rsp->is_reassoc)
746 		osif_indicate_reassoc_results(vdev, osif_priv, rsp);
747 	else
748 		osif_indcate_connect_results(vdev, osif_priv, rsp);
749 	osif_cm_connect_comp_ind(vdev, rsp, OSIF_POST_USERSPACE_UPDATE);
750 
751 	return QDF_STATUS_SUCCESS;
752 }
753 
754 QDF_STATUS osif_failed_candidate_handler(struct wlan_objmgr_vdev *vdev,
755 					 struct wlan_cm_connect_resp *rsp)
756 {
757 	struct vdev_osif_priv *osif_priv  = wlan_vdev_get_ospriv(vdev);
758 
759 	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",
760 		       osif_priv->wdev->netdev->name, rsp->vdev_id,
761 		       QDF_MAC_ADDR_REF(wlan_vdev_mlme_get_macaddr(vdev)),
762 		       QDF_MAC_ADDR_REF(rsp->bssid.bytes),
763 		       rsp->ssid.length, rsp->ssid.ssid, rsp->cm_id,
764 		       rsp->reason, rsp->status_code);
765 
766 	osif_check_and_unlink_bss(vdev, osif_priv, rsp);
767 
768 	return QDF_STATUS_SUCCESS;
769 }
770