1 /* 2 * Copyright (c) 2012-2015, 2020-2021, The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022 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: wlan_cm_api.c 20 * 21 * This file maintains definitaions public apis. 22 */ 23 24 #include <wlan_cm_api.h> 25 #include "connection_mgr/core/src/wlan_cm_main_api.h" 26 #include "connection_mgr/core/src/wlan_cm_roam.h" 27 #include <wlan_vdev_mgr_utils_api.h> 28 29 QDF_STATUS wlan_cm_start_connect(struct wlan_objmgr_vdev *vdev, 30 struct wlan_cm_connect_req *req) 31 { 32 return cm_connect_start_req(vdev, req); 33 } 34 35 QDF_STATUS wlan_cm_disconnect(struct wlan_objmgr_vdev *vdev, 36 enum wlan_cm_source source, 37 enum wlan_reason_code reason_code, 38 struct qdf_mac_addr *bssid) 39 { 40 struct wlan_cm_disconnect_req req = {0}; 41 42 req.vdev_id = wlan_vdev_get_id(vdev); 43 req.source = source; 44 req.reason_code = reason_code; 45 if (bssid) 46 qdf_copy_macaddr(&req.bssid, bssid); 47 48 return cm_disconnect_start_req(vdev, &req); 49 } 50 51 QDF_STATUS wlan_cm_disconnect_sync(struct wlan_objmgr_vdev *vdev, 52 enum wlan_cm_source source, 53 enum wlan_reason_code reason_code) 54 { 55 struct wlan_cm_disconnect_req req = {0}; 56 57 req.vdev_id = wlan_vdev_get_id(vdev); 58 req.source = source; 59 req.reason_code = reason_code; 60 61 return cm_disconnect_start_req_sync(vdev, &req); 62 } 63 64 QDF_STATUS wlan_cm_bss_select_ind_rsp(struct wlan_objmgr_vdev *vdev, 65 QDF_STATUS status) 66 { 67 return cm_bss_select_ind_rsp(vdev, status); 68 } 69 70 QDF_STATUS wlan_cm_bss_peer_create_rsp(struct wlan_objmgr_vdev *vdev, 71 QDF_STATUS status, 72 struct qdf_mac_addr *peer_mac) 73 { 74 uint32_t prefix; 75 struct cnx_mgr *cm_ctx = cm_get_cm_ctx(vdev); 76 77 if (!cm_ctx) 78 return QDF_STATUS_E_INVAL; 79 80 prefix = CM_ID_GET_PREFIX(cm_ctx->active_cm_id); 81 if (prefix == ROAM_REQ_PREFIX) 82 return cm_roam_bss_peer_create_rsp(vdev, status, peer_mac); 83 else 84 return cm_bss_peer_create_rsp(vdev, status, peer_mac); 85 } 86 87 QDF_STATUS wlan_cm_connect_rsp(struct wlan_objmgr_vdev *vdev, 88 struct wlan_cm_connect_resp *resp) 89 { 90 return cm_connect_rsp(vdev, resp); 91 } 92 93 QDF_STATUS wlan_cm_bss_peer_delete_ind(struct wlan_objmgr_vdev *vdev, 94 struct qdf_mac_addr *peer_mac) 95 { 96 return cm_bss_peer_delete_req(vdev, peer_mac); 97 } 98 99 QDF_STATUS wlan_cm_bss_peer_delete_rsp(struct wlan_objmgr_vdev *vdev, 100 uint32_t status) 101 { 102 return cm_vdev_down_req(vdev, status); 103 } 104 105 QDF_STATUS wlan_cm_disconnect_rsp(struct wlan_objmgr_vdev *vdev, 106 struct wlan_cm_discon_rsp *resp) 107 { 108 uint32_t prefix; 109 struct cnx_mgr *cm_ctx = cm_get_cm_ctx(vdev); 110 111 if (!cm_ctx) 112 return QDF_STATUS_E_INVAL; 113 114 prefix = CM_ID_GET_PREFIX(cm_ctx->active_cm_id); 115 if (prefix == ROAM_REQ_PREFIX) 116 return cm_roam_disconnect_rsp(vdev, resp); 117 else 118 return cm_disconnect_rsp(vdev, resp); 119 } 120 121 #ifdef WLAN_FEATURE_HOST_ROAM 122 QDF_STATUS wlan_cm_reassoc_rsp(struct wlan_objmgr_vdev *vdev, 123 struct wlan_cm_connect_resp *resp) 124 { 125 return cm_reassoc_rsp(vdev, resp); 126 } 127 #endif 128 129 void wlan_cm_set_max_connect_attempts(struct wlan_objmgr_vdev *vdev, 130 uint8_t max_connect_attempts) 131 { 132 cm_set_max_connect_attempts(vdev, max_connect_attempts); 133 } 134 135 void wlan_cm_set_max_connect_timeout(struct wlan_objmgr_vdev *vdev, 136 uint32_t max_connect_timeout) 137 { 138 cm_set_max_connect_timeout(vdev, max_connect_timeout); 139 } 140 141 bool wlan_cm_is_vdev_connecting(struct wlan_objmgr_vdev *vdev) 142 { 143 return cm_is_vdev_connecting(vdev); 144 } 145 146 bool wlan_cm_is_vdev_connected(struct wlan_objmgr_vdev *vdev) 147 { 148 return cm_is_vdev_connected(vdev); 149 } 150 151 bool wlan_cm_is_vdev_active(struct wlan_objmgr_vdev *vdev) 152 { 153 return cm_is_vdev_active(vdev); 154 } 155 156 bool wlan_cm_is_vdev_disconnecting(struct wlan_objmgr_vdev *vdev) 157 { 158 return cm_is_vdev_disconnecting(vdev); 159 } 160 161 bool wlan_cm_is_vdev_disconnected(struct wlan_objmgr_vdev *vdev) 162 { 163 return cm_is_vdev_disconnected(vdev); 164 } 165 166 bool wlan_cm_is_vdev_roaming(struct wlan_objmgr_vdev *vdev) 167 { 168 return cm_is_vdev_roaming(vdev); 169 } 170 171 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 172 bool wlan_cm_is_vdev_roam_started(struct wlan_objmgr_vdev *vdev) 173 { 174 return cm_is_vdev_roam_started(vdev); 175 } 176 177 bool wlan_cm_is_vdev_roam_sync_inprogress(struct wlan_objmgr_vdev *vdev) 178 { 179 return cm_is_vdev_roam_sync_inprogress(vdev); 180 } 181 #endif 182 183 #ifdef WLAN_FEATURE_HOST_ROAM 184 bool wlan_cm_is_vdev_roam_preauth_state(struct wlan_objmgr_vdev *vdev) 185 { 186 return cm_is_vdev_roam_preauth_state(vdev); 187 } 188 189 bool wlan_cm_is_vdev_roam_reassoc_state(struct wlan_objmgr_vdev *vdev) 190 { 191 return cm_is_vdev_roam_reassoc_state(vdev); 192 } 193 #endif 194 195 enum wlan_cm_active_request_type 196 wlan_cm_get_active_req_type(struct wlan_objmgr_vdev *vdev) 197 { 198 return cm_get_active_req_type(vdev); 199 } 200 201 bool wlan_cm_get_active_connect_req(struct wlan_objmgr_vdev *vdev, 202 struct wlan_cm_vdev_connect_req *req) 203 { 204 return cm_get_active_connect_req(vdev, req); 205 } 206 207 cm_ext_t *wlan_cm_get_ext_hdl(struct wlan_objmgr_vdev *vdev) 208 { 209 return cm_get_ext_hdl(vdev); 210 } 211 212 #ifdef WLAN_FEATURE_HOST_ROAM 213 bool wlan_cm_get_active_reassoc_req(struct wlan_objmgr_vdev *vdev, 214 struct wlan_cm_vdev_reassoc_req *req) 215 { 216 return cm_get_active_reassoc_req(vdev, req); 217 } 218 #endif 219 220 bool wlan_cm_get_active_disconnect_req(struct wlan_objmgr_vdev *vdev, 221 struct wlan_cm_vdev_discon_req *req) 222 { 223 return cm_get_active_disconnect_req(vdev, req); 224 } 225 226 const char *wlan_cm_reason_code_to_str(enum wlan_reason_code reason) 227 { 228 if (reason > REASON_PROP_START) 229 return ""; 230 231 switch (reason) { 232 CASE_RETURN_STRING(REASON_UNSPEC_FAILURE); 233 CASE_RETURN_STRING(REASON_PREV_AUTH_NOT_VALID); 234 CASE_RETURN_STRING(REASON_DEAUTH_NETWORK_LEAVING); 235 CASE_RETURN_STRING(REASON_DISASSOC_DUE_TO_INACTIVITY); 236 CASE_RETURN_STRING(REASON_DISASSOC_AP_BUSY); 237 CASE_RETURN_STRING(REASON_CLASS2_FRAME_FROM_NON_AUTH_STA); 238 CASE_RETURN_STRING(REASON_CLASS3_FRAME_FROM_NON_ASSOC_STA); 239 CASE_RETURN_STRING(REASON_DISASSOC_NETWORK_LEAVING); 240 CASE_RETURN_STRING(REASON_STA_NOT_AUTHENTICATED); 241 CASE_RETURN_STRING(REASON_BAD_PWR_CAPABILITY); 242 CASE_RETURN_STRING(REASON_BAD_SUPPORTED_CHANNELS); 243 CASE_RETURN_STRING(REASON_DISASSOC_BSS_TRANSITION); 244 CASE_RETURN_STRING(REASON_INVALID_IE); 245 CASE_RETURN_STRING(REASON_MIC_FAILURE); 246 CASE_RETURN_STRING(REASON_4WAY_HANDSHAKE_TIMEOUT); 247 CASE_RETURN_STRING(REASON_GROUP_KEY_UPDATE_TIMEOUT); 248 CASE_RETURN_STRING(REASON_IN_4WAY_DIFFERS); 249 CASE_RETURN_STRING(REASON_INVALID_GROUP_CIPHER); 250 CASE_RETURN_STRING(REASON_INVALID_PAIRWISE_CIPHER); 251 CASE_RETURN_STRING(REASON_INVALID_AKMP); 252 CASE_RETURN_STRING(REASON_UNSUPPORTED_RSNE_VER); 253 CASE_RETURN_STRING(REASON_INVALID_RSNE_CAPABILITIES); 254 CASE_RETURN_STRING(REASON_1X_AUTH_FAILURE); 255 CASE_RETURN_STRING(REASON_CIPHER_SUITE_REJECTED); 256 CASE_RETURN_STRING(REASON_TDLS_PEER_UNREACHABLE); 257 CASE_RETURN_STRING(REASON_TDLS_UNSPEC); 258 CASE_RETURN_STRING(REASON_DISASSOC_SSP_REQUESTED); 259 CASE_RETURN_STRING(REASON_NO_SSP_ROAMING_AGREEMENT); 260 CASE_RETURN_STRING(REASON_BAD_CIPHER_OR_AKM); 261 CASE_RETURN_STRING(REASON_LOCATION_NOT_AUTHORIZED); 262 CASE_RETURN_STRING(REASON_SERVICE_CHANGE_PRECLUDES_TS); 263 CASE_RETURN_STRING(REASON_QOS_UNSPECIFIED); 264 CASE_RETURN_STRING(REASON_NO_BANDWIDTH); 265 CASE_RETURN_STRING(REASON_XS_UNACKED_FRAMES); 266 CASE_RETURN_STRING(REASON_EXCEEDED_TXOP); 267 CASE_RETURN_STRING(REASON_STA_LEAVING); 268 CASE_RETURN_STRING(REASON_END_TS_BA_DLS); 269 CASE_RETURN_STRING(REASON_UNKNOWN_TS_BA); 270 CASE_RETURN_STRING(REASON_TIMEDOUT); 271 CASE_RETURN_STRING(REASON_PEERKEY_MISMATCH); 272 CASE_RETURN_STRING(REASON_AUTHORIZED_ACCESS_LIMIT_REACHED); 273 CASE_RETURN_STRING(REASON_EXTERNAL_SERVICE_REQUIREMENTS); 274 CASE_RETURN_STRING(REASON_INVALID_FT_ACTION_FRAME_COUNT); 275 CASE_RETURN_STRING(REASON_INVALID_PMKID); 276 CASE_RETURN_STRING(REASON_INVALID_MDE); 277 CASE_RETURN_STRING(REASON_INVALID_FTE); 278 CASE_RETURN_STRING(REASON_MESH_PEERING_CANCELLED); 279 CASE_RETURN_STRING(REASON_MESH_MAX_PEERS); 280 CASE_RETURN_STRING(REASON_MESH_CONFIG_POLICY_VIOLATION); 281 CASE_RETURN_STRING(REASON_MESH_CLOSE_RCVD); 282 CASE_RETURN_STRING(REASON_MESH_MAX_RETRIES); 283 CASE_RETURN_STRING(REASON_MESH_CONFIRM_TIMEOUT); 284 CASE_RETURN_STRING(REASON_MESH_INVALID_GTK); 285 CASE_RETURN_STRING(REASON_MESH_INCONSISTENT_PARAMS); 286 CASE_RETURN_STRING(REASON_MESH_INVALID_SECURITY_CAP); 287 CASE_RETURN_STRING(REASON_MESH_PATH_ERROR_NO_PROXY_INFO); 288 CASE_RETURN_STRING(REASON_MESH_PATH_ERROR_NO_FORWARDING_INFO); 289 CASE_RETURN_STRING(REASON_MESH_PATH_ERROR_DEST_UNREACHABLE); 290 CASE_RETURN_STRING(REASON_MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS); 291 CASE_RETURN_STRING(REASON_MESH_CHANNEL_SWITCH_REGULATORY_REQ); 292 CASE_RETURN_STRING(REASON_MESH_CHANNEL_SWITCH_UNSPECIFIED); 293 CASE_RETURN_STRING(REASON_POOR_RSSI_CONDITIONS); 294 default: 295 return "Unknown"; 296 } 297 } 298 299 #ifdef WLAN_POLICY_MGR_ENABLE 300 void wlan_cm_hw_mode_change_resp(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id, 301 wlan_cm_id cm_id, QDF_STATUS status) 302 { 303 uint32_t prefix; 304 305 prefix = CM_ID_GET_PREFIX(cm_id); 306 if (prefix == ROAM_REQ_PREFIX) 307 cm_reassoc_hw_mode_change_resp(pdev, vdev_id, cm_id, status); 308 else 309 cm_hw_mode_change_resp(pdev, vdev_id, cm_id, status); 310 } 311 #endif /* ifdef POLICY_MGR_ENABLE */ 312 313 #ifdef SM_ENG_HIST_ENABLE 314 void wlan_cm_sm_history_print(struct wlan_objmgr_vdev *vdev) 315 { 316 return cm_sm_history_print(vdev); 317 } 318 319 void wlan_cm_req_history_print(struct wlan_objmgr_vdev *vdev) 320 { 321 struct cnx_mgr *cm_ctx = cm_get_cm_ctx(vdev); 322 323 if (!cm_ctx) 324 return; 325 326 cm_req_history_print(cm_ctx); 327 } 328 #endif /* SM_ENG_HIST_ENABLE */ 329 330 #ifndef CONN_MGR_ADV_FEATURE 331 void wlan_cm_set_candidate_advance_filter_cb( 332 struct wlan_objmgr_vdev *vdev, 333 void (*filter_fun)(struct wlan_objmgr_vdev *vdev, 334 struct scan_filter *filter)) 335 { 336 cm_set_candidate_advance_filter_cb(vdev, filter_fun); 337 } 338 339 void wlan_cm_set_candidate_custom_sort_cb( 340 struct wlan_objmgr_vdev *vdev, 341 void (*sort_fun)(struct wlan_objmgr_vdev *vdev, 342 qdf_list_t *list)) 343 { 344 cm_set_candidate_custom_sort_cb(vdev, sort_fun); 345 } 346 347 #endif 348 349 struct reduced_neighbor_report *wlan_cm_get_rnr(struct wlan_objmgr_vdev *vdev, 350 wlan_cm_id cm_id) 351 { 352 enum QDF_OPMODE op_mode = wlan_vdev_mlme_get_opmode(vdev); 353 struct cm_req *cm_req; 354 struct cnx_mgr *cm_ctx; 355 356 if (op_mode != QDF_STA_MODE && op_mode != QDF_P2P_CLIENT_MODE) { 357 mlme_err("vdev %d Invalid mode %d", 358 wlan_vdev_get_id(vdev), op_mode); 359 return NULL; 360 } 361 362 cm_ctx = cm_get_cm_ctx(vdev); 363 if (!cm_ctx) 364 return NULL; 365 cm_req = cm_get_req_by_cm_id(cm_ctx, cm_id); 366 if (!cm_req) 367 return NULL; 368 369 if (cm_req->connect_req.cur_candidate && 370 cm_req->connect_req.cur_candidate->entry) 371 return &cm_req->connect_req.cur_candidate->entry->rnr; 372 373 return NULL; 374 } 375 376 QDF_STATUS 377 wlan_cm_disc_cont_after_rso_stop(struct wlan_objmgr_vdev *vdev, 378 struct wlan_cm_vdev_discon_req *req) 379 { 380 return cm_handle_rso_stop_rsp(vdev, req); 381 } 382 383 #ifdef WLAN_FEATURE_11BE 384 QDF_STATUS wlan_cm_sta_update_bw_puncture(struct wlan_objmgr_vdev *vdev, 385 uint8_t *peer_mac, 386 uint16_t ori_punc, 387 enum phy_ch_width ori_bw, 388 uint8_t ccfs0, uint8_t ccfs1, 389 enum phy_ch_width new_bw) 390 { 391 struct wlan_channel *des_chan; 392 uint16_t curr_punc = 0; 393 uint16_t new_punc = 0; 394 enum phy_ch_width curr_bw; 395 uint16_t primary_puncture_bitmap = 0; 396 struct wlan_objmgr_pdev *pdev; 397 struct reg_channel_list chan_list; 398 qdf_freq_t sec_ch_2g_freq = 0; 399 qdf_freq_t center_freq_320 = 0; 400 qdf_freq_t center_freq_40 = 0; 401 uint8_t band_mask; 402 uint32_t bw_puncture = 0; 403 404 if (!vdev || !peer_mac) { 405 mlme_err("invalid input parameters"); 406 return QDF_STATUS_E_INVAL; 407 } 408 pdev = wlan_vdev_get_pdev(vdev); 409 des_chan = wlan_vdev_mlme_get_des_chan(vdev); 410 if (!des_chan || !pdev) { 411 mlme_err("invalid des chan"); 412 return QDF_STATUS_E_INVAL; 413 } 414 if (ori_bw == CH_WIDTH_320MHZ) { 415 if (WLAN_REG_IS_6GHZ_CHAN_FREQ(des_chan->ch_freq)) 416 band_mask = BIT(REG_BAND_6G); 417 else 418 band_mask = BIT(REG_BAND_5G); 419 center_freq_320 = wlan_reg_chan_band_to_freq(pdev, ccfs1, 420 band_mask); 421 } else if (ori_bw == CH_WIDTH_40MHZ) { 422 if (WLAN_REG_IS_24GHZ_CH_FREQ(des_chan->ch_freq)) { 423 band_mask = BIT(REG_BAND_2G); 424 center_freq_40 = wlan_reg_chan_band_to_freq(pdev, 425 ccfs0, 426 band_mask); 427 if (center_freq_40 == des_chan->ch_freq + BW_10_MHZ) 428 sec_ch_2g_freq = des_chan->ch_freq + BW_20_MHZ; 429 if (center_freq_40 == des_chan->ch_freq - BW_10_MHZ) 430 sec_ch_2g_freq = des_chan->ch_freq - BW_20_MHZ; 431 } 432 } 433 qdf_mem_zero(&chan_list, sizeof(chan_list)); 434 curr_punc = des_chan->puncture_bitmap; 435 curr_bw = des_chan->ch_width; 436 wlan_reg_extract_puncture_by_bw(ori_bw, ori_punc, 437 des_chan->ch_freq, 438 center_freq_320, 439 CH_WIDTH_20MHZ, 440 &primary_puncture_bitmap); 441 if (primary_puncture_bitmap) { 442 mlme_err("sta vdev %d freq %d RX bw %d puncture 0x%x primary chan is punctured", 443 wlan_vdev_get_id(vdev), des_chan->ch_freq, 444 ori_bw, ori_punc); 445 return QDF_STATUS_E_FAULT; 446 } 447 if (new_bw == ori_bw) 448 new_punc = ori_punc; 449 else 450 wlan_reg_extract_puncture_by_bw(ori_bw, ori_punc, 451 des_chan->ch_freq, 452 center_freq_320, 453 new_bw, 454 &new_punc); 455 if (curr_bw == new_bw) { 456 if (curr_punc != new_punc) 457 des_chan->puncture_bitmap = new_punc; 458 else 459 return QDF_STATUS_SUCCESS; 460 } else { 461 if (new_bw != CH_WIDTH_320MHZ) 462 center_freq_320 = 0; 463 wlan_reg_fill_channel_list(pdev, des_chan->ch_freq, 464 sec_ch_2g_freq, new_bw, 465 center_freq_320, &chan_list, 466 true); 467 des_chan->ch_freq_seg1 = 468 chan_list.chan_param[0].center_freq_seg0; 469 des_chan->ch_freq_seg2 = 470 chan_list.chan_param[0].center_freq_seg1; 471 des_chan->ch_cfreq1 = chan_list.chan_param[0].mhz_freq_seg0; 472 des_chan->ch_cfreq2 = chan_list.chan_param[1].mhz_freq_seg1; 473 des_chan->puncture_bitmap = new_punc; 474 des_chan->ch_width = new_bw; 475 } 476 mlme_debug("sta vdev %d freq %d bw %d puncture 0x%x ch_cfreq1 %d ch_cfreq2 %d", 477 wlan_vdev_get_id(vdev), des_chan->ch_freq, 478 des_chan->ch_width, des_chan->puncture_bitmap, 479 des_chan->ch_cfreq1, des_chan->ch_cfreq2); 480 QDF_SET_BITS(bw_puncture, 0, 8, des_chan->ch_width); 481 QDF_SET_BITS(bw_puncture, 8, 16, des_chan->puncture_bitmap); 482 return wlan_util_vdev_peer_set_param_send(vdev, peer_mac, 483 WLAN_MLME_PEER_BW_PUNCTURE, 484 bw_puncture); 485 } 486 #endif /* WLAN_FEATURE_11BE */ 487