Base Linux RC5.0
echo mem > /sys/power/state
Suspend Resume
| |
call notifiers Turn On Power
| |
freeze tasks System core online
| |
devices suspend Nonboot cpu online
| |
.prepare Devices Resume
| |
.suspend .resume_noirq
| |
.suspend_late .resume_early
| |
.suspend_noir .resume
| |
nonboot cpu offline .comnplete
| |
system core offline thaw tasks
| |
turn off power call notifiers
autosleep_store /*節點調用的入口函數*/
decode_state /*解析對用state, pm_state的初始化在pm_state_init(pm init完成)*/
pm_autosleep_set_state
__pm_stay_awake(autosleep_ws);
__pm_relax(autosleep_ws);
pm_wakep_autosleep_enabled
pm_suspend (state < PM_SUSPEND_MAX) /*Externally visible function for suspending the system*/
enter_state /*Do common work needed to enter system sleep state*/
state_store
pm_autosleep_lock
pm_autosleep_state() > PM_SUSPEND_ON /*如果進入到suspend流程,返還出去*/
decode_state /*解析對用state, pm_state的初始化在pm_state_init(pm init完成)*/
if (state < PM_SUSPEND_MAX) {
if (state == PM_SUSPEND_MEM)
state = mem_sleep_current; /*mem_sleep_store 函數初始化 mem sleep current的值*/
error = pm_suspend(state); /*Externally visible function for suspending the system*/
enter_state() /*Do common work needed to enter system sleep state*/
if (state == PM_SUSPEND_TO_IDLE)
s2idle_begin(); /*s2idle_state = S2IDLE_STATE_NONE*/
pm_suspend_clear_flags /*設置pm_suspend_global_flags = 0*/
suspend_prepare() /*Prepare for entering system sleep state*/
pm_prepare_console() /*切換 控制檯打印口*/
__pm_notifier_call_chain() /*運行suspend的notifylist*/
suspend_freeze_processes()
freeze_processes /*凍結用戶進程, 失敗則thaw_processes解凍進程*/
freeze_kernel_threads /*凍結內核進程嗎,失敗則thaw_processes解凍進*/
dpm_save_failed_step() /*what to do????*/
error go out:
__pm_notifier_call_chain /*notify PM_POST_SUSPEND*/
pm_restore_console /*恢復控制檯*/
suspend_test() /*調試使用的api*/
suspend_devices_and_enter() /*設備驅動休眠與進系統休眠*/
sleep_state_supported() /*判斷是否支持*/
platform_suspend_begin()
s2idle_ops->begin()
suspend_ops->begin(state) /*suspend_set_ops(&psci_suspend_ops); psci 沒有begin這個api,所以return*/
suspend_console() /*Suspending console(s) (use no_console_suspend to debug)*/
suspend_test_start() /** what to do???/
dpm_suspend_start()
dpm_prepare()
wait_for_device_probe() /*清理workqueue, 等待wq完成,同步域中的所有異步函數*/
device_block_probing() /*sync with probes to avoid races*/
device_prepare() /*調用devices pm ops.prepare*/
dpm_suspend()
devfreq_suspend()
cpufreq_suspend()
device_suspend()
/*dpm_prepared_list),轉移到dpm_suspended_list*/
async_synchronize_full()
suspend_enter()
platform_suspend_prepare() /*suspend_ops->prepare*/
dpm_suspend_late() /*與dpm suspend 差別, 父節點的devices suspend, suspend late suspend設備*/
platform_suspend_prepare_late() /*s2idle_ops->prepare()*/
s2idle_loop /*state = id or test level RETURN*/
dpm_suspend_noirq() /*要disable irq的設備suspend,noirq,是通過禁止所有的中斷線的形式,而不是通過關全局中斷的方式*/
platform_suspend_prepare_noirq()
/*suspend_ops->prepare_late(), suspend_ops的prepare_late回調, 通知平臺代碼,以便讓其在最後關頭,再做一些處理, 失敗的話,需要跳至Platform_wake處,
如果是suspend to freeze,執行相應的操作,包括凍結進程、suspended devices(參數爲PM_SUSPEND_FREEZE)、cpu進入idle
如果有任何事件使CPU從idle狀態退出,跳至Platform_wake處,執行wake操作*/
disable_nonboot_cpus() /*offline 非boot cpu, 調用cpudown的接口*/
arch_suspend_disable_irqs() /*local_irq_disable*/
syscore_suspend()
pm_wakeup_pending /*檢查wakeup狀態, return error*/ /*用pm_wakeup_pending檢查一下,這段時間內,是否有喚醒事件發生,如果有就要終止suspend*/
ops->suspend /*syscore_ops_list 上的suspend調用,exp: cpufreq_stop_governor*/
pm_wakeup_pending /*再次檢查wakeup狀態*/
suspend_ops->enter(state) /*調用到psci接口中*/
out path:
syscore_resume
arch_suspend_enable_irqs
enable_nonboot_cpus
platform_resume_noirq
dpm_resume_noirq
platform_resume_early
dpm_resume_early
platform_resume_finish
} else if (state == PM_SUSPEND_MAX) {
error = hibernate();
} else {
error = -EINVAL;
}