/** * toi_go_atomic - do the actual atomic copy/restore * @state: The state to use for dpm_suspend_start & power_down calls. * @suspend_time: Whether we're suspending or resuming. **/ int toi_go_atomic(pm_message_t state, int suspend_time) { if (suspend_time) { if (platform_begin(1)) { set_abort_result(TOI_PLATFORM_PREP_FAILED); toi_end_atomic(ATOMIC_STEP_PLATFORM_END, suspend_time, 3); return 1; } if (dpm_prepare(PMSG_FREEZE)) { set_abort_result(TOI_DPM_PREPARE_FAILED); dpm_complete(PMSG_RECOVER); toi_end_atomic(ATOMIC_STEP_PLATFORM_END, suspend_time, 3); return 1; } } suspend_console(); ftrace_stop(); pm_restrict_gfp_mask(); if (suspend_time) { if (dpm_suspend(state)) { set_abort_result(TOI_DPM_SUSPEND_FAILED); toi_end_atomic(ATOMIC_STEP_DEVICE_RESUME, suspend_time, 3); return 1; } } else { if (dpm_suspend_start(state)) { set_abort_result(TOI_DPM_SUSPEND_FAILED); toi_end_atomic(ATOMIC_STEP_DEVICE_RESUME, suspend_time, 3); return 1; } } /* At this point, dpm_suspend_start() has been called, but *not* * dpm_suspend_noirq(). We *must* dpm_suspend_noirq() now. * Otherwise, drivers for some devices (e.g. interrupt controllers) * become desynchronized with the actual state of the hardware * at resume time, and evil weirdness ensues. */ if (dpm_suspend_end(state)) { set_abort_result(TOI_DEVICE_REFUSED); toi_end_atomic(ATOMIC_STEP_DEVICE_RESUME, suspend_time, 1); return 1; } if (suspend_time) { if (platform_pre_snapshot(1)) set_abort_result(TOI_PRE_SNAPSHOT_FAILED); } else { if (platform_pre_restore(1)) set_abort_result(TOI_PRE_RESTORE_FAILED); } if (test_result_state(TOI_ABORTED)) { toi_end_atomic(ATOMIC_STEP_PLATFORM_FINISH, suspend_time, 1); return 1; } if (test_action_state(TOI_LATE_CPU_HOTPLUG)) { if (disable_nonboot_cpus()) { set_abort_result(TOI_CPU_HOTPLUG_FAILED); toi_end_atomic(ATOMIC_STEP_CPU_HOTPLUG, suspend_time, 1); return 1; } } local_irq_disable(); if (syscore_suspend()) { set_abort_result(TOI_SYSCORE_REFUSED); toi_end_atomic(ATOMIC_STEP_IRQS, suspend_time, 1); return 1; } if (suspend_time && pm_wakeup_pending()) { set_abort_result(TOI_WAKEUP_EVENT); toi_end_atomic(ATOMIC_STEP_SYSCORE_RESUME, suspend_time, 1); return 1; } return 0; }
/** * toi_go_atomic - do the actual atomic copy/restore * @state: The state to use for dpm_suspend_start & power_down calls. * @suspend_time: Whether we're suspending or resuming. **/ int toi_go_atomic(pm_message_t state, int suspend_time) { if (suspend_time) { if (platform_begin(1)) { set_abort_result(TOI_PLATFORM_PREP_FAILED); toi_end_atomic(ATOMIC_STEP_PLATFORM_END, suspend_time, 3); hib_log("FAILED @line:%d suspend(%d) pm_state(%d)\n", __LINE__, suspend_time, state.event); return 1; } if (dpm_prepare(PMSG_FREEZE)) { set_abort_result(TOI_DPM_PREPARE_FAILED); dpm_complete(PMSG_RECOVER); toi_end_atomic(ATOMIC_STEP_PLATFORM_END, suspend_time, 3); hib_log("FAILED @line:%d suspend(%d) pm_state(%d)\n", __LINE__, suspend_time, state.event); return 1; } } suspend_console(); ftrace_stop(); pm_restrict_gfp_mask(); if (suspend_time) { #if 0 /* FIXME: jonathan.jmchen: trick code here to let dpm_suspend succeeded, NEED to find out the root cause!! */ if (events_check_enabled) { hib_log("play trick here set events_check_enabled(%d) = false!!\n", events_check_enabled); events_check_enabled = false; } #endif if (dpm_suspend(state)) { set_abort_result(TOI_DPM_SUSPEND_FAILED); toi_end_atomic(ATOMIC_STEP_DEVICE_RESUME, suspend_time, 3); hib_log("FAILED @line:%d suspend(%d) pm_state(%d) toi_result(0x%#lx)\n", __LINE__, suspend_time, state.event, toi_result); return 1; } } else { if (dpm_suspend_start(state)) { set_abort_result(TOI_DPM_SUSPEND_FAILED); toi_end_atomic(ATOMIC_STEP_DEVICE_RESUME, suspend_time, 3); hib_log("FAILED @line:%d suspend(%d) pm_state(%d) toi_result(0x%#lx)\n", __LINE__, suspend_time, state.event, toi_result); return 1; } } /* At this point, dpm_suspend_start() has been called, but *not* * dpm_suspend_noirq(). We *must* dpm_suspend_noirq() now. * Otherwise, drivers for some devices (e.g. interrupt controllers) * become desynchronized with the actual state of the hardware * at resume time, and evil weirdness ensues. */ if (dpm_suspend_end(state)) { set_abort_result(TOI_DEVICE_REFUSED); toi_end_atomic(ATOMIC_STEP_DEVICE_RESUME, suspend_time, 1); hib_log("FAILED @line:%d suspend(%d) pm_state(%d) toi_result(0x%#lx)\n", __LINE__, suspend_time, state.event, toi_result); return 1; } if (suspend_time) { if (platform_pre_snapshot(1)) set_abort_result(TOI_PRE_SNAPSHOT_FAILED); } else { if (platform_pre_restore(1)) set_abort_result(TOI_PRE_RESTORE_FAILED); } if (test_result_state(TOI_ABORTED)) { toi_end_atomic(ATOMIC_STEP_PLATFORM_FINISH, suspend_time, 1); hib_log("FAILED @line:%d suspend(%d) pm_state(%d) toi_result(0x%#lx)\n", __LINE__, suspend_time, state.event, toi_result); return 1; } if (test_action_state(TOI_LATE_CPU_HOTPLUG)) { if (disable_nonboot_cpus()) { set_abort_result(TOI_CPU_HOTPLUG_FAILED); toi_end_atomic(ATOMIC_STEP_CPU_HOTPLUG, suspend_time, 1); hib_log("FAILED @line:%d suspend(%d) pm_state(%d) toi_result(0x%#lx)\n", __LINE__, suspend_time, state.event, toi_result); return 1; } } local_irq_disable(); if (syscore_suspend()) { set_abort_result(TOI_SYSCORE_REFUSED); toi_end_atomic(ATOMIC_STEP_IRQS, suspend_time, 1); hib_log("FAILED @line:%d suspend(%d) pm_state(%d) toi_result(0x%#lx)\n", __LINE__, suspend_time, state.event, toi_result); return 1; } if (suspend_time && pm_wakeup_pending()) { set_abort_result(TOI_WAKEUP_EVENT); toi_end_atomic(ATOMIC_STEP_SYSCORE_RESUME, suspend_time, 1); hib_log("FAILED @line:%d suspend(%d) pm_state(%d) toi_result(0x%#lx)\n", __LINE__, suspend_time, state.event, toi_result); return 1; } hib_log("SUCCEEDED @line:%d suspend(%d) pm_state(%d)\n", __LINE__, suspend_time, state.event); return 0; }