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_STOP_REQ, 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_STOP_REQ, 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_STOP_REQ, 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_STOP_REQ: 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 "EV_ROAM", 1625 "EV_STOP_REQ", 1626 }; 1627 1628 struct wlan_sm_state_info sm_info[] = { 1629 { 1630 (uint8_t)WLAN_VDEV_S_INIT, 1631 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1632 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1633 true, 1634 "INIT", 1635 mlme_vdev_state_init_entry, 1636 mlme_vdev_state_init_exit, 1637 mlme_vdev_state_init_event 1638 }, 1639 { 1640 (uint8_t)WLAN_VDEV_S_START, 1641 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1642 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1643 true, 1644 "START", 1645 mlme_vdev_state_start_entry, 1646 mlme_vdev_state_start_exit, 1647 mlme_vdev_state_start_event 1648 }, 1649 { 1650 (uint8_t)WLAN_VDEV_S_DFS_CAC_WAIT, 1651 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1652 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1653 true, 1654 "DFS_CAC_WAIT", 1655 mlme_vdev_state_dfs_cac_wait_entry, 1656 mlme_vdev_state_dfs_cac_wait_exit, 1657 mlme_vdev_state_dfs_cac_wait_event 1658 }, 1659 { 1660 (uint8_t)WLAN_VDEV_S_UP, 1661 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1662 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1663 true, 1664 "UP", 1665 mlme_vdev_state_up_entry, 1666 mlme_vdev_state_up_exit, 1667 mlme_vdev_state_up_event 1668 }, 1669 { 1670 (uint8_t)WLAN_VDEV_S_SUSPEND, 1671 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1672 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1673 true, 1674 "SUSPEND", 1675 mlme_vdev_state_suspend_entry, 1676 mlme_vdev_state_suspend_exit, 1677 mlme_vdev_state_suspend_event 1678 }, 1679 { 1680 (uint8_t)WLAN_VDEV_S_STOP, 1681 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1682 (uint8_t)WLAN_VDEV_SS_STOP_STOP_PROGRESS, 1683 true, 1684 "STOP", 1685 mlme_vdev_state_stop_entry, 1686 mlme_vdev_state_stop_exit, 1687 mlme_vdev_state_stop_event 1688 }, 1689 { 1690 (uint8_t)WLAN_VDEV_S_MAX, 1691 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1692 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1693 false, 1694 "INVALID", 1695 NULL, 1696 NULL, 1697 NULL 1698 }, 1699 { 1700 (uint8_t)WLAN_VDEV_SS_START_START_PROGRESS, 1701 (uint8_t)WLAN_VDEV_S_START, 1702 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1703 false, 1704 "ST-START_PROG", 1705 mlme_vdev_subst_start_start_progress_entry, 1706 mlme_vdev_subst_start_start_progress_exit, 1707 mlme_vdev_subst_start_start_progress_event 1708 }, 1709 { 1710 (uint8_t)WLAN_VDEV_SS_START_RESTART_PROGRESS, 1711 (uint8_t)WLAN_VDEV_S_START, 1712 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1713 false, 1714 "ST-RESTART_PROG", 1715 mlme_vdev_subst_start_restart_progress_entry, 1716 mlme_vdev_subst_start_restart_progress_exit, 1717 mlme_vdev_subst_start_restart_progress_event 1718 }, 1719 { 1720 (uint8_t)WLAN_VDEV_SS_START_CONN_PROGRESS, 1721 (uint8_t)WLAN_VDEV_S_START, 1722 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1723 false, 1724 "ST-CONN_PROG", 1725 mlme_vdev_subst_start_conn_progress_entry, 1726 mlme_vdev_subst_start_conn_progress_exit, 1727 mlme_vdev_subst_start_conn_progress_event 1728 }, 1729 { 1730 (uint8_t)WLAN_VDEV_SS_START_DISCONN_PROGRESS, 1731 (uint8_t)WLAN_VDEV_S_START, 1732 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1733 false, 1734 "ST-DISCONN_PROG", 1735 mlme_vdev_subst_start_disconn_progress_entry, 1736 mlme_vdev_subst_start_disconn_progress_exit, 1737 mlme_vdev_subst_start_disconn_progress_event 1738 }, 1739 { 1740 (uint8_t)WLAN_VDEV_SS_SUSPEND_SUSPEND_DOWN, 1741 (uint8_t)WLAN_VDEV_S_SUSPEND, 1742 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1743 false, 1744 "SP-SUSPEND_DOWN", 1745 mlme_vdev_subst_suspend_suspend_down_entry, 1746 mlme_vdev_subst_suspend_suspend_down_exit, 1747 mlme_vdev_subst_suspend_suspend_down_event 1748 }, 1749 { 1750 (uint8_t)WLAN_VDEV_SS_SUSPEND_SUSPEND_RESTART, 1751 (uint8_t)WLAN_VDEV_S_SUSPEND, 1752 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1753 false, 1754 "SP-SUSPEND_RESTART", 1755 mlme_vdev_subst_suspend_suspend_restart_entry, 1756 mlme_vdev_subst_suspend_suspend_restart_exit, 1757 mlme_vdev_subst_suspend_suspend_restart_event 1758 }, 1759 { 1760 (uint8_t)WLAN_VDEV_SS_SUSPEND_HOST_RESTART, 1761 (uint8_t)WLAN_VDEV_S_SUSPEND, 1762 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1763 false, 1764 "SP-HOST_RESTART", 1765 mlme_vdev_subst_suspend_host_restart_entry, 1766 mlme_vdev_subst_suspend_host_restart_exit, 1767 mlme_vdev_subst_suspend_host_restart_event 1768 }, 1769 { 1770 (uint8_t)WLAN_VDEV_SS_SUSPEND_CSA_RESTART, 1771 (uint8_t)WLAN_VDEV_S_SUSPEND, 1772 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1773 false, 1774 "SP-CSA_RESTART", 1775 mlme_vdev_subst_suspend_csa_restart_entry, 1776 mlme_vdev_subst_suspend_csa_restart_exit, 1777 mlme_vdev_subst_suspend_csa_restart_event 1778 }, 1779 { 1780 (uint8_t)WLAN_VDEV_SS_STOP_STOP_PROGRESS, 1781 (uint8_t)WLAN_VDEV_S_STOP, 1782 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1783 false, 1784 "STOP-STOP_PROG", 1785 mlme_vdev_subst_stop_stop_progress_entry, 1786 mlme_vdev_subst_stop_stop_progress_exit, 1787 mlme_vdev_subst_stop_stop_progress_event 1788 }, 1789 { 1790 (uint8_t)WLAN_VDEV_SS_STOP_DOWN_PROGRESS, 1791 (uint8_t)WLAN_VDEV_S_STOP, 1792 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1793 false, 1794 "STOP-DOWN_PROG", 1795 mlme_vdev_subst_stop_down_progress_entry, 1796 mlme_vdev_subst_stop_down_progress_exit, 1797 mlme_vdev_subst_stop_down_progress_event 1798 }, 1799 { 1800 (uint8_t)WLAN_VDEV_SS_IDLE, 1801 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1802 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1803 false, 1804 "IDLE", 1805 NULL, 1806 NULL, 1807 NULL, 1808 }, 1809 { 1810 (uint8_t)WLAN_VDEV_SS_MAX, 1811 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1812 (uint8_t)WLAN_SM_ENGINE_STATE_NONE, 1813 false, 1814 "INVALID", 1815 NULL, 1816 NULL, 1817 NULL, 1818 }, 1819 }; 1820 1821 QDF_STATUS mlme_vdev_sm_deliver_event(struct vdev_mlme_obj *vdev_mlme, 1822 enum wlan_vdev_sm_evt event, 1823 uint16_t event_data_len, void *event_data) 1824 { 1825 return wlan_sm_dispatch(vdev_mlme->sm_hdl, event, 1826 event_data_len, event_data); 1827 } 1828 1829 void mlme_vdev_sm_print_state_event(struct vdev_mlme_obj *vdev_mlme, 1830 enum wlan_vdev_sm_evt event) 1831 { 1832 enum wlan_vdev_state state; 1833 enum wlan_vdev_state substate; 1834 struct wlan_objmgr_vdev *vdev; 1835 1836 vdev = vdev_mlme->vdev; 1837 1838 state = wlan_vdev_mlme_get_state(vdev); 1839 substate = wlan_vdev_mlme_get_substate(vdev); 1840 1841 mlme_nofl_info("[%s]%s - %s, %s", vdev_mlme->sm_hdl->name, 1842 sm_info[state].name, sm_info[substate].name, 1843 vdev_sm_event_names[event]); 1844 } 1845 1846 void mlme_vdev_sm_print_state(struct vdev_mlme_obj *vdev_mlme) 1847 { 1848 enum wlan_vdev_state state; 1849 enum wlan_vdev_state substate; 1850 struct wlan_objmgr_vdev *vdev; 1851 1852 vdev = vdev_mlme->vdev; 1853 1854 state = wlan_vdev_mlme_get_state(vdev); 1855 substate = wlan_vdev_mlme_get_substate(vdev); 1856 1857 mlme_nofl_info("[%s]%s - %s", vdev_mlme->sm_hdl->name, 1858 sm_info[state].name, sm_info[substate].name); 1859 } 1860 1861 #ifdef SM_ENG_HIST_ENABLE 1862 void mlme_vdev_sm_history_print(struct vdev_mlme_obj *vdev_mlme) 1863 { 1864 return wlan_sm_print_history(vdev_mlme->sm_hdl); 1865 } 1866 #endif 1867 1868 QDF_STATUS mlme_vdev_sm_create(struct vdev_mlme_obj *vdev_mlme) 1869 { 1870 struct wlan_sm *sm; 1871 uint8_t name[WLAN_SM_ENGINE_MAX_NAME]; 1872 1873 qdf_snprintf(name, sizeof(name), "VDEV%d-MLME", 1874 wlan_vdev_get_id(vdev_mlme->vdev)); 1875 sm = wlan_sm_create(name, vdev_mlme, 1876 WLAN_VDEV_S_INIT, 1877 sm_info, 1878 QDF_ARRAY_SIZE(sm_info), 1879 vdev_sm_event_names, 1880 QDF_ARRAY_SIZE(vdev_sm_event_names)); 1881 if (!sm) { 1882 mlme_err("VDEV MLME SM allocation failed"); 1883 return QDF_STATUS_E_FAILURE; 1884 } 1885 vdev_mlme->sm_hdl = sm; 1886 1887 mlme_vdev_sm_spinlock_create(vdev_mlme); 1888 1889 mlme_vdev_cmd_mutex_create(vdev_mlme); 1890 1891 return QDF_STATUS_SUCCESS; 1892 } 1893 1894 #else 1895 1896 QDF_STATUS mlme_vdev_sm_create(struct vdev_mlme_obj *vdev_mlme) 1897 { 1898 struct wlan_sm *sm; 1899 uint8_t name[WLAN_SM_ENGINE_MAX_NAME]; 1900 1901 qdf_snprintf(name, sizeof(name), "VDEV%d-MLME", 1902 wlan_vdev_get_id(vdev_mlme->vdev)); 1903 1904 sm = wlan_sm_create(name, vdev_mlme, 0, NULL, 0, NULL, 0); 1905 if (!sm) { 1906 mlme_err("VDEV MLME SM allocation failed"); 1907 return QDF_STATUS_E_FAILURE; 1908 } 1909 vdev_mlme->sm_hdl = sm; 1910 1911 mlme_vdev_sm_spinlock_create(vdev_mlme); 1912 1913 mlme_vdev_cmd_mutex_create(vdev_mlme); 1914 1915 return QDF_STATUS_SUCCESS; 1916 } 1917 #endif 1918 1919 QDF_STATUS mlme_vdev_sm_destroy(struct vdev_mlme_obj *vdev_mlme) 1920 { 1921 mlme_vdev_cmd_mutex_destroy(vdev_mlme); 1922 1923 mlme_vdev_sm_spinlock_destroy(vdev_mlme); 1924 1925 wlan_sm_delete(vdev_mlme->sm_hdl); 1926 1927 return QDF_STATUS_SUCCESS; 1928 } 1929