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