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