]> Git Repo - J-u-boot.git/blob - common/event.c
Merge tag 'v2023.10-rc4' into next
[J-u-boot.git] / common / event.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Events provide a general-purpose way to react to / subscribe to changes
4  * within U-Boot
5  *
6  * Copyright 2021 Google LLC
7  * Written by Simon Glass <[email protected]>
8  */
9
10 #define LOG_CATEGORY    LOGC_EVENT
11
12 #include <common.h>
13 #include <event.h>
14 #include <event_internal.h>
15 #include <log.h>
16 #include <linker_lists.h>
17 #include <malloc.h>
18 #include <asm/global_data.h>
19 #include <linux/list.h>
20 #include <relocate.h>
21
22 DECLARE_GLOBAL_DATA_PTR;
23
24 #if CONFIG_IS_ENABLED(EVENT_DEBUG)
25 const char *const type_name[] = {
26         "none",
27         "test",
28
29         /* Events related to driver model */
30         "dm_post_init_f",
31         "dm_post_init_r",
32         "dm_pre_probe",
33         "dm_post_probe",
34         "dm_pre_remove",
35         "dm_post_remove",
36
37         /* init hooks */
38         "misc_init_f",
39         "fsp_init_r",
40         "last_stage_init",
41
42         /* Fpga load hook */
43         "fpga_load",
44
45         /* fdt hooks */
46         "ft_fixup",
47
48         /* main loop events */
49         "main_loop",
50 };
51
52 _Static_assert(ARRAY_SIZE(type_name) == EVT_COUNT, "event type_name size");
53 #endif
54
55 const char *event_type_name(enum event_t type)
56 {
57 #if CONFIG_IS_ENABLED(EVENT_DEBUG)
58         return type_name[type];
59 #else
60         return "(unknown)";
61 #endif
62 }
63
64 static int notify_static(struct event *ev)
65 {
66         struct evspy_info *start =
67                 ll_entry_start(struct evspy_info, evspy_info);
68         const int n_ents = ll_entry_count(struct evspy_info, evspy_info);
69         struct evspy_info *spy;
70
71         for (spy = start; spy != start + n_ents; spy++) {
72                 if (spy->type == ev->type) {
73                         int ret;
74
75                         log_debug("Sending event %x/%s to spy '%s'\n", ev->type,
76                                   event_type_name(ev->type), event_spy_id(spy));
77                         if (spy->flags & EVSPYF_SIMPLE) {
78                                 const struct evspy_info_simple *simple;
79
80                                 simple = (struct evspy_info_simple *)spy;
81                                 ret = simple->func();
82                         } else {
83                                 ret = spy->func(NULL, ev);
84                         }
85
86                         /*
87                          * TODO: Handle various return codes to
88                          *
89                          * - claim an event (no others will see it)
90                          * - return an error from the event
91                          */
92                         if (ret)
93                                 return log_msg_ret("spy", ret);
94                 }
95         }
96
97         return 0;
98 }
99
100 static int notify_dynamic(struct event *ev)
101 {
102         struct event_state *state = gd_event_state();
103         struct event_spy *spy, *next;
104
105         list_for_each_entry_safe(spy, next, &state->spy_head, sibling_node) {
106                 if (spy->type == ev->type) {
107                         int ret;
108
109                         log_debug("Sending event %x/%s to spy '%s'\n", ev->type,
110                                   event_type_name(ev->type), spy->id);
111                         ret = spy->func(spy->ctx, ev);
112
113                         /*
114                          * TODO: Handle various return codes to
115                          *
116                          * - claim an event (no others will see it)
117                          * - return an error from the event
118                          */
119                         if (ret)
120                                 return log_msg_ret("spy", ret);
121                 }
122         }
123
124         return 0;
125 }
126
127 int event_notify(enum event_t type, void *data, int size)
128 {
129         struct event event;
130         int ret;
131
132         event.type = type;
133         if (size > sizeof(event.data))
134                 return log_msg_ret("size", -E2BIG);
135         memcpy(&event.data, data, size);
136
137         ret = notify_static(&event);
138         if (ret)
139                 return log_msg_ret("sta", ret);
140
141         if (CONFIG_IS_ENABLED(EVENT_DYNAMIC)) {
142                 ret = notify_dynamic(&event);
143                 if (ret)
144                         return log_msg_ret("dyn", ret);
145         }
146
147         return 0;
148 }
149
150 int event_notify_null(enum event_t type)
151 {
152         return event_notify(type, NULL, 0);
153 }
154
155 void event_show_spy_list(void)
156 {
157         struct evspy_info *start =
158                 ll_entry_start(struct evspy_info, evspy_info);
159         const int n_ents = ll_entry_count(struct evspy_info, evspy_info);
160         struct evspy_info *spy;
161         const int size = sizeof(ulong) * 2;
162
163         printf("Seq  %-24s  %*s  %s\n", "Type", size, "Function", "ID");
164         for (spy = start; spy != start + n_ents; spy++) {
165                 printf("%3x  %-3x %-20s  %*p  %s\n", (uint)(spy - start),
166                        spy->type, event_type_name(spy->type), size, spy->func,
167                        event_spy_id(spy));
168         }
169 }
170
171 #if IS_ENABLED(CONFIG_NEEDS_MANUAL_RELOC)
172 int event_manual_reloc(void)
173 {
174         struct evspy_info *spy, *end;
175
176         spy = ll_entry_start(struct evspy_info, evspy_info);
177         end = ll_entry_end(struct evspy_info, evspy_info);
178         for (; spy < end; spy++)
179                 MANUAL_RELOC(spy->func);
180
181         return 0;
182 }
183 #endif
184
185 #if CONFIG_IS_ENABLED(EVENT_DYNAMIC)
186 static void spy_free(struct event_spy *spy)
187 {
188         list_del(&spy->sibling_node);
189 }
190
191 int event_register(const char *id, enum event_t type, event_handler_t func, void *ctx)
192 {
193         struct event_state *state = gd_event_state();
194         struct event_spy *spy;
195
196         spy = malloc(sizeof(*spy));
197         if (!spy)
198                 return log_msg_ret("alloc", -ENOMEM);
199
200         spy->id = id;
201         spy->type = type;
202         spy->func = func;
203         spy->ctx = ctx;
204         list_add_tail(&spy->sibling_node, &state->spy_head);
205
206         return 0;
207 }
208
209 int event_uninit(void)
210 {
211         struct event_state *state = gd_event_state();
212         struct event_spy *spy, *next;
213
214         list_for_each_entry_safe(spy, next, &state->spy_head, sibling_node)
215                 spy_free(spy);
216
217         return 0;
218 }
219
220 int event_init(void)
221 {
222         struct event_state *state = gd_event_state();
223
224         INIT_LIST_HEAD(&state->spy_head);
225
226         return 0;
227 }
228 #endif /* EVENT_DYNAMIC */
This page took 0.039903 seconds and 4 git commands to generate.