1 /*
2  * Copyright (c) 2012-2015, 2020-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2024 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
osif_cm_get_assoc_req_ie_data(struct element_info * assoc_req,size_t * ie_data_len,const uint8_t ** ie_data_ptr)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
osif_cm_get_assoc_req_ie_data(struct element_info * assoc_req,size_t * ie_data_len,const uint8_t ** ie_data_ptr)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 
osif_cm_get_assoc_rsp_ie_data(struct element_info * assoc_rsp,size_t * ie_data_len,const uint8_t ** ie_data_ptr)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
osif_validate_connect_and_reset_src_id(struct vdev_osif_priv * osif_priv,struct wlan_cm_connect_resp * rsp)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
osif_get_statuscode(enum wlan_status_code status)124 osif_get_statuscode(enum wlan_status_code status)
125 {
126 	return (enum ieee80211_statuscode)status;
127 }
128 
129 static enum ieee80211_statuscode
osif_get_connect_status_code(struct wlan_cm_connect_resp * rsp)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
osif_convert_timeout_reason(enum wlan_cm_connect_fail_reason 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
osif_connect_timeout(struct net_device * dev,const u8 * bssid,enum wlan_cm_connect_fail_reason reason)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  */
__osif_connect_bss(struct net_device * dev,struct cfg80211_bss * bss,struct wlan_cm_connect_resp * rsp,enum ieee80211_statuscode status)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))
osif_connect_timeout(struct net_device * dev,const u8 * bssid,enum wlan_cm_connect_fail_reason reason)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 
__osif_connect_bss(struct net_device * dev,struct cfg80211_bss * bss,struct wlan_cm_connect_resp * rsp,ieee80211_statuscode status)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))
osif_connect_bss(struct net_device * dev,struct cfg80211_bss * bss,struct wlan_cm_connect_resp * rsp)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 */
osif_connect_bss(struct net_device * dev,struct cfg80211_bss * bss,struct wlan_cm_connect_resp * rsp)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
osif_populate_fils_params(struct cfg80211_connect_resp_params * rsp_params,struct wlan_connect_rsp_ies * connect_ies)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
osif_populate_fils_params(struct cfg80211_connect_resp_params * rsp_params,struct wlan_connect_rsp_ies * connect_ies)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
osif_populate_fils_params(struct cfg80211_connect_resp_params * rsp_params,struct wlan_connect_rsp_ies * connect_ies)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
osif_populate_fils_params(struct cfg80211_connect_resp_params * rsp_params,struct wlan_connect_rsp_ies * connect_ies)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
osif_get_partner_info_from_mlie(struct wlan_cm_connect_resp * connect_rsp,struct mlo_partner_info * partner_info)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
osif_get_link_id_from_assoc_ml_ie(struct mlo_link_info * rsp_link_info,struct mlo_partner_info * assoc_partner_info,uint8_t * link_id)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 *
osif_get_chan_bss_from_kernel(struct wlan_objmgr_vdev * vdev,struct mlo_link_info * rsp_link_info,struct wlan_cm_connect_resp * rsp)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 vdev id %d freq %d ssid:" QDF_SSID_FMT " and BSSID " QDF_MAC_ADDR_FMT,
466 			 wlan_vdev_get_id(vdev), rsp_link_info->chan_freq,
467 			 QDF_SSID_REF(rsp->ssid.length, rsp->ssid.ssid),
468 			 QDF_MAC_ADDR_REF(rsp->bssid.bytes));
469 		return NULL;
470 	}
471 
472 	return partner_bss;
473 }
474 #endif
475 
476 #if defined(CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT) && defined(WLAN_FEATURE_11BE_MLO)
477 #ifndef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
osif_get_partner_vdev(struct wlan_objmgr_vdev * vdev,struct mlo_link_info rsp_partner_info,wlan_objmgr_ref_dbgid id)478 static struct wlan_objmgr_vdev *osif_get_partner_vdev(
479 					struct wlan_objmgr_vdev *vdev,
480 					struct mlo_link_info rsp_partner_info,
481 					wlan_objmgr_ref_dbgid id)
482 {
483 	return mlo_get_vdev_by_link_id(vdev, rsp_partner_info.link_id, id);
484 }
485 #endif
486 
487 static
osif_populate_connect_response_for_link(struct wlan_objmgr_vdev * vdev,struct cfg80211_connect_resp_params * conn_rsp_params,uint8_t link_id,uint8_t * link_addr,struct cfg80211_bss * bss)488 void osif_populate_connect_response_for_link(struct wlan_objmgr_vdev *vdev,
489 					     struct cfg80211_connect_resp_params *conn_rsp_params,
490 					     uint8_t link_id,
491 					     uint8_t *link_addr,
492 					     struct cfg80211_bss *bss)
493 {
494 	if (bss) {
495 		osif_debug("Link_id :%d", link_id);
496 		conn_rsp_params->valid_links |=  BIT(link_id);
497 		conn_rsp_params->links[link_id].bssid = bss->bssid;
498 		conn_rsp_params->links[link_id].bss = bss;
499 		conn_rsp_params->links[link_id].addr = link_addr;
500 	}
501 
502 	mlo_mgr_osif_update_connect_info(vdev, link_id);
503 }
504 
505 static QDF_STATUS
osif_fill_peer_mld_mac_connect_resp(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_resp * rsp,struct cfg80211_connect_resp_params * conn_rsp_params)506 osif_fill_peer_mld_mac_connect_resp(struct wlan_objmgr_vdev *vdev,
507 				    struct wlan_cm_connect_resp *rsp,
508 				    struct cfg80211_connect_resp_params *conn_rsp_params)
509 {
510 	struct wlan_objmgr_peer *peer_obj;
511 	struct wlan_objmgr_psoc *psoc;
512 
513 	psoc = wlan_vdev_get_psoc(vdev);
514 	if (!psoc)
515 		return QDF_STATUS_E_INVAL;
516 
517 	peer_obj = wlan_objmgr_get_peer_by_mac(psoc, rsp->bssid.bytes,
518 					       WLAN_OSIF_ID);
519 	if (!peer_obj)
520 		return QDF_STATUS_E_INVAL;
521 
522 	conn_rsp_params->ap_mld_addr = wlan_peer_mlme_get_mldaddr(peer_obj);
523 
524 	wlan_objmgr_peer_release_ref(peer_obj, WLAN_OSIF_ID);
525 
526 	return QDF_STATUS_SUCCESS;
527 }
528 
529 static void
osif_populate_partner_links_mlo_params(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_resp * rsp,struct cfg80211_connect_resp_params * conn_rsp_params)530 osif_populate_partner_links_mlo_params(struct wlan_objmgr_vdev *vdev,
531 				       struct wlan_cm_connect_resp *rsp,
532 				       struct cfg80211_connect_resp_params *conn_rsp_params)
533 {
534 	struct mlo_link_info *rsp_partner_info;
535 	struct cfg80211_bss *bss = NULL;
536 	uint8_t link_id = 0, num_links;
537 	int i;
538 	struct mlo_link_info *link_info;
539 
540 	num_links = rsp->ml_parnter_info.num_partner_links;
541 	for (i = 0 ; i < num_links; i++) {
542 		rsp_partner_info = &rsp->ml_parnter_info.partner_link_info[i];
543 		link_id = rsp_partner_info->link_id;
544 
545 		link_info = mlo_mgr_get_ap_link_by_link_id(vdev->mlo_dev_ctx,
546 							   link_id);
547 		if (!link_info)
548 			continue;
549 
550 		bss = osif_get_chan_bss_from_kernel(vdev, rsp_partner_info,
551 						    rsp);
552 
553 		osif_populate_connect_response_for_link(vdev, conn_rsp_params,
554 							link_id,
555 							link_info->link_addr.bytes,
556 							bss);
557 	}
558 }
559 
osif_fill_connect_resp_mlo_params(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_resp * rsp,struct cfg80211_bss * bss,struct cfg80211_connect_resp_params * conn_rsp_params)560 static void osif_fill_connect_resp_mlo_params(struct wlan_objmgr_vdev *vdev,
561 					      struct wlan_cm_connect_resp *rsp,
562 					      struct cfg80211_bss *bss,
563 					      struct cfg80211_connect_resp_params *conn_rsp_params)
564 {
565 	uint8_t assoc_link_id;
566 	QDF_STATUS qdf_status;
567 	struct mlo_link_info *link_info = NULL;
568 
569 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
570 		return;
571 
572 	qdf_status = osif_fill_peer_mld_mac_connect_resp(vdev, rsp,
573 							 conn_rsp_params);
574 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
575 		osif_err("Unable to fill peer mld address: %d", qdf_status);
576 		return;
577 	}
578 
579 	assoc_link_id = wlan_vdev_get_link_id(vdev);
580 	link_info = mlo_mgr_get_ap_link_by_link_id(vdev->mlo_dev_ctx,
581 						   assoc_link_id);
582 	if (!link_info) {
583 		osif_err("Unable to find link_info for link_id: %d",
584 			 assoc_link_id);
585 		return;
586 	}
587 
588 	osif_populate_connect_response_for_link(vdev, conn_rsp_params,
589 						assoc_link_id,
590 						link_info->link_addr.bytes,
591 						bss);
592 	osif_populate_partner_links_mlo_params(vdev, rsp, conn_rsp_params);
593 }
594 
595 static void
osif_free_ml_link_params(struct cfg80211_connect_resp_params * conn_rsp_params)596 osif_free_ml_link_params(struct cfg80211_connect_resp_params *conn_rsp_params)
597 {
598 }
599 #elif defined(CFG80211_IFTYPE_MLO_LINK_SUPPORT) && defined(WLAN_FEATURE_11BE_MLO)
600 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
osif_get_partner_vdev(struct wlan_objmgr_vdev * vdev,struct mlo_link_info rsp_partner_info,wlan_objmgr_ref_dbgid id)601 static struct wlan_objmgr_vdev *osif_get_partner_vdev(
602 					struct wlan_objmgr_vdev *vdev,
603 					struct mlo_link_info rsp_partner_info,
604 					wlan_objmgr_ref_dbgid id)
605 {
606 	return wlan_objmgr_get_vdev_by_id_from_pdev(
607 						vdev->vdev_objmgr.wlan_pdev,
608 						rsp_partner_info.vdev_id, id);
609 }
610 #else
osif_get_partner_vdev(struct wlan_objmgr_vdev * vdev,struct mlo_link_info rsp_partner_info,wlan_objmgr_ref_dbgid id)611 static struct wlan_objmgr_vdev *osif_get_partner_vdev(
612 					struct wlan_objmgr_vdev *vdev,
613 					struct mlo_link_info rsp_partner_info,
614 					wlan_objmgr_ref_dbgid id)
615 {
616 	return mlo_get_vdev_by_link_id(vdev, rsp_partner_info.link_id, id);
617 }
618 #endif
osif_fill_connect_resp_mlo_params(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_resp * rsp,struct cfg80211_bss * bss,struct cfg80211_connect_resp_params * conn_rsp_params)619 static void osif_fill_connect_resp_mlo_params(
620 			struct wlan_objmgr_vdev *vdev,
621 			struct wlan_cm_connect_resp *rsp,
622 			struct cfg80211_bss *bss,
623 			struct cfg80211_connect_resp_params *conn_rsp_params)
624 {
625 	uint8_t i, num_mlo_links = rsp->ml_parnter_info.num_partner_links + 1;
626 	struct wlan_objmgr_vdev *ml_vdev = vdev;
627 	struct vdev_osif_priv *osif_priv;
628 	struct ieee80211_channel *chan;
629 	struct cfg80211_mlo_link_params *ml_link_params;
630 	struct mlo_link_info *rsp_partner_info;
631 
632 	if (num_mlo_links == 1)
633 		return;
634 
635 	ml_link_params = qdf_mem_malloc(
636 				num_mlo_links * sizeof(*ml_link_params));
637 	if (!ml_link_params)
638 		return;
639 
640 	rsp_partner_info = rsp->ml_parnter_info.partner_link_info;
641 	if (rsp->ml_parnter_info.num_partner_links) {
642 		conn_rsp_params->n_mlo_links = num_mlo_links;
643 		osif_priv = wlan_vdev_get_ospriv(ml_vdev);
644 		for (i = 0; i < conn_rsp_params->n_mlo_links; i++) {
645 			ml_link_params[i].wdev = osif_priv->wdev;
646 
647 			if (i != 0) {
648 				chan = ieee80211_get_channel(
649 					   osif_priv->wdev->wiphy,
650 					   rsp_partner_info[i - 1].chan_freq);
651 				if (!chan) {
652 					osif_err("Invalid partner channel");
653 					goto end;
654 				}
655 
656 				bss = wlan_cfg80211_get_bss(
657 					osif_priv->wdev->wiphy, chan,
658 					rsp_partner_info[i - 1].link_addr.bytes,
659 					rsp->ssid.ssid, rsp->ssid.length);
660 				if (!bss) {
661 					osif_err("Partner bss is null");
662 					goto end;
663 				}
664 			}
665 			qdf_mem_copy(ml_link_params[i].bssid, bss->bssid,
666 				     QDF_MAC_ADDR_SIZE);
667 
668 			if (i == rsp->ml_parnter_info.num_partner_links)
669 				break;
670 
671 			ml_vdev = osif_get_partner_vdev(vdev,
672 							rsp_partner_info[i],
673 							WLAN_OSIF_CM_ID);
674 
675 			if (ml_vdev) {
676 				osif_priv = wlan_vdev_get_ospriv(ml_vdev);
677 				wlan_objmgr_vdev_release_ref(ml_vdev,
678 							     WLAN_OSIF_CM_ID);
679 			} else {
680 				osif_err("Partner vdev not found with vdev_id:%d",
681 					 rsp_partner_info[i].vdev_id);
682 				goto end;
683 			}
684 		}
685 	}
686 end:
687 	conn_rsp_params->mlo_links = ml_link_params;
688 }
689 
690 static void
osif_free_ml_link_params(struct cfg80211_connect_resp_params * conn_rsp_params)691 osif_free_ml_link_params(struct cfg80211_connect_resp_params *conn_rsp_params)
692 {
693 	struct cfg80211_mlo_link_params *ml_links;
694 
695 	ml_links =
696 		(struct cfg80211_mlo_link_params *)conn_rsp_params->mlo_links;
697 	if (ml_links)
698 		qdf_mem_free(ml_links);
699 }
700 
701 #else
osif_fill_connect_resp_mlo_params(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_resp * rsp,struct cfg80211_bss * bss,struct cfg80211_connect_resp_params * conn_rsp_params)702 static void osif_fill_connect_resp_mlo_params(
703 			struct wlan_objmgr_vdev *vdev,
704 			struct wlan_cm_connect_resp *rsp,
705 			struct cfg80211_bss *bss,
706 			struct cfg80211_connect_resp_params *conn_rsp_params)
707 {
708 }
709 
710 static void
osif_free_ml_link_params(struct cfg80211_connect_resp_params * conn_rsp_params)711 osif_free_ml_link_params(struct cfg80211_connect_resp_params *conn_rsp_params)
712 {
713 }
714 #endif
715 
716 #ifdef CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT
717 static
osif_copy_connected_info(struct cfg80211_connect_resp_params * conn_rsp,struct wlan_cm_connect_resp * rsp,struct cfg80211_bss * bss,struct wlan_objmgr_vdev * vdev)718 void osif_copy_connected_info(struct cfg80211_connect_resp_params *conn_rsp,
719 			      struct wlan_cm_connect_resp *rsp,
720 			      struct cfg80211_bss *bss,
721 			      struct wlan_objmgr_vdev *vdev)
722 {
723 	if (wlan_vdev_mlme_is_mlo_vdev(vdev)) {
724 		qdf_debug("MLO vdev fill everything in mlo fill params");
725 		return;
726 	}
727 
728 	conn_rsp->links[0].bssid = rsp->bssid.bytes;
729 	conn_rsp->links[0].bss = bss;
730 }
731 #else
732 static
osif_copy_connected_info(struct cfg80211_connect_resp_params * conn_rsp,struct wlan_cm_connect_resp * rsp,struct cfg80211_bss * bss,struct wlan_objmgr_vdev * vdev)733 void osif_copy_connected_info(struct cfg80211_connect_resp_params *conn_rsp,
734 			      struct wlan_cm_connect_resp *rsp,
735 			      struct cfg80211_bss *bss,
736 			      struct wlan_objmgr_vdev *vdev)
737 {
738 	conn_rsp->bssid = rsp->bssid.bytes;
739 	conn_rsp->bss = bss;
740 }
741 #endif
742 
743 /**
744  * osif_connect_done() - Wrapper API to call cfg80211_connect_done
745  * @dev: network device
746  * @bss: bss info
747  * @rsp: Connection manager connect response
748  * @vdev: pointer to vdev
749  *
750  * This API is used as wrapper to send connect status and params to
751  * supplicant.
752  *
753  * Context: Any context.
754  * Return: 0 if success. Error code for failure
755  */
osif_connect_done(struct net_device * dev,struct cfg80211_bss * bss,struct wlan_cm_connect_resp * rsp,struct wlan_objmgr_vdev * vdev)756 static int osif_connect_done(struct net_device *dev, struct cfg80211_bss *bss,
757 			     struct wlan_cm_connect_resp *rsp,
758 			     struct wlan_objmgr_vdev *vdev)
759 {
760 	struct cfg80211_connect_resp_params conn_rsp_params;
761 	enum ieee80211_statuscode status;
762 
763 	osif_enter_dev(dev);
764 
765 	status = osif_get_connect_status_code(rsp);
766 	qdf_mem_zero(&conn_rsp_params, sizeof(conn_rsp_params));
767 
768 	conn_rsp_params.status = status;
769 	osif_copy_connected_info(&conn_rsp_params, rsp, bss, vdev);
770 	conn_rsp_params.timeout_reason =
771 			osif_convert_timeout_reason(rsp->reason);
772 	osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req,
773 				      &conn_rsp_params.req_ie_len,
774 				      &conn_rsp_params.req_ie);
775 	osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp,
776 				      &conn_rsp_params.resp_ie_len,
777 				      &conn_rsp_params.resp_ie);
778 	osif_populate_fils_params(&conn_rsp_params, &rsp->connect_ies);
779 	osif_cm_save_gtk(vdev, rsp);
780 
781 	if (status == WLAN_STATUS_SUCCESS)
782 		osif_fill_connect_resp_mlo_params(vdev, rsp, bss,
783 						  &conn_rsp_params);
784 
785 	osif_debug("Connect resp status  %d", conn_rsp_params.status);
786 
787 	cfg80211_connect_done(dev, &conn_rsp_params, qdf_mem_malloc_flags());
788 	osif_cm_set_hlp_data(dev, vdev, rsp);
789 
790 	osif_free_ml_link_params(&conn_rsp_params);
791 
792 	return 0;
793 }
794 #else /* CFG80211_CONNECT_DONE */
795 static inline int
osif_connect_done(struct net_device * dev,struct cfg80211_bss * bss,struct wlan_cm_connect_resp * rsp,struct wlan_objmgr_vdev * vdev)796 osif_connect_done(struct net_device *dev, struct cfg80211_bss *bss,
797 		  struct wlan_cm_connect_resp *rsp,
798 		  struct wlan_objmgr_vdev *vdev)
799 {
800 	return -EINVAL;
801 }
802 #endif
803 
804 #if (defined(CFG80211_CONNECT_DONE) || \
805 	(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)))
806 /**
807  * osif_update_connect_results() - API to send connection status to
808  * supplicant.
809  * @dev: network device
810  * @bss: bss info
811  * @rsp: Connection manager connect response
812  * @vdev: pointer to vdev
813  *
814  * The API is a wrapper to send connection status to supplicant
815  *
816  * Context: Any context.
817  * Return: 0 if success else failure
818  */
osif_update_connect_results(struct net_device * dev,struct cfg80211_bss * bss,struct wlan_cm_connect_resp * rsp,struct wlan_objmgr_vdev * vdev)819 static int osif_update_connect_results(struct net_device *dev,
820 				       struct cfg80211_bss *bss,
821 				       struct wlan_cm_connect_resp *rsp,
822 				       struct wlan_objmgr_vdev *vdev)
823 {
824 	return osif_connect_done(dev, bss, rsp, vdev);
825 }
826 #else /* CFG80211_CONNECT_DONE */
827 
osif_update_connect_results(struct net_device * dev,struct cfg80211_bss * bss,struct wlan_cm_connect_resp * rsp,struct wlan_objmgr_vdev * vdev)828 static inline int osif_update_connect_results(struct net_device *dev,
829 					      struct cfg80211_bss *bss,
830 					      struct wlan_cm_connect_resp *rsp,
831 					      struct wlan_objmgr_vdev *vdev)
832 {
833 	return -EINVAL;
834 }
835 #endif /* CFG80211_CONNECT_DONE */
836 
837 #ifdef WLAN_FEATURE_11BE_MLO
838 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
osif_indcate_connect_results(struct wlan_objmgr_vdev * vdev,struct vdev_osif_priv * osif_priv,struct wlan_cm_connect_resp * rsp)839 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev,
840 					 struct vdev_osif_priv *osif_priv,
841 					 struct wlan_cm_connect_resp *rsp)
842 {
843 	struct cfg80211_bss *bss = NULL;
844 	struct ieee80211_channel *chan;
845 	int32_t akm;
846 
847 	if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) {
848 		chan = ieee80211_get_channel(osif_priv->wdev->wiphy,
849 					     rsp->freq);
850 		bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan,
851 					    rsp->bssid.bytes,
852 					    rsp->ssid.ssid,
853 					    rsp->ssid.length);
854 	}
855 
856 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
857 		if (osif_update_connect_results(osif_priv->wdev->netdev, bss,
858 						rsp, vdev))
859 			osif_connect_bss(osif_priv->wdev->netdev, bss, rsp);
860 		return;
861 	}
862 
863 	akm = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT);
864 	if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev)) {
865 		if (osif_update_connect_results(
866 				osif_priv->wdev->netdev, bss,
867 				rsp, vdev))
868 			osif_connect_bss(osif_priv->wdev->netdev,
869 					 bss, rsp);
870 	} else if (osif_get_connect_status_code(rsp) == WLAN_STATUS_SUCCESS &&
871 		   QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_OWE)) {
872 		/*
873 		 * For OWE roaming, link vdev is disconnected on receiving
874 		 * roam synch indication. As part of the disconnect osif link
875 		 * info will be cleared and connect request is prepared from
876 		 * mlo roam module.
877 		 * So update OSIF Link info for that case here.
878 		 */
879 		mlo_mgr_osif_update_connect_info(vdev,
880 						 wlan_vdev_get_link_id(vdev));
881 	}
882 
883 }
884 #else /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */
885 
886 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 213)) && \
887 	(LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0))
888 /**
889  * osif_update_current_bss() - Wrapper API to call cfg80211_update_current_bss
890  * @dev: network device
891  * @bss: bss info
892  * @rsp: Connection manager connect response
893  * @vdev: pointer to vdev
894  *
895  * This API is used as wrapper to update the current bss param of non-assoc link
896  * sta vdev.
897  *
898  * Context: Any context.
899  * Return: QDF_STATUS.
900  */
osif_update_current_bss(struct net_device * dev,struct cfg80211_bss * bss,struct wlan_cm_connect_resp * rsp,struct wlan_objmgr_vdev * vdev)901 static QDF_STATUS osif_update_current_bss(struct net_device *dev,
902 					  struct cfg80211_bss *bss,
903 					  struct wlan_cm_connect_resp *rsp,
904 					  struct wlan_objmgr_vdev *vdev)
905 {
906 	struct cfg80211_connect_resp_params conn_rsp_params;
907 	enum ieee80211_statuscode status;
908 	int ret;
909 
910 	osif_enter_dev(dev);
911 
912 	qdf_mem_zero(&conn_rsp_params, sizeof(conn_rsp_params));
913 
914 	status = osif_get_connect_status_code(rsp);
915 	conn_rsp_params.status = status;
916 	osif_copy_connected_info(&conn_rsp_params, rsp, bss, vdev);
917 
918 	osif_debug("Connect resp status %d", conn_rsp_params.status);
919 	ret = cfg80211_update_current_bss(dev, &conn_rsp_params, rsp->ssid.ssid,
920 					  rsp->ssid.length);
921 	if (ret)
922 		osif_err("cfg80211_update_current_bss failed for psoc:%d pdev:%d vdev:%d",
923 			 wlan_vdev_get_psoc_id(vdev),
924 			 wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev)),
925 			 wlan_vdev_get_id(vdev));
926 
927 	return qdf_status_from_os_return(ret);
928 }
929 
930 /**
931  * osif_update_current_bss_for_non_assoc_link_vdevs() - API to update the
932  * current_bss param of non-assoc link STA vdev.
933  * @vdev: Pointer to vdev
934  * @arg: Connection manager connect response
935  *
936  * Return: None.
937  */
osif_update_current_bss_for_non_assoc_link_vdevs(struct wlan_objmgr_vdev * vdev,void * arg)938 static void osif_update_current_bss_for_non_assoc_link_vdevs(
939 		struct wlan_objmgr_vdev *vdev, void *arg)
940 {
941 	struct wlan_objmgr_vdev *assoc_vdev;
942 	struct wlan_cm_connect_resp resp = {0};
943 	struct qdf_mac_addr macaddr = {0};
944 	struct vdev_osif_priv *osif_priv = NULL;
945 	struct wlan_cm_connect_resp *assoc_link_rsp;
946 
947 	assoc_link_rsp = (struct wlan_cm_connect_resp *)arg;
948 	if (!assoc_link_rsp) {
949 		osif_err("assoc_link_rsp is null");
950 		return;
951 	}
952 
953 	assoc_vdev = wlan_mlo_get_assoc_link_vdev(vdev);
954 
955 	/* For assoc vdev cfg80211_connect_done() is called to update the
956 	 * current bss param. Hence, skip the assoc vdev here.
957 	 */
958 	if (vdev == assoc_vdev)
959 		return;
960 
961 	wlan_vdev_mlme_get_ssid(vdev, resp.ssid.ssid, &resp.ssid.length);
962 
963 	wlan_vdev_get_bss_peer_mac(vdev, &macaddr);
964 	qdf_mem_copy(resp.bssid.bytes, macaddr.bytes, QDF_MAC_ADDR_SIZE);
965 
966 	resp.connect_status = assoc_link_rsp->connect_status;
967 
968 	osif_debug("vdev:%p bssid:" QDF_MAC_ADDR_FMT " ssid.length:%d ssid: " QDF_SSID_FMT,
969 		   vdev, QDF_MAC_ADDR_REF(macaddr.bytes), resp.ssid.length,
970 		   QDF_SSID_REF(resp.ssid.length, resp.ssid.ssid));
971 
972 	osif_priv = wlan_vdev_get_ospriv(vdev);
973 	osif_update_current_bss(osif_priv->wdev->netdev, NULL, &resp, vdev);
974 }
975 
976 /**
977  * osif_update_current_bss_for_non_assoc_links() - API to update the
978  * current_bss param of non-assoc link STA vdev.
979  * @assoc_vdev: Pointer to assoc vdev
980  * @rsp: Connection manager connect response
981  *
982  * Return: None.
983  */
osif_update_current_bss_for_non_assoc_links(struct wlan_objmgr_vdev * assoc_vdev,struct wlan_cm_connect_resp * rsp)984 static void osif_update_current_bss_for_non_assoc_links(
985 		struct wlan_objmgr_vdev *assoc_vdev,
986 		struct wlan_cm_connect_resp *rsp)
987 {
988 	mlo_iterate_connected_vdev_list(
989 			assoc_vdev,
990 			osif_update_current_bss_for_non_assoc_link_vdevs,
991 			rsp);
992 }
993 #else
osif_update_current_bss_for_non_assoc_links(struct wlan_objmgr_vdev * assoc_vdev,struct wlan_cm_connect_resp * rsp)994 static void osif_update_current_bss_for_non_assoc_links(
995 		struct wlan_objmgr_vdev *assoc_vdev,
996 		struct wlan_cm_connect_resp *rsp)
997 {
998 }
999 #endif
1000 
osif_indcate_connect_results(struct wlan_objmgr_vdev * vdev,struct vdev_osif_priv * osif_priv,struct wlan_cm_connect_resp * rsp)1001 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev,
1002 					 struct vdev_osif_priv *osif_priv,
1003 					 struct wlan_cm_connect_resp *rsp)
1004 {
1005 	struct cfg80211_bss *bss = NULL;
1006 	struct ieee80211_channel *chan;
1007 	struct wlan_objmgr_vdev *assoc_vdev = NULL;
1008 	struct vdev_osif_priv *tmp_osif_priv = NULL;
1009 	qdf_freq_t freq;
1010 	struct qdf_mac_addr macaddr = {0};
1011 	struct wlan_cm_connect_resp resp = {0};
1012 
1013 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
1014 		if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) {
1015 			chan = ieee80211_get_channel(osif_priv->wdev->wiphy,
1016 						     rsp->freq);
1017 			bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy,
1018 						    chan,
1019 						    rsp->bssid.bytes,
1020 						    rsp->ssid.ssid,
1021 						    rsp->ssid.length);
1022 		}
1023 		if (osif_update_connect_results(osif_priv->wdev->netdev, bss,
1024 						rsp, vdev))
1025 			osif_connect_bss(osif_priv->wdev->netdev, bss, rsp);
1026 		return;
1027 	}
1028 
1029 	if ((QDF_IS_STATUS_SUCCESS(rsp->connect_status) &&
1030 	    ucfg_mlo_is_mld_connected(vdev)) ||
1031 	    (QDF_IS_STATUS_ERROR(rsp->connect_status) &&
1032 	    ucfg_mlo_is_mld_disconnected(vdev))) {
1033 		assoc_vdev = ucfg_mlo_get_assoc_link_vdev(vdev);
1034 		if (!assoc_vdev)
1035 			return;
1036 		qdf_mem_copy(&resp, rsp, sizeof(struct wlan_cm_connect_resp));
1037 		tmp_osif_priv  = wlan_vdev_get_ospriv(assoc_vdev);
1038 		freq = assoc_vdev->vdev_mlme.bss_chan->ch_freq;
1039 		qdf_mem_copy(macaddr.bytes, rsp->bssid.bytes,
1040 			     QDF_MAC_ADDR_SIZE);
1041 		if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) {
1042 			wlan_vdev_get_bss_peer_mac(assoc_vdev, &macaddr);
1043 			chan = ieee80211_get_channel(tmp_osif_priv->wdev->wiphy,
1044 						     freq);
1045 			bss = wlan_cfg80211_get_bss(tmp_osif_priv->wdev->wiphy,
1046 						    chan,
1047 						    macaddr.bytes,
1048 						    rsp->ssid.ssid,
1049 						    rsp->ssid.length);
1050 		}
1051 		qdf_mem_copy(resp.bssid.bytes, macaddr.bytes,
1052 			     QDF_MAC_ADDR_SIZE);
1053 		resp.freq = freq;
1054 		resp.connect_ies.assoc_req.ptr = rsp->connect_ies.assoc_req.ptr;
1055 		resp.connect_ies.assoc_req.len = rsp->connect_ies.assoc_req.len;
1056 		resp.connect_ies.assoc_rsp.ptr = rsp->connect_ies.assoc_rsp.ptr;
1057 		resp.connect_ies.assoc_rsp.len = rsp->connect_ies.assoc_rsp.len;
1058 		if (osif_update_connect_results(tmp_osif_priv->wdev->netdev, bss,
1059 						&resp, assoc_vdev))
1060 			osif_connect_bss(tmp_osif_priv->wdev->netdev, bss, &resp);
1061 
1062 		if (QDF_IS_STATUS_SUCCESS(rsp->connect_status))
1063 			osif_update_current_bss_for_non_assoc_links(assoc_vdev,
1064 								    rsp);
1065 	}
1066 }
1067 #endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */
1068 #else /* WLAN_FEATURE_11BE_MLO */
osif_indcate_connect_results(struct wlan_objmgr_vdev * vdev,struct vdev_osif_priv * osif_priv,struct wlan_cm_connect_resp * rsp)1069 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev,
1070 					 struct vdev_osif_priv *osif_priv,
1071 					 struct wlan_cm_connect_resp *rsp)
1072 {
1073 	struct cfg80211_bss *bss = NULL;
1074 	struct ieee80211_channel *chan;
1075 
1076 	if (QDF_IS_STATUS_SUCCESS(rsp->connect_status)) {
1077 		chan = ieee80211_get_channel(osif_priv->wdev->wiphy,
1078 					     rsp->freq);
1079 		bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan,
1080 					    rsp->bssid.bytes,
1081 					    rsp->ssid.ssid,
1082 					    rsp->ssid.length);
1083 	}
1084 
1085 	if (osif_update_connect_results(osif_priv->wdev->netdev, bss,
1086 					rsp, vdev))
1087 		osif_connect_bss(osif_priv->wdev->netdev, bss, rsp);
1088 }
1089 #endif /* WLAN_FEATURE_11BE_MLO */
1090 #else  /* CFG80211_CONNECT_BSS */
1091 #ifdef WLAN_FEATURE_11BE_MLO
1092 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
osif_indcate_connect_results(struct wlan_objmgr_vdev * vdev,struct vdev_osif_priv * osif_priv,struct wlan_cm_connect_resp * rsp)1093 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev,
1094 					 struct vdev_osif_priv *osif_priv,
1095 					 struct wlan_cm_connect_resp *rsp)
1096 {
1097 	enum ieee80211_statuscode status;
1098 	size_t req_len = 0;
1099 	const uint8_t *req_ptr = NULL;
1100 	size_t rsp_len = 0;
1101 	const uint8_t *rsp_ptr = NULL;
1102 	struct wlan_objmgr_vdev *assoc_vdev = NULL;
1103 	struct vdev_osif_priv *tmp_osif_priv = NULL;
1104 
1105 	status = osif_get_connect_status_code(rsp);
1106 	osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req,
1107 				      &req_len, &req_ptr);
1108 	osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp,
1109 				      &rsp_len, &rsp_ptr);
1110 	if (wlan_vdev_mlme_is_mlo_vdev(vdev)) {
1111 		if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev))
1112 			cfg80211_connect_result(
1113 				osif_priv->wdev->netdev,
1114 				rsp->bssid.bytes, req_ptr, req_len,
1115 				rsp_ptr, rsp_len, status,
1116 				qdf_mem_malloc_flags());
1117 	} else {
1118 		cfg80211_connect_result(osif_priv->wdev->netdev,
1119 					rsp->bssid.bytes, req_ptr, req_len,
1120 					rsp_ptr, rsp_len, status,
1121 					qdf_mem_malloc_flags());
1122 	}
1123 }
1124 #else /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */
osif_indcate_connect_results(struct wlan_objmgr_vdev * vdev,struct vdev_osif_priv * osif_priv,struct wlan_cm_connect_resp * rsp)1125 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev,
1126 					 struct vdev_osif_priv *osif_priv,
1127 					 struct wlan_cm_connect_resp *rsp)
1128 {
1129 	enum ieee80211_statuscode status;
1130 	size_t req_len = 0;
1131 	const uint8_t *req_ptr = NULL;
1132 	size_t rsp_len = 0;
1133 	const uint8_t *rsp_ptr = NULL;
1134 	struct wlan_objmgr_vdev *assoc_vdev = NULL;
1135 	struct vdev_osif_priv *tmp_osif_priv = NULL;
1136 	struct qdf_mac_addr macaddr = {0};
1137 
1138 	status = osif_get_connect_status_code(rsp);
1139 	osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req,
1140 				      &req_len, &req_ptr);
1141 	osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp,
1142 				      &rsp_len, &rsp_ptr);
1143 	if (wlan_vdev_mlme_is_mlo_vdev(vdev)) {
1144 		if ((QDF_IS_STATUS_SUCCESS(rsp->connect_status) &&
1145 		    ucfg_mlo_is_mld_connected(vdev)) ||
1146 		    (QDF_IS_STATUS_ERROR(rsp->connect_status) &&
1147 		    ucfg_mlo_is_mld_disconnected(vdev))) {
1148 			assoc_vdev = ucfg_mlo_get_assoc_link_vdev(vdev);
1149 			if (!assoc_vdev)
1150 				return;
1151 			tmp_osif_priv  = wlan_vdev_get_ospriv(assoc_vdev);
1152 			wlan_vdev_get_bss_peer_mac(assoc_vdev, &macaddr);
1153 			cfg80211_connect_result(tmp_osif_priv->wdev->netdev,
1154 						macaddr.bytes, req_ptr,
1155 						req_len, rsp_ptr, rsp_len,
1156 						status, qdf_mem_malloc_flags());
1157 		}
1158 	} else {
1159 		cfg80211_connect_result(osif_priv->wdev->netdev,
1160 					rsp->bssid.bytes, req_ptr, req_len,
1161 					rsp_ptr, rsp_len, status,
1162 					qdf_mem_malloc_flags());
1163 	}
1164 }
1165 #endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */
1166 #else /* WLAN_FEATURE_11BE_MLO */
osif_indcate_connect_results(struct wlan_objmgr_vdev * vdev,struct vdev_osif_priv * osif_priv,struct wlan_cm_connect_resp * rsp)1167 static void osif_indcate_connect_results(struct wlan_objmgr_vdev *vdev,
1168 					 struct vdev_osif_priv *osif_priv,
1169 					 struct wlan_cm_connect_resp *rsp)
1170 {
1171 	enum ieee80211_statuscode status;
1172 	size_t req_len = 0;
1173 	const uint8_t *req_ptr = NULL;
1174 	size_t rsp_len = 0;
1175 	const uint8_t *rsp_ptr = NULL;
1176 
1177 	status = osif_get_connect_status_code(rsp);
1178 	osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req,
1179 				      &req_len, &req_ptr);
1180 	osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp,
1181 				      &rsp_len, &rsp_ptr);
1182 	cfg80211_connect_result(osif_priv->wdev->netdev,
1183 				rsp->bssid.bytes, req_ptr, req_len,
1184 				rsp_ptr, rsp_len, status,
1185 				qdf_mem_malloc_flags());
1186 }
1187 #endif /* WLAN_FEATURE_11BE_MLO */
1188 #endif /* CFG80211_CONNECT_BSS */
1189 
1190 #ifdef CONN_MGR_ADV_FEATURE
1191 static inline
osif_cm_is_unlink_bss_required(struct wlan_cm_connect_resp * rsp)1192 bool osif_cm_is_unlink_bss_required(struct wlan_cm_connect_resp *rsp)
1193 {
1194 	if (QDF_IS_STATUS_SUCCESS(rsp->connect_status) ||
1195 	    ucfg_cm_is_link_switch_connect_resp(rsp))
1196 		return false;
1197 
1198 	if (rsp->reason == CM_NO_CANDIDATE_FOUND ||
1199 	    rsp->reason == CM_JOIN_TIMEOUT ||
1200 	    rsp->reason == CM_AUTH_TIMEOUT ||
1201 	    rsp->reason == CM_ASSOC_TIMEOUT)
1202 		return true;
1203 
1204 	return false;
1205 }
osif_check_and_unlink_bss(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_resp * rsp)1206 static inline void osif_check_and_unlink_bss(struct wlan_objmgr_vdev *vdev,
1207 					     struct wlan_cm_connect_resp *rsp)
1208 {
1209 	if (osif_cm_is_unlink_bss_required(rsp))
1210 		osif_cm_unlink_bss(vdev, &rsp->bssid);
1211 }
1212 #else
osif_check_and_unlink_bss(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_resp * rsp)1213 static inline void osif_check_and_unlink_bss(struct wlan_objmgr_vdev *vdev,
1214 					     struct wlan_cm_connect_resp *rsp)
1215 {}
1216 #endif
1217 
1218 #define OSIF_CM_FAIL_INFO_STRING_SIZE 50
1219 
1220 static inline void
osif_dump_connect_rsp(struct wlan_objmgr_vdev * vdev,struct vdev_osif_priv * osif_priv,struct wlan_cm_connect_resp * rsp)1221 osif_dump_connect_rsp(struct wlan_objmgr_vdev *vdev,
1222 		      struct vdev_osif_priv *osif_priv,
1223 		      struct wlan_cm_connect_resp *rsp)
1224 {
1225 	char fail_info[OSIF_CM_FAIL_INFO_STRING_SIZE] = {0};
1226 
1227 	/* Fill status code and reason only on failure */
1228 	if (QDF_IS_STATUS_ERROR(rsp->connect_status))
1229 		qdf_scnprintf(fail_info, sizeof(fail_info),
1230 			      "reason %d status %d %s",
1231 			      rsp->reason, rsp->status_code,
1232 			      rsp->send_disconnect ?
1233 			      ", Send disconnect" : "");
1234 
1235 	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",
1236 		       osif_priv->wdev->netdev->name, rsp->vdev_id,
1237 		       QDF_MAC_ADDR_REF(wlan_vdev_mlme_get_macaddr(vdev)),
1238 		       rsp->is_reassoc ? "Roam" : "Connect",
1239 		       QDF_MAC_ADDR_REF(rsp->bssid.bytes),
1240 		       QDF_SSID_REF(rsp->ssid.length, rsp->ssid.ssid),
1241 		       rsp->connect_status ? "FAILURE" : "SUCCESS", rsp->cm_id,
1242 		       fail_info);
1243 }
1244 
osif_connect_handler(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_resp * rsp)1245 QDF_STATUS osif_connect_handler(struct wlan_objmgr_vdev *vdev,
1246 				struct wlan_cm_connect_resp *rsp)
1247 {
1248 	struct vdev_osif_priv *osif_priv  = wlan_vdev_get_ospriv(vdev);
1249 	QDF_STATUS status;
1250 
1251 	osif_dump_connect_rsp(vdev, osif_priv, rsp);
1252 	osif_check_and_unlink_bss(vdev, rsp);
1253 
1254 	status = osif_validate_connect_and_reset_src_id(osif_priv, rsp);
1255 	if (QDF_IS_STATUS_ERROR(status) ||
1256 	    ucfg_cm_is_link_switch_connect_resp(rsp)) {
1257 		osif_cm_connect_comp_ind(vdev, rsp, OSIF_NOT_HANDLED);
1258 		return status;
1259 	}
1260 
1261 	osif_cm_connect_comp_ind(vdev, rsp, OSIF_PRE_USERSPACE_UPDATE);
1262 
1263 	/*
1264 	 * To fix issue that scan with random address failed since wdev keeps
1265 	 * connected, rsp->send_disconnect is added.
1266 	 * Reproduce steps:
1267 	 *  1.  Connect from OSIF success, wdev->connected = true;
1268 	 *  2.  Disconnect from target if and reassoc from OSIF happens back to
1269 	 *	back.
1270 	 *  3.  Disconnect event is not sent to kernel, wdev->connected keeps
1271 	 *	true, isn't cleared.
1272 	 *  4.  Connect from OSIF failed too, wdev->connected keeps true,  isn't
1273 	 *	cleared.
1274 	 *  5.  Scan with random address failed since wdev->connected is true.
1275 	 *
1276 	 * To fix it, if connect req was a reassoc req and received in not
1277 	 * connected state for race between disconnect from target if and
1278 	 * reassoc connect from OSIF, set reassoc_in_non_connected to send
1279 	 * disconnect instead of connect rsp to kernel to cleanup kernel flags
1280 	 * like: wdev->connected.
1281 	 */
1282 	if (rsp->is_reassoc)
1283 		osif_indicate_reassoc_results(vdev, osif_priv, rsp);
1284 	else if (rsp->send_disconnect &&
1285 		 QDF_IS_STATUS_ERROR(rsp->connect_status))
1286 		osif_cm_indicate_disconnect(vdev, osif_priv->wdev->netdev,
1287 					    WLAN_REASON_UNSPECIFIED,
1288 					    false, NULL, 0, -1,
1289 					    qdf_mem_malloc_flags());
1290 	else
1291 		osif_indcate_connect_results(vdev, osif_priv, rsp);
1292 	osif_cm_connect_comp_ind(vdev, rsp, OSIF_POST_USERSPACE_UPDATE);
1293 
1294 	return QDF_STATUS_SUCCESS;
1295 }
1296 
osif_failed_candidate_handler(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_resp * rsp)1297 QDF_STATUS osif_failed_candidate_handler(struct wlan_objmgr_vdev *vdev,
1298 					 struct wlan_cm_connect_resp *rsp)
1299 {
1300 	struct vdev_osif_priv *osif_priv  = wlan_vdev_get_ospriv(vdev);
1301 
1302 	osif_dump_connect_rsp(vdev, osif_priv, rsp);
1303 
1304 	/**
1305 	 * Do not unlink the BSS if it is an ML candidate. In case of ML,
1306 	 * failed candidate may be used as partner link while trying the
1307 	 * connection on other links.
1308 	 */
1309 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
1310 		osif_check_and_unlink_bss(vdev, rsp);
1311 
1312 	return QDF_STATUS_SUCCESS;
1313 }
1314