1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef __TRIGGER_H_ 3 #define __TRIGGER_H_ 1 4 5 #include "asm/bug.h" 6 7 /* 8 * Use trigger to model operations which need to be executed when 9 * an event (a signal, for example) is observed. 10 * 11 * States and transits: 12 * 13 * 14 * OFF--> ON --> READY --(hit)--> HIT 15 * ^ | 16 * | (ready) 17 * | | 18 * \_____________/ 19 * 20 * is_hit and is_ready are two key functions to query the state of 21 * a trigger. is_hit means the event already happen; is_ready means the 22 * trigger is waiting for the event. 23 */ 24 25 struct trigger { 26 volatile enum { 27 TRIGGER_ERROR = -2, 28 TRIGGER_OFF = -1, 29 TRIGGER_ON = 0, 30 TRIGGER_READY = 1, 31 TRIGGER_HIT = 2, 32 } state; 33 const char *name; 34 }; 35 36 #define TRIGGER_WARN_ONCE(t, exp) \ 37 WARN_ONCE(t->state != exp, "trigger '%s' state transist error: %d in %s()\n", \ 38 t->name, t->state, __func__) 39 40 static inline bool trigger_is_available(struct trigger *t) 41 { 42 return t->state >= 0; 43 } 44 45 static inline bool trigger_is_error(struct trigger *t) 46 { 47 return t->state <= TRIGGER_ERROR; 48 } 49 50 static inline void trigger_on(struct trigger *t) 51 { 52 TRIGGER_WARN_ONCE(t, TRIGGER_OFF); 53 t->state = TRIGGER_ON; 54 } 55 56 static inline void trigger_ready(struct trigger *t) 57 { 58 if (!trigger_is_available(t)) 59 return; 60 t->state = TRIGGER_READY; 61 } 62 63 static inline void trigger_hit(struct trigger *t) 64 { 65 if (!trigger_is_available(t)) 66 return; 67 TRIGGER_WARN_ONCE(t, TRIGGER_READY); 68 t->state = TRIGGER_HIT; 69 } 70 71 static inline void trigger_off(struct trigger *t) 72 { 73 if (!trigger_is_available(t)) 74 return; 75 t->state = TRIGGER_OFF; 76 } 77 78 static inline void trigger_error(struct trigger *t) 79 { 80 t->state = TRIGGER_ERROR; 81 } 82 83 static inline bool trigger_is_ready(struct trigger *t) 84 { 85 return t->state == TRIGGER_READY; 86 } 87 88 static inline bool trigger_is_hit(struct trigger *t) 89 { 90 return t->state == TRIGGER_HIT; 91 } 92 93 #define DEFINE_TRIGGER(n) \ 94 struct trigger n = {.state = TRIGGER_OFF, .name = #n} 95 #endif 96