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