1 // SPDX-License-Identifier: GPL-2.0+
3 * Events provide a general-purpose way to react to / subscribe to changes
6 * Copyright 2021 Google LLC
10 #define LOG_CATEGORY LOGC_EVENT
14 #include <event_internal.h>
16 #include <linker_lists.h>
18 #include <asm/global_data.h>
19 #include <linux/list.h>
22 DECLARE_GLOBAL_DATA_PTR;
24 #if CONFIG_IS_ENABLED(EVENT_DEBUG)
25 const char *const type_name[] = {
29 /* Events related to driver model */
45 /* main loop events */
49 _Static_assert(ARRAY_SIZE(type_name) == EVT_COUNT, "event type_name size");
52 static const char *event_type_name(enum event_t type)
54 #if CONFIG_IS_ENABLED(EVENT_DEBUG)
55 return type_name[type];
61 static int notify_static(struct event *ev)
63 struct evspy_info *start =
64 ll_entry_start(struct evspy_info, evspy_info);
65 const int n_ents = ll_entry_count(struct evspy_info, evspy_info);
66 struct evspy_info *spy;
68 for (spy = start; spy != start + n_ents; spy++) {
69 if (spy->type == ev->type) {
72 log_debug("Sending event %x/%s to spy '%s'\n", ev->type,
73 event_type_name(ev->type), event_spy_id(spy));
74 if (spy->flags & EVSPYF_SIMPLE) {
75 const struct evspy_info_simple *simple;
77 simple = (struct evspy_info_simple *)spy;
80 ret = spy->func(NULL, ev);
84 * TODO: Handle various return codes to
86 * - claim an event (no others will see it)
87 * - return an error from the event
90 return log_msg_ret("spy", ret);
97 static int notify_dynamic(struct event *ev)
99 struct event_state *state = gd_event_state();
100 struct event_spy *spy, *next;
102 list_for_each_entry_safe(spy, next, &state->spy_head, sibling_node) {
103 if (spy->type == ev->type) {
106 log_debug("Sending event %x/%s to spy '%s'\n", ev->type,
107 event_type_name(ev->type), spy->id);
108 ret = spy->func(spy->ctx, ev);
111 * TODO: Handle various return codes to
113 * - claim an event (no others will see it)
114 * - return an error from the event
117 return log_msg_ret("spy", ret);
124 int event_notify(enum event_t type, void *data, int size)
130 if (size > sizeof(event.data))
131 return log_msg_ret("size", -E2BIG);
132 memcpy(&event.data, data, size);
134 ret = notify_static(&event);
136 return log_msg_ret("sta", ret);
138 if (CONFIG_IS_ENABLED(EVENT_DYNAMIC)) {
139 ret = notify_dynamic(&event);
141 return log_msg_ret("dyn", ret);
147 int event_notify_null(enum event_t type)
149 return event_notify(type, NULL, 0);
152 void event_show_spy_list(void)
154 struct evspy_info *start =
155 ll_entry_start(struct evspy_info, evspy_info);
156 const int n_ents = ll_entry_count(struct evspy_info, evspy_info);
157 struct evspy_info *spy;
158 const int size = sizeof(ulong) * 2;
160 printf("Seq %-24s %*s %s\n", "Type", size, "Function", "ID");
161 for (spy = start; spy != start + n_ents; spy++) {
162 printf("%3x %-3x %-20s %*p %s\n", (uint)(spy - start),
163 spy->type, event_type_name(spy->type), size, spy->func,
168 #if IS_ENABLED(CONFIG_NEEDS_MANUAL_RELOC)
169 int event_manual_reloc(void)
171 struct evspy_info *spy, *end;
173 spy = ll_entry_start(struct evspy_info, evspy_info);
174 end = ll_entry_end(struct evspy_info, evspy_info);
175 for (; spy < end; spy++)
176 MANUAL_RELOC(spy->func);
182 #if CONFIG_IS_ENABLED(EVENT_DYNAMIC)
183 static void spy_free(struct event_spy *spy)
185 list_del(&spy->sibling_node);
188 int event_register(const char *id, enum event_t type, event_handler_t func, void *ctx)
190 struct event_state *state = gd_event_state();
191 struct event_spy *spy;
193 spy = malloc(sizeof(*spy));
195 return log_msg_ret("alloc", -ENOMEM);
201 list_add_tail(&spy->sibling_node, &state->spy_head);
206 int event_uninit(void)
208 struct event_state *state = gd_event_state();
209 struct event_spy *spy, *next;
211 list_for_each_entry_safe(spy, next, &state->spy_head, sibling_node)
219 struct event_state *state = gd_event_state();
221 INIT_LIST_HEAD(&state->spy_head);
225 #endif /* EVENT_DYNAMIC */