mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-03 21:48:15 +00:00 
			
		
		
		
	This converts 3 usages of this option to the non-SPL form, since there is no SPL_NEEDS_MANUAL_RELOC defined in Kconfig Signed-off-by: Simon Glass <sjg@chromium.org>
		
			
				
	
	
		
			216 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			216 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// SPDX-License-Identifier: GPL-2.0+
 | 
						|
/*
 | 
						|
 * Events provide a general-purpose way to react to / subscribe to changes
 | 
						|
 * within U-Boot
 | 
						|
 *
 | 
						|
 * Copyright 2021 Google LLC
 | 
						|
 * Written by Simon Glass <sjg@chromium.org>
 | 
						|
 */
 | 
						|
 | 
						|
#define LOG_CATEGORY	LOGC_EVENT
 | 
						|
 | 
						|
#include <common.h>
 | 
						|
#include <event.h>
 | 
						|
#include <event_internal.h>
 | 
						|
#include <log.h>
 | 
						|
#include <linker_lists.h>
 | 
						|
#include <malloc.h>
 | 
						|
#include <asm/global_data.h>
 | 
						|
#include <linux/list.h>
 | 
						|
#include <relocate.h>
 | 
						|
 | 
						|
DECLARE_GLOBAL_DATA_PTR;
 | 
						|
 | 
						|
#if CONFIG_IS_ENABLED(EVENT_DEBUG)
 | 
						|
const char *const type_name[] = {
 | 
						|
	"none",
 | 
						|
	"test",
 | 
						|
 | 
						|
	/* Events related to driver model */
 | 
						|
	"dm_post_init",
 | 
						|
	"dm_pre_probe",
 | 
						|
	"dm_post_probe",
 | 
						|
	"dm_pre_remove",
 | 
						|
	"dm_post_remove",
 | 
						|
 | 
						|
	/* init hooks */
 | 
						|
	"misc_init_f",
 | 
						|
 | 
						|
	/* fdt hooks */
 | 
						|
	"ft_fixup",
 | 
						|
 | 
						|
	/* main loop events */
 | 
						|
	"main_loop",
 | 
						|
};
 | 
						|
 | 
						|
_Static_assert(ARRAY_SIZE(type_name) == EVT_COUNT, "event type_name size");
 | 
						|
#endif
 | 
						|
 | 
						|
static const char *event_type_name(enum event_t type)
 | 
						|
{
 | 
						|
#if CONFIG_IS_ENABLED(EVENT_DEBUG)
 | 
						|
	return type_name[type];
 | 
						|
#else
 | 
						|
	return "(unknown)";
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
static int notify_static(struct event *ev)
 | 
						|
{
 | 
						|
	struct evspy_info *start =
 | 
						|
		ll_entry_start(struct evspy_info, evspy_info);
 | 
						|
	const int n_ents = ll_entry_count(struct evspy_info, evspy_info);
 | 
						|
	struct evspy_info *spy;
 | 
						|
 | 
						|
	for (spy = start; spy != start + n_ents; spy++) {
 | 
						|
		if (spy->type == ev->type) {
 | 
						|
			int ret;
 | 
						|
 | 
						|
			log_debug("Sending event %x/%s to spy '%s'\n", ev->type,
 | 
						|
				  event_type_name(ev->type), event_spy_id(spy));
 | 
						|
			ret = spy->func(NULL, ev);
 | 
						|
 | 
						|
			/*
 | 
						|
			 * TODO: Handle various return codes to
 | 
						|
			 *
 | 
						|
			 * - claim an event (no others will see it)
 | 
						|
			 * - return an error from the event
 | 
						|
			 */
 | 
						|
			if (ret)
 | 
						|
				return log_msg_ret("spy", ret);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int notify_dynamic(struct event *ev)
 | 
						|
{
 | 
						|
	struct event_state *state = gd_event_state();
 | 
						|
	struct event_spy *spy, *next;
 | 
						|
 | 
						|
	list_for_each_entry_safe(spy, next, &state->spy_head, sibling_node) {
 | 
						|
		if (spy->type == ev->type) {
 | 
						|
			int ret;
 | 
						|
 | 
						|
			log_debug("Sending event %x/%s to spy '%s'\n", ev->type,
 | 
						|
				  event_type_name(ev->type), spy->id);
 | 
						|
			ret = spy->func(spy->ctx, ev);
 | 
						|
 | 
						|
			/*
 | 
						|
			 * TODO: Handle various return codes to
 | 
						|
			 *
 | 
						|
			 * - claim an event (no others will see it)
 | 
						|
			 * - return an error from the event
 | 
						|
			 */
 | 
						|
			if (ret)
 | 
						|
				return log_msg_ret("spy", ret);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
int event_notify(enum event_t type, void *data, int size)
 | 
						|
{
 | 
						|
	struct event event;
 | 
						|
	int ret;
 | 
						|
 | 
						|
	event.type = type;
 | 
						|
	if (size > sizeof(event.data))
 | 
						|
		return log_msg_ret("size", -E2BIG);
 | 
						|
	memcpy(&event.data, data, size);
 | 
						|
 | 
						|
	ret = notify_static(&event);
 | 
						|
	if (ret)
 | 
						|
		return log_msg_ret("sta", ret);
 | 
						|
 | 
						|
	if (CONFIG_IS_ENABLED(EVENT_DYNAMIC)) {
 | 
						|
		ret = notify_dynamic(&event);
 | 
						|
		if (ret)
 | 
						|
			return log_msg_ret("dyn", ret);
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
int event_notify_null(enum event_t type)
 | 
						|
{
 | 
						|
	return event_notify(type, NULL, 0);
 | 
						|
}
 | 
						|
 | 
						|
void event_show_spy_list(void)
 | 
						|
{
 | 
						|
	struct evspy_info *start =
 | 
						|
		ll_entry_start(struct evspy_info, evspy_info);
 | 
						|
	const int n_ents = ll_entry_count(struct evspy_info, evspy_info);
 | 
						|
	struct evspy_info *spy;
 | 
						|
	const int size = sizeof(ulong) * 2;
 | 
						|
 | 
						|
	printf("Seq  %-24s  %*s  %s\n", "Type", size, "Function", "ID");
 | 
						|
	for (spy = start; spy != start + n_ents; spy++) {
 | 
						|
		printf("%3x  %-3x %-20s  %*p  %s\n", (uint)(spy - start),
 | 
						|
		       spy->type, event_type_name(spy->type), size, spy->func,
 | 
						|
		       event_spy_id(spy));
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
#if IS_ENABLED(CONFIG_NEEDS_MANUAL_RELOC)
 | 
						|
int event_manual_reloc(void)
 | 
						|
{
 | 
						|
	struct evspy_info *spy, *end;
 | 
						|
 | 
						|
	spy = ll_entry_start(struct evspy_info, evspy_info);
 | 
						|
	end = ll_entry_end(struct evspy_info, evspy_info);
 | 
						|
	for (; spy < end; spy++)
 | 
						|
		MANUAL_RELOC(spy->func);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
#if CONFIG_IS_ENABLED(EVENT_DYNAMIC)
 | 
						|
static void spy_free(struct event_spy *spy)
 | 
						|
{
 | 
						|
	list_del(&spy->sibling_node);
 | 
						|
}
 | 
						|
 | 
						|
int event_register(const char *id, enum event_t type, event_handler_t func, void *ctx)
 | 
						|
{
 | 
						|
	struct event_state *state = gd_event_state();
 | 
						|
	struct event_spy *spy;
 | 
						|
 | 
						|
	spy = malloc(sizeof(*spy));
 | 
						|
	if (!spy)
 | 
						|
		return log_msg_ret("alloc", -ENOMEM);
 | 
						|
 | 
						|
	spy->id = id;
 | 
						|
	spy->type = type;
 | 
						|
	spy->func = func;
 | 
						|
	spy->ctx = ctx;
 | 
						|
	list_add_tail(&spy->sibling_node, &state->spy_head);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
int event_uninit(void)
 | 
						|
{
 | 
						|
	struct event_state *state = gd_event_state();
 | 
						|
	struct event_spy *spy, *next;
 | 
						|
 | 
						|
	list_for_each_entry_safe(spy, next, &state->spy_head, sibling_node)
 | 
						|
		spy_free(spy);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
int event_init(void)
 | 
						|
{
 | 
						|
	struct event_state *state = gd_event_state();
 | 
						|
 | 
						|
	INIT_LIST_HEAD(&state->spy_head);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
#endif /* EVENT_DYNAMIC */
 |