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