power: defer state transition until booting done 73/269573/1
authorYoungjae Cho <y0.cho@samsung.com>
Tue, 18 Jan 2022 09:43:07 +0000 (18:43 +0900)
committerYoungjae Cho <y0.cho@samsung.com>
Tue, 18 Jan 2022 09:56:42 +0000 (18:56 +0900)
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 <y0.cho@samsung.com>
plugins/iot-headless/power/power-state-manager.c

index 60a7d1b..a2e90ad 100644 (file)
@@ -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);