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