trigger.h 2.0 KB

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