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