xref: /wlan-driver/qca-wifi-host-cmn/os_if/linux/mlme/src/osif_cm_req.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2012-2015,2020-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for any
6*5113495bSYour Name  * purpose with or without fee is hereby granted, provided that the above
7*5113495bSYour Name  * copyright notice and this permission notice appear in all copies.
8*5113495bSYour Name  *
9*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10*5113495bSYour Name  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11*5113495bSYour Name  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12*5113495bSYour Name  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13*5113495bSYour Name  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14*5113495bSYour Name  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15*5113495bSYour Name  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16*5113495bSYour Name  */
17*5113495bSYour Name 
18*5113495bSYour Name /**
19*5113495bSYour Name  * DOC: osif_cm_req.c
20*5113495bSYour Name  *
21*5113495bSYour Name  * This file maintains definitaions of connect, disconnect, roam
22*5113495bSYour Name  * request apis.
23*5113495bSYour Name  */
24*5113495bSYour Name 
25*5113495bSYour Name #include "wlan_osif_priv.h"
26*5113495bSYour Name #include "osif_cm_req.h"
27*5113495bSYour Name #include "wlan_cm_ucfg_api.h"
28*5113495bSYour Name #include "wlan_nl_to_crypto_params.h"
29*5113495bSYour Name #include <wlan_cfg80211.h>
30*5113495bSYour Name #include "osif_cm_util.h"
31*5113495bSYour Name #ifdef WLAN_FEATURE_FILS_SK
32*5113495bSYour Name #include <wlan_mlme_ucfg_api.h>
33*5113495bSYour Name #endif
34*5113495bSYour Name #include <wlan_mlo_mgr_sta.h>
35*5113495bSYour Name #include <utils_mlo.h>
36*5113495bSYour Name #include <wlan_mgmt_txrx_rx_reo_utils_api.h>
37*5113495bSYour Name #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
38*5113495bSYour Name #include <wlan_mlo_mgr_setup.h>
39*5113495bSYour Name #endif
40*5113495bSYour Name 
41*5113495bSYour Name #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0) && \
42*5113495bSYour Name LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0) && \
43*5113495bSYour Name !defined(CFG80211_CRYPTO_WEP_KEYS_REMOVED)
44*5113495bSYour Name static QDF_STATUS
osif_cm_update_wep_seq_info(struct wlan_cm_connect_req * connect_req,const struct cfg80211_connect_params * req)45*5113495bSYour Name osif_cm_update_wep_seq_info(struct wlan_cm_connect_req *connect_req,
46*5113495bSYour Name 			    const struct cfg80211_connect_params *req)
47*5113495bSYour Name {
48*5113495bSYour Name 	if (req->crypto.wep_keys->seq_len) {
49*5113495bSYour Name 		connect_req->crypto.wep_keys.seq_len =
50*5113495bSYour Name 						req->crypto.wep_keys->seq_len;
51*5113495bSYour Name 		connect_req->crypto.wep_keys.seq =
52*5113495bSYour Name 			qdf_mem_malloc(connect_req->crypto.wep_keys.seq_len);
53*5113495bSYour Name 		if (!connect_req->crypto.wep_keys.seq) {
54*5113495bSYour Name 			ucfg_cm_free_wep_key_params(connect_req);
55*5113495bSYour Name 			return QDF_STATUS_E_NOMEM;
56*5113495bSYour Name 		}
57*5113495bSYour Name 		qdf_mem_copy(connect_req->crypto.wep_keys.seq,
58*5113495bSYour Name 			     req->crypto.wep_keys->seq,
59*5113495bSYour Name 			     connect_req->crypto.wep_keys.seq_len);
60*5113495bSYour Name 	}
61*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
62*5113495bSYour Name }
63*5113495bSYour Name #else
64*5113495bSYour Name static inline QDF_STATUS
osif_cm_update_wep_seq_info(struct wlan_cm_connect_req * connect_req,const struct cfg80211_connect_params * req)65*5113495bSYour Name osif_cm_update_wep_seq_info(struct wlan_cm_connect_req *connect_req,
66*5113495bSYour Name 			    const struct cfg80211_connect_params *req)
67*5113495bSYour Name {
68*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
69*5113495bSYour Name }
70*5113495bSYour Name #endif
71*5113495bSYour Name 
72*5113495bSYour Name #if !defined(CFG80211_CRYPTO_WEP_KEYS_REMOVED)
73*5113495bSYour Name static QDF_STATUS
osif_cm_set_wep_key_params(struct wlan_cm_connect_req * connect_req,const struct cfg80211_connect_params * req)74*5113495bSYour Name osif_cm_set_wep_key_params(struct wlan_cm_connect_req *connect_req,
75*5113495bSYour Name 			   const struct cfg80211_connect_params *req)
76*5113495bSYour Name {
77*5113495bSYour Name 	if (!req->key_len)
78*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
79*5113495bSYour Name 
80*5113495bSYour Name 	connect_req->crypto.wep_keys.key_len = req->key_len;
81*5113495bSYour Name 	connect_req->crypto.wep_keys.key_idx = req->key_idx;
82*5113495bSYour Name 
83*5113495bSYour Name 	connect_req->crypto.wep_keys.key =
84*5113495bSYour Name 			qdf_mem_malloc(connect_req->crypto.wep_keys.key_len);
85*5113495bSYour Name 	if (!connect_req->crypto.wep_keys.key)
86*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
87*5113495bSYour Name 
88*5113495bSYour Name 	qdf_mem_copy(connect_req->crypto.wep_keys.key, req->key,
89*5113495bSYour Name 		     connect_req->crypto.wep_keys.key_len);
90*5113495bSYour Name 
91*5113495bSYour Name 	return osif_cm_update_wep_seq_info(connect_req, req);
92*5113495bSYour Name }
93*5113495bSYour Name #else
94*5113495bSYour Name static QDF_STATUS
osif_cm_set_wep_key_params(struct wlan_cm_connect_req * connect_req,const struct cfg80211_connect_params * req)95*5113495bSYour Name osif_cm_set_wep_key_params(struct wlan_cm_connect_req *connect_req,
96*5113495bSYour Name 			   const struct cfg80211_connect_params *req)
97*5113495bSYour Name {
98*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
99*5113495bSYour Name }
100*5113495bSYour Name #endif
101*5113495bSYour Name 
osif_cm_set_auth_type(struct wlan_cm_connect_req * connect_req,const struct cfg80211_connect_params * req)102*5113495bSYour Name static void osif_cm_set_auth_type(struct wlan_cm_connect_req *connect_req,
103*5113495bSYour Name 				  const struct cfg80211_connect_params *req)
104*5113495bSYour Name {
105*5113495bSYour Name 	wlan_crypto_auth_mode crypto_auth_type =
106*5113495bSYour Name 			osif_nl_to_crypto_auth_type(req->auth_type);
107*5113495bSYour Name 
108*5113495bSYour Name 	/* For auto check wpa version to decide WPA or RSNA */
109*5113495bSYour Name 	if (crypto_auth_type == WLAN_CRYPTO_AUTH_AUTO &&
110*5113495bSYour Name 	    req->crypto.wpa_versions) {
111*5113495bSYour Name 		if (req->crypto.wpa_versions & NL80211_WPA_VERSION_1)
112*5113495bSYour Name 			crypto_auth_type = WLAN_CRYPTO_AUTH_WPA;
113*5113495bSYour Name 		else
114*5113495bSYour Name 			crypto_auth_type = WLAN_CRYPTO_AUTH_RSNA;
115*5113495bSYour Name 	} else if (!req->crypto.n_ciphers_pairwise) {
116*5113495bSYour Name 		crypto_auth_type = WLAN_CRYPTO_AUTH_OPEN;
117*5113495bSYour Name 	}
118*5113495bSYour Name 
119*5113495bSYour Name 	QDF_SET_PARAM(connect_req->crypto.auth_type, crypto_auth_type);
120*5113495bSYour Name }
121*5113495bSYour Name 
122*5113495bSYour Name static int
osif_cm_get_num_akm_suites(const struct cfg80211_connect_params * req)123*5113495bSYour Name osif_cm_get_num_akm_suites(const struct cfg80211_connect_params *req)
124*5113495bSYour Name {
125*5113495bSYour Name 	return req->crypto.n_akm_suites;
126*5113495bSYour Name }
127*5113495bSYour Name 
128*5113495bSYour Name static uint32_t*
osif_cm_get_akm_suites(const struct cfg80211_connect_params * req)129*5113495bSYour Name osif_cm_get_akm_suites(const struct cfg80211_connect_params *req)
130*5113495bSYour Name {
131*5113495bSYour Name 	return (uint32_t *)req->crypto.akm_suites;
132*5113495bSYour Name }
133*5113495bSYour Name 
134*5113495bSYour Name #ifdef CFG80211_MULTI_AKM_CONNECT_SUPPORT
135*5113495bSYour Name #define MAX_AKM_SUITES WLAN_CM_MAX_CONNECT_AKMS
136*5113495bSYour Name #else
137*5113495bSYour Name #define MAX_AKM_SUITES NL80211_MAX_NR_AKM_SUITES
138*5113495bSYour Name #endif
139*5113495bSYour Name static void
osif_cm_set_akm_params(struct wlan_cm_connect_req * connect_req,const struct cfg80211_connect_params * req)140*5113495bSYour Name osif_cm_set_akm_params(struct wlan_cm_connect_req *connect_req,
141*5113495bSYour Name 		       const struct cfg80211_connect_params *req)
142*5113495bSYour Name {
143*5113495bSYour Name 	uint32_t i;
144*5113495bSYour Name 	wlan_crypto_key_mgmt akm;
145*5113495bSYour Name 
146*5113495bSYour Name 	/* Fill AKM suites */
147*5113495bSYour Name 	if (req->crypto.n_akm_suites) {
148*5113495bSYour Name 		for (i = 0; i < req->crypto.n_akm_suites &&
149*5113495bSYour Name 		     i < MAX_AKM_SUITES; i++) {
150*5113495bSYour Name 			akm = osif_nl_to_crypto_akm_type(
151*5113495bSYour Name 					req->crypto.akm_suites[i]);
152*5113495bSYour Name 			QDF_SET_PARAM(connect_req->crypto.akm_suites, akm);
153*5113495bSYour Name 		}
154*5113495bSYour Name 	} else {
155*5113495bSYour Name 		QDF_SET_PARAM(connect_req->crypto.akm_suites,
156*5113495bSYour Name 			      WLAN_CRYPTO_KEY_MGMT_NONE);
157*5113495bSYour Name 	}
158*5113495bSYour Name }
159*5113495bSYour Name 
160*5113495bSYour Name static inline
osif_cm_get_rsn_cap_mfp(enum nl80211_mfp mfp_state)161*5113495bSYour Name uint8_t osif_cm_get_rsn_cap_mfp(enum nl80211_mfp mfp_state)
162*5113495bSYour Name {
163*5113495bSYour Name 	switch (mfp_state) {
164*5113495bSYour Name 	case NL80211_MFP_REQUIRED:
165*5113495bSYour Name 		return RSN_CAP_MFP_REQUIRED;
166*5113495bSYour Name 	case NL80211_MFP_OPTIONAL:
167*5113495bSYour Name 		return RSN_CAP_MFP_CAPABLE;
168*5113495bSYour Name 	default:
169*5113495bSYour Name 		return RSN_CAP_MFP_DISABLED;
170*5113495bSYour Name 	}
171*5113495bSYour Name }
172*5113495bSYour Name 
173*5113495bSYour Name #ifdef CONNECTIVITY_DIAG_EVENT
174*5113495bSYour Name /**
175*5113495bSYour Name  * osif_cm_populate_user_crypto_param() - API to cache crypto param
176*5113495bSYour Name  * received from the userspace.
177*5113495bSYour Name  * @connect_req: Connect request buffer to cache parameter
178*5113495bSYour Name  * @req: Connection request parameter received from userspace.
179*5113495bSYour Name  *
180*5113495bSYour Name  * Return: None
181*5113495bSYour Name  */
182*5113495bSYour Name static void
osif_cm_populate_user_crypto_param(struct wlan_cm_connect_req * connect_req,const struct cfg80211_connect_params * req)183*5113495bSYour Name osif_cm_populate_user_crypto_param(struct wlan_cm_connect_req *connect_req,
184*5113495bSYour Name 				   const struct cfg80211_connect_params *req)
185*5113495bSYour Name {
186*5113495bSYour Name 	connect_req->crypto.user_cipher_pairwise =
187*5113495bSYour Name 					req->crypto.ciphers_pairwise[0];
188*5113495bSYour Name 	connect_req->crypto.user_akm_suite = req->crypto.akm_suites[0];
189*5113495bSYour Name 	connect_req->crypto.user_auth_type = req->auth_type;
190*5113495bSYour Name 	connect_req->crypto.user_grp_cipher = req->crypto.cipher_group;
191*5113495bSYour Name }
192*5113495bSYour Name #else
193*5113495bSYour Name static void
osif_cm_populate_user_crypto_param(struct wlan_cm_connect_req * connect_req,const struct cfg80211_connect_params * req)194*5113495bSYour Name osif_cm_populate_user_crypto_param(struct wlan_cm_connect_req *connect_req,
195*5113495bSYour Name 				   const struct cfg80211_connect_params *req)
196*5113495bSYour Name {
197*5113495bSYour Name }
198*5113495bSYour Name #endif
199*5113495bSYour Name 
200*5113495bSYour Name static
osif_cm_set_crypto_params(struct wlan_cm_connect_req * connect_req,const struct cfg80211_connect_params * req)201*5113495bSYour Name QDF_STATUS osif_cm_set_crypto_params(struct wlan_cm_connect_req *connect_req,
202*5113495bSYour Name 				     const struct cfg80211_connect_params *req)
203*5113495bSYour Name {
204*5113495bSYour Name 	uint32_t i;
205*5113495bSYour Name 	QDF_STATUS status;
206*5113495bSYour Name 	wlan_crypto_cipher_type cipher = WLAN_CRYPTO_CIPHER_NONE;
207*5113495bSYour Name 
208*5113495bSYour Name 	connect_req->crypto.wpa_versions = req->crypto.wpa_versions;
209*5113495bSYour Name 
210*5113495bSYour Name 	osif_cm_set_auth_type(connect_req, req);
211*5113495bSYour Name 
212*5113495bSYour Name 	if (req->crypto.cipher_group)
213*5113495bSYour Name 		cipher =
214*5113495bSYour Name 			osif_nl_to_crypto_cipher_type(req->crypto.cipher_group);
215*5113495bSYour Name 
216*5113495bSYour Name 	QDF_SET_PARAM(connect_req->crypto.group_cipher, cipher);
217*5113495bSYour Name 
218*5113495bSYour Name 	/* Fill Pairwise ciphers */
219*5113495bSYour Name 	if (req->crypto.n_ciphers_pairwise) {
220*5113495bSYour Name 		for (i = 0; i < req->crypto.n_ciphers_pairwise &&
221*5113495bSYour Name 		     i < NL80211_MAX_NR_CIPHER_SUITES; i++) {
222*5113495bSYour Name 			cipher = osif_nl_to_crypto_cipher_type(
223*5113495bSYour Name 					req->crypto.ciphers_pairwise[i]);
224*5113495bSYour Name 			QDF_SET_PARAM(connect_req->crypto.ciphers_pairwise,
225*5113495bSYour Name 				      cipher);
226*5113495bSYour Name 		}
227*5113495bSYour Name 	} else {
228*5113495bSYour Name 		QDF_SET_PARAM(connect_req->crypto.ciphers_pairwise,
229*5113495bSYour Name 			      WLAN_CRYPTO_CIPHER_NONE);
230*5113495bSYour Name 	}
231*5113495bSYour Name 
232*5113495bSYour Name 	/* Fill AKM suites */
233*5113495bSYour Name 	osif_cm_set_akm_params(connect_req, req);
234*5113495bSYour Name 
235*5113495bSYour Name 	/* Fill WEP Key information */
236*5113495bSYour Name 	status = osif_cm_set_wep_key_params(connect_req, req);
237*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
238*5113495bSYour Name 		osif_err("set wep key params failed");
239*5113495bSYour Name 
240*5113495bSYour Name 	/* Copy user configured MFP capability */
241*5113495bSYour Name 	connect_req->crypto.user_mfp = osif_cm_get_rsn_cap_mfp(req->mfp);
242*5113495bSYour Name 
243*5113495bSYour Name 	osif_cm_populate_user_crypto_param(connect_req, req);
244*5113495bSYour Name 
245*5113495bSYour Name 	return status;
246*5113495bSYour Name }
247*5113495bSYour Name 
248*5113495bSYour Name #ifdef WLAN_FEATURE_FILS_SK
osif_cm_is_akm_suite_fils(uint32_t key_mgmt)249*5113495bSYour Name static bool osif_cm_is_akm_suite_fils(uint32_t key_mgmt)
250*5113495bSYour Name {
251*5113495bSYour Name 	switch (key_mgmt) {
252*5113495bSYour Name 	case WLAN_AKM_SUITE_FILS_SHA256:
253*5113495bSYour Name 	case WLAN_AKM_SUITE_FILS_SHA384:
254*5113495bSYour Name 	case WLAN_AKM_SUITE_FT_FILS_SHA256:
255*5113495bSYour Name 	case WLAN_AKM_SUITE_FT_FILS_SHA384:
256*5113495bSYour Name 		osif_debug("Fils AKM : %x", key_mgmt);
257*5113495bSYour Name 		return true;
258*5113495bSYour Name 	default:
259*5113495bSYour Name 		return false;
260*5113495bSYour Name 	}
261*5113495bSYour Name }
262*5113495bSYour Name 
osif_cm_is_conn_type_fils(struct wlan_cm_connect_req * connect_req,const struct cfg80211_connect_params * req)263*5113495bSYour Name static bool osif_cm_is_conn_type_fils(struct wlan_cm_connect_req *connect_req,
264*5113495bSYour Name 				      const struct cfg80211_connect_params *req)
265*5113495bSYour Name {
266*5113495bSYour Name 	int num_akm_suites;
267*5113495bSYour Name 	uint32_t *akm_suites;
268*5113495bSYour Name 	uint8_t i;
269*5113495bSYour Name 
270*5113495bSYour Name 	num_akm_suites = osif_cm_get_num_akm_suites(req);
271*5113495bSYour Name 	akm_suites = osif_cm_get_akm_suites(req);
272*5113495bSYour Name 
273*5113495bSYour Name 	if (num_akm_suites <= 0)
274*5113495bSYour Name 		return false;
275*5113495bSYour Name 
276*5113495bSYour Name 	/*
277*5113495bSYour Name 	 * Auth type will be either be OPEN or FILS type for a FILS connection
278*5113495bSYour Name 	 */
279*5113495bSYour Name 	if (connect_req->fils_info.auth_type == FILS_PK_MAX &&
280*5113495bSYour Name 	    req->auth_type != NL80211_AUTHTYPE_OPEN_SYSTEM)
281*5113495bSYour Name 		return false;
282*5113495bSYour Name 
283*5113495bSYour Name 	for (i = 0; i < num_akm_suites; i++) {
284*5113495bSYour Name 		if (!osif_cm_is_akm_suite_fils(akm_suites[i]))
285*5113495bSYour Name 			continue;
286*5113495bSYour Name 		return true;
287*5113495bSYour Name 	}
288*5113495bSYour Name 
289*5113495bSYour Name 
290*5113495bSYour Name 	return false;
291*5113495bSYour Name }
292*5113495bSYour Name 
293*5113495bSYour Name enum wlan_fils_auth_type
osif_cm_get_fils_auth_type(enum nl80211_auth_type auth)294*5113495bSYour Name osif_cm_get_fils_auth_type(enum nl80211_auth_type auth)
295*5113495bSYour Name {
296*5113495bSYour Name 	switch (auth) {
297*5113495bSYour Name 	case NL80211_AUTHTYPE_FILS_SK:
298*5113495bSYour Name 		return FILS_SK_WITHOUT_PFS;
299*5113495bSYour Name 	case NL80211_AUTHTYPE_FILS_SK_PFS:
300*5113495bSYour Name 		return FILS_SK_WITH_PFS;
301*5113495bSYour Name 	case NL80211_AUTHTYPE_FILS_PK:
302*5113495bSYour Name 		return FILS_PK_AUTH;
303*5113495bSYour Name 	default:
304*5113495bSYour Name 		return FILS_PK_MAX;
305*5113495bSYour Name 	}
306*5113495bSYour Name }
307*5113495bSYour Name 
308*5113495bSYour Name static QDF_STATUS
osif_cm_set_fils_info(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_req * connect_req,const struct cfg80211_connect_params * req)309*5113495bSYour Name osif_cm_set_fils_info(struct wlan_objmgr_vdev *vdev,
310*5113495bSYour Name 		      struct wlan_cm_connect_req *connect_req,
311*5113495bSYour Name 		      const struct cfg80211_connect_params *req)
312*5113495bSYour Name {
313*5113495bSYour Name 	bool value = 0;
314*5113495bSYour Name 	QDF_STATUS status;
315*5113495bSYour Name 	uint8_t *buf;
316*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
317*5113495bSYour Name 
318*5113495bSYour Name 	psoc = wlan_vdev_get_psoc(vdev);
319*5113495bSYour Name 	if (!psoc)
320*5113495bSYour Name 		return -QDF_STATUS_E_INVAL;
321*5113495bSYour Name 
322*5113495bSYour Name 	connect_req->fils_info.auth_type =
323*5113495bSYour Name 		osif_cm_get_fils_auth_type(req->auth_type);
324*5113495bSYour Name 	connect_req->fils_info.is_fils_connection =
325*5113495bSYour Name 					osif_cm_is_conn_type_fils(connect_req,
326*5113495bSYour Name 								  req);
327*5113495bSYour Name 	osif_debug("auth type %d is fils %d",
328*5113495bSYour Name 		   connect_req->fils_info.auth_type,
329*5113495bSYour Name 		   connect_req->fils_info.is_fils_connection);
330*5113495bSYour Name 	if (!connect_req->fils_info.is_fils_connection)
331*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
332*5113495bSYour Name 
333*5113495bSYour Name 	status = ucfg_mlme_get_fils_enabled_info(psoc, &value);
334*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status) || !value) {
335*5113495bSYour Name 		osif_err("get_fils_enabled status: %d fils_enabled: %d",
336*5113495bSYour Name 			 status, value);
337*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
338*5113495bSYour Name 	}
339*5113495bSYour Name 
340*5113495bSYour Name 	/*
341*5113495bSYour Name 	 * The initial connection for FILS may happen with an OPEN
342*5113495bSYour Name 	 * auth type. Hence we need to allow the connection to go
343*5113495bSYour Name 	 * through in that case as well.
344*5113495bSYour Name 	 */
345*5113495bSYour Name 	if (req->auth_type != NL80211_AUTHTYPE_FILS_SK) {
346*5113495bSYour Name 		osif_debug("set is fils false for initial connection");
347*5113495bSYour Name 		connect_req->fils_info.is_fils_connection = false;
348*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
349*5113495bSYour Name 	}
350*5113495bSYour Name 
351*5113495bSYour Name 	connect_req->fils_info.realm_len = req->fils_erp_realm_len;
352*5113495bSYour Name 
353*5113495bSYour Name 	if (connect_req->fils_info.realm_len > WLAN_CM_FILS_MAX_REALM_LEN) {
354*5113495bSYour Name 		osif_err("Invalid fils realm len %d",
355*5113495bSYour Name 			 connect_req->fils_info.realm_len);
356*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
357*5113495bSYour Name 	}
358*5113495bSYour Name 	qdf_mem_zero(connect_req->fils_info.realm, WLAN_CM_FILS_MAX_REALM_LEN);
359*5113495bSYour Name 	qdf_mem_copy(connect_req->fils_info.realm, req->fils_erp_realm,
360*5113495bSYour Name 		     connect_req->fils_info.realm_len);
361*5113495bSYour Name 
362*5113495bSYour Name 	connect_req->fils_info.next_seq_num = req->fils_erp_next_seq_num + 1;
363*5113495bSYour Name 
364*5113495bSYour Name 	connect_req->fils_info.rrk_len = req->fils_erp_rrk_len;
365*5113495bSYour Name 
366*5113495bSYour Name 	if (connect_req->fils_info.rrk_len > WLAN_CM_FILS_MAX_RRK_LENGTH) {
367*5113495bSYour Name 		osif_err("Invalid fils rrk len %d",
368*5113495bSYour Name 			 connect_req->fils_info.rrk_len);
369*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
370*5113495bSYour Name 	}
371*5113495bSYour Name 	qdf_mem_zero(connect_req->fils_info.rrk, WLAN_CM_FILS_MAX_RRK_LENGTH);
372*5113495bSYour Name 	qdf_mem_copy(connect_req->fils_info.rrk, req->fils_erp_rrk,
373*5113495bSYour Name 		     connect_req->fils_info.rrk_len);
374*5113495bSYour Name 
375*5113495bSYour Name 	connect_req->fils_info.username_len = req->fils_erp_username_len +
376*5113495bSYour Name 					sizeof(char) + req->fils_erp_realm_len;
377*5113495bSYour Name 	osif_debug("usrname len %d = usrname recv len %zu + realm len %d + %zu",
378*5113495bSYour Name 		   connect_req->fils_info.username_len,
379*5113495bSYour Name 		   req->fils_erp_username_len,
380*5113495bSYour Name 		   connect_req->fils_info.realm_len, sizeof(char));
381*5113495bSYour Name 
382*5113495bSYour Name 	if (connect_req->fils_info.username_len >
383*5113495bSYour Name 					WLAN_CM_FILS_MAX_KEYNAME_NAI_LENGTH) {
384*5113495bSYour Name 		osif_err("Invalid fils username len %d",
385*5113495bSYour Name 			 connect_req->fils_info.username_len);
386*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
387*5113495bSYour Name 	}
388*5113495bSYour Name 	if (!req->fils_erp_username_len) {
389*5113495bSYour Name 		osif_info("FILS_PMKSA: No ERP username, return success");
390*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
391*5113495bSYour Name 	}
392*5113495bSYour Name 	buf = connect_req->fils_info.username;
393*5113495bSYour Name 	qdf_mem_zero(connect_req->fils_info.username,
394*5113495bSYour Name 		     WLAN_CM_FILS_MAX_KEYNAME_NAI_LENGTH);
395*5113495bSYour Name 	qdf_mem_copy(buf, req->fils_erp_username, req->fils_erp_username_len);
396*5113495bSYour Name 	buf += req->fils_erp_username_len;
397*5113495bSYour Name 	*buf++ = '@';
398*5113495bSYour Name 	qdf_mem_copy(buf, req->fils_erp_realm, req->fils_erp_realm_len);
399*5113495bSYour Name 
400*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
401*5113495bSYour Name }
402*5113495bSYour Name #else
403*5113495bSYour Name static inline
osif_cm_set_fils_info(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_req * connect_req,const struct cfg80211_connect_params * req)404*5113495bSYour Name QDF_STATUS osif_cm_set_fils_info(struct wlan_objmgr_vdev *vdev,
405*5113495bSYour Name 				 struct wlan_cm_connect_req *connect_req,
406*5113495bSYour Name 				 const struct cfg80211_connect_params *req)
407*5113495bSYour Name {
408*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
409*5113495bSYour Name }
410*5113495bSYour Name #endif
411*5113495bSYour Name 
412*5113495bSYour Name #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
413*5113495bSYour Name static inline void
osif_cm_set_prev_bssid(struct wlan_cm_connect_req * connect_req,const struct cfg80211_connect_params * req)414*5113495bSYour Name osif_cm_set_prev_bssid(struct wlan_cm_connect_req *connect_req,
415*5113495bSYour Name 		       const struct cfg80211_connect_params *req)
416*5113495bSYour Name {
417*5113495bSYour Name 	if (req->prev_bssid)
418*5113495bSYour Name 		qdf_mem_copy(connect_req->prev_bssid.bytes, req->prev_bssid,
419*5113495bSYour Name 			     QDF_MAC_ADDR_SIZE);
420*5113495bSYour Name }
421*5113495bSYour Name 
422*5113495bSYour Name static inline
osif_cm_dump_prev_bssid(const struct cfg80211_connect_params * req)423*5113495bSYour Name void osif_cm_dump_prev_bssid(const struct cfg80211_connect_params *req)
424*5113495bSYour Name {
425*5113495bSYour Name 	if (req->prev_bssid)
426*5113495bSYour Name 		osif_nofl_debug("prev BSSID "QDF_MAC_ADDR_FMT,
427*5113495bSYour Name 				QDF_MAC_ADDR_REF(req->prev_bssid));
428*5113495bSYour Name }
429*5113495bSYour Name 
430*5113495bSYour Name #else
431*5113495bSYour Name static inline void
osif_cm_set_prev_bssid(struct wlan_cm_connect_req * connect_req,const struct cfg80211_connect_params * req)432*5113495bSYour Name osif_cm_set_prev_bssid(struct wlan_cm_connect_req *connect_req,
433*5113495bSYour Name 		       const struct cfg80211_connect_params *req)
434*5113495bSYour Name {
435*5113495bSYour Name }
436*5113495bSYour Name 
437*5113495bSYour Name static inline
osif_cm_dump_prev_bssid(const struct cfg80211_connect_params * req)438*5113495bSYour Name void osif_cm_dump_prev_bssid(const struct cfg80211_connect_params *req)
439*5113495bSYour Name {
440*5113495bSYour Name }
441*5113495bSYour Name 
442*5113495bSYour Name #endif
443*5113495bSYour Name 
444*5113495bSYour Name static inline void
osif_cm_dump_connect_req(struct net_device * dev,uint8_t vdev_id,const struct cfg80211_connect_params * req)445*5113495bSYour Name osif_cm_dump_connect_req(struct net_device *dev, uint8_t vdev_id,
446*5113495bSYour Name 			 const struct cfg80211_connect_params *req)
447*5113495bSYour Name {
448*5113495bSYour Name 	uint32_t i;
449*5113495bSYour Name 	uint32_t num_akm_suites;
450*5113495bSYour Name 	uint32_t *akm_suites;
451*5113495bSYour Name 
452*5113495bSYour Name 	num_akm_suites = osif_cm_get_num_akm_suites(req);
453*5113495bSYour Name 	akm_suites = osif_cm_get_akm_suites(req);
454*5113495bSYour Name 
455*5113495bSYour Name 	osif_nofl_debug("connect req for %s(vdevid-%d) freq %d SSID " QDF_SSID_FMT " auth type %d WPA ver %d n_akm %d n_cipher %d grp_cipher %x mfp %d freq hint %d",
456*5113495bSYour Name 			dev->name, vdev_id,
457*5113495bSYour Name 			req->channel ? req->channel->center_freq : 0,
458*5113495bSYour Name 			QDF_SSID_REF((int)req->ssid_len, req->ssid),
459*5113495bSYour Name 			req->auth_type, req->crypto.wpa_versions,
460*5113495bSYour Name 			num_akm_suites,
461*5113495bSYour Name 			req->crypto.n_ciphers_pairwise,
462*5113495bSYour Name 			req->crypto.cipher_group, req->mfp,
463*5113495bSYour Name 			req->channel_hint ? req->channel_hint->center_freq : 0);
464*5113495bSYour Name 	if (req->bssid)
465*5113495bSYour Name 		osif_nofl_debug("BSSID "QDF_MAC_ADDR_FMT,
466*5113495bSYour Name 				QDF_MAC_ADDR_REF(req->bssid));
467*5113495bSYour Name 	if (req->bssid_hint)
468*5113495bSYour Name 		osif_nofl_debug("BSSID hint "QDF_MAC_ADDR_FMT,
469*5113495bSYour Name 				QDF_MAC_ADDR_REF(req->bssid_hint));
470*5113495bSYour Name 	osif_cm_dump_prev_bssid(req);
471*5113495bSYour Name 
472*5113495bSYour Name 	for (i = 0; i < num_akm_suites; i++)
473*5113495bSYour Name 		osif_nofl_debug("akm[%d] = %x", i, akm_suites[i]);
474*5113495bSYour Name 
475*5113495bSYour Name 	for (i = 0; i < req->crypto.n_ciphers_pairwise; i++)
476*5113495bSYour Name 		osif_nofl_debug("cipher_pairwise[%d] = %x", i,
477*5113495bSYour Name 				req->crypto.ciphers_pairwise[i]);
478*5113495bSYour Name }
479*5113495bSYour Name 
480*5113495bSYour Name static void
osif_cm_fill_connect_params(struct wlan_cm_connect_req * req,const struct osif_connect_params * params)481*5113495bSYour Name osif_cm_fill_connect_params(struct wlan_cm_connect_req *req,
482*5113495bSYour Name 			    const struct osif_connect_params *params)
483*5113495bSYour Name {
484*5113495bSYour Name 	if (!params)
485*5113495bSYour Name 		return;
486*5113495bSYour Name 
487*5113495bSYour Name 	if (params->scan_ie.len) {
488*5113495bSYour Name 		req->scan_ie.ptr = qdf_mem_malloc(params->scan_ie.len);
489*5113495bSYour Name 		if (req->scan_ie.ptr) {
490*5113495bSYour Name 			qdf_mem_copy(req->scan_ie.ptr, params->scan_ie.ptr,
491*5113495bSYour Name 				     params->scan_ie.len);
492*5113495bSYour Name 			req->scan_ie.len = params->scan_ie.len;
493*5113495bSYour Name 		}
494*5113495bSYour Name 	}
495*5113495bSYour Name 	req->dot11mode_filter = params->dot11mode_filter;
496*5113495bSYour Name 	req->force_rsne_override = params->force_rsne_override;
497*5113495bSYour Name 	req->sae_pwe = params->sae_pwe;
498*5113495bSYour Name 
499*5113495bSYour Name 	if (!qdf_is_macaddr_zero((struct qdf_mac_addr *)&params->prev_bssid))
500*5113495bSYour Name 		qdf_copy_macaddr(&req->prev_bssid,
501*5113495bSYour Name 				 (struct qdf_mac_addr *)&params->prev_bssid);
502*5113495bSYour Name }
503*5113495bSYour Name 
504*5113495bSYour Name #ifdef WLAN_FEATURE_11BE_MLO
505*5113495bSYour Name #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
506*5113495bSYour Name static inline
osif_update_mlo_partner_info(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_req * connect_req,const struct cfg80211_connect_params * req)507*5113495bSYour Name QDF_STATUS osif_update_mlo_partner_info(
508*5113495bSYour Name 			struct wlan_objmgr_vdev *vdev,
509*5113495bSYour Name 			struct wlan_cm_connect_req *connect_req,
510*5113495bSYour Name 			const struct cfg80211_connect_params *req)
511*5113495bSYour Name {
512*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
513*5113495bSYour Name }
514*5113495bSYour Name #else
515*5113495bSYour Name static inline
osif_update_partner_vdev_info(struct wlan_objmgr_vdev * vdev,struct mlo_partner_info partner_info)516*5113495bSYour Name void osif_update_partner_vdev_info(struct wlan_objmgr_vdev *vdev,
517*5113495bSYour Name 				   struct mlo_partner_info partner_info)
518*5113495bSYour Name {
519*5113495bSYour Name 	struct wlan_objmgr_vdev *tmp_vdev;
520*5113495bSYour Name 	struct wlan_mlo_dev_context *ml_dev = NULL;
521*5113495bSYour Name 	uint8_t i;
522*5113495bSYour Name 	uint8_t link_id;
523*5113495bSYour Name 
524*5113495bSYour Name 	if (!vdev)
525*5113495bSYour Name 		return;
526*5113495bSYour Name 
527*5113495bSYour Name 	ml_dev = vdev->mlo_dev_ctx;
528*5113495bSYour Name 	if (!ml_dev)
529*5113495bSYour Name 		return;
530*5113495bSYour Name 
531*5113495bSYour Name 	for (i = 0; i < partner_info.num_partner_links; i++) {
532*5113495bSYour Name 		tmp_vdev = mlo_get_ml_vdev_by_mac(
533*5113495bSYour Name 				vdev,
534*5113495bSYour Name 				&partner_info.partner_link_info[i].link_addr);
535*5113495bSYour Name 		if (tmp_vdev) {
536*5113495bSYour Name 			mlo_update_connect_req_links(tmp_vdev, 1);
537*5113495bSYour Name 			wlan_vdev_mlme_set_mlo_vdev(tmp_vdev);
538*5113495bSYour Name 			wlan_vdev_mlme_set_mlo_link_vdev(tmp_vdev);
539*5113495bSYour Name 			/* Set link id for bridge sta vap */
540*5113495bSYour Name 			if (mlo_is_sta_bridge_vdev(tmp_vdev)) {
541*5113495bSYour Name 				link_id = ml_dev->bridge_sta_ctx->bridge_link_id;
542*5113495bSYour Name 				wlan_vdev_set_link_id(tmp_vdev, link_id);
543*5113495bSYour Name 			} else
544*5113495bSYour Name 				wlan_vdev_set_link_id(
545*5113495bSYour Name 					tmp_vdev,
546*5113495bSYour Name 					partner_info.partner_link_info[i].link_id);
547*5113495bSYour Name 			osif_debug("link id %d",
548*5113495bSYour Name 				   tmp_vdev->vdev_mlme.mlo_link_id);
549*5113495bSYour Name 		}
550*5113495bSYour Name 	}
551*5113495bSYour Name }
552*5113495bSYour Name 
553*5113495bSYour Name static inline
osif_update_mlo_partner_info(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_req * connect_req,const struct cfg80211_connect_params * req)554*5113495bSYour Name QDF_STATUS osif_update_mlo_partner_info(
555*5113495bSYour Name 			struct wlan_objmgr_vdev *vdev,
556*5113495bSYour Name 			struct wlan_cm_connect_req *connect_req,
557*5113495bSYour Name 			const struct cfg80211_connect_params *req)
558*5113495bSYour Name {
559*5113495bSYour Name 	/* Update ml partner info from connect req*/
560*5113495bSYour Name 	uint8_t *ptr = NULL;
561*5113495bSYour Name 	uint8_t *ml_ie = NULL;
562*5113495bSYour Name 	qdf_size_t ml_ie_len = 0;
563*5113495bSYour Name 	struct mlo_partner_info partner_info = {0};
564*5113495bSYour Name 	bool ml_ie_found = false, linkidfound = false;
565*5113495bSYour Name 	uint8_t linkid = 0;
566*5113495bSYour Name 	uint8_t aplinks = 0;
567*5113495bSYour Name 	enum wlan_ml_variant variant;
568*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
569*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev = NULL;
570*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
571*5113495bSYour Name 	struct wlan_mlo_dev_context *ml_dev = NULL;
572*5113495bSYour Name 
573*5113495bSYour Name 	if (!vdev || !connect_req || !req)
574*5113495bSYour Name 		return status;
575*5113495bSYour Name 
576*5113495bSYour Name 	ml_dev = vdev->mlo_dev_ctx;
577*5113495bSYour Name 	if (!ml_dev) {
578*5113495bSYour Name 		osif_debug("ML ctx is NULL, ignore ML IE");
579*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
580*5113495bSYour Name 	}
581*5113495bSYour Name 	pdev = wlan_vdev_get_pdev(vdev);
582*5113495bSYour Name 
583*5113495bSYour Name 	if (!pdev) {
584*5113495bSYour Name 		osif_debug("null pdev");
585*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
586*5113495bSYour Name 	}
587*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
588*5113495bSYour Name 
589*5113495bSYour Name 	if (!psoc) {
590*5113495bSYour Name 		osif_debug("null psoc");
591*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
592*5113495bSYour Name 	}
593*5113495bSYour Name 
594*5113495bSYour Name 	if (!wlan_mlo_get_psoc_capable(psoc))
595*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
596*5113495bSYour Name 
597*5113495bSYour Name 	osif_debug("ML IE search start");
598*5113495bSYour Name 	if (req->ie_len) {
599*5113495bSYour Name 		ptr = (uint8_t *)req->ie;
600*5113495bSYour Name 		status = util_find_mlie(ptr, req->ie_len, &ml_ie, &ml_ie_len);
601*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status) || !ml_ie) {
602*5113495bSYour Name 			osif_debug("ML IE not found");
603*5113495bSYour Name 			/* Return success since ML is not mandatory for a
604*5113495bSYour Name 			 * connect request
605*5113495bSYour Name 			 */
606*5113495bSYour Name 			return QDF_STATUS_SUCCESS;
607*5113495bSYour Name 		}
608*5113495bSYour Name 
609*5113495bSYour Name 		osif_debug("ML IE found length %d", (int)ml_ie_len);
610*5113495bSYour Name 		qdf_trace_hex_dump(QDF_MODULE_ID_OS_IF, QDF_TRACE_LEVEL_DEBUG,
611*5113495bSYour Name 				   ml_ie, (int)ml_ie_len);
612*5113495bSYour Name 		ml_ie_found = true;
613*5113495bSYour Name 
614*5113495bSYour Name 		status = util_get_mlie_variant(ml_ie, ml_ie_len,
615*5113495bSYour Name 					       (int *)&variant);
616*5113495bSYour Name 		if (status != QDF_STATUS_SUCCESS) {
617*5113495bSYour Name 			osif_err("Unable to get Multi-Link element variant");
618*5113495bSYour Name 			return status;
619*5113495bSYour Name 		}
620*5113495bSYour Name 
621*5113495bSYour Name 		if (variant != WLAN_ML_VARIANT_BASIC) {
622*5113495bSYour Name 			osif_err("Invalid Multi-Link element variant %u",
623*5113495bSYour Name 				 variant);
624*5113495bSYour Name 			return status;
625*5113495bSYour Name 		}
626*5113495bSYour Name 
627*5113495bSYour Name 		status = util_get_bvmlie_primary_linkid(ml_ie, ml_ie_len,
628*5113495bSYour Name 							&linkidfound, &linkid);
629*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
630*5113495bSYour Name 			osif_err("Unable to find primary link ID in ML IE");
631*5113495bSYour Name 			return status;
632*5113495bSYour Name 		}
633*5113495bSYour Name 
634*5113495bSYour Name 		status = util_get_bvmlie_persta_partner_info(ml_ie, ml_ie_len,
635*5113495bSYour Name 							     &partner_info);
636*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
637*5113495bSYour Name 			osif_err("Unable to find per-sta profile in ML IE");
638*5113495bSYour Name 			return status;
639*5113495bSYour Name 		}
640*5113495bSYour Name 
641*5113495bSYour Name 		if (partner_info.num_partner_links + 1 >
642*5113495bSYour Name 			WLAN_UMAC_MLO_ASSOC_MAX_SUPPORTED_LINKS) {
643*5113495bSYour Name 			osif_err("Rejecting connect for more than %d Assoc links",
644*5113495bSYour Name 				 WLAN_UMAC_MLO_ASSOC_MAX_SUPPORTED_LINKS);
645*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
646*5113495bSYour Name 		}
647*5113495bSYour Name 
648*5113495bSYour Name 		wlan_vdev_set_link_id(vdev, linkid);
649*5113495bSYour Name 		wlan_vdev_mlme_set_mlo_vdev(vdev);
650*5113495bSYour Name 	}
651*5113495bSYour Name 
652*5113495bSYour Name 	qdf_mem_copy(&connect_req->ml_parnter_info,
653*5113495bSYour Name 		     &partner_info, sizeof(struct mlo_partner_info));
654*5113495bSYour Name 	/* Get total number of links in association */
655*5113495bSYour Name 	aplinks = partner_info.num_partner_links + 1;
656*5113495bSYour Name 	if (ml_ie_found) {
657*5113495bSYour Name 		mlo_clear_connect_req_links_bmap(vdev);
658*5113495bSYour Name 		/* Handle 4 LINK RDP Case*/
659*5113495bSYour Name 		if (mlo_check_topology(pdev, vdev, aplinks) != QDF_STATUS_SUCCESS) {
660*5113495bSYour Name 			osif_err("Topology check failed prevent association\n");
661*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
662*5113495bSYour Name 		}
663*5113495bSYour Name 
664*5113495bSYour Name 		if (mlo_sta_bridge_exists(vdev))
665*5113495bSYour Name 			mlo_update_partner_bridge_info(ml_dev, &partner_info);
666*5113495bSYour Name 
667*5113495bSYour Name 		mlo_update_connect_req_links(vdev, 1);
668*5113495bSYour Name 		osif_update_partner_vdev_info(vdev, partner_info);
669*5113495bSYour Name 		mlo_mlme_sta_op_class(vdev, ml_ie);
670*5113495bSYour Name 	}
671*5113495bSYour Name 
672*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
673*5113495bSYour Name }
674*5113495bSYour Name #endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */
675*5113495bSYour Name #else
676*5113495bSYour Name static inline
osif_update_mlo_partner_info(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_req * connect_req,const struct cfg80211_connect_params * req)677*5113495bSYour Name QDF_STATUS osif_update_mlo_partner_info(
678*5113495bSYour Name 			struct wlan_objmgr_vdev *vdev,
679*5113495bSYour Name 			struct wlan_cm_connect_req *connect_req,
680*5113495bSYour Name 			const struct cfg80211_connect_params *req)
681*5113495bSYour Name {
682*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
683*5113495bSYour Name }
684*5113495bSYour Name #endif
685*5113495bSYour Name 
osif_cm_connect(struct net_device * dev,struct wlan_objmgr_vdev * vdev,const struct cfg80211_connect_params * req,const struct osif_connect_params * params)686*5113495bSYour Name int osif_cm_connect(struct net_device *dev, struct wlan_objmgr_vdev *vdev,
687*5113495bSYour Name 		    const struct cfg80211_connect_params *req,
688*5113495bSYour Name 		    const struct osif_connect_params *params)
689*5113495bSYour Name {
690*5113495bSYour Name 	struct wlan_cm_connect_req *connect_req;
691*5113495bSYour Name 	const u8 *bssid_hint = req->bssid_hint;
692*5113495bSYour Name 	uint8_t vdev_id = vdev->vdev_objmgr.vdev_id;
693*5113495bSYour Name 	QDF_STATUS status;
694*5113495bSYour Name 	struct qdf_mac_addr bssid = QDF_MAC_ADDR_BCAST_INIT;
695*5113495bSYour Name 	struct wlan_objmgr_vdev *temp_vdev;
696*5113495bSYour Name 
697*5113495bSYour Name 	if (req->bssid)
698*5113495bSYour Name 		qdf_mem_copy(bssid.bytes, req->bssid,
699*5113495bSYour Name 			     QDF_MAC_ADDR_SIZE);
700*5113495bSYour Name 	else if (bssid_hint)
701*5113495bSYour Name 		qdf_mem_copy(bssid.bytes, req->bssid_hint,
702*5113495bSYour Name 			     QDF_MAC_ADDR_SIZE);
703*5113495bSYour Name 
704*5113495bSYour Name 	temp_vdev = wlan_objmgr_get_vdev_by_macaddr_from_pdev(
705*5113495bSYour Name 						wlan_vdev_get_pdev(vdev),
706*5113495bSYour Name 						bssid.bytes,
707*5113495bSYour Name 						WLAN_OSIF_CM_ID);
708*5113495bSYour Name 
709*5113495bSYour Name 	if (temp_vdev) {
710*5113495bSYour Name 		osif_err("vdev %d already exist with same mac address"
711*5113495bSYour Name 			 QDF_MAC_ADDR_FMT, wlan_vdev_get_id(temp_vdev),
712*5113495bSYour Name 			 QDF_MAC_ADDR_REF(bssid.bytes));
713*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(temp_vdev, WLAN_OSIF_CM_ID);
714*5113495bSYour Name 		return -EINVAL;
715*5113495bSYour Name 	}
716*5113495bSYour Name 	osif_cm_dump_connect_req(dev, vdev_id, req);
717*5113495bSYour Name 
718*5113495bSYour Name 	status = osif_cm_reset_id_and_src(vdev);
719*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
720*5113495bSYour Name 		return qdf_status_to_os_return(status);
721*5113495bSYour Name 
722*5113495bSYour Name 	connect_req = qdf_mem_malloc(sizeof(*connect_req));
723*5113495bSYour Name 	if (!connect_req)
724*5113495bSYour Name 		return -ENOMEM;
725*5113495bSYour Name 
726*5113495bSYour Name 	connect_req->vdev_id = vdev_id;
727*5113495bSYour Name 	connect_req->source = CM_OSIF_CONNECT;
728*5113495bSYour Name 	if (req->bssid)
729*5113495bSYour Name 		qdf_mem_copy(connect_req->bssid.bytes, req->bssid,
730*5113495bSYour Name 			     QDF_MAC_ADDR_SIZE);
731*5113495bSYour Name 	else if (bssid_hint)
732*5113495bSYour Name 		qdf_mem_copy(connect_req->bssid_hint.bytes, req->bssid_hint,
733*5113495bSYour Name 			     QDF_MAC_ADDR_SIZE);
734*5113495bSYour Name 
735*5113495bSYour Name 	osif_cm_set_prev_bssid(connect_req, req);
736*5113495bSYour Name 
737*5113495bSYour Name 	connect_req->ssid.length = req->ssid_len;
738*5113495bSYour Name 	if (connect_req->ssid.length > WLAN_SSID_MAX_LEN) {
739*5113495bSYour Name 		osif_err("Invalid ssid len %zu", req->ssid_len);
740*5113495bSYour Name 		ucfg_cm_free_connect_req(connect_req);
741*5113495bSYour Name 		return -EINVAL;
742*5113495bSYour Name 	}
743*5113495bSYour Name 
744*5113495bSYour Name 	qdf_mem_copy(connect_req->ssid.ssid, req->ssid,
745*5113495bSYour Name 		     connect_req->ssid.length);
746*5113495bSYour Name 
747*5113495bSYour Name 	if (req->channel)
748*5113495bSYour Name 		connect_req->chan_freq = req->channel->center_freq;
749*5113495bSYour Name 
750*5113495bSYour Name 	if (req->channel_hint)
751*5113495bSYour Name 		connect_req->chan_freq_hint = req->channel_hint->center_freq;
752*5113495bSYour Name 
753*5113495bSYour Name 	status = osif_cm_set_crypto_params(connect_req, req);
754*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
755*5113495bSYour Name 		goto connect_start_fail;
756*5113495bSYour Name 
757*5113495bSYour Name 	connect_req->ht_caps = req->ht_capa.cap_info;
758*5113495bSYour Name 	connect_req->ht_caps_mask = req->ht_capa_mask.cap_info;
759*5113495bSYour Name 	connect_req->vht_caps = req->vht_capa.vht_cap_info;
760*5113495bSYour Name 	connect_req->vht_caps_mask = req->vht_capa_mask.vht_cap_info;
761*5113495bSYour Name 
762*5113495bSYour Name 	/* Copy complete ie */
763*5113495bSYour Name 	if (req->ie_len) {
764*5113495bSYour Name 		connect_req->assoc_ie.len = req->ie_len;
765*5113495bSYour Name 		connect_req->assoc_ie.ptr = qdf_mem_malloc(req->ie_len);
766*5113495bSYour Name 		if (!connect_req->assoc_ie.ptr) {
767*5113495bSYour Name 			connect_req->assoc_ie.len = 0;
768*5113495bSYour Name 			status = QDF_STATUS_E_NOMEM;
769*5113495bSYour Name 				goto connect_start_fail;
770*5113495bSYour Name 		}
771*5113495bSYour Name 		qdf_mem_copy(connect_req->assoc_ie.ptr, req->ie,
772*5113495bSYour Name 			     connect_req->assoc_ie.len);
773*5113495bSYour Name 	}
774*5113495bSYour Name 
775*5113495bSYour Name 	status = osif_cm_set_fils_info(vdev, connect_req, req);
776*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
777*5113495bSYour Name 		goto connect_start_fail;
778*5113495bSYour Name 
779*5113495bSYour Name 	osif_cm_fill_connect_params(connect_req, params);
780*5113495bSYour Name 
781*5113495bSYour Name 	status = osif_update_mlo_partner_info(vdev, connect_req, req);
782*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
783*5113495bSYour Name 		goto connect_start_fail;
784*5113495bSYour Name 
785*5113495bSYour Name 	status = mlo_connect(vdev, connect_req);
786*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
787*5113495bSYour Name 		osif_err("Connect failed with status %d", status);
788*5113495bSYour Name 
789*5113495bSYour Name connect_start_fail:
790*5113495bSYour Name 	ucfg_cm_free_connect_req(connect_req);
791*5113495bSYour Name 
792*5113495bSYour Name 	return qdf_status_to_os_return(status);
793*5113495bSYour Name }
794*5113495bSYour Name 
osif_cm_disconnect(struct net_device * dev,struct wlan_objmgr_vdev * vdev,uint16_t reason)795*5113495bSYour Name int osif_cm_disconnect(struct net_device *dev, struct wlan_objmgr_vdev *vdev,
796*5113495bSYour Name 		       uint16_t reason)
797*5113495bSYour Name {
798*5113495bSYour Name 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
799*5113495bSYour Name 	QDF_STATUS status;
800*5113495bSYour Name 
801*5113495bSYour Name 	osif_info("%s(vdevid-%d): Received Disconnect reason:%d %s",
802*5113495bSYour Name 		  dev->name, vdev_id, reason,
803*5113495bSYour Name 		  ucfg_cm_reason_code_to_str(reason));
804*5113495bSYour Name 
805*5113495bSYour Name 	status = mlo_disconnect(vdev, CM_OSIF_DISCONNECT, reason, NULL);
806*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
807*5113495bSYour Name 		osif_err("Disconnect failed with status %d", status);
808*5113495bSYour Name 
809*5113495bSYour Name 	return qdf_status_to_os_return(status);
810*5113495bSYour Name }
811*5113495bSYour Name 
osif_cm_disconnect_sync(struct wlan_objmgr_vdev * vdev,uint16_t reason)812*5113495bSYour Name int osif_cm_disconnect_sync(struct wlan_objmgr_vdev *vdev, uint16_t reason)
813*5113495bSYour Name {
814*5113495bSYour Name 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
815*5113495bSYour Name 	QDF_STATUS status;
816*5113495bSYour Name 
817*5113495bSYour Name 	osif_info("vdevid-%d: Received Disconnect reason:%d %s",
818*5113495bSYour Name 		  vdev_id, reason, ucfg_cm_reason_code_to_str(reason));
819*5113495bSYour Name 
820*5113495bSYour Name 	status = mlo_sync_disconnect(vdev, CM_OSIF_DISCONNECT, reason, NULL);
821*5113495bSYour Name 
822*5113495bSYour Name 	return qdf_status_to_os_return(status);
823*5113495bSYour Name }
824