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