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>
This commit is contained in:
parent
340ca91f18
commit
8fc41e1b84
|
@ -78,23 +78,27 @@ struct boot_state {
|
||||||
struct boot_state_callback *seq_callbacks[2];
|
struct boot_state_callback *seq_callbacks[2];
|
||||||
boot_state_t (*run_state)(void *arg);
|
boot_state_t (*run_state)(void *arg);
|
||||||
void *arg;
|
void *arg;
|
||||||
int complete;
|
int complete : 1;
|
||||||
|
int timers_drain : 1;
|
||||||
#if CONFIG_HAVE_MONOTONIC_TIMER
|
#if CONFIG_HAVE_MONOTONIC_TIMER
|
||||||
struct boot_state_times times;
|
struct boot_state_times times;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BS_INIT(state_, run_func_) \
|
#define BS_INIT(state_, run_func_, drain_timers_) \
|
||||||
{ \
|
{ \
|
||||||
.name = #state_, \
|
.name = #state_, \
|
||||||
.id = state_, \
|
.id = state_, \
|
||||||
.seq_callbacks = { NULL, NULL },\
|
.seq_callbacks = { NULL, NULL }, \
|
||||||
.run_state = run_func_, \
|
.run_state = run_func_, \
|
||||||
.arg = NULL, \
|
.arg = NULL, \
|
||||||
.complete = 0 \
|
.complete = 0, \
|
||||||
|
.timers_drain = drain_timers_, \
|
||||||
}
|
}
|
||||||
#define BS_INIT_ENTRY(state_, run_func_) \
|
#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[] = {
|
static struct boot_state boot_states[] = {
|
||||||
BS_INIT_ENTRY(BS_PRE_DEVICE, bs_pre_device),
|
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_DEV_INIT, bs_dev_init),
|
||||||
BS_INIT_ENTRY(BS_POST_DEVICE, bs_post_device),
|
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_CHECK, bs_os_resume_check),
|
||||||
BS_INIT_ENTRY(BS_OS_RESUME, bs_os_resume),
|
BS_INIT_ENTRY_DRAIN_TIMERS(BS_OS_RESUME, bs_os_resume),
|
||||||
BS_INIT_ENTRY(BS_WRITE_TABLES, bs_write_tables),
|
BS_INIT_ENTRY_DRAIN_TIMERS(BS_WRITE_TABLES, bs_write_tables),
|
||||||
BS_INIT_ENTRY(BS_PAYLOAD_LOAD, bs_payload_load),
|
BS_INIT_ENTRY_DRAIN_TIMERS(BS_PAYLOAD_LOAD, bs_payload_load),
|
||||||
BS_INIT_ENTRY(BS_PAYLOAD_BOOT, bs_payload_boot),
|
BS_INIT_ENTRY_DRAIN_TIMERS(BS_PAYLOAD_BOOT, bs_payload_boot),
|
||||||
};
|
};
|
||||||
|
|
||||||
static boot_state_t bs_pre_device(void *arg)
|
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) {}
|
static inline void bs_report_time(struct boot_state *state) {}
|
||||||
#endif
|
#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,
|
static void bs_call_callbacks(struct boot_state *state,
|
||||||
boot_state_sequence_t seq)
|
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);
|
printk(BS_DEBUG_LVL, "BS: Entering %s state.\n", state->name);
|
||||||
|
|
||||||
|
bs_run_timers(state->timers_drain);
|
||||||
|
|
||||||
bs_sample_time(state);
|
bs_sample_time(state);
|
||||||
|
|
||||||
bs_call_callbacks(state, BS_ON_ENTRY);
|
bs_call_callbacks(state, BS_ON_ENTRY);
|
||||||
|
|
Loading…
Reference in New Issue