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