xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlme/connection_mgr/core/src/wlan_cm_connect.c (revision 8e7416b1e69d2fc559b0e9d184091b1ef894fafb)
1 /*
2  * Copyright (c) 2012-2015, 2020-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2022 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: Implements connect specific APIs of connection manager
20  */
21 
22 #include "wlan_cm_main_api.h"
23 #include "wlan_scan_api.h"
24 #include "wlan_cm_roam.h"
25 #include "wlan_cm_sm.h"
26 #ifdef WLAN_POLICY_MGR_ENABLE
27 #include "wlan_policy_mgr_api.h"
28 #endif
29 #include <wlan_serialization_api.h>
30 #ifdef CONN_MGR_ADV_FEATURE
31 #include "wlan_dlm_api.h"
32 #include "wlan_cm_roam_api.h"
33 #include "wlan_tdls_api.h"
34 #endif
35 #include <wlan_utility.h>
36 #include <wlan_mlo_mgr_sta.h>
37 #include <wlan_objmgr_vdev_obj.h>
38 #include "wlan_psoc_mlme_api.h"
39 
40 static void
41 cm_fill_failure_resp_from_cm_id(struct cnx_mgr *cm_ctx,
42 				struct wlan_cm_connect_resp *resp,
43 				wlan_cm_id cm_id,
44 				enum wlan_cm_connect_fail_reason reason)
45 {
46 	resp->connect_status = QDF_STATUS_E_FAILURE;
47 	resp->cm_id = cm_id;
48 	resp->vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
49 	resp->reason = reason;
50 	/* Get bssid and ssid and freq for the cm id from the req list */
51 	cm_fill_bss_info_in_connect_rsp_by_cm_id(cm_ctx, cm_id, resp);
52 }
53 
54 static QDF_STATUS cm_connect_cmd_timeout(struct cnx_mgr *cm_ctx,
55 					 wlan_cm_id cm_id)
56 {
57 	struct wlan_cm_connect_resp *resp;
58 	QDF_STATUS status;
59 
60 	resp = qdf_mem_malloc(sizeof(*resp));
61 	if (!resp)
62 		return QDF_STATUS_E_NOMEM;
63 
64 	cm_fill_failure_resp_from_cm_id(cm_ctx, resp, cm_id, CM_SER_TIMEOUT);
65 	status = cm_sm_deliver_event(cm_ctx->vdev,
66 				     WLAN_CM_SM_EV_CONNECT_FAILURE,
67 				     sizeof(*resp), resp);
68 	qdf_mem_free(resp);
69 
70 	if (QDF_IS_STATUS_ERROR(status))
71 		cm_connect_handle_event_post_fail(cm_ctx, cm_id);
72 
73 	return status;
74 }
75 
76 #ifdef WLAN_CM_USE_SPINLOCK
77 static QDF_STATUS cm_activate_connect_req_sched_cb(struct scheduler_msg *msg)
78 {
79 	struct wlan_serialization_command *cmd = msg->bodyptr;
80 	struct wlan_objmgr_vdev *vdev;
81 	struct cnx_mgr *cm_ctx;
82 	QDF_STATUS ret = QDF_STATUS_E_FAILURE;
83 
84 	if (!cmd) {
85 		mlme_err("cmd is null");
86 		return QDF_STATUS_E_INVAL;
87 	}
88 
89 	vdev = cmd->vdev;
90 	if (!vdev) {
91 		mlme_err("vdev is null");
92 		return QDF_STATUS_E_INVAL;
93 	}
94 
95 	cm_ctx = cm_get_cm_ctx(vdev);
96 	if (!cm_ctx)
97 		return QDF_STATUS_E_INVAL;
98 
99 	ret = cm_sm_deliver_event(vdev,
100 				  WLAN_CM_SM_EV_CONNECT_ACTIVE,
101 				  sizeof(wlan_cm_id),
102 				  &cmd->cmd_id);
103 
104 	/*
105 	 * Called from scheduler context hence posting failure
106 	 */
107 	if (QDF_IS_STATUS_ERROR(ret)) {
108 		mlme_err(CM_PREFIX_FMT "Activation failed for cmd:%d",
109 			 CM_PREFIX_REF(wlan_vdev_get_id(vdev), cmd->cmd_id),
110 			 cmd->cmd_type);
111 		cm_connect_handle_event_post_fail(cm_ctx, cmd->cmd_id);
112 	}
113 
114 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
115 	return ret;
116 }
117 
118 static QDF_STATUS
119 cm_activate_connect_req(struct wlan_serialization_command *cmd)
120 {
121 	struct wlan_objmgr_vdev *vdev = cmd->vdev;
122 	struct scheduler_msg msg = {0};
123 	QDF_STATUS ret;
124 
125 	msg.bodyptr = cmd;
126 	msg.callback = cm_activate_connect_req_sched_cb;
127 	msg.flush_callback = cm_activate_cmd_req_flush_cb;
128 
129 	ret = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_MLME_CM_ID);
130 	if (QDF_IS_STATUS_ERROR(ret))
131 		return ret;
132 
133 	ret = scheduler_post_message(QDF_MODULE_ID_MLME,
134 				     QDF_MODULE_ID_MLME,
135 				     QDF_MODULE_ID_MLME, &msg);
136 
137 	if (QDF_IS_STATUS_ERROR(ret)) {
138 		mlme_err(CM_PREFIX_FMT "Failed to post scheduler_msg",
139 			 CM_PREFIX_REF(wlan_vdev_get_id(vdev), cmd->cmd_id));
140 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
141 		return ret;
142 	}
143 	mlme_debug(CM_PREFIX_FMT "Cmd act in sched cmd type:%d",
144 		   CM_PREFIX_REF(wlan_vdev_get_id(vdev), cmd->cmd_id),
145 		   cmd->cmd_type);
146 
147 	return ret;
148 }
149 #else
150 static QDF_STATUS
151 cm_activate_connect_req(struct wlan_serialization_command *cmd)
152 {
153 	return cm_sm_deliver_event(cmd->vdev,
154 				   WLAN_CM_SM_EV_CONNECT_ACTIVE,
155 				   sizeof(wlan_cm_id),
156 				   &cmd->cmd_id);
157 }
158 #endif
159 
160 static QDF_STATUS
161 cm_ser_connect_cb(struct wlan_serialization_command *cmd,
162 		  enum wlan_serialization_cb_reason reason)
163 {
164 	QDF_STATUS status = QDF_STATUS_SUCCESS;
165 	struct wlan_objmgr_vdev *vdev;
166 	struct cnx_mgr *cm_ctx;
167 
168 	if (!cmd) {
169 		mlme_err("cmd is NULL, reason: %d", reason);
170 		QDF_ASSERT(0);
171 		return QDF_STATUS_E_NULL_VALUE;
172 	}
173 
174 	vdev = cmd->vdev;
175 
176 	cm_ctx = cm_get_cm_ctx(vdev);
177 	if (!cm_ctx)
178 		return QDF_STATUS_E_NULL_VALUE;
179 
180 	switch (reason) {
181 	case WLAN_SER_CB_ACTIVATE_CMD:
182 		/*
183 		 * For pending to active reason, use async api to take lock.
184 		 * For direct activation use sync api to avoid taking lock
185 		 * as lock is already acquired by the requester.
186 		 */
187 		if (cmd->activation_reason == SER_PENDING_TO_ACTIVE)
188 			status = cm_activate_connect_req(cmd);
189 		else
190 			status = cm_sm_deliver_event_sync(cm_ctx,
191 						   WLAN_CM_SM_EV_CONNECT_ACTIVE,
192 						   sizeof(wlan_cm_id),
193 						   &cmd->cmd_id);
194 		if (QDF_IS_STATUS_SUCCESS(status))
195 			break;
196 		/*
197 		 * Handle failure if posting fails, i.e. the SM state has
198 		 * changed or head cm_id doesn't match the active cm_id.
199 		 * connect active should be handled only in JOIN_PENDING. If
200 		 * new command has been received connect activation should be
201 		 * aborted from here with connect req cleanup.
202 		 */
203 		cm_connect_handle_event_post_fail(cm_ctx, cmd->cmd_id);
204 		break;
205 	case WLAN_SER_CB_CANCEL_CMD:
206 		/* command removed from pending list. */
207 		break;
208 	case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT:
209 		mlme_err(CM_PREFIX_FMT "Active command timeout",
210 			 CM_PREFIX_REF(wlan_vdev_get_id(vdev), cmd->cmd_id));
211 		cm_trigger_panic_on_cmd_timeout(cm_ctx->vdev);
212 		cm_connect_cmd_timeout(cm_ctx, cmd->cmd_id);
213 		break;
214 	case WLAN_SER_CB_RELEASE_MEM_CMD:
215 		cm_reset_active_cm_id(vdev, cmd->cmd_id);
216 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
217 		break;
218 	default:
219 		QDF_ASSERT(0);
220 		status = QDF_STATUS_E_INVAL;
221 		break;
222 	}
223 
224 	return status;
225 }
226 
227 static QDF_STATUS cm_ser_connect_req(struct wlan_objmgr_pdev *pdev,
228 				     struct cnx_mgr *cm_ctx,
229 				     struct cm_connect_req *cm_req)
230 {
231 	struct wlan_serialization_command cmd = {0, };
232 	enum wlan_serialization_status ser_cmd_status;
233 	QDF_STATUS status;
234 	uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
235 
236 	status = wlan_objmgr_vdev_try_get_ref(cm_ctx->vdev, WLAN_MLME_CM_ID);
237 	if (QDF_IS_STATUS_ERROR(status)) {
238 		mlme_err(CM_PREFIX_FMT "unable to get reference",
239 			 CM_PREFIX_REF(vdev_id, cm_req->cm_id));
240 		return status;
241 	}
242 
243 	cmd.cmd_type = WLAN_SER_CMD_VDEV_CONNECT;
244 	cmd.cmd_id = cm_req->cm_id;
245 	cmd.cmd_cb = cm_ser_connect_cb;
246 	cmd.source = WLAN_UMAC_COMP_MLME;
247 	cmd.is_high_priority = false;
248 	cmd.cmd_timeout_duration = cm_ctx->connect_timeout;
249 	cmd.vdev = cm_ctx->vdev;
250 	cmd.is_blocking = true;
251 
252 	ser_cmd_status = wlan_serialization_request(&cmd);
253 	switch (ser_cmd_status) {
254 	case WLAN_SER_CMD_PENDING:
255 		/* command moved to pending list.Do nothing */
256 		break;
257 	case WLAN_SER_CMD_ACTIVE:
258 		/* command moved to active list. Do nothing */
259 		break;
260 	default:
261 		mlme_err(CM_PREFIX_FMT "ser cmd status %d",
262 			 CM_PREFIX_REF(vdev_id, cm_req->cm_id), ser_cmd_status);
263 		wlan_objmgr_vdev_release_ref(cm_ctx->vdev, WLAN_MLME_CM_ID);
264 
265 		return QDF_STATUS_E_FAILURE;
266 	}
267 
268 	return QDF_STATUS_SUCCESS;
269 }
270 
271 void
272 cm_connect_handle_event_post_fail(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id)
273 {
274 	struct wlan_cm_connect_resp *resp;
275 
276 	resp = qdf_mem_malloc(sizeof(*resp));
277 	if (!resp)
278 		return;
279 
280 	cm_fill_failure_resp_from_cm_id(cm_ctx, resp, cm_id,
281 					CM_ABORT_DUE_TO_NEW_REQ_RECVD);
282 	cm_connect_complete(cm_ctx, resp);
283 	qdf_mem_free(resp);
284 }
285 
286 QDF_STATUS
287 cm_send_connect_start_fail(struct cnx_mgr *cm_ctx,
288 			   struct cm_connect_req *req,
289 			   enum wlan_cm_connect_fail_reason reason)
290 {
291 	struct wlan_cm_connect_resp *resp;
292 	QDF_STATUS status;
293 
294 	resp = qdf_mem_malloc(sizeof(*resp));
295 	if (!resp)
296 		return QDF_STATUS_E_NOMEM;
297 
298 	cm_fill_failure_resp_from_cm_id(cm_ctx, resp, req->cm_id, reason);
299 
300 	status = cm_sm_deliver_event_sync(cm_ctx, WLAN_CM_SM_EV_CONNECT_FAILURE,
301 					  sizeof(*resp), resp);
302 	qdf_mem_free(resp);
303 
304 	return status;
305 }
306 
307 #ifdef WLAN_POLICY_MGR_ENABLE
308 
309 QDF_STATUS cm_handle_hw_mode_change(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id,
310 				    enum wlan_cm_sm_evt event)
311 {
312 	struct cm_req *cm_req;
313 	enum wlan_cm_connect_fail_reason reason = CM_GENERIC_FAILURE;
314 	struct wlan_objmgr_pdev *pdev;
315 	QDF_STATUS status;
316 
317 	if (!cm_id)
318 		return QDF_STATUS_E_FAILURE;
319 
320 	cm_req = cm_get_req_by_cm_id(cm_ctx, *cm_id);
321 	if (!cm_req)
322 		return QDF_STATUS_E_INVAL;
323 
324 	pdev = wlan_vdev_get_pdev(cm_ctx->vdev);
325 	if (!pdev) {
326 		mlme_err(CM_PREFIX_FMT "Failed to find pdev",
327 			 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
328 				       cm_req->cm_id));
329 		goto send_failure;
330 	}
331 
332 	if (event == WLAN_CM_SM_EV_HW_MODE_SUCCESS) {
333 		status = cm_ser_connect_req(pdev, cm_ctx, &cm_req->connect_req);
334 		if (QDF_IS_STATUS_ERROR(status)) {
335 			reason = CM_SER_FAILURE;
336 			goto send_failure;
337 		}
338 		return status;
339 	}
340 
341 	/* Set reason HW mode fail for event WLAN_CM_SM_EV_HW_MODE_FAILURE */
342 	reason = CM_HW_MODE_FAILURE;
343 
344 send_failure:
345 	return cm_send_connect_start_fail(cm_ctx, &cm_req->connect_req, reason);
346 }
347 
348 void cm_hw_mode_change_resp(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id,
349 			    wlan_cm_id cm_id, QDF_STATUS status)
350 {
351 	struct wlan_objmgr_vdev *vdev;
352 	QDF_STATUS qdf_status;
353 	enum wlan_cm_sm_evt event = WLAN_CM_SM_EV_HW_MODE_SUCCESS;
354 	struct cnx_mgr *cm_ctx;
355 
356 	mlme_debug(CM_PREFIX_FMT "Continue connect after HW mode change, status %d",
357 		   CM_PREFIX_REF(vdev_id, cm_id), status);
358 
359 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
360 						    WLAN_MLME_CM_ID);
361 	if (!vdev)
362 		return;
363 
364 	cm_ctx = cm_get_cm_ctx(vdev);
365 	if (!cm_ctx) {
366 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
367 		return;
368 	}
369 
370 	if (QDF_IS_STATUS_ERROR(status))
371 		event = WLAN_CM_SM_EV_HW_MODE_FAILURE;
372 	qdf_status = cm_sm_deliver_event(vdev, event, sizeof(wlan_cm_id),
373 					 &cm_id);
374 
375 	/*
376 	 * Handle failure if posting fails, i.e. the SM state has
377 	 * changed or head cm_id doesn't match the active cm_id.
378 	 * hw mode change resp should be handled only in JOIN_PENDING. If
379 	 * new command has been received connect should be
380 	 * aborted from here with connect req cleanup.
381 	 */
382 	if (QDF_IS_STATUS_ERROR(status))
383 		cm_connect_handle_event_post_fail(cm_ctx, cm_id);
384 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
385 }
386 
387 static QDF_STATUS cm_check_for_hw_mode_change(struct wlan_objmgr_psoc *psoc,
388 					      qdf_list_t *scan_list,
389 					      uint8_t vdev_id,
390 					      wlan_cm_id connect_id)
391 {
392 	return policy_mgr_change_hw_mode_sta_connect(psoc, scan_list, vdev_id,
393 						     connect_id);
394 }
395 
396 
397 #else
398 
399 static inline
400 QDF_STATUS cm_check_for_hw_mode_change(struct wlan_objmgr_psoc *psoc,
401 				       qdf_list_t *scan_list, uint8_t vdev_id,
402 				       uint8_t connect_id)
403 {
404 	return QDF_STATUS_E_ALREADY;
405 }
406 
407 #endif /* WLAN_POLICY_MGR_ENABLE */
408 
409 static inline void cm_delete_pmksa_for_bssid(struct cnx_mgr *cm_ctx,
410 					     struct qdf_mac_addr *bssid)
411 {
412 	struct wlan_crypto_pmksa pmksa;
413 
414 	qdf_mem_zero(&pmksa, sizeof(pmksa));
415 	qdf_copy_macaddr(&pmksa.bssid, bssid);
416 	wlan_crypto_set_del_pmksa(cm_ctx->vdev, &pmksa, false);
417 }
418 
419 #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
420 static inline
421 void cm_delete_pmksa_for_single_pmk_bssid(struct cnx_mgr *cm_ctx,
422 					  struct qdf_mac_addr *bssid)
423 {
424 	cm_delete_pmksa_for_bssid(cm_ctx, bssid);
425 }
426 #else
427 static inline
428 void cm_delete_pmksa_for_single_pmk_bssid(struct cnx_mgr *cm_ctx,
429 					  struct qdf_mac_addr *bssid)
430 {
431 }
432 #endif /* WLAN_SAE_SINGLE_PMK && WLAN_FEATURE_ROAM_OFFLOAD */
433 
434 static inline void
435 cm_set_pmf_caps(struct wlan_cm_connect_req *req, struct scan_filter *filter)
436 {
437 	if (req->crypto.rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED)
438 		filter->pmf_cap = WLAN_PMF_REQUIRED;
439 	else if (req->crypto.rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED)
440 		filter->pmf_cap = WLAN_PMF_CAPABLE;
441 	else
442 		filter->pmf_cap = WLAN_PMF_DISABLED;
443 }
444 
445 #ifdef WLAN_FEATURE_11BE_MLO
446 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
447 static inline
448 void cm_set_vdev_link_id(struct cnx_mgr *cm_ctx,
449 			 struct cm_connect_req *req)
450 {
451 	uint8_t link_id;
452 
453 	link_id = req->cur_candidate->entry->ml_info.self_link_id;
454 	if (cm_ctx->vdev) {
455 		mlme_debug("setting link ID to %d", link_id);
456 		wlan_vdev_set_link_id(cm_ctx->vdev, link_id);
457 	}
458 }
459 
460 static void cm_update_vdev_mlme_macaddr(struct cnx_mgr *cm_ctx,
461 					struct cm_connect_req *req)
462 {
463 	struct qdf_mac_addr *mac;
464 	bool eht_capab;
465 
466 	if (wlan_vdev_mlme_get_opmode(cm_ctx->vdev) != QDF_STA_MODE)
467 		return;
468 
469 	wlan_psoc_mlme_get_11be_capab(wlan_vdev_get_psoc(cm_ctx->vdev),
470 				      &eht_capab);
471 	if (!eht_capab)
472 		return;
473 
474 	if (req->cur_candidate->entry->ie_list.multi_link) {
475 		wlan_vdev_obj_lock(cm_ctx->vdev);
476 		/* Use link address for ML connection */
477 		wlan_vdev_mlme_set_macaddr(cm_ctx->vdev,
478 					   cm_ctx->vdev->vdev_mlme.linkaddr);
479 		wlan_vdev_obj_unlock(cm_ctx->vdev);
480 		wlan_vdev_mlme_set_mlo_vdev(cm_ctx->vdev);
481 		mlme_debug("set link address for ML connection");
482 	} else {
483 		wlan_vdev_obj_lock(cm_ctx->vdev);
484 		/* Use net_dev address for non-ML connection */
485 		mac = (struct qdf_mac_addr *)cm_ctx->vdev->vdev_mlme.mldaddr;
486 		if (!qdf_is_macaddr_zero(mac)) {
487 			wlan_vdev_mlme_set_macaddr(cm_ctx->vdev, mac->bytes);
488 			mlme_debug(QDF_MAC_ADDR_FMT " for non-ML connection",
489 				   QDF_MAC_ADDR_REF(mac->bytes));
490 		}
491 		wlan_vdev_obj_unlock(cm_ctx->vdev);
492 
493 		wlan_vdev_mlme_clear_mlo_vdev(cm_ctx->vdev);
494 		mlme_debug("clear MLO cap for non-ML connection");
495 	}
496 }
497 #else
498 static inline
499 void cm_set_vdev_link_id(struct cnx_mgr *cm_ctx,
500 			 struct cm_connect_req *req)
501 { }
502 
503 static void cm_update_vdev_mlme_macaddr(struct cnx_mgr *cm_ctx,
504 					struct cm_connect_req *req)
505 {
506 }
507 #endif
508 /**
509  * cm_get_bss_peer_mld_addr() - get bss peer mld mac address
510  * @req: pointer to cm_connect_req
511  *
512  * Return: mld mac address
513  */
514 static struct qdf_mac_addr *cm_get_bss_peer_mld_addr(struct cm_connect_req *req)
515 {
516 	if (req && req->cur_candidate && req->cur_candidate->entry)
517 		return &req->cur_candidate->entry->ml_info.mld_mac_addr;
518 	else
519 		return NULL;
520 }
521 
522 /**
523  * cm_bss_peer_is_assoc_peer() - is the bss peer to be created assoc peer or not
524  * @req: pointer to cm_connect_req
525  *
526  * Return: true if the bss peer to be created is assoc peer
527  */
528 static bool cm_bss_peer_is_assoc_peer(struct cm_connect_req *req)
529 {
530 	if (req)
531 		return !req->req.is_non_assoc_link;
532 
533 	return false;
534 }
535 
536 /**
537  * cm_candidate_mlo_update() - handle mlo scenario for candidate validating
538  * @scan_entry: scan result of the candidate
539  * @validate_bss_info: candidate info to be updated
540  *
541  * Return: None
542  */
543 static void
544 cm_candidate_mlo_update(struct scan_cache_entry *scan_entry,
545 			struct validate_bss_data *validate_bss_info)
546 {
547 	validate_bss_info->is_mlo = !!scan_entry->ie_list.multi_link;
548 }
549 #else
550 static inline
551 void cm_set_vdev_link_id(struct cnx_mgr *cm_ctx,
552 			 struct cm_connect_req *req)
553 { }
554 
555 static void cm_update_vdev_mlme_macaddr(struct cnx_mgr *cm_ctx,
556 					struct cm_connect_req *req)
557 {
558 }
559 
560 static struct qdf_mac_addr *cm_get_bss_peer_mld_addr(struct cm_connect_req *req)
561 {
562 	return NULL;
563 }
564 
565 static bool cm_bss_peer_is_assoc_peer(struct cm_connect_req *req)
566 {
567 	return false;
568 }
569 
570 static inline void
571 cm_candidate_mlo_update(struct scan_cache_entry *scan_entry,
572 			struct validate_bss_data *validate_bss_info)
573 {
574 }
575 #endif
576 
577 static void cm_create_bss_peer(struct cnx_mgr *cm_ctx,
578 			       struct cm_connect_req *req)
579 {
580 	QDF_STATUS status;
581 	struct qdf_mac_addr *bssid;
582 	struct qdf_mac_addr *mld_mac = NULL;
583 	bool is_assoc_link = false;
584 	bool eht_capab;
585 
586 	if (!cm_ctx) {
587 		mlme_err("invalid cm_ctx");
588 		return;
589 	}
590 	if (!req || !req->cur_candidate || !req->cur_candidate->entry) {
591 		mlme_err("invalid req");
592 		return;
593 	}
594 
595 	wlan_psoc_mlme_get_11be_capab(wlan_vdev_get_psoc(cm_ctx->vdev),
596 				      &eht_capab);
597 	if (eht_capab) {
598 		cm_set_vdev_link_id(cm_ctx, req);
599 		mld_mac = cm_get_bss_peer_mld_addr(req);
600 		is_assoc_link = cm_bss_peer_is_assoc_peer(req);
601 	}
602 
603 	bssid = &req->cur_candidate->entry->bssid;
604 	status = mlme_cm_bss_peer_create_req(cm_ctx->vdev, bssid,
605 					     mld_mac, is_assoc_link);
606 	if (QDF_IS_STATUS_ERROR(status)) {
607 		struct wlan_cm_connect_resp *resp;
608 		uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
609 
610 		/* In case of failure try with next candidate */
611 		mlme_err(CM_PREFIX_FMT "peer create request failed %d",
612 			 CM_PREFIX_REF(vdev_id, req->cm_id), status);
613 
614 		resp = qdf_mem_malloc(sizeof(*resp));
615 		if (!resp)
616 			return;
617 
618 		cm_fill_failure_resp_from_cm_id(cm_ctx, resp, req->cm_id,
619 						CM_PEER_CREATE_FAILED);
620 		cm_sm_deliver_event_sync(cm_ctx,
621 				WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE,
622 				sizeof(*resp), resp);
623 		qdf_mem_free(resp);
624 	}
625 }
626 
627 static
628 QDF_STATUS cm_if_mgr_validate_candidate(struct cnx_mgr *cm_ctx,
629 					struct scan_cache_entry *scan_entry)
630 {
631 	struct if_mgr_event_data event_data = {0};
632 
633 	event_data.validate_bss_info.chan_freq = scan_entry->channel.chan_freq;
634 	event_data.validate_bss_info.beacon_interval = scan_entry->bcn_int;
635 	qdf_copy_macaddr(&event_data.validate_bss_info.peer_addr,
636 			 &scan_entry->bssid);
637 	cm_candidate_mlo_update(scan_entry, &event_data.validate_bss_info);
638 
639 	return if_mgr_deliver_event(cm_ctx->vdev,
640 				    WLAN_IF_MGR_EV_VALIDATE_CANDIDATE,
641 				    &event_data);
642 }
643 
644 #ifdef CONN_MGR_ADV_FEATURE
645 #ifdef WLAN_FEATURE_FILS_SK
646 /*
647  * cm_create_fils_realm_hash: API to create hash using realm
648  * @fils_info: fils connection info obtained from supplicant
649  * @tmp_hash: pointer to new hash
650  *
651  * Return: QDF_STATUS
652  */
653 static QDF_STATUS
654 cm_create_fils_realm_hash(struct wlan_fils_con_info *fils_info,
655 			  uint8_t *tmp_hash)
656 {
657 	uint8_t *hash;
658 	uint8_t *data;
659 
660 	if (!fils_info->realm_len)
661 		return QDF_STATUS_E_NOSUPPORT;
662 
663 	hash = qdf_mem_malloc(SHA256_DIGEST_SIZE);
664 	if (!hash)
665 		return QDF_STATUS_E_NOMEM;
666 
667 	data = fils_info->realm;
668 	qdf_get_hash(SHA256_CRYPTO_TYPE, 1, &data, &fils_info->realm_len, hash);
669 	qdf_mem_copy(tmp_hash, hash, REALM_HASH_LEN);
670 	qdf_mem_free(hash);
671 
672 	return QDF_STATUS_SUCCESS;
673 }
674 
675 static void cm_update_fils_scan_filter(struct scan_filter *filter,
676 				       struct cm_connect_req *cm_req)
677 
678 {
679 	uint8_t realm_hash[REALM_HASH_LEN];
680 	QDF_STATUS status;
681 
682 	if (!cm_req->req.fils_info.is_fils_connection)
683 		return;
684 
685 	status = cm_create_fils_realm_hash(&cm_req->req.fils_info, realm_hash);
686 	if (QDF_IS_STATUS_ERROR(status))
687 		return;
688 
689 	filter->fils_scan_filter.realm_check = true;
690 	mlme_debug(CM_PREFIX_FMT "creating realm based on fils info",
691 		   CM_PREFIX_REF(cm_req->req.vdev_id, cm_req->cm_id));
692 	qdf_mem_copy(filter->fils_scan_filter.fils_realm, realm_hash,
693 		     REALM_HASH_LEN);
694 }
695 
696 static inline bool cm_is_fils_connection(struct wlan_cm_connect_resp *resp)
697 {
698 	return resp->is_fils_connection;
699 }
700 
701 static QDF_STATUS cm_set_fils_key(struct cnx_mgr *cm_ctx,
702 				  struct wlan_cm_connect_resp *resp)
703 {
704 	struct fils_connect_rsp_params *fils_ie;
705 
706 	fils_ie = resp->connect_ies.fils_ie;
707 
708 	if (!fils_ie)
709 		return QDF_STATUS_E_INVAL;
710 
711 	cm_store_fils_key(cm_ctx, true, 0, fils_ie->tk_len, fils_ie->tk,
712 			  &resp->bssid, resp->cm_id);
713 	cm_store_fils_key(cm_ctx, false, 2, fils_ie->gtk_len, fils_ie->gtk,
714 			  &resp->bssid, resp->cm_id);
715 	cm_set_key(cm_ctx, true, 0, &resp->bssid);
716 	cm_set_key(cm_ctx, false, 2, &resp->bssid);
717 
718 	return QDF_STATUS_SUCCESS;
719 }
720 
721 #else
722 static inline void cm_update_fils_scan_filter(struct scan_filter *filter,
723 					      struct cm_connect_req *cm_req)
724 { }
725 
726 static inline bool cm_is_fils_connection(struct wlan_cm_connect_resp *resp)
727 {
728 	return false;
729 }
730 
731 static inline QDF_STATUS cm_set_fils_key(struct cnx_mgr *cm_ctx,
732 					 struct wlan_cm_connect_resp *resp)
733 {
734 	return QDF_STATUS_SUCCESS;
735 }
736 #endif /* WLAN_FEATURE_FILS_SK */
737 
738 static void cm_get_vdev_id_from_bssid(struct wlan_objmgr_pdev *pdev,
739 				   void *object, void *arg)
740 {
741 	uint8_t *vdev_id = arg;
742 	struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
743 
744 	if (!vdev_id)
745 		return;
746 
747 	if (!(wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE ||
748 	      wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_CLIENT_MODE))
749 		return;
750 
751 	if (cm_is_vdev_disconnecting(vdev))
752 		*vdev_id = wlan_vdev_get_id(vdev);
753 }
754 
755 /**
756  * cm_is_any_other_vdev_disconnecting() - check whether any other vdev is in
757  * disconnecting state
758  * @cm_ctx: connection manager context
759  * @cm_req: Connect request.
760  *
761  * As Connect is a blocking call this API will make sure the disconnect
762  * doesn't timeout on any vdev and thus make sure that PEER/VDEV SM are cleaned
763  * before vdev delete is sent.
764  *
765  * Return : true if disconnection is on any vdev_id
766  */
767 static bool cm_is_any_other_vdev_disconnecting(struct cnx_mgr *cm_ctx,
768 					       struct cm_req *cm_req)
769 {
770 	struct wlan_objmgr_pdev *pdev;
771 	uint8_t vdev_id;
772 	uint8_t cur_vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
773 
774 	pdev = wlan_vdev_get_pdev(cm_ctx->vdev);
775 	if (!pdev) {
776 		mlme_err(CM_PREFIX_FMT "Failed to find pdev",
777 			 CM_PREFIX_REF(cur_vdev_id, cm_req->cm_id));
778 		return false;
779 	}
780 
781 	vdev_id = WLAN_INVALID_VDEV_ID;
782 	wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
783 					  cm_get_vdev_id_from_bssid,
784 					  &vdev_id, 0,
785 					  WLAN_MLME_CM_ID);
786 
787 	if (vdev_id != WLAN_INVALID_VDEV_ID && vdev_id != cur_vdev_id) {
788 		mlme_info(CM_PREFIX_FMT "Abort connection as vdev %d is waiting for disconnect",
789 			  CM_PREFIX_REF(cur_vdev_id, cm_req->cm_id),
790 			  vdev_id);
791 		return true;
792 	}
793 
794 	return false;
795 }
796 
797 QDF_STATUS
798 cm_inform_dlm_connect_complete(struct wlan_objmgr_vdev *vdev,
799 			       struct wlan_cm_connect_resp *resp)
800 {
801 	struct wlan_objmgr_pdev *pdev;
802 
803 	pdev = wlan_vdev_get_pdev(vdev);
804 	if (!pdev) {
805 		mlme_err(CM_PREFIX_FMT "Failed to find pdev",
806 			 CM_PREFIX_REF(wlan_vdev_get_id(vdev), resp->cm_id));
807 		return QDF_STATUS_E_FAILURE;
808 	}
809 
810 	if (QDF_IS_STATUS_SUCCESS(resp->connect_status))
811 		wlan_dlm_update_bssid_connect_params(pdev, resp->bssid,
812 						     DLM_AP_CONNECTED);
813 
814 	return QDF_STATUS_SUCCESS;
815 }
816 
817 /**
818  * cm_is_retry_with_same_candidate() - This API check if reconnect attempt is
819  * required with the same candidate again
820  * @cm_ctx: connection manager context
821  * @req: Connect request.
822  * @resp: connect resp from previous connection attempt
823  *
824  * This function return true if same candidate needs to be tried again
825  *
826  * Return: bool
827  */
828 static bool cm_is_retry_with_same_candidate(struct cnx_mgr *cm_ctx,
829 					    struct cm_connect_req *req,
830 					    struct wlan_cm_connect_resp *resp)
831 {
832 	uint8_t max_retry_count = CM_MAX_CANDIDATE_RETRIES;
833 	uint32_t key_mgmt;
834 	struct wlan_objmgr_psoc *psoc;
835 	bool sae_connection;
836 	QDF_STATUS status;
837 
838 	psoc = wlan_pdev_get_psoc(wlan_vdev_get_pdev(cm_ctx->vdev));
839 	key_mgmt = req->cur_candidate->entry->neg_sec_info.key_mgmt;
840 
841 	/* Try once again for the invalid PMKID case without PMKID */
842 	if (resp->status_code == STATUS_INVALID_PMKID)
843 		goto use_same_candidate;
844 
845 	/* Try again for the JOIN timeout if only one candidate */
846 	if (resp->reason == CM_JOIN_TIMEOUT &&
847 	    qdf_list_size(req->candidate_list) == 1) {
848 		/* Get assoc retry count */
849 		wlan_mlme_get_sae_assoc_retry_count(psoc, &max_retry_count);
850 		goto use_same_candidate;
851 	}
852 
853 	/*
854 	 * Try again for the ASSOC timeout in SAE connection or
855 	 * AP has reconnect on assoc timeout OUI.
856 	 */
857 	sae_connection = key_mgmt & (1 << WLAN_CRYPTO_KEY_MGMT_SAE |
858 				     1 << WLAN_CRYPTO_KEY_MGMT_FT_SAE);
859 	if (resp->reason == CM_ASSOC_TIMEOUT && (sae_connection ||
860 	    (mlme_get_reconn_after_assoc_timeout_flag(psoc, resp->vdev_id)))) {
861 		/* For SAE use max retry count from INI */
862 		if (sae_connection)
863 			wlan_mlme_get_sae_assoc_retry_count(psoc,
864 							    &max_retry_count);
865 		goto use_same_candidate;
866 	}
867 
868 	return false;
869 
870 use_same_candidate:
871 	if (req->cur_candidate_retries >= max_retry_count)
872 		return false;
873 
874 	status = cm_if_mgr_validate_candidate(cm_ctx,
875 					      req->cur_candidate->entry);
876 	if (QDF_IS_STATUS_ERROR(status))
877 		return false;
878 
879 	mlme_info(CM_PREFIX_FMT "Retry again with " QDF_MAC_ADDR_FMT ", status code %d reason %d key_mgmt 0x%x retry count %d max retry %d",
880 		  CM_PREFIX_REF(resp->vdev_id, resp->cm_id),
881 		  QDF_MAC_ADDR_REF(resp->bssid.bytes), resp->status_code,
882 		  resp->reason, key_mgmt, req->cur_candidate_retries,
883 		  max_retry_count);
884 
885 	req->cur_candidate_retries++;
886 
887 	return true;
888 }
889 
890 /*
891  * Do not allow last connect attempt after 25 sec, assuming last attempt will
892  * complete in max 10 sec, total connect time will not be more than 35 sec.
893  * Do not confuse this with active command timeout, that is taken care by
894  * CM_MAX_PER_CANDIDATE_CONNECT_TIMEOUT
895  */
896 #define CM_CONNECT_MAX_ACTIVE_TIME 25000
897 
898 /**
899  * cm_is_time_allowed_for_connect_attempt() - This API check if next connect
900  * attempt can be tried within allocated time.
901  * @cm_ctx: connection manager context
902  * @req: Connect request.
903  *
904  * This function return true if connect attempt can be tried so that total time
905  * taken by connect req do not exceed 30-35 seconds.
906  *
907  * Return: bool
908  */
909 static bool cm_is_time_allowed_for_connect_attempt(struct cnx_mgr *cm_ctx,
910 						   struct cm_connect_req *req)
911 {
912 	qdf_time_t time_since_connect_active;
913 	uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
914 
915 	time_since_connect_active = qdf_mc_timer_get_system_time() -
916 					req->connect_active_time;
917 	if (time_since_connect_active >= CM_CONNECT_MAX_ACTIVE_TIME) {
918 		mlme_info(CM_PREFIX_FMT "Max time allocated (%d ms) for connect completed, cur time %lu, active time %lu and diff %lu",
919 			  CM_PREFIX_REF(vdev_id, req->cm_id),
920 			  CM_CONNECT_MAX_ACTIVE_TIME,
921 			  qdf_mc_timer_get_system_time(),
922 			  req->connect_active_time,
923 			  time_since_connect_active);
924 		return false;
925 	}
926 
927 	return true;
928 }
929 
930 static inline void cm_update_advance_filter(struct wlan_objmgr_pdev *pdev,
931 					    struct cnx_mgr *cm_ctx,
932 					    struct scan_filter *filter,
933 					    struct cm_connect_req *cm_req)
934 {
935 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
936 
937 	/* Select only ESS type */
938 	filter->bss_type = WLAN_TYPE_BSS;
939 	filter->enable_adaptive_11r =
940 		wlan_mlme_adaptive_11r_enabled(psoc);
941 	if (wlan_vdev_mlme_get_opmode(cm_ctx->vdev) != QDF_STA_MODE)
942 		return;
943 	/* For link vdev, we don't filter any channels.
944 	 * Dual STA mode, one link can be disabled in post connection
945 	 * if needed.
946 	 */
947 	if (!cm_req->req.is_non_assoc_link)
948 		wlan_cm_dual_sta_roam_update_connect_channels(psoc, filter);
949 	filter->dot11mode = cm_req->req.dot11mode_filter;
950 	cm_update_fils_scan_filter(filter, cm_req);
951 }
952 
953 static void cm_update_security_filter(struct scan_filter *filter,
954 				      struct wlan_cm_connect_req *req)
955 {
956 	/* Ignore security match for rsn override, OSEN and WPS connection */
957 	if (req->force_rsne_override || req->is_wps_connection ||
958 	    req->is_osen_connection) {
959 		filter->ignore_auth_enc_type = 1;
960 		return;
961 	}
962 
963 	filter->authmodeset = req->crypto.auth_type;
964 	filter->ucastcipherset = req->crypto.ciphers_pairwise;
965 	filter->key_mgmt = req->crypto.akm_suites;
966 	filter->mcastcipherset = req->crypto.group_cipher;
967 	filter->mgmtcipherset = req->crypto.mgmt_ciphers;
968 	cm_set_pmf_caps(req, filter);
969 }
970 
971 /**
972  * cm_set_fils_wep_key() - check and set wep or fils keys if required
973  * @cm_ctx: connection manager context
974  * @resp: connect resp
975  *
976  * Context: Can be called from any context and to be used only after posting a
977  * msg to SM (ie holding the SM lock) i.e. on successful connection.
978  */
979 static void cm_set_fils_wep_key(struct cnx_mgr *cm_ctx,
980 				struct wlan_cm_connect_resp *resp)
981 {
982 	int32_t cipher;
983 	struct qdf_mac_addr broadcast_mac = QDF_MAC_ADDR_BCAST_INIT;
984 
985 	/* Check and set FILS keys */
986 	if (cm_is_fils_connection(resp)) {
987 		cm_set_fils_key(cm_ctx, resp);
988 		return;
989 	}
990 	/* Check and set WEP keys */
991 	cipher = wlan_crypto_get_param(cm_ctx->vdev,
992 				       WLAN_CRYPTO_PARAM_UCAST_CIPHER);
993 	if (cipher < 0)
994 		return;
995 
996 	if (!(cipher & (1 << WLAN_CRYPTO_CIPHER_WEP_40 |
997 			1 << WLAN_CRYPTO_CIPHER_WEP_104)))
998 		return;
999 
1000 	cm_set_key(cm_ctx, true, 0, &resp->bssid);
1001 	cm_set_key(cm_ctx, false, 0, &broadcast_mac);
1002 }
1003 
1004 static void cm_teardown_tdls(struct wlan_objmgr_vdev *vdev)
1005 {
1006 	struct wlan_objmgr_psoc *psoc;
1007 
1008 	psoc = wlan_vdev_get_psoc(vdev);
1009 	if (!psoc)
1010 		return;
1011 
1012 	wlan_tdls_teardown_links_sync(psoc);
1013 }
1014 
1015 #else
1016 
1017 static inline
1018 bool cm_is_any_other_vdev_disconnecting(struct cnx_mgr *cm_ctx,
1019 					struct cm_req *cm_req)
1020 {
1021 	return false;
1022 }
1023 
1024 static inline
1025 bool cm_is_retry_with_same_candidate(struct cnx_mgr *cm_ctx,
1026 				     struct cm_connect_req *req,
1027 				     struct wlan_cm_connect_resp *resp)
1028 {
1029 	return false;
1030 }
1031 
1032 static inline
1033 bool cm_is_time_allowed_for_connect_attempt(struct cnx_mgr *cm_ctx,
1034 					    struct cm_connect_req *req)
1035 {
1036 	return true;
1037 }
1038 
1039 static inline void cm_update_advance_filter(struct wlan_objmgr_pdev *pdev,
1040 					    struct cnx_mgr *cm_ctx,
1041 					    struct scan_filter *filter,
1042 					    struct cm_connect_req *cm_req)
1043 {
1044 	struct wlan_objmgr_vdev *vdev = cm_ctx->vdev;
1045 
1046 	if (cm_ctx->cm_candidate_advance_filter)
1047 		cm_ctx->cm_candidate_advance_filter(vdev, filter);
1048 }
1049 
1050 static void cm_update_security_filter(struct scan_filter *filter,
1051 				      struct wlan_cm_connect_req *req)
1052 {
1053 	if (!QDF_HAS_PARAM(req->crypto.auth_type, WLAN_CRYPTO_AUTH_WAPI) &&
1054 	    !QDF_HAS_PARAM(req->crypto.auth_type, WLAN_CRYPTO_AUTH_RSNA) &&
1055 	    !QDF_HAS_PARAM(req->crypto.auth_type, WLAN_CRYPTO_AUTH_WPA)) {
1056 		filter->ignore_auth_enc_type = 1;
1057 		return;
1058 	}
1059 
1060 	filter->authmodeset = req->crypto.auth_type;
1061 	filter->ucastcipherset = req->crypto.ciphers_pairwise;
1062 	filter->key_mgmt = req->crypto.akm_suites;
1063 	filter->mcastcipherset = req->crypto.group_cipher;
1064 	filter->mgmtcipherset = req->crypto.mgmt_ciphers;
1065 	cm_set_pmf_caps(req, filter);
1066 }
1067 
1068 static inline void cm_set_fils_wep_key(struct cnx_mgr *cm_ctx,
1069 				       struct wlan_cm_connect_resp *resp)
1070 {}
1071 
1072 QDF_STATUS
1073 cm_peer_create_on_bss_select_ind_resp(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
1074 {
1075 	struct cm_req *cm_req;
1076 
1077 	cm_req = cm_get_req_by_cm_id(cm_ctx, *cm_id);
1078 	if (!cm_req)
1079 		return QDF_STATUS_E_FAILURE;
1080 
1081 	/* Update vdev mlme mac address based on connection type */
1082 	cm_update_vdev_mlme_macaddr(cm_ctx, &cm_req->connect_req);
1083 
1084 	cm_create_bss_peer(cm_ctx, &cm_req->connect_req);
1085 
1086 	return QDF_STATUS_SUCCESS;
1087 }
1088 
1089 QDF_STATUS cm_bss_select_ind_rsp(struct wlan_objmgr_vdev *vdev,
1090 				 QDF_STATUS status)
1091 {
1092 	struct cnx_mgr *cm_ctx;
1093 	QDF_STATUS qdf_status;
1094 	wlan_cm_id cm_id;
1095 	uint32_t prefix;
1096 	struct wlan_cm_connect_resp *resp;
1097 
1098 	cm_ctx = cm_get_cm_ctx(vdev);
1099 	if (!cm_ctx)
1100 		return QDF_STATUS_E_INVAL;
1101 
1102 	cm_id = cm_ctx->active_cm_id;
1103 	prefix = CM_ID_GET_PREFIX(cm_id);
1104 
1105 	if (prefix != CONNECT_REQ_PREFIX) {
1106 		mlme_err(CM_PREFIX_FMT "active req is not connect req",
1107 			 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), cm_id));
1108 		return QDF_STATUS_E_INVAL;
1109 	}
1110 
1111 	if (QDF_IS_STATUS_SUCCESS(status)) {
1112 		qdf_status =
1113 			cm_sm_deliver_event(vdev,
1114 				WLAN_CM_SM_EV_BSS_SELECT_IND_SUCCESS,
1115 				sizeof(wlan_cm_id), &cm_id);
1116 		if (QDF_IS_STATUS_SUCCESS(qdf_status))
1117 			return qdf_status;
1118 
1119 		goto post_err;
1120 	}
1121 
1122 	/* In case of failure try with next candidate */
1123 	resp = qdf_mem_malloc(sizeof(*resp));
1124 	if (!resp) {
1125 		qdf_status = QDF_STATUS_E_NOMEM;
1126 		goto post_err;
1127 	}
1128 
1129 	cm_fill_failure_resp_from_cm_id(cm_ctx, resp, cm_id,
1130 					CM_BSS_SELECT_IND_FAILED);
1131 	qdf_status =
1132 		cm_sm_deliver_event(vdev,
1133 				    WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE,
1134 				    sizeof(*resp), resp);
1135 	qdf_mem_free(resp);
1136 	if (QDF_IS_STATUS_SUCCESS(qdf_status))
1137 		return qdf_status;
1138 
1139 post_err:
1140 	/*
1141 	 * If there is a event posting error it means the SM state is not in
1142 	 * JOIN ACTIVE (some new cmd has changed the state of SM), so just
1143 	 * complete the connect command.
1144 	 */
1145 	cm_connect_handle_event_post_fail(cm_ctx, cm_id);
1146 	return qdf_status;
1147 }
1148 
1149 static inline void cm_teardown_tdls(struct wlan_objmgr_vdev *vdev) {}
1150 
1151 #endif /* CONN_MGR_ADV_FEATURE */
1152 
1153 static void cm_connect_prepare_scan_filter(struct wlan_objmgr_pdev *pdev,
1154 					   struct cnx_mgr *cm_ctx,
1155 					   struct cm_connect_req *cm_req,
1156 					   struct scan_filter *filter,
1157 					   bool security_valid_for_6ghz)
1158 {
1159 	if (!qdf_is_macaddr_zero(&cm_req->req.bssid)) {
1160 		filter->num_of_bssid = 1;
1161 		qdf_copy_macaddr(&filter->bssid_list[0], &cm_req->req.bssid);
1162 	}
1163 
1164 	qdf_copy_macaddr(&filter->bssid_hint, &cm_req->req.bssid_hint);
1165 	filter->num_of_ssid = 1;
1166 	qdf_mem_copy(&filter->ssid_list[0], &cm_req->req.ssid,
1167 		     sizeof(struct wlan_ssid));
1168 
1169 	if (cm_req->req.chan_freq) {
1170 		filter->num_of_channels = 1;
1171 		filter->chan_freq_list[0] = cm_req->req.chan_freq;
1172 	}
1173 
1174 	/* Security is not valid for 6Ghz so ignore 6Ghz APs */
1175 	if (!security_valid_for_6ghz)
1176 		filter->ignore_6ghz_channel = true;
1177 
1178 	if (cm_req->req.is_non_assoc_link)
1179 		filter->ignore_6ghz_channel = false;
1180 
1181 	cm_update_security_filter(filter, &cm_req->req);
1182 	cm_update_advance_filter(pdev, cm_ctx, filter, cm_req);
1183 }
1184 
1185 #ifdef WLAN_FEATURE_11BE_MLO
1186 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
1187 static QDF_STATUS cm_is_scan_support(struct cm_connect_req *cm_req)
1188 {
1189 	if (cm_req->req.is_non_assoc_link)
1190 		return QDF_STATUS_E_FAILURE;
1191 
1192 	return QDF_STATUS_SUCCESS;
1193 }
1194 #else
1195 static QDF_STATUS cm_is_scan_support(struct cm_connect_req *cm_req)
1196 {
1197 	if (cm_req->req.ml_parnter_info.num_partner_links)
1198 		return QDF_STATUS_E_FAILURE;
1199 
1200 	return QDF_STATUS_SUCCESS;
1201 }
1202 #endif
1203 #else
1204 static QDF_STATUS cm_is_scan_support(struct cm_connect_req *cm_req)
1205 {
1206 	return QDF_STATUS_SUCCESS;
1207 }
1208 #endif
1209 
1210 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_FEATURE_11BE_MLO_ADV_FEATURE)
1211 #define CFG_MLO_ASSOC_LINK_BAND_MAX 0x70
1212 
1213 static QDF_STATUS cm_update_mlo_filter(struct wlan_objmgr_pdev *pdev,
1214 				       struct cm_connect_req *cm_req,
1215 				       struct scan_filter *filter)
1216 {
1217 	struct wlan_objmgr_psoc *psoc;
1218 
1219 	psoc = wlan_pdev_get_psoc(pdev);
1220 	filter->band_bitmap = wlan_mlme_get_sta_mlo_conn_band_bmp(psoc);
1221 	/* Apply assoc band filter only for assoc link */
1222 	if (cm_req->req.is_non_assoc_link) {
1223 		filter->band_bitmap =  filter->band_bitmap |
1224 				       CFG_MLO_ASSOC_LINK_BAND_MAX;
1225 	}
1226 	mlme_debug("band bitmap: 0x%x", filter->band_bitmap);
1227 
1228 	return QDF_STATUS_SUCCESS;
1229 }
1230 #else
1231 static QDF_STATUS cm_update_mlo_filter(struct wlan_objmgr_pdev *pdev,
1232 				       struct cm_connect_req *cm_req,
1233 				       struct scan_filter *filter)
1234 {
1235 	return QDF_STATUS_SUCCESS;
1236 }
1237 #endif
1238 
1239 static QDF_STATUS cm_connect_get_candidates(struct wlan_objmgr_pdev *pdev,
1240 					    struct cnx_mgr *cm_ctx,
1241 					    struct cm_connect_req *cm_req)
1242 {
1243 	struct scan_filter *filter;
1244 	uint32_t num_bss = 0;
1245 	enum QDF_OPMODE op_mode;
1246 	qdf_list_t *candidate_list;
1247 	uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
1248 	bool security_valid_for_6ghz;
1249 	const uint8_t *rsnxe;
1250 
1251 	filter = qdf_mem_malloc(sizeof(*filter));
1252 	if (!filter)
1253 		return QDF_STATUS_E_NOMEM;
1254 
1255 	rsnxe = wlan_get_ie_ptr_from_eid(WLAN_ELEMID_RSNXE,
1256 					 cm_req->req.assoc_ie.ptr,
1257 					 cm_req->req.assoc_ie.len);
1258 	security_valid_for_6ghz =
1259 		wlan_cm_6ghz_allowed_for_akm(wlan_pdev_get_psoc(pdev),
1260 					     cm_req->req.crypto.akm_suites,
1261 					     cm_req->req.crypto.rsn_caps,
1262 					     rsnxe, cm_req->req.sae_pwe,
1263 					     cm_req->req.is_wps_connection);
1264 
1265 	/*
1266 	 * Ignore connect req if the freq is provided and its 6Ghz and
1267 	 * security is not valid for 6Ghz
1268 	 */
1269 	if (cm_req->req.chan_freq && !security_valid_for_6ghz &&
1270 	    WLAN_REG_IS_6GHZ_CHAN_FREQ(cm_req->req.chan_freq)) {
1271 		mlme_info(CM_PREFIX_FMT "6ghz freq (%d) given and 6Ghz not allowed for the security in connect req",
1272 			  CM_PREFIX_REF(vdev_id, cm_req->cm_id),
1273 			  cm_req->req.chan_freq);
1274 		return QDF_STATUS_E_INVAL;
1275 	}
1276 	cm_connect_prepare_scan_filter(pdev, cm_ctx, cm_req, filter,
1277 				       security_valid_for_6ghz);
1278 
1279 	cm_update_mlo_filter(pdev, cm_req, filter);
1280 
1281 	candidate_list = wlan_scan_get_result(pdev, filter);
1282 	if (candidate_list) {
1283 		num_bss = qdf_list_size(candidate_list);
1284 		mlme_debug(CM_PREFIX_FMT "num_entries found %d",
1285 			   CM_PREFIX_REF(vdev_id, cm_req->cm_id), num_bss);
1286 	}
1287 
1288 	op_mode = wlan_vdev_mlme_get_opmode(cm_ctx->vdev);
1289 	if (num_bss && op_mode == QDF_STA_MODE &&
1290 	    !cm_req->req.is_non_assoc_link)
1291 		cm_calculate_scores(cm_ctx, pdev, filter, candidate_list);
1292 	qdf_mem_free(filter);
1293 
1294 	if (!candidate_list || !qdf_list_size(candidate_list)) {
1295 		QDF_STATUS status;
1296 
1297 		if (candidate_list)
1298 			wlan_scan_purge_results(candidate_list);
1299 		mlme_info(CM_PREFIX_FMT "no valid candidate found, num_bss %d scan_id %d",
1300 			  CM_PREFIX_REF(vdev_id, cm_req->cm_id), num_bss,
1301 			  cm_req->scan_id);
1302 
1303 		/*
1304 		 * If connect scan was already done OR candidate were found
1305 		 * but none of them were valid OR if ML link connection
1306 		 * return QDF_STATUS_E_EMPTY.
1307 		 */
1308 		if (cm_req->scan_id || num_bss ||
1309 		    QDF_IS_STATUS_ERROR(cm_is_scan_support(cm_req)))
1310 			return QDF_STATUS_E_EMPTY;
1311 
1312 		/* Try connect scan to search for any valid candidate */
1313 		status = cm_sm_deliver_event_sync(cm_ctx, WLAN_CM_SM_EV_SCAN,
1314 						  sizeof(*cm_req), cm_req);
1315 		/*
1316 		 * If connect scan is initiated, return pending, so that
1317 		 * connect start after scan complete
1318 		 */
1319 		if (QDF_IS_STATUS_SUCCESS(status))
1320 			status = QDF_STATUS_E_PENDING;
1321 
1322 		return status;
1323 	}
1324 	cm_req->candidate_list = candidate_list;
1325 
1326 	return QDF_STATUS_SUCCESS;
1327 }
1328 
1329 QDF_STATUS cm_if_mgr_inform_connect_complete(struct wlan_objmgr_vdev *vdev,
1330 					     QDF_STATUS connect_status)
1331 {
1332 	struct if_mgr_event_data *connect_complete;
1333 
1334 	connect_complete = qdf_mem_malloc(sizeof(*connect_complete));
1335 	if (!connect_complete)
1336 		return QDF_STATUS_E_NOMEM;
1337 
1338 	connect_complete->status = connect_status;
1339 	if_mgr_deliver_event(vdev, WLAN_IF_MGR_EV_CONNECT_COMPLETE,
1340 			     connect_complete);
1341 	qdf_mem_free(connect_complete);
1342 
1343 	return QDF_STATUS_SUCCESS;
1344 }
1345 
1346 static QDF_STATUS
1347 cm_if_mgr_inform_connect_start(struct wlan_objmgr_vdev *vdev)
1348 {
1349 	return if_mgr_deliver_event(vdev, WLAN_IF_MGR_EV_CONNECT_START, NULL);
1350 }
1351 
1352 QDF_STATUS
1353 cm_handle_connect_req_in_non_init_state(struct cnx_mgr *cm_ctx,
1354 					struct cm_connect_req *cm_req,
1355 					enum wlan_cm_sm_state cm_state_substate)
1356 {
1357 	if (cm_state_substate != WLAN_CM_S_CONNECTED &&
1358 	    cm_is_connect_req_reassoc(&cm_req->req)) {
1359 		cm_req->req.reassoc_in_non_connected = true;
1360 		mlme_debug(CM_PREFIX_FMT "Reassoc received in %d state",
1361 			   CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
1362 					 cm_req->cm_id),
1363 			   cm_state_substate);
1364 	}
1365 
1366 	switch (cm_state_substate) {
1367 	case WLAN_CM_S_ROAMING:
1368 		/* for FW roam/LFR3 remove the req from the list */
1369 		if (cm_roam_offload_enabled(wlan_vdev_get_psoc(cm_ctx->vdev)))
1370 			cm_flush_pending_request(cm_ctx, ROAM_REQ_PREFIX,
1371 						 false);
1372 		fallthrough;
1373 	case WLAN_CM_S_CONNECTED:
1374 	case WLAN_CM_SS_JOIN_ACTIVE:
1375 		/*
1376 		 * In roaming state, there would be no
1377 		 * pending command, so for new connect request, queue internal
1378 		 * disconnect. The preauth and reassoc process will be aborted
1379 		 * as the state machine will be moved to connecting state and
1380 		 * preauth/reassoc/roam start event posting will fail.
1381 		 *
1382 		 * In connected state, there would be no pending command, so
1383 		 * for new connect request, queue internal disconnect
1384 		 *
1385 		 * In join active state there would be only one active connect
1386 		 * request in the cm req list, so to abort at certain stages and
1387 		 * to cleanup after its completion, queue internal disconnect.
1388 		 */
1389 		cm_initiate_internal_disconnect(cm_ctx);
1390 		break;
1391 	case WLAN_CM_SS_SCAN:
1392 		/* In the scan state abort the ongoing scan */
1393 		cm_vdev_scan_cancel(wlan_vdev_get_pdev(cm_ctx->vdev),
1394 				    cm_ctx->vdev);
1395 		fallthrough;
1396 	case WLAN_CM_SS_JOIN_PENDING:
1397 		/*
1398 		 * In case of scan or join pending there could be 2 scenarios:-
1399 		 *
1400 		 * 1. There is a connect request pending, so just remove
1401 		 *    the pending connect req. As we will queue a new connect
1402 		 *    req, all resp for pending connect req will be dropped.
1403 		 * 2. There is a connect request in active and
1404 		 *    and a internal disconnect followed by a connect req in
1405 		 *    pending. In this case the disconnect will take care of
1406 		 *    cleaning up the active connect request and thus only
1407 		 *    remove the pending connect.
1408 		 */
1409 		cm_flush_pending_request(cm_ctx, CONNECT_REQ_PREFIX, false);
1410 		break;
1411 	case WLAN_CM_S_DISCONNECTING:
1412 		/*
1413 		 * Flush failed pending connect req as new req is received
1414 		 * and its no longer the latest one.
1415 		 */
1416 		if (cm_ctx->connect_count)
1417 			cm_flush_pending_request(cm_ctx, CONNECT_REQ_PREFIX,
1418 						 true);
1419 		/*
1420 		 * In case of disconnecting state, there could be 2 scenarios:-
1421 		 * In both case no state specific action is required.
1422 		 * 1. There is disconnect request in the cm_req list, no action
1423 		 *    required to cleanup.
1424 		 *    so just add the connect request to the list.
1425 		 * 2. There is a connect request activated, followed by
1426 		 *    disconnect in pending queue. So keep the disconnect
1427 		 *    to cleanup the active connect and no action required to
1428 		 *    cleanup.
1429 		 */
1430 		break;
1431 	default:
1432 		mlme_err("Vdev %d Connect req in invalid state %d",
1433 			 wlan_vdev_get_id(cm_ctx->vdev),
1434 			 cm_state_substate);
1435 		return QDF_STATUS_E_FAILURE;
1436 	};
1437 
1438 	/* Queue the new connect request after state specific actions */
1439 	return cm_add_connect_req_to_list(cm_ctx, cm_req);
1440 }
1441 
1442 QDF_STATUS cm_connect_start(struct cnx_mgr *cm_ctx,
1443 			    struct cm_connect_req *cm_req)
1444 {
1445 	struct wlan_objmgr_pdev *pdev;
1446 	struct wlan_objmgr_psoc *psoc;
1447 	enum wlan_cm_connect_fail_reason reason = CM_GENERIC_FAILURE;
1448 	QDF_STATUS status;
1449 	uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
1450 
1451 	/* Interface event */
1452 	pdev = wlan_vdev_get_pdev(cm_ctx->vdev);
1453 	if (!pdev) {
1454 		mlme_err(CM_PREFIX_FMT "Failed to find pdev",
1455 			 CM_PREFIX_REF(vdev_id, cm_req->cm_id));
1456 		goto connect_err;
1457 	}
1458 
1459 	psoc = wlan_pdev_get_psoc(pdev);
1460 	if (!psoc) {
1461 		mlme_err(CM_PREFIX_FMT "Failed to find psoc",
1462 			 CM_PREFIX_REF(vdev_id, cm_req->cm_id));
1463 		goto connect_err;
1464 	}
1465 
1466 	/*
1467 	 * Do not initiate the duplicate ifmanager and connect start ind if
1468 	 * this is called from Scan for ssid
1469 	 */
1470 	if (!cm_req->scan_id) {
1471 		cm_if_mgr_inform_connect_start(cm_ctx->vdev);
1472 		status = mlme_cm_connect_start_ind(cm_ctx->vdev, &cm_req->req);
1473 		if (QDF_IS_STATUS_ERROR(status)) {
1474 			reason = CM_NO_CANDIDATE_FOUND;
1475 			goto connect_err;
1476 		}
1477 	}
1478 
1479 	status = cm_connect_get_candidates(pdev, cm_ctx, cm_req);
1480 
1481 	/* In case of status pending connect will continue after scan */
1482 	if (status == QDF_STATUS_E_PENDING)
1483 		return QDF_STATUS_SUCCESS;
1484 	if (QDF_IS_STATUS_ERROR(status)) {
1485 		reason = CM_NO_CANDIDATE_FOUND;
1486 		goto connect_err;
1487 	}
1488 
1489 	status = cm_check_for_hw_mode_change(psoc, cm_req->candidate_list,
1490 					     vdev_id, cm_req->cm_id);
1491 	if (QDF_IS_STATUS_ERROR(status) && status != QDF_STATUS_E_ALREADY) {
1492 		reason = CM_HW_MODE_FAILURE;
1493 		mlme_err(CM_PREFIX_FMT "Failed to set HW mode change",
1494 			 CM_PREFIX_REF(vdev_id, cm_req->cm_id));
1495 		goto connect_err;
1496 	} else if (QDF_IS_STATUS_SUCCESS(status)) {
1497 		mlme_debug(CM_PREFIX_FMT "Connect will continue after HW mode change",
1498 			   CM_PREFIX_REF(vdev_id, cm_req->cm_id));
1499 		return QDF_STATUS_SUCCESS;
1500 	}
1501 
1502 	status = cm_ser_connect_req(pdev, cm_ctx, cm_req);
1503 	if (QDF_IS_STATUS_ERROR(status)) {
1504 		reason = CM_SER_FAILURE;
1505 		goto connect_err;
1506 	}
1507 
1508 	return QDF_STATUS_SUCCESS;
1509 
1510 connect_err:
1511 	return cm_send_connect_start_fail(cm_ctx, cm_req, reason);
1512 }
1513 
1514 /**
1515  * cm_get_valid_candidate() - This API will be called to get the next valid
1516  * candidate
1517  * @cm_ctx: connection manager context
1518  * @cm_req: Connect request.
1519  * @resp: connect resp from previous connection attempt
1520  * @same_candidate_used: this will be set if same candidate used
1521  *
1522  * This function return a valid candidate to try connection. It return failure
1523  * if no valid candidate is present or all valid candidate are tried.
1524  *
1525  * Return: QDF status
1526  */
1527 static QDF_STATUS cm_get_valid_candidate(struct cnx_mgr *cm_ctx,
1528 					 struct cm_req *cm_req,
1529 					 struct wlan_cm_connect_resp *resp,
1530 					 bool *same_candidate_used)
1531 {
1532 	struct wlan_objmgr_psoc *psoc;
1533 	struct scan_cache_node *scan_node = NULL;
1534 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
1535 	struct scan_cache_node *new_candidate = NULL, *prev_candidate;
1536 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1537 	uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
1538 	bool use_same_candidate = false;
1539 	int32_t akm;
1540 
1541 	psoc = wlan_vdev_get_psoc(cm_ctx->vdev);
1542 	if (!psoc) {
1543 		mlme_err(CM_PREFIX_FMT "Failed to find psoc",
1544 			 CM_PREFIX_REF(vdev_id, cm_req->cm_id));
1545 		return QDF_STATUS_E_FAILURE;
1546 	}
1547 
1548 	prev_candidate = cm_req->connect_req.cur_candidate;
1549 	/*
1550 	 * In case of STA/CLI + STA/CLI, if a STA/CLI is in connecting state and
1551 	 * a disconnect is received on any other STA/CLI, the disconnect can
1552 	 * timeout waiting for the connection on first STA/CLI to get completed.
1553 	 * This is because the connect is a blocking serialization command and
1554 	 * it can try multiple candidates and thus can take upto 30+ sec to
1555 	 * complete.
1556 	 *
1557 	 * Now osif will proceed with vdev delete after disconnect timeout.
1558 	 * This can lead to vdev delete sent without vdev down/stop/peer delete
1559 	 * for the vdev.
1560 	 *
1561 	 * So abort the connection if any of the vdev is waiting for disconnect,
1562 	 * to avoid disconnect timeout.
1563 	 */
1564 	if (cm_is_any_other_vdev_disconnecting(cm_ctx, cm_req)) {
1565 		status = QDF_STATUS_E_FAILURE;
1566 		goto flush_single_pmk;
1567 	}
1568 
1569 	if (cm_req->connect_req.connect_attempts >=
1570 	    cm_ctx->max_connect_attempts) {
1571 		mlme_info(CM_PREFIX_FMT "%d attempts tried, max %d",
1572 			  CM_PREFIX_REF(vdev_id, cm_req->cm_id),
1573 			  cm_req->connect_req.connect_attempts,
1574 			  cm_ctx->max_connect_attempts);
1575 		status = QDF_STATUS_E_FAILURE;
1576 		goto flush_single_pmk;
1577 	}
1578 
1579 	/* From 2nd attempt onward, check if time allows for a new attempt */
1580 	if (cm_req->connect_req.connect_attempts &&
1581 	    !cm_is_time_allowed_for_connect_attempt(cm_ctx,
1582 						    &cm_req->connect_req)) {
1583 		status = QDF_STATUS_E_FAILURE;
1584 		goto flush_single_pmk;
1585 	}
1586 
1587 	if (prev_candidate && resp &&
1588 	    cm_is_retry_with_same_candidate(cm_ctx, &cm_req->connect_req,
1589 					    resp)) {
1590 		new_candidate = prev_candidate;
1591 		use_same_candidate = true;
1592 		goto try_same_candidate;
1593 	}
1594 
1595 	/*
1596 	 * Get next candidate if prev_candidate is not NULL, else get
1597 	 * the first candidate
1598 	 */
1599 	if (prev_candidate)
1600 		qdf_list_peek_next(cm_req->connect_req.candidate_list,
1601 				   &prev_candidate->node, &cur_node);
1602 	else
1603 		qdf_list_peek_front(cm_req->connect_req.candidate_list,
1604 				    &cur_node);
1605 
1606 	while (cur_node) {
1607 		qdf_list_peek_next(cm_req->connect_req.candidate_list,
1608 				   cur_node, &next_node);
1609 		scan_node = qdf_container_of(cur_node, struct scan_cache_node,
1610 					     node);
1611 		status = cm_if_mgr_validate_candidate(cm_ctx, scan_node->entry);
1612 		if (QDF_IS_STATUS_SUCCESS(status)) {
1613 			new_candidate = scan_node;
1614 			break;
1615 		}
1616 
1617 		cur_node = next_node;
1618 		next_node = NULL;
1619 	}
1620 
1621 	/*
1622 	 * If cur_node is NULL prev candidate was last to be tried so no more
1623 	 * candidates left for connect now.
1624 	 */
1625 	if (!cur_node) {
1626 		mlme_debug(CM_PREFIX_FMT "No more candidates left",
1627 			   CM_PREFIX_REF(vdev_id, cm_req->cm_id));
1628 		cm_req->connect_req.cur_candidate = NULL;
1629 		status = QDF_STATUS_E_FAILURE;
1630 		goto flush_single_pmk;
1631 	}
1632 
1633 	/* Reset current candidate retries when a new candidate is tried */
1634 	cm_req->connect_req.cur_candidate_retries = 0;
1635 
1636 try_same_candidate:
1637 	cm_req->connect_req.connect_attempts++;
1638 	cm_req->connect_req.cur_candidate = new_candidate;
1639 
1640 flush_single_pmk:
1641 	akm = wlan_crypto_get_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_KEY_MGMT);
1642 	/*
1643 	 * If connection fails with Single PMK bssid (prev candidate),
1644 	 * clear the pmk entry. Flush only in case if we are not trying again
1645 	 * with same candidate again.
1646 	 */
1647 	if (prev_candidate && !use_same_candidate &&
1648 	    util_scan_entry_single_pmk(psoc, prev_candidate->entry) &&
1649 	    QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE))
1650 		cm_delete_pmksa_for_single_pmk_bssid(cm_ctx,
1651 						&prev_candidate->entry->bssid);
1652 
1653 	if (same_candidate_used)
1654 		*same_candidate_used = use_same_candidate;
1655 
1656 	return status;
1657 }
1658 
1659 static QDF_STATUS
1660 cm_send_bss_select_ind(struct cnx_mgr *cm_ctx, struct cm_connect_req *req)
1661 {
1662 	QDF_STATUS status;
1663 	struct wlan_cm_vdev_connect_req vdev_req;
1664 	struct wlan_cm_connect_resp *resp;
1665 
1666 	vdev_req.vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
1667 	vdev_req.cm_id = req->cm_id;
1668 	vdev_req.bss = req->cur_candidate;
1669 
1670 	status = mlme_cm_bss_select_ind(cm_ctx->vdev, &vdev_req);
1671 	if (QDF_IS_STATUS_SUCCESS(status) ||
1672 	    status == QDF_STATUS_E_NOSUPPORT)
1673 		return status;
1674 
1675 	/* In supported and failure try with next candidate */
1676 	mlme_err(CM_PREFIX_FMT "mlme candidate select indication failed %d",
1677 		 CM_PREFIX_REF(vdev_req.vdev_id, req->cm_id), status);
1678 	resp = qdf_mem_malloc(sizeof(*resp));
1679 	if (!resp)
1680 		return QDF_STATUS_E_FAILURE;
1681 
1682 	cm_fill_failure_resp_from_cm_id(cm_ctx, resp, req->cm_id,
1683 					CM_BSS_SELECT_IND_FAILED);
1684 	cm_sm_deliver_event_sync(cm_ctx,
1685 				 WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE,
1686 				 sizeof(*resp), resp);
1687 	qdf_mem_free(resp);
1688 
1689 	return QDF_STATUS_SUCCESS;
1690 }
1691 
1692 static void cm_update_ser_timer_for_new_candidate(struct cnx_mgr *cm_ctx,
1693 						  wlan_cm_id cm_id)
1694 {
1695 	struct wlan_serialization_command cmd;
1696 
1697 	cmd.cmd_type = WLAN_SER_CMD_VDEV_CONNECT;
1698 	cmd.cmd_id = cm_id;
1699 	cmd.cmd_timeout_duration = cm_ctx->connect_timeout;
1700 	cmd.vdev = cm_ctx->vdev;
1701 
1702 	wlan_serialization_update_timer(&cmd);
1703 }
1704 
1705 QDF_STATUS cm_try_next_candidate(struct cnx_mgr *cm_ctx,
1706 				 struct wlan_cm_connect_resp *resp)
1707 {
1708 	QDF_STATUS status;
1709 	struct cm_req *cm_req;
1710 	bool same_candidate_used = false;
1711 
1712 	cm_req = cm_get_req_by_cm_id(cm_ctx, resp->cm_id);
1713 	if (!cm_req)
1714 		return QDF_STATUS_E_FAILURE;
1715 
1716 	status = cm_get_valid_candidate(cm_ctx, cm_req, resp,
1717 					&same_candidate_used);
1718 	if (QDF_IS_STATUS_ERROR(status))
1719 		goto connect_err;
1720 
1721 	/*
1722 	 * Do not indicate to OSIF if same candidate is used again as we are not
1723 	 * done with this candidate. So inform once we move to next candidate.
1724 	 * This will also avoid flush for the scan entry.
1725 	 */
1726 	if (!same_candidate_used)
1727 		mlme_cm_osif_failed_candidate_ind(cm_ctx->vdev, resp);
1728 
1729 	cm_update_ser_timer_for_new_candidate(cm_ctx, resp->cm_id);
1730 
1731 	status = cm_send_bss_select_ind(cm_ctx, &cm_req->connect_req);
1732 
1733 	/*
1734 	 * If candidate select indication is not supported continue with bss
1735 	 * peer create, else peer will be created after resp.
1736 	 */
1737 	if (status == QDF_STATUS_E_NOSUPPORT) {
1738 		/* Update vdev mlme mac address based on connection type */
1739 		cm_update_vdev_mlme_macaddr(cm_ctx, &cm_req->connect_req);
1740 
1741 		cm_create_bss_peer(cm_ctx, &cm_req->connect_req);
1742 	} else if (QDF_IS_STATUS_ERROR(status)) {
1743 		goto connect_err;
1744 	}
1745 
1746 	return QDF_STATUS_SUCCESS;
1747 
1748 connect_err:
1749 	return cm_sm_deliver_event_sync(cm_ctx, WLAN_CM_SM_EV_CONNECT_FAILURE,
1750 					sizeof(*resp), resp);
1751 
1752 }
1753 
1754 bool cm_connect_resp_cmid_match_list_head(struct cnx_mgr *cm_ctx,
1755 					  struct wlan_cm_connect_resp *resp)
1756 {
1757 	return cm_check_cmid_match_list_head(cm_ctx, &resp->cm_id);
1758 }
1759 
1760 void cm_fill_vdev_crypto_params(struct cnx_mgr *cm_ctx,
1761 				struct wlan_cm_connect_req *req)
1762 {
1763 	/* fill vdev crypto from the connect req */
1764 	wlan_crypto_set_vdev_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_AUTH_MODE,
1765 				   req->crypto.auth_type);
1766 	wlan_crypto_set_vdev_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_KEY_MGMT,
1767 				   req->crypto.akm_suites);
1768 	wlan_crypto_set_vdev_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_UCAST_CIPHER,
1769 				   req->crypto.ciphers_pairwise);
1770 	wlan_crypto_set_vdev_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_MCAST_CIPHER,
1771 				   req->crypto.group_cipher);
1772 	wlan_crypto_set_vdev_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_MGMT_CIPHER,
1773 				   req->crypto.mgmt_ciphers);
1774 	wlan_crypto_set_vdev_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_RSN_CAP,
1775 				   req->crypto.rsn_caps);
1776 }
1777 
1778 QDF_STATUS cm_connect_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
1779 {
1780 	struct cm_req *cm_req;
1781 	QDF_STATUS status;
1782 	struct wlan_cm_connect_req *req;
1783 
1784 	cm_ctx->active_cm_id = *cm_id;
1785 	cm_req = cm_get_req_by_cm_id(cm_ctx, *cm_id);
1786 	if (!cm_req) {
1787 		/*
1788 		 * Remove the command from serialization active queue, if
1789 		 * connect req was not found, to avoid active cmd timeout.
1790 		 * This can happen if a thread tried to flush the pending
1791 		 * connect request and while doing so, it removed the
1792 		 * CM pending request, but before it tried to remove pending
1793 		 * command from serialization, the command becomes active in
1794 		 * another thread.
1795 		 */
1796 		cm_remove_cmd_from_serialization(cm_ctx, *cm_id);
1797 		return QDF_STATUS_E_INVAL;
1798 	}
1799 
1800 	cm_req->connect_req.connect_active_time =
1801 				qdf_mc_timer_get_system_time();
1802 	req = &cm_req->connect_req.req;
1803 	wlan_vdev_mlme_set_ssid(cm_ctx->vdev, req->ssid.ssid, req->ssid.length);
1804 	/* free vdev keys before setting crypto params */
1805 	wlan_crypto_free_vdev_key(cm_ctx->vdev);
1806 	cm_fill_vdev_crypto_params(cm_ctx, req);
1807 	cm_store_wep_key(cm_ctx, &req->crypto, *cm_id);
1808 
1809 	status = cm_get_valid_candidate(cm_ctx, cm_req, NULL, NULL);
1810 	if (QDF_IS_STATUS_ERROR(status))
1811 		goto connect_err;
1812 
1813 	status = cm_send_bss_select_ind(cm_ctx, &cm_req->connect_req);
1814 	/*
1815 	 * If candidate select indication is not supported continue with bss
1816 	 * peer create, else peer will be created after resp.
1817 	 */
1818 	if (status == QDF_STATUS_E_NOSUPPORT) {
1819 		/* Update vdev mlme mac address based on connection type */
1820 		cm_update_vdev_mlme_macaddr(cm_ctx, &cm_req->connect_req);
1821 
1822 		cm_create_bss_peer(cm_ctx, &cm_req->connect_req);
1823 	} else if (QDF_IS_STATUS_ERROR(status)) {
1824 		goto connect_err;
1825 	}
1826 
1827 	return QDF_STATUS_SUCCESS;
1828 
1829 connect_err:
1830 	return cm_send_connect_start_fail(cm_ctx,
1831 					  &cm_req->connect_req, CM_JOIN_FAILED);
1832 }
1833 
1834 #ifdef WLAN_FEATURE_FILS_SK
1835 static void cm_copy_fils_info(struct wlan_cm_vdev_connect_req *req,
1836 			      struct cm_req *cm_req)
1837 {
1838 	req->fils_info = &cm_req->connect_req.req.fils_info;
1839 }
1840 
1841 static inline void cm_set_fils_connection(struct cnx_mgr *cm_ctx,
1842 					  struct wlan_cm_connect_resp *resp)
1843 {
1844 	int32_t key_mgmt;
1845 
1846 	/*
1847 	 * Check and set only in case of failure and when
1848 	 * resp->is_fils_connection is not already set, else return.
1849 	 */
1850 	if (QDF_IS_STATUS_SUCCESS(resp->connect_status) ||
1851 	    resp->is_fils_connection)
1852 		return;
1853 
1854 	key_mgmt = wlan_crypto_get_param(cm_ctx->vdev,
1855 					 WLAN_CRYPTO_PARAM_KEY_MGMT);
1856 
1857 	if (key_mgmt & (1 << WLAN_CRYPTO_KEY_MGMT_FILS_SHA256 |
1858 			  1 << WLAN_CRYPTO_KEY_MGMT_FILS_SHA384 |
1859 			  1 << WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA256 |
1860 			  1 << WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA384))
1861 		resp->is_fils_connection = true;
1862 }
1863 #else
1864 static inline void cm_copy_fils_info(struct wlan_cm_vdev_connect_req *req,
1865 				     struct cm_req *cm_req)
1866 {
1867 }
1868 
1869 static inline void cm_set_fils_connection(struct cnx_mgr *cm_ctx,
1870 					  struct wlan_cm_connect_resp *resp)
1871 {
1872 }
1873 #endif
1874 
1875 #ifdef WLAN_FEATURE_11BE_MLO
1876 static inline
1877 void cm_update_ml_partner_info(struct wlan_cm_connect_req *req,
1878 			       struct wlan_cm_vdev_connect_req *connect_req)
1879 {
1880 	if (req->ml_parnter_info.num_partner_links)
1881 		qdf_mem_copy(&connect_req->ml_parnter_info,
1882 			     &req->ml_parnter_info,
1883 			     sizeof(struct mlo_partner_info));
1884 }
1885 #else
1886 static inline
1887 void cm_update_ml_partner_info(struct wlan_cm_connect_req *req,
1888 			       struct wlan_cm_vdev_connect_req *connect_req)
1889 {
1890 }
1891 #endif
1892 
1893 static
1894 void cm_update_per_peer_key_mgmt_crypto_params(struct wlan_objmgr_vdev *vdev,
1895 					struct security_info *neg_sec_info)
1896 {
1897 	int32_t key_mgmt = 0;
1898 	int32_t neg_akm = neg_sec_info->key_mgmt;
1899 
1900 	/*
1901 	 * As there can be multiple AKM present select the most secured AKM
1902 	 * present
1903 	 */
1904 	if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FT_SAE))
1905 		QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_SAE);
1906 	else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_SAE))
1907 		QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_SAE);
1908 	else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B))
1909 		QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B);
1910 	else if (QDF_HAS_PARAM(neg_akm,
1911 			       WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B_192))
1912 		QDF_SET_PARAM(key_mgmt,
1913 			      WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SUITE_B_192);
1914 	else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FILS_SHA256))
1915 		QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FILS_SHA256);
1916 	else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FILS_SHA384))
1917 		QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FILS_SHA384);
1918 	else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA256))
1919 		QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA256);
1920 	else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA384))
1921 		QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_FILS_SHA384);
1922 	else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_OWE))
1923 		QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_OWE);
1924 	else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_DPP))
1925 		QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_DPP);
1926 	else if (QDF_HAS_PARAM(neg_akm,
1927 			       WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384))
1928 		QDF_SET_PARAM(key_mgmt,
1929 			      WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384);
1930 	else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FT_PSK))
1931 		QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_PSK);
1932 	else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X))
1933 		QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X);
1934 	else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_PSK))
1935 		QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_PSK);
1936 	else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256))
1937 		QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256);
1938 	else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_PSK_SHA256))
1939 		QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_PSK_SHA256);
1940 	else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_FT_PSK_SHA384))
1941 		QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_PSK_SHA384);
1942 	else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_PSK_SHA384))
1943 		QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_PSK_SHA384);
1944 	else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_WAPI_PSK))
1945 		QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_WAPI_PSK);
1946 	else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_WAPI_CERT))
1947 		QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_WAPI_CERT);
1948 	else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_CCKM))
1949 		QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_CCKM);
1950 	else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_OSEN))
1951 		QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_OSEN);
1952 	else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_WPS))
1953 		QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_WPS);
1954 	else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X))
1955 		QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_IEEE8021X);
1956 	else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_NO_WPA))
1957 		QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_NO_WPA);
1958 	else if (QDF_HAS_PARAM(neg_akm, WLAN_CRYPTO_KEY_MGMT_WPA_NONE))
1959 		QDF_SET_PARAM(key_mgmt, WLAN_CRYPTO_KEY_MGMT_WPA_NONE);
1960 	else /* use original if no akm match */
1961 		key_mgmt = neg_akm;
1962 
1963 	wlan_crypto_set_vdev_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT, key_mgmt);
1964 	/*
1965 	 * Overwrite the key mgmt with single key_mgmt if multiple are present
1966 	 */
1967 	neg_sec_info->key_mgmt = key_mgmt;
1968 }
1969 
1970 static
1971 void cm_update_per_peer_ucastcipher_crypto_params(struct wlan_objmgr_vdev *vdev,
1972 					struct security_info *neg_sec_info)
1973 {
1974 	int32_t ucastcipherset = 0;
1975 
1976 	/*
1977 	 * As there can be multiple ucastcipher present select the most secured
1978 	 * ucastcipher present.
1979 	 */
1980 	if (QDF_HAS_PARAM(neg_sec_info->ucastcipherset,
1981 			  WLAN_CRYPTO_CIPHER_AES_GCM_256))
1982 		QDF_SET_PARAM(ucastcipherset, WLAN_CRYPTO_CIPHER_AES_GCM_256);
1983 	else if (QDF_HAS_PARAM(neg_sec_info->ucastcipherset,
1984 			       WLAN_CRYPTO_CIPHER_AES_CCM_256))
1985 		QDF_SET_PARAM(ucastcipherset, WLAN_CRYPTO_CIPHER_AES_CCM_256);
1986 	else if (QDF_HAS_PARAM(neg_sec_info->ucastcipherset,
1987 			       WLAN_CRYPTO_CIPHER_AES_GCM))
1988 		QDF_SET_PARAM(ucastcipherset, WLAN_CRYPTO_CIPHER_AES_GCM);
1989 	else if (QDF_HAS_PARAM(neg_sec_info->ucastcipherset,
1990 			       WLAN_CRYPTO_CIPHER_AES_CCM))
1991 		QDF_SET_PARAM(ucastcipherset, WLAN_CRYPTO_CIPHER_AES_CCM);
1992 	else if (QDF_HAS_PARAM(neg_sec_info->ucastcipherset,
1993 			       WLAN_CRYPTO_CIPHER_TKIP))
1994 		QDF_SET_PARAM(ucastcipherset, WLAN_CRYPTO_CIPHER_TKIP);
1995 	else
1996 		ucastcipherset = neg_sec_info->ucastcipherset;
1997 
1998 	wlan_crypto_set_vdev_param(vdev, WLAN_CRYPTO_PARAM_UCAST_CIPHER,
1999 				   ucastcipherset);
2000 	/*
2001 	 * Overwrite the ucastcipher with single ucast cipher if multiple are
2002 	 * present
2003 	 */
2004 	neg_sec_info->ucastcipherset = ucastcipherset;
2005 }
2006 
2007 static
2008 void cm_update_per_peer_crypto_params(struct wlan_objmgr_vdev *vdev,
2009 				      struct cm_connect_req *connect_req)
2010 {
2011 	struct security_info *neg_sec_info;
2012 	uint16_t rsn_caps;
2013 
2014 	/* Do only for WPA/WPA2/WPA3 */
2015 	if (!connect_req->req.crypto.wpa_versions)
2016 		return;
2017 
2018 	/*
2019 	 * Some non PMF AP misbehave if in assoc req RSN IE contain PMF capable
2020 	 * bit set. Thus only if AP and self are capable, try PMF connection
2021 	 * else set PMF as 0. The PMF filtering is already taken care in
2022 	 * get scan results.
2023 	 */
2024 	neg_sec_info = &connect_req->cur_candidate->entry->neg_sec_info;
2025 	rsn_caps = connect_req->req.crypto.rsn_caps;
2026 	if (!(neg_sec_info->rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED &&
2027 	     rsn_caps & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED)) {
2028 		rsn_caps &= ~WLAN_CRYPTO_RSN_CAP_MFP_ENABLED;
2029 		rsn_caps &= ~WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED;
2030 		rsn_caps &= ~WLAN_CRYPTO_RSN_CAP_OCV_SUPPORTED;
2031 	}
2032 
2033 	/* Update the new rsn caps */
2034 	wlan_crypto_set_vdev_param(vdev, WLAN_CRYPTO_PARAM_RSN_CAP,
2035 				   rsn_caps);
2036 
2037 	cm_update_per_peer_key_mgmt_crypto_params(vdev, neg_sec_info);
2038 	cm_update_per_peer_ucastcipher_crypto_params(vdev, neg_sec_info);
2039 }
2040 
2041 QDF_STATUS
2042 cm_resume_connect_after_peer_create(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
2043 {
2044 	struct wlan_cm_vdev_connect_req req;
2045 	struct cm_req *cm_req;
2046 	QDF_STATUS status;
2047 	struct security_info *neg_sec_info;
2048 	uint8_t country_code[REG_ALPHA2_LEN + 1] = {0};
2049 	struct wlan_objmgr_psoc *psoc;
2050 
2051 	psoc = wlan_pdev_get_psoc(wlan_vdev_get_pdev(cm_ctx->vdev));
2052 
2053 	cm_req = cm_get_req_by_cm_id(cm_ctx, *cm_id);
2054 	if (!cm_req)
2055 		return QDF_STATUS_E_FAILURE;
2056 
2057 	/*
2058 	 * As keymgmt and ucast cipher can be multiple.
2059 	 * Choose one keymgmt and one ucastcipherset based on higher security.
2060 	 */
2061 	cm_update_per_peer_crypto_params(cm_ctx->vdev, &cm_req->connect_req);
2062 
2063 	req.vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
2064 	req.cm_id = *cm_id;
2065 	req.force_rsne_override = cm_req->connect_req.req.force_rsne_override;
2066 	req.is_wps_connection = cm_req->connect_req.req.is_wps_connection;
2067 	req.is_osen_connection = cm_req->connect_req.req.is_osen_connection;
2068 	req.assoc_ie = cm_req->connect_req.req.assoc_ie;
2069 	req.scan_ie = cm_req->connect_req.req.scan_ie;
2070 	req.bss = cm_req->connect_req.cur_candidate;
2071 	cm_copy_fils_info(&req, cm_req);
2072 	req.ht_caps = cm_req->connect_req.req.ht_caps;
2073 	req.ht_caps_mask = cm_req->connect_req.req.ht_caps_mask;
2074 	req.vht_caps = cm_req->connect_req.req.vht_caps;
2075 	req.vht_caps_mask = cm_req->connect_req.req.vht_caps_mask;
2076 	req.is_non_assoc_link = cm_req->connect_req.req.is_non_assoc_link;
2077 	cm_update_ml_partner_info(&cm_req->connect_req.req, &req);
2078 
2079 	neg_sec_info = &cm_req->connect_req.cur_candidate->entry->neg_sec_info;
2080 	if (util_scan_entry_is_hidden_ap(req.bss->entry) &&
2081 	    QDF_HAS_PARAM(neg_sec_info->key_mgmt, WLAN_CRYPTO_KEY_MGMT_OWE)) {
2082 		mlme_debug("OWE transition candidate has wildcard ssid");
2083 		req.owe_trans_ssid = cm_req->connect_req.req.ssid;
2084 	}
2085 
2086 	wlan_reg_get_cc_and_src(psoc, country_code);
2087 	mlme_nofl_info(CM_PREFIX_FMT "Connecting to %.*s " QDF_MAC_ADDR_FMT " rssi: %d freq: %d akm 0x%x cipher: uc 0x%x mc 0x%x, wps %d osen %d force RSN %d CC: %c%c",
2088 		       CM_PREFIX_REF(req.vdev_id, req.cm_id),
2089 		       cm_req->connect_req.req.ssid.length,
2090 		       cm_req->connect_req.req.ssid.ssid,
2091 		       QDF_MAC_ADDR_REF(req.bss->entry->bssid.bytes),
2092 		       req.bss->entry->rssi_raw,
2093 		       req.bss->entry->channel.chan_freq,
2094 		       neg_sec_info->key_mgmt, neg_sec_info->ucastcipherset,
2095 		       neg_sec_info->mcastcipherset, req.is_wps_connection,
2096 		       req.is_osen_connection, req.force_rsne_override,
2097 		       country_code[0],
2098 		       country_code[1]);
2099 
2100 	status = mlme_cm_connect_req(cm_ctx->vdev, &req);
2101 	if (QDF_IS_STATUS_ERROR(status)) {
2102 		mlme_err(CM_PREFIX_FMT "connect request failed",
2103 			 CM_PREFIX_REF(req.vdev_id, req.cm_id));
2104 		/* try delete bss peer if req fails */
2105 		mlme_cm_bss_peer_delete_req(cm_ctx->vdev);
2106 		status = cm_send_connect_start_fail(cm_ctx,
2107 						    &cm_req->connect_req,
2108 						    CM_JOIN_FAILED);
2109 	}
2110 
2111 	return status;
2112 }
2113 
2114 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_FEATURE_11BE_MLO_ADV_FEATURE)
2115 static void cm_inform_bcn_probe_handler(struct cnx_mgr *cm_ctx,
2116 					struct scan_cache_entry *bss,
2117 					wlan_cm_id cm_id)
2118 {
2119 	struct element_info *bcn_probe_rsp;
2120 	int32_t rssi;
2121 	qdf_freq_t freq;
2122 
2123 	bcn_probe_rsp = &bss->raw_frame;
2124 	rssi = bss->rssi_raw;
2125 	freq = util_scan_entry_channel_frequency(bss);
2126 
2127 	cm_inform_bcn_probe(cm_ctx, bcn_probe_rsp->ptr, bcn_probe_rsp->len,
2128 			    freq, rssi, cm_id);
2129 }
2130 
2131 static void cm_update_partner_link_scan_db(struct cnx_mgr *cm_ctx,
2132 					   wlan_cm_id cm_id,
2133 					   qdf_list_t *candidate_list,
2134 					   struct scan_cache_entry *cur_bss)
2135 {
2136 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
2137 	struct scan_cache_node *candidate;
2138 	struct scan_cache_entry *bss;
2139 
2140 	qdf_list_peek_front(candidate_list, &cur_node);
2141 
2142 	while (cur_node) {
2143 		qdf_list_peek_next(candidate_list, cur_node, &next_node);
2144 		candidate = qdf_container_of(cur_node, struct scan_cache_node,
2145 					     node);
2146 		bss = candidate->entry;
2147 		/*
2148 		 * If BSS is ML and not current bss and BSS mld mac is same as
2149 		 * cur bss then inform it to scan cache to avoid scan cache
2150 		 * ageing out.
2151 		 */
2152 		if (!qdf_is_macaddr_equal(&bss->bssid, &cur_bss->bssid) &&
2153 		    bss->ml_info.num_links &&
2154 		    cur_bss->ml_info.num_links &&
2155 		    qdf_is_macaddr_equal(&bss->ml_info.mld_mac_addr,
2156 					 &cur_bss->ml_info.mld_mac_addr)) {
2157 			mlme_debug("Inform Partner bssid: " QDF_MAC_ADDR_FMT " to kernel",
2158 					QDF_MAC_ADDR_REF(bss->bssid.bytes));
2159 			cm_inform_bcn_probe_handler(cm_ctx, bss, cm_id);
2160 		}
2161 		cur_node = next_node;
2162 		next_node = NULL;
2163 	}
2164 }
2165 #else
2166 static
2167 inline void cm_update_partner_link_scan_db(struct cnx_mgr *cm_ctx,
2168 					   wlan_cm_id cm_id,
2169 					   qdf_list_t *candidate_list,
2170 					   struct scan_cache_entry *cur_bss)
2171 {
2172 }
2173 #endif
2174 
2175 /**
2176  * cm_update_scan_db_on_connect_success() - update scan db with beacon or
2177  * probe resp
2178  * @cm_ctx: connection manager context
2179  * @resp: connect resp
2180  *
2181  * update scan db, so that kernel and driver do not age out
2182  * the connected AP entry.
2183  *
2184  * Context: Can be called from any context and to be used only if connect
2185  * is successful and SM is in connected state. i.e. SM lock is hold.
2186  *
2187  * Return: void
2188  */
2189 static void
2190 cm_update_scan_db_on_connect_success(struct cnx_mgr *cm_ctx,
2191 				     struct wlan_cm_connect_resp *resp)
2192 {
2193 	struct element_info *bcn_probe_rsp;
2194 	struct cm_req *cm_req;
2195 	int32_t rssi;
2196 	struct scan_cache_node *cur_candidate;
2197 
2198 	if (!cm_is_vdev_connected(cm_ctx->vdev))
2199 		return;
2200 
2201 	cm_req = cm_get_req_by_cm_id(cm_ctx, resp->cm_id);
2202 	if (!cm_req)
2203 		return;
2204 	/* if reassoc get from roam req else from connect req */
2205 	if (resp->is_reassoc)
2206 		cur_candidate = cm_req->roam_req.cur_candidate;
2207 	else
2208 		cur_candidate = cm_req->connect_req.cur_candidate;
2209 
2210 	if (!cur_candidate)
2211 		return;
2212 
2213 	/*
2214 	 * Get beacon or probe resp from connect response, and if not present
2215 	 * use cur candidate to get beacon or probe resp
2216 	 */
2217 	if (resp->connect_ies.bcn_probe_rsp.ptr)
2218 		bcn_probe_rsp = &resp->connect_ies.bcn_probe_rsp;
2219 	else
2220 		bcn_probe_rsp = &cur_candidate->entry->raw_frame;
2221 
2222 	rssi = cur_candidate->entry->rssi_raw;
2223 
2224 	cm_inform_bcn_probe(cm_ctx, bcn_probe_rsp->ptr, bcn_probe_rsp->len,
2225 			    resp->freq, rssi, resp->cm_id);
2226 
2227 	/*
2228 	 * If vdev is an MLO vdev and not reassoc then use partner link info to
2229 	 * inform partner link scan entry to kernel.
2230 	 */
2231 	if (!resp->is_reassoc && wlan_vdev_mlme_is_mlo_vdev(cm_ctx->vdev))
2232 		cm_update_partner_link_scan_db(cm_ctx, resp->cm_id,
2233 				cm_req->connect_req.candidate_list,
2234 				cur_candidate->entry);
2235 }
2236 
2237 #ifdef WLAN_FEATURE_11BE_MLO
2238 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
2239 static inline void
2240 cm_clear_vdev_mlo_cap(struct wlan_objmgr_vdev *vdev)
2241 {
2242 	wlan_vdev_mlme_clear_mlo_vdev(vdev);
2243 }
2244 #else /*WLAN_FEATURE_11BE_MLO_ADV_FEATURE*/
2245 static inline void
2246 cm_clear_vdev_mlo_cap(struct wlan_objmgr_vdev *vdev)
2247 {
2248 	/* If the connect req fails on assoc link, reset
2249 	 * the MLO cap flags. The flags will be updated based
2250 	 * on next connect req
2251 	 */
2252 	if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev))
2253 		ucfg_mlo_mld_clear_mlo_cap(vdev);
2254 }
2255 #endif /*WLAN_FEATURE_11BE_MLO_ADV_FEATURE*/
2256 #else /*WLAN_FEATURE_11BE_MLO*/
2257 static inline void
2258 cm_clear_vdev_mlo_cap(struct wlan_objmgr_vdev *vdev)
2259 { }
2260 #endif /*WLAN_FEATURE_11BE_MLO*/
2261 
2262 /**
2263  * cm_is_connect_id_reassoc_in_non_connected()
2264  * @cm_ctx: connection manager context
2265  * @cm_id: cm id
2266  *
2267  * If connect req is a reassoc req and received in not connected state
2268  *
2269  * Return: bool
2270  */
2271 static bool cm_is_connect_id_reassoc_in_non_connected(struct cnx_mgr *cm_ctx,
2272 						      wlan_cm_id cm_id)
2273 {
2274 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
2275 	struct cm_req *cm_req;
2276 	uint32_t prefix = CM_ID_GET_PREFIX(cm_id);
2277 	bool is_reassoc = false;
2278 
2279 	if (prefix != CONNECT_REQ_PREFIX)
2280 		return is_reassoc;
2281 
2282 	cm_req_lock_acquire(cm_ctx);
2283 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
2284 	while (cur_node) {
2285 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
2286 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
2287 
2288 		if (cm_req->cm_id == cm_id) {
2289 			if (cm_req->connect_req.req.reassoc_in_non_connected)
2290 				is_reassoc = true;
2291 			cm_req_lock_release(cm_ctx);
2292 			return is_reassoc;
2293 		}
2294 
2295 		cur_node = next_node;
2296 		next_node = NULL;
2297 	}
2298 	cm_req_lock_release(cm_ctx);
2299 
2300 	return is_reassoc;
2301 }
2302 
2303 QDF_STATUS cm_notify_connect_complete(struct cnx_mgr *cm_ctx,
2304 				      struct wlan_cm_connect_resp *resp)
2305 {
2306 	enum wlan_cm_sm_state sm_state;
2307 
2308 	sm_state = cm_get_state(cm_ctx);
2309 
2310 	mlme_cm_connect_complete_ind(cm_ctx->vdev, resp);
2311 	mlo_sta_link_connect_notify(cm_ctx->vdev, resp);
2312 	/*
2313 	 * If connect req was a reassoc req and was received in not connected
2314 	 * state send disconnect instead of connect resp to kernel to cleanup
2315 	 * kernel flags
2316 	 */
2317 	if (QDF_IS_STATUS_ERROR(resp->connect_status) &&
2318 	    sm_state == WLAN_CM_S_INIT &&
2319 	    cm_is_connect_id_reassoc_in_non_connected(cm_ctx, resp->cm_id)) {
2320 		resp->send_disconnect = true;
2321 		mlme_debug(CM_PREFIX_FMT "Set send disconnect to true to indicate disconnect instead of connect resp",
2322 			   CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
2323 					 resp->cm_id));
2324 	}
2325 	mlme_cm_osif_connect_complete(cm_ctx->vdev, resp);
2326 	cm_if_mgr_inform_connect_complete(cm_ctx->vdev,
2327 					  resp->connect_status);
2328 	cm_inform_dlm_connect_complete(cm_ctx->vdev, resp);
2329 
2330 	if (QDF_IS_STATUS_ERROR(resp->connect_status) &&
2331 	    sm_state == WLAN_CM_S_INIT)
2332 		cm_clear_vdev_mlo_cap(cm_ctx->vdev);
2333 
2334 	return QDF_STATUS_SUCCESS;
2335 }
2336 
2337 QDF_STATUS cm_connect_complete(struct cnx_mgr *cm_ctx,
2338 			       struct wlan_cm_connect_resp *resp)
2339 {
2340 	enum wlan_cm_sm_state sm_state;
2341 	struct bss_info bss_info;
2342 	struct mlme_info mlme_info;
2343 	bool send_ind = true;
2344 
2345 	/*
2346 	 * If the entry is not present in the list, it must have been cleared
2347 	 * already.
2348 	 */
2349 	if (!cm_get_req_by_cm_id(cm_ctx, resp->cm_id))
2350 		return QDF_STATUS_SUCCESS;
2351 
2352 	sm_state = cm_get_state(cm_ctx);
2353 	cm_set_fils_connection(cm_ctx, resp);
2354 	if (QDF_IS_STATUS_SUCCESS(resp->connect_status) &&
2355 	    sm_state == WLAN_CM_S_CONNECTED) {
2356 		cm_update_scan_db_on_connect_success(cm_ctx, resp);
2357 		/* set WEP and FILS key on success */
2358 		cm_set_fils_wep_key(cm_ctx, resp);
2359 	}
2360 
2361 	/* In case of reassoc failure no need to inform osif/legacy/ifmanager */
2362 	if (resp->is_reassoc && QDF_IS_STATUS_ERROR(resp->connect_status))
2363 		send_ind = false;
2364 
2365 	if (send_ind)
2366 		cm_notify_connect_complete(cm_ctx, resp);
2367 
2368 	/* Update scan entry in case connect is success or fails with bssid */
2369 	if (!qdf_is_macaddr_zero(&resp->bssid)) {
2370 		if (QDF_IS_STATUS_SUCCESS(resp->connect_status))
2371 			mlme_info.assoc_state  = SCAN_ENTRY_CON_STATE_ASSOC;
2372 		else
2373 			mlme_info.assoc_state = SCAN_ENTRY_CON_STATE_NONE;
2374 		qdf_copy_macaddr(&bss_info.bssid, &resp->bssid);
2375 		bss_info.freq = resp->freq;
2376 		bss_info.ssid.length = resp->ssid.length;
2377 		qdf_mem_copy(&bss_info.ssid.ssid, resp->ssid.ssid,
2378 			     bss_info.ssid.length);
2379 		wlan_scan_update_mlme_by_bssinfo(
2380 					wlan_vdev_get_pdev(cm_ctx->vdev),
2381 					&bss_info, &mlme_info);
2382 	}
2383 
2384 	mlme_debug(CM_PREFIX_FMT,
2385 		   CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
2386 				 resp->cm_id));
2387 	cm_remove_cmd(cm_ctx, &resp->cm_id);
2388 
2389 	return QDF_STATUS_SUCCESS;
2390 }
2391 
2392 QDF_STATUS cm_add_connect_req_to_list(struct cnx_mgr *cm_ctx,
2393 				      struct cm_connect_req *req)
2394 {
2395 	QDF_STATUS status;
2396 	struct cm_req *cm_req;
2397 
2398 	cm_req = qdf_container_of(req, struct cm_req, connect_req);
2399 	req->cm_id = cm_get_cm_id(cm_ctx, req->req.source);
2400 	cm_req->cm_id = req->cm_id;
2401 	status = cm_add_req_to_list_and_indicate_osif(cm_ctx, cm_req,
2402 						      req->req.source);
2403 
2404 	return status;
2405 }
2406 
2407 QDF_STATUS cm_connect_rsp(struct wlan_objmgr_vdev *vdev,
2408 			  struct wlan_cm_connect_resp *resp)
2409 {
2410 	struct cnx_mgr *cm_ctx;
2411 	QDF_STATUS qdf_status;
2412 	wlan_cm_id cm_id;
2413 	uint32_t prefix;
2414 
2415 	cm_ctx = cm_get_cm_ctx(vdev);
2416 	if (!cm_ctx)
2417 		return QDF_STATUS_E_INVAL;
2418 
2419 	cm_id = cm_ctx->active_cm_id;
2420 	prefix = CM_ID_GET_PREFIX(cm_id);
2421 
2422 	if (prefix != CONNECT_REQ_PREFIX || cm_id != resp->cm_id) {
2423 		mlme_err(CM_PREFIX_FMT " Active cm_id 0x%x is different",
2424 			 CM_PREFIX_REF(wlan_vdev_get_id(vdev), resp->cm_id),
2425 			 cm_id);
2426 		qdf_status = QDF_STATUS_E_FAILURE;
2427 		goto post_err;
2428 	}
2429 
2430 	if (QDF_IS_STATUS_SUCCESS(resp->connect_status)) {
2431 		/*
2432 		 * On successful connection to sae single pmk AP,
2433 		 * clear all the single pmk AP.
2434 		 */
2435 		if (cm_is_cm_id_current_candidate_single_pmk(cm_ctx, cm_id))
2436 			wlan_crypto_selective_clear_sae_single_pmk_entries(vdev,
2437 								&resp->bssid);
2438 		qdf_status =
2439 			cm_sm_deliver_event(vdev,
2440 					    WLAN_CM_SM_EV_CONNECT_SUCCESS,
2441 					    sizeof(*resp), resp);
2442 		if (QDF_IS_STATUS_SUCCESS(qdf_status))
2443 			return qdf_status;
2444 		/*
2445 		 * failure mean that the new connect/disconnect is received so
2446 		 * cleanup.
2447 		 */
2448 		goto post_err;
2449 	}
2450 
2451 	/*
2452 	 * Delete the PMKID of the BSSID for which the assoc reject is
2453 	 * received from the AP due to invalid PMKID reason.
2454 	 * This will avoid the driver trying to connect to same AP with
2455 	 * the same stale PMKID. when connection is tried again with this AP.
2456 	 */
2457 	if (resp->status_code == STATUS_INVALID_PMKID)
2458 		cm_delete_pmksa_for_bssid(cm_ctx, &resp->bssid);
2459 
2460 	/* In case of failure try with next candidate */
2461 	qdf_status =
2462 		cm_sm_deliver_event(vdev,
2463 				    WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE,
2464 				    sizeof(*resp), resp);
2465 
2466 	if (QDF_IS_STATUS_SUCCESS(qdf_status))
2467 		return qdf_status;
2468 	/*
2469 	 * If connection fails with Single PMK bssid, clear this pmk
2470 	 * entry in case of post failure.
2471 	 */
2472 	if (cm_is_cm_id_current_candidate_single_pmk(cm_ctx, cm_id))
2473 		cm_delete_pmksa_for_single_pmk_bssid(cm_ctx, &resp->bssid);
2474 post_err:
2475 	/*
2476 	 * If there is a event posting error it means the SM state is not in
2477 	 * JOIN ACTIVE (some new cmd has changed the state of SM), so just
2478 	 * complete the connect command.
2479 	 */
2480 	cm_connect_complete(cm_ctx, resp);
2481 
2482 	return qdf_status;
2483 }
2484 
2485 QDF_STATUS cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev,
2486 				  QDF_STATUS status,
2487 				  struct qdf_mac_addr *peer_mac)
2488 {
2489 	struct cnx_mgr *cm_ctx;
2490 	QDF_STATUS qdf_status;
2491 	wlan_cm_id cm_id;
2492 	uint32_t prefix;
2493 	struct wlan_cm_connect_resp *resp;
2494 
2495 	cm_ctx = cm_get_cm_ctx(vdev);
2496 	if (!cm_ctx)
2497 		return QDF_STATUS_E_INVAL;
2498 
2499 	cm_id = cm_ctx->active_cm_id;
2500 	prefix = CM_ID_GET_PREFIX(cm_id);
2501 
2502 	if (prefix != CONNECT_REQ_PREFIX) {
2503 		mlme_err(CM_PREFIX_FMT "active req is not connect req",
2504 			 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), cm_id));
2505 		mlme_cm_bss_peer_delete_req(vdev);
2506 		return QDF_STATUS_E_INVAL;
2507 	}
2508 
2509 	if (QDF_IS_STATUS_SUCCESS(status)) {
2510 		qdf_status =
2511 			cm_sm_deliver_event(vdev,
2512 					  WLAN_CM_SM_EV_BSS_CREATE_PEER_SUCCESS,
2513 					  sizeof(wlan_cm_id), &cm_id);
2514 		if (QDF_IS_STATUS_SUCCESS(qdf_status))
2515 			return qdf_status;
2516 
2517 		mlme_cm_bss_peer_delete_req(vdev);
2518 		goto post_err;
2519 	}
2520 
2521 	/* In case of failure try with next candidate */
2522 	resp = qdf_mem_malloc(sizeof(*resp));
2523 	if (!resp) {
2524 		qdf_status = QDF_STATUS_E_NOMEM;
2525 		goto post_err;
2526 	}
2527 
2528 	cm_fill_failure_resp_from_cm_id(cm_ctx, resp, cm_id,
2529 					CM_PEER_CREATE_FAILED);
2530 	qdf_status =
2531 		cm_sm_deliver_event(vdev,
2532 				    WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE,
2533 				    sizeof(*resp), resp);
2534 	qdf_mem_free(resp);
2535 	if (QDF_IS_STATUS_SUCCESS(qdf_status))
2536 		return qdf_status;
2537 
2538 post_err:
2539 	/*
2540 	 * If there is a event posting error it means the SM state is not in
2541 	 * JOIN ACTIVE (some new cmd has changed the state of SM), so just
2542 	 * complete the connect command.
2543 	 */
2544 	cm_connect_handle_event_post_fail(cm_ctx, cm_id);
2545 	return qdf_status;
2546 }
2547 
2548 static void
2549 cm_copy_crypto_prarams(struct wlan_cm_connect_crypto_info *dst_params,
2550 		       struct wlan_crypto_params  *src_params)
2551 {
2552 	/*
2553 	 * As akm suites and ucast ciphers can be multiple. So, do ORing to
2554 	 * keep it along with newly added one's (newly added one will anyway
2555 	 * be part of it)
2556 	 */
2557 	dst_params->akm_suites |= src_params->key_mgmt;
2558 	dst_params->auth_type = src_params->authmodeset;
2559 	dst_params->ciphers_pairwise |= src_params->ucastcipherset;
2560 	dst_params->group_cipher = src_params->mcastcipherset;
2561 	dst_params->mgmt_ciphers = src_params->mgmtcipherset;
2562 	dst_params->rsn_caps = src_params->rsn_caps;
2563 }
2564 
2565 static void
2566 cm_set_crypto_params_from_ie(struct wlan_cm_connect_req *req)
2567 {
2568 	struct wlan_crypto_params crypto_params;
2569 	QDF_STATUS status;
2570 	uint8_t wsc_oui[OUI_LENGTH];
2571 	uint8_t osen_oui[OUI_LENGTH];
2572 	uint32_t oui_cpu;
2573 
2574 	if (!req->assoc_ie.ptr)
2575 		return;
2576 
2577 	oui_cpu = qdf_be32_to_cpu(WSC_OUI);
2578 	qdf_mem_copy(wsc_oui, &oui_cpu, OUI_LENGTH);
2579 	oui_cpu = qdf_be32_to_cpu(OSEN_OUI);
2580 	qdf_mem_copy(osen_oui, &oui_cpu, OUI_LENGTH);
2581 	if (wlan_get_vendor_ie_ptr_from_oui(osen_oui, OUI_LENGTH,
2582 					    req->assoc_ie.ptr,
2583 					    req->assoc_ie.len))
2584 		req->is_osen_connection = true;
2585 
2586 	if (wlan_get_vendor_ie_ptr_from_oui(wsc_oui, OUI_LENGTH,
2587 					    req->assoc_ie.ptr,
2588 					    req->assoc_ie.len))
2589 		req->is_wps_connection = true;
2590 
2591 	status = wlan_get_crypto_params_from_rsn_ie(&crypto_params,
2592 						    req->assoc_ie.ptr,
2593 						    req->assoc_ie.len);
2594 	if (QDF_IS_STATUS_SUCCESS(status)) {
2595 		cm_copy_crypto_prarams(&req->crypto, &crypto_params);
2596 		return;
2597 	}
2598 
2599 	status = wlan_get_crypto_params_from_wpa_ie(&crypto_params,
2600 						    req->assoc_ie.ptr,
2601 						    req->assoc_ie.len);
2602 	if (QDF_IS_STATUS_SUCCESS(status)) {
2603 		cm_copy_crypto_prarams(&req->crypto, &crypto_params);
2604 		return;
2605 	}
2606 
2607 	status = wlan_get_crypto_params_from_wapi_ie(&crypto_params,
2608 						     req->assoc_ie.ptr,
2609 						     req->assoc_ie.len);
2610 	if (QDF_IS_STATUS_SUCCESS(status))
2611 		cm_copy_crypto_prarams(&req->crypto, &crypto_params);
2612 }
2613 
2614 static QDF_STATUS
2615 cm_allocate_and_copy_ies_and_keys(struct wlan_cm_connect_req *target,
2616 				  struct wlan_cm_connect_req *source)
2617 {
2618 	/* Reset the copied pointers of target */
2619 	target->assoc_ie.ptr = NULL;
2620 	target->crypto.wep_keys.key = NULL;
2621 	target->crypto.wep_keys.seq = NULL;
2622 	target->scan_ie.ptr = NULL;
2623 
2624 	if (source->scan_ie.ptr) {
2625 		target->scan_ie.ptr = qdf_mem_malloc(source->scan_ie.len);
2626 		if (!target->scan_ie.ptr)
2627 			target->scan_ie.len = 0;
2628 		else
2629 			qdf_mem_copy(target->scan_ie.ptr,
2630 				     source->scan_ie.ptr, source->scan_ie.len);
2631 	}
2632 
2633 	if (source->assoc_ie.ptr) {
2634 		target->assoc_ie.ptr = qdf_mem_malloc(source->assoc_ie.len);
2635 		if (!target->assoc_ie.ptr)
2636 			return QDF_STATUS_E_NOMEM;
2637 
2638 		qdf_mem_copy(target->assoc_ie.ptr, source->assoc_ie.ptr,
2639 			     source->assoc_ie.len);
2640 	}
2641 
2642 	if (source->crypto.wep_keys.key) {
2643 		target->crypto.wep_keys.key =
2644 			qdf_mem_malloc(source->crypto.wep_keys.key_len);
2645 		if (!target->crypto.wep_keys.key)
2646 			return QDF_STATUS_E_NOMEM;
2647 
2648 		qdf_mem_copy(target->crypto.wep_keys.key,
2649 			     source->crypto.wep_keys.key,
2650 			     source->crypto.wep_keys.key_len);
2651 	}
2652 
2653 	if (source->crypto.wep_keys.seq) {
2654 		target->crypto.wep_keys.seq =
2655 			qdf_mem_malloc(source->crypto.wep_keys.seq_len);
2656 		if (!target->crypto.wep_keys.seq)
2657 			return QDF_STATUS_E_NOMEM;
2658 
2659 		qdf_mem_copy(target->crypto.wep_keys.seq,
2660 			     source->crypto.wep_keys.seq,
2661 			     source->crypto.wep_keys.seq_len);
2662 	}
2663 
2664 	return QDF_STATUS_SUCCESS;
2665 }
2666 
2667 QDF_STATUS cm_connect_start_req(struct wlan_objmgr_vdev *vdev,
2668 				struct wlan_cm_connect_req *req)
2669 {
2670 	struct cnx_mgr *cm_ctx;
2671 	struct cm_req *cm_req;
2672 	struct cm_connect_req *connect_req;
2673 	QDF_STATUS status;
2674 
2675 	cm_ctx = cm_get_cm_ctx(vdev);
2676 	if (!cm_ctx)
2677 		return QDF_STATUS_E_INVAL;
2678 
2679 	cm_vdev_scan_cancel(wlan_vdev_get_pdev(cm_ctx->vdev), cm_ctx->vdev);
2680 
2681 	/*
2682 	 * This would be freed as part of removal from cm req list if adding
2683 	 * to list is success after posting WLAN_CM_SM_EV_CONNECT_REQ.
2684 	 */
2685 	cm_req = qdf_mem_malloc(sizeof(*cm_req));
2686 	if (!cm_req)
2687 		return QDF_STATUS_E_NOMEM;
2688 
2689 	if (wlan_vdev_mlme_is_mlo_vdev(vdev) &&
2690 	    wlan_vdev_mlme_is_mlo_link_vdev(vdev))
2691 		req->is_non_assoc_link = 1;
2692 
2693 	connect_req = &cm_req->connect_req;
2694 	connect_req->req = *req;
2695 
2696 	status = cm_allocate_and_copy_ies_and_keys(&connect_req->req, req);
2697 	if (QDF_IS_STATUS_ERROR(status))
2698 		goto err;
2699 
2700 	cm_set_crypto_params_from_ie(&connect_req->req);
2701 
2702 	if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev))
2703 		cm_teardown_tdls(vdev);
2704 
2705 	status = cm_sm_deliver_event(vdev, WLAN_CM_SM_EV_CONNECT_REQ,
2706 				     sizeof(*connect_req), connect_req);
2707 
2708 err:
2709 	/* free the req if connect is not handled */
2710 	if (QDF_IS_STATUS_ERROR(status)) {
2711 		cm_free_connect_req_mem(connect_req);
2712 		qdf_mem_free(cm_req);
2713 	}
2714 
2715 	return status;
2716 }
2717