FILE
fsm.c
File preview with syntax highlighting.
linux-6.19.14/drivers/s390/net/fsm.c
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * A generic FSM based on fsm used in isdn4linux 4 * 5 */ 6 7#include "fsm.h" 8#include <linux/export.h> 9#include <linux/module.h> 10#include <linux/slab.h> 11#include <linux/timer.h> 12 13MODULE_AUTHOR("(C) 2000 IBM Corp. by Fritz Elfert <felfert@millenux.com>"); 14MODULE_DESCRIPTION("Finite state machine helper functions"); 15MODULE_LICENSE("GPL"); 16 17fsm_instance * 18init_fsm(char *name, const char **state_names, const char **event_names, int nr_states, 19 int nr_events, const fsm_node *tmpl, int tmpl_len, gfp_t order) 20{ 21 int i; 22 fsm_instance *this; 23 fsm_function_t *m; 24 fsm *f; 25 26 this = kzalloc(sizeof(fsm_instance), order); 27 if (this == NULL) { 28 printk(KERN_WARNING 29 "fsm(%s): init_fsm: Couldn't alloc instance\n", name); 30 return NULL; 31 } 32 strscpy(this->name, name, sizeof(this->name)); 33 init_waitqueue_head(&this->wait_q); 34 35 f = kzalloc(sizeof(fsm), order); 36 if (f == NULL) { 37 printk(KERN_WARNING 38 "fsm(%s): init_fsm: Couldn't alloc fsm\n", name); 39 kfree_fsm(this); 40 return NULL; 41 } 42 f->nr_events = nr_events; 43 f->nr_states = nr_states; 44 f->event_names = event_names; 45 f->state_names = state_names; 46 this->f = f; 47 48 m = kcalloc(nr_states*nr_events, sizeof(fsm_function_t), order); 49 if (m == NULL) { 50 printk(KERN_WARNING 51 "fsm(%s): init_fsm: Couldn't alloc jumptable\n", name); 52 kfree_fsm(this); 53 return NULL; 54 } 55 f->jumpmatrix = m; 56 57 for (i = 0; i < tmpl_len; i++) { 58 if ((tmpl[i].cond_state >= nr_states) || 59 (tmpl[i].cond_event >= nr_events) ) { 60 printk(KERN_ERR 61 "fsm(%s): init_fsm: Bad template l=%d st(%ld/%ld) ev(%ld/%ld)\n", 62 name, i, (long)tmpl[i].cond_state, (long)f->nr_states, 63 (long)tmpl[i].cond_event, (long)f->nr_events); 64 kfree_fsm(this); 65 return NULL; 66 } else 67 m[nr_states * tmpl[i].cond_event + tmpl[i].cond_state] = 68 tmpl[i].function; 69 } 70 return this; 71} 72 73void 74kfree_fsm(fsm_instance *this) 75{ 76 if (this) { 77 if (this->f) { 78 kfree(this->f->jumpmatrix); 79 kfree(this->f); 80 } 81 kfree(this); 82 } else 83 printk(KERN_WARNING 84 "fsm: kfree_fsm called with NULL argument\n"); 85} 86 87#if FSM_DEBUG_HISTORY 88void 89fsm_print_history(fsm_instance *fi) 90{ 91 int idx = 0; 92 int i; 93 94 if (fi->history_size >= FSM_HISTORY_SIZE) 95 idx = fi->history_index; 96 97 printk(KERN_DEBUG "fsm(%s): History:\n", fi->name); 98 for (i = 0; i < fi->history_size; i++) { 99 int e = fi->history[idx].event; 100 int s = fi->history[idx++].state; 101 idx %= FSM_HISTORY_SIZE; 102 if (e == -1) 103 printk(KERN_DEBUG " S=%s\n", 104 fi->f->state_names[s]); 105 else 106 printk(KERN_DEBUG " S=%s E=%s\n", 107 fi->f->state_names[s], 108 fi->f->event_names[e]); 109 } 110 fi->history_size = fi->history_index = 0; 111} 112 113void 114fsm_record_history(fsm_instance *fi, int state, int event) 115{ 116 fi->history[fi->history_index].state = state; 117 fi->history[fi->history_index++].event = event; 118 fi->history_index %= FSM_HISTORY_SIZE; 119 if (fi->history_size < FSM_HISTORY_SIZE) 120 fi->history_size++; 121} 122#endif 123 124const char * 125fsm_getstate_str(fsm_instance *fi) 126{ 127 int st = atomic_read(&fi->state); 128 if (st >= fi->f->nr_states) 129 return "Invalid"; 130 return fi->f->state_names[st]; 131} 132 133static void 134fsm_expire_timer(struct timer_list *t) 135{ 136 fsm_timer *this = timer_container_of(this, t, tl); 137#if FSM_TIMER_DEBUG 138 printk(KERN_DEBUG "fsm(%s): Timer %p expired\n", 139 this->fi->name, this); 140#endif 141 fsm_event(this->fi, this->expire_event, this->event_arg); 142} 143 144void 145fsm_settimer(fsm_instance *fi, fsm_timer *this) 146{ 147 this->fi = fi; 148#if FSM_TIMER_DEBUG 149 printk(KERN_DEBUG "fsm(%s): Create timer %p\n", fi->name, 150 this); 151#endif 152 timer_setup(&this->tl, fsm_expire_timer, 0); 153} 154 155void 156fsm_deltimer(fsm_timer *this) 157{ 158#if FSM_TIMER_DEBUG 159 printk(KERN_DEBUG "fsm(%s): Delete timer %p\n", this->fi->name, 160 this); 161#endif 162 timer_delete(&this->tl); 163} 164 165int 166fsm_addtimer(fsm_timer *this, int millisec, int event, void *arg) 167{ 168 169#if FSM_TIMER_DEBUG 170 printk(KERN_DEBUG "fsm(%s): Add timer %p %dms\n", 171 this->fi->name, this, millisec); 172#endif 173 174 timer_setup(&this->tl, fsm_expire_timer, 0); 175 this->expire_event = event; 176 this->event_arg = arg; 177 this->tl.expires = jiffies + (millisec * HZ) / 1000; 178 add_timer(&this->tl); 179 return 0; 180} 181 182/* FIXME: this function is never used, why */ 183void 184fsm_modtimer(fsm_timer *this, int millisec, int event, void *arg) 185{ 186 187#if FSM_TIMER_DEBUG 188 printk(KERN_DEBUG "fsm(%s): Restart timer %p %dms\n", 189 this->fi->name, this, millisec); 190#endif 191 192 timer_delete(&this->tl); 193 timer_setup(&this->tl, fsm_expire_timer, 0); 194 this->expire_event = event; 195 this->event_arg = arg; 196 this->tl.expires = jiffies + (millisec * HZ) / 1000; 197 add_timer(&this->tl); 198} 199 200EXPORT_SYMBOL(init_fsm); 201EXPORT_SYMBOL(kfree_fsm); 202EXPORT_SYMBOL(fsm_settimer); 203EXPORT_SYMBOL(fsm_deltimer); 204EXPORT_SYMBOL(fsm_addtimer); 205EXPORT_SYMBOL(fsm_modtimer); 206EXPORT_SYMBOL(fsm_getstate_str); 207 208#if FSM_DEBUG_HISTORY 209EXPORT_SYMBOL(fsm_print_history); 210EXPORT_SYMBOL(fsm_record_history); 211#endif
~/
Read-only file preview.