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