1 /* 2 * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 /** 18 * DOC: Implements MLME global APIs 19 */ 20 21 #include <wlan_objmgr_cmn.h> 22 #include <include/wlan_mlme_cmn.h> 23 #include <include/wlan_pdev_mlme.h> 24 #include <include/wlan_vdev_mlme.h> 25 #include <include/wlan_mlme_cmn.h> 26 #include <wlan_psoc_mlme_main.h> 27 #include <wlan_pdev_mlme_main.h> 28 #include <wlan_vdev_mlme_main.h> 29 #include <wlan_psoc_mlme_api.h> 30 31 struct mlme_ext_ops *glbl_ops; 32 mlme_get_global_ops_cb glbl_ops_cb; 33 34 struct mlme_cm_ops *glbl_cm_ops; 35 osif_cm_get_global_ops_cb glbl_cm_ops_cb; 36 37 static void mlme_cm_ops_init(void) 38 { 39 if (glbl_cm_ops_cb) 40 glbl_cm_ops = glbl_cm_ops_cb(); 41 } 42 43 static void mlme_cm_ops_deinit(void) 44 { 45 if (glbl_cm_ops_cb) 46 glbl_cm_ops = NULL; 47 } 48 49 QDF_STATUS wlan_cmn_mlme_init(void) 50 { 51 QDF_STATUS status; 52 53 status = wlan_psoc_mlme_init(); 54 if (status != QDF_STATUS_SUCCESS) 55 return status; 56 57 status = wlan_pdev_mlme_init(); 58 if (status != QDF_STATUS_SUCCESS) 59 return status; 60 61 status = wlan_vdev_mlme_init(); 62 if (status != QDF_STATUS_SUCCESS) 63 return status; 64 65 if (glbl_ops_cb) 66 glbl_ops = glbl_ops_cb(); 67 68 mlme_cm_ops_init(); 69 70 return QDF_STATUS_SUCCESS; 71 } 72 73 QDF_STATUS wlan_cmn_mlme_deinit(void) 74 { 75 QDF_STATUS status; 76 77 status = wlan_vdev_mlme_deinit(); 78 if (status != QDF_STATUS_SUCCESS) 79 return status; 80 81 status = wlan_pdev_mlme_deinit(); 82 if (status != QDF_STATUS_SUCCESS) 83 return status; 84 85 status = wlan_psoc_mlme_deinit(); 86 if (status != QDF_STATUS_SUCCESS) 87 return status; 88 89 mlme_cm_ops_deinit(); 90 91 return QDF_STATUS_SUCCESS; 92 } 93 94 QDF_STATUS mlme_psoc_ops_ext_hdl_create(struct psoc_mlme_obj *psoc_mlme) 95 { 96 QDF_STATUS ret = QDF_STATUS_SUCCESS; 97 98 if (glbl_ops && glbl_ops->mlme_psoc_ext_hdl_create) 99 ret = glbl_ops->mlme_psoc_ext_hdl_create(psoc_mlme); 100 101 return ret; 102 } 103 104 QDF_STATUS mlme_psoc_ops_ext_hdl_destroy(struct psoc_mlme_obj *psoc_mlme) 105 { 106 QDF_STATUS ret = QDF_STATUS_SUCCESS; 107 108 if (glbl_ops && glbl_ops->mlme_psoc_ext_hdl_destroy) 109 ret = glbl_ops->mlme_psoc_ext_hdl_destroy(psoc_mlme); 110 111 return ret; 112 } 113 114 QDF_STATUS mlme_pdev_ops_ext_hdl_create(struct pdev_mlme_obj *pdev_mlme) 115 { 116 QDF_STATUS ret = QDF_STATUS_SUCCESS; 117 118 if (glbl_ops && glbl_ops->mlme_pdev_ext_hdl_create) 119 ret = glbl_ops->mlme_pdev_ext_hdl_create(pdev_mlme); 120 121 return ret; 122 } 123 124 QDF_STATUS mlme_pdev_ops_ext_hdl_destroy(struct pdev_mlme_obj *pdev_mlme) 125 { 126 QDF_STATUS ret = QDF_STATUS_SUCCESS; 127 128 if (glbl_ops && glbl_ops->mlme_pdev_ext_hdl_destroy) 129 ret = glbl_ops->mlme_pdev_ext_hdl_destroy(pdev_mlme); 130 131 return ret; 132 } 133 134 QDF_STATUS mlme_vdev_ops_ext_hdl_create(struct vdev_mlme_obj *vdev_mlme) 135 { 136 QDF_STATUS ret = QDF_STATUS_SUCCESS; 137 138 if (glbl_ops && glbl_ops->mlme_vdev_ext_hdl_create) 139 ret = glbl_ops->mlme_vdev_ext_hdl_create(vdev_mlme); 140 141 return ret; 142 } 143 144 QDF_STATUS mlme_vdev_ops_ext_hdl_post_create(struct vdev_mlme_obj *vdev_mlme) 145 { 146 QDF_STATUS ret = QDF_STATUS_SUCCESS; 147 148 if (glbl_ops && glbl_ops->mlme_vdev_ext_hdl_post_create) 149 ret = glbl_ops->mlme_vdev_ext_hdl_post_create(vdev_mlme); 150 151 return ret; 152 } 153 154 QDF_STATUS mlme_vdev_ops_ext_hdl_destroy(struct vdev_mlme_obj *vdev_mlme) 155 { 156 QDF_STATUS ret = QDF_STATUS_SUCCESS; 157 158 if (glbl_ops && glbl_ops->mlme_vdev_ext_hdl_destroy) 159 ret = glbl_ops->mlme_vdev_ext_hdl_destroy(vdev_mlme); 160 161 return ret; 162 } 163 164 QDF_STATUS mlme_vdev_ops_start_fw_send(struct wlan_objmgr_vdev *vdev, 165 uint8_t restart) 166 { 167 QDF_STATUS ret = QDF_STATUS_SUCCESS; 168 169 if (glbl_ops && glbl_ops->mlme_vdev_start_fw_send) 170 ret = glbl_ops->mlme_vdev_start_fw_send(vdev, restart); 171 172 return ret; 173 } 174 175 QDF_STATUS mlme_vdev_ops_multivdev_restart_fw_cmd_send( 176 struct wlan_objmgr_pdev *pdev) 177 { 178 QDF_STATUS ret = QDF_STATUS_SUCCESS; 179 180 if (glbl_ops && glbl_ops->mlme_multivdev_restart_fw_send) 181 ret = glbl_ops->mlme_multivdev_restart_fw_send(pdev); 182 183 return ret; 184 } 185 186 QDF_STATUS mlme_vdev_ops_stop_fw_send(struct wlan_objmgr_vdev *vdev) 187 { 188 QDF_STATUS ret = QDF_STATUS_SUCCESS; 189 190 if (glbl_ops && glbl_ops->mlme_vdev_stop_fw_send) 191 ret = glbl_ops->mlme_vdev_stop_fw_send(vdev); 192 193 return ret; 194 } 195 196 QDF_STATUS mlme_vdev_ops_down_fw_send(struct wlan_objmgr_vdev *vdev) 197 { 198 QDF_STATUS ret = QDF_STATUS_SUCCESS; 199 200 if (glbl_ops && glbl_ops->mlme_vdev_down_fw_send) 201 ret = glbl_ops->mlme_vdev_down_fw_send(vdev); 202 203 return ret; 204 } 205 206 QDF_STATUS mlme_vdev_enqueue_exp_ser_cmd(struct vdev_mlme_obj *vdev_mlme, 207 uint8_t cmd_type) 208 { 209 QDF_STATUS ret = QDF_STATUS_SUCCESS; 210 211 if (glbl_ops && glbl_ops->mlme_vdev_enqueue_exp_cmd) 212 ret = glbl_ops->mlme_vdev_enqueue_exp_cmd(vdev_mlme, cmd_type); 213 214 return ret; 215 } 216 217 QDF_STATUS mlme_vdev_ops_ext_hdl_delete_rsp(struct wlan_objmgr_psoc *psoc, 218 struct vdev_delete_response *rsp) 219 { 220 QDF_STATUS ret = QDF_STATUS_SUCCESS; 221 222 if ((glbl_ops) && glbl_ops->mlme_vdev_ext_delete_rsp) 223 ret = glbl_ops->mlme_vdev_ext_delete_rsp(psoc, rsp); 224 225 return ret; 226 } 227 228 QDF_STATUS mlme_vdev_ops_ext_hdl_multivdev_restart_resp( 229 struct wlan_objmgr_psoc *psoc, 230 struct multi_vdev_restart_resp *resp) 231 { 232 QDF_STATUS ret = QDF_STATUS_SUCCESS; 233 234 if ((glbl_ops) && glbl_ops->mlme_multi_vdev_restart_resp) 235 ret = glbl_ops->mlme_multi_vdev_restart_resp(psoc, resp); 236 237 return ret; 238 } 239 240 QDF_STATUS mlme_cm_ext_hdl_create(struct wlan_objmgr_vdev *vdev, 241 cm_ext_t **ext_cm_ptr) 242 { 243 QDF_STATUS ret = QDF_STATUS_SUCCESS; 244 245 if (glbl_ops && glbl_ops->mlme_cm_ext_hdl_create_cb) 246 ret = glbl_ops->mlme_cm_ext_hdl_create_cb(vdev, ext_cm_ptr); 247 248 return ret; 249 } 250 251 QDF_STATUS mlme_cm_ext_hdl_destroy(struct wlan_objmgr_vdev *vdev, 252 cm_ext_t *ext_cm_ptr) 253 { 254 QDF_STATUS ret = QDF_STATUS_SUCCESS; 255 256 if (glbl_ops && glbl_ops->mlme_cm_ext_hdl_destroy_cb) 257 ret = glbl_ops->mlme_cm_ext_hdl_destroy_cb(vdev, ext_cm_ptr); 258 259 return ret; 260 } 261 262 QDF_STATUS mlme_cm_connect_start_ind(struct wlan_objmgr_vdev *vdev, 263 struct wlan_cm_connect_req *req) 264 { 265 QDF_STATUS ret = QDF_STATUS_SUCCESS; 266 267 if ((glbl_ops) && glbl_ops->mlme_cm_ext_connect_start_ind_cb) 268 ret = glbl_ops->mlme_cm_ext_connect_start_ind_cb(vdev, req); 269 270 return ret; 271 } 272 273 QDF_STATUS mlme_cm_bss_select_ind(struct wlan_objmgr_vdev *vdev, 274 struct wlan_cm_vdev_connect_req *req) 275 { 276 QDF_STATUS ret = QDF_STATUS_E_NOSUPPORT; 277 278 if ((glbl_ops) && glbl_ops->mlme_cm_ext_bss_select_ind_cb) 279 ret = glbl_ops->mlme_cm_ext_bss_select_ind_cb(vdev, req); 280 281 return ret; 282 } 283 284 QDF_STATUS mlme_cm_bss_peer_create_req(struct wlan_objmgr_vdev *vdev, 285 struct qdf_mac_addr *peer_mac, 286 struct qdf_mac_addr *mld_mac, 287 bool is_assoc_link) 288 { 289 QDF_STATUS ret = QDF_STATUS_SUCCESS; 290 291 if ((glbl_ops) && glbl_ops->mlme_cm_ext_bss_peer_create_req_cb) 292 ret = glbl_ops->mlme_cm_ext_bss_peer_create_req_cb( 293 vdev, peer_mac, mld_mac, is_assoc_link); 294 295 return ret; 296 } 297 298 QDF_STATUS mlme_cm_connect_req(struct wlan_objmgr_vdev *vdev, 299 struct wlan_cm_vdev_connect_req *req) 300 { 301 QDF_STATUS ret = QDF_STATUS_SUCCESS; 302 303 if ((glbl_ops) && glbl_ops->mlme_cm_ext_connect_req_cb) 304 ret = glbl_ops->mlme_cm_ext_connect_req_cb(vdev, req); 305 306 return ret; 307 } 308 309 QDF_STATUS mlme_cm_roam_start_ind(struct wlan_objmgr_vdev *vdev, 310 struct wlan_cm_roam_req *req) 311 { 312 QDF_STATUS ret = QDF_STATUS_SUCCESS; 313 314 if ((glbl_ops) && glbl_ops->mlme_cm_ext_roam_start_ind_cb) 315 ret = glbl_ops->mlme_cm_ext_roam_start_ind_cb(vdev, req); 316 317 return ret; 318 } 319 320 QDF_STATUS mlme_cm_reassoc_req(struct wlan_objmgr_vdev *vdev, 321 struct wlan_cm_vdev_reassoc_req *req) 322 { 323 QDF_STATUS ret = QDF_STATUS_SUCCESS; 324 325 if ((glbl_ops) && glbl_ops->mlme_cm_ext_reassoc_req_cb) 326 ret = glbl_ops->mlme_cm_ext_reassoc_req_cb(vdev, req); 327 328 return ret; 329 } 330 331 QDF_STATUS mlme_cm_connect_complete_ind(struct wlan_objmgr_vdev *vdev, 332 struct wlan_cm_connect_resp *rsp) 333 { 334 QDF_STATUS ret = QDF_STATUS_SUCCESS; 335 336 if ((glbl_ops) && glbl_ops->mlme_cm_ext_connect_complete_ind_cb) 337 ret = glbl_ops->mlme_cm_ext_connect_complete_ind_cb(vdev, rsp); 338 339 return ret; 340 } 341 342 QDF_STATUS mlme_cm_disconnect_start_ind(struct wlan_objmgr_vdev *vdev, 343 struct wlan_cm_disconnect_req *req) 344 { 345 QDF_STATUS ret = QDF_STATUS_SUCCESS; 346 347 if ((glbl_ops) && glbl_ops->mlme_cm_ext_disconnect_start_ind_cb) 348 ret = glbl_ops->mlme_cm_ext_disconnect_start_ind_cb(vdev, req); 349 350 return ret; 351 } 352 353 QDF_STATUS mlme_cm_disconnect_req(struct wlan_objmgr_vdev *vdev, 354 struct wlan_cm_vdev_discon_req *req) 355 { 356 QDF_STATUS ret = QDF_STATUS_SUCCESS; 357 358 if ((glbl_ops) && glbl_ops->mlme_cm_ext_disconnect_req_cb) 359 ret = glbl_ops->mlme_cm_ext_disconnect_req_cb(vdev, req); 360 361 return ret; 362 } 363 364 QDF_STATUS mlme_cm_bss_peer_delete_req(struct wlan_objmgr_vdev *vdev) 365 { 366 QDF_STATUS ret = QDF_STATUS_SUCCESS; 367 368 if ((glbl_ops) && glbl_ops->mlme_cm_ext_bss_peer_delete_req_cb) 369 ret = glbl_ops->mlme_cm_ext_bss_peer_delete_req_cb(vdev); 370 371 return ret; 372 } 373 374 QDF_STATUS mlme_cm_disconnect_complete_ind(struct wlan_objmgr_vdev *vdev, 375 struct wlan_cm_discon_rsp *rsp) 376 { 377 QDF_STATUS ret = QDF_STATUS_SUCCESS; 378 379 if ((glbl_ops) && glbl_ops->mlme_cm_ext_disconnect_complete_ind_cb) 380 ret = glbl_ops->mlme_cm_ext_disconnect_complete_ind_cb(vdev, 381 rsp); 382 383 return ret; 384 } 385 386 QDF_STATUS mlme_cm_vdev_down_req(struct wlan_objmgr_vdev *vdev) 387 { 388 QDF_STATUS ret = QDF_STATUS_SUCCESS; 389 390 if ((glbl_ops) && glbl_ops->mlme_cm_ext_vdev_down_req_cb) 391 ret = glbl_ops->mlme_cm_ext_vdev_down_req_cb(vdev); 392 return ret; 393 } 394 395 QDF_STATUS mlme_cm_osif_connect_complete(struct wlan_objmgr_vdev *vdev, 396 struct wlan_cm_connect_resp *rsp) 397 { 398 QDF_STATUS ret = QDF_STATUS_SUCCESS; 399 400 if (glbl_cm_ops && glbl_cm_ops->mlme_cm_connect_complete_cb) 401 ret = glbl_cm_ops->mlme_cm_connect_complete_cb(vdev, rsp); 402 403 return ret; 404 } 405 406 QDF_STATUS 407 mlme_cm_osif_failed_candidate_ind(struct wlan_objmgr_vdev *vdev, 408 struct wlan_cm_connect_resp *rsp) 409 { 410 QDF_STATUS ret = QDF_STATUS_SUCCESS; 411 412 if (glbl_cm_ops && 413 glbl_cm_ops->mlme_cm_failed_candidate_cb) 414 ret = glbl_cm_ops->mlme_cm_failed_candidate_cb(vdev, rsp); 415 416 return ret; 417 } 418 419 QDF_STATUS mlme_cm_osif_update_id_and_src(struct wlan_objmgr_vdev *vdev, 420 enum wlan_cm_source source, 421 wlan_cm_id cm_id) 422 { 423 QDF_STATUS ret = QDF_STATUS_SUCCESS; 424 425 if (glbl_cm_ops && 426 glbl_cm_ops->mlme_cm_update_id_and_src_cb) 427 ret = glbl_cm_ops->mlme_cm_update_id_and_src_cb(vdev, source, 428 cm_id); 429 430 return ret; 431 } 432 433 QDF_STATUS mlme_cm_osif_disconnect_complete(struct wlan_objmgr_vdev *vdev, 434 struct wlan_cm_discon_rsp *rsp) 435 { 436 QDF_STATUS ret = QDF_STATUS_SUCCESS; 437 438 if (glbl_cm_ops && 439 glbl_cm_ops->mlme_cm_disconnect_complete_cb) 440 ret = glbl_cm_ops->mlme_cm_disconnect_complete_cb(vdev, rsp); 441 442 return ret; 443 } 444 445 QDF_STATUS mlme_cm_osif_disconnect_start_ind(struct wlan_objmgr_vdev *vdev) 446 { 447 QDF_STATUS ret = QDF_STATUS_SUCCESS; 448 449 if (glbl_cm_ops && 450 glbl_cm_ops->mlme_cm_disconnect_start_cb) 451 ret = glbl_cm_ops->mlme_cm_disconnect_start_cb(vdev); 452 453 return ret; 454 } 455 456 #ifdef CONN_MGR_ADV_FEATURE 457 QDF_STATUS mlme_cm_osif_roam_sync_ind(struct wlan_objmgr_vdev *vdev) 458 { 459 QDF_STATUS ret = QDF_STATUS_SUCCESS; 460 461 if (glbl_cm_ops && 462 glbl_cm_ops->mlme_cm_roam_sync_cb) 463 ret = glbl_cm_ops->mlme_cm_roam_sync_cb(vdev); 464 465 return ret; 466 } 467 468 QDF_STATUS mlme_cm_osif_pmksa_candidate_notify(struct wlan_objmgr_vdev *vdev, 469 struct qdf_mac_addr *bssid, 470 int index, bool preauth) 471 { 472 QDF_STATUS ret = QDF_STATUS_SUCCESS; 473 474 if (glbl_cm_ops && 475 glbl_cm_ops->mlme_cm_pmksa_candidate_notify_cb) 476 ret = glbl_cm_ops->mlme_cm_pmksa_candidate_notify_cb( 477 vdev, bssid, index, preauth); 478 479 return ret; 480 } 481 #endif 482 483 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 484 QDF_STATUS mlme_cm_osif_roam_start_ind(struct wlan_objmgr_vdev *vdev) 485 { 486 QDF_STATUS ret = QDF_STATUS_SUCCESS; 487 488 if (glbl_cm_ops && 489 glbl_cm_ops->mlme_cm_roam_start_cb) 490 ret = glbl_cm_ops->mlme_cm_roam_start_cb(vdev); 491 492 return ret; 493 } 494 495 QDF_STATUS mlme_cm_osif_roam_abort_ind(struct wlan_objmgr_vdev *vdev) 496 { 497 QDF_STATUS ret = QDF_STATUS_SUCCESS; 498 499 if (glbl_cm_ops && 500 glbl_cm_ops->mlme_cm_roam_abort_cb) 501 ret = glbl_cm_ops->mlme_cm_roam_abort_cb(vdev); 502 503 return ret; 504 } 505 506 QDF_STATUS 507 mlme_cm_osif_roam_complete(struct wlan_objmgr_vdev *vdev) 508 { 509 QDF_STATUS ret = QDF_STATUS_SUCCESS; 510 511 if (glbl_cm_ops && 512 glbl_cm_ops->mlme_cm_roam_cmpl_cb) 513 ret = glbl_cm_ops->mlme_cm_roam_cmpl_cb(vdev); 514 515 return ret; 516 } 517 #endif 518 519 #ifdef WLAN_FEATURE_PREAUTH_ENABLE 520 QDF_STATUS 521 mlme_cm_osif_ft_preauth_complete(struct wlan_objmgr_vdev *vdev, 522 struct wlan_preauth_rsp *rsp) 523 { 524 QDF_STATUS ret = QDF_STATUS_SUCCESS; 525 526 if (glbl_cm_ops && 527 glbl_cm_ops->mlme_cm_ft_preauth_cmpl_cb) 528 ret = glbl_cm_ops->mlme_cm_ft_preauth_cmpl_cb(vdev, rsp); 529 530 return ret; 531 } 532 533 #ifdef FEATURE_WLAN_ESE 534 QDF_STATUS 535 mlme_cm_osif_cckm_preauth_complete(struct wlan_objmgr_vdev *vdev, 536 struct wlan_preauth_rsp *rsp) 537 { 538 QDF_STATUS ret = QDF_STATUS_SUCCESS; 539 540 if (glbl_cm_ops && 541 glbl_cm_ops->mlme_cm_cckm_preauth_cmpl_cb) 542 ret = glbl_cm_ops->mlme_cm_cckm_preauth_cmpl_cb(vdev, rsp); 543 544 return ret; 545 } 546 #endif 547 #endif 548 549 void mlme_set_osif_cm_cb(osif_cm_get_global_ops_cb osif_cm_ops) 550 { 551 glbl_cm_ops_cb = osif_cm_ops; 552 } 553 554 void mlme_set_ops_register_cb(mlme_get_global_ops_cb ops_cb) 555 { 556 glbl_ops_cb = ops_cb; 557 } 558 559 bool mlme_max_chan_switch_is_set(struct wlan_objmgr_vdev *vdev) 560 { 561 struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(vdev); 562 struct psoc_mlme_obj *mlme_psoc_obj; 563 struct psoc_phy_config *phy_config; 564 565 if (!psoc) 566 return false; 567 568 mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc); 569 if (!mlme_psoc_obj) 570 return false; 571 572 phy_config = &mlme_psoc_obj->psoc_cfg.phy_config; 573 574 return phy_config->max_chan_switch_ie; 575 } 576