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