From 8fc41e1b84301e76921730caa4e6b8e8bf27cc35 Mon Sep 17 00:00:00 2001 From: Aaron Durbin Date: Mon, 29 Apr 2013 23:22:01 -0500 Subject: boot state: run timers on state entry When TIMER_QUEUE is configured on call the timer callbacks on entry into a state but before its entry callbacks. In addition provide a barrier to the following states so that timers are drained before proceeding. This allows for blocking state traversal for key components of boot. BS_OS_RESUME BS_WRITE_TABLES BS_PAYLOAD_LOAD BS_PAYLOAD_BOOT Future functionality consists of evaluating the timer callbacks within the device tree. One example is dev_initialize() as that seems state seems to take 90% of the boot time. The timer callbacks could then be ran in a more granular manner. Change-Id: Idb549ea17c5ec38eb57b4f6f366a1c2183f4a6dd Signed-off-by: Aaron Durbin Reviewed-on: http://review.coreboot.org/3159 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich --- src/lib/hardwaremain.c | 48 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 14 deletions(-) (limited to 'src/lib/hardwaremain.c') diff --git a/src/lib/hardwaremain.c b/src/lib/hardwaremain.c index 7bf0237f91..8e5481e398 100644 --- a/src/lib/hardwaremain.c +++ b/src/lib/hardwaremain.c @@ -78,23 +78,27 @@ struct boot_state { struct boot_state_callback *seq_callbacks[2]; boot_state_t (*run_state)(void *arg); void *arg; - int complete; + int complete : 1; + int timers_drain : 1; #if CONFIG_HAVE_MONOTONIC_TIMER struct boot_state_times times; #endif }; -#define BS_INIT(state_, run_func_) \ - { \ - .name = #state_, \ - .id = state_, \ - .seq_callbacks = { NULL, NULL },\ - .run_state = run_func_, \ - .arg = NULL, \ - .complete = 0 \ +#define BS_INIT(state_, run_func_, drain_timers_) \ + { \ + .name = #state_, \ + .id = state_, \ + .seq_callbacks = { NULL, NULL }, \ + .run_state = run_func_, \ + .arg = NULL, \ + .complete = 0, \ + .timers_drain = drain_timers_, \ } #define BS_INIT_ENTRY(state_, run_func_) \ - [state_] = BS_INIT(state_, run_func_) + [state_] = BS_INIT(state_, run_func_, 0) +#define BS_INIT_ENTRY_DRAIN_TIMERS(state_, run_func_) \ + [state_] = BS_INIT(state_, run_func_, 1) static struct boot_state boot_states[] = { BS_INIT_ENTRY(BS_PRE_DEVICE, bs_pre_device), @@ -105,10 +109,10 @@ static struct boot_state boot_states[] = { BS_INIT_ENTRY(BS_DEV_INIT, bs_dev_init), BS_INIT_ENTRY(BS_POST_DEVICE, bs_post_device), BS_INIT_ENTRY(BS_OS_RESUME_CHECK, bs_os_resume_check), - BS_INIT_ENTRY(BS_OS_RESUME, bs_os_resume), - BS_INIT_ENTRY(BS_WRITE_TABLES, bs_write_tables), - BS_INIT_ENTRY(BS_PAYLOAD_LOAD, bs_payload_load), - BS_INIT_ENTRY(BS_PAYLOAD_BOOT, bs_payload_boot), + BS_INIT_ENTRY_DRAIN_TIMERS(BS_OS_RESUME, bs_os_resume), + BS_INIT_ENTRY_DRAIN_TIMERS(BS_WRITE_TABLES, bs_write_tables), + BS_INIT_ENTRY_DRAIN_TIMERS(BS_PAYLOAD_LOAD, bs_payload_load), + BS_INIT_ENTRY_DRAIN_TIMERS(BS_PAYLOAD_BOOT, bs_payload_boot), }; static boot_state_t bs_pre_device(void *arg) @@ -278,6 +282,20 @@ static inline void bs_sample_time(struct boot_state *state) {} static inline void bs_report_time(struct boot_state *state) {} #endif +#if CONFIG_TIMER_QUEUE +static void bs_run_timers(int drain) +{ + /* Drain all timer callbacks until none are left, if directed. + * Otherwise run the timers only once. */ + do { + if (!timers_run()) + break; + } while (drain); +} +#else +static void bs_run_timers(int drain) {} +#endif + static void bs_call_callbacks(struct boot_state *state, boot_state_sequence_t seq) { @@ -313,6 +331,8 @@ static void bs_walk_state_machine(boot_state_t current_state_id) printk(BS_DEBUG_LVL, "BS: Entering %s state.\n", state->name); + bs_run_timers(state->timers_drain); + bs_sample_time(state); bs_call_callbacks(state, BS_ON_ENTRY); -- cgit v1.2.3