xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlme/connection_mgr/core/src/wlan_cm_util.c (revision a1b2495738bed0b17dc751face96d3c2242e8c49)
1 /*
2  * Copyright (c) 2012-2015, 2020-2021, The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /**
19  * DOC: Implements general util apis of connection manager
20  */
21 
22 #include "wlan_cm_main_api.h"
23 #include "wlan_scan_api.h"
24 #include "wlan_cm_public_struct.h"
25 #include "wlan_serialization_api.h"
26 #include "wlan_cm_bss_score_param.h"
27 #ifdef WLAN_POLICY_MGR_ENABLE
28 #include <wlan_policy_mgr_api.h>
29 #endif
30 #include "wlan_cm_roam.h"
31 #include <qdf_platform.h>
32 #include <wlan_mlo_mgr_link_switch.h>
33 
34 static uint32_t cm_get_prefix_for_cm_id(enum wlan_cm_source source) {
35 	switch (source) {
36 	case CM_OSIF_CONNECT:
37 	case CM_OSIF_CFG_CONNECT:
38 	case CM_MLO_LINK_VDEV_CONNECT:
39 	case CM_MLO_LINK_SWITCH_CONNECT:
40 		return CONNECT_REQ_PREFIX;
41 	case CM_ROAMING_HOST:
42 	case CM_ROAMING_FW:
43 	case CM_ROAMING_NUD_FAILURE:
44 	case CM_ROAMING_LINK_REMOVAL:
45 	case CM_ROAMING_USER:
46 		return ROAM_REQ_PREFIX;
47 	default:
48 		return DISCONNECT_REQ_PREFIX;
49 	}
50 }
51 
52 wlan_cm_id cm_get_cm_id(struct cnx_mgr *cm_ctx, enum wlan_cm_source source)
53 {
54 	wlan_cm_id cm_id;
55 	uint32_t prefix;
56 	uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
57 
58 	prefix = cm_get_prefix_for_cm_id(source);
59 
60 	cm_id = qdf_atomic_inc_return(&cm_ctx->global_cmd_id);
61 	cm_id = (cm_id & CM_ID_MASK);
62 	cm_id = CM_ID_SET_VDEV_ID(cm_id, vdev_id);
63 	cm_id = (cm_id | prefix);
64 	if (source == CM_MLO_LINK_SWITCH_DISCONNECT ||
65 	    source == CM_MLO_LINK_SWITCH_CONNECT)
66 		cm_id |= CM_ID_LSWITCH_BIT;
67 
68 	return cm_id;
69 }
70 
71 struct cnx_mgr *cm_get_cm_ctx_fl(struct wlan_objmgr_vdev *vdev,
72 				 const char *func, uint32_t line)
73 {
74 	struct vdev_mlme_obj *vdev_mlme;
75 	struct cnx_mgr *cm_ctx = NULL;
76 
77 	if (!vdev) {
78 		mlme_rl_nofl_err("%s:%u: vdev is NULL", func, line);
79 		return NULL;
80 	}
81 
82 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
83 	if (vdev_mlme)
84 		cm_ctx = vdev_mlme->cnx_mgr_ctx;
85 
86 	if (!cm_ctx)
87 		mlme_nofl_err("%s:%u: vdev %d cm_ctx is NULL", func, line,
88 			      wlan_vdev_get_id(vdev));
89 
90 	return cm_ctx;
91 }
92 
93 cm_ext_t *cm_get_ext_hdl_fl(struct wlan_objmgr_vdev *vdev,
94 			    const char *func, uint32_t line)
95 {
96 	struct cnx_mgr *cm_ctx;
97 	cm_ext_t *ext_ctx = NULL;
98 
99 	cm_ctx = cm_get_cm_ctx_fl(vdev, func, line);
100 	if (cm_ctx)
101 		ext_ctx = cm_ctx->ext_cm_ptr;
102 
103 	if (!ext_ctx)
104 		mlme_nofl_err("%s:%u: vdev %d cm ext ctx is NULL", func, line,
105 			      wlan_vdev_get_id(vdev));
106 	return ext_ctx;
107 }
108 
109 void cm_reset_active_cm_id(struct wlan_objmgr_vdev *vdev, wlan_cm_id cm_id)
110 {
111 	struct cnx_mgr *cm_ctx;
112 
113 	cm_ctx = cm_get_cm_ctx(vdev);
114 	if (!cm_ctx)
115 		return;
116 
117 	/* Reset active cm id if cm id match */
118 	if (cm_ctx->active_cm_id == cm_id)
119 		cm_ctx->active_cm_id = CM_ID_INVALID;
120 }
121 
122 
123 #ifdef WLAN_CM_USE_SPINLOCK
124 /**
125  * cm_req_lock_acquire - acquire CM SM mutex/spinlock
126  * @cm_ctx:  connection manager ctx
127  *
128  * acquire CM SM mutex/spinlock
129  *
130  * return: void
131  */
132 inline void cm_req_lock_acquire(struct cnx_mgr *cm_ctx)
133 {
134 	qdf_spinlock_acquire(&cm_ctx->cm_req_lock);
135 }
136 
137 /**
138  * cm_req_lock_release - release CM SM mutex/spinlock
139  * @cm_ctx:  connection manager ctx
140  *
141  * release CM SM mutex/spinlock
142  *
143  * return: void
144  */
145 inline void cm_req_lock_release(struct cnx_mgr *cm_ctx)
146 {
147 	qdf_spinlock_release(&cm_ctx->cm_req_lock);
148 }
149 
150 QDF_STATUS cm_activate_cmd_req_flush_cb(struct scheduler_msg *msg)
151 {
152 	struct wlan_serialization_command *cmd = msg->bodyptr;
153 
154 	if (!cmd || !cmd->vdev) {
155 		mlme_err("Null input cmd:%pK", cmd);
156 		return QDF_STATUS_E_INVAL;
157 	}
158 
159 	wlan_objmgr_vdev_release_ref(cmd->vdev, WLAN_MLME_CM_ID);
160 	return QDF_STATUS_SUCCESS;
161 }
162 
163 #else
164 inline void cm_req_lock_acquire(struct cnx_mgr *cm_ctx)
165 {
166 	qdf_mutex_acquire(&cm_ctx->cm_req_lock);
167 }
168 
169 inline void cm_req_lock_release(struct cnx_mgr *cm_ctx)
170 {
171 	qdf_mutex_release(&cm_ctx->cm_req_lock);
172 }
173 #endif /* WLAN_CM_USE_SPINLOCK */
174 
175 #ifdef CRYPTO_SET_KEY_CONVERGED
176 QDF_STATUS cm_set_key(struct cnx_mgr *cm_ctx, bool unicast,
177 		      uint8_t key_idx, struct qdf_mac_addr *bssid)
178 {
179 	enum wlan_crypto_cipher_type cipher;
180 	struct wlan_crypto_key *crypto_key;
181 	uint8_t wep_key_idx = 0;
182 
183 	cipher = wlan_crypto_get_cipher(cm_ctx->vdev, unicast, key_idx);
184 	if (IS_WEP_CIPHER(cipher)) {
185 		wep_key_idx = wlan_crypto_get_default_key_idx(cm_ctx->vdev,
186 							      false);
187 		crypto_key = wlan_crypto_get_key(cm_ctx->vdev, wep_key_idx);
188 		qdf_mem_copy(crypto_key->macaddr, bssid->bytes,
189 			     QDF_MAC_ADDR_SIZE);
190 	} else {
191 		crypto_key = wlan_crypto_get_key(cm_ctx->vdev, key_idx);
192 	}
193 
194 	return wlan_crypto_set_key_req(cm_ctx->vdev, crypto_key, (unicast ?
195 				       WLAN_CRYPTO_KEY_TYPE_UNICAST :
196 				       WLAN_CRYPTO_KEY_TYPE_GROUP));
197 }
198 #endif
199 
200 #ifdef CONN_MGR_ADV_FEATURE
201 void cm_store_wep_key(struct cnx_mgr *cm_ctx,
202 		      struct wlan_cm_connect_crypto_info *crypto,
203 		      wlan_cm_id cm_id)
204 {
205 	struct wlan_crypto_key *crypto_key = NULL;
206 	QDF_STATUS status;
207 	enum wlan_crypto_cipher_type cipher_type;
208 	struct wlan_cm_wep_key_params *wep_keys;
209 
210 	if (!(crypto->ciphers_pairwise & (1 << WLAN_CRYPTO_CIPHER_WEP_40 |
211 					  1 << WLAN_CRYPTO_CIPHER_WEP_104)))
212 		return;
213 
214 	if (crypto->ciphers_pairwise & 1 << WLAN_CRYPTO_CIPHER_WEP_40)
215 		cipher_type = WLAN_CRYPTO_CIPHER_WEP_40;
216 	else
217 		cipher_type = WLAN_CRYPTO_CIPHER_WEP_104;
218 
219 	wep_keys = &crypto->wep_keys;
220 	status = wlan_crypto_validate_key_params(cipher_type,
221 						 wep_keys->key_idx,
222 						 wep_keys->key_len,
223 						 wep_keys->seq_len);
224 	if (QDF_IS_STATUS_ERROR(status)) {
225 		mlme_err(CM_PREFIX_FMT "Invalid key params",
226 			 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), cm_id));
227 		return;
228 	}
229 
230 	crypto_key = wlan_crypto_get_key(cm_ctx->vdev, wep_keys->key_idx);
231 	if (!crypto_key) {
232 		crypto_key = qdf_mem_malloc(sizeof(*crypto_key));
233 		if (!crypto_key)
234 			return;
235 
236 		status = wlan_crypto_save_key(cm_ctx->vdev, wep_keys->key_idx,
237 					      crypto_key);
238 		if (QDF_IS_STATUS_ERROR(status)) {
239 			mlme_err(CM_PREFIX_FMT "Failed to save key",
240 				 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
241 					       cm_id));
242 			qdf_mem_free(crypto_key);
243 			return;
244 		}
245 	}
246 	qdf_mem_zero(crypto_key, sizeof(*crypto_key));
247 	crypto_key->cipher_type = cipher_type;
248 	crypto_key->keylen = wep_keys->key_len;
249 	crypto_key->keyix = wep_keys->key_idx;
250 	qdf_mem_copy(&crypto_key->keyval[0], wep_keys->key, wep_keys->key_len);
251 	qdf_mem_copy(&crypto_key->keyrsc[0], wep_keys->seq, wep_keys->seq_len);
252 	mlme_debug(CM_PREFIX_FMT "cipher_type %d key_len %d, seq_len %d",
253 		   CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), cm_id),
254 		   crypto_key->cipher_type, wep_keys->key_len,
255 		   wep_keys->seq_len);
256 }
257 
258 void cm_trigger_panic_on_cmd_timeout(struct wlan_objmgr_vdev *vdev)
259 {
260 	struct wlan_objmgr_psoc *psoc;
261 
262 	psoc = wlan_vdev_get_psoc(vdev);
263 	if (!psoc)
264 		return;
265 
266 	if (qdf_is_recovering() || qdf_is_fw_down())
267 		return;
268 
269 	qdf_trigger_self_recovery(psoc, QDF_ACTIVE_LIST_TIMEOUT);
270 }
271 
272 #else
273 void cm_trigger_panic_on_cmd_timeout(struct wlan_objmgr_vdev *vdev)
274 {
275 	struct vdev_mlme_obj *vdev_mlme = NULL;
276 	struct wlan_sm *vdev_sm = NULL;
277 
278 	vdev_mlme = wlan_objmgr_vdev_get_comp_private_obj(
279 			vdev,
280 			WLAN_UMAC_COMP_MLME);
281 	if (!vdev_mlme) {
282 		mlme_err("VDEV MLME is null");
283 		goto error;
284 	}
285 
286 	vdev_sm = vdev_mlme->sm_hdl;
287 	if (!vdev_sm) {
288 		mlme_err("VDEV SM is null");
289 		goto error;
290 	}
291 
292 	wlan_sm_print_history(vdev_sm);
293 	cm_sm_history_print(vdev);
294 error:
295 	QDF_ASSERT(0);
296 }
297 #endif
298 
299 #ifdef WLAN_FEATURE_FILS_SK
300 void cm_store_fils_key(struct cnx_mgr *cm_ctx, bool unicast,
301 		       uint8_t key_id, uint16_t key_length,
302 		       uint8_t *key, struct qdf_mac_addr *bssid,
303 		       wlan_cm_id cm_id)
304 {
305 	struct wlan_crypto_key *crypto_key = NULL;
306 	QDF_STATUS status;
307 	uint8_t i;
308 	int32_t cipher;
309 	enum wlan_crypto_cipher_type cipher_type = WLAN_CRYPTO_CIPHER_NONE;
310 
311 	if (unicast)
312 		cipher = wlan_crypto_get_param(cm_ctx->vdev,
313 					       WLAN_CRYPTO_PARAM_UCAST_CIPHER);
314 	else
315 		cipher = wlan_crypto_get_param(cm_ctx->vdev,
316 					       WLAN_CRYPTO_PARAM_MCAST_CIPHER);
317 
318 	for (i = 0; i <= WLAN_CRYPTO_CIPHER_MAX; i++) {
319 		if (QDF_HAS_PARAM(cipher, i)) {
320 			cipher_type = i;
321 			break;
322 		}
323 	}
324 	crypto_key = wlan_crypto_get_key(cm_ctx->vdev, key_id);
325 	if (!crypto_key) {
326 		crypto_key = qdf_mem_malloc(sizeof(*crypto_key));
327 		if (!crypto_key)
328 			return;
329 		status = wlan_crypto_save_key(cm_ctx->vdev, key_id, crypto_key);
330 		if (QDF_IS_STATUS_ERROR(status)) {
331 			mlme_err(CM_PREFIX_FMT "Failed to save key",
332 				 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
333 					       cm_id));
334 			qdf_mem_free(crypto_key);
335 			return;
336 		}
337 	}
338 	qdf_mem_zero(crypto_key, sizeof(*crypto_key));
339 	crypto_key->cipher_type = cipher_type;
340 	crypto_key->keylen = key_length;
341 	crypto_key->keyix = key_id;
342 	qdf_mem_copy(&crypto_key->keyval[0], key, key_length);
343 	qdf_mem_copy(crypto_key->macaddr, bssid->bytes, QDF_MAC_ADDR_SIZE);
344 	mlme_debug(CM_PREFIX_FMT "cipher_type %d key_len %d, key_id %d mac:" QDF_MAC_ADDR_FMT,
345 		   CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), cm_id),
346 		   crypto_key->cipher_type, crypto_key->keylen,
347 		   crypto_key->keyix, QDF_MAC_ADDR_REF(crypto_key->macaddr));
348 }
349 static void cm_set_fils_connection_from_req(struct wlan_cm_connect_req *req,
350 					    struct wlan_cm_connect_resp *resp)
351 {
352 	resp->is_fils_connection = req->fils_info.is_fils_connection;
353 }
354 #else
355 static inline
356 void cm_set_fils_connection_from_req(struct wlan_cm_connect_req *req,
357 				     struct wlan_cm_connect_resp *resp)
358 {}
359 #endif
360 
361 bool cm_check_cmid_match_list_head(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
362 {
363 	qdf_list_node_t *cur_node = NULL;
364 	struct cm_req *cm_req;
365 	bool match = false;
366 	wlan_cm_id head_cm_id = 0;
367 
368 	if (!cm_id)
369 		return false;
370 
371 	cm_req_lock_acquire(cm_ctx);
372 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
373 	if (!cur_node)
374 		goto exit;
375 
376 	cm_req = qdf_container_of(cur_node, struct cm_req, node);
377 	head_cm_id = cm_req->cm_id;
378 	if (head_cm_id == *cm_id)
379 		match = true;
380 
381 exit:
382 	cm_req_lock_release(cm_ctx);
383 	if (!match)
384 		mlme_info("head_cm_id 0x%x didn't match the given cm_id 0x%x",
385 			  head_cm_id, *cm_id);
386 
387 	return match;
388 }
389 
390 bool cm_check_scanid_match_list_head(struct cnx_mgr *cm_ctx,
391 				     wlan_scan_id *scan_id)
392 {
393 	qdf_list_node_t *cur_node = NULL;
394 	struct cm_req *cm_req;
395 	bool match = false;
396 	wlan_cm_id head_scan_id = 0;
397 	uint32_t prefix = 0;
398 
399 	if (!scan_id)
400 		return false;
401 
402 	cm_req_lock_acquire(cm_ctx);
403 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
404 	if (!cur_node)
405 		goto exit;
406 
407 	cm_req = qdf_container_of(cur_node, struct cm_req, node);
408 	prefix = CM_ID_GET_PREFIX(cm_req->cm_id);
409 	/* Check only if head is connect req */
410 	if (prefix != CONNECT_REQ_PREFIX)
411 		goto exit;
412 	head_scan_id = cm_req->connect_req.scan_id;
413 	if (head_scan_id == *scan_id)
414 		match = true;
415 
416 exit:
417 	cm_req_lock_release(cm_ctx);
418 	if (!match)
419 		mlme_info("head_scan_id 0x%x didn't match the given scan_id 0x%x prefix 0x%x",
420 			  head_scan_id, *scan_id, prefix);
421 
422 	return match;
423 }
424 
425 struct cm_req *cm_get_req_by_cm_id_fl(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id,
426 				      const char *func, uint32_t line)
427 {
428 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
429 	struct cm_req * cm_req;
430 
431 	cm_req_lock_acquire(cm_ctx);
432 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
433 	while (cur_node) {
434 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
435 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
436 
437 		if (cm_req->cm_id == cm_id) {
438 			cm_req_lock_release(cm_ctx);
439 			return cm_req;
440 		}
441 
442 		cur_node = next_node;
443 		next_node = NULL;
444 	}
445 	cm_req_lock_release(cm_ctx);
446 
447 	mlme_nofl_info("%s:%u: cm req not found for cm id 0x%x", func,
448 		       line, cm_id);
449 
450 	return NULL;
451 }
452 
453 #ifdef WLAN_FEATURE_11BE_MLO
454 void
455 cm_connect_resp_fill_mld_addr_from_candidate(struct wlan_objmgr_vdev *vdev,
456 					     struct scan_cache_entry *entry,
457 					     struct wlan_cm_connect_resp *resp)
458 {
459 	struct qdf_mac_addr *mld_addr;
460 
461 	if (!entry || !vdev || !wlan_vdev_mlme_is_mlo_vdev(vdev))
462 		return;
463 
464 	mld_addr = util_scan_entry_mldaddr(entry);
465 	if (!mld_addr)
466 		return;
467 
468 	qdf_copy_macaddr(&resp->mld_addr, mld_addr);
469 }
470 
471 void
472 cm_connect_resp_fill_mld_addr_from_cm_id(struct wlan_objmgr_vdev *vdev,
473 					 wlan_cm_id cm_id,
474 					 struct wlan_cm_connect_resp *rsp)
475 {
476 	struct cm_req *cm_req;
477 	struct cnx_mgr *cm_ctx;
478 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
479 	struct scan_cache_entry *entry;
480 
481 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
482 		return;
483 
484 	cm_ctx = cm_get_cm_ctx(vdev);
485 	if (!cm_ctx)
486 		return;
487 
488 	cm_req_lock_acquire(cm_ctx);
489 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
490 	while (cur_node) {
491 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
492 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
493 
494 		if (cm_req->cm_id != cm_id) {
495 			cur_node = next_node;
496 			next_node = NULL;
497 			continue;
498 		}
499 
500 		if (!cm_req->connect_req.cur_candidate ||
501 		    !cm_req->connect_req.cur_candidate->entry)
502 			break;
503 
504 		entry = cm_req->connect_req.cur_candidate->entry;
505 		cm_connect_resp_fill_mld_addr_from_candidate(vdev, entry, rsp);
506 		break;
507 	}
508 	cm_req_lock_release(cm_ctx);
509 }
510 
511 static void
512 cm_connect_resp_fill_mld_addr_from_scan_db(struct wlan_objmgr_vdev *vdev,
513 					   struct qdf_mac_addr *bssid,
514 					   struct wlan_cm_connect_resp *resp)
515 {
516 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
517 		return;
518 
519 	wlan_scan_get_mld_addr_by_link_addr(wlan_vdev_get_pdev(vdev), bssid,
520 					    &resp->mld_addr);
521 }
522 #else
523 static inline void
524 cm_connect_resp_fill_mld_addr_from_scan_db(struct wlan_objmgr_vdev *vdev,
525 					   struct qdf_mac_addr *bssid,
526 					   struct wlan_cm_connect_resp *resp)
527 {
528 }
529 #endif
530 
531 /**
532  * cm_fill_connect_resp_from_req() - Fill connect resp from connect request
533  * @vdev: VDEV objmgr pointer
534  * @resp: cm connect response
535  * @cm_req: cm request
536  *
537  * Context: Can be called from APIs holding cm request list lock
538  *
539  * Return: void
540  */
541 static void
542 cm_fill_connect_resp_from_req(struct wlan_objmgr_vdev *vdev,
543 			      struct wlan_cm_connect_resp *resp,
544 			      struct cm_req *cm_req)
545 {
546 	struct scan_cache_node *candidate;
547 	struct wlan_cm_connect_req *req;
548 
549 	req = &cm_req->connect_req.req;
550 	candidate = cm_req->connect_req.cur_candidate;
551 	if (candidate) {
552 		qdf_copy_macaddr(&resp->bssid, &candidate->entry->bssid);
553 		cm_connect_resp_fill_mld_addr_from_candidate(vdev,
554 							     candidate->entry,
555 							     resp);
556 	} else if (!qdf_is_macaddr_zero(&req->bssid)) {
557 		qdf_copy_macaddr(&resp->bssid, &req->bssid);
558 		cm_connect_resp_fill_mld_addr_from_scan_db(vdev, &req->bssid,
559 							   resp);
560 	} else {
561 		qdf_copy_macaddr(&resp->bssid, &req->bssid_hint);
562 		cm_connect_resp_fill_mld_addr_from_scan_db(vdev, &req->bssid,
563 							   resp);
564 	}
565 
566 	if (candidate)
567 		resp->freq = candidate->entry->channel.chan_freq;
568 	else if (req->chan_freq)
569 		resp->freq = req->chan_freq;
570 	else
571 		resp->freq = req->chan_freq_hint;
572 
573 	resp->ssid = req->ssid;
574 	resp->is_wps_connection = req->is_wps_connection;
575 	resp->is_osen_connection = req->is_osen_connection;
576 	cm_set_fils_connection_from_req(req, resp);
577 }
578 
579 /**
580  * cm_handle_connect_flush() - Fill fail connect resp from req and indicate
581  * same to osif
582  * @cm_ctx: connection manager context
583  * @cm_req: cm request
584  *
585  * Context: Can be called from APIs holding cm request list lock
586  *
587  * Return: void
588  */
589 static void
590 cm_handle_connect_flush(struct cnx_mgr *cm_ctx, struct cm_req *cm_req)
591 {
592 	struct wlan_cm_connect_resp *resp;
593 
594 	resp = qdf_mem_malloc(sizeof(*resp));
595 	if (!resp)
596 		return;
597 
598 	resp->connect_status = QDF_STATUS_E_FAILURE;
599 	resp->cm_id = cm_req->cm_id;
600 	resp->vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
601 	if (cm_req->failed_req)
602 		resp->reason = CM_GENERIC_FAILURE;
603 	else
604 		resp->reason = CM_ABORT_DUE_TO_NEW_REQ_RECVD;
605 
606 	/* Get bssid and ssid and freq for the cm id from the req list */
607 	cm_fill_connect_resp_from_req(cm_ctx->vdev, resp, cm_req);
608 
609 	cm_notify_connect_complete(cm_ctx, resp, 0);
610 
611 	/* For link switch connect request, notify MLO mgr */
612 	if (cm_is_link_switch_connect_resp(resp)) {
613 		cm_reset_active_cm_id(cm_ctx->vdev, resp->cm_id);
614 		mlo_mgr_link_switch_connect_done(cm_ctx->vdev,
615 						 resp->connect_status);
616 	}
617 
618 	qdf_mem_free(resp);
619 }
620 
621 /**
622  * cm_handle_disconnect_flush() - Fill disconnect resp from req and indicate
623  * same to osif
624  * @cm_ctx: connection manager context
625  * @cm_req: cm request
626  *
627  * Context: Can be called from APIs holding cm request list lock
628  *
629  * Return: void
630  */
631 static void
632 cm_handle_disconnect_flush(struct cnx_mgr *cm_ctx, struct cm_req *cm_req)
633 {
634 	struct wlan_cm_discon_rsp resp;
635 
636 	qdf_mem_zero(&resp, sizeof(resp));
637 	resp.req.cm_id = cm_req->cm_id;
638 	resp.req.req = cm_req->discon_req.req;
639 	/*
640 	 * Indicate to OSIF to inform kernel if not already done and this is
641 	 * the latest disconnect req received. If this is not the latest, it
642 	 * will be dropped in OSIF as src and cm_id will not match. A flushed
643 	 * disconnect can be last of this was received when previous disconnect
644 	 * was already in serialization active queue and thus wasn't flushed.
645 	 */
646 	mlme_cm_osif_disconnect_complete(cm_ctx->vdev, &resp);
647 
648 	if (cm_is_link_switch_disconnect_resp(&resp)) {
649 		cm_reset_active_cm_id(cm_ctx->vdev, resp.req.cm_id);
650 		mlo_mgr_link_switch_disconnect_done(cm_ctx->vdev,
651 						    QDF_STATUS_E_ABORTED,
652 						    true);
653 	}
654 }
655 
656 void cm_remove_cmd_from_serialization(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id)
657 {
658 	struct wlan_serialization_queued_cmd_info cmd_info;
659 	uint32_t prefix = CM_ID_GET_PREFIX(cm_id);
660 
661 	qdf_mem_zero(&cmd_info, sizeof(cmd_info));
662 	cmd_info.cmd_id = cm_id;
663 	cmd_info.req_type = WLAN_SER_CANCEL_NON_SCAN_CMD;
664 
665 	if (prefix == CONNECT_REQ_PREFIX) {
666 		cmd_info.cmd_type = WLAN_SER_CMD_VDEV_CONNECT;
667 	} else if (prefix == ROAM_REQ_PREFIX) {
668 		/*
669 		 * Try removing PREAUTH command when in preauth state else
670 		 * try remove ROAM command
671 		 */
672 		if (cm_ctx->preauth_in_progress)
673 			cmd_info.cmd_type = WLAN_SER_CMD_PERFORM_PRE_AUTH;
674 		else
675 			cmd_info.cmd_type = WLAN_SER_CMD_VDEV_ROAM;
676 		cm_ctx->preauth_in_progress = false;
677 	} else if (prefix == DISCONNECT_REQ_PREFIX) {
678 		cmd_info.cmd_type = WLAN_SER_CMD_VDEV_DISCONNECT;
679 	} else {
680 		mlme_err(CM_PREFIX_FMT "Invalid prefix %x",
681 			 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), cm_id),
682 			 prefix);
683 		return;
684 	}
685 
686 	cmd_info.vdev = cm_ctx->vdev;
687 
688 	if (cm_id == cm_ctx->active_cm_id) {
689 		mlme_debug(CM_PREFIX_FMT "Remove cmd type %d from active",
690 			   CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), cm_id),
691 			   cmd_info.cmd_type);
692 		cmd_info.queue_type = WLAN_SERIALIZATION_ACTIVE_QUEUE;
693 		/*
694 		 * Active command id is reset during memory release, but a new
695 		 * command will become active before memory release of
696 		 * serialization command, and if it try to check the active
697 		 * cm_id(using cm_get_active_req_type) it will be valid (), so
698 		 * reset the cm id for active command before calling release
699 		 * active command.
700 		 * One example: For ML vdevs, disconnect on Assoc vdev can get
701 		 * activated before release memory of link vdev command which
702 		 * reset active CM id, and thus during RSO stop can lead to
703 		 * assumption that link vdev disconnect is active when it is not.
704 		 */
705 		cm_reset_active_cm_id(cm_ctx->vdev, cm_id);
706 		wlan_serialization_remove_cmd(&cmd_info);
707 	} else {
708 		mlme_debug(CM_PREFIX_FMT "Remove cmd type %d from pending",
709 			   CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), cm_id),
710 			   cmd_info.cmd_type);
711 		cmd_info.queue_type = WLAN_SERIALIZATION_PENDING_QUEUE;
712 		wlan_serialization_cancel_request(&cmd_info);
713 	}
714 }
715 
716 void
717 cm_flush_pending_request(struct cnx_mgr *cm_ctx, uint32_t prefix,
718 			 bool only_failed_req)
719 {
720 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
721 	struct cm_req *cm_req;
722 	uint32_t req_prefix;
723 	bool roam_offload = false;
724 
725 	if (cm_roam_offload_enabled(wlan_vdev_get_psoc(cm_ctx->vdev)) &&
726 	     prefix == ROAM_REQ_PREFIX)
727 		roam_offload = true;
728 
729 	cm_req_lock_acquire(cm_ctx);
730 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
731 	while (cur_node) {
732 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
733 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
734 
735 		req_prefix = CM_ID_GET_PREFIX(cm_req->cm_id);
736 
737 		/*
738 		 * Only remove requests matching the flush prefix and
739 		 * the pending req for non roam offload(LFR3) commands
740 		 * (roam command is dummy in FW roam/LFR3 so active
741 		 * command can be removed)
742 		 */
743 		if (req_prefix != prefix ||
744 		    (!roam_offload && cm_req->cm_id == cm_ctx->active_cm_id))
745 			goto next;
746 
747 		/* If only_failed_req is set flush only failed req */
748 		if (only_failed_req && !cm_req->failed_req)
749 			goto next;
750 
751 		if (req_prefix == CONNECT_REQ_PREFIX) {
752 			cm_handle_connect_flush(cm_ctx, cm_req);
753 			cm_ctx->connect_count--;
754 			cm_free_connect_req_mem(&cm_req->connect_req);
755 		} else if (req_prefix == ROAM_REQ_PREFIX) {
756 			cm_free_roam_req_mem(&cm_req->roam_req);
757 		} else if (req_prefix == DISCONNECT_REQ_PREFIX) {
758 			cm_handle_disconnect_flush(cm_ctx, cm_req);
759 			cm_ctx->disconnect_count--;
760 		} else {
761 			mlme_err(CM_PREFIX_FMT "Invalid prefix %x",
762 				 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
763 					       cm_req->cm_id), prefix);
764 		}
765 
766 		cm_req_history_del(cm_ctx, cm_req, CM_REQ_DEL_FLUSH);
767 		mlme_debug(CM_PREFIX_FMT,
768 			   CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
769 					 cm_req->cm_id));
770 		cm_remove_cmd_from_serialization(cm_ctx, cm_req->cm_id);
771 		qdf_list_remove_node(&cm_ctx->req_list, &cm_req->node);
772 		qdf_mem_free(cm_req);
773 next:
774 		cur_node = next_node;
775 		next_node = NULL;
776 	}
777 
778 	cm_req_lock_release(cm_ctx);
779 }
780 
781 QDF_STATUS
782 cm_fill_bss_info_in_connect_rsp_by_cm_id(struct cnx_mgr *cm_ctx,
783 					 wlan_cm_id cm_id,
784 					 struct wlan_cm_connect_resp *resp)
785 {
786 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
787 	struct cm_req *cm_req;
788 	uint32_t prefix = CM_ID_GET_PREFIX(cm_id);
789 
790 	if (prefix != CONNECT_REQ_PREFIX)
791 		return QDF_STATUS_E_INVAL;
792 
793 	cm_req_lock_acquire(cm_ctx);
794 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
795 	while (cur_node) {
796 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
797 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
798 
799 		if (cm_req->cm_id == cm_id) {
800 			cm_fill_connect_resp_from_req(cm_ctx->vdev,
801 						      resp, cm_req);
802 			cm_req_lock_release(cm_ctx);
803 			return QDF_STATUS_SUCCESS;
804 		}
805 
806 		cur_node = next_node;
807 		next_node = NULL;
808 	}
809 	cm_req_lock_release(cm_ctx);
810 
811 	return QDF_STATUS_E_FAILURE;
812 }
813 
814 #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
815 bool cm_is_cm_id_current_candidate_single_pmk(struct cnx_mgr *cm_ctx,
816 					      wlan_cm_id cm_id)
817 {
818 	struct wlan_objmgr_psoc *psoc;
819 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
820 	struct cm_req *cm_req;
821 	uint32_t prefix = CM_ID_GET_PREFIX(cm_id);
822 	int32_t akm;
823 	struct scan_cache_node *candidate;
824 	bool is_single_pmk = false;
825 
826 	psoc = wlan_vdev_get_psoc(cm_ctx->vdev);
827 	if (!psoc) {
828 		mlme_err(CM_PREFIX_FMT "Failed to find psoc",
829 			 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
830 				       cm_id));
831 		return is_single_pmk;
832 	}
833 
834 	if (prefix != CONNECT_REQ_PREFIX)
835 		return is_single_pmk;
836 
837 	akm = wlan_crypto_get_param(cm_ctx->vdev, WLAN_CRYPTO_PARAM_KEY_MGMT);
838 	if (!QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE))
839 		return is_single_pmk;
840 
841 	cm_req_lock_acquire(cm_ctx);
842 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
843 	while (cur_node) {
844 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
845 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
846 
847 		if (cm_req->cm_id == cm_id) {
848 			candidate = cm_req->connect_req.cur_candidate;
849 			if (candidate &&
850 			    util_scan_entry_single_pmk(psoc, candidate->entry))
851 				is_single_pmk = true;
852 			break;
853 		}
854 
855 		cur_node = next_node;
856 		next_node = NULL;
857 	}
858 	cm_req_lock_release(cm_ctx);
859 
860 	return is_single_pmk;
861 }
862 #endif
863 
864 QDF_STATUS cm_add_req_to_list_and_indicate_osif(struct cnx_mgr *cm_ctx,
865 						struct cm_req *cm_req,
866 						enum wlan_cm_source source)
867 {
868 	uint32_t prefix = CM_ID_GET_PREFIX(cm_req->cm_id);
869 
870 	cm_req_lock_acquire(cm_ctx);
871 	if (qdf_list_size(&cm_ctx->req_list) >= CM_MAX_REQ) {
872 		cm_req_lock_release(cm_ctx);
873 		mlme_err(CM_PREFIX_FMT "List full size %d",
874 			 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
875 				       cm_req->cm_id),
876 			 qdf_list_size(&cm_ctx->req_list));
877 		return QDF_STATUS_E_FAILURE;
878 	}
879 
880 	qdf_list_insert_front(&cm_ctx->req_list, &cm_req->node);
881 	if (prefix == CONNECT_REQ_PREFIX)
882 		cm_ctx->connect_count++;
883 	else if (prefix == DISCONNECT_REQ_PREFIX)
884 		cm_ctx->disconnect_count++;
885 
886 	cm_req_history_add(cm_ctx, cm_req);
887 	cm_req_lock_release(cm_ctx);
888 	mlme_debug(CM_PREFIX_FMT,
889 		   CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
890 				 cm_req->cm_id));
891 
892 	mlme_cm_osif_update_id_and_src(cm_ctx->vdev, source, cm_req->cm_id);
893 
894 	return QDF_STATUS_SUCCESS;
895 }
896 
897 static void cm_zero_and_free_memory(uint8_t *ptr, uint32_t len)
898 {
899 	if (!ptr)
900 		return;
901 
902 	qdf_mem_zero(ptr, len);
903 	qdf_mem_free(ptr);
904 }
905 
906 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
907 /**
908  * cm_free_roaming_info() - Function to free all params in roaming info
909  * @connect_rsp: pointer to connect response
910  *
911  * Function to free up all the memory in connect response
912  *
913  * Return: void
914  */
915 static
916 void cm_free_roaming_info(struct wlan_cm_connect_resp *connect_rsp)
917 {
918 	cm_zero_and_free_memory((uint8_t *)connect_rsp->roaming_info,
919 				sizeof(*connect_rsp->roaming_info));
920 }
921 #else
922 static inline
923 void cm_free_roaming_info(struct wlan_cm_connect_resp *connect_rsp)
924 {
925 }
926 #endif
927 
928 #ifdef WLAN_FEATURE_FILS_SK
929 /**
930  * cm_free_fils_ie() - function to free all params in fils ie
931  * @connect_ie: ptr to connect ies
932  *
933  * Function to free up all the memory in fils ies response.
934  *
935  * Return: void
936  */
937 static
938 void cm_free_fils_ie(struct wlan_connect_rsp_ies *connect_ie)
939 {
940 	if (!connect_ie->fils_ie)
941 		return;
942 
943 	if (connect_ie->fils_ie->fils_pmk)
944 		cm_zero_and_free_memory(connect_ie->fils_ie->fils_pmk,
945 					connect_ie->fils_ie->fils_pmk_len);
946 
947 	cm_zero_and_free_memory((uint8_t *)connect_ie->fils_ie,
948 				sizeof(*connect_ie->fils_ie));
949 }
950 #else
951 static inline
952 void cm_free_fils_ie(struct wlan_connect_rsp_ies *connect_ie)
953 {
954 }
955 #endif
956 
957 /**
958  * cm_free_connect_ies() - Function to free all params in coonect ies
959  * @connect_ie: ptr to connect ies
960  *
961  * Function to free up all the memory in connect ies response
962  *
963  * Return: void
964  */
965 static
966 void cm_free_connect_ies(struct wlan_connect_rsp_ies *connect_ie)
967 {
968 	cm_zero_and_free_memory(connect_ie->assoc_req.ptr,
969 				connect_ie->assoc_req.len);
970 	connect_ie->assoc_req.len = 0;
971 
972 	cm_zero_and_free_memory(connect_ie->bcn_probe_rsp.ptr,
973 				connect_ie->bcn_probe_rsp.len);
974 	connect_ie->bcn_probe_rsp.len = 0;
975 
976 	cm_zero_and_free_memory(connect_ie->link_bcn_probe_rsp.ptr,
977 				connect_ie->link_bcn_probe_rsp.len);
978 	connect_ie->link_bcn_probe_rsp.len = 0;
979 
980 	cm_zero_and_free_memory(connect_ie->assoc_rsp.ptr,
981 				connect_ie->assoc_rsp.len);
982 	connect_ie->assoc_rsp.len = 0;
983 }
984 
985 void cm_free_connect_rsp_ies(struct wlan_cm_connect_resp *connect_rsp)
986 {
987 	cm_free_connect_ies(&connect_rsp->connect_ies);
988 	cm_free_fils_ie(&connect_rsp->connect_ies);
989 	cm_free_roaming_info(connect_rsp);
990 }
991 
992 static void cm_free_connect_req_ies(struct wlan_cm_connect_req *req)
993 {
994 	cm_zero_and_free_memory(req->assoc_ie.ptr, req->assoc_ie.len);
995 	req->assoc_ie.ptr = NULL;
996 	cm_zero_and_free_memory(req->scan_ie.ptr, req->scan_ie.len);
997 	req->scan_ie.ptr = NULL;
998 }
999 
1000 void cm_free_wep_key_params(struct wlan_cm_connect_req *req)
1001 {
1002 	cm_zero_and_free_memory(req->crypto.wep_keys.key,
1003 				req->crypto.wep_keys.key_len);
1004 	req->crypto.wep_keys.key = NULL;
1005 	cm_zero_and_free_memory(req->crypto.wep_keys.seq,
1006 				req->crypto.wep_keys.seq_len);
1007 	req->crypto.wep_keys.seq = NULL;
1008 }
1009 
1010 void cm_free_connect_req_param(struct wlan_cm_connect_req *req)
1011 {
1012 	cm_free_connect_req_ies(req);
1013 	cm_free_wep_key_params(req);
1014 }
1015 
1016 void cm_free_connect_req(struct wlan_cm_connect_req *req)
1017 {
1018 	cm_free_connect_req_param(req);
1019 	cm_zero_and_free_memory((uint8_t *)req, sizeof(*req));
1020 }
1021 
1022 void cm_free_connect_rsp(struct wlan_cm_connect_resp *connect_rsp)
1023 {
1024 	cm_free_connect_rsp_ies(connect_rsp);
1025 	cm_zero_and_free_memory((uint8_t *)connect_rsp, sizeof(*connect_rsp));
1026 }
1027 
1028 #ifdef CONN_MGR_ADV_FEATURE
1029 /**
1030  * cm_free_first_connect_rsp() - Function to free all params in connect rsp
1031  * @req: pointer to connect req struct
1032  *
1033  * Function to free up all the memory in connect rsp.
1034  *
1035  * Return: void
1036  */
1037 static
1038 void cm_free_first_connect_rsp(struct cm_connect_req *req)
1039 {
1040 	struct wlan_cm_connect_resp *connect_rsp = req->first_candidate_rsp;
1041 
1042 	if (!connect_rsp)
1043 		return;
1044 
1045 	cm_free_connect_rsp(connect_rsp);
1046 }
1047 #else
1048 static inline
1049 void cm_free_first_connect_rsp(struct cm_connect_req *req)
1050 {
1051 }
1052 #endif /* CONN_MGR_ADV_FEATURE */
1053 
1054 void cm_free_connect_req_mem(struct cm_connect_req *connect_req)
1055 {
1056 	struct wlan_cm_connect_req *req;
1057 
1058 	req = &connect_req->req;
1059 
1060 	if (connect_req->candidate_list)
1061 		wlan_scan_purge_results(connect_req->candidate_list);
1062 
1063 	cm_free_connect_req_param(req);
1064 
1065 	cm_free_first_connect_rsp(connect_req);
1066 
1067 	qdf_mem_zero(connect_req, sizeof(*connect_req));
1068 }
1069 
1070 QDF_STATUS
1071 cm_delete_req_from_list(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id)
1072 {
1073 	uint32_t prefix = CM_ID_GET_PREFIX(cm_id);
1074 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
1075 	struct cm_req *cm_req = NULL;
1076 
1077 	cm_req_lock_acquire(cm_ctx);
1078 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
1079 	while (cur_node) {
1080 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
1081 
1082 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
1083 		if (cm_req->cm_id == cm_id)
1084 			break;
1085 
1086 		cur_node = next_node;
1087 		next_node = NULL;
1088 		cm_req = NULL;
1089 	}
1090 
1091 	if (!cm_req) {
1092 		cm_req_lock_release(cm_ctx);
1093 		mlme_err(CM_PREFIX_FMT " req not found",
1094 			 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), cm_id));
1095 		return QDF_STATUS_E_FAILURE;
1096 	}
1097 
1098 	qdf_list_remove_node(&cm_ctx->req_list, &cm_req->node);
1099 	if (prefix == CONNECT_REQ_PREFIX) {
1100 		cm_ctx->connect_count--;
1101 		cm_free_connect_req_mem(&cm_req->connect_req);
1102 	} else if (prefix == ROAM_REQ_PREFIX) {
1103 		cm_free_roam_req_mem(&cm_req->roam_req);
1104 	} else if (prefix == DISCONNECT_REQ_PREFIX) {
1105 		cm_ctx->disconnect_count--;
1106 	} else {
1107 		mlme_err(CM_PREFIX_FMT "Invalid prefix %x",
1108 			 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
1109 				       cm_req->cm_id), prefix);
1110 	}
1111 
1112 	if (cm_id == cm_ctx->active_cm_id)
1113 		cm_req_history_del(cm_ctx, cm_req, CM_REQ_DEL_ACTIVE);
1114 	else
1115 		cm_req_history_del(cm_ctx, cm_req, CM_REQ_DEL_PENDING);
1116 
1117 	mlme_debug(CM_PREFIX_FMT,
1118 		   CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
1119 				 cm_req->cm_id));
1120 
1121 	qdf_mem_free(cm_req);
1122 	cm_req_lock_release(cm_ctx);
1123 
1124 	return QDF_STATUS_SUCCESS;
1125 }
1126 
1127 void cm_remove_cmd(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id_to_remove)
1128 {
1129 	struct wlan_objmgr_psoc *psoc;
1130 	QDF_STATUS status;
1131 	wlan_cm_id cm_id;
1132 
1133 	if (!cm_id_to_remove) {
1134 		mlme_err("cm_id_to_remove is null");
1135 		return;
1136 	}
1137 
1138 	/*
1139 	 * store local value as cm_delete_req_from_list may free the
1140 	 * cm_id_to_remove pointer
1141 	 */
1142 	cm_id = *cm_id_to_remove;
1143 	/* return if zero or invalid cm_id */
1144 	if (!cm_id || cm_id == CM_ID_INVALID) {
1145 		mlme_debug(CM_PREFIX_FMT " Invalid cm_id",
1146 			   CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
1147 					 cm_id));
1148 		return;
1149 	}
1150 
1151 	psoc = wlan_vdev_get_psoc(cm_ctx->vdev);
1152 	if (!psoc) {
1153 		mlme_err(CM_PREFIX_FMT "Failed to find psoc",
1154 			 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), cm_id));
1155 		return;
1156 	}
1157 
1158 	status = cm_delete_req_from_list(cm_ctx, cm_id);
1159 	if (QDF_IS_STATUS_ERROR(status))
1160 		return;
1161 
1162 	if (cm_is_link_switch_cmd(cm_id)) {
1163 		mlme_debug("Skip cmd remove for link switch connect/disconnect");
1164 		return;
1165 	}
1166 
1167 	cm_remove_cmd_from_serialization(cm_ctx, cm_id);
1168 }
1169 
1170 void cm_vdev_scan_cancel(struct wlan_objmgr_pdev *pdev,
1171 			 struct wlan_objmgr_vdev *vdev)
1172 {
1173 	struct scan_cancel_request *req;
1174 	QDF_STATUS status;
1175 
1176 	req = qdf_mem_malloc(sizeof(*req));
1177 	if (!req)
1178 		return;
1179 
1180 	req->vdev = vdev;
1181 	req->cancel_req.scan_id = INVAL_SCAN_ID;
1182 	req->cancel_req.vdev_id = wlan_vdev_get_id(vdev);
1183 	req->cancel_req.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
1184 	req->cancel_req.req_type = WLAN_SCAN_CANCEL_VDEV_ALL;
1185 
1186 	status = wlan_scan_cancel(req);
1187 	/* In success/failure case wlan_scan_cancel free the req memory */
1188 	if (QDF_IS_STATUS_ERROR(status))
1189 		mlme_err("vdev %d cancel scan request failed",
1190 			 wlan_vdev_get_id(vdev));
1191 }
1192 
1193 void cm_set_max_connect_attempts(struct wlan_objmgr_vdev *vdev,
1194 				 uint8_t max_connect_attempts)
1195 {
1196 	struct cnx_mgr *cm_ctx;
1197 
1198 	cm_ctx = cm_get_cm_ctx(vdev);
1199 	if (!cm_ctx)
1200 		return;
1201 
1202 	cm_ctx->max_connect_attempts =
1203 		QDF_MIN(max_connect_attempts, CM_MAX_CONNECT_ATTEMPTS);
1204 	mlme_debug("vdev %d max connect attempts set to %d, requested %d",
1205 		   wlan_vdev_get_id(vdev),
1206 		   cm_ctx->max_connect_attempts, max_connect_attempts);
1207 }
1208 
1209 void cm_set_max_connect_timeout(struct wlan_objmgr_vdev *vdev,
1210 				uint32_t max_connect_timeout)
1211 {
1212 	struct cnx_mgr *cm_ctx;
1213 
1214 	cm_ctx = cm_get_cm_ctx(vdev);
1215 	if (!cm_ctx)
1216 		return;
1217 
1218 	cm_ctx->connect_timeout = max_connect_timeout;
1219 }
1220 
1221 QDF_STATUS
1222 cm_fill_disconnect_resp_from_cm_id(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id,
1223 				   struct wlan_cm_discon_rsp *resp)
1224 {
1225 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
1226 	struct cm_req *cm_req;
1227 	uint32_t prefix = CM_ID_GET_PREFIX(cm_id);
1228 
1229 	if (prefix != DISCONNECT_REQ_PREFIX)
1230 		return QDF_STATUS_E_INVAL;
1231 
1232 	cm_req_lock_acquire(cm_ctx);
1233 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
1234 	while (cur_node) {
1235 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
1236 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
1237 
1238 		if (cm_req->cm_id == cm_id) {
1239 			resp->req.cm_id = cm_id;
1240 			resp->req.req = cm_req->discon_req.req;
1241 			cm_req_lock_release(cm_ctx);
1242 			return QDF_STATUS_SUCCESS;
1243 		}
1244 
1245 		cur_node = next_node;
1246 		next_node = NULL;
1247 	}
1248 	cm_req_lock_release(cm_ctx);
1249 
1250 	return QDF_STATUS_E_FAILURE;
1251 }
1252 
1253 void cm_inform_bcn_probe(struct cnx_mgr *cm_ctx, uint8_t *bcn_probe,
1254 			 uint32_t len, qdf_freq_t freq, int32_t rssi,
1255 			 wlan_cm_id cm_id)
1256 {
1257 	qdf_nbuf_t buf;
1258 	struct wlan_objmgr_pdev *pdev;
1259 	uint8_t *data, i, vdev_id;
1260 	struct mgmt_rx_event_params rx_param = {0};
1261 	struct wlan_frame_hdr *hdr;
1262 	enum mgmt_frame_type frm_type = MGMT_BEACON;
1263 
1264 	vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
1265 	if (!bcn_probe || !len || (len < sizeof(*hdr))) {
1266 		mlme_err(CM_PREFIX_FMT "bcn_probe is null or invalid len %d",
1267 			 CM_PREFIX_REF(vdev_id, cm_id), len);
1268 		return;
1269 	}
1270 
1271 	pdev = wlan_vdev_get_pdev(cm_ctx->vdev);
1272 	if (!pdev) {
1273 		mlme_err(CM_PREFIX_FMT "Failed to find pdev",
1274 			 CM_PREFIX_REF(vdev_id, cm_id));
1275 		return;
1276 	}
1277 
1278 	hdr = (struct wlan_frame_hdr *)bcn_probe;
1279 	if ((hdr->i_fc[0] & QDF_IEEE80211_FC0_SUBTYPE_MASK) ==
1280 	    MGMT_SUBTYPE_PROBE_RESP)
1281 		frm_type = MGMT_PROBE_RESP;
1282 
1283 	rx_param.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
1284 	rx_param.chan_freq = freq;
1285 	rx_param.rssi = rssi;
1286 
1287 	/* Set all per chain rssi as invalid */
1288 	for (i = 0; i < WLAN_MGMT_TXRX_HOST_MAX_ANTENNA; i++)
1289 		rx_param.rssi_ctl[i] = WLAN_INVALID_PER_CHAIN_RSSI;
1290 
1291 	buf = qdf_nbuf_alloc(NULL, qdf_roundup(len, 4), 0, 4, false);
1292 	if (!buf)
1293 		return;
1294 
1295 	qdf_nbuf_put_tail(buf, len);
1296 	qdf_nbuf_set_protocol(buf, ETH_P_CONTROL);
1297 
1298 	data = qdf_nbuf_data(buf);
1299 	qdf_mem_copy(data, bcn_probe, len);
1300 	/* buf will be freed by scan module in error or success case */
1301 	wlan_scan_process_bcn_probe_rx_sync(wlan_pdev_get_psoc(pdev), buf,
1302 					    &rx_param, frm_type);
1303 }
1304 
1305 bool cm_is_vdev_connecting(struct wlan_objmgr_vdev *vdev)
1306 {
1307 	struct cnx_mgr *cm_ctx;
1308 	enum wlan_cm_sm_state state;
1309 
1310 	cm_ctx = cm_get_cm_ctx(vdev);
1311 	if (!cm_ctx)
1312 		return false;
1313 
1314 	state = cm_get_state(cm_ctx);
1315 
1316 	if (state == WLAN_CM_S_CONNECTING)
1317 		return true;
1318 
1319 	return false;
1320 }
1321 
1322 bool cm_is_vdev_connected(struct wlan_objmgr_vdev *vdev)
1323 {
1324 	struct cnx_mgr *cm_ctx;
1325 	enum wlan_cm_sm_state state;
1326 
1327 	cm_ctx = cm_get_cm_ctx(vdev);
1328 	if (!cm_ctx)
1329 		return false;
1330 
1331 	state = cm_get_state(cm_ctx);
1332 
1333 	if (state == WLAN_CM_S_CONNECTED)
1334 		return true;
1335 
1336 	return false;
1337 }
1338 
1339 bool cm_is_vdev_active(struct wlan_objmgr_vdev *vdev)
1340 {
1341 	struct cnx_mgr *cm_ctx;
1342 	enum wlan_cm_sm_state state;
1343 
1344 	cm_ctx = cm_get_cm_ctx(vdev);
1345 	if (!cm_ctx)
1346 		return false;
1347 
1348 	state = cm_get_state(cm_ctx);
1349 
1350 	if (state == WLAN_CM_S_CONNECTED || state == WLAN_CM_S_ROAMING)
1351 		return true;
1352 
1353 	return false;
1354 }
1355 
1356 bool cm_is_vdev_disconnecting(struct wlan_objmgr_vdev *vdev)
1357 {
1358 	struct cnx_mgr *cm_ctx;
1359 	enum wlan_cm_sm_state state;
1360 
1361 	cm_ctx = cm_get_cm_ctx(vdev);
1362 	if (!cm_ctx)
1363 		return false;
1364 
1365 	state = cm_get_state(cm_ctx);
1366 
1367 	if (state == WLAN_CM_S_DISCONNECTING)
1368 		return true;
1369 
1370 	return false;
1371 }
1372 
1373 bool cm_is_vdev_disconnected(struct wlan_objmgr_vdev *vdev)
1374 {
1375 	struct cnx_mgr *cm_ctx;
1376 	enum wlan_cm_sm_state state;
1377 
1378 	cm_ctx = cm_get_cm_ctx(vdev);
1379 	if (!cm_ctx)
1380 		return true;
1381 
1382 	state = cm_get_state(cm_ctx);
1383 
1384 	if (state == WLAN_CM_S_INIT)
1385 		return true;
1386 
1387 	return false;
1388 }
1389 
1390 bool cm_is_vdev_roaming(struct wlan_objmgr_vdev *vdev)
1391 {
1392 	struct cnx_mgr *cm_ctx;
1393 	enum wlan_cm_sm_state state;
1394 
1395 	cm_ctx = cm_get_cm_ctx(vdev);
1396 	if (!cm_ctx)
1397 		return false;
1398 
1399 	state = cm_get_state(cm_ctx);
1400 
1401 	if (state == WLAN_CM_S_ROAMING)
1402 		return true;
1403 
1404 	return false;
1405 }
1406 
1407 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
1408 bool cm_is_vdev_roam_started(struct wlan_objmgr_vdev *vdev)
1409 {
1410 	struct cnx_mgr *cm_ctx;
1411 	enum wlan_cm_sm_state state;
1412 	enum wlan_cm_sm_state sub_state;
1413 
1414 	cm_ctx = cm_get_cm_ctx(vdev);
1415 	if (!cm_ctx)
1416 		return false;
1417 
1418 	state = cm_get_state(cm_ctx);
1419 	sub_state = cm_get_sub_state(cm_ctx);
1420 	if (state == WLAN_CM_S_ROAMING && sub_state == WLAN_CM_SS_ROAM_STARTED)
1421 		return true;
1422 
1423 	return false;
1424 }
1425 
1426 bool cm_is_vdev_roam_sync_inprogress(struct wlan_objmgr_vdev *vdev)
1427 {
1428 	struct cnx_mgr *cm_ctx;
1429 	enum wlan_cm_sm_state state;
1430 	enum wlan_cm_sm_state sub_state;
1431 
1432 	cm_ctx = cm_get_cm_ctx(vdev);
1433 	if (!cm_ctx)
1434 		return false;
1435 
1436 	state = cm_get_state(cm_ctx);
1437 	sub_state = cm_get_sub_state(cm_ctx);
1438 	if (state == WLAN_CM_S_ROAMING && sub_state == WLAN_CM_SS_ROAM_SYNC)
1439 		return true;
1440 
1441 	return false;
1442 }
1443 #endif
1444 
1445 #ifdef WLAN_FEATURE_HOST_ROAM
1446 bool cm_is_vdev_roam_preauth_state(struct wlan_objmgr_vdev *vdev)
1447 {
1448 	struct cnx_mgr *cm_ctx;
1449 	enum wlan_cm_sm_state state;
1450 	enum wlan_cm_sm_state sub_state;
1451 
1452 	cm_ctx = cm_get_cm_ctx(vdev);
1453 	if (!cm_ctx)
1454 		return false;
1455 
1456 	state = cm_get_state(cm_ctx);
1457 	sub_state = cm_get_sub_state(cm_ctx);
1458 	if (state == WLAN_CM_S_ROAMING && sub_state == WLAN_CM_SS_PREAUTH)
1459 		return true;
1460 
1461 	return false;
1462 }
1463 
1464 bool cm_is_vdev_roam_reassoc_state(struct wlan_objmgr_vdev *vdev)
1465 {
1466 	struct cnx_mgr *cm_ctx;
1467 	enum wlan_cm_sm_state state;
1468 	enum wlan_cm_sm_state sub_state;
1469 
1470 	cm_ctx = cm_get_cm_ctx(vdev);
1471 	if (!cm_ctx)
1472 		return false;
1473 
1474 	state = cm_get_state(cm_ctx);
1475 	sub_state = cm_get_sub_state(cm_ctx);
1476 	if (state == WLAN_CM_S_ROAMING && sub_state == WLAN_CM_SS_REASSOC)
1477 		return true;
1478 
1479 	return false;
1480 }
1481 #endif
1482 
1483 enum wlan_cm_active_request_type
1484 cm_get_active_req_type(struct wlan_objmgr_vdev *vdev)
1485 {
1486 	struct cnx_mgr *cm_ctx;
1487 	wlan_cm_id cm_id;
1488 	uint32_t active_req_prefix = 0;
1489 
1490 	cm_ctx = cm_get_cm_ctx(vdev);
1491 	if (!cm_ctx)
1492 		return CM_NONE;
1493 
1494 	cm_id = cm_ctx->active_cm_id;
1495 
1496 	if (cm_id != CM_ID_INVALID)
1497 		active_req_prefix = CM_ID_GET_PREFIX(cm_id);
1498 
1499 	if (active_req_prefix == CONNECT_REQ_PREFIX)
1500 		return CM_CONNECT_ACTIVE;
1501 	else if (active_req_prefix == DISCONNECT_REQ_PREFIX)
1502 		return CM_DISCONNECT_ACTIVE;
1503 	else if (active_req_prefix == ROAM_REQ_PREFIX)
1504 		return CM_ROAM_ACTIVE;
1505 	else
1506 		return CM_NONE;
1507 }
1508 
1509 #ifdef WLAN_FEATURE_11BE_MLO
1510 static inline
1511 void cm_fill_ml_partner_info(struct wlan_cm_connect_req *req,
1512 			       struct wlan_cm_vdev_connect_req *connect_req)
1513 {
1514 	if (req->ml_parnter_info.num_partner_links)
1515 		qdf_mem_copy(&connect_req->ml_parnter_info,
1516 			     &req->ml_parnter_info,
1517 			     sizeof(struct mlo_partner_info));
1518 }
1519 #else
1520 static inline
1521 void cm_fill_ml_partner_info(struct wlan_cm_connect_req *req,
1522 			     struct wlan_cm_vdev_connect_req *connect_req)
1523 {
1524 }
1525 #endif
1526 
1527 bool cm_find_bss_from_candidate_list(qdf_list_t *candidate_list,
1528 				     struct qdf_mac_addr *bssid,
1529 				     struct scan_cache_node **entry_found)
1530 {
1531 	struct scan_cache_node *scan_entry;
1532 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
1533 	struct qdf_mac_addr *bssid2;
1534 
1535 	if (qdf_is_macaddr_zero(bssid) ||
1536 	    qdf_is_macaddr_broadcast(bssid))
1537 		return false;
1538 
1539 	if (qdf_list_peek_front(candidate_list, &cur_node) !=
1540 					QDF_STATUS_SUCCESS) {
1541 		mlme_err("failed to peer front of candidate_list");
1542 		return false;
1543 	}
1544 
1545 	while (cur_node) {
1546 		qdf_list_peek_next(candidate_list, cur_node, &next_node);
1547 
1548 		scan_entry = qdf_container_of(cur_node, struct scan_cache_node,
1549 					      node);
1550 		bssid2 = &scan_entry->entry->bssid;
1551 		if (qdf_is_macaddr_zero(bssid2))
1552 			goto next;
1553 
1554 		if (qdf_is_macaddr_equal(bssid, bssid2)) {
1555 			if (entry_found)
1556 				*entry_found = scan_entry;
1557 			return true;
1558 		}
1559 next:
1560 		cur_node = next_node;
1561 		next_node = NULL;
1562 	}
1563 
1564 	return false;
1565 }
1566 
1567 bool cm_is_connect_req_reassoc(struct wlan_cm_connect_req *req)
1568 {
1569 	if (!qdf_is_macaddr_zero(&req->prev_bssid) &&
1570 	    (!qdf_is_macaddr_zero(&req->bssid) ||
1571 	     !qdf_is_macaddr_zero(&req->bssid_hint)) &&
1572 	    (req->chan_freq || req->chan_freq_hint))
1573 		return true;
1574 
1575 	return false;
1576 }
1577 
1578 bool cm_is_first_candidate_connect_attempt(struct wlan_objmgr_vdev *vdev)
1579 {
1580 	struct cnx_mgr *cm_ctx;
1581 	struct cm_req *cm_req;
1582 	bool status = false;
1583 
1584 	cm_ctx = cm_get_cm_ctx(vdev);
1585 	if (!cm_ctx)
1586 		return status;
1587 
1588 	cm_req_lock_acquire(cm_ctx);
1589 	cm_req = cm_get_req_by_cm_id(cm_ctx, cm_ctx->active_cm_id);
1590 	if (!cm_req)
1591 		goto out;
1592 
1593 	if (cm_req->connect_req.cur_candidate_retries ||
1594 	    cm_req->connect_req.connect_attempts > 1)
1595 		goto out;
1596 
1597 	status = true;
1598 
1599 out:
1600 	cm_req_lock_release(cm_ctx);
1601 	return status;
1602 }
1603 
1604 QDF_STATUS
1605 cm_get_active_connect_req_param(struct wlan_objmgr_vdev *vdev,
1606 				struct wlan_cm_connect_req *req)
1607 {
1608 	struct cnx_mgr *cm_ctx;
1609 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
1610 	struct cm_req *cm_req = NULL;
1611 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
1612 	uint32_t cm_id_prefix;
1613 
1614 	cm_ctx = cm_get_cm_ctx(vdev);
1615 	if (!cm_ctx)
1616 		return QDF_STATUS_E_FAILURE;
1617 
1618 	cm_req_lock_acquire(cm_ctx);
1619 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
1620 	while (cur_node) {
1621 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
1622 
1623 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
1624 		cm_id_prefix = CM_ID_GET_PREFIX((cm_req->cm_id));
1625 
1626 		if (cm_req->cm_id != cm_ctx->active_cm_id ||
1627 		    cm_id_prefix != CONNECT_REQ_PREFIX) {
1628 			cur_node = next_node;
1629 			next_node = NULL;
1630 			continue;
1631 		}
1632 
1633 		*req = cm_req->connect_req.req;
1634 		qdf_mem_zero(&req->assoc_ie, sizeof(struct element_info));
1635 		qdf_mem_zero(&req->scan_ie, sizeof(struct element_info));
1636 		status = QDF_STATUS_SUCCESS;
1637 		break;
1638 	}
1639 
1640 	cm_req_lock_release(cm_ctx);
1641 	return status;
1642 }
1643 
1644 bool cm_get_active_connect_req(struct wlan_objmgr_vdev *vdev,
1645 			       struct wlan_cm_vdev_connect_req *req)
1646 {
1647 	struct cnx_mgr *cm_ctx;
1648 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
1649 	struct cm_req *cm_req = NULL;
1650 	bool status = false;
1651 	uint32_t cm_id_prefix;
1652 
1653 	cm_ctx = cm_get_cm_ctx(vdev);
1654 	if (!cm_ctx)
1655 		return status;
1656 
1657 	cm_req_lock_acquire(cm_ctx);
1658 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
1659 	while (cur_node) {
1660 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
1661 
1662 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
1663 		cm_id_prefix = CM_ID_GET_PREFIX((cm_req->cm_id));
1664 
1665 		if (cm_req->cm_id == cm_ctx->active_cm_id &&
1666 		    cm_id_prefix == CONNECT_REQ_PREFIX) {
1667 			req->vdev_id = wlan_vdev_get_id(vdev);
1668 			req->cm_id = cm_req->connect_req.cm_id;
1669 			req->bss =  cm_req->connect_req.cur_candidate;
1670 			req->is_wps_connection =
1671 				cm_req->connect_req.req.is_wps_connection;
1672 			req->is_osen_connection =
1673 				cm_req->connect_req.req.is_osen_connection;
1674 			req->is_non_assoc_link = cm_req->connect_req.req.is_non_assoc_link;
1675 			cm_fill_ml_partner_info(&cm_req->connect_req.req, req);
1676 			status = true;
1677 			cm_req_lock_release(cm_ctx);
1678 			return status;
1679 		}
1680 
1681 		cur_node = next_node;
1682 		next_node = NULL;
1683 	}
1684 	cm_req_lock_release(cm_ctx);
1685 
1686 	return status;
1687 }
1688 
1689 bool cm_get_active_disconnect_req(struct wlan_objmgr_vdev *vdev,
1690 				  struct wlan_cm_vdev_discon_req *req)
1691 {
1692 	struct cnx_mgr *cm_ctx;
1693 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
1694 	struct cm_req *cm_req = NULL;
1695 	bool status = false;
1696 	uint32_t cm_id_prefix;
1697 
1698 	cm_ctx = cm_get_cm_ctx(vdev);
1699 	if (!cm_ctx)
1700 		return status;
1701 
1702 	cm_req_lock_acquire(cm_ctx);
1703 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
1704 	while (cur_node) {
1705 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
1706 
1707 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
1708 		cm_id_prefix = CM_ID_GET_PREFIX((cm_req->cm_id));
1709 
1710 		if (cm_req->cm_id == cm_ctx->active_cm_id &&
1711 		    cm_id_prefix == DISCONNECT_REQ_PREFIX) {
1712 			req->cm_id = cm_req->cm_id;
1713 			req->req.vdev_id = wlan_vdev_get_id(vdev);
1714 			req->req.source = cm_req->discon_req.req.source;
1715 			req->req.reason_code =
1716 					cm_req->discon_req.req.reason_code;
1717 			req->req.bssid = cm_req->discon_req.req.bssid;
1718 			req->req.is_no_disassoc_disconnect =
1719 				cm_req->discon_req.req.is_no_disassoc_disconnect;
1720 			status = true;
1721 			cm_req_lock_release(cm_ctx);
1722 			return status;
1723 		}
1724 
1725 		cur_node = next_node;
1726 		next_node = NULL;
1727 	}
1728 	cm_req_lock_release(cm_ctx);
1729 
1730 	return status;
1731 }
1732 
1733 struct cm_req *cm_get_req_by_scan_id(struct cnx_mgr *cm_ctx,
1734 				     wlan_scan_id scan_id)
1735 {
1736 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
1737 	struct cm_req *cm_req;
1738 
1739 	cm_req_lock_acquire(cm_ctx);
1740 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
1741 	while (cur_node) {
1742 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
1743 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
1744 
1745 		if (cm_req->connect_req.scan_id == scan_id) {
1746 			cm_req_lock_release(cm_ctx);
1747 			return cm_req;
1748 		}
1749 
1750 		cur_node = next_node;
1751 		next_node = NULL;
1752 	}
1753 	cm_req_lock_release(cm_ctx);
1754 
1755 	return NULL;
1756 }
1757 
1758 wlan_cm_id cm_get_cm_id_by_scan_id(struct cnx_mgr *cm_ctx,
1759 				   wlan_scan_id scan_id)
1760 {
1761 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
1762 	struct cm_req *cm_req;
1763 
1764 	cm_req_lock_acquire(cm_ctx);
1765 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
1766 	while (cur_node) {
1767 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
1768 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
1769 
1770 		if (cm_req->connect_req.scan_id == scan_id) {
1771 			cm_req_lock_release(cm_ctx);
1772 			return cm_req->cm_id;
1773 		}
1774 
1775 		cur_node = next_node;
1776 		next_node = NULL;
1777 	}
1778 	cm_req_lock_release(cm_ctx);
1779 
1780 	return CM_ID_INVALID;
1781 }
1782 
1783 QDF_STATUS cm_get_rnr(struct wlan_objmgr_vdev *vdev, wlan_cm_id cm_id,
1784 		      struct reduced_neighbor_report *rnr)
1785 {
1786 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
1787 	struct cm_req *cm_req;
1788 	uint32_t prefix = CM_ID_GET_PREFIX(cm_id);
1789 	struct cnx_mgr *cm_ctx;
1790 
1791 	if (prefix != CONNECT_REQ_PREFIX)
1792 		return QDF_STATUS_E_INVAL;
1793 
1794 	cm_ctx = cm_get_cm_ctx(vdev);
1795 	if (!cm_ctx)
1796 		return QDF_STATUS_E_INVAL;
1797 
1798 	cm_req_lock_acquire(cm_ctx);
1799 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
1800 	while (cur_node) {
1801 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
1802 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
1803 
1804 		if (cm_req->cm_id == cm_id) {
1805 			if (!cm_req->connect_req.cur_candidate ||
1806 			    !cm_req->connect_req.cur_candidate->entry)
1807 				break;
1808 
1809 			qdf_mem_copy(rnr,
1810 				&cm_req->connect_req.cur_candidate->entry->rnr,
1811 				sizeof(*rnr));
1812 			cm_req_lock_release(cm_ctx);
1813 			return QDF_STATUS_SUCCESS;
1814 		}
1815 
1816 		cur_node = next_node;
1817 		next_node = NULL;
1818 	}
1819 	cm_req_lock_release(cm_ctx);
1820 
1821 	return QDF_STATUS_E_FAILURE;
1822 }
1823 
1824 #ifdef WLAN_POLICY_MGR_ENABLE
1825 static void
1826 cm_get_pcl_chan_weigtage_for_sta(struct wlan_objmgr_pdev *pdev,
1827 				 struct pcl_freq_weight_list *pcl_lst,
1828 				 struct wlan_objmgr_vdev *vdev)
1829 {
1830 	uint32_t num_entries = 0;
1831 	uint8_t vdev_id;
1832 	QDF_STATUS status;
1833 
1834 	if (!pcl_lst || !vdev)
1835 		return;
1836 
1837 	vdev_id = wlan_vdev_get_id(vdev);
1838 
1839 	status = policy_mgr_get_pcl(wlan_pdev_get_psoc(pdev),
1840 				    PM_STA_MODE,
1841 				    pcl_lst->pcl_freq_list,
1842 				    &num_entries,
1843 				    pcl_lst->pcl_weight_list,
1844 				    NUM_CHANNELS, vdev_id);
1845 	if (QDF_IS_STATUS_ERROR(status))
1846 		return;
1847 	pcl_lst->num_of_pcl_channels = num_entries;
1848 }
1849 
1850 void cm_calculate_scores(struct cnx_mgr *cm_ctx,
1851 			 struct wlan_objmgr_pdev *pdev,
1852 			 struct scan_filter *filter, qdf_list_t *list)
1853 {
1854 	struct pcl_freq_weight_list *pcl_lst = NULL;
1855 
1856 	if (!filter->num_of_bssid) {
1857 		pcl_lst = qdf_mem_malloc(sizeof(*pcl_lst));
1858 		cm_get_pcl_chan_weigtage_for_sta(pdev, pcl_lst, cm_ctx->vdev);
1859 		if (pcl_lst && !pcl_lst->num_of_pcl_channels) {
1860 			qdf_mem_free(pcl_lst);
1861 			pcl_lst = NULL;
1862 		}
1863 	}
1864 	wlan_cm_calculate_bss_score(pdev, pcl_lst, list, &filter->bssid_hint,
1865 				    (struct qdf_mac_addr *)
1866 				    wlan_vdev_mlme_get_macaddr(cm_ctx->vdev));
1867 	if (pcl_lst)
1868 		qdf_mem_free(pcl_lst);
1869 }
1870 #else
1871 inline
1872 void cm_calculate_scores(struct cnx_mgr *cm_ctx,
1873 			 struct wlan_objmgr_pdev *pdev,
1874 			 struct scan_filter *filter, qdf_list_t *list)
1875 {
1876 	wlan_cm_calculate_bss_score(pdev, NULL, list, &filter->bssid_hint,
1877 				    NULL);
1878 
1879 	/*
1880 	 * Custom sorting if enabled
1881 	 */
1882 	if (cm_ctx && cm_ctx->cm_candidate_list_custom_sort)
1883 		cm_ctx->cm_candidate_list_custom_sort(cm_ctx->vdev, list);
1884 }
1885 #endif
1886 
1887 #ifdef SM_ENG_HIST_ENABLE
1888 static const char *cm_id_to_string(wlan_cm_id cm_id)
1889 {
1890 	uint32_t prefix = CM_ID_GET_PREFIX(cm_id);
1891 
1892 	switch (prefix) {
1893 	case CONNECT_REQ_PREFIX:
1894 		return "CONNECT";
1895 	case DISCONNECT_REQ_PREFIX:
1896 		return "DISCONNECT";
1897 	case ROAM_REQ_PREFIX:
1898 		return "ROAM";
1899 	default:
1900 		return "INVALID";
1901 	}
1902 }
1903 
1904 void cm_req_history_add(struct cnx_mgr *cm_ctx,
1905 			struct cm_req *cm_req)
1906 {
1907 	struct cm_req_history *history = &cm_ctx->req_history;
1908 	struct cm_req_history_info *data;
1909 
1910 	qdf_spin_lock_bh(&history->cm_req_hist_lock);
1911 	data = &history->data[history->index];
1912 	history->index++;
1913 	history->index %= CM_REQ_HISTORY_SIZE;
1914 
1915 	qdf_mem_zero(data, sizeof(*data));
1916 	data->cm_id = cm_req->cm_id;
1917 	data->add_time = qdf_get_log_timestamp();
1918 	data->add_cm_state = cm_get_state(cm_ctx);
1919 	qdf_spin_unlock_bh(&history->cm_req_hist_lock);
1920 }
1921 
1922 void cm_req_history_del(struct cnx_mgr *cm_ctx,
1923 			struct cm_req *cm_req,
1924 			enum cm_req_del_type del_type)
1925 {
1926 	uint8_t i, idx;
1927 	struct cm_req_history_info *data;
1928 	struct cm_req_history *history = &cm_ctx->req_history;
1929 
1930 	qdf_spin_lock_bh(&history->cm_req_hist_lock);
1931 	for (i = 0; i < CM_REQ_HISTORY_SIZE; i++) {
1932 		if (history->index < i)
1933 			idx = CM_REQ_HISTORY_SIZE + history->index - i;
1934 		else
1935 			idx = history->index - i;
1936 
1937 		data = &history->data[idx];
1938 		if (data->cm_id == cm_req->cm_id) {
1939 			data->del_time = qdf_get_log_timestamp();
1940 			data->del_cm_state = cm_get_state(cm_ctx);
1941 			data->del_type = del_type;
1942 			break;
1943 		}
1944 
1945 		if (!data->cm_id)
1946 			break;
1947 	}
1948 	qdf_spin_unlock_bh(&history->cm_req_hist_lock);
1949 }
1950 
1951 void cm_req_history_init(struct cnx_mgr *cm_ctx)
1952 {
1953 	qdf_mem_zero(&cm_ctx->req_history, sizeof(struct cm_req_history));
1954 	qdf_spinlock_create(&cm_ctx->req_history.cm_req_hist_lock);
1955 }
1956 
1957 void cm_req_history_deinit(struct cnx_mgr *cm_ctx)
1958 {
1959 	qdf_spinlock_destroy(&cm_ctx->req_history.cm_req_hist_lock);
1960 }
1961 
1962 static inline void cm_req_history_print_entry(uint16_t idx,
1963 					      struct cm_req_history_info *data)
1964 {
1965 	if (!data->cm_id)
1966 		return;
1967 
1968 	mlme_nofl_err("    |%6u | 0x%016llx | 0x%016llx |%12s | 0x%08x |%15s |%15s |%8u",
1969 		      idx, data->add_time, data->del_time,
1970 		      cm_id_to_string(data->cm_id), data->cm_id,
1971 		      cm_sm_info[data->add_cm_state].name,
1972 		      cm_sm_info[data->del_cm_state].name,
1973 		      data->del_type);
1974 }
1975 
1976 void cm_req_history_print(struct cnx_mgr *cm_ctx)
1977 {
1978 	struct cm_req_history *history = &cm_ctx->req_history;
1979 	uint8_t i, idx;
1980 
1981 	mlme_nofl_err("CM Request history is as below");
1982 	mlme_nofl_err("|%6s |%19s |%19s |%12s |%11s |%15s |%15s |%8s",
1983 		      "Index", "Add Time", "Del Time", "Req type",
1984 		      "Cm Id", "Add State", "Del State", "Del Type");
1985 
1986 	qdf_spin_lock_bh(&history->cm_req_hist_lock);
1987 	for (i = 0; i < CM_REQ_HISTORY_SIZE; i++) {
1988 		idx = (history->index + i) % CM_REQ_HISTORY_SIZE;
1989 		cm_req_history_print_entry(idx, &history->data[idx]);
1990 	}
1991 	qdf_spin_unlock_bh(&history->cm_req_hist_lock);
1992 }
1993 #endif
1994 
1995 #ifndef CONN_MGR_ADV_FEATURE
1996 void cm_set_candidate_advance_filter_cb(
1997 		struct wlan_objmgr_vdev *vdev,
1998 		void (*filter_fun)(struct wlan_objmgr_vdev *vdev,
1999 				   struct scan_filter *filter))
2000 {
2001 	struct cnx_mgr *cm_ctx;
2002 
2003 	cm_ctx = cm_get_cm_ctx(vdev);
2004 	if (!cm_ctx)
2005 		return;
2006 
2007 	cm_ctx->cm_candidate_advance_filter = filter_fun;
2008 }
2009 
2010 void cm_set_candidate_custom_sort_cb(
2011 		struct wlan_objmgr_vdev *vdev,
2012 		void (*sort_fun)(struct wlan_objmgr_vdev *vdev,
2013 				 qdf_list_t *list))
2014 {
2015 	struct cnx_mgr *cm_ctx;
2016 
2017 	cm_ctx = cm_get_cm_ctx(vdev);
2018 	if (!cm_ctx)
2019 		return;
2020 
2021 	cm_ctx->cm_candidate_list_custom_sort = sort_fun;
2022 }
2023 #endif
2024 
2025 #ifdef CONN_MGR_ADV_FEATURE
2026 #define CM_MIN_CANDIDATE_NUM 1
2027 
2028 /**
2029  * cm_fill_connect_ies_from_rsp() - fill connect ies from response structure
2030  * @first_cand_rsp: first candidate connect failure response
2031  * @rsp: connect response
2032  *
2033  * This API fills roaming info for first candidate failure response from the
2034  * provided response.
2035  *
2036  * Return: void
2037  */
2038 static
2039 void cm_fill_connect_ies_from_rsp(struct wlan_cm_connect_resp *first_cand_rsp,
2040 				  struct wlan_cm_connect_resp *rsp)
2041 {
2042 	struct wlan_connect_rsp_ies *connect_ies;
2043 
2044 	connect_ies = &first_cand_rsp->connect_ies;
2045 
2046 	connect_ies->bcn_probe_rsp.ptr = NULL;
2047 	connect_ies->link_bcn_probe_rsp.ptr = NULL;
2048 	connect_ies->assoc_req.ptr = NULL;
2049 	connect_ies->assoc_rsp.ptr = NULL;
2050 
2051 	/* Beacon/Probe Rsp frame */
2052 	if (rsp->connect_ies.bcn_probe_rsp.ptr &&
2053 	    rsp->connect_ies.bcn_probe_rsp.len) {
2054 		connect_ies->bcn_probe_rsp.ptr =
2055 			qdf_mem_malloc(rsp->connect_ies.bcn_probe_rsp.len);
2056 		if (connect_ies->bcn_probe_rsp.ptr)
2057 			qdf_mem_copy(connect_ies->bcn_probe_rsp.ptr,
2058 				     rsp->connect_ies.bcn_probe_rsp.ptr,
2059 				     rsp->connect_ies.bcn_probe_rsp.len);
2060 		else
2061 			connect_ies->bcn_probe_rsp.len = 0;
2062 	}
2063 
2064 	/* Link Beacon/Probe Rsp frame */
2065 	if (rsp->connect_ies.link_bcn_probe_rsp.ptr &&
2066 	    rsp->connect_ies.link_bcn_probe_rsp.len) {
2067 		connect_ies->link_bcn_probe_rsp.ptr =
2068 			qdf_mem_malloc(rsp->connect_ies.link_bcn_probe_rsp.len);
2069 		if (connect_ies->link_bcn_probe_rsp.ptr)
2070 			qdf_mem_copy(connect_ies->link_bcn_probe_rsp.ptr,
2071 				     rsp->connect_ies.link_bcn_probe_rsp.ptr,
2072 				     rsp->connect_ies.link_bcn_probe_rsp.len);
2073 		else
2074 			connect_ies->link_bcn_probe_rsp.len = 0;
2075 	}
2076 
2077 	/* Assoc Req IE data */
2078 	if (rsp->connect_ies.assoc_req.ptr &&
2079 	    rsp->connect_ies.assoc_req.len) {
2080 		connect_ies->assoc_req.ptr =
2081 				qdf_mem_malloc(rsp->connect_ies.assoc_req.len);
2082 		if (connect_ies->assoc_req.ptr)
2083 			qdf_mem_copy(connect_ies->assoc_req.ptr,
2084 				     rsp->connect_ies.assoc_req.ptr,
2085 				     rsp->connect_ies.assoc_req.len);
2086 		else
2087 			connect_ies->assoc_req.len = 0;
2088 	}
2089 
2090 	/* Assoc Rsp IE data */
2091 	if (rsp->connect_ies.assoc_rsp.ptr &&
2092 	    rsp->connect_ies.assoc_rsp.len) {
2093 		connect_ies->assoc_rsp.ptr =
2094 				qdf_mem_malloc(rsp->connect_ies.assoc_rsp.len);
2095 		if (connect_ies->assoc_rsp.ptr)
2096 			qdf_mem_copy(connect_ies->assoc_rsp.ptr,
2097 				     rsp->connect_ies.assoc_rsp.ptr,
2098 				     rsp->connect_ies.assoc_rsp.len);
2099 		else
2100 			connect_ies->assoc_rsp.len = 0;
2101 	}
2102 }
2103 
2104 /**
2105  * cm_copy_rsp_from_rsp() - copy response from other response
2106  * @destination_rsp: destination connect response
2107  * @source_rsp: source connect response
2108  *
2109  * This API copies source response to destination response.
2110  *
2111  * Return: void
2112  */
2113 static
2114 void cm_copy_rsp_from_rsp(struct wlan_cm_connect_resp *destination_rsp,
2115 			  struct wlan_cm_connect_resp *source_rsp)
2116 {
2117 	*destination_rsp = *source_rsp;
2118 	cm_fill_connect_ies_from_rsp(destination_rsp, source_rsp);
2119 }
2120 
2121 void cm_store_first_candidate_rsp(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id,
2122 				  struct wlan_cm_connect_resp *resp)
2123 {
2124 	struct wlan_cm_connect_resp *first_candid_rsp;
2125 	uint8_t num_candidates;
2126 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
2127 	struct cm_req *cm_req;
2128 	uint32_t prefix = CM_ID_GET_PREFIX(cm_id);
2129 
2130 	if (prefix != CONNECT_REQ_PREFIX)
2131 		return;
2132 
2133 	cm_req_lock_acquire(cm_ctx);
2134 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
2135 	while (cur_node) {
2136 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
2137 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
2138 
2139 		if (cm_req->cm_id == cm_id) {
2140 			/*
2141 			 * Do not cache response if first candidate response is
2142 			 * already stored. "first_candidate_rsp" pointer is
2143 			 * freed once connect request is completed and freed.
2144 			 */
2145 			if (cm_req->connect_req.first_candidate_rsp)
2146 				break;
2147 
2148 			/* only cached for more than one candidate */
2149 			num_candidates = qdf_list_size(
2150 					cm_req->connect_req.candidate_list);
2151 			if (num_candidates <= CM_MIN_CANDIDATE_NUM)
2152 				break;
2153 
2154 			first_candid_rsp = qdf_mem_malloc(
2155 						sizeof(*first_candid_rsp));
2156 			if (!first_candid_rsp)
2157 				break;
2158 
2159 			cm_copy_rsp_from_rsp(first_candid_rsp, resp);
2160 			cm_req->connect_req.first_candidate_rsp =
2161 							first_candid_rsp;
2162 			mlme_debug(CM_PREFIX_FMT " " QDF_MAC_ADDR_FMT " with reason %d",
2163 				   CM_PREFIX_REF(first_candid_rsp->vdev_id,
2164 						 cm_id),
2165 				QDF_MAC_ADDR_REF(first_candid_rsp->bssid.bytes),
2166 				first_candid_rsp->reason);
2167 			break;
2168 		}
2169 
2170 		cur_node = next_node;
2171 		next_node = NULL;
2172 	}
2173 
2174 	cm_req_lock_release(cm_ctx);
2175 }
2176 
2177 QDF_STATUS
2178 cm_get_first_candidate_rsp(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id,
2179 			   struct wlan_cm_connect_resp *first_candid_rsp)
2180 {
2181 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
2182 	struct cm_req *cm_req;
2183 	uint32_t prefix = CM_ID_GET_PREFIX(cm_id);
2184 
2185 	if (prefix != CONNECT_REQ_PREFIX)
2186 		return QDF_STATUS_E_INVAL;
2187 
2188 	cm_req_lock_acquire(cm_ctx);
2189 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
2190 	while (cur_node) {
2191 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
2192 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
2193 
2194 		if (cm_req->cm_id == cm_id) {
2195 			if (!cm_req->connect_req.first_candidate_rsp)
2196 				break;
2197 
2198 			cm_copy_rsp_from_rsp(first_candid_rsp,
2199 				cm_req->connect_req.first_candidate_rsp);
2200 
2201 			mlme_debug(CM_PREFIX_FMT " " QDF_MAC_ADDR_FMT "with reason %d",
2202 				   CM_PREFIX_REF(first_candid_rsp->vdev_id,
2203 						 cm_id),
2204 				QDF_MAC_ADDR_REF(first_candid_rsp->bssid.bytes),
2205 				first_candid_rsp->reason);
2206 
2207 			cm_req_lock_release(cm_ctx);
2208 			return QDF_STATUS_SUCCESS;
2209 		}
2210 
2211 		cur_node = next_node;
2212 		next_node = NULL;
2213 	}
2214 
2215 	cm_req_lock_release(cm_ctx);
2216 	return QDF_STATUS_E_FAILURE;
2217 }
2218 
2219 void cm_store_n_send_failed_candidate(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id)
2220 {
2221 	struct wlan_cm_connect_resp resp = {0};
2222 
2223 	cm_fill_failure_resp_from_cm_id(cm_ctx, &resp, cm_id,
2224 					CM_VALID_CANDIDATE_CHECK_FAIL);
2225 	cm_store_first_candidate_rsp(cm_ctx, cm_id, &resp);
2226 	mlme_cm_osif_failed_candidate_ind(cm_ctx->vdev, &resp);
2227 }
2228 #endif /* CONN_MGR_ADV_FEATURE */
2229