1 /* 2 * Copyright (c) 2018 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /** 21 * DOC: Define general SM framework, The modules can implement state machine 22 * using framework, it provides framework for state, event, state transition, 23 * event handling 24 * 25 * The module, whoever implement SM using this framework need to define an array 26 * of structures (of type struct wlan_sm_state_info) as below, 27 * for example, sample state array definition 28 * 29 * struct wlan_sm_state_info sm_info[] = { 30 * { 31 * (uint8_t) WLAN_VDEV_S_INIT, 32 * (uint8_t) WLAN_SM_ENGINE_STATE_NONE, 33 * (uint8_t) WLAN_SM_ENGINE_STATE_NONE, 34 * true, 35 * "INIT", 36 * mlme_vdev_state_init_entry, --> gets invoked on entering the state 37 * mlme_vdev_state_init_exit, --> gets invoked before exiting the state 38 * mlme_vdev_state_init_event --> gets invoked on event dispatch 39 * }, 40 * { 41 * (uint8_t) WLAN_VDEV_S_START, 42 * (uint8_t) WLAN_SM_ENGINE_STATE_NONE, 43 * (uint8_t) WLAN_SM_ENGINE_STATE_NONE, 44 * true, 45 * "START", 46 * mlme_vdev_state_start_entry, 47 * mlme_vdev_state_start_exit, 48 * mlme_vdev_state_start_event 49 * }, 50 * { 51 * (uint8_t) WLAN_VDEV_S_DFS_CAC_WAIT, 52 * (uint8_t) WLAN_SM_ENGINE_STATE_NONE, 53 * (uint8_t) WLAN_SM_ENGINE_STATE_NONE, 54 * true, 55 * "DFS_CAC_WAIT", 56 * mlme_vdev_state_dfs_cac_wait_entry, 57 * mlme_vdev_state_dfs_cac_wait_exit, 58 * mlme_vdev_state_dfs_cac_wait_event 59 * }, 60 * ... 61 * }; 62 * 63 * Invoke wlan_sm_create() with this state array as below 64 * 65 * sm = wlan_sm_create("VDEV_SM", vdev_obj, WLAN_VDEV_S_INIT, sm_info, 3, 66 * event_names[], num_events); 67 * 68 * on successful creation, invoke below functions to dispatch events and state 69 * transition 70 * 71 * Event dispatch: 72 * wlan_sm_dispatch(sm, start_event_id, 0, NULL); 73 * 74 * State transition: 75 * wlan_sm_transition_to(sm, WLAN_VDEV_S_INIT); 76 * 77 * 78 */ 79 #ifndef _WLAN_SM_ENGINE_H_ 80 #define _WLAN_SM_ENGINE_H_ 81 82 #include <qdf_types.h> 83 #include <qdf_atomic.h> 84 #include <wlan_sm_engine_dbg.h> 85 86 /* invalid state */ 87 #define WLAN_SM_ENGINE_STATE_NONE 255 88 /* invalid event */ 89 #define WLAN_SM_ENGINE_EVENT_NONE 255 90 91 #define WLAN_SM_ENGINE_MAX_STATE_NAME 128 92 #define WLAN_SM_ENGINE_MAX_NAME 64 93 #define WLAN_SM_ENGINE_MAX_STATES 200 94 #define WLAN_SM_ENGINE_MAX_EVENTS 200 95 96 /** 97 * struct wlan_sm_state_info - state structure definition 98 * @state: State id 99 * @parent_state: Parent state id (optional) 100 * @initial_substate: Initial sub state of this state 101 * @has_substates: flag to specify, whether it has sub states 102 * @name: Name of the state 103 * @wlan_sm_entry: State entry callback pointer 104 * @wlan_sm_exit: State exit callback pointer 105 * @wlan_sm_event: State event callback pointer 106 */ 107 struct wlan_sm_state_info { 108 uint8_t state; 109 uint8_t parent_state; 110 uint8_t initial_substate; 111 uint8_t has_substates; 112 const char *name; 113 void (*wlan_sm_entry) (void *ctx); 114 void (*wlan_sm_exit) (void *ctx); 115 bool (*wlan_sm_event) (void *ctx, uint16_t event, 116 uint16_t event_data_len, void *event_data); 117 }; 118 119 /** 120 * struct wlan_sm - state machine structure 121 * @name: Name of the statemachine 122 * @cur_state: Current state (state/sub-state) 123 * @num_states: Number of states 124 * @last_event: Holds the last handled event of SM 125 * @state_info: Initialized States' table 126 * @ctx: Holds the caller's context 127 * @in_state_transition: Flag to check whether state transition is in progress 128 * @event_names: Array of event names 129 * @num_event_names: Number of event names 130 * @history: Holds the SM history pointer 131 */ 132 struct wlan_sm { 133 uint8_t name[WLAN_SM_ENGINE_MAX_NAME]; 134 uint8_t cur_state; 135 uint8_t num_states; 136 uint8_t last_event; 137 struct wlan_sm_state_info *state_info; 138 void *ctx; 139 qdf_atomic_t in_state_transition; 140 const char **event_names; 141 uint32_t num_event_names; 142 #ifdef SM_ENG_HIST_ENABLE 143 struct wlan_sm_history history; 144 #endif 145 }; 146 147 #define WLAN_SM_ENGINE_ENTRY(name, state, parent, initsubstate, has_substates) \ 148 { state, parent, initsubstate, has_substates, \ 149 "##name", wlan_sm_##name_entry, wlan_sm_##name_exit,\ 150 wlan_sm_##name_event } 151 152 /* 153 * flag definitions 154 */ 155 #define WLAN_SM_ENGINE_ASYNCHRONOUS 0x0 /* run SM asynchronously */ 156 #define WLAN_SM_ENGINE_SYNCHRONOUS 0x1 /* run SM synchronously */ 157 158 /** 159 * wlan_sm_create() - SM create 160 * @name: Name of SM owner module 161 * @ctx: caller pointer, used on invoking callbacks 162 * @init_state: Default state of the SM 163 * @state_info: States' definitions 164 * @num_states: Number of states 165 * @event_names: Event name table 166 * @num_event_names: Number of events 167 * 168 * Creates SM object, initializes with init_state, stores the name and owner 169 * module pointer, states definition table, and event name table 170 * 171 * Return: Handle to struct wlan_sm on successful creation, 172 * NULL on Failure 173 */ 174 struct wlan_sm *wlan_sm_create(const char *name, void *ctx, 175 uint8_t init_state, 176 struct wlan_sm_state_info *state_info, 177 uint8_t num_states, 178 const char **event_names, 179 uint32_t num_event_names); 180 181 /** 182 * wlan_sm_delete() - SM delete 183 * @sm: state machine handle 184 * 185 * Delete SM object 186 * 187 * Return: void 188 */ 189 void wlan_sm_delete(struct wlan_sm *sm); 190 191 /** 192 * wlan_sm_dispatch() - API to notify event to SM 193 * @sm: state machine handle 194 * @event: event id 195 * @event_data_len: Size of event data 196 * @event_data: Event data 197 * 198 * Notifies event to SM, it invokes event callback of the current state of SM 199 * 200 * Return: QDF_STATUS_SUCCESS for handling 201 * QDF_STATUS_E_INVAL for not handling 202 */ 203 QDF_STATUS wlan_sm_dispatch(struct wlan_sm *sm, uint16_t event, 204 uint16_t event_data_len, void *event_data); 205 206 /** 207 * wlan_sm_transition_to() - API to move the state of SM 208 * @sm: state machine handle 209 * @state: State id 210 * 211 * Moves the SM's state 212 * 213 * Return: void 214 */ 215 void wlan_sm_transition_to(struct wlan_sm *sm, uint8_t state); 216 217 /** 218 * wlan_sm_get_lastevent() - API to get last dispatched event 219 * @sm: state machine handle 220 * 221 * Gets the last dispatched event 222 * 223 * Return: event id 224 */ 225 uint8_t wlan_sm_get_lastevent(struct wlan_sm *sm); 226 227 /** 228 * wlan_sm_get_current_state() - API to get current state of SM 229 * @sm: state machine handle 230 * 231 * Gets the current state of SM 232 * 233 * Return: state id 234 */ 235 uint8_t wlan_sm_get_current_state(struct wlan_sm *sm); 236 237 /** 238 * wlan_sm_get_current_state_name() - API to get current state's name of SM 239 * @sm: state machine handle 240 * 241 * Gets the current state name of SM 242 * 243 * Return: name of the state 244 */ 245 const char *wlan_sm_get_current_state_name(struct wlan_sm *sm); 246 247 /** 248 * wlan_sm_get_state_name() - API to get state's name 249 * @sm: state machine handle 250 * @state: state id 251 * 252 * Gets the given state name of SM 253 * 254 * Return: name of the state 255 */ 256 const char *wlan_sm_get_state_name(struct wlan_sm *sm, uint8_t state); 257 258 /** 259 * wlan_sm_reset() - API to reset SM state 260 * @sm: state machine handle 261 * @init_state: state to reset SM 262 * 263 * Resets the SM to given state 264 * 265 * Return: void 266 */ 267 void wlan_sm_reset(struct wlan_sm *sm, uint8_t init_state); 268 269 #endif 270