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 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 VDEV MLME SM 19 */ 20 21 #include <wlan_objmgr_vdev_obj.h> 22 #include <wlan_mlme_dbg.h> 23 #include <wlan_sm_engine.h> 24 #include "include/wlan_vdev_mlme.h" 25 #include "vdev_mlme_sm.h" 26 27 /** 28 * mlme_vdev_set_state() - set mlme state 29 * @vdev: VDEV object 30 * @state: MLME state 31 * 32 * API to set MLME state 33 * 34 * Return: void 35 */ 36 static void mlme_vdev_set_state(struct wlan_objmgr_vdev *vdev, 37 enum wlan_vdev_state state) 38 { 39 if (state < WLAN_VDEV_S_MAX) { 40 vdev->vdev_mlme.mlme_state = state; 41 } else { 42 mlme_err("mlme state (%d) is invalid", state); 43 QDF_BUG(0); 44 } 45 } 46 47 /** 48 * mlme_vdev_set_substate() - set mlme sub state 49 * @vdev: VDEV object 50 * @substate: MLME sub state 51 * 52 * API to set MLME sub state 53 * 54 * Return: void 55 */ 56 static void mlme_vdev_set_substate(struct wlan_objmgr_vdev *vdev, 57 enum wlan_vdev_state substate) 58 { 59 if ((substate > WLAN_VDEV_S_MAX) && (substate < WLAN_VDEV_SS_MAX)) { 60 vdev->vdev_mlme.mlme_substate = substate; 61 } else { 62 mlme_err(" mlme sub state (%d) is invalid", substate); 63 QDF_BUG(0); 64 } 65 } 66 67 /** 68 * mlme_vdev_sm_state_update() - set mlme state and sub state 69 * @vdev_mlme: MLME VDEV comp object 70 * @state: MLME state 71 * @substate: MLME sub state 72 * 73 * API to invoke util APIs to set state and MLME sub state 74 * 75 * Return: void 76 */ 77 static void mlme_vdev_sm_state_update(struct vdev_mlme_obj *vdev_mlme, 78 enum wlan_vdev_state state, 79 enum wlan_vdev_state substate) 80 { 81 struct wlan_objmgr_vdev *vdev; 82 83 vdev = vdev_mlme->vdev; 84 if (!vdev) { 85 mlme_err(" VDEV is NULL"); 86 QDF_BUG(0); 87 } 88 89 mlme_vdev_set_state(vdev, state); 90 mlme_vdev_set_substate(vdev, substate); 91 } 92 93 /** 94 * mlme_vdev_sm_transition_to() - invokes state transition 95 * @vdev_mlme: MLME VDEV comp object 96 * @state: new MLME state 97 * 98 * API to invoke SM API to move to new state 99 * 100 * Return: void 101 */ 102 static void mlme_vdev_sm_transition_to(struct vdev_mlme_obj *vdev_mlme, 103 enum wlan_vdev_state state) 104 { 105 wlan_sm_transition_to(vdev_mlme->sm_hdl, state); 106 } 107 108 /** 109 * mlme_vdev_state_init_entry() - Entry API for Init state 110 * @ctx: VDEV MLME object 111 * 112 * API to perform operations on moving to INIT state 113 * 114 * Return: void 115 */ 116 static void mlme_vdev_state_init_entry(void *ctx) 117 { 118 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 119 120 mlme_vdev_sm_state_update(vdev_mlme, WLAN_VDEV_S_INIT, 121 WLAN_VDEV_SS_IDLE); 122 } 123 124 /** 125 * mlme_vdev_state_init_exit() - Exit API for Init state 126 * @ctx: VDEV MLME object 127 * 128 * API to perform operations on moving out of INIT state 129 * 130 * Return: void 131 */ 132 static void mlme_vdev_state_init_exit(void *ctx) 133 { 134 /* NONE */ 135 } 136 137 /** 138 * mlme_vdev_state_init_event() - Init State event handler 139 * @ctx: VDEV MLME object 140 * 141 * API to handle events in INIT state 142 * 143 * Return: SUCCESS: on handling event 144 * FAILURE: on ignoring the event 145 */ 146 static bool mlme_vdev_state_init_event(void *ctx, uint16_t event, 147 uint16_t event_data_len, 148 void *event_data) 149 { 150 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 151 bool status; 152 153 switch (event) { 154 case WLAN_VDEV_SM_EV_START: 155 /* call mlme callback API for sanity checks */ 156 if (mlme_vdev_validate_basic_params(vdev_mlme, event_data_len, 157 event_data) == QDF_STATUS_SUCCESS) { 158 mlme_vdev_sm_transition_to(vdev_mlme, 159 WLAN_VDEV_S_START); 160 mlme_vdev_sm_deliver_event(vdev_mlme, 161 WLAN_VDEV_SM_EV_START_REQ, 162 event_data_len, event_data); 163 status = true; 164 } else { 165 mlme_err( 166 "failed to validate vdev init params to move to START state"); 167 status = true; 168 mlme_vdev_notify_down_complete(vdev_mlme, 169 event_data_len, 170 event_data); 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_STOP_REQ, 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_SUSPEND_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_SUSPEND_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 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 891 892 mlme_vdev_notify_start_state_exit(vdev_mlme); 893 } 894 895 /** 896 * mlme_vdev_subst_start_conn_progress_event() - Event handler API for Conn. 897 * Progress substate 898 * @ctx: VDEV MLME object 899 * 900 * API to handle events in CONN-PROGRESS substate 901 * 902 * Return: SUCCESS: on handling event 903 * FAILURE: on ignoring the event 904 */ 905 static bool mlme_vdev_subst_start_conn_progress_event(void *ctx, 906 uint16_t event, 907 uint16_t event_data_len, 908 void *event_data) 909 { 910 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 911 enum QDF_OPMODE mode; 912 struct wlan_objmgr_vdev *vdev; 913 bool status; 914 915 vdev = vdev_mlme->vdev; 916 917 mode = wlan_vdev_mlme_get_opmode(vdev); 918 919 switch (event) { 920 case WLAN_VDEV_SM_EV_CONN_PROGRESS: 921 /* This API decides to move to DFS CAC WAIT or UP state, 922 * for station notify connection state machine */ 923 mlme_vdev_start_continue(vdev_mlme, event_data_len, event_data); 924 status = true; 925 break; 926 927 case WLAN_VDEV_SM_EV_DFS_CAC_WAIT: 928 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_DFS_CAC_WAIT); 929 mlme_vdev_sm_deliver_event(vdev_mlme, event, 930 event_data_len, event_data); 931 status = true; 932 break; 933 934 case WLAN_VDEV_SM_EV_START_SUCCESS: 935 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_UP); 936 mlme_vdev_sm_deliver_event(vdev_mlme, event, 937 event_data_len, event_data); 938 status = true; 939 break; 940 941 case WLAN_VDEV_SM_EV_STA_CONN_START: 942 /* This event triggers station connection, if it is blocked for 943 * CAC WAIT 944 */ 945 if (mode != QDF_STA_MODE) 946 QDF_BUG(0); 947 948 mlme_vdev_sta_conn_start(vdev_mlme, event_data_len, event_data); 949 status = true; 950 break; 951 952 case WLAN_VDEV_SM_EV_RADAR_DETECTED: 953 if (mode != QDF_STA_MODE) 954 QDF_BUG(0); 955 956 status = true; 957 break; 958 959 case WLAN_VDEV_SM_EV_DOWN: 960 case WLAN_VDEV_SM_EV_CONNECTION_FAIL: 961 mlme_vdev_sm_transition_to(vdev_mlme, 962 WLAN_VDEV_SS_START_DISCONN_PROGRESS); 963 mlme_vdev_sm_deliver_event(vdev_mlme, event, 964 event_data_len, event_data); 965 status = true; 966 break; 967 968 default: 969 status = false; 970 break; 971 } 972 973 return status; 974 } 975 976 /** 977 * mlme_vdev_subst_start_disconn_progress_entry() - Entry API for Disconn 978 * progress sub state 979 * @ctx: VDEV MLME object 980 * 981 * API to perform operations on moving to DISCONN-PROGRESS substate 982 * 983 * Return: SUCCESS: on handling event 984 * FAILURE: on ignoring the event 985 */ 986 static void mlme_vdev_subst_start_disconn_progress_entry(void *ctx) 987 { 988 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 989 struct wlan_objmgr_vdev *vdev; 990 991 vdev = vdev_mlme->vdev; 992 993 if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_START) 994 QDF_BUG(0); 995 996 mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_START_DISCONN_PROGRESS); 997 } 998 999 /** 1000 * mlme_vdev_subst_start_disconn_progress_exit() - Exit API for Disconn Progress 1001 * sub state 1002 * @ctx: VDEV MLME object 1003 * 1004 * API to perform operations on moving out of DISCONN-PROGRESS substate 1005 * 1006 * Return: void 1007 */ 1008 static void mlme_vdev_subst_start_disconn_progress_exit(void *ctx) 1009 { 1010 /* NONE */ 1011 } 1012 1013 /** 1014 * mlme_vdev_subst_start_disconn_progress_event() - Event handler API for Discon 1015 * Progress substate 1016 * @ctx: VDEV MLME object 1017 * 1018 * API to handle events in DISCONN-PROGRESS substate 1019 * 1020 * Return: SUCCESS: on handling event 1021 * FAILURE: on ignoring the event 1022 */ 1023 static bool mlme_vdev_subst_start_disconn_progress_event(void *ctx, 1024 uint16_t event, uint16_t event_data_len, void *event_data) 1025 { 1026 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 1027 bool status; 1028 1029 switch (event) { 1030 case WLAN_VDEV_SM_EV_START_RESP: 1031 /* clean up, if any needs to be cleaned up */ 1032 case WLAN_VDEV_SM_EV_CONNECTION_FAIL: 1033 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_STOP); 1034 mlme_vdev_sm_deliver_event(vdev_mlme, WLAN_VDEV_SM_EV_STOP_REQ, 1035 event_data_len, event_data); 1036 status = true; 1037 break; 1038 1039 case WLAN_VDEV_SM_EV_RESTART_RESP: 1040 case WLAN_VDEV_SM_EV_RESTART_REQ_FAIL: 1041 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_SUSPEND); 1042 mlme_vdev_sm_deliver_event(vdev_mlme, WLAN_VDEV_SM_EV_DOWN, 1043 event_data_len, event_data); 1044 status = true; 1045 break; 1046 1047 case WLAN_VDEV_SM_EV_START_REQ_FAIL: 1048 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_INIT); 1049 mlme_vdev_sm_deliver_event(vdev_mlme, event, 1050 event_data_len, event_data); 1051 status = true; 1052 break; 1053 1054 default: 1055 status = false; 1056 break; 1057 } 1058 1059 return status; 1060 } 1061 1062 /** 1063 * mlme_vdev_subst_suspend_suspend_down_entry() - Entry API for Suspend down 1064 * sub state 1065 * @ctx: VDEV MLME object 1066 * 1067 * API to perform operations on moving to SUSPEND-DOWN substate 1068 * 1069 * Return: void 1070 */ 1071 static void mlme_vdev_subst_suspend_suspend_down_entry(void *ctx) 1072 { 1073 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 1074 struct wlan_objmgr_vdev *vdev; 1075 1076 vdev = vdev_mlme->vdev; 1077 1078 if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_SUSPEND) 1079 QDF_BUG(0); 1080 1081 mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_SUSPEND_SUSPEND_DOWN); 1082 } 1083 1084 /** 1085 * mlme_vdev_subst_suspend_suspend_down_exit() - Exit API for Suspend down 1086 * sub state 1087 * @ctx: VDEV MLME object 1088 * 1089 * API to perform operations on moving out of SUSPEND-DOWN substate 1090 * 1091 * Return: void 1092 */ 1093 static void mlme_vdev_subst_suspend_suspend_down_exit(void *ctx) 1094 { 1095 /* NONE */ 1096 } 1097 1098 /** 1099 * mlme_vdev_subst_suspend_suspend_down_event() - Event handler API for Suspend 1100 * down substate 1101 * @ctx: VDEV MLME object 1102 * 1103 * API to handle events in SUSPEND-DOWN substate 1104 * 1105 * Return: SUCCESS: on handling event 1106 * FAILURE: on ignoring the event 1107 */ 1108 static bool mlme_vdev_subst_suspend_suspend_down_event(void *ctx, 1109 uint16_t event, uint16_t event_data_len, void *event_data) 1110 { 1111 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 1112 bool status; 1113 1114 switch (event) { 1115 case WLAN_VDEV_SM_EV_DOWN: 1116 case WLAN_VDEV_SM_EV_RESTART_REQ_FAIL: 1117 mlme_vdev_disconnect_peers(vdev_mlme, 1118 event_data_len, event_data); 1119 status = true; 1120 break; 1121 1122 case WLAN_VDEV_SM_EV_DISCONNECT_COMPLETE: 1123 /* clean up, if any needs to be cleaned up */ 1124 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_STOP); 1125 mlme_vdev_sm_deliver_event(vdev_mlme, WLAN_VDEV_SM_EV_STOP_REQ, 1126 event_data_len, event_data); 1127 status = true; 1128 break; 1129 1130 default: 1131 status = false; 1132 break; 1133 } 1134 1135 return status; 1136 } 1137 1138 /** 1139 * mlme_vdev_subst_suspend_suspend_restart_entry() - Entry API for Suspend 1140 * restart substate 1141 * @ctx: VDEV MLME object 1142 * 1143 * API to perform operations on moving to SUSPEND-RESTART substate 1144 * 1145 * Return: void 1146 */ 1147 static void mlme_vdev_subst_suspend_suspend_restart_entry(void *ctx) 1148 { 1149 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 1150 struct wlan_objmgr_vdev *vdev; 1151 1152 vdev = vdev_mlme->vdev; 1153 1154 if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_SUSPEND) 1155 QDF_BUG(0); 1156 1157 mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_SUSPEND_SUSPEND_RESTART); 1158 } 1159 1160 /** 1161 * mlme_vdev_subst_suspend_suspend_restart_exit() - Exit API for Suspend restart 1162 * sub state 1163 * @ctx: VDEV MLME object 1164 * 1165 * API to perform operations on moving out of SUSPEND-RESTART substate 1166 * 1167 * Return: void 1168 */ 1169 static void mlme_vdev_subst_suspend_suspend_restart_exit(void *ctx) 1170 { 1171 /* NONE */ 1172 } 1173 1174 /** 1175 * mlme_vdev_subst_suspend_suspend_restart_event() - Event handler API for 1176 * Suspend restart substate 1177 * @ctx: VDEV MLME object 1178 * 1179 * API to handle events in SUSPEND-RESTART substate 1180 * 1181 * Return: SUCCESS: on handling event 1182 * FAILURE: on ignoring the event 1183 */ 1184 static bool mlme_vdev_subst_suspend_suspend_restart_event(void *ctx, 1185 uint16_t event, uint16_t event_data_len, void *event_data) 1186 { 1187 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 1188 bool status; 1189 1190 switch (event) { 1191 case WLAN_VDEV_SM_EV_SUSPEND_RESTART: 1192 mlme_vdev_disconnect_peers(vdev_mlme, 1193 event_data_len, event_data); 1194 status = true; 1195 break; 1196 1197 case WLAN_VDEV_SM_EV_DISCONNECT_COMPLETE: 1198 /* clean up, if any needs to be cleaned up */ 1199 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_START); 1200 mlme_vdev_sm_deliver_event(vdev_mlme, 1201 WLAN_VDEV_SM_EV_RESTART_REQ, 1202 event_data_len, event_data); 1203 status = true; 1204 break; 1205 1206 case WLAN_VDEV_SM_EV_DOWN: 1207 mlme_vdev_sm_transition_to(vdev_mlme, 1208 WLAN_VDEV_SS_SUSPEND_SUSPEND_DOWN); 1209 status = true; 1210 break; 1211 1212 case WLAN_VDEV_SM_EV_RADAR_DETECTED: 1213 mlme_vdev_sm_transition_to(vdev_mlme, 1214 WLAN_VDEV_SS_SUSPEND_CSA_RESTART); 1215 mlme_vdev_sm_deliver_event(vdev_mlme, 1216 WLAN_VDEV_SM_EV_CSA_RESTART, 1217 event_data_len, event_data); 1218 status = true; 1219 break; 1220 1221 default: 1222 status = false; 1223 break; 1224 } 1225 1226 return status; 1227 } 1228 1229 /** 1230 * mlme_vdev_subst_suspend_host_restart_entry() - Entry API for Host restart 1231 * substate 1232 * @ctx: VDEV MLME object 1233 * 1234 * API to perform operations on moving to HOST-RESTART substate 1235 * 1236 * Return: void 1237 */ 1238 static void mlme_vdev_subst_suspend_host_restart_entry(void *ctx) 1239 { 1240 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 1241 struct wlan_objmgr_vdev *vdev; 1242 1243 vdev = vdev_mlme->vdev; 1244 1245 if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_SUSPEND) 1246 QDF_BUG(0); 1247 1248 mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_SUSPEND_HOST_RESTART); 1249 } 1250 1251 /** 1252 * mlme_vdev_subst_suspend_host_restart_exit() - Exit API for host restart 1253 * sub state 1254 * @ctx: VDEV MLME object 1255 * 1256 * API to perform operations on moving out of HOST-RESTART substate 1257 * 1258 * Return: void 1259 */ 1260 static void mlme_vdev_subst_suspend_host_restart_exit(void *ctx) 1261 { 1262 /* NONE */ 1263 } 1264 1265 /** 1266 * mlme_vdev_subst_suspend_host_restart_entry() - Event handler API for Host 1267 * restart substate 1268 * @ctx: VDEV MLME object 1269 * 1270 * API to handle events in HOST-RESTART substate 1271 * 1272 * Return: void 1273 */ 1274 static bool mlme_vdev_subst_suspend_host_restart_event(void *ctx, 1275 uint16_t event, uint16_t event_data_len, void *event_data) 1276 { 1277 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 1278 bool status; 1279 1280 switch (event) { 1281 case WLAN_VDEV_SM_EV_HOST_RESTART: 1282 mlme_vdev_disconnect_peers(vdev_mlme, 1283 event_data_len, event_data); 1284 status = true; 1285 break; 1286 1287 case WLAN_VDEV_SM_EV_DISCONNECT_COMPLETE: 1288 /* VDEV up command need not be sent */ 1289 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_UP); 1290 mlme_vdev_sm_deliver_event(vdev_mlme, 1291 WLAN_VDEV_SM_EV_UP_HOST_RESTART, 1292 event_data_len, event_data); 1293 status = true; 1294 break; 1295 1296 case WLAN_VDEV_SM_EV_DOWN: 1297 mlme_vdev_sm_transition_to(vdev_mlme, 1298 WLAN_VDEV_SS_SUSPEND_SUSPEND_DOWN); 1299 status = true; 1300 break; 1301 1302 case WLAN_VDEV_SM_EV_RADAR_DETECTED: 1303 mlme_vdev_sm_transition_to(vdev_mlme, 1304 WLAN_VDEV_SS_SUSPEND_CSA_RESTART); 1305 mlme_vdev_sm_deliver_event(vdev_mlme, 1306 WLAN_VDEV_SM_EV_CSA_RESTART, 1307 event_data_len, event_data); 1308 status = true; 1309 break; 1310 1311 default: 1312 status = false; 1313 break; 1314 } 1315 1316 return status; 1317 } 1318 1319 /** 1320 * mlme_vdev_subst_suspend_csa_restart_entry() - Entry API for CSA restart 1321 * substate 1322 * @ctx: VDEV MLME object 1323 * 1324 * API to perform operations on moving to CSA-RESTART substate 1325 * 1326 * Return: void 1327 */ 1328 static void mlme_vdev_subst_suspend_csa_restart_entry(void *ctx) 1329 { 1330 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 1331 struct wlan_objmgr_vdev *vdev; 1332 1333 vdev = vdev_mlme->vdev; 1334 1335 if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_SUSPEND) 1336 QDF_BUG(0); 1337 1338 mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_SUSPEND_CSA_RESTART); 1339 } 1340 1341 /** 1342 * mlme_vdev_subst_suspend_csa_restart_exit() - Exit API for CSA restart 1343 * sub state 1344 * @ctx: VDEV MLME object 1345 * 1346 * API to perform operations on moving out of CSA-RESTART substate 1347 * 1348 * Return: void 1349 */ 1350 static void mlme_vdev_subst_suspend_csa_restart_exit(void *ctx) 1351 { 1352 /* NONE */ 1353 } 1354 1355 /** 1356 * mlme_vdev_subst_suspend_csa_restart_event() - Event handler API for CSA 1357 * restart substate 1358 * @ctx: VDEV MLME object 1359 * 1360 * API to handle events in CSA-RESTART substate 1361 * 1362 * Return: SUCCESS: on handling event 1363 * FAILURE: on ignoring the event 1364 */ 1365 static bool mlme_vdev_subst_suspend_csa_restart_event(void *ctx, 1366 uint16_t event, uint16_t event_data_len, void *event_data) 1367 { 1368 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 1369 bool status; 1370 1371 switch (event) { 1372 case WLAN_VDEV_SM_EV_CSA_RESTART: 1373 mlme_vdev_update_beacon(vdev_mlme, BEACON_CSA, 1374 event_data_len, event_data); 1375 status = true; 1376 break; 1377 case WLAN_VDEV_SM_EV_CSA_COMPLETE: 1378 if (mlme_vdev_is_newchan_no_cac(vdev_mlme) == 1379 QDF_STATUS_SUCCESS) { 1380 mlme_vdev_sm_transition_to(vdev_mlme, 1381 WLAN_VDEV_S_START); 1382 mlme_vdev_sm_deliver_event(vdev_mlme, 1383 WLAN_VDEV_SM_EV_RESTART_REQ, 1384 event_data_len, event_data); 1385 } else { 1386 mlme_vdev_sm_transition_to 1387 (vdev_mlme, 1388 WLAN_VDEV_SS_SUSPEND_SUSPEND_RESTART); 1389 mlme_vdev_sm_deliver_event 1390 (vdev_mlme, WLAN_VDEV_SM_EV_SUSPEND_RESTART, 1391 event_data_len, event_data); 1392 } 1393 status = true; 1394 break; 1395 1396 case WLAN_VDEV_SM_EV_DOWN: 1397 mlme_vdev_sm_transition_to(vdev_mlme, 1398 WLAN_VDEV_SS_SUSPEND_SUSPEND_DOWN); 1399 mlme_vdev_sm_deliver_event(vdev_mlme, event, 1400 event_data_len, event_data); 1401 status = true; 1402 break; 1403 1404 case WLAN_VDEV_SM_EV_RADAR_DETECTED: 1405 /* since channel change is already in progress, 1406 * dfs ignore radar detected event 1407 */ 1408 status = true; 1409 break; 1410 1411 default: 1412 status = false; 1413 break; 1414 } 1415 1416 return status; 1417 } 1418 1419 /** 1420 * mlme_vdev_subst_stop_stop_progress_entry() - Entry API for Stop Progress 1421 * sub state 1422 * @ctx: VDEV MLME object 1423 * 1424 * API to perform operations on moving to STOP-PROGRESS substate 1425 * 1426 * Return: void 1427 */ 1428 static void mlme_vdev_subst_stop_stop_progress_entry(void *ctx) 1429 { 1430 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *) ctx; 1431 struct wlan_objmgr_vdev *vdev; 1432 1433 vdev = vdev_mlme->vdev; 1434 1435 if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_STOP) 1436 QDF_BUG(0); 1437 1438 mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_STOP_STOP_PROGRESS); 1439 } 1440 1441 /** 1442 * mlme_vdev_subst_stop_stop_progress_exit() - Exit API for Stop Progress 1443 * sub state 1444 * @ctx: VDEV MLME object 1445 * 1446 * API to perform operations on moving out of STOP-PROGRESS substate 1447 * 1448 * Return: void 1449 */ 1450 static void mlme_vdev_subst_stop_stop_progress_exit(void *ctx) 1451 { 1452 /* NONE */ 1453 } 1454 1455 /** 1456 * mlme_vdev_subst_stop_stop_progress_event() - Event handler API for Stop 1457 * Progress substate 1458 * @ctx: VDEV MLME object 1459 * 1460 * API to handle events in STOP-PROGRESS substate 1461 * 1462 * Return: SUCCESS: on handling event 1463 * FAILURE: on ignoring the event 1464 */ 1465 static bool mlme_vdev_subst_stop_stop_progress_event(void *ctx, 1466 uint16_t event, uint16_t event_data_len, void *event_data) 1467 { 1468 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 1469 bool status; 1470 1471 /* Debug framework is required to hold the events */ 1472 1473 switch (event) { 1474 case WLAN_VDEV_SM_EV_STOP_REQ: 1475 /* send vdev stop command to FW and delete BSS peer*/ 1476 mlme_vdev_stop_send(vdev_mlme, event_data_len, event_data); 1477 status = true; 1478 break; 1479 1480 case WLAN_VDEV_SM_EV_STOP_RESP: 1481 /* Processes stop response, and checks BSS peer delete wait 1482 * is needed 1483 */ 1484 mlme_vdev_stop_continue(vdev_mlme, event_data_len, event_data); 1485 status = true; 1486 break; 1487 1488 /* This event should be given by MLME on stop complete and BSS 1489 * peer delete complete to move forward 1490 */ 1491 case WLAN_VDEV_SM_EV_MLME_DOWN_REQ: 1492 mlme_vdev_sm_transition_to(vdev_mlme, 1493 WLAN_VDEV_SS_STOP_DOWN_PROGRESS); 1494 mlme_vdev_sm_deliver_event(vdev_mlme, 1495 WLAN_VDEV_SM_EV_MLME_DOWN_REQ, 1496 event_data_len, event_data); 1497 status = true; 1498 break; 1499 1500 case WLAN_VDEV_SM_EV_STOP_FAIL: 1501 mlme_vdev_sm_transition_to(vdev_mlme, 1502 WLAN_VDEV_SS_STOP_DOWN_PROGRESS); 1503 mlme_vdev_sm_deliver_event(vdev_mlme, 1504 WLAN_VDEV_SM_EV_MLME_DOWN_REQ, 1505 event_data_len, event_data); 1506 status = true; 1507 break; 1508 1509 default: 1510 status = false; 1511 break; 1512 } 1513 1514 return status; 1515 } 1516 1517 /** 1518 * mlme_vdev_subst_stop_down_progress_entry() - Entry API for Down Progress 1519 * sub state 1520 * @ctx: VDEV MLME object 1521 * 1522 * API to perform operations on moving to DOWN-PROGRESS substate 1523 * 1524 * Return: void 1525 */ 1526 static void mlme_vdev_subst_stop_down_progress_entry(void *ctx) 1527 { 1528 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 1529 struct wlan_objmgr_vdev *vdev; 1530 1531 vdev = vdev_mlme->vdev; 1532 1533 if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_STOP) 1534 QDF_BUG(0); 1535 1536 mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_STOP_DOWN_PROGRESS); 1537 } 1538 1539 /** 1540 * mlme_vdev_subst_stop_down_progress_exit() - Exit API for Down Progress 1541 * sub state 1542 * @ctx: VDEV MLME object 1543 * 1544 * API to perform operations on moving out of DOWN-PROGRESS substate 1545 * 1546 * Return: void 1547 */ 1548 static void mlme_vdev_subst_stop_down_progress_exit(void *ctx) 1549 { 1550 /* NONE */ 1551 } 1552 1553 /** 1554 * mlme_vdev_subst_stop_down_progress_event() - Event handler API for Down 1555 * Progress substate 1556 * @ctx: VDEV MLME object 1557 * 1558 * API to handle events in DOWN-PROGRESS substate 1559 * 1560 * Return: SUCCESS: on handling event 1561 * FAILURE: on ignoring the event 1562 */ 1563 static bool mlme_vdev_subst_stop_down_progress_event(void *ctx, 1564 uint16_t event, uint16_t event_data_len, void *event_data) 1565 { 1566 struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; 1567 bool status; 1568 1569 switch (event) { 1570 case WLAN_VDEV_SM_EV_DOWN: 1571 status = true; 1572 break; 1573 1574 case WLAN_VDEV_SM_EV_MLME_DOWN_REQ: 1575 /* send vdev down command to FW, if send is successful, sends 1576 * DOWN_COMPLETE event 1577 */ 1578 mlme_vdev_down_send(vdev_mlme, event_data_len, event_data); 1579 status = true; 1580 break; 1581 1582 case WLAN_VDEV_SM_EV_DOWN_COMPLETE: 1583 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_INIT); 1584 mlme_vdev_sm_deliver_event(vdev_mlme, 1585 WLAN_VDEV_SM_EV_DOWN_COMPLETE, 1586 event_data_len, event_data); 1587 status = true; 1588 break; 1589 1590 case WLAN_VDEV_SM_EV_DOWN_FAIL: 1591 mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_INIT); 1592 mlme_vdev_sm_deliver_event(vdev_mlme, 1593 WLAN_VDEV_SM_EV_DOWN_COMPLETE, 1594 event_data_len, event_data); 1595 status = true; 1596 break; 1597 1598 default: 1599 status = false; 1600 break; 1601 } 1602 1603 return status; 1604 } 1605 1606 1607 static const char *vdev_sm_event_names[] = { 1608 "EV_START", 1609 "EV_START_REQ", 1610 "EV_RESTART_REQ", 1611 "EV_START_RESP", 1612 "EV_RESTART_RESP", 1613 "EV_START_REQ_FAIL", 1614 "EV_RESTART_REQ_FAIL", 1615 "EV_START_SUCCESS", 1616 "EV_CONN_PROGRESS", 1617 "EV_STA_CONN_START", 1618 "EV_DFS_CAC_WAIT", 1619 "EV_DFS_CAC_COMPLETED", 1620 "EV_DOWN", 1621 "EV_CONNECTION_FAIL", 1622 "EV_STOP_RESP", 1623 "EV_STOP_FAIL", 1624 "EV_DOWN_FAIL", 1625 "EV_DISCONNECT_COMPLETE", 1626 "EV_SUSPEND_RESTART", 1627 "EV_HOST_RESTART", 1628 "EV_UP_HOST_RESTART", 1629 "EV_FW_VDEV_RESTART", 1630 "EV_UP_FAIL", 1631 "EV_RADAR_DETECTED", 1632 "EV_CSA_RESTART", 1633 "EV_CSA_COMPLETE", 1634 "EV_MLME_DOWN_REQ", 1635 "EV_DOWN_COMPLETE", 1636 "EV_ROAM", 1637 "EV_STOP_REQ", 1638 }; 1639 1640 struct wlan_sm_state_info sm_info[] = { 1641 { 1642 (uint8_t)WLAN_VDEV_S_INIT, 1643 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1644 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1645 true, 1646 "INIT", 1647 mlme_vdev_state_init_entry, 1648 mlme_vdev_state_init_exit, 1649 mlme_vdev_state_init_event 1650 }, 1651 { 1652 (uint8_t)WLAN_VDEV_S_START, 1653 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1654 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1655 true, 1656 "START", 1657 mlme_vdev_state_start_entry, 1658 mlme_vdev_state_start_exit, 1659 mlme_vdev_state_start_event 1660 }, 1661 { 1662 (uint8_t)WLAN_VDEV_S_DFS_CAC_WAIT, 1663 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1664 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1665 true, 1666 "DFS_CAC_WAIT", 1667 mlme_vdev_state_dfs_cac_wait_entry, 1668 mlme_vdev_state_dfs_cac_wait_exit, 1669 mlme_vdev_state_dfs_cac_wait_event 1670 }, 1671 { 1672 (uint8_t)WLAN_VDEV_S_UP, 1673 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1674 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1675 true, 1676 "UP", 1677 mlme_vdev_state_up_entry, 1678 mlme_vdev_state_up_exit, 1679 mlme_vdev_state_up_event 1680 }, 1681 { 1682 (uint8_t)WLAN_VDEV_S_SUSPEND, 1683 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1684 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1685 true, 1686 "SUSPEND", 1687 mlme_vdev_state_suspend_entry, 1688 mlme_vdev_state_suspend_exit, 1689 mlme_vdev_state_suspend_event 1690 }, 1691 { 1692 (uint8_t)WLAN_VDEV_S_STOP, 1693 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1694 (uint8_t)WLAN_VDEV_SS_STOP_STOP_PROGRESS, 1695 true, 1696 "STOP", 1697 mlme_vdev_state_stop_entry, 1698 mlme_vdev_state_stop_exit, 1699 mlme_vdev_state_stop_event 1700 }, 1701 { 1702 (uint8_t)WLAN_VDEV_S_MAX, 1703 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1704 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1705 false, 1706 "INVALID", 1707 NULL, 1708 NULL, 1709 NULL 1710 }, 1711 { 1712 (uint8_t)WLAN_VDEV_SS_START_START_PROGRESS, 1713 (uint8_t)WLAN_VDEV_S_START, 1714 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1715 false, 1716 "ST-START_PROG", 1717 mlme_vdev_subst_start_start_progress_entry, 1718 mlme_vdev_subst_start_start_progress_exit, 1719 mlme_vdev_subst_start_start_progress_event 1720 }, 1721 { 1722 (uint8_t)WLAN_VDEV_SS_START_RESTART_PROGRESS, 1723 (uint8_t)WLAN_VDEV_S_START, 1724 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1725 false, 1726 "ST-RESTART_PROG", 1727 mlme_vdev_subst_start_restart_progress_entry, 1728 mlme_vdev_subst_start_restart_progress_exit, 1729 mlme_vdev_subst_start_restart_progress_event 1730 }, 1731 { 1732 (uint8_t)WLAN_VDEV_SS_START_CONN_PROGRESS, 1733 (uint8_t)WLAN_VDEV_S_START, 1734 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1735 false, 1736 "ST-CONN_PROG", 1737 mlme_vdev_subst_start_conn_progress_entry, 1738 mlme_vdev_subst_start_conn_progress_exit, 1739 mlme_vdev_subst_start_conn_progress_event 1740 }, 1741 { 1742 (uint8_t)WLAN_VDEV_SS_START_DISCONN_PROGRESS, 1743 (uint8_t)WLAN_VDEV_S_START, 1744 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1745 false, 1746 "ST-DISCONN_PROG", 1747 mlme_vdev_subst_start_disconn_progress_entry, 1748 mlme_vdev_subst_start_disconn_progress_exit, 1749 mlme_vdev_subst_start_disconn_progress_event 1750 }, 1751 { 1752 (uint8_t)WLAN_VDEV_SS_SUSPEND_SUSPEND_DOWN, 1753 (uint8_t)WLAN_VDEV_S_SUSPEND, 1754 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1755 false, 1756 "SP-SUSPEND_DOWN", 1757 mlme_vdev_subst_suspend_suspend_down_entry, 1758 mlme_vdev_subst_suspend_suspend_down_exit, 1759 mlme_vdev_subst_suspend_suspend_down_event 1760 }, 1761 { 1762 (uint8_t)WLAN_VDEV_SS_SUSPEND_SUSPEND_RESTART, 1763 (uint8_t)WLAN_VDEV_S_SUSPEND, 1764 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1765 false, 1766 "SP-SUSPEND_RESTART", 1767 mlme_vdev_subst_suspend_suspend_restart_entry, 1768 mlme_vdev_subst_suspend_suspend_restart_exit, 1769 mlme_vdev_subst_suspend_suspend_restart_event 1770 }, 1771 { 1772 (uint8_t)WLAN_VDEV_SS_SUSPEND_HOST_RESTART, 1773 (uint8_t)WLAN_VDEV_S_SUSPEND, 1774 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1775 false, 1776 "SP-HOST_RESTART", 1777 mlme_vdev_subst_suspend_host_restart_entry, 1778 mlme_vdev_subst_suspend_host_restart_exit, 1779 mlme_vdev_subst_suspend_host_restart_event 1780 }, 1781 { 1782 (uint8_t)WLAN_VDEV_SS_SUSPEND_CSA_RESTART, 1783 (uint8_t)WLAN_VDEV_S_SUSPEND, 1784 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1785 false, 1786 "SP-CSA_RESTART", 1787 mlme_vdev_subst_suspend_csa_restart_entry, 1788 mlme_vdev_subst_suspend_csa_restart_exit, 1789 mlme_vdev_subst_suspend_csa_restart_event 1790 }, 1791 { 1792 (uint8_t)WLAN_VDEV_SS_STOP_STOP_PROGRESS, 1793 (uint8_t)WLAN_VDEV_S_STOP, 1794 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1795 false, 1796 "STOP-STOP_PROG", 1797 mlme_vdev_subst_stop_stop_progress_entry, 1798 mlme_vdev_subst_stop_stop_progress_exit, 1799 mlme_vdev_subst_stop_stop_progress_event 1800 }, 1801 { 1802 (uint8_t)WLAN_VDEV_SS_STOP_DOWN_PROGRESS, 1803 (uint8_t)WLAN_VDEV_S_STOP, 1804 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1805 false, 1806 "STOP-DOWN_PROG", 1807 mlme_vdev_subst_stop_down_progress_entry, 1808 mlme_vdev_subst_stop_down_progress_exit, 1809 mlme_vdev_subst_stop_down_progress_event 1810 }, 1811 { 1812 (uint8_t)WLAN_VDEV_SS_IDLE, 1813 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1814 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1815 false, 1816 "IDLE", 1817 NULL, 1818 NULL, 1819 NULL, 1820 }, 1821 { 1822 (uint8_t)WLAN_VDEV_SS_MAX, 1823 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1824 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1825 false, 1826 "INVALID", 1827 NULL, 1828 NULL, 1829 NULL, 1830 }, 1831 }; 1832 1833 QDF_STATUS mlme_vdev_sm_deliver_event(struct vdev_mlme_obj *vdev_mlme, 1834 enum wlan_vdev_sm_evt event, 1835 uint16_t event_data_len, void *event_data) 1836 { 1837 return wlan_sm_dispatch(vdev_mlme->sm_hdl, event, 1838 event_data_len, event_data); 1839 } 1840 1841 void mlme_vdev_sm_print_state_event(struct vdev_mlme_obj *vdev_mlme, 1842 enum wlan_vdev_sm_evt event) 1843 { 1844 enum wlan_vdev_state state; 1845 enum wlan_vdev_state substate; 1846 struct wlan_objmgr_vdev *vdev; 1847 1848 vdev = vdev_mlme->vdev; 1849 1850 state = wlan_vdev_mlme_get_state(vdev); 1851 substate = wlan_vdev_mlme_get_substate(vdev); 1852 1853 mlme_nofl_debug("[%s]%s - %s, %s", vdev_mlme->sm_hdl->name, 1854 sm_info[state].name, sm_info[substate].name, 1855 vdev_sm_event_names[event]); 1856 } 1857 1858 void mlme_vdev_sm_print_state(struct vdev_mlme_obj *vdev_mlme) 1859 { 1860 enum wlan_vdev_state state; 1861 enum wlan_vdev_state substate; 1862 struct wlan_objmgr_vdev *vdev; 1863 1864 vdev = vdev_mlme->vdev; 1865 1866 state = wlan_vdev_mlme_get_state(vdev); 1867 substate = wlan_vdev_mlme_get_substate(vdev); 1868 1869 mlme_nofl_debug("[%s]%s - %s", vdev_mlme->sm_hdl->name, 1870 sm_info[state].name, sm_info[substate].name); 1871 } 1872 1873 #ifdef SM_ENG_HIST_ENABLE 1874 void mlme_vdev_sm_history_print(struct vdev_mlme_obj *vdev_mlme) 1875 { 1876 return wlan_sm_print_history(vdev_mlme->sm_hdl); 1877 } 1878 #endif 1879 1880 QDF_STATUS mlme_vdev_sm_create(struct vdev_mlme_obj *vdev_mlme) 1881 { 1882 struct wlan_sm *sm; 1883 uint8_t name[WLAN_SM_ENGINE_MAX_NAME]; 1884 1885 qdf_snprintf(name, sizeof(name), "VDEV%d-MLME", 1886 wlan_vdev_get_id(vdev_mlme->vdev)); 1887 sm = wlan_sm_create(name, vdev_mlme, 1888 WLAN_VDEV_S_INIT, 1889 sm_info, 1890 QDF_ARRAY_SIZE(sm_info), 1891 vdev_sm_event_names, 1892 QDF_ARRAY_SIZE(vdev_sm_event_names)); 1893 if (!sm) { 1894 mlme_err("VDEV MLME SM allocation failed"); 1895 return QDF_STATUS_E_FAILURE; 1896 } 1897 vdev_mlme->sm_hdl = sm; 1898 1899 mlme_vdev_sm_spinlock_create(vdev_mlme); 1900 1901 mlme_vdev_cmd_mutex_create(vdev_mlme); 1902 1903 return QDF_STATUS_SUCCESS; 1904 } 1905 1906 QDF_STATUS mlme_vdev_sm_destroy(struct vdev_mlme_obj *vdev_mlme) 1907 { 1908 mlme_vdev_cmd_mutex_destroy(vdev_mlme); 1909 1910 mlme_vdev_sm_spinlock_destroy(vdev_mlme); 1911 1912 wlan_sm_delete(vdev_mlme->sm_hdl); 1913 1914 return QDF_STATUS_SUCCESS; 1915 } 1916