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