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