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