xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlme/connection_mgr/core/src/wlan_cm_util.c (revision 878d42c770e8f4f39f616b20412de44faeced7b9)
1 /*
2  * Copyright (c) 2012-2015, 2020-2021, The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /**
18  * DOC: Implements general util apis of connection manager
19  */
20 
21 #include "wlan_cm_main_api.h"
22 #include "wlan_scan_api.h"
23 #include "wlan_cm_public_struct.h"
24 #include "wlan_serialization_api.h"
25 #include "wlan_cm_bss_score_param.h"
26 #ifdef WLAN_POLICY_MGR_ENABLE
27 #include <wlan_policy_mgr_api.h>
28 #endif
29 #include "wlan_cm_roam.h"
30 
31 static uint32_t cm_get_prefix_for_cm_id(enum wlan_cm_source source) {
32 	switch (source) {
33 	case CM_OSIF_CONNECT:
34 	case CM_OSIF_CFG_CONNECT:
35 		return CONNECT_REQ_PREFIX;
36 	case CM_ROAMING_HOST:
37 	case CM_ROAMING_FW:
38 	case CM_ROAMING_NUD_FAILURE:
39 		return ROAM_REQ_PREFIX;
40 	default:
41 		return DISCONNECT_REQ_PREFIX;
42 	}
43 }
44 
45 wlan_cm_id cm_get_cm_id(struct cnx_mgr *cm_ctx, enum wlan_cm_source source)
46 {
47 	wlan_cm_id cmd_id;
48 	uint32_t prefix;
49 
50 	prefix = cm_get_prefix_for_cm_id(source);
51 
52 	cmd_id = qdf_atomic_inc_return(&cm_ctx->global_cmd_id);
53 	cmd_id = (cmd_id & CM_ID_MASK);
54 	cmd_id = (cmd_id | prefix);
55 
56 	return cmd_id;
57 }
58 
59 struct cnx_mgr *cm_get_cm_ctx_fl(struct wlan_objmgr_vdev *vdev,
60 				 const char *func, uint32_t line)
61 {
62 	struct vdev_mlme_obj *vdev_mlme;
63 	struct cnx_mgr *cm_ctx = NULL;
64 
65 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
66 	if (vdev_mlme)
67 		cm_ctx = vdev_mlme->cnx_mgr_ctx;
68 
69 	if (!cm_ctx)
70 		mlme_nofl_err("%s:%u: vdev %d cm_ctx is NULL", func, line,
71 			      wlan_vdev_get_id(vdev));
72 
73 	return cm_ctx;
74 }
75 
76 cm_ext_t *cm_get_ext_hdl_fl(struct wlan_objmgr_vdev *vdev,
77 			    const char *func, uint32_t line)
78 {
79 	struct cnx_mgr *cm_ctx;
80 	cm_ext_t *ext_ctx = NULL;
81 
82 	cm_ctx = cm_get_cm_ctx_fl(vdev, func, line);
83 	if (cm_ctx)
84 		ext_ctx = cm_ctx->ext_cm_ptr;
85 
86 	if (!ext_ctx)
87 		mlme_nofl_err("%s:%u: vdev %d cm ext ctx is NULL", func, line,
88 			      wlan_vdev_get_id(vdev));
89 	return ext_ctx;
90 }
91 
92 void cm_reset_active_cm_id(struct wlan_objmgr_vdev *vdev, wlan_cm_id cm_id)
93 {
94 	struct cnx_mgr *cm_ctx;
95 
96 	cm_ctx = cm_get_cm_ctx(vdev);
97 	if (!cm_ctx)
98 		return;
99 
100 	/* Reset active cm id if cm id match */
101 	if (cm_ctx->active_cm_id == cm_id)
102 		cm_ctx->active_cm_id = CM_ID_INVALID;
103 }
104 
105 
106 #ifdef WLAN_CM_USE_SPINLOCK
107 /**
108  * cm_req_lock_acquire - acquire CM SM mutex/spinlock
109  * @cm_ctx:  connection manager ctx
110  *
111  * acquire CM SM mutex/spinlock
112  *
113  * return: void
114  */
115 inline void cm_req_lock_acquire(struct cnx_mgr *cm_ctx)
116 {
117 	qdf_spinlock_acquire(&cm_ctx->cm_req_lock);
118 }
119 
120 /**
121  * cm_req_lock_release - release CM SM mutex/spinlock
122  * @cm_ctx:  connection manager ctx
123  *
124  * release CM SM mutex/spinlock
125  *
126  * return: void
127  */
128 inline void cm_req_lock_release(struct cnx_mgr *cm_ctx)
129 {
130 	qdf_spinlock_release(&cm_ctx->cm_req_lock);
131 }
132 
133 QDF_STATUS cm_activate_cmd_req_flush_cb(struct scheduler_msg *msg)
134 {
135 	struct wlan_serialization_command *cmd = msg->bodyptr;
136 
137 	if (!cmd || !cmd->vdev) {
138 		mlme_err("Null input cmd:%pK", cmd);
139 		return QDF_STATUS_E_INVAL;
140 	}
141 
142 	wlan_objmgr_vdev_release_ref(cmd->vdev, WLAN_MLME_CM_ID);
143 	return QDF_STATUS_SUCCESS;
144 }
145 
146 #else
147 inline void cm_req_lock_acquire(struct cnx_mgr *cm_ctx)
148 {
149 	qdf_mutex_acquire(&cm_ctx->cm_req_lock);
150 }
151 
152 inline void cm_req_lock_release(struct cnx_mgr *cm_ctx)
153 {
154 	qdf_mutex_release(&cm_ctx->cm_req_lock);
155 }
156 #endif /* WLAN_CM_USE_SPINLOCK */
157 
158 #ifdef CRYPTO_SET_KEY_CONVERGED
159 QDF_STATUS cm_set_key(struct cnx_mgr *cm_ctx, bool unicast,
160 		      uint8_t key_idx, struct qdf_mac_addr *bssid)
161 {
162 	enum wlan_crypto_cipher_type cipher;
163 	struct wlan_crypto_key *crypto_key;
164 	uint8_t wep_key_idx = 0;
165 
166 	cipher = wlan_crypto_get_cipher(cm_ctx->vdev, unicast, key_idx);
167 	if (IS_WEP_CIPHER(cipher)) {
168 		wep_key_idx = wlan_crypto_get_default_key_idx(cm_ctx->vdev,
169 							      !unicast);
170 		crypto_key = wlan_crypto_get_key(cm_ctx->vdev, wep_key_idx);
171 		qdf_mem_copy(crypto_key->macaddr, bssid->bytes,
172 			     QDF_MAC_ADDR_SIZE);
173 	} else {
174 		crypto_key = wlan_crypto_get_key(cm_ctx->vdev, key_idx);
175 	}
176 
177 	return wlan_crypto_set_key_req(cm_ctx->vdev, crypto_key, (unicast ?
178 				       WLAN_CRYPTO_KEY_TYPE_UNICAST :
179 				       WLAN_CRYPTO_KEY_TYPE_GROUP));
180 }
181 #endif
182 
183 #ifdef CONN_MGR_ADV_FEATURE
184 void cm_store_wep_key(struct cnx_mgr *cm_ctx,
185 		      struct wlan_cm_connect_crypto_info *crypto,
186 		      wlan_cm_id cm_id)
187 {
188 	struct wlan_crypto_key *crypto_key = NULL;
189 	QDF_STATUS status;
190 	enum wlan_crypto_cipher_type cipher_type;
191 	struct wlan_cm_wep_key_params *wep_keys;
192 
193 	if (!(crypto->ciphers_pairwise & (1 << WLAN_CRYPTO_CIPHER_WEP_40 |
194 					  1 << WLAN_CRYPTO_CIPHER_WEP_104)))
195 		return;
196 
197 	if (crypto->ciphers_pairwise & 1 << WLAN_CRYPTO_CIPHER_WEP_40)
198 		cipher_type = WLAN_CRYPTO_CIPHER_WEP_40;
199 	else
200 		cipher_type = WLAN_CRYPTO_CIPHER_WEP_104;
201 
202 	wep_keys = &crypto->wep_keys;
203 	status = wlan_crypto_validate_key_params(cipher_type,
204 						 wep_keys->key_idx,
205 						 wep_keys->key_len,
206 						 wep_keys->seq_len);
207 	if (QDF_IS_STATUS_ERROR(status)) {
208 		mlme_err(CM_PREFIX_FMT "Invalid key params",
209 			 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), cm_id));
210 		return;
211 	}
212 
213 	crypto_key = wlan_crypto_get_key(cm_ctx->vdev, wep_keys->key_idx);
214 	if (!crypto_key) {
215 		crypto_key = qdf_mem_malloc(sizeof(*crypto_key));
216 		if (!crypto_key)
217 			return;
218 
219 		status = wlan_crypto_save_key(cm_ctx->vdev, wep_keys->key_idx,
220 					      crypto_key);
221 		if (QDF_IS_STATUS_ERROR(status)) {
222 			mlme_err(CM_PREFIX_FMT "Failed to save key",
223 				 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
224 					       cm_id));
225 			qdf_mem_free(crypto_key);
226 			return;
227 		}
228 	}
229 	qdf_mem_zero(crypto_key, sizeof(*crypto_key));
230 	crypto_key->cipher_type = cipher_type;
231 	crypto_key->keylen = wep_keys->key_len;
232 	crypto_key->keyix = wep_keys->key_idx;
233 	qdf_mem_copy(&crypto_key->keyval[0], wep_keys->key, wep_keys->key_len);
234 	qdf_mem_copy(&crypto_key->keyrsc[0], wep_keys->seq, wep_keys->seq_len);
235 	mlme_debug(CM_PREFIX_FMT "cipher_type %d key_len %d, seq_len %d",
236 		   CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), cm_id),
237 		   crypto_key->cipher_type, wep_keys->key_len,
238 		   wep_keys->seq_len);
239 }
240 #endif
241 
242 #ifdef WLAN_FEATURE_FILS_SK
243 void cm_store_fils_key(struct cnx_mgr *cm_ctx, bool unicast,
244 		       uint8_t key_id, uint16_t key_length,
245 		       uint8_t *key, struct qdf_mac_addr *bssid,
246 		       wlan_cm_id cm_id)
247 {
248 	struct wlan_crypto_key *crypto_key = NULL;
249 	QDF_STATUS status;
250 	uint8_t i;
251 	int32_t cipher;
252 	enum wlan_crypto_cipher_type cipher_type = WLAN_CRYPTO_CIPHER_NONE;
253 
254 	if (unicast)
255 		cipher = wlan_crypto_get_param(cm_ctx->vdev,
256 					       WLAN_CRYPTO_PARAM_UCAST_CIPHER);
257 	else
258 		cipher = wlan_crypto_get_param(cm_ctx->vdev,
259 					       WLAN_CRYPTO_PARAM_MCAST_CIPHER);
260 
261 	for (i = 0; i <= WLAN_CRYPTO_CIPHER_MAX; i++) {
262 		if (QDF_HAS_PARAM(cipher, i)) {
263 			cipher_type = i;
264 			break;
265 		}
266 	}
267 	crypto_key = wlan_crypto_get_key(cm_ctx->vdev, key_id);
268 	if (!crypto_key) {
269 		crypto_key = qdf_mem_malloc(sizeof(*crypto_key));
270 		if (!crypto_key)
271 			return;
272 		status = wlan_crypto_save_key(cm_ctx->vdev, key_id, crypto_key);
273 		if (QDF_IS_STATUS_ERROR(status)) {
274 			mlme_err(CM_PREFIX_FMT "Failed to save key",
275 				 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
276 					       cm_id));
277 			qdf_mem_free(crypto_key);
278 			return;
279 		}
280 	}
281 	qdf_mem_zero(crypto_key, sizeof(*crypto_key));
282 	crypto_key->cipher_type = cipher_type;
283 	crypto_key->keylen = key_length;
284 	crypto_key->keyix = key_id;
285 	qdf_mem_copy(&crypto_key->keyval[0], key, key_length);
286 	qdf_mem_copy(crypto_key->macaddr, bssid->bytes, QDF_MAC_ADDR_SIZE);
287 	mlme_debug(CM_PREFIX_FMT "cipher_type %d key_len %d, key_id %d mac:" QDF_MAC_ADDR_FMT,
288 		   CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), cm_id),
289 		   crypto_key->cipher_type, crypto_key->keylen,
290 		   crypto_key->keyix, QDF_MAC_ADDR_REF(crypto_key->macaddr));
291 }
292 static void cm_set_fils_connection_from_req(struct wlan_cm_connect_req *req,
293 					    struct wlan_cm_connect_resp *resp)
294 {
295 	resp->is_fils_connection = req->fils_info.is_fils_connection;
296 }
297 #else
298 static inline
299 void cm_set_fils_connection_from_req(struct wlan_cm_connect_req *req,
300 				     struct wlan_cm_connect_resp *resp)
301 {}
302 #endif
303 
304 bool cm_check_cmid_match_list_head(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
305 {
306 	qdf_list_node_t *cur_node = NULL;
307 	struct cm_req *cm_req;
308 	bool match = false;
309 	wlan_cm_id head_cm_id = 0;
310 
311 	if (!cm_id)
312 		return false;
313 
314 	cm_req_lock_acquire(cm_ctx);
315 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
316 	if (!cur_node)
317 		goto exit;
318 
319 	cm_req = qdf_container_of(cur_node, struct cm_req, node);
320 	head_cm_id = cm_req->cm_id;
321 	if (head_cm_id == *cm_id)
322 		match = true;
323 
324 exit:
325 	cm_req_lock_release(cm_ctx);
326 	if (!match)
327 		mlme_info("head_cm_id 0x%x didn't match the given cm_id 0x%x",
328 			  head_cm_id, *cm_id);
329 
330 	return match;
331 }
332 
333 bool cm_check_scanid_match_list_head(struct cnx_mgr *cm_ctx,
334 				     wlan_scan_id *scan_id)
335 {
336 	qdf_list_node_t *cur_node = NULL;
337 	struct cm_req *cm_req;
338 	bool match = false;
339 	wlan_cm_id head_scan_id = 0;
340 	uint32_t prefix = 0;
341 
342 	if (!scan_id)
343 		return false;
344 
345 	cm_req_lock_acquire(cm_ctx);
346 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
347 	if (!cur_node)
348 		goto exit;
349 
350 	cm_req = qdf_container_of(cur_node, struct cm_req, node);
351 	prefix = CM_ID_GET_PREFIX(cm_req->cm_id);
352 	/* Check only if head is connect req */
353 	if (prefix != CONNECT_REQ_PREFIX)
354 		goto exit;
355 	head_scan_id = cm_req->connect_req.scan_id;
356 	if (head_scan_id == *scan_id)
357 		match = true;
358 
359 exit:
360 	cm_req_lock_release(cm_ctx);
361 	if (!match)
362 		mlme_info("head_scan_id 0x%x didn't match the given scan_id 0x%x prefix 0x%x",
363 			  head_scan_id, *scan_id, prefix);
364 
365 	return match;
366 }
367 
368 struct cm_req *cm_get_req_by_cm_id_fl(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id,
369 				      const char *func, uint32_t line)
370 {
371 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
372 	struct cm_req * cm_req;
373 
374 	cm_req_lock_acquire(cm_ctx);
375 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
376 	while (cur_node) {
377 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
378 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
379 
380 		if (cm_req->cm_id == cm_id) {
381 			cm_req_lock_release(cm_ctx);
382 			return cm_req;
383 		}
384 
385 		cur_node = next_node;
386 		next_node = NULL;
387 	}
388 	cm_req_lock_release(cm_ctx);
389 
390 	mlme_nofl_info("%s:%u: cm req not found for cm id 0x%x", func,
391 		       line, cm_id);
392 
393 	return NULL;
394 }
395 
396 /**
397  * cm_fill_connect_resp_from_req() - Fill connect resp from connect request
398  * @resp: cm connect response
399  * @cm_req: cm request
400  *
401  * Context: Can be called from APIs holding cm request list lock
402  *
403  * Return: void
404  */
405 static void
406 cm_fill_connect_resp_from_req(struct wlan_cm_connect_resp *resp,
407 			      struct cm_req *cm_req)
408 {
409 	struct scan_cache_node *candidate;
410 	struct wlan_cm_connect_req *req;
411 
412 	req = &cm_req->connect_req.req;
413 	candidate = cm_req->connect_req.cur_candidate;
414 	if (candidate)
415 		qdf_copy_macaddr(&resp->bssid, &candidate->entry->bssid);
416 	else if (!qdf_is_macaddr_zero(&req->bssid))
417 		qdf_copy_macaddr(&resp->bssid, &req->bssid);
418 	else
419 		qdf_copy_macaddr(&resp->bssid, &req->bssid_hint);
420 
421 	if (candidate)
422 		resp->freq = candidate->entry->channel.chan_freq;
423 	else
424 		resp->freq = req->chan_freq;
425 
426 	resp->ssid = req->ssid;
427 	resp->is_wps_connection = req->is_wps_connection;
428 	resp->is_osen_connection = req->is_osen_connection;
429 	cm_set_fils_connection_from_req(req, resp);
430 }
431 
432 /**
433  * cm_handle_connect_flush() - Fill fail connect resp from req and indicate
434  * same to osif
435  * @cm_ctx: connection manager context
436  * @cm_req: cm request
437  *
438  * Context: Can be called from APIs holding cm request list lock
439  *
440  * Return: void
441  */
442 static void
443 cm_handle_connect_flush(struct cnx_mgr *cm_ctx, struct cm_req *cm_req)
444 {
445 	struct wlan_cm_connect_resp *resp;
446 
447 	resp = qdf_mem_malloc(sizeof(*resp));
448 	if (!resp)
449 		return;
450 
451 	resp->connect_status = QDF_STATUS_E_FAILURE;
452 	resp->cm_id = cm_req->cm_id;
453 	resp->vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
454 	resp->reason = CM_ABORT_DUE_TO_NEW_REQ_RECVD;
455 
456 	/* Get bssid and ssid and freq for the cm id from the req list */
457 	cm_fill_connect_resp_from_req(resp, cm_req);
458 
459 	mlme_cm_osif_connect_complete(cm_ctx->vdev, resp);
460 	qdf_mem_free(resp);
461 }
462 
463 /**
464  * cm_handle_disconnect_flush() - Fill disconnect resp from req and indicate
465  * same to osif
466  * @cm_ctx: connection manager context
467  * @cm_req: cm request
468  *
469  * Context: Can be called from APIs holding cm request list lock
470  *
471  * Return: void
472  */
473 static void
474 cm_handle_disconnect_flush(struct cnx_mgr *cm_ctx, struct cm_req *cm_req)
475 {
476 	struct wlan_cm_discon_rsp resp;
477 
478 	qdf_mem_zero(&resp, sizeof(resp));
479 	resp.req.cm_id = cm_req->cm_id;
480 	resp.req.req = cm_req->discon_req.req;
481 
482 	mlme_cm_osif_disconnect_complete(cm_ctx->vdev, &resp);
483 }
484 
485 static void cm_remove_cmd_from_serialization(struct cnx_mgr *cm_ctx,
486 					     wlan_cm_id cm_id)
487 {
488 	struct wlan_serialization_queued_cmd_info cmd_info;
489 	uint32_t prefix = CM_ID_GET_PREFIX(cm_id);
490 
491 	qdf_mem_zero(&cmd_info, sizeof(cmd_info));
492 	cmd_info.cmd_id = cm_id;
493 	cmd_info.req_type = WLAN_SER_CANCEL_NON_SCAN_CMD;
494 
495 	if (prefix == CONNECT_REQ_PREFIX) {
496 		cmd_info.cmd_type = WLAN_SER_CMD_VDEV_CONNECT;
497 	} else if (prefix == ROAM_REQ_PREFIX) {
498 		/*
499 		 * Try removing PREAUTH command when in preauth state else
500 		 * try remove ROAM command
501 		 */
502 		if (cm_ctx->preauth_in_progress)
503 			cmd_info.cmd_type = WLAN_SER_CMD_PERFORM_PRE_AUTH;
504 		else
505 			cmd_info.cmd_type = WLAN_SER_CMD_VDEV_ROAM;
506 		cm_ctx->preauth_in_progress = false;
507 	} else {
508 		cmd_info.cmd_type = WLAN_SER_CMD_VDEV_DISCONNECT;
509 	}
510 
511 	cmd_info.vdev = cm_ctx->vdev;
512 
513 	if (cm_id == cm_ctx->active_cm_id) {
514 		mlme_debug(CM_PREFIX_FMT "Remove cmd type %d from active",
515 			   CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), cm_id),
516 			   cmd_info.cmd_type);
517 		cmd_info.queue_type = WLAN_SERIALIZATION_ACTIVE_QUEUE;
518 		wlan_serialization_remove_cmd(&cmd_info);
519 	} else {
520 		mlme_debug(CM_PREFIX_FMT "Remove cmd type %d from pending",
521 			   CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), cm_id),
522 			   cmd_info.cmd_type);
523 		cmd_info.queue_type = WLAN_SERIALIZATION_PENDING_QUEUE;
524 		wlan_serialization_cancel_request(&cmd_info);
525 	}
526 }
527 
528 void
529 cm_flush_pending_request(struct cnx_mgr *cm_ctx, uint32_t prefix,
530 			 bool only_failed_req)
531 {
532 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
533 	struct cm_req *cm_req;
534 	uint32_t req_prefix;
535 	bool roam_offload = false;
536 
537 	if (cm_roam_offload_enabled(wlan_vdev_get_psoc(cm_ctx->vdev)) &&
538 	     prefix == ROAM_REQ_PREFIX)
539 		roam_offload = true;
540 
541 	cm_req_lock_acquire(cm_ctx);
542 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
543 	while (cur_node) {
544 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
545 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
546 
547 		req_prefix = CM_ID_GET_PREFIX(cm_req->cm_id);
548 
549 		/*
550 		 * Only remove requests matching the flush prefix and
551 		 * the pending req for non roam offload(LFR3) commands
552 		 * (roam command is dummy in FW roam/LFR3 so active
553 		 * command can be removed)
554 		 */
555 		if (req_prefix != prefix ||
556 		    (!roam_offload && cm_req->cm_id == cm_ctx->active_cm_id))
557 			goto next;
558 
559 		/* If only_failed_req is set flush only failed req */
560 		if (only_failed_req && !cm_req->failed_req)
561 			goto next;
562 
563 		if (req_prefix == CONNECT_REQ_PREFIX) {
564 			cm_handle_connect_flush(cm_ctx, cm_req);
565 			cm_ctx->connect_count--;
566 			cm_free_connect_req_mem(&cm_req->connect_req);
567 		} else if (req_prefix == ROAM_REQ_PREFIX) {
568 			cm_free_roam_req_mem(&cm_req->roam_req);
569 		} else {
570 			cm_handle_disconnect_flush(cm_ctx, cm_req);
571 			cm_ctx->disconnect_count--;
572 		}
573 
574 		cm_req_history_del(cm_ctx, cm_req, CM_REQ_DEL_FLUSH);
575 		mlme_debug(CM_PREFIX_FMT,
576 			   CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
577 					 cm_req->cm_id));
578 		cm_remove_cmd_from_serialization(cm_ctx, cm_req->cm_id);
579 		qdf_list_remove_node(&cm_ctx->req_list, &cm_req->node);
580 		qdf_mem_free(cm_req);
581 next:
582 		cur_node = next_node;
583 		next_node = NULL;
584 	}
585 
586 	cm_req_lock_release(cm_ctx);
587 }
588 
589 QDF_STATUS
590 cm_fill_bss_info_in_connect_rsp_by_cm_id(struct cnx_mgr *cm_ctx,
591 					 wlan_cm_id cm_id,
592 					 struct wlan_cm_connect_resp *resp)
593 {
594 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
595 	struct cm_req *cm_req;
596 	uint32_t prefix = CM_ID_GET_PREFIX(cm_id);
597 
598 	if (prefix != CONNECT_REQ_PREFIX)
599 		return QDF_STATUS_E_INVAL;
600 
601 	cm_req_lock_acquire(cm_ctx);
602 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
603 	while (cur_node) {
604 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
605 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
606 
607 		if (cm_req->cm_id == cm_id) {
608 			cm_fill_connect_resp_from_req(resp, cm_req);
609 			cm_req_lock_release(cm_ctx);
610 			return QDF_STATUS_SUCCESS;
611 		}
612 
613 		cur_node = next_node;
614 		next_node = NULL;
615 	}
616 	cm_req_lock_release(cm_ctx);
617 
618 	return QDF_STATUS_E_FAILURE;
619 }
620 
621 #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
622 bool cm_is_cm_id_current_candidate_single_pmk(struct cnx_mgr *cm_ctx,
623 					      wlan_cm_id cm_id)
624 {
625 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
626 	struct cm_req *cm_req;
627 	uint32_t prefix = CM_ID_GET_PREFIX(cm_id);
628 	struct scan_cache_node *candidate;
629 	bool is_single_pmk = false;
630 
631 	if (prefix != CONNECT_REQ_PREFIX)
632 		return is_single_pmk;
633 
634 	cm_req_lock_acquire(cm_ctx);
635 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
636 	while (cur_node) {
637 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
638 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
639 
640 		if (cm_req->cm_id == cm_id) {
641 			candidate = cm_req->connect_req.cur_candidate;
642 			if (candidate &&
643 			    util_scan_entry_single_pmk(candidate->entry))
644 				is_single_pmk = true;
645 			break;
646 		}
647 
648 		cur_node = next_node;
649 		next_node = NULL;
650 	}
651 	cm_req_lock_release(cm_ctx);
652 
653 	return is_single_pmk;
654 }
655 #endif
656 
657 QDF_STATUS cm_add_req_to_list_and_indicate_osif(struct cnx_mgr *cm_ctx,
658 						struct cm_req *cm_req,
659 						enum wlan_cm_source source)
660 {
661 	uint32_t prefix = CM_ID_GET_PREFIX(cm_req->cm_id);
662 
663 	cm_req_lock_acquire(cm_ctx);
664 	if (qdf_list_size(&cm_ctx->req_list) >= CM_MAX_REQ) {
665 		cm_req_lock_release(cm_ctx);
666 		mlme_err(CM_PREFIX_FMT "List full size %d",
667 			 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
668 				       cm_req->cm_id),
669 			 qdf_list_size(&cm_ctx->req_list));
670 		return QDF_STATUS_E_FAILURE;
671 	}
672 
673 	qdf_list_insert_front(&cm_ctx->req_list, &cm_req->node);
674 	if (prefix == CONNECT_REQ_PREFIX)
675 		cm_ctx->connect_count++;
676 	else if (prefix == DISCONNECT_REQ_PREFIX)
677 		cm_ctx->disconnect_count++;
678 
679 	cm_req_history_add(cm_ctx, cm_req);
680 	cm_req_lock_release(cm_ctx);
681 	mlme_debug(CM_PREFIX_FMT,
682 		   CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
683 				 cm_req->cm_id));
684 
685 	mlme_cm_osif_update_id_and_src(cm_ctx->vdev, source, cm_req->cm_id);
686 
687 	return QDF_STATUS_SUCCESS;
688 }
689 
690 static void cm_zero_and_free_memory(uint8_t *ptr, uint32_t len)
691 {
692 	if (!ptr)
693 		return;
694 
695 	qdf_mem_zero(ptr, len);
696 	qdf_mem_free(ptr);
697 }
698 
699 void cm_free_connect_req_mem(struct cm_connect_req *connect_req)
700 {
701 	struct wlan_cm_connect_req *req;
702 
703 	req = &connect_req->req;
704 
705 	if (connect_req->candidate_list)
706 		wlan_scan_purge_results(connect_req->candidate_list);
707 
708 	cm_zero_and_free_memory(req->assoc_ie.ptr, req->assoc_ie.len);
709 	cm_zero_and_free_memory(req->scan_ie.ptr, req->scan_ie.len);
710 
711 	cm_zero_and_free_memory(req->crypto.wep_keys.key,
712 				req->crypto.wep_keys.key_len);
713 	cm_zero_and_free_memory(req->crypto.wep_keys.seq,
714 				req->crypto.wep_keys.seq_len);
715 
716 	qdf_mem_zero(connect_req, sizeof(*connect_req));
717 }
718 
719 QDF_STATUS
720 cm_delete_req_from_list(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id)
721 {
722 	uint32_t prefix = CM_ID_GET_PREFIX(cm_id);
723 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
724 	struct cm_req *cm_req = NULL;
725 
726 	cm_req_lock_acquire(cm_ctx);
727 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
728 	while (cur_node) {
729 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
730 
731 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
732 		if (cm_req->cm_id == cm_id)
733 			break;
734 
735 		cur_node = next_node;
736 		next_node = NULL;
737 		cm_req = NULL;
738 	}
739 
740 	if (!cm_req) {
741 		cm_req_lock_release(cm_ctx);
742 		mlme_err(CM_PREFIX_FMT " req not found",
743 			 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), cm_id));
744 		return QDF_STATUS_E_FAILURE;
745 	}
746 
747 	qdf_list_remove_node(&cm_ctx->req_list, &cm_req->node);
748 	if (prefix == CONNECT_REQ_PREFIX) {
749 		cm_ctx->connect_count--;
750 		cm_free_connect_req_mem(&cm_req->connect_req);
751 	} else if (prefix == ROAM_REQ_PREFIX) {
752 		cm_free_roam_req_mem(&cm_req->roam_req);
753 	} else {
754 		cm_ctx->disconnect_count--;
755 	}
756 
757 	if (cm_id == cm_ctx->active_cm_id)
758 		cm_req_history_del(cm_ctx, cm_req, CM_REQ_DEL_ACTIVE);
759 	else
760 		cm_req_history_del(cm_ctx, cm_req, CM_REQ_DEL_PENDING);
761 
762 	mlme_debug(CM_PREFIX_FMT,
763 		   CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
764 				 cm_req->cm_id));
765 
766 	qdf_mem_free(cm_req);
767 	cm_req_lock_release(cm_ctx);
768 
769 	return QDF_STATUS_SUCCESS;
770 }
771 
772 void cm_remove_cmd(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
773 {
774 	struct wlan_objmgr_psoc *psoc;
775 	QDF_STATUS status;
776 
777 	if (!cm_id) {
778 		mlme_err("cmd_id is null");
779 		return;
780 	}
781 
782 	/* return if zero or invalid cm_id */
783 	if (!*cm_id || *cm_id == CM_ID_INVALID) {
784 		mlme_debug(CM_PREFIX_FMT " Invalid cm_id",
785 			   CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
786 					 *cm_id));
787 		return;
788 	}
789 
790 	psoc = wlan_vdev_get_psoc(cm_ctx->vdev);
791 	if (!psoc) {
792 		mlme_err(CM_PREFIX_FMT "Failed to find psoc",
793 			 CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), *cm_id));
794 		return;
795 	}
796 
797 	status = cm_delete_req_from_list(cm_ctx, *cm_id);
798 	if (QDF_IS_STATUS_ERROR(status))
799 		return;
800 
801 	cm_remove_cmd_from_serialization(cm_ctx, *cm_id);
802 }
803 
804 void cm_vdev_scan_cancel(struct wlan_objmgr_pdev *pdev,
805 			 struct wlan_objmgr_vdev *vdev)
806 {
807 	struct scan_cancel_request *req;
808 	QDF_STATUS status;
809 
810 	req = qdf_mem_malloc(sizeof(*req));
811 	if (!req)
812 		return;
813 
814 	req->vdev = vdev;
815 	req->cancel_req.scan_id = INVAL_SCAN_ID;
816 	req->cancel_req.vdev_id = wlan_vdev_get_id(vdev);
817 	req->cancel_req.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
818 	req->cancel_req.req_type = WLAN_SCAN_CANCEL_VDEV_ALL;
819 
820 	status = wlan_scan_cancel(req);
821 	/* In success/failure case wlan_scan_cancel free the req memory */
822 	if (QDF_IS_STATUS_ERROR(status))
823 		mlme_err("vdev %d cancel scan request failed",
824 			 wlan_vdev_get_id(vdev));
825 }
826 
827 void cm_set_max_connect_attempts(struct wlan_objmgr_vdev *vdev,
828 				 uint8_t max_connect_attempts)
829 {
830 	struct cnx_mgr *cm_ctx;
831 
832 	cm_ctx = cm_get_cm_ctx(vdev);
833 	if (!cm_ctx)
834 		return;
835 
836 	cm_ctx->max_connect_attempts =
837 		QDF_MIN(max_connect_attempts, CM_MAX_CONNECT_ATTEMPTS);
838 	mlme_debug("vdev %d max connect attempts set to %d, requested %d",
839 		   wlan_vdev_get_id(vdev),
840 		   cm_ctx->max_connect_attempts, max_connect_attempts);
841 }
842 
843 void cm_set_max_connect_timeout(struct wlan_objmgr_vdev *vdev,
844 				uint32_t max_connect_timeout)
845 {
846 	struct cnx_mgr *cm_ctx;
847 
848 	cm_ctx = cm_get_cm_ctx(vdev);
849 	if (!cm_ctx)
850 		return;
851 
852 	cm_ctx->connect_timeout = max_connect_timeout;
853 }
854 
855 QDF_STATUS
856 cm_fill_disconnect_resp_from_cm_id(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id,
857 				   struct wlan_cm_discon_rsp *resp)
858 {
859 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
860 	struct cm_req *cm_req;
861 	uint32_t prefix = CM_ID_GET_PREFIX(cm_id);
862 
863 	if (prefix != DISCONNECT_REQ_PREFIX)
864 		return QDF_STATUS_E_INVAL;
865 
866 	cm_req_lock_acquire(cm_ctx);
867 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
868 	while (cur_node) {
869 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
870 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
871 
872 		if (cm_req->cm_id == cm_id) {
873 			resp->req.cm_id = cm_id;
874 			resp->req.req = cm_req->discon_req.req;
875 			cm_req_lock_release(cm_ctx);
876 			return QDF_STATUS_SUCCESS;
877 		}
878 
879 		cur_node = next_node;
880 		next_node = NULL;
881 	}
882 	cm_req_lock_release(cm_ctx);
883 
884 	return QDF_STATUS_E_FAILURE;
885 }
886 
887 void cm_inform_bcn_probe(struct cnx_mgr *cm_ctx, uint8_t *bcn_probe,
888 			 uint32_t len, qdf_freq_t freq, int32_t rssi,
889 			 wlan_cm_id cm_id)
890 {
891 	qdf_nbuf_t buf;
892 	struct wlan_objmgr_pdev *pdev;
893 	uint8_t *data, i, vdev_id;
894 	struct mgmt_rx_event_params rx_param = {0};
895 	struct wlan_frame_hdr *hdr;
896 	enum mgmt_frame_type frm_type = MGMT_BEACON;
897 
898 	vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
899 	if (!bcn_probe || !len || (len < sizeof(*hdr))) {
900 		mlme_err(CM_PREFIX_FMT "bcn_probe is null or invalid len %d",
901 			 CM_PREFIX_REF(vdev_id, cm_id), len);
902 		return;
903 	}
904 
905 	pdev = wlan_vdev_get_pdev(cm_ctx->vdev);
906 	if (!pdev) {
907 		mlme_err(CM_PREFIX_FMT "Failed to find pdev",
908 			 CM_PREFIX_REF(vdev_id, cm_id));
909 		return;
910 	}
911 
912 	hdr = (struct wlan_frame_hdr *)bcn_probe;
913 	if ((hdr->i_fc[0] & QDF_IEEE80211_FC0_SUBTYPE_MASK) ==
914 	    MGMT_SUBTYPE_PROBE_RESP)
915 		frm_type = MGMT_PROBE_RESP;
916 
917 	rx_param.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
918 	rx_param.chan_freq = freq;
919 	rx_param.rssi = rssi;
920 
921 	/* Set all per chain rssi as invalid */
922 	for (i = 0; i < WLAN_MGMT_TXRX_HOST_MAX_ANTENNA; i++)
923 		rx_param.rssi_ctl[i] = WLAN_INVALID_PER_CHAIN_RSSI;
924 
925 	buf = qdf_nbuf_alloc(NULL, qdf_roundup(len, 4), 0, 4, false);
926 	if (!buf)
927 		return;
928 
929 	qdf_nbuf_put_tail(buf, len);
930 	qdf_nbuf_set_protocol(buf, ETH_P_CONTROL);
931 
932 	data = qdf_nbuf_data(buf);
933 	qdf_mem_copy(data, bcn_probe, len);
934 	/* buf will be freed by scan module in error or success case */
935 	wlan_scan_process_bcn_probe_rx_sync(wlan_pdev_get_psoc(pdev), buf,
936 					    &rx_param, frm_type);
937 }
938 
939 bool cm_is_vdev_connecting(struct wlan_objmgr_vdev *vdev)
940 {
941 	struct cnx_mgr *cm_ctx;
942 	enum wlan_cm_sm_state state;
943 
944 	cm_ctx = cm_get_cm_ctx(vdev);
945 	if (!cm_ctx)
946 		return false;
947 
948 	state = cm_get_state(cm_ctx);
949 
950 	if (state == WLAN_CM_S_CONNECTING)
951 		return true;
952 
953 	return false;
954 }
955 
956 bool cm_is_vdev_connected(struct wlan_objmgr_vdev *vdev)
957 {
958 	struct cnx_mgr *cm_ctx;
959 	enum wlan_cm_sm_state state;
960 
961 	cm_ctx = cm_get_cm_ctx(vdev);
962 	if (!cm_ctx)
963 		return false;
964 
965 	state = cm_get_state(cm_ctx);
966 
967 	if (state == WLAN_CM_S_CONNECTED)
968 		return true;
969 
970 	return false;
971 }
972 
973 bool cm_is_vdev_active(struct wlan_objmgr_vdev *vdev)
974 {
975 	struct cnx_mgr *cm_ctx;
976 	enum wlan_cm_sm_state state;
977 
978 	cm_ctx = cm_get_cm_ctx(vdev);
979 	if (!cm_ctx)
980 		return false;
981 
982 	state = cm_get_state(cm_ctx);
983 
984 	if (state == WLAN_CM_S_CONNECTED || state == WLAN_CM_S_ROAMING)
985 		return true;
986 
987 	return false;
988 }
989 
990 bool cm_is_vdev_disconnecting(struct wlan_objmgr_vdev *vdev)
991 {
992 	struct cnx_mgr *cm_ctx;
993 	enum wlan_cm_sm_state state;
994 
995 	cm_ctx = cm_get_cm_ctx(vdev);
996 	if (!cm_ctx)
997 		return false;
998 
999 	state = cm_get_state(cm_ctx);
1000 
1001 	if (state == WLAN_CM_S_DISCONNECTING)
1002 		return true;
1003 
1004 	return false;
1005 }
1006 
1007 bool cm_is_vdev_disconnected(struct wlan_objmgr_vdev *vdev)
1008 {
1009 	struct cnx_mgr *cm_ctx;
1010 	enum wlan_cm_sm_state state;
1011 
1012 	cm_ctx = cm_get_cm_ctx(vdev);
1013 	if (!cm_ctx)
1014 		return false;
1015 
1016 	state = cm_get_state(cm_ctx);
1017 
1018 	if (state == WLAN_CM_S_INIT)
1019 		return true;
1020 
1021 	return false;
1022 }
1023 
1024 bool cm_is_vdev_roaming(struct wlan_objmgr_vdev *vdev)
1025 {
1026 	struct cnx_mgr *cm_ctx;
1027 	enum wlan_cm_sm_state state;
1028 
1029 	cm_ctx = cm_get_cm_ctx(vdev);
1030 	if (!cm_ctx)
1031 		return false;
1032 
1033 	state = cm_get_state(cm_ctx);
1034 
1035 	if (state == WLAN_CM_S_ROAMING)
1036 		return true;
1037 
1038 	return false;
1039 }
1040 
1041 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
1042 bool cm_is_vdev_roam_started(struct wlan_objmgr_vdev *vdev)
1043 {
1044 	struct cnx_mgr *cm_ctx;
1045 	enum wlan_cm_sm_state state;
1046 	enum wlan_cm_sm_state sub_state;
1047 
1048 	cm_ctx = cm_get_cm_ctx(vdev);
1049 	if (!cm_ctx)
1050 		return false;
1051 
1052 	state = cm_get_state(cm_ctx);
1053 	sub_state = cm_get_sub_state(cm_ctx);
1054 	if (state == WLAN_CM_S_ROAMING && sub_state == WLAN_CM_SS_ROAM_STARTED)
1055 		return true;
1056 
1057 	return false;
1058 }
1059 
1060 bool cm_is_vdev_roam_sync_inprogress(struct wlan_objmgr_vdev *vdev)
1061 {
1062 	struct cnx_mgr *cm_ctx;
1063 	enum wlan_cm_sm_state state;
1064 	enum wlan_cm_sm_state sub_state;
1065 
1066 	cm_ctx = cm_get_cm_ctx(vdev);
1067 	if (!cm_ctx)
1068 		return false;
1069 
1070 	state = cm_get_state(cm_ctx);
1071 	sub_state = cm_get_sub_state(cm_ctx);
1072 	if (state == WLAN_CM_S_ROAMING && sub_state == WLAN_CM_SS_ROAM_SYNC)
1073 		return true;
1074 
1075 	return false;
1076 }
1077 #endif
1078 
1079 #ifdef WLAN_FEATURE_HOST_ROAM
1080 bool cm_is_vdev_roam_preauth_state(struct wlan_objmgr_vdev *vdev)
1081 {
1082 	struct cnx_mgr *cm_ctx;
1083 	enum wlan_cm_sm_state state;
1084 	enum wlan_cm_sm_state sub_state;
1085 
1086 	cm_ctx = cm_get_cm_ctx(vdev);
1087 	if (!cm_ctx)
1088 		return false;
1089 
1090 	state = cm_get_state(cm_ctx);
1091 	sub_state = cm_get_sub_state(cm_ctx);
1092 	if (state == WLAN_CM_S_ROAMING && sub_state == WLAN_CM_SS_PREAUTH)
1093 		return true;
1094 
1095 	return false;
1096 }
1097 
1098 bool cm_is_vdev_roam_reassoc_state(struct wlan_objmgr_vdev *vdev)
1099 {
1100 	struct cnx_mgr *cm_ctx;
1101 	enum wlan_cm_sm_state state;
1102 	enum wlan_cm_sm_state sub_state;
1103 
1104 	cm_ctx = cm_get_cm_ctx(vdev);
1105 	if (!cm_ctx)
1106 		return false;
1107 
1108 	state = cm_get_state(cm_ctx);
1109 	sub_state = cm_get_sub_state(cm_ctx);
1110 	if (state == WLAN_CM_S_ROAMING && sub_state == WLAN_CM_SS_REASSOC)
1111 		return true;
1112 
1113 	return false;
1114 }
1115 #endif
1116 
1117 enum wlan_cm_active_request_type
1118 cm_get_active_req_type(struct wlan_objmgr_vdev *vdev)
1119 {
1120 	struct cnx_mgr *cm_ctx;
1121 	wlan_cm_id cm_id;
1122 	uint32_t active_req_prefix = 0;
1123 
1124 	cm_ctx = cm_get_cm_ctx(vdev);
1125 	if (!cm_ctx)
1126 		return CM_NONE;
1127 
1128 	cm_id = cm_ctx->active_cm_id;
1129 
1130 	if (cm_id != CM_ID_INVALID)
1131 		active_req_prefix = CM_ID_GET_PREFIX(cm_id);
1132 
1133 	if (active_req_prefix == CONNECT_REQ_PREFIX)
1134 		return CM_CONNECT_ACTIVE;
1135 	else if (active_req_prefix == DISCONNECT_REQ_PREFIX)
1136 		return CM_DISCONNECT_ACTIVE;
1137 	else if (active_req_prefix == ROAM_REQ_PREFIX)
1138 		return CM_ROAM_ACTIVE;
1139 	else
1140 		return CM_NONE;
1141 }
1142 
1143 bool cm_get_active_connect_req(struct wlan_objmgr_vdev *vdev,
1144 			       struct wlan_cm_vdev_connect_req *req)
1145 {
1146 	struct cnx_mgr *cm_ctx;
1147 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
1148 	struct cm_req *cm_req = NULL;
1149 	bool status = false;
1150 	uint32_t cm_id_prefix;
1151 
1152 	cm_ctx = cm_get_cm_ctx(vdev);
1153 	if (!cm_ctx)
1154 		return status;
1155 
1156 	cm_req_lock_acquire(cm_ctx);
1157 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
1158 	while (cur_node) {
1159 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
1160 
1161 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
1162 		cm_id_prefix = CM_ID_GET_PREFIX((cm_req->cm_id));
1163 
1164 		if (cm_req->cm_id == cm_ctx->active_cm_id &&
1165 		    cm_id_prefix == CONNECT_REQ_PREFIX) {
1166 			req->vdev_id = wlan_vdev_get_id(vdev);
1167 			req->cm_id = cm_req->connect_req.cm_id;
1168 			req->bss =  cm_req->connect_req.cur_candidate;
1169 			req->is_wps_connection =
1170 				cm_req->connect_req.req.is_wps_connection;
1171 			req->is_osen_connection =
1172 				cm_req->connect_req.req.is_osen_connection;
1173 			status = true;
1174 			cm_req_lock_release(cm_ctx);
1175 			return status;
1176 		}
1177 
1178 		cur_node = next_node;
1179 		next_node = NULL;
1180 	}
1181 	cm_req_lock_release(cm_ctx);
1182 
1183 	return status;
1184 }
1185 
1186 bool cm_get_active_disconnect_req(struct wlan_objmgr_vdev *vdev,
1187 				  struct wlan_cm_vdev_discon_req *req)
1188 {
1189 	struct cnx_mgr *cm_ctx;
1190 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
1191 	struct cm_req *cm_req = NULL;
1192 	bool status = false;
1193 	uint32_t cm_id_prefix;
1194 
1195 	cm_ctx = cm_get_cm_ctx(vdev);
1196 	if (!cm_ctx)
1197 		return status;
1198 
1199 	cm_req_lock_acquire(cm_ctx);
1200 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
1201 	while (cur_node) {
1202 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
1203 
1204 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
1205 		cm_id_prefix = CM_ID_GET_PREFIX((cm_req->cm_id));
1206 
1207 		if (cm_req->cm_id == cm_ctx->active_cm_id &&
1208 		    cm_id_prefix == DISCONNECT_REQ_PREFIX) {
1209 			req->cm_id = cm_req->cm_id;
1210 			req->req.vdev_id = wlan_vdev_get_id(vdev);
1211 			req->req.source = cm_req->discon_req.req.source;
1212 			req->req.reason_code =
1213 					cm_req->discon_req.req.reason_code;
1214 			req->req.bssid = cm_req->discon_req.req.bssid;
1215 			status = true;
1216 			cm_req_lock_release(cm_ctx);
1217 			return status;
1218 		}
1219 
1220 		cur_node = next_node;
1221 		next_node = NULL;
1222 	}
1223 	cm_req_lock_release(cm_ctx);
1224 
1225 	return status;
1226 }
1227 
1228 struct cm_req *cm_get_req_by_scan_id(struct cnx_mgr *cm_ctx,
1229 				     wlan_scan_id scan_id)
1230 {
1231 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
1232 	struct cm_req *cm_req;
1233 
1234 	cm_req_lock_acquire(cm_ctx);
1235 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
1236 	while (cur_node) {
1237 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
1238 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
1239 
1240 		if (cm_req->connect_req.scan_id == scan_id) {
1241 			cm_req_lock_release(cm_ctx);
1242 			return cm_req;
1243 		}
1244 
1245 		cur_node = next_node;
1246 		next_node = NULL;
1247 	}
1248 	cm_req_lock_release(cm_ctx);
1249 
1250 	return NULL;
1251 }
1252 
1253 wlan_cm_id cm_get_cm_id_by_scan_id(struct cnx_mgr *cm_ctx,
1254 				   wlan_scan_id scan_id)
1255 {
1256 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
1257 	struct cm_req *cm_req;
1258 
1259 	cm_req_lock_acquire(cm_ctx);
1260 	qdf_list_peek_front(&cm_ctx->req_list, &cur_node);
1261 	while (cur_node) {
1262 		qdf_list_peek_next(&cm_ctx->req_list, cur_node, &next_node);
1263 		cm_req = qdf_container_of(cur_node, struct cm_req, node);
1264 
1265 		if (cm_req->connect_req.scan_id == scan_id) {
1266 			cm_req_lock_release(cm_ctx);
1267 			return cm_req->cm_id;
1268 		}
1269 
1270 		cur_node = next_node;
1271 		next_node = NULL;
1272 	}
1273 	cm_req_lock_release(cm_ctx);
1274 
1275 	return CM_ID_INVALID;
1276 }
1277 
1278 #ifdef WLAN_POLICY_MGR_ENABLE
1279 static void
1280 cm_get_pcl_chan_weigtage_for_sta(struct wlan_objmgr_pdev *pdev,
1281 				 struct pcl_freq_weight_list *pcl_lst)
1282 {
1283 	enum QDF_OPMODE opmode = QDF_STA_MODE;
1284 	enum policy_mgr_con_mode pm_mode;
1285 	uint32_t num_entries = 0;
1286 	QDF_STATUS status;
1287 
1288 	if (!pcl_lst)
1289 		return;
1290 
1291 	if (policy_mgr_map_concurrency_mode(&opmode, &pm_mode)) {
1292 		status = policy_mgr_get_pcl(wlan_pdev_get_psoc(pdev), pm_mode,
1293 					    pcl_lst->pcl_freq_list,
1294 					    &num_entries,
1295 					    pcl_lst->pcl_weight_list,
1296 					    NUM_CHANNELS);
1297 		if (QDF_IS_STATUS_ERROR(status))
1298 			return;
1299 		pcl_lst->num_of_pcl_channels = num_entries;
1300 	}
1301 }
1302 
1303 void cm_calculate_scores(struct cnx_mgr *cm_ctx,
1304 			 struct wlan_objmgr_pdev *pdev,
1305 			 struct scan_filter *filter, qdf_list_t *list)
1306 {
1307 	struct pcl_freq_weight_list *pcl_lst = NULL;
1308 
1309 	if (!filter->num_of_bssid) {
1310 		pcl_lst = qdf_mem_malloc(sizeof(*pcl_lst));
1311 		cm_get_pcl_chan_weigtage_for_sta(pdev, pcl_lst);
1312 		if (pcl_lst && !pcl_lst->num_of_pcl_channels) {
1313 			qdf_mem_free(pcl_lst);
1314 			pcl_lst = NULL;
1315 		}
1316 	}
1317 	wlan_cm_calculate_bss_score(pdev, pcl_lst, list, &filter->bssid_hint);
1318 	if (pcl_lst)
1319 		qdf_mem_free(pcl_lst);
1320 }
1321 #else
1322 inline
1323 void cm_calculate_scores(struct cnx_mgr *cm_ctx,
1324 			 struct wlan_objmgr_pdev *pdev,
1325 			 struct scan_filter *filter, qdf_list_t *list)
1326 {
1327 	wlan_cm_calculate_bss_score(pdev, NULL, list, &filter->bssid_hint);
1328 
1329 	/*
1330 	 * Custom sorting if enabled
1331 	 */
1332 	if (cm_ctx && cm_ctx->cm_candidate_list_custom_sort)
1333 		cm_ctx->cm_candidate_list_custom_sort(cm_ctx->vdev, list);
1334 }
1335 #endif
1336 
1337 #ifdef SM_ENG_HIST_ENABLE
1338 static const char *cm_id_to_string(wlan_cm_id cm_id)
1339 {
1340 	uint32_t prefix = CM_ID_GET_PREFIX(cm_id);
1341 
1342 	switch (prefix) {
1343 	case CONNECT_REQ_PREFIX:
1344 		return "CONNECT";
1345 	case DISCONNECT_REQ_PREFIX:
1346 		return "DISCONNECT";
1347 	case ROAM_REQ_PREFIX:
1348 		return "ROAM";
1349 	default:
1350 		return "INVALID";
1351 	}
1352 }
1353 
1354 void cm_req_history_add(struct cnx_mgr *cm_ctx,
1355 			struct cm_req *cm_req)
1356 {
1357 	struct cm_req_history *history = &cm_ctx->req_history;
1358 	struct cm_req_history_info *data;
1359 
1360 	qdf_spin_lock_bh(&history->cm_req_hist_lock);
1361 	data = &history->data[history->index];
1362 	history->index++;
1363 	history->index %= CM_REQ_HISTORY_SIZE;
1364 
1365 	qdf_mem_zero(data, sizeof(*data));
1366 	data->cm_id = cm_req->cm_id;
1367 	data->add_time = qdf_get_log_timestamp();
1368 	data->add_cm_state = cm_get_state(cm_ctx);
1369 	qdf_spin_unlock_bh(&history->cm_req_hist_lock);
1370 }
1371 
1372 void cm_req_history_del(struct cnx_mgr *cm_ctx,
1373 			struct cm_req *cm_req,
1374 			enum cm_req_del_type del_type)
1375 {
1376 	uint8_t i, idx;
1377 	struct cm_req_history_info *data;
1378 	struct cm_req_history *history = &cm_ctx->req_history;
1379 
1380 	qdf_spin_lock_bh(&history->cm_req_hist_lock);
1381 	for (i = 0; i < CM_REQ_HISTORY_SIZE; i++) {
1382 		if (history->index < i)
1383 			idx = CM_REQ_HISTORY_SIZE + history->index - i;
1384 		else
1385 			idx = history->index - i;
1386 
1387 		data = &history->data[idx];
1388 		if (data->cm_id == cm_req->cm_id) {
1389 			data->del_time = qdf_get_log_timestamp();
1390 			data->del_cm_state = cm_get_state(cm_ctx);
1391 			data->del_type = del_type;
1392 			break;
1393 		}
1394 
1395 		if (!data->cm_id)
1396 			break;
1397 	}
1398 	qdf_spin_unlock_bh(&history->cm_req_hist_lock);
1399 }
1400 
1401 void cm_req_history_init(struct cnx_mgr *cm_ctx)
1402 {
1403 	qdf_spinlock_create(&cm_ctx->req_history.cm_req_hist_lock);
1404 	qdf_mem_zero(&cm_ctx->req_history, sizeof(struct cm_req_history));
1405 }
1406 
1407 void cm_req_history_deinit(struct cnx_mgr *cm_ctx)
1408 {
1409 	qdf_spinlock_destroy(&cm_ctx->req_history.cm_req_hist_lock);
1410 }
1411 
1412 static inline void cm_req_history_print_entry(uint16_t idx,
1413 					      struct cm_req_history_info *data)
1414 {
1415 	if (!data->cm_id)
1416 		return;
1417 
1418 	mlme_nofl_err("    |%6u | 0x%016llx | 0x%016llx |%12s | 0x%08x |%15s |%15s |%8u",
1419 		      idx, data->add_time, data->del_time,
1420 		      cm_id_to_string(data->cm_id), data->cm_id,
1421 		      cm_sm_info[data->add_cm_state].name,
1422 		      cm_sm_info[data->del_cm_state].name,
1423 		      data->del_type);
1424 }
1425 
1426 void cm_req_history_print(struct cnx_mgr *cm_ctx)
1427 {
1428 	struct cm_req_history *history = &cm_ctx->req_history;
1429 	uint8_t i, idx;
1430 
1431 	mlme_nofl_err("CM Request history is as below");
1432 	mlme_nofl_err("|%6s |%19s |%19s |%12s |%11s |%15s |%15s |%8s",
1433 		      "Index", "Add Time", "Del Time", "Req type",
1434 		      "Cm Id", "Add State", "Del State", "Del Type");
1435 
1436 	qdf_spin_lock_bh(&history->cm_req_hist_lock);
1437 	for (i = 0; i < CM_REQ_HISTORY_SIZE; i++) {
1438 		idx = (history->index + i) % CM_REQ_HISTORY_SIZE;
1439 		cm_req_history_print_entry(idx, &history->data[idx]);
1440 	}
1441 	qdf_spin_unlock_bh(&history->cm_req_hist_lock);
1442 }
1443 #endif
1444 
1445 #ifndef CONN_MGR_ADV_FEATURE
1446 void cm_set_candidate_advance_filter_cb(
1447 		struct wlan_objmgr_vdev *vdev,
1448 		void (*filter_fun)(struct wlan_objmgr_vdev *vdev,
1449 				   struct scan_filter *filter))
1450 {
1451 	struct cnx_mgr *cm_ctx;
1452 
1453 	cm_ctx = cm_get_cm_ctx(vdev);
1454 	if (!cm_ctx)
1455 		return;
1456 
1457 	cm_ctx->cm_candidate_advance_filter = filter_fun;
1458 }
1459 
1460 void cm_set_candidate_custom_sort_cb(
1461 		struct wlan_objmgr_vdev *vdev,
1462 		void (*sort_fun)(struct wlan_objmgr_vdev *vdev,
1463 				 qdf_list_t *list))
1464 {
1465 	struct cnx_mgr *cm_ctx;
1466 
1467 	cm_ctx = cm_get_cm_ctx(vdev);
1468 	if (!cm_ctx)
1469 		return;
1470 
1471 	cm_ctx->cm_candidate_list_custom_sort = sort_fun;
1472 }
1473 #endif
1474