1 /* 2 * Copyright (c) 2012-2015, 2020, 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 general SM framework for connection manager 19 */ 20 21 #include "wlan_cm_main_api.h" 22 #include "wlan_cm_sm.h" 23 #include "wlan_cm_roam_sm.h" 24 25 void cm_set_state(struct cnx_mgr *cm_ctx, enum wlan_cm_sm_state state) 26 { 27 if (state < WLAN_CM_S_MAX) 28 cm_ctx->sm.cm_state = state; 29 else 30 mlme_err("mlme state (%d) is invalid", state); 31 } 32 33 void cm_set_substate(struct cnx_mgr *cm_ctx, enum wlan_cm_sm_state substate) 34 { 35 if ((substate > WLAN_CM_S_MAX) && (substate < WLAN_CM_SS_MAX)) 36 cm_ctx->sm.cm_substate = substate; 37 else 38 mlme_err(" mlme sub state (%d) is invalid", substate); 39 } 40 41 void cm_sm_state_update(struct cnx_mgr *cm_ctx, 42 enum wlan_cm_sm_state state, 43 enum wlan_cm_sm_state substate) 44 { 45 if (!cm_ctx) { 46 mlme_err("cm_ctx is NULL"); 47 return; 48 } 49 50 cm_set_state(cm_ctx, state); 51 cm_set_substate(cm_ctx, substate); 52 } 53 54 /** 55 * cm_state_init_entry() - Entry API for init state for connection mgr 56 * @ctx: connection manager ctx 57 * 58 * API to perform operations on moving to init state 59 * 60 * Return: void 61 */ 62 static void cm_state_init_entry(void *ctx) 63 { 64 struct cnx_mgr *cm_ctx = ctx; 65 66 cm_sm_state_update(cm_ctx, WLAN_CM_S_INIT, WLAN_CM_SS_IDLE); 67 } 68 69 /** 70 * cm_state_init_exit() - Exit API for init state for connection mgr 71 * @ctx: connection manager ctx 72 * 73 * API to perform operations on exiting from init state 74 * 75 * Return: void 76 */ 77 static void cm_state_init_exit(void *ctx) 78 { 79 } 80 81 /** 82 * cm_state_init_event() - Init State event handler for connection mgr 83 * @ctx: connection manager ctx 84 * 85 * API to handle events in INIT state 86 * 87 * Return: bool 88 */ 89 static bool cm_state_init_event(void *ctx, uint16_t event, 90 uint16_t data_len, void *data) 91 { 92 struct cnx_mgr *cm_ctx = ctx; 93 bool status; 94 95 switch (event) { 96 case WLAN_CM_SM_EV_CONNECT_REQ: 97 cm_sm_transition_to(cm_ctx, WLAN_CM_S_CONNECTING); 98 cm_sm_deliver_event(cm_ctx, WLAN_CM_SM_EV_CONNECT_START, 99 data_len, data); 100 status = true; 101 break; 102 case WLAN_CM_SM_EV_CONNECT_FAILURE: 103 cm_connect_complete(cm_ctx, data); 104 status = true; 105 break; 106 case WLAN_CM_SM_EV_DISCONNECT_DONE: 107 cm_disconnect_complete(cm_ctx, data); 108 status = true; 109 break; 110 default: 111 status = false; 112 break; 113 } 114 115 return status; 116 } 117 118 /** 119 * cm_state_connecting_entry() - Entry API for connecting state for 120 * connection mgr 121 * @ctx: connection manager ctx 122 * 123 * API to perform operations on moving to connecting state 124 * 125 * Return: void 126 */ 127 static void cm_state_connecting_entry(void *ctx) 128 { 129 struct cnx_mgr *cm_ctx = ctx; 130 131 cm_sm_state_update(cm_ctx, WLAN_CM_S_CONNECTING, WLAN_CM_SS_IDLE); 132 } 133 134 /** 135 * cm_state_connecting_exit() - Exit API for connecting state for 136 * connection mgr 137 * @ctx: connection manager ctx 138 * 139 * API to perform operations on exiting from connecting state 140 * 141 * Return: void 142 */ 143 static void cm_state_connecting_exit(void *ctx) 144 { 145 } 146 147 /** 148 * cm_state_connecting_event() - Connecting State event handler for 149 * connection mgr 150 * @ctx: connection manager ctx 151 * 152 * API to handle events in CONNECTING state 153 * 154 * Return: bool 155 */ 156 static bool cm_state_connecting_event(void *ctx, uint16_t event, 157 uint16_t data_len, void *data) 158 { 159 struct cnx_mgr *cm_ctx = ctx; 160 bool status; 161 162 switch (event) { 163 case WLAN_CM_SM_EV_CONNECT_START: 164 cm_sm_transition_to(cm_ctx, WLAN_CM_SS_JOIN_PENDING); 165 cm_sm_deliver_event(cm_ctx, event, data_len, data); 166 status = true; 167 break; 168 default: 169 status = false; 170 break; 171 } 172 173 return status; 174 } 175 176 /** 177 * cm_state_connected_entry() - Entry API for connected state for 178 * connection mgr 179 * @ctx: connection manager ctx 180 * 181 * API to perform operations on moving to connected state 182 * 183 * Return: void 184 */ 185 static void cm_state_connected_entry(void *ctx) 186 { 187 struct cnx_mgr *cm_ctx = ctx; 188 189 cm_sm_state_update(cm_ctx, WLAN_CM_S_CONNECTED, WLAN_CM_SS_IDLE); 190 } 191 192 /** 193 * cm_state_connected_exit() - Exit API for connected state for 194 * connection mgr 195 * @ctx: connection manager ctx 196 * 197 * API to perform operations on exiting from connected state 198 * 199 * Return: void 200 */ 201 static void cm_state_connected_exit(void *ctx) 202 { 203 } 204 205 /** 206 * cm_state_connected_event() - Connected State event handler for 207 * connection mgr 208 * @ctx: connection manager ctx 209 * 210 * API to handle events in CONNECTED state 211 * 212 * Return: bool 213 */ 214 static bool cm_state_connected_event(void *ctx, uint16_t event, 215 uint16_t data_len, void *data) 216 { 217 struct cnx_mgr *cm_ctx = ctx; 218 bool status; 219 220 switch (event) { 221 case WLAN_CM_SM_EV_CONNECT_SUCCESS: 222 cm_connect_complete(cm_ctx, data); 223 status = true; 224 break; 225 case WLAN_CM_SM_EV_DISCONNECT_REQ: 226 cm_sm_transition_to(cm_ctx, WLAN_CM_S_DISCONNECTING); 227 cm_sm_deliver_event(cm_ctx, WLAN_CM_SM_EV_DISCONNECT_START, 228 data_len, data); 229 status = true; 230 break; 231 default: 232 status = false; 233 break; 234 } 235 236 return status; 237 } 238 239 /** 240 * cm_state_disconnecting_entry() - Entry API for disconnecting state for 241 * connection mgr 242 * @ctx: connection manager ctx 243 * 244 * API to perform operations on moving to disconnecting state 245 * 246 * Return: void 247 */ 248 static void cm_state_disconnecting_entry(void *ctx) 249 { 250 struct cnx_mgr *cm_ctx = ctx; 251 252 cm_sm_state_update(cm_ctx, WLAN_CM_S_DISCONNECTING, WLAN_CM_SS_IDLE); 253 } 254 255 /** 256 * cm_state_disconnecting_exit() - Exit API for disconnecting state for 257 * connection mgr 258 * @ctx: connection manager ctx 259 * 260 * API to perform operations on exiting from disconnecting state 261 * 262 * Return: void 263 */ 264 static void cm_state_disconnecting_exit(void *ctx) 265 { 266 } 267 268 /** 269 * cm_state_connected_event() - Disconnecting State event handler for 270 * connection mgr 271 * @ctx: connection manager ctx 272 * 273 * API to handle events in Disconnecting state 274 * 275 * Return: bool 276 */ 277 static bool cm_state_disconnecting_event(void *ctx, uint16_t event, 278 uint16_t data_len, void *data) 279 { 280 struct cnx_mgr *cm_ctx = ctx; 281 bool status; 282 283 switch (event) { 284 case WLAN_CM_SM_EV_DISCONNECT_START: 285 cm_disconnect_start(cm_ctx, data); 286 status = true; 287 break; 288 case WLAN_CM_SM_EV_DISCONNECT_ACTIVE: 289 cm_disconnect_active(cm_ctx, data); 290 status = true; 291 break; 292 case WLAN_CM_SM_EV_DISCONNECT_DONE: 293 cm_sm_transition_to(cm_ctx, WLAN_CM_S_INIT); 294 cm_sm_deliver_event(cm_ctx, event, data_len, data); 295 status = true; 296 break; 297 default: 298 status = false; 299 break; 300 } 301 302 return status; 303 } 304 305 /** 306 * cm_subst_join_pending_entry() - Entry API for join pending sub-state for 307 * connection mgr 308 * @ctx: connection manager ctx 309 * 310 * API to perform operations on moving to join pending sub-state 311 * 312 * Return: void 313 */ 314 static void cm_subst_join_pending_entry(void *ctx) 315 { 316 struct cnx_mgr *cm_ctx = ctx; 317 318 if (cm_get_state(cm_ctx) != WLAN_CM_S_CONNECTING) 319 QDF_BUG(0); 320 321 cm_set_substate(cm_ctx, WLAN_CM_SS_JOIN_PENDING); 322 } 323 324 /** 325 * cm_subst_join_pending_exit() - Exit API for join pending sub-state for 326 * connection mgr 327 * @ctx: connection manager ctx 328 * 329 * API to perform operations on exiting from join pending sub-state 330 * 331 * Return: void 332 */ 333 static void cm_subst_join_pending_exit(void *ctx) 334 { 335 } 336 337 /** 338 * cm_subst_join_pending_event() - Join pending sub-state event handler for 339 * connection mgr 340 * @ctx: connection manager ctx 341 * 342 * API to handle events in Join pending sub-state 343 * 344 * Return: bool 345 */ 346 static bool cm_subst_join_pending_event(void *ctx, uint16_t event, 347 uint16_t data_len, void *data) 348 { 349 struct cnx_mgr *cm_ctx = ctx; 350 bool status; 351 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; 352 353 switch (event) { 354 case WLAN_CM_SM_EV_CONNECT_START: 355 cm_connect_start(cm_ctx, data); 356 status = true; 357 break; 358 case WLAN_CM_SM_EV_CONNECT_ACTIVE: 359 cm_sm_transition_to(cm_ctx, WLAN_CM_SS_JOIN_ACTIVE); 360 cm_sm_deliver_event(cm_ctx, event, data_len, data); 361 status = true; 362 break; 363 case WLAN_CM_SM_EV_SCAN: 364 cm_sm_transition_to(cm_ctx, WLAN_CM_SS_SCAN); 365 cm_sm_deliver_event(cm_ctx, event, data_len, data); 366 status = true; 367 break; 368 case WLAN_CM_SM_EV_SCAN_FAILURE: 369 qdf_status = QDF_STATUS_E_FAILURE; 370 /* Fall through after setting status failure */ 371 case WLAN_CM_SM_EV_SCAN_SUCCESS: 372 cm_connect_scan_resp(cm_ctx, data, qdf_status); 373 status = true; 374 break; 375 case WLAN_CM_SM_EV_CONNECT_FAILURE: 376 cm_sm_transition_to(cm_ctx, WLAN_CM_S_INIT); 377 cm_sm_deliver_event(cm_ctx, event, data_len, data); 378 status = true; 379 break; 380 default: 381 status = false; 382 break; 383 } 384 385 return status; 386 } 387 388 /** 389 * cm_subst_scan_entry() - Entry API for scan sub-state for 390 * connection mgr 391 * @ctx: connection manager ctx 392 * 393 * API to perform operations on moving to scan sub-state 394 * 395 * Return: void 396 */ 397 static void cm_subst_scan_entry(void *ctx) 398 { 399 struct cnx_mgr *cm_ctx = ctx; 400 401 if (cm_get_state(cm_ctx) != WLAN_CM_S_CONNECTING) 402 QDF_BUG(0); 403 404 cm_set_substate(cm_ctx, WLAN_CM_SS_SCAN); 405 } 406 407 /** 408 * cm_subst_scan_exit() - Exit API for scan sub-state for 409 * connection mgr 410 * @ctx: connection manager ctx 411 * 412 * API to perform operations on exiting from scan sub-state 413 * 414 * Return: void 415 */ 416 static void cm_subst_scan_exit(void *ctx) 417 { 418 } 419 420 /** 421 * cm_subst_scan_event() - Scan sub-state event handler for 422 * connection mgr 423 * @ctx: connection manager ctx 424 * 425 * API to handle events in scan sub-state 426 * 427 * Return: bool 428 */ 429 static bool cm_subst_scan_event(void *ctx, uint16_t event, 430 uint16_t data_len, void *data) 431 { 432 struct cnx_mgr *cm_ctx = ctx; 433 bool status; 434 435 switch (event) { 436 case WLAN_CM_SM_EV_SCAN: 437 cm_connect_scan_start(cm_ctx, data); 438 status = true; 439 break; 440 case WLAN_CM_SM_EV_SCAN_SUCCESS: 441 case WLAN_CM_SM_EV_SCAN_FAILURE: 442 cm_sm_transition_to(cm_ctx, WLAN_CM_SS_JOIN_PENDING); 443 cm_sm_deliver_event(cm_ctx, event, data_len, data); 444 status = true; 445 break; 446 default: 447 status = false; 448 break; 449 } 450 451 return status; 452 } 453 454 /** 455 * cm_subst_join_active_entry() - Entry API for join active sub-state for 456 * connection mgr 457 * @ctx: connection manager ctx 458 * 459 * API to perform operations on moving to join active sub-state 460 * 461 * Return: void 462 */ 463 static void cm_subst_join_active_entry(void *ctx) 464 { 465 struct cnx_mgr *cm_ctx = ctx; 466 467 if (cm_get_state(cm_ctx) != WLAN_CM_S_CONNECTING) 468 QDF_BUG(0); 469 470 cm_set_substate(cm_ctx, WLAN_CM_SS_JOIN_ACTIVE); 471 } 472 473 /** 474 * cm_subst_join_active_exit() - Exit API for join active sub-state for 475 * connection mgr 476 * @ctx: connection manager ctx 477 * 478 * API to perform operations on exiting from join active sub-state 479 * 480 * Return: void 481 */ 482 static void cm_subst_join_active_exit(void *ctx) 483 { 484 } 485 486 /** 487 * cm_subst_join_active_event() - Join active sub-state event handler for 488 * connection mgr 489 * @ctx: connection manager ctx 490 * 491 * API to handle events in join active sub-state 492 * 493 * Return: bool 494 */ 495 static bool cm_subst_join_active_event(void *ctx, uint16_t event, 496 uint16_t data_len, void *data) 497 { 498 struct cnx_mgr *cm_ctx = ctx; 499 bool status; 500 501 switch (event) { 502 case WLAN_CM_SM_EV_CONNECT_ACTIVE: 503 cm_connect_active(cm_ctx, data); 504 status = true; 505 break; 506 case WLAN_CM_SM_EV_CONNECT_SUCCESS: 507 cm_sm_transition_to(cm_ctx, WLAN_CM_S_CONNECTED); 508 cm_sm_deliver_event(cm_ctx, event, data_len, data); 509 status = true; 510 break; 511 case WLAN_CM_SM_EV_CONNECT_GET_NEXT_CANDIDATE: 512 cm_try_next_candidate(cm_ctx, data); 513 status = true; 514 break; 515 case WLAN_CM_SM_EV_CONNECT_FAILURE: 516 cm_sm_transition_to(cm_ctx, WLAN_CM_S_INIT); 517 cm_sm_deliver_event(cm_ctx, event, data_len, data); 518 status = true; 519 break; 520 default: 521 status = false; 522 break; 523 } 524 525 return status; 526 } 527 528 struct wlan_sm_state_info cm_sm_info[] = { 529 { 530 (uint8_t)WLAN_CM_S_INIT, 531 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 532 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 533 true, 534 "INIT", 535 cm_state_init_entry, 536 cm_state_init_exit, 537 cm_state_init_event 538 }, 539 { 540 (uint8_t)WLAN_CM_S_CONNECTING, 541 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 542 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 543 true, 544 "CONNECTING", 545 cm_state_connecting_entry, 546 cm_state_connecting_exit, 547 cm_state_connecting_event 548 }, 549 { 550 (uint8_t)WLAN_CM_S_CONNECTED, 551 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 552 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 553 true, 554 "CONNECTED", 555 cm_state_connected_entry, 556 cm_state_connected_exit, 557 cm_state_connected_event 558 }, 559 { 560 (uint8_t)WLAN_CM_S_DISCONNECTING, 561 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 562 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 563 true, 564 "DISCONNECTING", 565 cm_state_disconnecting_entry, 566 cm_state_disconnecting_exit, 567 cm_state_disconnecting_event 568 }, 569 { 570 (uint8_t)WLAN_CM_S_ROAMING, 571 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 572 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 573 true, 574 "ROAMING", 575 cm_state_roaming_entry, 576 cm_state_roaming_exit, 577 cm_state_roaming_event 578 }, 579 { 580 (uint8_t)WLAN_CM_S_MAX, 581 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 582 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 583 false, 584 "INVALID", 585 NULL, 586 NULL, 587 NULL 588 }, 589 { 590 (uint8_t)WLAN_CM_SS_IDLE, 591 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 592 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 593 false, 594 "IDLE", 595 NULL, 596 NULL, 597 NULL 598 }, 599 { 600 (uint8_t)WLAN_CM_SS_JOIN_PENDING, 601 (uint8_t)WLAN_CM_S_CONNECTING, 602 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 603 false, 604 "JOIN_PENDING", 605 cm_subst_join_pending_entry, 606 cm_subst_join_pending_exit, 607 cm_subst_join_pending_event 608 }, 609 { 610 (uint8_t)WLAN_CM_SS_SCAN, 611 (uint8_t)WLAN_CM_S_CONNECTING, 612 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 613 false, 614 "SCAN", 615 cm_subst_scan_entry, 616 cm_subst_scan_exit, 617 cm_subst_scan_event 618 }, 619 { 620 (uint8_t)WLAN_CM_SS_JOIN_ACTIVE, 621 (uint8_t)WLAN_CM_S_CONNECTING, 622 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 623 false, 624 "JOIN_ACTIVE", 625 cm_subst_join_active_entry, 626 cm_subst_join_active_exit, 627 cm_subst_join_active_event 628 }, 629 #ifdef WLAN_FEATURE_HOST_ROAM 630 { 631 (uint8_t)WLAN_CM_SS_PREAUTH, 632 (uint8_t)WLAN_CM_S_ROAMING, 633 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 634 false, 635 "PREAUTH", 636 cm_subst_preauth_entry, 637 cm_subst_preauth_exit, 638 cm_subst_preauth_event 639 }, 640 { 641 (uint8_t)WLAN_CM_SS_REASSOC, 642 (uint8_t)WLAN_CM_S_ROAMING, 643 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 644 false, 645 "REASSOC", 646 cm_subst_reassoc_entry, 647 cm_subst_reassoc_exit, 648 cm_subst_reassoc_event 649 }, 650 #endif 651 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 652 { 653 (uint8_t)WLAN_CM_SS_ROAM_STARTED, 654 (uint8_t)WLAN_CM_S_ROAMING, 655 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 656 false, 657 "ROAM_START", 658 cm_subst_roam_start_entry, 659 cm_subst_roam_start_exit, 660 cm_subst_roam_start_event 661 }, 662 { 663 (uint8_t)WLAN_CM_SS_ROAM_SYNC, 664 (uint8_t)WLAN_CM_S_ROAMING, 665 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 666 false, 667 "ROAM_SYNC", 668 cm_subst_roam_sync_entry, 669 cm_subst_roam_sync_exit, 670 cm_subst_roam_sync_event 671 }, 672 #endif 673 { 674 (uint8_t)WLAN_CM_SS_MAX, 675 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 676 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 677 false, 678 "INVALID", 679 NULL, 680 NULL, 681 NULL 682 }, 683 }; 684 685 static const char *cm_sm_event_names[] = { 686 "EV_CONNECT_REQ", 687 "EV_SCAN", 688 "EV_SCAN_SUCCESS", 689 "EV_SCAN_FAILURE", 690 "EV_CONNECT_START", 691 "EV_CONNECT_ACTIVE", 692 "EV_CONNECT_SUCCESS", 693 "EV_CONNECT_GET_NXT_CANDIDATE", 694 "EV_CONNECT_FAILURE", 695 "EV_DISCONNECT_REQ", 696 "EV_DISCONNECT_START", 697 "EV_DISCONNECT_ACTIVE", 698 "EV_DISCONNECT_DONE", 699 "EV_ROAM_START", 700 "EV_ROAM_SYNC", 701 "EV_ROAM_INVOKE_FAIL", 702 "EV_ROAM_HO_FAIL", 703 "EV_PREAUTH_DONE", 704 "EV_GET_NEXT_PREAUTH_AP", 705 "EV_PREAUTH_FAIL", 706 "EV_START_REASSOC", 707 "EV_REASSOC_DONE", 708 "EV_REASSOC_FAILURE", 709 "EV_ROAM_COMPLETE", 710 }; 711 712 enum wlan_cm_sm_state cm_get_state(struct cnx_mgr *cm_ctx) 713 { 714 enum QDF_OPMODE op_mode; 715 716 if (!cm_ctx || !cm_ctx->vdev) 717 return WLAN_CM_S_MAX; 718 719 op_mode = wlan_vdev_mlme_get_opmode(cm_ctx->vdev); 720 721 if (op_mode != QDF_STA_MODE && op_mode != QDF_P2P_CLIENT_MODE) 722 return WLAN_CM_S_MAX; 723 724 return cm_ctx->sm.cm_state; 725 } 726 727 enum wlan_cm_sm_state cm_get_sub_state(struct cnx_mgr *cm_ctx) 728 { 729 enum QDF_OPMODE op_mode; 730 731 if (!cm_ctx || !cm_ctx->vdev) 732 return WLAN_CM_SS_MAX; 733 734 op_mode = wlan_vdev_mlme_get_opmode(cm_ctx->vdev); 735 736 if (op_mode != QDF_STA_MODE && op_mode != QDF_P2P_CLIENT_MODE) 737 return WLAN_CM_SS_MAX; 738 739 return cm_ctx->sm.cm_substate; 740 } 741 742 static void cm_sm_print_state_event(struct cnx_mgr *cm_ctx, 743 enum wlan_cm_sm_evt event) 744 { 745 enum wlan_cm_sm_state state; 746 enum wlan_cm_sm_state substate; 747 748 state = cm_get_state(cm_ctx); 749 substate = cm_get_sub_state(cm_ctx); 750 751 mlme_nofl_debug("[%s]%s - %s, %s", cm_ctx->sm.sm_hdl->name, 752 cm_sm_info[state].name, cm_sm_info[substate].name, 753 cm_sm_event_names[event]); 754 } 755 756 static void cm_sm_print_state(struct cnx_mgr *cm_ctx) 757 { 758 enum wlan_cm_sm_state state; 759 enum wlan_cm_sm_state substate; 760 761 state = cm_get_state(cm_ctx); 762 substate = cm_get_sub_state(cm_ctx); 763 764 mlme_nofl_debug("[%s]%s - %s", cm_ctx->sm.sm_hdl->name, 765 cm_sm_info[state].name, cm_sm_info[substate].name); 766 } 767 768 QDF_STATUS wlan_cm_sm_deliver_evt(struct wlan_objmgr_vdev *vdev, 769 enum wlan_cm_sm_evt event, 770 uint16_t data_len, void *data) 771 { 772 struct vdev_mlme_obj *vdev_mlme; 773 QDF_STATUS status; 774 enum wlan_cm_sm_state state_entry, state_exit; 775 enum wlan_cm_sm_state substate_entry, substate_exit; 776 enum QDF_OPMODE op_mode = wlan_vdev_mlme_get_opmode(vdev); 777 struct cnx_mgr *cm_ctx; 778 779 if (op_mode != QDF_STA_MODE && op_mode != QDF_P2P_CLIENT_MODE) { 780 mlme_err("Invalid mode %d", op_mode); 781 return QDF_STATUS_E_NOSUPPORT; 782 } 783 784 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 785 if (!vdev_mlme || !vdev_mlme->cnx_mgr_ctx) { 786 mlme_err("vdev mlme or cm ctx is NULL"); 787 return QDF_STATUS_E_FAILURE; 788 } 789 cm_ctx = vdev_mlme->cnx_mgr_ctx; 790 cm_lock_acquire(cm_ctx); 791 792 /* store entry state and sub state for prints */ 793 state_entry = cm_get_state(cm_ctx); 794 substate_entry = cm_get_sub_state(cm_ctx); 795 cm_sm_print_state_event(cm_ctx, event); 796 797 status = cm_sm_deliver_event(cm_ctx, event, data_len, data); 798 /* Take exit state, exit substate for prints */ 799 state_exit = cm_get_state(cm_ctx); 800 substate_exit = cm_get_sub_state(cm_ctx); 801 /* If no state and substate change, don't print */ 802 if (!((state_entry == state_exit) && (substate_entry == substate_exit))) 803 cm_sm_print_state(cm_ctx); 804 cm_lock_release(cm_ctx); 805 806 return status; 807 } 808 809 QDF_STATUS cm_sm_create(struct cnx_mgr *cm_ctx) 810 { 811 struct wlan_sm *sm; 812 uint8_t name[WLAN_SM_ENGINE_MAX_NAME]; 813 814 qdf_snprintf(name, sizeof(name), "CM-VDEV-%d", 815 wlan_vdev_get_id(cm_ctx->vdev)); 816 sm = wlan_sm_create(name, cm_ctx, 817 WLAN_CM_S_INIT, 818 cm_sm_info, 819 QDF_ARRAY_SIZE(cm_sm_info), 820 cm_sm_event_names, 821 QDF_ARRAY_SIZE(cm_sm_event_names)); 822 if (!sm) { 823 mlme_err("CM MLME SM allocation failed"); 824 return QDF_STATUS_E_NOMEM; 825 } 826 cm_ctx->sm.sm_hdl = sm; 827 828 cm_lock_create(cm_ctx); 829 830 return QDF_STATUS_SUCCESS; 831 } 832 833 QDF_STATUS cm_sm_destroy(struct cnx_mgr *cm_ctx) 834 { 835 cm_lock_destroy(cm_ctx); 836 wlan_sm_delete(cm_ctx->sm.sm_hdl); 837 838 return QDF_STATUS_SUCCESS; 839 } 840