]> Git Repo - J-u-boot.git/blob - common/event.c
common: Remove <common.h> and add needed includes
[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 <event.h>
13 #include <event_internal.h>
14 #include <log.h>
15 #include <linker_lists.h>
16 #include <malloc.h>
17 #include <asm/global_data.h>
18 #include <linux/errno.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         "settings_r",
41         "last_stage_init",
42
43         /* Fpga load hook */
44         "fpga_load",
45
46         /* fdt hooks */
47         "ft_fixup",
48
49         /* main loop events */
50         "main_loop",
51 };
52
53 _Static_assert(ARRAY_SIZE(type_name) == EVT_COUNT, "event type_name size");
54 #endif
55
56 const char *event_type_name(enum event_t type)
57 {
58 #if CONFIG_IS_ENABLED(EVENT_DEBUG)
59         if (type < ARRAY_SIZE(type_name))
60                 return type_name[type];
61         else
62                 return "(unknown)";
63 #else
64         return "(unknown)";
65 #endif
66 }
67
68 static int notify_static(struct event *ev)
69 {
70         struct evspy_info *start =
71                 ll_entry_start(struct evspy_info, evspy_info);
72         const int n_ents = ll_entry_count(struct evspy_info, evspy_info);
73         struct evspy_info *spy;
74
75         for (spy = start; spy != start + n_ents; spy++) {
76                 if (spy->type == ev->type) {
77                         int ret;
78
79                         log_debug("Sending event %x/%s to spy '%s'\n", ev->type,
80                                   event_type_name(ev->type), event_spy_id(spy));
81                         if (spy->flags & EVSPYF_SIMPLE) {
82                                 const struct evspy_info_simple *simple;
83
84                                 simple = (struct evspy_info_simple *)spy;
85                                 ret = simple->func();
86                         } else {
87                                 ret = spy->func(NULL, ev);
88                         }
89
90                         /*
91                          * TODO: Handle various return codes to
92                          *
93                          * - claim an event (no others will see it)
94                          * - return an error from the event
95                          */
96                         if (ret)
97                                 return log_msg_ret("spy", ret);
98                 }
99         }
100
101         return 0;
102 }
103
104 static int notify_dynamic(struct event *ev)
105 {
106         struct event_state *state = gd_event_state();
107         struct event_spy *spy, *next;
108
109         list_for_each_entry_safe(spy, next, &state->spy_head, sibling_node) {
110                 if (spy->type == ev->type) {
111                         int ret;
112
113                         log_debug("Sending event %x/%s to spy '%s'\n", ev->type,
114                                   event_type_name(ev->type), spy->id);
115                         ret = spy->func(spy->ctx, ev);
116
117                         /*
118                          * TODO: Handle various return codes to
119                          *
120                          * - claim an event (no others will see it)
121                          * - return an error from the event
122                          */
123                         if (ret)
124                                 return log_msg_ret("spy", ret);
125                 }
126         }
127
128         return 0;
129 }
130
131 int event_notify(enum event_t type, void *data, int size)
132 {
133         struct event event;
134         int ret;
135
136         event.type = type;
137         if (size > sizeof(event.data))
138                 return log_msg_ret("size", -E2BIG);
139         memcpy(&event.data, data, size);
140
141         ret = notify_static(&event);
142         if (ret)
143                 return log_msg_ret("sta", ret);
144
145         if (CONFIG_IS_ENABLED(EVENT_DYNAMIC)) {
146                 ret = notify_dynamic(&event);
147                 if (ret)
148                         return log_msg_ret("dyn", ret);
149         }
150
151         return 0;
152 }
153
154 int event_notify_null(enum event_t type)
155 {
156         return event_notify(type, NULL, 0);
157 }
158
159 void event_show_spy_list(void)
160 {
161         struct evspy_info *start =
162                 ll_entry_start(struct evspy_info, evspy_info);
163         const int n_ents = ll_entry_count(struct evspy_info, evspy_info);
164         struct evspy_info *spy;
165         const int size = sizeof(ulong) * 2;
166
167         printf("Seq  %-24s  %*s  %s\n", "Type", size, "Function", "ID");
168         for (spy = start; spy != start + n_ents; spy++) {
169                 printf("%3x  %-3x %-20s  %*p  %s\n", (uint)(spy - start),
170                        spy->type, event_type_name(spy->type), size, spy->func,
171                        event_spy_id(spy));
172         }
173 }
174
175 #if CONFIG_IS_ENABLED(EVENT_DYNAMIC)
176 static void spy_free(struct event_spy *spy)
177 {
178         list_del(&spy->sibling_node);
179 }
180
181 int event_register(const char *id, enum event_t type, event_handler_t func, void *ctx)
182 {
183         struct event_state *state = gd_event_state();
184         struct event_spy *spy;
185
186         spy = malloc(sizeof(*spy));
187         if (!spy)
188                 return log_msg_ret("alloc", -ENOMEM);
189
190         spy->id = id;
191         spy->type = type;
192         spy->func = func;
193         spy->ctx = ctx;
194         list_add_tail(&spy->sibling_node, &state->spy_head);
195
196         return 0;
197 }
198
199 int event_uninit(void)
200 {
201         struct event_state *state = gd_event_state();
202         struct event_spy *spy, *next;
203
204         list_for_each_entry_safe(spy, next, &state->spy_head, sibling_node)
205                 spy_free(spy);
206
207         return 0;
208 }
209
210 int event_init(void)
211 {
212         struct event_state *state = gd_event_state();
213
214         INIT_LIST_HEAD(&state->spy_head);
215
216         return 0;
217 }
218 #endif /* EVENT_DYNAMIC */
This page took 0.038849 seconds and 4 git commands to generate.