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