static void action_transition(void);
static uint64_t get_next_state(void);
-static void action_for_normal(void *data);
-static void action_for_sleep(void *data);
-static void action_for_poweroff(void *data);
-static void (*const action_for_state[DEVICED_POWER_STATE_MAX_INDEX]) (void *) = {
- [DEVICED_POWER_STATE_NORMAL_INDEX] = action_for_normal,
- [DEVICED_POWER_STATE_SLEEP_INDEX] = action_for_sleep,
- [DEVICED_POWER_STATE_POWEROFF_INDEX] = action_for_poweroff,
- [DEVICED_POWER_STATE_REBOOT_INDEX] = action_for_poweroff,
- [DEVICED_POWER_STATE_EXIT_INDEX] = action_for_poweroff,
+static void pre_action_normal(void *data);
+static void pre_action_poweroff(void *data);
+static void (*const pre_action_state[DEVICED_POWER_STATE_MAX_INDEX]) (void *) = {
+ [DEVICED_POWER_STATE_NORMAL_INDEX] = pre_action_normal,
+ [DEVICED_POWER_STATE_POWEROFF_INDEX] = pre_action_poweroff,
+ [DEVICED_POWER_STATE_REBOOT_INDEX] = pre_action_poweroff,
+ [DEVICED_POWER_STATE_EXIT_INDEX] = pre_action_poweroff,
};
+static void post_action_sleep(void *data);
+static void post_action_poweroff(void *data);
+static void (*const post_action_state[DEVICED_POWER_STATE_MAX_INDEX]) (void *) = {
+ [DEVICED_POWER_STATE_SLEEP_INDEX] = post_action_sleep,
+ [DEVICED_POWER_STATE_POWEROFF_INDEX] = post_action_poweroff,
+ [DEVICED_POWER_STATE_REBOOT_INDEX] = post_action_poweroff,
+ [DEVICED_POWER_STATE_EXIT_INDEX] = post_action_poweroff,
+};
+
+
uint64_t power_get_state(void)
{
return current;
return ++id;
}
-static void action_for_normal(void *udata)
+static void pre_action_normal(void *udata)
{
power_resume(transition_context.ti.reason);
}
-static void action_for_sleep(void *udata)
+static void post_action_sleep(void *udata)
{
power_suspend(transition_context.ti.reason);
}
-static void action_for_poweroff(void *data)
+static void pre_action_poweroff(void *data)
{
// do not transition anymore after poweroff
unregister_notifier(DEVICE_NOTIFIER_REQUEST_TRANSITION_STATE, transition_request_callback);
-
poweroff_prepare(current);
+}
+
+static void post_action_poweroff(void *data)
+{
poweroff_main((void *)(intptr_t) current);
}
static void action_transition(void)
{
uint64_t state = get_next_state();
+ struct trans_info ti = { 0 , };
+ int retval;
+ int index;
transition_description(0);
- if (state == transition_context.ti.next) {
- // it has reached the destination state
- struct trans_info ti = { 0 , };
- int retval;
- int index;
-
- index = DEVICED_POWER_STATE_INDEX(transition_context.ti.next);
- if (transition_context.cancel)
- cancel_transition();
- else if (action_for_state[index])
- action_for_state[index](transition_context.ti.data);
-
- // transition end
- transition_context.ongoing = 0;
- current = transition_context.ti.next;
- event_wake_unlock(EL_POWER_TRANSITION_STATE);
-
- // trigger next transition if exist
- retval = dequeue_transition(&ti);
- if (retval == 0) {
- prepare_transition(&ti);
- trigger_transition();
- }
- } else {
+ if (state != transition_context.ti.next) {
// step into the next transient state
++transition_context.transient_step;
trigger_transition();
+ return;
+ }
+
+ /* it reached the destination state */
+ index = DEVICED_POWER_STATE_INDEX(transition_context.ti.next);
+ if (transition_context.cancel) {
+ cancel_transition();
+ goto trigger_next;
+ }
+
+ if (pre_action_state[index])
+ pre_action_state[index](transition_context.ti.data);
+
+ current = transition_context.ti.next;
+
+ if (post_action_state[index])
+ post_action_state[index](transition_context.ti.data);
+
+ /**
+ * transition_context.ongiong must be reset after the post_action_state().
+ * This prevents the post_action_state() from triggering another transition
+ * that might have been requested during its execution. Transition will be
+ * enqueued, not executed, if transition_context.ongoing is 1.
+ */
+ transition_context.ongoing = 0;
+ event_wake_unlock(EL_POWER_TRANSITION_STATE);
+
+trigger_next:
+ retval = dequeue_transition(&ti);
+ if (retval == 0) {
+ prepare_transition(&ti);
+ trigger_transition();
}
}