diff options
author | Aaron Durbin <adurbin@chromium.org> | 2013-04-29 23:22:01 -0500 |
---|---|---|
committer | Ronald G. Minnich <rminnich@gmail.com> | 2013-05-01 07:19:52 +0200 |
commit | 8fc41e1b84301e76921730caa4e6b8e8bf27cc35 (patch) | |
tree | 65b5ce10e1dcc70864f65f3c930becb5ada3968d | |
parent | 340ca91f18a448e09973341f60bb6f46102d2410 (diff) |
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 <adurbin@chromium.org>
Reviewed-on: http://review.coreboot.org/3159
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
-rw-r--r-- | src/lib/hardwaremain.c | 48 |
1 files changed, 34 insertions, 14 deletions
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); |