1 /* 2 * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /** 20 * DOC: Implements VDEV MLME SM 21 */ 22 23 #include <wlan_objmgr_vdev_obj.h> 24 #include <wlan_mlme_dbg.h> 25 #include <wlan_sm_engine.h> 26 #include "include/wlan_vdev_mlme.h" 27 #include "vdev_mlme_sm.h" 28 29 #ifdef CMN_VDEV_MLME_SM_ENABLE 30 /** 31 * mlme_vdev_set_state() - set mlme state 32 * @vdev: VDEV object 33 * @state: MLME state 34 * 35 * API to set MLME state 36 * 37 * Return: void 38 */ 39 static void mlme_vdev_set_state(struct wlan_objmgr_vdev *vdev, 40 enum wlan_vdev_state state) 41 { 42 if (state < WLAN_VDEV_S_MAX) { 43 vdev->vdev_mlme.mlme_state = state; 44 } else { 45 mlme_err("mlme state (%d) is invalid", state); 46 QDF_BUG(0); 47 } 48 } 49 50 /** 51 * mlme_vdev_set_substate() - set mlme sub state 52 * @vdev: VDEV object 53 * @substate: MLME sub state 54 * 55 * API to set MLME sub state 56 * 57 * Return: void 58 */ 59 static void mlme_vdev_set_substate(struct wlan_objmgr_vdev *vdev, 60 enum wlan_vdev_state substate) 61 { 62 if ((substate > WLAN_VDEV_S_MAX) && (substate < WLAN_VDEV_SS_MAX)) { 63 vdev->vdev_mlme.mlme_substate = substate; 64 } else { 65 mlme_err(" mlme sub state (%d) is invalid", substate); 66 QDF_BUG(0); 67 } 68 } 69 70 /** 71 * mlme_vdev_sm_state_update() - set mlme state and sub state 72 * @vdev_mlme: MLME VDEV comp object 73 * @state: MLME state 74 * @substate: MLME sub state 75 * 76 * API to invoke util APIs to set state and MLME sub state 77 * 78 * Return: void 79 */ 80 static void mlme_vdev_sm_state_update(struct vdev_mlme_obj *vdev_mlme, 81 enum wlan_vdev_state state, 82 enum wlan_vdev_state substate) 83 { 84 struct wlan_objmgr_vdev *vdev; 85 86 vdev = vdev_mlme->vdev; 87 if (!vdev) { 88 mlme_err(" VDEV is NULL"); 89 QDF_BUG(0); 90 } 91 92 mlme_vdev_set_state(vdev, state); 93 mlme_vdev_set_substate(vdev, substate); 94 } 95 96 /** 97 * mlme_vdev_sm_transition_to() - invokes state transition 98 * @vdev_mlme: MLME VDEV comp object 99 * @state: new MLME state 100 * 101 * API to invoke SM API to move to new state 102 * 103 * Return: void 104 */ 105 static void mlme_vdev_sm_transition_to(struct vdev_mlme_obj *vdev_mlme, 106 enum wlan_vdev_state state) 107 { 108 wlan_sm_transition_to(vdev_mlme->sm_hdl, state); 109 } 110 111 /** 112 * mlme_vdev_state_init_entry() - Entry API for Init state 113 * @ctx: VDEV MLME object 114 * 115 * API to perform operations on moving to INIT state 116 * 117 * Return: void 118 */ 119 static void mlme_vdev_state_init_entry(void *ctx) 120 { 121 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 122 123 mlme_vdev_sm_state_update(vdev_mlme, WLAN_VDEV_S_INIT, 124 WLAN_VDEV_SS_IDLE); 125 } 126 127 /** 128 * mlme_vdev_state_init_exit() - Exit API for Init state 129 * @ctx: VDEV MLME object 130 * 131 * API to perform operations on moving out of INIT state 132 * 133 * Return: void 134 */ 135 static void mlme_vdev_state_init_exit(void *ctx) 136 { 137 /* NONE */ 138 } 139 140 /** 141 * mlme_vdev_state_init_event() - Init State event handler 142 * @ctx: VDEV MLME object 143 * 144 * API to handle events in INIT state 145 * 146 * Return: SUCCESS: on handling event 147 * FAILURE: on ignoring the event 148 */ 149 static bool mlme_vdev_state_init_event(void *ctx, uint16_t event, 150 uint16_t event_data_len, 151 void *event_data) 152 { 153 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 154 bool status; 155 156 switch (event) { 157 case WLAN_VDEV_SM_EV_START: 158 /* call mlme callback API for sanity checks */ 159 if (mlme_vdev_validate_basic_params(vdev_mlme, event_data_len, 160 event_data) == QDF_STATUS_SUCCESS) { 161 mlme_vdev_sm_transition_to(vdev_mlme, 162 WLAN_VDEV_S_START); 163 mlme_vdev_sm_deliver_event(vdev_mlme, 164 WLAN_VDEV_SM_EV_START_REQ, 165 event_data_len, event_data); 166 status = true; 167 } else { 168 mlme_err( 169 "failed to validate vdev init params to move to START state"); 170 status = true; 171 } 172 break; 173 174 case WLAN_VDEV_SM_EV_DOWN_COMPLETE: 175 case WLAN_VDEV_SM_EV_DOWN: 176 case WLAN_VDEV_SM_EV_START_REQ_FAIL: 177 /* already in down state, notify DOWN command is completed */ 178 /* NOTE: Keep this function call always at the end, to allow 179 * connection restart from this event 180 */ 181 mlme_vdev_notify_down_complete(vdev_mlme, event_data_len, 182 event_data); 183 status = true; 184 break; 185 186 default: 187 status = false; 188 break; 189 } 190 191 return status; 192 } 193 194 /** 195 * mlme_vdev_state_start_entry() - Entry API for Start state 196 * @ctx: VDEV MLME object 197 * 198 * API to perform operations on moving to START state 199 * 200 * Return: void 201 */ 202 static void mlme_vdev_state_start_entry(void *ctx) 203 { 204 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 205 206 mlme_vdev_sm_state_update(vdev_mlme, WLAN_VDEV_S_START, 207 WLAN_VDEV_SS_IDLE); 208 } 209 210 /** 211 * mlme_vdev_state_start_exit() - Exit API for Start state 212 * @ctx: VDEV MLME object 213 * 214 * API to perform operations on moving out of START state 215 * 216 * Return: void 217 */ 218 static void mlme_vdev_state_start_exit(void *ctx) 219 { 220 /* NONE */ 221 } 222 223 /** 224 * mlme_vdev_state_start_event() - Start State event handler 225 * @ctx: VDEV MLME object 226 * 227 * API to handle events in START state 228 * 229 * Return: SUCCESS: on handling event 230 * FAILURE: on ignoring the event 231 */ 232 static bool mlme_vdev_state_start_event(void *ctx, uint16_t event, 233 uint16_t event_data_len, 234 void *event_data) 235 { 236 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 237 bool status; 238 239 switch (event) { 240 case WLAN_VDEV_SM_EV_START_REQ: 241 mlme_vdev_sm_transition_to(vdev_mlme, 242 WLAN_VDEV_SS_START_START_PROGRESS); 243 mlme_vdev_sm_deliver_event(vdev_mlme, event, event_data_len, 244 event_data); 245 status = true; 246 break; 247 248 case WLAN_VDEV_SM_EV_RESTART_REQ: 249 case WLAN_VDEV_SM_EV_RADAR_DETECTED: 250 mlme_vdev_sm_transition_to(vdev_mlme, 251 WLAN_VDEV_SS_START_RESTART_PROGRESS); 252 mlme_vdev_sm_deliver_event(vdev_mlme, event, event_data_len, 253 event_data); 254 status = true; 255 break; 256 257 case WLAN_VDEV_SM_EV_STA_CONN_START: 258 mlme_vdev_sm_transition_to(vdev_mlme, 259 WLAN_VDEV_SS_START_CONN_PROGRESS); 260 mlme_vdev_sm_deliver_event(vdev_mlme, event, 261 event_data_len, event_data); 262 status = true; 263 break; 264 265 default: 266 status = false; 267 break; 268 } 269 270 return status; 271 } 272 273 /** 274 * mlme_vdev_state_dfs_cac_wait_entry() - Entry API for DFS CAC WAIT state 275 * @ctx: VDEV MLME object 276 * 277 * API to perform operations on moving to DFS CAC WAIT state 278 * 279 * Return: void 280 */ 281 static void mlme_vdev_state_dfs_cac_wait_entry(void *ctx) 282 { 283 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 284 285 mlme_vdev_sm_state_update(vdev_mlme, WLAN_VDEV_S_DFS_CAC_WAIT, 286 WLAN_VDEV_SS_IDLE); 287 } 288 289 /** 290 * mlme_vdev_state_dfs_cac_wait_exit() - Exit API for DFS CAC WAIT state 291 * @ctx: VDEV MLME object 292 * 293 * API to perform operations on moving out of DFS CAC WAIT state 294 * 295 * Return: void 296 */ 297 static void mlme_vdev_state_dfs_cac_wait_exit(void *ctx) 298 { 299 /* NONE */ 300 } 301 302 /** 303 * mlme_vdev_state_dfs_cac_wait_event() - DFS CAC WAIT State event handler 304 * @ctx: VDEV MLME object 305 * 306 * API to handle events in DFS CAC WAIT state 307 * 308 * Return: SUCCESS: on handling event 309 * FAILURE: on ignoring the event 310 */ 311 static bool mlme_vdev_state_dfs_cac_wait_event(void *ctx, uint16_t event, 312 uint16_t event_data_len, 313 void *event_data) 314 { 315 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 316 enum QDF_OPMODE mode; 317 struct wlan_objmgr_vdev *vdev; 318 bool status; 319 320 vdev = vdev_mlme->vdev; 321 322 mode = wlan_vdev_mlme_get_opmode(vdev); 323 324 switch (event) { 325 case WLAN_VDEV_SM_EV_DFS_CAC_WAIT: 326 /* DFS timer should have started already, then only this event 327 * could have been triggered 328 */ 329 status = true; 330 break; 331 332 case WLAN_VDEV_SM_EV_DOWN: 333 /* stop the CAC timer, then notify state machine */ 334 mlme_vdev_dfs_cac_timer_stop(vdev_mlme, event_data_len, 335 event_data); 336 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_STOP); 337 mlme_vdev_sm_deliver_event(vdev_mlme, WLAN_VDEV_SM_EV_DOWN, 338 event_data_len, event_data); 339 status = true; 340 break; 341 342 case WLAN_VDEV_SM_EV_RADAR_DETECTED: 343 /* the random channel should have been selected, before issuing 344 * this event 345 */ 346 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_START); 347 mlme_vdev_sm_deliver_event(vdev_mlme, 348 WLAN_VDEV_SM_EV_RESTART_REQ, 349 event_data_len, event_data); 350 status = true; 351 break; 352 353 case WLAN_VDEV_SM_EV_DFS_CAC_COMPLETED: 354 if (mode == QDF_STA_MODE) { 355 mlme_vdev_sm_transition_to(vdev_mlme, 356 WLAN_VDEV_S_START); 357 mlme_vdev_sm_deliver_event(vdev_mlme, 358 WLAN_VDEV_SM_EV_STA_CONN_START, 359 event_data_len, event_data); 360 } else { 361 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_UP); 362 mlme_vdev_sm_deliver_event(vdev_mlme, 363 WLAN_VDEV_SM_EV_START_SUCCESS, 364 event_data_len, event_data); 365 } 366 status = true; 367 break; 368 369 default: 370 status = false; 371 break; 372 } 373 374 return status; 375 } 376 377 /** 378 * mlme_vdev_state_up_entry() - Entry API for UP state 379 * @ctx: VDEV MLME object 380 * 381 * API to perform operations on moving to UP state 382 * 383 * Return: void 384 */ 385 static void mlme_vdev_state_up_entry(void *ctx) 386 { 387 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 388 389 mlme_vdev_sm_state_update(vdev_mlme, WLAN_VDEV_S_UP, 390 WLAN_VDEV_SS_IDLE); 391 } 392 393 /** 394 * mlme_vdev_state_up_exit() - Exit API for UP state 395 * @ctx: VDEV MLME object 396 * 397 * API to perform operations on moving out of UP state 398 * 399 * Return: void 400 */ 401 static void mlme_vdev_state_up_exit(void *ctx) 402 { 403 /* NONE */ 404 } 405 406 /** 407 * mlme_vdev_state_up_event() - UP State event handler 408 * @ctx: VDEV MLME object 409 * 410 * API to handle events in UP state 411 * 412 * Return: SUCCESS: on handling event 413 * FAILURE: on ignoring the event 414 */ 415 static bool mlme_vdev_state_up_event(void *ctx, uint16_t event, 416 uint16_t event_data_len, void *event_data) 417 { 418 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 419 enum QDF_OPMODE mode; 420 struct wlan_objmgr_vdev *vdev; 421 bool status; 422 423 vdev = vdev_mlme->vdev; 424 mode = wlan_vdev_mlme_get_opmode(vdev); 425 426 switch (event) { 427 case WLAN_VDEV_SM_EV_START_SUCCESS: 428 mlme_vdev_update_beacon(vdev_mlme, BEACON_INIT, 429 event_data_len, event_data); 430 if (mlme_vdev_up_send(vdev_mlme, event_data_len, 431 event_data) != QDF_STATUS_SUCCESS) 432 mlme_vdev_sm_deliver_event(vdev_mlme, 433 WLAN_VDEV_SM_EV_UP_FAIL, 434 event_data_len, event_data); 435 else 436 mlme_vdev_notify_up_complete(vdev_mlme, event_data_len, 437 event_data); 438 439 status = true; 440 break; 441 442 case WLAN_VDEV_SM_EV_SUPSEND_RESTART: 443 case WLAN_VDEV_SM_EV_HOST_RESTART: 444 case WLAN_VDEV_SM_EV_CSA_RESTART: 445 /* These events are not supported in STA mode */ 446 if (mode == QDF_STA_MODE) 447 QDF_BUG(0); 448 449 case WLAN_VDEV_SM_EV_DOWN: 450 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_SUSPEND); 451 mlme_vdev_sm_deliver_event(vdev_mlme, event, 452 event_data_len, event_data); 453 status = true; 454 break; 455 456 case WLAN_VDEV_SM_EV_RADAR_DETECTED: 457 /* These events are not supported in STA mode */ 458 if (mode == QDF_STA_MODE) 459 QDF_BUG(0); 460 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_SUSPEND); 461 mlme_vdev_sm_deliver_event(vdev_mlme, 462 WLAN_VDEV_SM_EV_CSA_RESTART, 463 event_data_len, event_data); 464 status = true; 465 break; 466 467 case WLAN_VDEV_SM_EV_UP_HOST_RESTART: 468 /* Reinit beacon, send template to FW(use ping-pong buffer) */ 469 mlme_vdev_update_beacon(vdev_mlme, BEACON_UPDATE, 470 event_data_len, event_data); 471 case WLAN_VDEV_SM_EV_START: 472 /* notify that UP command is completed */ 473 mlme_vdev_notify_up_complete(vdev_mlme, 474 event_data_len, event_data); 475 status = true; 476 break; 477 478 case WLAN_VDEV_SM_EV_FW_VDEV_RESTART: 479 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_START); 480 mlme_vdev_sm_deliver_event(vdev_mlme, 481 WLAN_VDEV_SM_EV_RESTART_REQ, 482 event_data_len, event_data); 483 status = true; 484 break; 485 486 case WLAN_VDEV_SM_EV_UP_FAIL: 487 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_SUSPEND); 488 mlme_vdev_sm_deliver_event(vdev_mlme, event, 489 event_data_len, event_data); 490 status = true; 491 break; 492 493 case WLAN_VDEV_SM_EV_ROAM: 494 mlme_vdev_notify_roam_start(vdev_mlme, event_data_len, 495 event_data); 496 status = true; 497 break; 498 499 default: 500 status = false; 501 break; 502 } 503 504 return status; 505 } 506 507 /** 508 * mlme_vdev_state_suspend_entry() - Entry API for Suspend state 509 * @ctx: VDEV MLME object 510 * 511 * API to perform operations on moving to SUSPEND state 512 * 513 * Return: void 514 */ 515 static void mlme_vdev_state_suspend_entry(void *ctx) 516 { 517 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 518 519 mlme_vdev_sm_state_update(vdev_mlme, WLAN_VDEV_S_SUSPEND, 520 WLAN_VDEV_SS_IDLE); 521 } 522 523 /** 524 * mlme_vdev_state_suspend_exit() - Exit API for Suspend state 525 * @ctx: VDEV MLME object 526 * 527 * API to perform operations on moving out of SUSPEND state 528 * 529 * Return: void 530 */ 531 static void mlme_vdev_state_suspend_exit(void *ctx) 532 { 533 /* NONE */ 534 } 535 536 /** 537 * mlme_vdev_state_suspend_event() - Suspend State event handler 538 * @ctx: VDEV MLME object 539 * 540 * API to handle events in SUSPEND state 541 * 542 * Return: SUCCESS: on handling event 543 * FAILURE: on ignoring the event 544 */ 545 static bool mlme_vdev_state_suspend_event(void *ctx, uint16_t event, 546 uint16_t event_data_len, 547 void *event_data) 548 { 549 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 550 bool status; 551 552 switch (event) { 553 case WLAN_VDEV_SM_EV_DOWN: 554 case WLAN_VDEV_SM_EV_RESTART_REQ_FAIL: 555 mlme_vdev_sm_transition_to(vdev_mlme, 556 WLAN_VDEV_SS_SUSPEND_SUSPEND_DOWN); 557 mlme_vdev_sm_deliver_event(vdev_mlme, event, 558 event_data_len, event_data); 559 status = true; 560 break; 561 562 case WLAN_VDEV_SM_EV_SUPSEND_RESTART: 563 mlme_vdev_sm_transition_to(vdev_mlme, 564 WLAN_VDEV_SS_SUSPEND_SUSPEND_RESTART); 565 mlme_vdev_sm_deliver_event(vdev_mlme, event, 566 event_data_len, event_data); 567 status = true; 568 break; 569 570 case WLAN_VDEV_SM_EV_HOST_RESTART: 571 mlme_vdev_sm_transition_to(vdev_mlme, 572 WLAN_VDEV_SS_SUSPEND_HOST_RESTART); 573 mlme_vdev_sm_deliver_event(vdev_mlme, event, 574 event_data_len, event_data); 575 status = true; 576 break; 577 578 case WLAN_VDEV_SM_EV_CSA_RESTART: 579 mlme_vdev_sm_transition_to(vdev_mlme, 580 WLAN_VDEV_SS_SUSPEND_CSA_RESTART); 581 mlme_vdev_sm_deliver_event(vdev_mlme, event, 582 event_data_len, event_data); 583 status = true; 584 break; 585 586 case WLAN_VDEV_SM_EV_UP_FAIL: 587 mlme_vdev_sm_transition_to(vdev_mlme, 588 WLAN_VDEV_SS_SUSPEND_SUSPEND_DOWN); 589 mlme_vdev_sm_deliver_event(vdev_mlme, WLAN_VDEV_SM_EV_DOWN, 590 event_data_len, event_data); 591 status = true; 592 break; 593 594 default: 595 status = false; 596 break; 597 } 598 599 return status; 600 } 601 602 /** 603 * mlme_vdev_state_stop_entry() - Entry API for Stop state 604 * @ctx: VDEV MLME object 605 * 606 * API to perform operations on moving to STOP state 607 * 608 * Return: void 609 */ 610 static void mlme_vdev_state_stop_entry(void *ctx) 611 { 612 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *) ctx; 613 614 mlme_vdev_sm_state_update(vdev_mlme, WLAN_VDEV_S_STOP, 615 WLAN_VDEV_SS_IDLE); 616 } 617 618 /** 619 * mlme_vdev_state_stop_exit() - Exit API for Stop state 620 * @ctx: VDEV MLME object 621 * 622 * API to perform operations on moving out of STOP state 623 * 624 * Return: void 625 */ 626 static void mlme_vdev_state_stop_exit(void *ctx) 627 { 628 /* NONE */ 629 } 630 631 /** 632 * mlme_vdev_state_stop_event() - Stop State event handler 633 * @ctx: VDEV MLME object 634 * 635 * API to handle events in STOP state 636 * 637 * Return: SUCCESS: on handling event 638 * FAILURE: on ignoring the event 639 */ 640 static bool mlme_vdev_state_stop_event(void *ctx, uint16_t event, 641 uint16_t event_data_len, 642 void *event_data) 643 { 644 QDF_BUG(0); 645 return false; 646 } 647 648 /** 649 * mlme_vdev_subst_start_start_progress_entry() - Entry API for Start Progress 650 * sub state 651 * @ctx: VDEV MLME object 652 * 653 * API to perform operations on moving to START-PROGRESS substate 654 * 655 * Return: void 656 */ 657 static void mlme_vdev_subst_start_start_progress_entry(void *ctx) 658 { 659 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 660 struct wlan_objmgr_vdev *vdev; 661 662 vdev = vdev_mlme->vdev; 663 664 if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_START) 665 QDF_BUG(0); 666 667 mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_START_START_PROGRESS); 668 } 669 670 /** 671 * mlme_vdev_subst_start_start_progress_exit() - Exit API for Start Progress 672 * sub state 673 * @ctx: VDEV MLME object 674 * 675 * API to perform operations on moving out of START-PROGRESS substate 676 * 677 * Return: void 678 */ 679 static void mlme_vdev_subst_start_start_progress_exit(void *ctx) 680 { 681 /* NONE */ 682 } 683 684 /** 685 * mlme_vdev_subst_start_start_progress_event() - Event handler API for Start 686 * Progress substate 687 * @ctx: VDEV MLME object 688 * 689 * API to handle events in START-PROGRESS substate 690 * 691 * Return: SUCCESS: on handling event 692 * FAILURE: on ignoring the event 693 */ 694 static bool mlme_vdev_subst_start_start_progress_event(void *ctx, 695 uint16_t event, uint16_t event_data_len, void *event_data) 696 { 697 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 698 struct wlan_objmgr_vdev *vdev; 699 bool status; 700 701 vdev = vdev_mlme->vdev; 702 703 switch (event) { 704 case WLAN_VDEV_SM_EV_START_REQ: 705 /* send vdev start req command to FW */ 706 mlme_vdev_start_send(vdev_mlme, event_data_len, event_data); 707 status = true; 708 break; 709 /* While waiting for START response, move to RESTART_PROGRESS, 710 * wait for START response to send RESTART req */ 711 case WLAN_VDEV_SM_EV_RADAR_DETECTED: 712 mlme_vdev_sm_transition_to(vdev_mlme, 713 WLAN_VDEV_SS_START_RESTART_PROGRESS); 714 status = true; 715 break; 716 case WLAN_VDEV_SM_EV_START_RESP: 717 case WLAN_VDEV_SM_EV_RESTART_RESP: 718 mlme_vdev_sm_transition_to(vdev_mlme, 719 WLAN_VDEV_SS_START_CONN_PROGRESS); 720 mlme_vdev_sm_deliver_event(vdev_mlme, 721 WLAN_VDEV_SM_EV_CONN_PROGRESS, 722 event_data_len, event_data); 723 status = true; 724 break; 725 726 case WLAN_VDEV_SM_EV_START_REQ_FAIL: 727 mlme_vdev_start_req_failed(vdev_mlme, 728 event_data_len, event_data); 729 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_INIT); 730 mlme_vdev_sm_deliver_event(vdev_mlme, event, 731 event_data_len, event_data); 732 status = true; 733 break; 734 735 case WLAN_VDEV_SM_EV_DOWN: 736 mlme_vdev_sm_transition_to(vdev_mlme, 737 WLAN_VDEV_SS_START_DISCONN_PROGRESS); 738 /* block start request, if it is pending */ 739 mlme_vdev_stop_start_send(vdev_mlme, START_REQ, 740 event_data_len, event_data); 741 status = true; 742 break; 743 744 default: 745 status = false; 746 break; 747 } 748 749 return status; 750 } 751 752 /** 753 * mlme_vdev_subst_start_restart_progress_entry() - Entry API for Restart 754 * progress sub state 755 * @ctx: VDEV MLME object 756 * 757 * API to perform operations on moving to RESTART-PROGRESS substate 758 * 759 * Return: void 760 */ 761 static void mlme_vdev_subst_start_restart_progress_entry(void *ctx) 762 { 763 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 764 struct wlan_objmgr_vdev *vdev; 765 766 vdev = vdev_mlme->vdev; 767 768 if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_START) 769 QDF_BUG(0); 770 771 mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_START_RESTART_PROGRESS); 772 } 773 774 /** 775 * mlme_vdev_subst_start_restart_progress_exit() - Exit API for Restart Progress 776 * sub state 777 * @ctx: VDEV MLME object 778 * 779 * API to perform operations on moving out of RESTART-PROGRESS substate 780 * 781 * Return: void 782 */ 783 static void mlme_vdev_subst_start_restart_progress_exit(void *ctx) 784 { 785 /* NONE */ 786 } 787 788 /** 789 * mlme_vdev_subst_start_restart_progress_event() - Event handler API for 790 * Restart Progress substate 791 * @ctx: VDEV MLME object 792 * 793 * API to handle events in RESTART-PROGRESS substate 794 * 795 * Return: SUCCESS: on handling event 796 * FAILURE: on ignoring the event 797 */ 798 static bool mlme_vdev_subst_start_restart_progress_event(void *ctx, 799 uint16_t event, uint16_t event_data_len, void *event_data) 800 { 801 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 802 struct wlan_objmgr_vdev *vdev; 803 bool status; 804 805 vdev = vdev_mlme->vdev; 806 807 switch (event) { 808 case WLAN_VDEV_SM_EV_RESTART_REQ: 809 /* If Start resp is pending, send restart after start response */ 810 case WLAN_VDEV_SM_EV_START_RESP: 811 /* send vdev restart req command to FW */ 812 mlme_vdev_restart_send(vdev_mlme, event_data_len, event_data); 813 status = true; 814 break; 815 case WLAN_VDEV_SM_EV_RESTART_RESP: 816 mlme_vdev_sm_transition_to(vdev_mlme, 817 WLAN_VDEV_SS_START_CONN_PROGRESS); 818 mlme_vdev_sm_deliver_event(vdev_mlme, 819 WLAN_VDEV_SM_EV_CONN_PROGRESS, 820 event_data_len, event_data); 821 status = true; 822 break; 823 824 case WLAN_VDEV_SM_EV_RESTART_REQ_FAIL: 825 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_SUSPEND); 826 mlme_vdev_sm_deliver_event(vdev_mlme, event, 827 event_data_len, event_data); 828 status = true; 829 break; 830 831 case WLAN_VDEV_SM_EV_DOWN: 832 mlme_vdev_sm_transition_to(vdev_mlme, 833 WLAN_VDEV_SS_START_DISCONN_PROGRESS); 834 /* block restart request, if it is pending */ 835 mlme_vdev_stop_start_send(vdev_mlme, RESTART_REQ, 836 event_data_len, event_data); 837 status = true; 838 break; 839 840 case WLAN_VDEV_SM_EV_RADAR_DETECTED: 841 /* It is complicated to handle RADAR detected in this substate, 842 * as vdev updates des channels as bss channel on response, 843 * it would be easily handled, if it is deferred by DFS module 844 */ 845 QDF_BUG(0); 846 status = true; 847 break; 848 849 default: 850 status = false; 851 break; 852 } 853 854 return status; 855 } 856 857 /** 858 * mlme_vdev_subst_start_conn_progress_entry() - Entry API for Conn. Progress 859 * sub state 860 * @ctx: VDEV MLME object 861 * 862 * API to perform operations on moving to CONN-PROGRESS substate 863 * 864 * Return: void 865 */ 866 static void mlme_vdev_subst_start_conn_progress_entry(void *ctx) 867 { 868 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 869 struct wlan_objmgr_vdev *vdev; 870 871 vdev = vdev_mlme->vdev; 872 873 if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_START) 874 QDF_BUG(0); 875 876 mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_START_CONN_PROGRESS); 877 } 878 879 /** 880 * mlme_vdev_subst_start_conn_progress_exit() - Exit API for Conn. Progress 881 * sub state 882 * @ctx: VDEV MLME object 883 * 884 * API to perform operations on moving out of CONN-PROGRESS substate 885 * 886 * Return: void 887 */ 888 static void mlme_vdev_subst_start_conn_progress_exit(void *ctx) 889 { 890 /* NONE */ 891 } 892 893 /** 894 * mlme_vdev_subst_start_conn_progress_event() - Event handler API for Conn. 895 * Progress substate 896 * @ctx: VDEV MLME object 897 * 898 * API to handle events in CONN-PROGRESS substate 899 * 900 * Return: SUCCESS: on handling event 901 * FAILURE: on ignoring the event 902 */ 903 static bool mlme_vdev_subst_start_conn_progress_event(void *ctx, 904 uint16_t event, 905 uint16_t event_data_len, 906 void *event_data) 907 { 908 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 909 enum QDF_OPMODE mode; 910 struct wlan_objmgr_vdev *vdev; 911 bool status; 912 913 vdev = vdev_mlme->vdev; 914 915 mode = wlan_vdev_mlme_get_opmode(vdev); 916 917 switch (event) { 918 case WLAN_VDEV_SM_EV_CONN_PROGRESS: 919 /* This API decides to move to DFS CAC WAIT or UP state, 920 * for station notify connection state machine */ 921 mlme_vdev_start_continue(vdev_mlme, event_data_len, event_data); 922 status = true; 923 break; 924 925 case WLAN_VDEV_SM_EV_DFS_CAC_WAIT: 926 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_DFS_CAC_WAIT); 927 mlme_vdev_sm_deliver_event(vdev_mlme, event, 928 event_data_len, event_data); 929 status = true; 930 break; 931 932 case WLAN_VDEV_SM_EV_START_SUCCESS: 933 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_UP); 934 mlme_vdev_sm_deliver_event(vdev_mlme, event, 935 event_data_len, event_data); 936 status = true; 937 break; 938 939 case WLAN_VDEV_SM_EV_STA_CONN_START: 940 /* This event triggers station connection, if it is blocked for 941 * CAC WAIT 942 */ 943 if (mode != QDF_STA_MODE) 944 QDF_BUG(0); 945 946 mlme_vdev_sta_conn_start(vdev_mlme, event_data_len, event_data); 947 status = true; 948 break; 949 950 case WLAN_VDEV_SM_EV_RADAR_DETECTED: 951 if (mode != QDF_STA_MODE) 952 QDF_BUG(0); 953 954 status = true; 955 break; 956 957 case WLAN_VDEV_SM_EV_DOWN: 958 case WLAN_VDEV_SM_EV_CONNECTION_FAIL: 959 mlme_vdev_sm_transition_to(vdev_mlme, 960 WLAN_VDEV_SS_START_DISCONN_PROGRESS); 961 mlme_vdev_sm_deliver_event(vdev_mlme, event, 962 event_data_len, event_data); 963 status = true; 964 break; 965 966 default: 967 status = false; 968 break; 969 } 970 971 return status; 972 } 973 974 /** 975 * mlme_vdev_subst_start_disconn_progress_entry() - Entry API for Disconn 976 * progress sub state 977 * @ctx: VDEV MLME object 978 * 979 * API to perform operations on moving to DISCONN-PROGRESS substate 980 * 981 * Return: SUCCESS: on handling event 982 * FAILURE: on ignoring the event 983 */ 984 static void mlme_vdev_subst_start_disconn_progress_entry(void *ctx) 985 { 986 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 987 struct wlan_objmgr_vdev *vdev; 988 989 vdev = vdev_mlme->vdev; 990 991 if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_START) 992 QDF_BUG(0); 993 994 mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_START_DISCONN_PROGRESS); 995 } 996 997 /** 998 * mlme_vdev_subst_start_disconn_progress_exit() - Exit API for Disconn Progress 999 * sub state 1000 * @ctx: VDEV MLME object 1001 * 1002 * API to perform operations on moving out of DISCONN-PROGRESS substate 1003 * 1004 * Return: void 1005 */ 1006 static void mlme_vdev_subst_start_disconn_progress_exit(void *ctx) 1007 { 1008 /* NONE */ 1009 } 1010 1011 /** 1012 * mlme_vdev_subst_start_disconn_progress_event() - Event handler API for Discon 1013 * Progress substate 1014 * @ctx: VDEV MLME object 1015 * 1016 * API to handle events in DISCONN-PROGRESS substate 1017 * 1018 * Return: SUCCESS: on handling event 1019 * FAILURE: on ignoring the event 1020 */ 1021 static bool mlme_vdev_subst_start_disconn_progress_event(void *ctx, 1022 uint16_t event, uint16_t event_data_len, void *event_data) 1023 { 1024 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 1025 bool status; 1026 1027 switch (event) { 1028 case WLAN_VDEV_SM_EV_START_RESP: 1029 /* clean up, if any needs to be cleaned up */ 1030 case WLAN_VDEV_SM_EV_CONNECTION_FAIL: 1031 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_STOP); 1032 mlme_vdev_sm_deliver_event(vdev_mlme, WLAN_VDEV_SM_EV_DOWN, 1033 event_data_len, event_data); 1034 status = true; 1035 break; 1036 1037 case WLAN_VDEV_SM_EV_RESTART_RESP: 1038 case WLAN_VDEV_SM_EV_RESTART_REQ_FAIL: 1039 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_SUSPEND); 1040 mlme_vdev_sm_deliver_event(vdev_mlme, WLAN_VDEV_SM_EV_DOWN, 1041 event_data_len, event_data); 1042 status = true; 1043 break; 1044 1045 case WLAN_VDEV_SM_EV_START_REQ_FAIL: 1046 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_INIT); 1047 mlme_vdev_sm_deliver_event(vdev_mlme, event, 1048 event_data_len, event_data); 1049 status = true; 1050 break; 1051 1052 default: 1053 status = false; 1054 break; 1055 } 1056 1057 return status; 1058 } 1059 1060 /** 1061 * mlme_vdev_subst_suspend_suspend_down_entry() - Entry API for Suspend down 1062 * sub state 1063 * @ctx: VDEV MLME object 1064 * 1065 * API to perform operations on moving to SUSPEND-DOWN substate 1066 * 1067 * Return: void 1068 */ 1069 static void mlme_vdev_subst_suspend_suspend_down_entry(void *ctx) 1070 { 1071 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 1072 struct wlan_objmgr_vdev *vdev; 1073 1074 vdev = vdev_mlme->vdev; 1075 1076 if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_SUSPEND) 1077 QDF_BUG(0); 1078 1079 mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_SUSPEND_SUSPEND_DOWN); 1080 } 1081 1082 /** 1083 * mlme_vdev_subst_suspend_suspend_down_exit() - Exit API for Suspend down 1084 * sub state 1085 * @ctx: VDEV MLME object 1086 * 1087 * API to perform operations on moving out of SUSPEND-DOWN substate 1088 * 1089 * Return: void 1090 */ 1091 static void mlme_vdev_subst_suspend_suspend_down_exit(void *ctx) 1092 { 1093 /* NONE */ 1094 } 1095 1096 /** 1097 * mlme_vdev_subst_suspend_suspend_down_event() - Event handler API for Suspend 1098 * down substate 1099 * @ctx: VDEV MLME object 1100 * 1101 * API to handle events in SUSPEND-DOWN substate 1102 * 1103 * Return: SUCCESS: on handling event 1104 * FAILURE: on ignoring the event 1105 */ 1106 static bool mlme_vdev_subst_suspend_suspend_down_event(void *ctx, 1107 uint16_t event, uint16_t event_data_len, void *event_data) 1108 { 1109 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 1110 bool status; 1111 1112 switch (event) { 1113 case WLAN_VDEV_SM_EV_DOWN: 1114 case WLAN_VDEV_SM_EV_RESTART_REQ_FAIL: 1115 mlme_vdev_disconnect_peers(vdev_mlme, 1116 event_data_len, event_data); 1117 status = true; 1118 break; 1119 1120 case WLAN_VDEV_SM_EV_DISCONNECT_COMPLETE: 1121 /* clean up, if any needs to be cleaned up */ 1122 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_STOP); 1123 mlme_vdev_sm_deliver_event(vdev_mlme, WLAN_VDEV_SM_EV_DOWN, 1124 event_data_len, event_data); 1125 status = true; 1126 break; 1127 1128 default: 1129 status = false; 1130 break; 1131 } 1132 1133 return status; 1134 } 1135 1136 /** 1137 * mlme_vdev_subst_suspend_suspend_restart_entry() - Entry API for Suspend 1138 * restart substate 1139 * @ctx: VDEV MLME object 1140 * 1141 * API to perform operations on moving to SUSPEND-RESTART substate 1142 * 1143 * Return: void 1144 */ 1145 static void mlme_vdev_subst_suspend_suspend_restart_entry(void *ctx) 1146 { 1147 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 1148 struct wlan_objmgr_vdev *vdev; 1149 1150 vdev = vdev_mlme->vdev; 1151 1152 if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_SUSPEND) 1153 QDF_BUG(0); 1154 1155 mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_SUSPEND_SUSPEND_RESTART); 1156 } 1157 1158 /** 1159 * mlme_vdev_subst_suspend_suspend_restart_exit() - Exit API for Suspend restart 1160 * sub state 1161 * @ctx: VDEV MLME object 1162 * 1163 * API to perform operations on moving out of SUSPEND-RESTART substate 1164 * 1165 * Return: void 1166 */ 1167 static void mlme_vdev_subst_suspend_suspend_restart_exit(void *ctx) 1168 { 1169 /* NONE */ 1170 } 1171 1172 /** 1173 * mlme_vdev_subst_suspend_suspend_restart_event() - Event handler API for 1174 * Suspend restart substate 1175 * @ctx: VDEV MLME object 1176 * 1177 * API to handle events in SUSPEND-RESTART substate 1178 * 1179 * Return: SUCCESS: on handling event 1180 * FAILURE: on ignoring the event 1181 */ 1182 static bool mlme_vdev_subst_suspend_suspend_restart_event(void *ctx, 1183 uint16_t event, uint16_t event_data_len, void *event_data) 1184 { 1185 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 1186 bool status; 1187 1188 switch (event) { 1189 case WLAN_VDEV_SM_EV_SUPSEND_RESTART: 1190 mlme_vdev_disconnect_peers(vdev_mlme, 1191 event_data_len, event_data); 1192 status = true; 1193 break; 1194 1195 case WLAN_VDEV_SM_EV_DISCONNECT_COMPLETE: 1196 /* clean up, if any needs to be cleaned up */ 1197 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_START); 1198 mlme_vdev_sm_deliver_event(vdev_mlme, 1199 WLAN_VDEV_SM_EV_RESTART_REQ, 1200 event_data_len, event_data); 1201 status = true; 1202 break; 1203 1204 case WLAN_VDEV_SM_EV_DOWN: 1205 mlme_vdev_sm_transition_to(vdev_mlme, 1206 WLAN_VDEV_SS_SUSPEND_SUSPEND_DOWN); 1207 status = true; 1208 break; 1209 1210 case WLAN_VDEV_SM_EV_RADAR_DETECTED: 1211 mlme_vdev_sm_transition_to(vdev_mlme, 1212 WLAN_VDEV_SS_SUSPEND_CSA_RESTART); 1213 mlme_vdev_sm_deliver_event(vdev_mlme, 1214 WLAN_VDEV_SM_EV_CSA_RESTART, 1215 event_data_len, event_data); 1216 status = true; 1217 break; 1218 1219 default: 1220 status = false; 1221 break; 1222 } 1223 1224 return status; 1225 } 1226 1227 /** 1228 * mlme_vdev_subst_suspend_host_restart_entry() - Entry API for Host restart 1229 * substate 1230 * @ctx: VDEV MLME object 1231 * 1232 * API to perform operations on moving to HOST-RESTART substate 1233 * 1234 * Return: void 1235 */ 1236 static void mlme_vdev_subst_suspend_host_restart_entry(void *ctx) 1237 { 1238 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 1239 struct wlan_objmgr_vdev *vdev; 1240 1241 vdev = vdev_mlme->vdev; 1242 1243 if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_SUSPEND) 1244 QDF_BUG(0); 1245 1246 mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_SUSPEND_HOST_RESTART); 1247 } 1248 1249 /** 1250 * mlme_vdev_subst_suspend_host_restart_exit() - Exit API for host restart 1251 * sub state 1252 * @ctx: VDEV MLME object 1253 * 1254 * API to perform operations on moving out of HOST-RESTART substate 1255 * 1256 * Return: void 1257 */ 1258 static void mlme_vdev_subst_suspend_host_restart_exit(void *ctx) 1259 { 1260 /* NONE */ 1261 } 1262 1263 /** 1264 * mlme_vdev_subst_suspend_host_restart_entry() - Event handler API for Host 1265 * restart substate 1266 * @ctx: VDEV MLME object 1267 * 1268 * API to handle events in HOST-RESTART substate 1269 * 1270 * Return: void 1271 */ 1272 static bool mlme_vdev_subst_suspend_host_restart_event(void *ctx, 1273 uint16_t event, uint16_t event_data_len, void *event_data) 1274 { 1275 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 1276 bool status; 1277 1278 switch (event) { 1279 case WLAN_VDEV_SM_EV_HOST_RESTART: 1280 mlme_vdev_disconnect_peers(vdev_mlme, 1281 event_data_len, event_data); 1282 status = true; 1283 break; 1284 1285 case WLAN_VDEV_SM_EV_DISCONNECT_COMPLETE: 1286 /* VDEV up command need not be sent */ 1287 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_UP); 1288 mlme_vdev_sm_deliver_event(vdev_mlme, 1289 WLAN_VDEV_SM_EV_UP_HOST_RESTART, 1290 event_data_len, event_data); 1291 status = true; 1292 break; 1293 1294 case WLAN_VDEV_SM_EV_DOWN: 1295 mlme_vdev_sm_transition_to(vdev_mlme, 1296 WLAN_VDEV_SS_SUSPEND_SUSPEND_DOWN); 1297 status = true; 1298 break; 1299 1300 case WLAN_VDEV_SM_EV_RADAR_DETECTED: 1301 mlme_vdev_sm_transition_to(vdev_mlme, 1302 WLAN_VDEV_SS_SUSPEND_CSA_RESTART); 1303 mlme_vdev_sm_deliver_event(vdev_mlme, 1304 WLAN_VDEV_SM_EV_CSA_RESTART, 1305 event_data_len, event_data); 1306 status = true; 1307 break; 1308 1309 default: 1310 status = false; 1311 break; 1312 } 1313 1314 return status; 1315 } 1316 1317 /** 1318 * mlme_vdev_subst_suspend_csa_restart_entry() - Entry API for CSA restart 1319 * substate 1320 * @ctx: VDEV MLME object 1321 * 1322 * API to perform operations on moving to CSA-RESTART substate 1323 * 1324 * Return: void 1325 */ 1326 static void mlme_vdev_subst_suspend_csa_restart_entry(void *ctx) 1327 { 1328 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 1329 struct wlan_objmgr_vdev *vdev; 1330 1331 vdev = vdev_mlme->vdev; 1332 1333 if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_SUSPEND) 1334 QDF_BUG(0); 1335 1336 mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_SUSPEND_CSA_RESTART); 1337 } 1338 1339 /** 1340 * mlme_vdev_subst_suspend_csa_restart_exit() - Exit API for CSA restart 1341 * sub state 1342 * @ctx: VDEV MLME object 1343 * 1344 * API to perform operations on moving out of CSA-RESTART substate 1345 * 1346 * Return: void 1347 */ 1348 static void mlme_vdev_subst_suspend_csa_restart_exit(void *ctx) 1349 { 1350 /* NONE */ 1351 } 1352 1353 /** 1354 * mlme_vdev_subst_suspend_csa_restart_event() - Event handler API for CSA 1355 * restart substate 1356 * @ctx: VDEV MLME object 1357 * 1358 * API to handle events in CSA-RESTART substate 1359 * 1360 * Return: SUCCESS: on handling event 1361 * FAILURE: on ignoring the event 1362 */ 1363 static bool mlme_vdev_subst_suspend_csa_restart_event(void *ctx, 1364 uint16_t event, uint16_t event_data_len, void *event_data) 1365 { 1366 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 1367 bool status; 1368 1369 switch (event) { 1370 case WLAN_VDEV_SM_EV_CSA_RESTART: 1371 mlme_vdev_update_beacon(vdev_mlme, BEACON_CSA, 1372 event_data_len, event_data); 1373 status = true; 1374 break; 1375 case WLAN_VDEV_SM_EV_CSA_COMPLETE: 1376 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_START); 1377 mlme_vdev_sm_deliver_event(vdev_mlme, 1378 WLAN_VDEV_SM_EV_RESTART_REQ, 1379 event_data_len, event_data); 1380 status = true; 1381 break; 1382 1383 case WLAN_VDEV_SM_EV_DOWN: 1384 mlme_vdev_sm_transition_to(vdev_mlme, 1385 WLAN_VDEV_SS_SUSPEND_SUSPEND_DOWN); 1386 mlme_vdev_sm_deliver_event(vdev_mlme, event, 1387 event_data_len, event_data); 1388 status = true; 1389 break; 1390 1391 case WLAN_VDEV_SM_EV_RADAR_DETECTED: 1392 /* since channel change is already in progress, 1393 * dfs ignore radar detected event 1394 */ 1395 status = true; 1396 break; 1397 1398 default: 1399 status = false; 1400 break; 1401 } 1402 1403 return status; 1404 } 1405 1406 /** 1407 * mlme_vdev_subst_stop_stop_progress_entry() - Entry API for Stop Progress 1408 * sub state 1409 * @ctx: VDEV MLME object 1410 * 1411 * API to perform operations on moving to STOP-PROGRESS substate 1412 * 1413 * Return: void 1414 */ 1415 static void mlme_vdev_subst_stop_stop_progress_entry(void *ctx) 1416 { 1417 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *) ctx; 1418 struct wlan_objmgr_vdev *vdev; 1419 1420 vdev = vdev_mlme->vdev; 1421 1422 if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_STOP) 1423 QDF_BUG(0); 1424 1425 mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_STOP_STOP_PROGRESS); 1426 } 1427 1428 /** 1429 * mlme_vdev_subst_stop_stop_progress_exit() - Exit API for Stop Progress 1430 * sub state 1431 * @ctx: VDEV MLME object 1432 * 1433 * API to perform operations on moving out of STOP-PROGRESS substate 1434 * 1435 * Return: void 1436 */ 1437 static void mlme_vdev_subst_stop_stop_progress_exit(void *ctx) 1438 { 1439 /* NONE */ 1440 } 1441 1442 /** 1443 * mlme_vdev_subst_stop_stop_progress_event() - Event handler API for Stop 1444 * Progress substate 1445 * @ctx: VDEV MLME object 1446 * 1447 * API to handle events in STOP-PROGRESS substate 1448 * 1449 * Return: SUCCESS: on handling event 1450 * FAILURE: on ignoring the event 1451 */ 1452 static bool mlme_vdev_subst_stop_stop_progress_event(void *ctx, 1453 uint16_t event, uint16_t event_data_len, void *event_data) 1454 { 1455 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 1456 bool status; 1457 1458 /* Debug framework is required to hold the events */ 1459 1460 switch (event) { 1461 case WLAN_VDEV_SM_EV_DOWN: 1462 /* send vdev stop command to FW and delete BSS peer*/ 1463 mlme_vdev_stop_send(vdev_mlme, event_data_len, event_data); 1464 status = true; 1465 break; 1466 1467 case WLAN_VDEV_SM_EV_STOP_RESP: 1468 /* Processes stop response, and checks BSS peer delete wait 1469 * is needed 1470 */ 1471 mlme_vdev_stop_continue(vdev_mlme, event_data_len, event_data); 1472 status = true; 1473 break; 1474 1475 /* This event should be given by MLME on stop complete and BSS 1476 * peer delete complete to move forward 1477 */ 1478 case WLAN_VDEV_SM_EV_MLME_DOWN_REQ: 1479 mlme_vdev_sm_transition_to(vdev_mlme, 1480 WLAN_VDEV_SS_STOP_DOWN_PROGRESS); 1481 mlme_vdev_sm_deliver_event(vdev_mlme, 1482 WLAN_VDEV_SM_EV_MLME_DOWN_REQ, 1483 event_data_len, event_data); 1484 status = true; 1485 break; 1486 1487 case WLAN_VDEV_SM_EV_STOP_FAIL: 1488 mlme_vdev_sm_transition_to(vdev_mlme, 1489 WLAN_VDEV_SS_STOP_DOWN_PROGRESS); 1490 mlme_vdev_sm_deliver_event(vdev_mlme, 1491 WLAN_VDEV_SM_EV_MLME_DOWN_REQ, 1492 event_data_len, event_data); 1493 status = true; 1494 break; 1495 1496 default: 1497 status = false; 1498 break; 1499 } 1500 1501 return status; 1502 } 1503 1504 /** 1505 * mlme_vdev_subst_stop_down_progress_entry() - Entry API for Down Progress 1506 * sub state 1507 * @ctx: VDEV MLME object 1508 * 1509 * API to perform operations on moving to DOWN-PROGRESS substate 1510 * 1511 * Return: void 1512 */ 1513 static void mlme_vdev_subst_stop_down_progress_entry(void *ctx) 1514 { 1515 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 1516 struct wlan_objmgr_vdev *vdev; 1517 1518 vdev = vdev_mlme->vdev; 1519 1520 if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_STOP) 1521 QDF_BUG(0); 1522 1523 mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_STOP_DOWN_PROGRESS); 1524 } 1525 1526 /** 1527 * mlme_vdev_subst_stop_down_progress_exit() - Exit API for Down Progress 1528 * sub state 1529 * @ctx: VDEV MLME object 1530 * 1531 * API to perform operations on moving out of DOWN-PROGRESS substate 1532 * 1533 * Return: void 1534 */ 1535 static void mlme_vdev_subst_stop_down_progress_exit(void *ctx) 1536 { 1537 /* NONE */ 1538 } 1539 1540 /** 1541 * mlme_vdev_subst_stop_down_progress_event() - Event handler API for Down 1542 * Progress substate 1543 * @ctx: VDEV MLME object 1544 * 1545 * API to handle events in DOWN-PROGRESS substate 1546 * 1547 * Return: SUCCESS: on handling event 1548 * FAILURE: on ignoring the event 1549 */ 1550 static bool mlme_vdev_subst_stop_down_progress_event(void *ctx, 1551 uint16_t event, uint16_t event_data_len, void *event_data) 1552 { 1553 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 1554 bool status; 1555 1556 switch (event) { 1557 case WLAN_VDEV_SM_EV_DOWN: 1558 status = true; 1559 break; 1560 1561 case WLAN_VDEV_SM_EV_MLME_DOWN_REQ: 1562 /* send vdev down command to FW, if send is successful, sends 1563 * DOWN_COMPLETE event 1564 */ 1565 mlme_vdev_down_send(vdev_mlme, event_data_len, event_data); 1566 status = true; 1567 break; 1568 1569 case WLAN_VDEV_SM_EV_DOWN_COMPLETE: 1570 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_INIT); 1571 mlme_vdev_sm_deliver_event(vdev_mlme, 1572 WLAN_VDEV_SM_EV_DOWN_COMPLETE, 1573 event_data_len, event_data); 1574 status = true; 1575 break; 1576 1577 case WLAN_VDEV_SM_EV_DOWN_FAIL: 1578 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_INIT); 1579 mlme_vdev_sm_deliver_event(vdev_mlme, 1580 WLAN_VDEV_SM_EV_DOWN_COMPLETE, 1581 event_data_len, event_data); 1582 status = true; 1583 break; 1584 1585 default: 1586 status = false; 1587 break; 1588 } 1589 1590 return status; 1591 } 1592 1593 1594 static const char *vdev_sm_event_names[] = { 1595 "VDEV_SM_EV_START", 1596 "VDEV_SM_EV_START_REQ", 1597 "VDEV_SM_EV_RESTART_REQ", 1598 "VDEV_SM_EV_START_RESP", 1599 "VDEV_SM_EV_RESTART_RESP", 1600 "VDEV_SM_EV_START_REQ_FAIL", 1601 "VDEV_SM_EV_RESTART_REQ_FAIL", 1602 "VDEV_SM_EV_START_SUCCESS", 1603 "VDEV_SM_EV_CONN_PROGRESS", 1604 "VDEV_SM_EV_STA_CONN_START", 1605 "VDEV_SM_EV_DFS_CAC_WAIT", 1606 "VDEV_SM_EV_DFS_CAC_COMPLETED", 1607 "VDEV_SM_EV_DOWN", 1608 "VDEV_SM_EV_CONNECTION_FAIL", 1609 "VDEV_SM_EV_STOP_RESP", 1610 "VDEV_SM_EV_STOP_FAIL", 1611 "VDEV_SM_EV_DOWN_FAIL", 1612 "VDEV_SM_EV_DISCONNECT_COMPLETE", 1613 "VDEV_SM_EV_SUPSEND_RESTART", 1614 "VDEV_SM_EV_HOST_RESTART", 1615 "VDEV_SM_EV_UP_HOST_RESTART", 1616 "VDEV_SM_EV_FW_VDEV_RESTART", 1617 "VDEV_SM_EV_UP_FAIL", 1618 "VDEV_SM_EV_RADAR_DETECTED", 1619 "VDEV_SM_EV_CSA_RESTART", 1620 "VDEV_SM_EV_CSA_COMPLETE", 1621 "VDEV_SM_EV_MLME_DOWN_REQ", 1622 "VDEV_SM_EV_DOWN_COMPLETE", 1623 }; 1624 1625 struct wlan_sm_state_info sm_info[] = { 1626 { 1627 (uint8_t)WLAN_VDEV_S_INIT, 1628 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1629 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1630 true, 1631 "INIT", 1632 mlme_vdev_state_init_entry, 1633 mlme_vdev_state_init_exit, 1634 mlme_vdev_state_init_event 1635 }, 1636 { 1637 (uint8_t)WLAN_VDEV_S_START, 1638 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1639 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1640 true, 1641 "START", 1642 mlme_vdev_state_start_entry, 1643 mlme_vdev_state_start_exit, 1644 mlme_vdev_state_start_event 1645 }, 1646 { 1647 (uint8_t)WLAN_VDEV_S_DFS_CAC_WAIT, 1648 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1649 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1650 true, 1651 "DFS_CAC_WAIT", 1652 mlme_vdev_state_dfs_cac_wait_entry, 1653 mlme_vdev_state_dfs_cac_wait_exit, 1654 mlme_vdev_state_dfs_cac_wait_event 1655 }, 1656 { 1657 (uint8_t)WLAN_VDEV_S_UP, 1658 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1659 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1660 true, 1661 "UP", 1662 mlme_vdev_state_up_entry, 1663 mlme_vdev_state_up_exit, 1664 mlme_vdev_state_up_event 1665 }, 1666 { 1667 (uint8_t)WLAN_VDEV_S_SUSPEND, 1668 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1669 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1670 true, 1671 "SUSPEND", 1672 mlme_vdev_state_suspend_entry, 1673 mlme_vdev_state_suspend_exit, 1674 mlme_vdev_state_suspend_event 1675 }, 1676 { 1677 (uint8_t)WLAN_VDEV_S_STOP, 1678 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1679 (uint8_t)WLAN_VDEV_SS_STOP_STOP_PROGRESS, 1680 true, 1681 "STOP", 1682 mlme_vdev_state_stop_entry, 1683 mlme_vdev_state_stop_exit, 1684 mlme_vdev_state_stop_event 1685 }, 1686 { 1687 (uint8_t)WLAN_VDEV_S_MAX, 1688 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1689 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1690 false, 1691 "INVALID", 1692 NULL, 1693 NULL, 1694 NULL 1695 }, 1696 { 1697 (uint8_t)WLAN_VDEV_SS_START_START_PROGRESS, 1698 (uint8_t)WLAN_VDEV_S_START, 1699 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1700 false, 1701 "START-START_PROGRESS", 1702 mlme_vdev_subst_start_start_progress_entry, 1703 mlme_vdev_subst_start_start_progress_exit, 1704 mlme_vdev_subst_start_start_progress_event 1705 }, 1706 { 1707 (uint8_t)WLAN_VDEV_SS_START_RESTART_PROGRESS, 1708 (uint8_t)WLAN_VDEV_S_START, 1709 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1710 false, 1711 "START-RESTART_PROGRESS", 1712 mlme_vdev_subst_start_restart_progress_entry, 1713 mlme_vdev_subst_start_restart_progress_exit, 1714 mlme_vdev_subst_start_restart_progress_event 1715 }, 1716 { 1717 (uint8_t)WLAN_VDEV_SS_START_CONN_PROGRESS, 1718 (uint8_t)WLAN_VDEV_S_START, 1719 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1720 false, 1721 "START-CONN_PROGRESS", 1722 mlme_vdev_subst_start_conn_progress_entry, 1723 mlme_vdev_subst_start_conn_progress_exit, 1724 mlme_vdev_subst_start_conn_progress_event 1725 }, 1726 { 1727 (uint8_t)WLAN_VDEV_SS_START_DISCONN_PROGRESS, 1728 (uint8_t)WLAN_VDEV_S_START, 1729 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1730 false, 1731 "START-DISCONN_PROGRESS", 1732 mlme_vdev_subst_start_disconn_progress_entry, 1733 mlme_vdev_subst_start_disconn_progress_exit, 1734 mlme_vdev_subst_start_disconn_progress_event 1735 }, 1736 { 1737 (uint8_t)WLAN_VDEV_SS_SUSPEND_SUSPEND_DOWN, 1738 (uint8_t)WLAN_VDEV_S_SUSPEND, 1739 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1740 false, 1741 "SUSPEND-SUSPEND_DOWN", 1742 mlme_vdev_subst_suspend_suspend_down_entry, 1743 mlme_vdev_subst_suspend_suspend_down_exit, 1744 mlme_vdev_subst_suspend_suspend_down_event 1745 }, 1746 { 1747 (uint8_t)WLAN_VDEV_SS_SUSPEND_SUSPEND_RESTART, 1748 (uint8_t)WLAN_VDEV_S_SUSPEND, 1749 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1750 false, 1751 "SUSPEND-SUSPEND_RESTART", 1752 mlme_vdev_subst_suspend_suspend_restart_entry, 1753 mlme_vdev_subst_suspend_suspend_restart_exit, 1754 mlme_vdev_subst_suspend_suspend_restart_event 1755 }, 1756 { 1757 (uint8_t)WLAN_VDEV_SS_SUSPEND_HOST_RESTART, 1758 (uint8_t)WLAN_VDEV_S_SUSPEND, 1759 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1760 false, 1761 "SUSPEND-HOST_RESTART", 1762 mlme_vdev_subst_suspend_host_restart_entry, 1763 mlme_vdev_subst_suspend_host_restart_exit, 1764 mlme_vdev_subst_suspend_host_restart_event 1765 }, 1766 { 1767 (uint8_t)WLAN_VDEV_SS_SUSPEND_CSA_RESTART, 1768 (uint8_t)WLAN_VDEV_S_SUSPEND, 1769 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1770 false, 1771 "SUSPEND-CSA_RESTART", 1772 mlme_vdev_subst_suspend_csa_restart_entry, 1773 mlme_vdev_subst_suspend_csa_restart_exit, 1774 mlme_vdev_subst_suspend_csa_restart_event 1775 }, 1776 { 1777 (uint8_t)WLAN_VDEV_SS_STOP_STOP_PROGRESS, 1778 (uint8_t)WLAN_VDEV_S_STOP, 1779 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1780 false, 1781 "STOP-STOP_PROGRESS", 1782 mlme_vdev_subst_stop_stop_progress_entry, 1783 mlme_vdev_subst_stop_stop_progress_exit, 1784 mlme_vdev_subst_stop_stop_progress_event 1785 }, 1786 { 1787 (uint8_t)WLAN_VDEV_SS_STOP_DOWN_PROGRESS, 1788 (uint8_t)WLAN_VDEV_S_STOP, 1789 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1790 false, 1791 "STOP-DOWN_PROGRESS", 1792 mlme_vdev_subst_stop_down_progress_entry, 1793 mlme_vdev_subst_stop_down_progress_exit, 1794 mlme_vdev_subst_stop_down_progress_event 1795 }, 1796 { 1797 (uint8_t)WLAN_VDEV_SS_IDLE, 1798 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1799 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1800 false, 1801 "INVALID", 1802 NULL, 1803 NULL, 1804 NULL, 1805 }, 1806 { 1807 (uint8_t)WLAN_VDEV_SS_MAX, 1808 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1809 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1810 false, 1811 "INVALID", 1812 NULL, 1813 NULL, 1814 NULL, 1815 }, 1816 }; 1817 1818 QDF_STATUS mlme_vdev_sm_deliver_event(struct vdev_mlme_obj *vdev_mlme, 1819 enum wlan_vdev_sm_evt event, 1820 uint16_t event_data_len, void *event_data) 1821 { 1822 return wlan_sm_dispatch(vdev_mlme->sm_hdl, event, 1823 event_data_len, event_data); 1824 } 1825 1826 #ifdef SM_ENG_HIST_ENABLE 1827 void mlme_vdev_sm_history_print(struct vdev_mlme_obj *vdev_mlme) 1828 { 1829 return wlan_sm_print_history(vdev_mlme->sm_hdl); 1830 } 1831 #endif 1832 1833 QDF_STATUS mlme_vdev_sm_create(struct vdev_mlme_obj *vdev_mlme) 1834 { 1835 struct wlan_sm *sm; 1836 uint8_t name[WLAN_SM_ENGINE_MAX_NAME]; 1837 1838 qdf_snprintf(name, sizeof(name), "VDEV%d-MLME", 1839 wlan_vdev_get_id(vdev_mlme->vdev)); 1840 sm = wlan_sm_create(name, vdev_mlme, 1841 WLAN_VDEV_S_INIT, 1842 sm_info, 1843 QDF_ARRAY_SIZE(sm_info), 1844 vdev_sm_event_names, 1845 QDF_ARRAY_SIZE(vdev_sm_event_names)); 1846 if (!sm) { 1847 mlme_err("VDEV MLME SM allocation failed"); 1848 return QDF_STATUS_E_FAILURE; 1849 } 1850 vdev_mlme->sm_hdl = sm; 1851 1852 mlme_vdev_sm_spinlock_create(vdev_mlme); 1853 1854 mlme_vdev_cmd_mutex_create(vdev_mlme); 1855 1856 return QDF_STATUS_SUCCESS; 1857 } 1858 1859 #else 1860 1861 QDF_STATUS mlme_vdev_sm_create(struct vdev_mlme_obj *vdev_mlme) 1862 { 1863 struct wlan_sm *sm; 1864 uint8_t name[WLAN_SM_ENGINE_MAX_NAME]; 1865 1866 qdf_snprintf(name, sizeof(name), "VDEV%d-MLME", 1867 wlan_vdev_get_id(vdev_mlme->vdev)); 1868 1869 sm = wlan_sm_create(name, vdev_mlme, 0, NULL, 0, NULL, 0); 1870 if (!sm) { 1871 mlme_err("VDEV MLME SM allocation failed"); 1872 return QDF_STATUS_E_FAILURE; 1873 } 1874 vdev_mlme->sm_hdl = sm; 1875 1876 mlme_vdev_sm_spinlock_create(vdev_mlme); 1877 1878 mlme_vdev_cmd_mutex_create(vdev_mlme); 1879 1880 return QDF_STATUS_SUCCESS; 1881 } 1882 #endif 1883 1884 QDF_STATUS mlme_vdev_sm_destroy(struct vdev_mlme_obj *vdev_mlme) 1885 { 1886 mlme_vdev_cmd_mutex_destroy(vdev_mlme); 1887 1888 mlme_vdev_sm_spinlock_destroy(vdev_mlme); 1889 1890 wlan_sm_delete(vdev_mlme->sm_hdl); 1891 1892 return QDF_STATUS_SUCCESS; 1893 } 1894