From 37e7e856441de13dcdfb630b7ef066736bff12ac Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Tue, 18 Jan 2022 18:43:07 +0900 Subject: [PATCH] power: defer state transition until booting done If a transition event occured before booting_done(=delayed_init_done), defer the transition until booting done. Change-Id: Ib79974b34a8b55751d542c50f9354cdc95ae021b Signed-off-by: Youngjae Cho --- plugins/iot-headless/power/power-state-manager.c | 80 ++++++++++++++++++------ 1 file changed, 61 insertions(+), 19 deletions(-) diff --git a/plugins/iot-headless/power/power-state-manager.c b/plugins/iot-headless/power/power-state-manager.c index 60a7d1b..a2e90ad 100644 --- a/plugins/iot-headless/power/power-state-manager.c +++ b/plugins/iot-headless/power/power-state-manager.c @@ -43,9 +43,13 @@ char *psm_name[PSM_MAX] = { [PSM_REBOOT] = "PSM_REBOOT", }; +static int delayed_init_done = 0; static guint64 state_transition_counter = 0; static enum psm_state current = PSM_START; +/* hold trans_info until booting done */ +static GList *deferred_transition_list; + static void psm_wake_unlock(void) { /* for PSM_NORMAL, PSM_POWEROFF, do not wake unlock */ @@ -182,26 +186,10 @@ static void psm_transition_normal_to_poweroff(const struct trans_info *ti) psm_trigger_poweroff(); } -static int psm_transition_state_cb(void *data) +static void transition_state(const struct trans_info *ti) { - GList *action_list, *elem; - const struct trans_info *ti = NULL; enum psm_state next; - if (!data) - return 0; - - action_list = (GList *) data; - - /* look for transition defined on the current state */ - SYS_G_LIST_FOREACH(action_list, elem, ti) { - if (ti->curr == current) - break; - } - - if (!ti) - return 0; - next = ti->next; _D("Transition power state: %s -> %s, reason=%d", @@ -227,12 +215,66 @@ static int psm_transition_state_cb(void *data) else if (next == PSM_SLEEP) psm_transition_sleep_to_sleep(ti); } +} + +static void deferred_transition_state(gpointer data) +{ + transition_state(data); +} + +static int psm_transition_state_cb(void *data) +{ + GList *action_list, *elem; + const struct trans_info *ti = NULL; + + if (!data) + return 0; + + action_list = (GList *) data; + + /* look for transition defined on the current state */ + SYS_G_LIST_FOREACH(action_list, elem, ti) { + if (ti->curr == current) + break; + } + + if (!ti) + return 0; + + /* defer state transition until booting done */ + if (!delayed_init_done) { + struct trans_info *deferred_ti = calloc(1, sizeof(struct trans_info)); + if (!deferred_ti) { + CRITICAL_LOG("Failed to defer transition"); + return 0; + } + + // mocking state transition + current = ti->next; + + memcpy(deferred_ti, ti, sizeof(struct trans_info)); + deferred_transition_list = g_list_append(deferred_transition_list, deferred_ti); + _D("Defer state transition %s->%s until booting done", psm_name[ti->curr], psm_name[ti->next]); + + return 0; + } + + transition_state(ti); return 0; } -static int defer_autosleep_enable(void *data) +static int delayed_init_cb(void *data) { + delayed_init_done = 1; + + _D("Start deferred state transition"); + /* rewind current state to initial state and do the deferred transition */ + current = PSM_START; + g_list_free_full(deferred_transition_list, deferred_transition_state); + deferred_transition_list = NULL; + _D("Finished deferred state transition"); + /* Deferred autosleep enable, * This prevents system go suspend during booting */ device_notify(DEVICE_NOTIFIER_REQUEST_ENABLE_AUTOSLEEP, NULL); @@ -244,7 +286,7 @@ void power_state_manager_init(void *data) { GList *initial_ti = NULL; - register_notifier(DEVICE_NOTIFIER_DELAYED_INIT, defer_autosleep_enable); + register_notifier(DEVICE_NOTIFIER_DELAYED_INIT, delayed_init_cb); register_notifier(DEVICE_NOTIFIER_REQUEST_TRANSITION_STATE, psm_transition_state_cb); power_plugin_dbus_init(NULL); -- 2.7.4