| /* |
| * Copyright (c) 2018 The Linux Foundation. All rights reserved. |
| * |
| * Permission to use, copy, modify, and/or distribute this software for |
| * any purpose with or without fee is hereby granted, provided that the |
| * above copyright notice and this permission notice appear in all |
| * copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
| * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
| * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
| * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
| * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| * PERFORMANCE OF THIS SOFTWARE. |
| */ |
| |
| /** |
| * DOC: Implements VDEV MLME SM |
| */ |
| |
| #include <wlan_objmgr_vdev_obj.h> |
| #include <wlan_mlme_dbg.h> |
| #include <wlan_sm_engine.h> |
| #include "include/wlan_vdev_mlme.h" |
| #include "vdev_mlme_sm.h" |
| |
| #ifdef CMN_VDEV_MLME_SM_ENABLE |
| /** |
| * mlme_vdev_set_state() - set mlme state |
| * @vdev: VDEV object |
| * @state: MLME state |
| * |
| * API to set MLME state |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_set_state(struct wlan_objmgr_vdev *vdev, |
| enum wlan_vdev_state state) |
| { |
| if (state < WLAN_VDEV_S_MAX) { |
| vdev->vdev_mlme.mlme_state = state; |
| } else { |
| mlme_err("mlme state (%d) is invalid", state); |
| QDF_BUG(0); |
| } |
| } |
| |
| /** |
| * mlme_vdev_set_substate() - set mlme sub state |
| * @vdev: VDEV object |
| * @substate: MLME sub state |
| * |
| * API to set MLME sub state |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_set_substate(struct wlan_objmgr_vdev *vdev, |
| enum wlan_vdev_state substate) |
| { |
| if ((substate > WLAN_VDEV_S_MAX) && (substate < WLAN_VDEV_SS_MAX)) { |
| vdev->vdev_mlme.mlme_substate = substate; |
| } else { |
| mlme_err(" mlme sub state (%d) is invalid", substate); |
| QDF_BUG(0); |
| } |
| } |
| |
| /** |
| * mlme_vdev_sm_state_update() - set mlme state and sub state |
| * @vdev_mlme: MLME VDEV comp object |
| * @state: MLME state |
| * @substate: MLME sub state |
| * |
| * API to invoke util APIs to set state and MLME sub state |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_sm_state_update(struct vdev_mlme_obj *vdev_mlme, |
| enum wlan_vdev_state state, |
| enum wlan_vdev_state substate) |
| { |
| struct wlan_objmgr_vdev *vdev; |
| |
| vdev = vdev_mlme->vdev; |
| if (!vdev) { |
| mlme_err(" VDEV is NULL"); |
| QDF_BUG(0); |
| } |
| |
| mlme_vdev_set_state(vdev, state); |
| mlme_vdev_set_substate(vdev, substate); |
| } |
| |
| /** |
| * mlme_vdev_sm_transition_to() - invokes state transition |
| * @vdev_mlme: MLME VDEV comp object |
| * @state: new MLME state |
| * |
| * API to invoke SM API to move to new state |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_sm_transition_to(struct vdev_mlme_obj *vdev_mlme, |
| enum wlan_vdev_state state) |
| { |
| wlan_sm_transition_to(vdev_mlme->sm_hdl, state); |
| } |
| |
| /** |
| * mlme_vdev_state_init_entry() - Entry API for Init state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving to INIT state |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_state_init_entry(void *ctx) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| |
| mlme_vdev_sm_state_update(vdev_mlme, WLAN_VDEV_S_INIT, |
| WLAN_VDEV_SS_IDLE); |
| } |
| |
| /** |
| * mlme_vdev_state_init_exit() - Exit API for Init state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving out of INIT state |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_state_init_exit(void *ctx) |
| { |
| /* NONE */ |
| } |
| |
| /** |
| * mlme_vdev_state_init_event() - Init State event handler |
| * @ctx: VDEV MLME object |
| * |
| * API to handle events in INIT state |
| * |
| * Return: SUCCESS: on handling event |
| * FAILURE: on ignoring the event |
| */ |
| static bool mlme_vdev_state_init_event(void *ctx, uint16_t event, |
| uint16_t event_data_len, |
| void *event_data) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| |
| switch (event) { |
| case WLAN_VDEV_SM_EV_START: |
| /* call mlme callback API for sanity checks */ |
| if (mlme_vdev_validate_basic_params(vdev_mlme, event_data_len, |
| event_data) == QDF_STATUS_SUCCESS) { |
| mlme_vdev_sm_transition_to(vdev_mlme, |
| WLAN_VDEV_S_START); |
| mlme_vdev_sm_deliver_event(vdev_mlme, |
| WLAN_VDEV_SM_EV_START_REQ, |
| event_data_len, event_data); |
| return true; |
| } else { |
| mlme_err( |
| "failed to validate vdev init params to move to START state"); |
| return true; |
| } |
| break; |
| |
| case WLAN_VDEV_SM_EV_DOWN_COMPLETE: |
| case WLAN_VDEV_SM_EV_DOWN: |
| case WLAN_VDEV_SM_EV_START_REQ_FAIL: |
| /* already in down state, notify DOWN command is completed */ |
| /* NOTE: Keep this function call always at the end, to allow |
| * connection restart from this event |
| */ |
| mlme_vdev_notify_down_complete(vdev_mlme, event_data_len, |
| event_data); |
| return true; |
| break; |
| |
| default: |
| return false; |
| break; |
| } |
| } |
| |
| /** |
| * mlme_vdev_state_start_entry() - Entry API for Start state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving to START state |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_state_start_entry(void *ctx) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| |
| mlme_vdev_sm_state_update(vdev_mlme, WLAN_VDEV_S_START, |
| WLAN_VDEV_SS_IDLE); |
| } |
| |
| /** |
| * mlme_vdev_state_start_exit() - Exit API for Start state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving out of START state |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_state_start_exit(void *ctx) |
| { |
| /* NONE */ |
| } |
| |
| /** |
| * mlme_vdev_state_start_event() - Start State event handler |
| * @ctx: VDEV MLME object |
| * |
| * API to handle events in START state |
| * |
| * Return: SUCCESS: on handling event |
| * FAILURE: on ignoring the event |
| */ |
| static bool mlme_vdev_state_start_event(void *ctx, uint16_t event, |
| uint16_t event_data_len, |
| void *event_data) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| |
| switch (event) { |
| case WLAN_VDEV_SM_EV_START_REQ: |
| mlme_vdev_sm_transition_to(vdev_mlme, |
| WLAN_VDEV_SS_START_START_PROGRESS); |
| mlme_vdev_sm_deliver_event(vdev_mlme, event, event_data_len, |
| event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_RESTART_REQ: |
| case WLAN_VDEV_SM_EV_RADAR_DETECTED: |
| mlme_vdev_sm_transition_to(vdev_mlme, |
| WLAN_VDEV_SS_START_RESTART_PROGRESS); |
| mlme_vdev_sm_deliver_event(vdev_mlme, event, event_data_len, |
| event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_STA_CONN_START: |
| mlme_vdev_sm_transition_to(vdev_mlme, |
| WLAN_VDEV_SS_START_CONN_PROGRESS); |
| mlme_vdev_sm_deliver_event(vdev_mlme, event, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| default: |
| return false; |
| break; |
| } |
| } |
| |
| /** |
| * mlme_vdev_state_dfs_cac_wait_entry() - Entry API for DFS CAC WAIT state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving to DFS CAC WAIT state |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_state_dfs_cac_wait_entry(void *ctx) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| |
| mlme_vdev_sm_state_update(vdev_mlme, WLAN_VDEV_S_DFS_CAC_WAIT, |
| WLAN_VDEV_SS_IDLE); |
| } |
| |
| /** |
| * mlme_vdev_state_dfs_cac_wait_exit() - Exit API for DFS CAC WAIT state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving out of DFS CAC WAIT state |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_state_dfs_cac_wait_exit(void *ctx) |
| { |
| /* NONE */ |
| } |
| |
| /** |
| * mlme_vdev_state_dfs_cac_wait_event() - DFS CAC WAIT State event handler |
| * @ctx: VDEV MLME object |
| * |
| * API to handle events in DFS CAC WAIT state |
| * |
| * Return: SUCCESS: on handling event |
| * FAILURE: on ignoring the event |
| */ |
| static bool mlme_vdev_state_dfs_cac_wait_event(void *ctx, uint16_t event, |
| uint16_t event_data_len, |
| void *event_data) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| enum QDF_OPMODE mode; |
| struct wlan_objmgr_vdev *vdev; |
| |
| vdev = vdev_mlme->vdev; |
| |
| mode = wlan_vdev_mlme_get_opmode(vdev); |
| |
| switch (event) { |
| case WLAN_VDEV_SM_EV_DFS_CAC_WAIT: |
| /* DFS timer should have started already, then only this event |
| * could have been triggered |
| */ |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_DOWN: |
| /* stop the CAC timer, then notify state machine */ |
| mlme_vdev_dfs_cac_timer_stop(vdev_mlme, event_data_len, |
| event_data); |
| mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_STOP); |
| mlme_vdev_sm_deliver_event(vdev_mlme, WLAN_VDEV_SM_EV_DOWN, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_RADAR_DETECTED: |
| /* the random channel should have been selected, before issuing |
| * this event |
| */ |
| mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_START); |
| mlme_vdev_sm_deliver_event(vdev_mlme, |
| WLAN_VDEV_SM_EV_RESTART_REQ, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_DFS_CAC_COMPLETED: |
| if (mode == QDF_STA_MODE) { |
| mlme_vdev_sm_transition_to(vdev_mlme, |
| WLAN_VDEV_S_START); |
| mlme_vdev_sm_deliver_event(vdev_mlme, |
| WLAN_VDEV_SM_EV_STA_CONN_START, |
| event_data_len, event_data); |
| } else { |
| mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_UP); |
| mlme_vdev_sm_deliver_event(vdev_mlme, |
| WLAN_VDEV_SM_EV_START_SUCCESS, |
| event_data_len, event_data); |
| } |
| return true; |
| break; |
| |
| default: |
| return false; |
| break; |
| } |
| } |
| |
| /** |
| * mlme_vdev_state_up_entry() - Entry API for UP state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving to UP state |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_state_up_entry(void *ctx) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| |
| mlme_vdev_sm_state_update(vdev_mlme, WLAN_VDEV_S_UP, |
| WLAN_VDEV_SS_IDLE); |
| } |
| |
| /** |
| * mlme_vdev_state_up_exit() - Exit API for UP state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving out of UP state |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_state_up_exit(void *ctx) |
| { |
| /* NONE */ |
| } |
| |
| /** |
| * mlme_vdev_state_up_event() - UP State event handler |
| * @ctx: VDEV MLME object |
| * |
| * API to handle events in UP state |
| * |
| * Return: SUCCESS: on handling event |
| * FAILURE: on ignoring the event |
| */ |
| static bool mlme_vdev_state_up_event(void *ctx, uint16_t event, |
| uint16_t event_data_len, void *event_data) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| enum QDF_OPMODE mode; |
| struct wlan_objmgr_vdev *vdev; |
| |
| vdev = vdev_mlme->vdev; |
| |
| mode = wlan_vdev_mlme_get_opmode(vdev); |
| |
| switch (event) { |
| case WLAN_VDEV_SM_EV_START_SUCCESS: |
| mlme_vdev_update_beacon(vdev_mlme, BEACON_INIT, |
| event_data_len, event_data); |
| if (mlme_vdev_up_send(vdev_mlme, event_data_len, |
| event_data) != QDF_STATUS_SUCCESS) |
| mlme_vdev_sm_deliver_event(vdev_mlme, |
| WLAN_VDEV_SM_EV_UP_FAIL, |
| event_data_len, event_data); |
| else |
| mlme_vdev_notify_up_complete(vdev_mlme, event_data_len, |
| event_data); |
| |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_SUPSEND_RESTART: |
| case WLAN_VDEV_SM_EV_HOST_RESTART: |
| case WLAN_VDEV_SM_EV_CSA_RESTART: |
| /* These events are not supported in STA mode */ |
| if (mode == QDF_STA_MODE) |
| QDF_BUG(0); |
| |
| case WLAN_VDEV_SM_EV_DOWN: |
| mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_SUSPEND); |
| mlme_vdev_sm_deliver_event(vdev_mlme, event, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_RADAR_DETECTED: |
| /* These events are not supported in STA mode */ |
| if (mode == QDF_STA_MODE) |
| QDF_BUG(0); |
| mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_SUSPEND); |
| mlme_vdev_sm_deliver_event(vdev_mlme, |
| WLAN_VDEV_SM_EV_CSA_RESTART, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_UP_HOST_RESTART: |
| /* Reinit beacon, send template to FW(use ping-pong buffer) */ |
| mlme_vdev_update_beacon(vdev_mlme, BEACON_UPDATE, |
| event_data_len, event_data); |
| case WLAN_VDEV_SM_EV_START: |
| /* notify that UP command is completed */ |
| mlme_vdev_notify_up_complete(vdev_mlme, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_FW_VDEV_RESTART: |
| mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_START); |
| mlme_vdev_sm_deliver_event(vdev_mlme, |
| WLAN_VDEV_SM_EV_RESTART_REQ, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_UP_FAIL: |
| mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_SUSPEND); |
| mlme_vdev_sm_deliver_event(vdev_mlme, event, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| default: |
| return false; |
| break; |
| } |
| } |
| |
| /** |
| * mlme_vdev_state_suspend_entry() - Entry API for Suspend state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving to SUSPEND state |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_state_suspend_entry(void *ctx) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| |
| mlme_vdev_sm_state_update(vdev_mlme, WLAN_VDEV_S_SUSPEND, |
| WLAN_VDEV_SS_IDLE); |
| } |
| |
| /** |
| * mlme_vdev_state_suspend_exit() - Exit API for Suspend state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving out of SUSPEND state |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_state_suspend_exit(void *ctx) |
| { |
| /* NONE */ |
| } |
| |
| /** |
| * mlme_vdev_state_suspend_event() - Suspend State event handler |
| * @ctx: VDEV MLME object |
| * |
| * API to handle events in SUSPEND state |
| * |
| * Return: SUCCESS: on handling event |
| * FAILURE: on ignoring the event |
| */ |
| static bool mlme_vdev_state_suspend_event(void *ctx, uint16_t event, |
| uint16_t event_data_len, |
| void *event_data) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| |
| switch (event) { |
| case WLAN_VDEV_SM_EV_DOWN: |
| case WLAN_VDEV_SM_EV_RESTART_REQ_FAIL: |
| mlme_vdev_sm_transition_to(vdev_mlme, |
| WLAN_VDEV_SS_SUSPEND_SUSPEND_DOWN); |
| mlme_vdev_sm_deliver_event(vdev_mlme, event, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_SUPSEND_RESTART: |
| mlme_vdev_sm_transition_to(vdev_mlme, |
| WLAN_VDEV_SS_SUSPEND_SUSPEND_RESTART); |
| mlme_vdev_sm_deliver_event(vdev_mlme, event, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_HOST_RESTART: |
| mlme_vdev_sm_transition_to(vdev_mlme, |
| WLAN_VDEV_SS_SUSPEND_HOST_RESTART); |
| mlme_vdev_sm_deliver_event(vdev_mlme, event, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_CSA_RESTART: |
| mlme_vdev_sm_transition_to(vdev_mlme, |
| WLAN_VDEV_SS_SUSPEND_CSA_RESTART); |
| mlme_vdev_sm_deliver_event(vdev_mlme, event, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_UP_FAIL: |
| mlme_vdev_sm_transition_to(vdev_mlme, |
| WLAN_VDEV_SS_SUSPEND_SUSPEND_DOWN); |
| mlme_vdev_sm_deliver_event(vdev_mlme, WLAN_VDEV_SM_EV_DOWN, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| default: |
| return false; |
| break; |
| } |
| } |
| |
| /** |
| * mlme_vdev_state_stop_entry() - Entry API for Stop state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving to STOP state |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_state_stop_entry(void *ctx) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *) ctx; |
| |
| mlme_vdev_sm_state_update(vdev_mlme, WLAN_VDEV_S_STOP, |
| WLAN_VDEV_SS_IDLE); |
| } |
| |
| /** |
| * mlme_vdev_state_stop_exit() - Exit API for Stop state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving out of STOP state |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_state_stop_exit(void *ctx) |
| { |
| /* NONE */ |
| } |
| |
| /** |
| * mlme_vdev_state_stop_event() - Stop State event handler |
| * @ctx: VDEV MLME object |
| * |
| * API to handle events in STOP state |
| * |
| * Return: SUCCESS: on handling event |
| * FAILURE: on ignoring the event |
| */ |
| static bool mlme_vdev_state_stop_event(void *ctx, uint16_t event, |
| uint16_t event_data_len, |
| void *event_data) |
| { |
| QDF_BUG(0); |
| return false; |
| } |
| |
| /** |
| * mlme_vdev_subst_start_start_progress_entry() - Entry API for Start Progress |
| * sub state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving to START-PROGRESS substate |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_subst_start_start_progress_entry(void *ctx) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| struct wlan_objmgr_vdev *vdev; |
| |
| vdev = vdev_mlme->vdev; |
| |
| if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_START) |
| QDF_BUG(0); |
| |
| mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_START_START_PROGRESS); |
| } |
| |
| /** |
| * mlme_vdev_subst_start_start_progress_exit() - Exit API for Start Progress |
| * sub state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving out of START-PROGRESS substate |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_subst_start_start_progress_exit(void *ctx) |
| { |
| /* NONE */ |
| } |
| |
| /** |
| * mlme_vdev_subst_start_start_progress_event() - Event handler API for Start |
| * Progress substate |
| * @ctx: VDEV MLME object |
| * |
| * API to handle events in START-PROGRESS substate |
| * |
| * Return: SUCCESS: on handling event |
| * FAILURE: on ignoring the event |
| */ |
| static bool mlme_vdev_subst_start_start_progress_event(void *ctx, |
| uint16_t event, uint16_t event_data_len, void *event_data) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| struct wlan_objmgr_vdev *vdev; |
| |
| vdev = vdev_mlme->vdev; |
| |
| switch (event) { |
| case WLAN_VDEV_SM_EV_START_REQ: |
| /* send vdev start req command to FW */ |
| mlme_vdev_start_send(vdev_mlme, event_data_len, event_data); |
| return true; |
| break; |
| /* While waiting for START response, move to RESTART_PROGRESS, |
| * wait for START response to send RESTART req */ |
| case WLAN_VDEV_SM_EV_RADAR_DETECTED: |
| mlme_vdev_sm_transition_to(vdev_mlme, |
| WLAN_VDEV_SS_START_RESTART_PROGRESS); |
| return true; |
| break; |
| case WLAN_VDEV_SM_EV_START_RESP: |
| case WLAN_VDEV_SM_EV_RESTART_RESP: |
| mlme_vdev_sm_transition_to(vdev_mlme, |
| WLAN_VDEV_SS_START_CONN_PROGRESS); |
| mlme_vdev_sm_deliver_event(vdev_mlme, |
| WLAN_VDEV_SM_EV_CONN_PROGRESS, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_START_REQ_FAIL: |
| mlme_vdev_start_req_failed(vdev_mlme, |
| event_data_len, event_data); |
| mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_INIT); |
| mlme_vdev_sm_deliver_event(vdev_mlme, event, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_DOWN: |
| mlme_vdev_sm_transition_to(vdev_mlme, |
| WLAN_VDEV_SS_START_DISCONN_PROGRESS); |
| /* block start request, if it is pending */ |
| mlme_vdev_stop_start_send(vdev_mlme, START_REQ, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| default: |
| return false; |
| break; |
| } |
| } |
| |
| /** |
| * mlme_vdev_subst_start_restart_progress_entry() - Entry API for Restart |
| * progress sub state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving to RESTART-PROGRESS substate |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_subst_start_restart_progress_entry(void *ctx) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| struct wlan_objmgr_vdev *vdev; |
| |
| vdev = vdev_mlme->vdev; |
| |
| if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_START) |
| QDF_BUG(0); |
| |
| mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_START_RESTART_PROGRESS); |
| } |
| |
| /** |
| * mlme_vdev_subst_start_restart_progress_exit() - Exit API for Restart Progress |
| * sub state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving out of RESTART-PROGRESS substate |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_subst_start_restart_progress_exit(void *ctx) |
| { |
| /* NONE */ |
| } |
| |
| /** |
| * mlme_vdev_subst_start_restart_progress_event() - Event handler API for |
| * Restart Progress substate |
| * @ctx: VDEV MLME object |
| * |
| * API to handle events in RESTART-PROGRESS substate |
| * |
| * Return: SUCCESS: on handling event |
| * FAILURE: on ignoring the event |
| */ |
| static bool mlme_vdev_subst_start_restart_progress_event(void *ctx, |
| uint16_t event, uint16_t event_data_len, void *event_data) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| struct wlan_objmgr_vdev *vdev; |
| |
| vdev = vdev_mlme->vdev; |
| |
| switch (event) { |
| case WLAN_VDEV_SM_EV_RESTART_REQ: |
| /* If Start resp is pending, send restart after start response */ |
| case WLAN_VDEV_SM_EV_START_RESP: |
| /* send vdev restart req command to FW */ |
| mlme_vdev_restart_send(vdev_mlme, event_data_len, event_data); |
| return true; |
| break; |
| case WLAN_VDEV_SM_EV_RESTART_RESP: |
| mlme_vdev_sm_transition_to(vdev_mlme, |
| WLAN_VDEV_SS_START_CONN_PROGRESS); |
| mlme_vdev_sm_deliver_event(vdev_mlme, |
| WLAN_VDEV_SM_EV_CONN_PROGRESS, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_RESTART_REQ_FAIL: |
| mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_SUSPEND); |
| mlme_vdev_sm_deliver_event(vdev_mlme, event, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_DOWN: |
| mlme_vdev_sm_transition_to(vdev_mlme, |
| WLAN_VDEV_SS_START_DISCONN_PROGRESS); |
| /* block restart request, if it is pending */ |
| mlme_vdev_stop_start_send(vdev_mlme, RESTART_REQ, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_RADAR_DETECTED: |
| /* It is complicated to handle RADAR detected in this substate, |
| * as vdev updates des channels as bss channel on response, |
| * it would be easily handled, if it is deferred by DFS module |
| */ |
| QDF_BUG(0); |
| return true; |
| break; |
| |
| default: |
| return false; |
| break; |
| } |
| } |
| |
| /** |
| * mlme_vdev_subst_start_conn_progress_entry() - Entry API for Conn. Progress |
| * sub state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving to CONN-PROGRESS substate |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_subst_start_conn_progress_entry(void *ctx) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| struct wlan_objmgr_vdev *vdev; |
| |
| vdev = vdev_mlme->vdev; |
| |
| if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_START) |
| QDF_BUG(0); |
| |
| mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_START_CONN_PROGRESS); |
| } |
| |
| /** |
| * mlme_vdev_subst_start_conn_progress_exit() - Exit API for Conn. Progress |
| * sub state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving out of CONN-PROGRESS substate |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_subst_start_conn_progress_exit(void *ctx) |
| { |
| /* NONE */ |
| } |
| |
| /** |
| * mlme_vdev_subst_start_conn_progress_event() - Event handler API for Conn. |
| * Progress substate |
| * @ctx: VDEV MLME object |
| * |
| * API to handle events in CONN-PROGRESS substate |
| * |
| * Return: SUCCESS: on handling event |
| * FAILURE: on ignoring the event |
| */ |
| static bool mlme_vdev_subst_start_conn_progress_event(void *ctx, |
| uint16_t event, |
| uint16_t event_data_len, |
| void *event_data) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| enum QDF_OPMODE mode; |
| struct wlan_objmgr_vdev *vdev; |
| |
| vdev = vdev_mlme->vdev; |
| |
| mode = wlan_vdev_mlme_get_opmode(vdev); |
| |
| switch (event) { |
| case WLAN_VDEV_SM_EV_CONN_PROGRESS: |
| /* This API decides to move to DFS CAC WAIT or UP state, |
| * for station notify connection state machine */ |
| mlme_vdev_start_continue(vdev_mlme, event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_DFS_CAC_WAIT: |
| mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_DFS_CAC_WAIT); |
| mlme_vdev_sm_deliver_event(vdev_mlme, event, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_START_SUCCESS: |
| mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_UP); |
| mlme_vdev_sm_deliver_event(vdev_mlme, event, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_STA_CONN_START: |
| /* This event triggers station connection, if it is blocked for |
| * CAC WAIT |
| */ |
| if (mode != QDF_STA_MODE) |
| QDF_BUG(0); |
| |
| mlme_vdev_sta_conn_start(vdev_mlme, event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_RADAR_DETECTED: |
| if (mode != QDF_STA_MODE) |
| QDF_BUG(0); |
| |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_DOWN: |
| case WLAN_VDEV_SM_EV_CONNECTION_FAIL: |
| mlme_vdev_sm_transition_to(vdev_mlme, |
| WLAN_VDEV_SS_START_DISCONN_PROGRESS); |
| mlme_vdev_sm_deliver_event(vdev_mlme, event, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| default: |
| return false; |
| break; |
| } |
| } |
| |
| /** |
| * mlme_vdev_subst_start_disconn_progress_entry() - Entry API for Disconn |
| * progress sub state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving to DISCONN-PROGRESS substate |
| * |
| * Return: SUCCESS: on handling event |
| * FAILURE: on ignoring the event |
| */ |
| static void mlme_vdev_subst_start_disconn_progress_entry(void *ctx) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| struct wlan_objmgr_vdev *vdev; |
| |
| vdev = vdev_mlme->vdev; |
| |
| if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_START) |
| QDF_BUG(0); |
| |
| mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_START_DISCONN_PROGRESS); |
| } |
| |
| /** |
| * mlme_vdev_subst_start_disconn_progress_exit() - Exit API for Disconn Progress |
| * sub state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving out of DISCONN-PROGRESS substate |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_subst_start_disconn_progress_exit(void *ctx) |
| { |
| /* NONE */ |
| } |
| |
| /** |
| * mlme_vdev_subst_start_disconn_progress_event() - Event handler API for Discon |
| * Progress substate |
| * @ctx: VDEV MLME object |
| * |
| * API to handle events in DISCONN-PROGRESS substate |
| * |
| * Return: SUCCESS: on handling event |
| * FAILURE: on ignoring the event |
| */ |
| static bool mlme_vdev_subst_start_disconn_progress_event(void *ctx, |
| uint16_t event, uint16_t event_data_len, void *event_data) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| |
| switch (event) { |
| case WLAN_VDEV_SM_EV_START_RESP: |
| /* clean up, if any needs to be cleaned up */ |
| case WLAN_VDEV_SM_EV_CONNECTION_FAIL: |
| mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_STOP); |
| mlme_vdev_sm_deliver_event(vdev_mlme, WLAN_VDEV_SM_EV_DOWN, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_RESTART_RESP: |
| case WLAN_VDEV_SM_EV_RESTART_REQ_FAIL: |
| mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_SUSPEND); |
| mlme_vdev_sm_deliver_event(vdev_mlme, event, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_START_REQ_FAIL: |
| mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_INIT); |
| mlme_vdev_sm_deliver_event(vdev_mlme, event, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| default: |
| return false; |
| break; |
| } |
| } |
| |
| /** |
| * mlme_vdev_subst_suspend_suspend_down_entry() - Entry API for Suspend down |
| * sub state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving to SUSPEND-DOWN substate |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_subst_suspend_suspend_down_entry(void *ctx) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| struct wlan_objmgr_vdev *vdev; |
| |
| vdev = vdev_mlme->vdev; |
| |
| if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_SUSPEND) |
| QDF_BUG(0); |
| |
| mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_SUSPEND_SUSPEND_DOWN); |
| } |
| |
| /** |
| * mlme_vdev_subst_suspend_suspend_down_exit() - Exit API for Suspend down |
| * sub state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving out of SUSPEND-DOWN substate |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_subst_suspend_suspend_down_exit(void *ctx) |
| { |
| /* NONE */ |
| } |
| |
| /** |
| * mlme_vdev_subst_suspend_suspend_down_event() - Event handler API for Suspend |
| * down substate |
| * @ctx: VDEV MLME object |
| * |
| * API to handle events in SUSPEND-DOWN substate |
| * |
| * Return: SUCCESS: on handling event |
| * FAILURE: on ignoring the event |
| */ |
| static bool mlme_vdev_subst_suspend_suspend_down_event(void *ctx, |
| uint16_t event, uint16_t event_data_len, void *event_data) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| |
| switch (event) { |
| case WLAN_VDEV_SM_EV_DOWN: |
| case WLAN_VDEV_SM_EV_RESTART_REQ_FAIL: |
| mlme_vdev_disconnect_peers(vdev_mlme, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_DISCONNECT_COMPLETE: |
| /* clean up, if any needs to be cleaned up */ |
| mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_STOP); |
| mlme_vdev_sm_deliver_event(vdev_mlme, WLAN_VDEV_SM_EV_DOWN, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| default: |
| return false; |
| break; |
| } |
| } |
| |
| /** |
| * mlme_vdev_subst_suspend_suspend_restart_entry() - Entry API for Suspend |
| * restart substate |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving to SUSPEND-RESTART substate |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_subst_suspend_suspend_restart_entry(void *ctx) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| struct wlan_objmgr_vdev *vdev; |
| |
| vdev = vdev_mlme->vdev; |
| |
| if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_SUSPEND) |
| QDF_BUG(0); |
| |
| mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_SUSPEND_SUSPEND_RESTART); |
| } |
| |
| /** |
| * mlme_vdev_subst_suspend_suspend_restart_exit() - Exit API for Suspend restart |
| * sub state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving out of SUSPEND-RESTART substate |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_subst_suspend_suspend_restart_exit(void *ctx) |
| { |
| /* NONE */ |
| } |
| |
| /** |
| * mlme_vdev_subst_suspend_suspend_restart_event() - Event handler API for |
| * Suspend restart substate |
| * @ctx: VDEV MLME object |
| * |
| * API to handle events in SUSPEND-RESTART substate |
| * |
| * Return: SUCCESS: on handling event |
| * FAILURE: on ignoring the event |
| */ |
| static bool mlme_vdev_subst_suspend_suspend_restart_event(void *ctx, |
| uint16_t event, uint16_t event_data_len, void *event_data) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| |
| switch (event) { |
| case WLAN_VDEV_SM_EV_SUPSEND_RESTART: |
| mlme_vdev_disconnect_peers(vdev_mlme, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_DISCONNECT_COMPLETE: |
| /* clean up, if any needs to be cleaned up */ |
| mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_START); |
| mlme_vdev_sm_deliver_event(vdev_mlme, |
| WLAN_VDEV_SM_EV_RESTART_REQ, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_DOWN: |
| mlme_vdev_sm_transition_to(vdev_mlme, |
| WLAN_VDEV_SS_SUSPEND_SUSPEND_DOWN); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_RADAR_DETECTED: |
| mlme_vdev_sm_transition_to(vdev_mlme, |
| WLAN_VDEV_SS_SUSPEND_CSA_RESTART); |
| mlme_vdev_sm_deliver_event(vdev_mlme, |
| WLAN_VDEV_SM_EV_CSA_RESTART, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| default: |
| return false; |
| break; |
| } |
| } |
| |
| /** |
| * mlme_vdev_subst_suspend_host_restart_entry() - Entry API for Host restart |
| * substate |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving to HOST-RESTART substate |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_subst_suspend_host_restart_entry(void *ctx) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| struct wlan_objmgr_vdev *vdev; |
| |
| vdev = vdev_mlme->vdev; |
| |
| if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_SUSPEND) |
| QDF_BUG(0); |
| |
| mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_SUSPEND_HOST_RESTART); |
| } |
| |
| /** |
| * mlme_vdev_subst_suspend_host_restart_exit() - Exit API for host restart |
| * sub state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving out of HOST-RESTART substate |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_subst_suspend_host_restart_exit(void *ctx) |
| { |
| /* NONE */ |
| } |
| |
| /** |
| * mlme_vdev_subst_suspend_host_restart_entry() - Event handler API for Host |
| * restart substate |
| * @ctx: VDEV MLME object |
| * |
| * API to handle events in HOST-RESTART substate |
| * |
| * Return: void |
| */ |
| static bool mlme_vdev_subst_suspend_host_restart_event(void *ctx, |
| uint16_t event, uint16_t event_data_len, void *event_data) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| |
| switch (event) { |
| case WLAN_VDEV_SM_EV_HOST_RESTART: |
| mlme_vdev_disconnect_peers(vdev_mlme, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_DISCONNECT_COMPLETE: |
| /* VDEV up command need not be sent */ |
| mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_UP); |
| mlme_vdev_sm_deliver_event(vdev_mlme, |
| WLAN_VDEV_SM_EV_UP_HOST_RESTART, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_DOWN: |
| mlme_vdev_sm_transition_to(vdev_mlme, |
| WLAN_VDEV_SS_SUSPEND_SUSPEND_DOWN); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_RADAR_DETECTED: |
| mlme_vdev_sm_transition_to(vdev_mlme, |
| WLAN_VDEV_SS_SUSPEND_CSA_RESTART); |
| mlme_vdev_sm_deliver_event(vdev_mlme, |
| WLAN_VDEV_SM_EV_CSA_RESTART, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| default: |
| return false; |
| break; |
| } |
| } |
| |
| /** |
| * mlme_vdev_subst_suspend_csa_restart_entry() - Entry API for CSA restart |
| * substate |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving to CSA-RESTART substate |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_subst_suspend_csa_restart_entry(void *ctx) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| struct wlan_objmgr_vdev *vdev; |
| |
| vdev = vdev_mlme->vdev; |
| |
| if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_SUSPEND) |
| QDF_BUG(0); |
| |
| mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_SUSPEND_CSA_RESTART); |
| } |
| |
| /** |
| * mlme_vdev_subst_suspend_csa_restart_exit() - Exit API for CSA restart |
| * sub state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving out of CSA-RESTART substate |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_subst_suspend_csa_restart_exit(void *ctx) |
| { |
| /* NONE */ |
| } |
| |
| /** |
| * mlme_vdev_subst_suspend_csa_restart_event() - Event handler API for CSA |
| * restart substate |
| * @ctx: VDEV MLME object |
| * |
| * API to handle events in CSA-RESTART substate |
| * |
| * Return: SUCCESS: on handling event |
| * FAILURE: on ignoring the event |
| */ |
| static bool mlme_vdev_subst_suspend_csa_restart_event(void *ctx, |
| uint16_t event, uint16_t event_data_len, void *event_data) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| |
| switch (event) { |
| case WLAN_VDEV_SM_EV_CSA_RESTART: |
| mlme_vdev_update_beacon(vdev_mlme, BEACON_CSA, |
| event_data_len, event_data); |
| return true; |
| break; |
| case WLAN_VDEV_SM_EV_CSA_COMPLETE: |
| mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_START); |
| mlme_vdev_sm_deliver_event(vdev_mlme, |
| WLAN_VDEV_SM_EV_RESTART_REQ, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_DOWN: |
| mlme_vdev_sm_transition_to(vdev_mlme, |
| WLAN_VDEV_SS_SUSPEND_SUSPEND_DOWN); |
| mlme_vdev_sm_deliver_event(vdev_mlme, event, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_RADAR_DETECTED: |
| /* since channel change is already in progress, |
| * dfs ignore radar detected event |
| */ |
| return true; |
| break; |
| |
| default: |
| return false; |
| break; |
| } |
| } |
| |
| /** |
| * mlme_vdev_subst_stop_stop_progress_entry() - Entry API for Stop Progress |
| * sub state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving to STOP-PROGRESS substate |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_subst_stop_stop_progress_entry(void *ctx) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *) ctx; |
| struct wlan_objmgr_vdev *vdev; |
| |
| vdev = vdev_mlme->vdev; |
| |
| if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_STOP) |
| QDF_BUG(0); |
| |
| mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_STOP_STOP_PROGRESS); |
| } |
| |
| /** |
| * mlme_vdev_subst_stop_stop_progress_exit() - Exit API for Stop Progress |
| * sub state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving out of STOP-PROGRESS substate |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_subst_stop_stop_progress_exit(void *ctx) |
| { |
| /* NONE */ |
| } |
| |
| /** |
| * mlme_vdev_subst_stop_stop_progress_event() - Event handler API for Stop |
| * Progress substate |
| * @ctx: VDEV MLME object |
| * |
| * API to handle events in STOP-PROGRESS substate |
| * |
| * Return: SUCCESS: on handling event |
| * FAILURE: on ignoring the event |
| */ |
| static bool mlme_vdev_subst_stop_stop_progress_event(void *ctx, |
| uint16_t event, uint16_t event_data_len, void *event_data) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| |
| /* Debug framework is required to hold the events */ |
| |
| switch (event) { |
| case WLAN_VDEV_SM_EV_DOWN: |
| /* send vdev stop command to FW and delete BSS peer*/ |
| mlme_vdev_stop_send(vdev_mlme, event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_STOP_RESP: |
| /* Processes stop response, and checks BSS peer delete wait |
| * is needed |
| */ |
| mlme_vdev_stop_continue(vdev_mlme, event_data_len, event_data); |
| return true; |
| break; |
| |
| /* This event should be given by MLME on stop complete and BSS |
| * peer delete complete to move forward |
| */ |
| case WLAN_VDEV_SM_EV_MLME_DOWN_REQ: |
| mlme_vdev_sm_transition_to(vdev_mlme, |
| WLAN_VDEV_SS_STOP_DOWN_PROGRESS); |
| mlme_vdev_sm_deliver_event(vdev_mlme, |
| WLAN_VDEV_SM_EV_MLME_DOWN_REQ, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_STOP_FAIL: |
| mlme_vdev_sm_transition_to(vdev_mlme, |
| WLAN_VDEV_SS_STOP_DOWN_PROGRESS); |
| mlme_vdev_sm_deliver_event(vdev_mlme, |
| WLAN_VDEV_SM_EV_MLME_DOWN_REQ, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| default: |
| return false; |
| break; |
| } |
| } |
| |
| /** |
| * mlme_vdev_subst_stop_down_progress_entry() - Entry API for Down Progress |
| * sub state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving to DOWN-PROGRESS substate |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_subst_stop_down_progress_entry(void *ctx) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| struct wlan_objmgr_vdev *vdev; |
| |
| vdev = vdev_mlme->vdev; |
| |
| if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_STOP) |
| QDF_BUG(0); |
| |
| mlme_vdev_set_substate(vdev, WLAN_VDEV_SS_STOP_DOWN_PROGRESS); |
| } |
| |
| /** |
| * mlme_vdev_subst_stop_down_progress_exit() - Exit API for Down Progress |
| * sub state |
| * @ctx: VDEV MLME object |
| * |
| * API to perform operations on moving out of DOWN-PROGRESS substate |
| * |
| * Return: void |
| */ |
| static void mlme_vdev_subst_stop_down_progress_exit(void *ctx) |
| { |
| /* NONE */ |
| } |
| |
| /** |
| * mlme_vdev_subst_stop_down_progress_event() - Event handler API for Down |
| * Progress substate |
| * @ctx: VDEV MLME object |
| * |
| * API to handle events in DOWN-PROGRESS substate |
| * |
| * Return: SUCCESS: on handling event |
| * FAILURE: on ignoring the event |
| */ |
| static bool mlme_vdev_subst_stop_down_progress_event(void *ctx, |
| uint16_t event, uint16_t event_data_len, void *event_data) |
| { |
| struct vdev_mlme_obj *vdev_mlme = (struct vdev_mlme_obj *)ctx; |
| |
| switch (event) { |
| case WLAN_VDEV_SM_EV_DOWN: |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_MLME_DOWN_REQ: |
| /* send vdev down command to FW, if send is successful, sends |
| * DOWN_COMPLETE event |
| */ |
| mlme_vdev_down_send(vdev_mlme, event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_DOWN_COMPLETE: |
| mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_INIT); |
| mlme_vdev_sm_deliver_event(vdev_mlme, |
| WLAN_VDEV_SM_EV_DOWN_COMPLETE, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| case WLAN_VDEV_SM_EV_DOWN_FAIL: |
| mlme_vdev_sm_transition_to(vdev_mlme, WLAN_VDEV_S_INIT); |
| mlme_vdev_sm_deliver_event(vdev_mlme, |
| WLAN_VDEV_SM_EV_DOWN_COMPLETE, |
| event_data_len, event_data); |
| return true; |
| break; |
| |
| default: |
| return false; |
| break; |
| } |
| } |
| |
| |
| static const char *vdev_sm_event_names[] = { |
| "VDEV_SM_EV_START", |
| "VDEV_SM_EV_START_REQ", |
| "VDEV_SM_EV_RESTART_REQ", |
| "VDEV_SM_EV_START_RESP", |
| "VDEV_SM_EV_RESTART_RESP", |
| "VDEV_SM_EV_START_REQ_FAIL", |
| "VDEV_SM_EV_RESTART_REQ_FAIL", |
| "VDEV_SM_EV_START_SUCCESS", |
| "VDEV_SM_EV_CONN_PROGRESS", |
| "VDEV_SM_EV_STA_CONN_START", |
| "VDEV_SM_EV_DFS_CAC_WAIT", |
| "VDEV_SM_EV_DFS_CAC_COMPLETED", |
| "VDEV_SM_EV_DOWN", |
| "VDEV_SM_EV_CONNECTION_FAIL", |
| "VDEV_SM_EV_STOP_RESP", |
| "VDEV_SM_EV_STOP_FAIL", |
| "VDEV_SM_EV_DOWN_FAIL", |
| "VDEV_SM_EV_DISCONNECT_COMPLETE", |
| "VDEV_SM_EV_SUPSEND_RESTART", |
| "VDEV_SM_EV_HOST_RESTART", |
| "VDEV_SM_EV_UP_HOST_RESTART", |
| "VDEV_SM_EV_FW_VDEV_RESTART", |
| "VDEV_SM_EV_UP_FAIL", |
| "VDEV_SM_EV_RADAR_DETECTED", |
| "VDEV_SM_EV_CSA_RESTART", |
| "VDEV_SM_EV_CSA_COMPLETE", |
| "VDEV_SM_EV_MLME_DOWN_REQ", |
| "VDEV_SM_EV_DOWN_COMPLETE", |
| }; |
| |
| struct wlan_sm_state_info sm_info[] = { |
| { |
| (uint8_t)WLAN_VDEV_S_INIT, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| true, |
| "INIT", |
| mlme_vdev_state_init_entry, |
| mlme_vdev_state_init_exit, |
| mlme_vdev_state_init_event |
| }, |
| { |
| (uint8_t)WLAN_VDEV_S_START, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| true, |
| "START", |
| mlme_vdev_state_start_entry, |
| mlme_vdev_state_start_exit, |
| mlme_vdev_state_start_event |
| }, |
| { |
| (uint8_t)WLAN_VDEV_S_DFS_CAC_WAIT, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| true, |
| "DFS_CAC_WAIT", |
| mlme_vdev_state_dfs_cac_wait_entry, |
| mlme_vdev_state_dfs_cac_wait_exit, |
| mlme_vdev_state_dfs_cac_wait_event |
| }, |
| { |
| (uint8_t)WLAN_VDEV_S_UP, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| true, |
| "UP", |
| mlme_vdev_state_up_entry, |
| mlme_vdev_state_up_exit, |
| mlme_vdev_state_up_event |
| }, |
| { |
| (uint8_t)WLAN_VDEV_S_SUSPEND, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| true, |
| "SUSPEND", |
| mlme_vdev_state_suspend_entry, |
| mlme_vdev_state_suspend_exit, |
| mlme_vdev_state_suspend_event |
| }, |
| { |
| (uint8_t)WLAN_VDEV_S_STOP, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| (uint8_t)WLAN_VDEV_SS_STOP_STOP_PROGRESS, |
| true, |
| "STOP", |
| mlme_vdev_state_stop_entry, |
| mlme_vdev_state_stop_exit, |
| mlme_vdev_state_stop_event |
| }, |
| { |
| (uint8_t)WLAN_VDEV_S_MAX, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| false, |
| "INVALID", |
| NULL, |
| NULL, |
| NULL |
| }, |
| { |
| (uint8_t)WLAN_VDEV_SS_START_START_PROGRESS, |
| (uint8_t)WLAN_VDEV_S_START, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| false, |
| "START-START_PROGRESS", |
| mlme_vdev_subst_start_start_progress_entry, |
| mlme_vdev_subst_start_start_progress_exit, |
| mlme_vdev_subst_start_start_progress_event |
| }, |
| { |
| (uint8_t)WLAN_VDEV_SS_START_RESTART_PROGRESS, |
| (uint8_t)WLAN_VDEV_S_START, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| false, |
| "START-RESTART_PROGRESS", |
| mlme_vdev_subst_start_restart_progress_entry, |
| mlme_vdev_subst_start_restart_progress_exit, |
| mlme_vdev_subst_start_restart_progress_event |
| }, |
| { |
| (uint8_t)WLAN_VDEV_SS_START_CONN_PROGRESS, |
| (uint8_t)WLAN_VDEV_S_START, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| false, |
| "START-CONN_PROGRESS", |
| mlme_vdev_subst_start_conn_progress_entry, |
| mlme_vdev_subst_start_conn_progress_exit, |
| mlme_vdev_subst_start_conn_progress_event |
| }, |
| { |
| (uint8_t)WLAN_VDEV_SS_START_DISCONN_PROGRESS, |
| (uint8_t)WLAN_VDEV_S_START, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| false, |
| "START-DISCONN_PROGRESS", |
| mlme_vdev_subst_start_disconn_progress_entry, |
| mlme_vdev_subst_start_disconn_progress_exit, |
| mlme_vdev_subst_start_disconn_progress_event |
| }, |
| { |
| (uint8_t)WLAN_VDEV_SS_SUSPEND_SUSPEND_DOWN, |
| (uint8_t)WLAN_VDEV_S_SUSPEND, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| false, |
| "SUSPEND-SUSPEND_DOWN", |
| mlme_vdev_subst_suspend_suspend_down_entry, |
| mlme_vdev_subst_suspend_suspend_down_exit, |
| mlme_vdev_subst_suspend_suspend_down_event |
| }, |
| { |
| (uint8_t)WLAN_VDEV_SS_SUSPEND_SUSPEND_RESTART, |
| (uint8_t)WLAN_VDEV_S_SUSPEND, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| false, |
| "SUSPEND-SUSPEND_RESTART", |
| mlme_vdev_subst_suspend_suspend_restart_entry, |
| mlme_vdev_subst_suspend_suspend_restart_exit, |
| mlme_vdev_subst_suspend_suspend_restart_event |
| }, |
| { |
| (uint8_t)WLAN_VDEV_SS_SUSPEND_HOST_RESTART, |
| (uint8_t)WLAN_VDEV_S_SUSPEND, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| false, |
| "SUSPEND-HOST_RESTART", |
| mlme_vdev_subst_suspend_host_restart_entry, |
| mlme_vdev_subst_suspend_host_restart_exit, |
| mlme_vdev_subst_suspend_host_restart_event |
| }, |
| { |
| (uint8_t)WLAN_VDEV_SS_SUSPEND_CSA_RESTART, |
| (uint8_t)WLAN_VDEV_S_SUSPEND, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| false, |
| "SUSPEND-CSA_RESTART", |
| mlme_vdev_subst_suspend_csa_restart_entry, |
| mlme_vdev_subst_suspend_csa_restart_exit, |
| mlme_vdev_subst_suspend_csa_restart_event |
| }, |
| { |
| (uint8_t)WLAN_VDEV_SS_STOP_STOP_PROGRESS, |
| (uint8_t)WLAN_VDEV_S_STOP, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| false, |
| "STOP-STOP_PROGRESS", |
| mlme_vdev_subst_stop_stop_progress_entry, |
| mlme_vdev_subst_stop_stop_progress_exit, |
| mlme_vdev_subst_stop_stop_progress_event |
| }, |
| { |
| (uint8_t)WLAN_VDEV_SS_STOP_DOWN_PROGRESS, |
| (uint8_t)WLAN_VDEV_S_STOP, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| false, |
| "STOP-DOWN_PROGRESS", |
| mlme_vdev_subst_stop_down_progress_entry, |
| mlme_vdev_subst_stop_down_progress_exit, |
| mlme_vdev_subst_stop_down_progress_event |
| }, |
| { |
| (uint8_t)WLAN_VDEV_SS_IDLE, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| false, |
| "INVALID", |
| NULL, |
| NULL, |
| NULL, |
| }, |
| { |
| (uint8_t)WLAN_VDEV_SS_MAX, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| (uint8_t)WLAN_SM_ENGINE_STATE_NONE, |
| false, |
| "INVALID", |
| NULL, |
| NULL, |
| NULL, |
| }, |
| }; |
| |
| QDF_STATUS mlme_vdev_sm_deliver_event(struct vdev_mlme_obj *vdev_mlme, |
| enum wlan_vdev_sm_evt event, |
| uint16_t event_data_len, void *event_data) |
| { |
| return wlan_sm_dispatch(vdev_mlme->sm_hdl, event, |
| event_data_len, event_data); |
| } |
| |
| #ifdef SM_ENG_HIST_ENABLE |
| void mlme_vdev_sm_history_print(struct vdev_mlme_obj *vdev_mlme) |
| { |
| return wlan_sm_print_history(vdev_mlme->sm_hdl); |
| } |
| #endif |
| |
| QDF_STATUS mlme_vdev_sm_create(struct vdev_mlme_obj *vdev_mlme) |
| { |
| struct wlan_sm *sm; |
| uint8_t name[WLAN_SM_ENGINE_MAX_NAME]; |
| |
| snprintf(name, sizeof(name), "VDEV%d-MLME", |
| wlan_vdev_get_id(vdev_mlme->vdev)); |
| sm = wlan_sm_create(name, vdev_mlme, |
| WLAN_VDEV_S_INIT, |
| sm_info, |
| QDF_ARRAY_SIZE(sm_info), |
| vdev_sm_event_names, |
| QDF_ARRAY_SIZE(vdev_sm_event_names)); |
| if (!sm) { |
| mlme_err("VDEV MLME SM allocation failed"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| vdev_mlme->sm_hdl = sm; |
| |
| mlme_vdev_sm_spinlock_create(vdev_mlme); |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| |
| #else |
| |
| QDF_STATUS mlme_vdev_sm_create(struct vdev_mlme_obj *vdev_mlme) |
| { |
| struct wlan_sm *sm; |
| uint8_t name[WLAN_SM_ENGINE_MAX_NAME]; |
| |
| snprintf(name, sizeof(name), "VDEV%d-MLME", |
| wlan_vdev_get_id(vdev_mlme->vdev)); |
| |
| sm = wlan_sm_create(name, vdev_mlme, 0, NULL, 0, NULL, 0); |
| if (!sm) { |
| mlme_err("VDEV MLME SM allocation failed"); |
| return QDF_STATUS_E_FAILURE; |
| } |
| vdev_mlme->sm_hdl = sm; |
| |
| mlme_vdev_sm_spinlock_create(vdev_mlme); |
| |
| return QDF_STATUS_SUCCESS; |
| } |
| #endif |
| |
| QDF_STATUS mlme_vdev_sm_destroy(struct vdev_mlme_obj *vdev_mlme) |
| { |
| mlme_vdev_sm_spinlock_destroy(vdev_mlme); |
| |
| wlan_sm_delete(vdev_mlme->sm_hdl); |
| |
| return QDF_STATUS_SUCCESS; |
| } |