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