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