Linux suspend procedure introduction (1)
1. 简介
在消费类电子产品中,系统功耗是非常重要的指标,其直接影响到设备的续航时间。比如智能手机,当暂时不使用时,需要关闭部分设备(如显示屏)以降低功耗,进入低功耗模式,此时执行的就是suspend流程,当我们使用手机时,就需要将其从低功耗模式唤醒,此时系统进入resume流程,唤醒系统。本文主要介绍linux系统中的suspend流程,resume流程和suspend流程基本类似,只是执行的操作刚好相反,本文就不赘述了。
在系统suspend的过程中,主要完成以下工作:
1) 调用其他子系统注册在通知链上的回调函数,通知其suspend事件到来
a) 当设备驱动在framework层(userspace)实现,此时需要使用通知链提前通知其suspend事件到来;
b) 当驱动在resume流程中调用了request_firmware,因此在系统suspend前需要通知设备驱动在suspend回调函数中将firmware文件下载到RAM中。
当发生如下事件时,会调用注册在通知链上的回调函数:
PM_HIBERNATION_PREPARE
PM_POST_HIBERNATION
PM_RESTORE_PREPARE
PM_POST_RESTORE
PM_SUSPEND_PREPARE (suspend流程会调用这个)
PM_POST_SUSPEND
2) Freeze 系统进程
后续文章会详细介绍。
3) Suspend console
4) Suspend 非系统设备(non-sysdev)
5) 调用各个驱动程序的suspend函数
此阶段调用各个驱动中注册的suspend函数,需驱动工程师按具体需求实现。
6) Suspend 中断
后续文章会详细介绍
7) Suspend system core
2. 代码分析
代码路径:kernel/power/suspend.c
pm_suspend函数是一个对外部可见的API,其他模块可通过调用它使系统进入低功耗模式,函数实现如下:
int pm_suspend(suspend_state_t state)
{
int error;
if (state <= PM_SUSPEND_ON || state >= PM_SUSPEND_MAX)
return -EINVAL;
pm_suspend_marker("entry");
error = enter_state(state);
if (error) {
suspend_stats.fail++;
dpm_save_failed_errno(error);
} else {
suspend_stats.success++;
}
pm_suspend_marker("exit");
return error;
}
EXPORT_SYMBOL(pm_suspend);
其中state是系统要进入的睡眠模式。
整个suspend过程中的函数调用关系如下:
pm_suspend
->enter_state
->suspend_prepare
-> pm_prepare_console
-> __pm_notifier_call_chain
-> suspend_freeze_processes
->suspend_devices_and_enter
->platform_suspend_begin
->suspend_console
->dpm_suspend_start
->suspend_enter
->platform_suspend_prepare
->dpm_suspend_late
->platform_suspend_prepare_late
->dpm_suspend_noirq
->platform_suspend_prepare_noirq
->disable_nonboot_cpus
->syscore_suspend
参考文献:
Linux 内核文档:freezing-of-tasks.txt