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