1 /****************************************************************************** 2 * 3 * Copyright(c) 2019 - 2020 Realtek Corporation. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of version 2 of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 * 14 *****************************************************************************/ 15 #ifndef __PHL_FSM_H__ 16 #define __PHL_FSM_H__ 17 18 #define PHL_INCLUDE_FSM 19 20 /* #define PHL_DEBUG_FSM */ 21 /* #define FSM_DBG_MEM_OVERWRITE */ 22 23 #ifdef FSM_DBG_MEM_OVERWRITE 24 void *fsm_kmalloc(u32 sz); 25 void fsm_kfree(void *ptr, u32 sz); 26 #endif 27 #define FSM_NAME_LEN 32 28 #define CLOCK_UNIT 10 /* ms */ 29 30 struct fsm_root; 31 struct fsm_main; 32 struct fsm_obj; 33 34 /* event map 35 */ 36 #define FSM_EV_MASK 0xff00 37 #define FSM_USR_EV_MASK 0x0100 38 #define FSM_INT_EV_MASK 0x0200 39 #define FSM_GBL_EV_MASK 0x0400 40 #define FSM_EV_UNKNOWN 0xffff 41 42 /* FSM EVENT */ 43 enum FSM_EV_ID { 44 /* Expose to all FSM service */ 45 FSM_INT_EV_MASK_ = FSM_INT_EV_MASK, 46 FSM_EV_CANCEL, 47 FSM_EV_TIMER_EXPIRE, 48 FSM_EV_END, /* for reference */ 49 50 FSM_EV_SWITCH_IN, 51 FSM_EV_SWITCH_OUT, 52 FSM_EV_STATE_IN, 53 FSM_EV_STATE_OUT, 54 55 /* Global Events for announcement */ 56 /* BE CAUREFUL the EVENT ORDER 57 * please also modify int_event_tbl[] in phl_fsm.c 58 */ 59 FSM_GB_SCAN_START, 60 FSM_GB_SCAN_COMPLETE, 61 62 FSM_EV_MAX 63 }; 64 65 enum fsm_mode { 66 FSM_SHARE_THREAD, /* fsm shares root_fsm thread */ 67 FSM_ALONE_THREAD /* fsm has its own thread */ 68 }; 69 70 enum fsm_run_rtn { 71 FSM_FREE_PARAM, 72 FSM_KEEP_PARAM 73 }; 74 75 /* @oid: object id 76 * @event: event id 77 * @msg: additional message of the event 78 * @msg_sz: message size 79 */ 80 struct fsm_msg { 81 _os_list list; 82 u8 oid; /* receiver */ 83 u16 event; /* event id */ 84 struct fsm_main *fsm; 85 86 void *param; 87 int param_sz; 88 }; 89 90 enum fsm_dbg_level { 91 FSM_DBG_NONE, 92 FSM_DBG_PRINT, 93 FSM_DBG_ERR, 94 FSM_DBG_WARN, 95 FSM_DBG_INFO, /* dbg_level: dump normal info msg */ 96 FSM_DBG_DBG, /* dbg_level: dump state change info */ 97 FSM_DBG_MAX 98 }; 99 100 #define EV_ENT(ev) {ev, #ev, FSM_DBG_INFO} 101 #define EV_WRN(ev) {ev, #ev, FSM_DBG_WARN} 102 #define EV_INF(ev) {ev, #ev, FSM_DBG_INFO} 103 #define EV_DBG(ev) {ev, #ev, FSM_DBG_DBG} 104 105 struct fsm_event_ent { 106 u16 event; 107 char *name; 108 u8 evt_level; 109 }; 110 111 #define ST_ENT(st, hdl) {st, #st, hdl} 112 struct fsm_state_ent { 113 u8 state; 114 char *name; 115 int (*fsm_func)(void *priv, u16 event, void *param); 116 }; 117 118 /* struct of phl_fsm_init_fsm() */ 119 struct rtw_phl_fsm_tb { 120 u8 mode; /* 0/1: Share/Standalone thread mode */ 121 u8 dbg_level; 122 u8 evt_level; 123 u8 max_state; 124 u16 max_event; 125 struct fsm_state_ent *state_tbl; 126 struct fsm_event_ent *evt_tbl; 127 128 /* debug function */ 129 void (*dump_obj)(void *obj, char *p, int *sz); /* optional */ 130 void (*dump_fsm)(void *fsm, char *p, int *sz); /* optional */ 131 void (*debug)(void *custom_obj, char input[][MAX_ARGV], 132 u32 input_num, char *output, u32 *out_len); 133 }; 134 135 enum gbl_evt_result { 136 GBL_ST_NOT_FINISH, 137 GBL_ST_SUCCESS, 138 GBL_ST_ABORT, 139 GBL_ST_FAIL, 140 GBL_ST_WAIT_REACH_MAX, 141 GBL_ST_REPLY_REACH_MAX, 142 GBL_ST_ALLOC_MEM_FAIL 143 }; 144 145 #define PHL_FSM_MAX_WAIT_OCUNT 16 146 struct gbl_param { 147 struct list_head list; 148 u16 event; 149 u16 cb_evt; 150 u16 count; 151 u32 wait_ms; 152 u32 seq; 153 struct fsm_obj *obj_from; /* GBL event original issuer */ 154 struct fsm_obj *obj_to; /* GBL event original receiver */ 155 struct fsm_obj *wait_list[PHL_FSM_MAX_WAIT_OCUNT]; 156 int result; 157 }; 158 159 /* GBL event caller use */ 160 int phl_fsm_gbl_msg_announce(struct fsm_obj *obj, u16 gbl_evt, u16 cb_evt); 161 int phl_fsm_gbl_not_reply_num(struct fsm_obj *obj, struct gbl_param *param); 162 enum rtw_phl_status phl_fsm_flush_gbl(struct fsm_obj *obj); 163 164 /* GBL event callee use */ 165 int phl_fsm_gbl_msg_hold(struct fsm_obj *obj, 166 struct gbl_param *param, u32 ms); 167 enum rtw_phl_status phl_fsm_gbl_msg_release(struct fsm_obj *obj, 168 u16 event, u32 seq, enum gbl_evt_result result); 169 170 /* fsm init funciton */ 171 struct fsm_root *phl_fsm_init_root(void *phl_info); 172 void phl_fsm_deinit_root(struct fsm_root *root); 173 enum rtw_phl_status phl_fsm_start_root(struct fsm_root *root); 174 enum rtw_phl_status phl_fsm_stop_root(struct fsm_root *root); 175 176 177 struct fsm_main *phl_fsm_init_fsm(struct fsm_root *root, 178 const char *name, void *phl_info, struct rtw_phl_fsm_tb *tb); 179 enum rtw_phl_status phl_fsm_deinit_fsm(struct fsm_main *fsm); 180 181 enum rtw_phl_status phl_fsm_start_fsm(struct fsm_main *fsm); 182 enum rtw_phl_status phl_fsm_stop_fsm(struct fsm_main *fsm); 183 void *phl_fsm_new_obj(struct fsm_main *fsm, void **fsm_obj, int obj_sz); 184 void phl_fsm_destory_obj(struct fsm_obj *obj); 185 void phl_fsm_dbg(struct phl_info_t *phl_info, char input[][MAX_ARGV], 186 u32 input_num, char *output, u32 out_len); 187 188 /* fsm operating funciton */ 189 struct fsm_msg *phl_fsm_new_msg(struct fsm_obj *obj, u16 event); 190 enum rtw_phl_status phl_fsm_sent_msg(struct fsm_obj *obj, struct fsm_msg *msg); 191 enum rtw_phl_status phl_fsm_cancel_obj(struct fsm_obj *obj); 192 void phl_fsm_state_goto(struct fsm_obj *obj, u8 new_state); 193 void phl_fsm_set_alarm(struct fsm_obj *obj, int ms, u16 event); 194 void phl_fsm_set_alarm_ext(struct fsm_obj *obj, 195 int ms, u16 event, u8 id, void *priv); 196 void phl_fsm_cancel_alarm(struct fsm_obj *obj); 197 void phl_fsm_cancel_alarm_ext(struct fsm_obj *obj, u8 id); 198 void phl_fsm_pause_alarm(struct fsm_obj *obj); 199 void phl_fsm_pause_alarm_ext(struct fsm_obj *obj, u8 id); 200 void phl_fsm_resume_alarm(struct fsm_obj *obj); 201 void phl_fsm_resume_alarm_ext(struct fsm_obj *obj, u8 id); 202 bool phl_fsm_is_alarm_off(struct fsm_obj *obj); 203 bool phl_fsm_is_alarm_off_ext(struct fsm_obj *obj, u8 id); 204 void phl_fsm_extend_alarm_ext(struct fsm_obj *obj, int ms, u8 id); 205 u8 phl_fsm_dbg_level(struct fsm_main *fsm, u8 level); 206 u8 phl_fsm_evt_level(struct fsm_main *fsm, u8 level); 207 enum rtw_phl_status phl_fsm_gen_msg(void *phl, struct fsm_obj *obj, 208 void *pbuf, u32 sz, u16 event); 209 210 /* function to manipulate extra queue */ 211 int phl_fsm_enqueue_ext(struct fsm_main *fsm, struct fsm_msg *msg, u8 to_head); 212 struct fsm_msg *phl_fsm_dequeue_ext(struct fsm_main *fsm); 213 int phl_fsm_is_ext_queue_empty(struct fsm_main *fsm); 214 215 /* util function */ 216 u8 phl_fsm_state_id(struct fsm_obj *obj); 217 char *phl_fsm_obj_name(struct fsm_obj *obj); 218 char *phl_fsm_evt_name(struct fsm_obj *obj, u16 event); 219 u32 phl_fsm_time_pass(u32 start); 220 u32 phl_fsm_time_left(u32 start, u32 end); 221 222 223 #ifndef CONFIG_PHL_WPP 224 #define FSM_PRINT(fsm, fmt, ...) \ 225 do {\ 226 if (!fsm || phl_fsm_dbg_level(fsm, FSM_DBG_PRINT)) \ 227 PHL_TRACE(COMP_PHL_FSM, _PHL_ALWAYS_, fmt, ##__VA_ARGS__); \ 228 } while (0) 229 230 #define FSM_ERR(fsm, fmt, ...) \ 231 do {\ 232 if (!fsm || phl_fsm_dbg_level(fsm, FSM_DBG_ERR)) \ 233 PHL_TRACE(COMP_PHL_FSM, _PHL_ERR_, fmt, ##__VA_ARGS__); \ 234 } while (0) 235 236 #define FSM_WARN(fsm, fmt, ...) \ 237 do {\ 238 if (!fsm || phl_fsm_dbg_level(fsm, FSM_DBG_WARN)) \ 239 PHL_TRACE(COMP_PHL_FSM, _PHL_WARNING_, fmt, ##__VA_ARGS__); \ 240 } while (0) 241 242 #define FSM_INFO(fsm, fmt, ...) \ 243 do {\ 244 if (!fsm || phl_fsm_dbg_level(fsm, FSM_DBG_INFO)) \ 245 PHL_TRACE(COMP_PHL_FSM, _PHL_INFO_, fmt, ##__VA_ARGS__); \ 246 } while (0) 247 248 #define FSM_DBG(fsm, fmt, ...) \ 249 do {\ 250 if (!fsm || phl_fsm_dbg_level(fsm, FSM_DBG_DBG)) \ 251 PHL_TRACE(COMP_PHL_FSM, _PHL_DEBUG_, fmt, ##__VA_ARGS__); \ 252 } while (0) 253 254 #define FSM_MSG(fsm, level_, fmt, ...) \ 255 do {\ 256 if (!fsm || phl_fsm_dbg_level(fsm, level_)) \ 257 PHL_TRACE(COMP_PHL_FSM, _PHL_INFO_, fmt, ##__VA_ARGS__); \ 258 } while (0) 259 260 #define FSM_EV_MSG(fsm, level_, fmt, ...) \ 261 do {\ 262 if (!fsm || phl_fsm_evt_level(fsm, level_)) \ 263 PHL_TRACE(COMP_PHL_FSM, _PHL_INFO_, fmt, ##__VA_ARGS__); \ 264 } while (0) 265 #else 266 #undef FSM_PRINT 267 #define FSM_PRINT(fsm, fmt, ...) 268 #undef FSM_ERR 269 #define FSM_ERR(fsm, fmt, ...) 270 #undef FSM_WARN 271 #define FSM_WARN(fsm, fmt, ...) 272 #undef FSM_INFO 273 #define FSM_INFO(fsm, fmt, ...) 274 #undef FSM_DBG 275 #define FSM_DBG(fsm, fmt, ...) 276 #undef FSM_MSG 277 #define FSM_MSG(fsm, level, fmt, ...) 278 #undef FSM_EV_MSG 279 #define FSM_EV_MSG(fsm, level, fmt, ...) 280 #endif /* CONFIG_PHL_WPP */ 281 282 #endif /* __PHL_FSM_H__ */ 283