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