Power Management
迫切的想知道power management 的流程。
对整个流程稍微整理了下
1、autosleep 流程
上层操作底层的/sys/power/autosleep 这个接口进行操作底层。在main .c 里面会创建一个autosleep 接口,对应main.c 里面的store 函数。
所对应的source code 在:/kernel/kernel/main.c 里面
static ssize_t autosleep_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t n)
{
suspend_state_t state = decode_state(buf, n);
int error;
if (state == PM_SUSPEND_ON
&& strcmp(buf, off) && strcmp(buf, off
))
return -EINVAL;
error = pm_autosleep_set_state(state);
old_state=state;
return error error : n;
}
当底层接受到上层传递到的值进行一些列的操作,有很多的state 状态:
#define PM_SUSPEND_ON ((__force suspend_state_t) 0)
#define PM_SUSPEND_STANDBY ((__force suspend_state_t) 1)
#define PM_SUSPEND_MEM ((__force suspend_state_t) 3)
#define PM_SUSPEND_MAX ((__force suspend_state_t) 4)
当底层接受到上层的state 之后,主要是调用pm_autosleep_set_state 这个函数进行power management 的管理。
它的实现如下:
int pm_autosleep_set_state(suspend_state_t state)
{
#ifndef CONFIG_HIBERNATION
if (state >= PM_SUSPEND_MAX)
return -EINVAL;
#endif
__pm_stay_awake(autosleep_ws);
mutex_lock(&autosleep_lock);
autosleep_state = state;
__pm_relax(autosleep_ws);
if (state > PM_SUSPEND_ON) {
pm_wakep_autosleep_enabled(true);
//Add a timer to trigger wakelock debug
pr_info([PM]unattended_timer: mod_timer (auto_sleep)
);
mod_timer(&unattended_timer, jiffies + msecs_to_jiffies(PM_UNATTENDED_TIMEOUT));
queue_up_suspend_work();
} else {
pm_wakep_autosleep_enabled(false);
//Add a timer to trigger wakelock debug
pr_info([PM]unattended_timer: del_timer (late_resume)
);
del_timer(&unattended_timer);
}
mutex_unlock(&autosleep_lock);
return 0;
}
调用的流程:
1、 pm_wakep_autosleep_enabled 设置所注册的wake source 的auto sleep 全部设置成1,ws->autosleep_enabled = set;
2、调用queue_up_suspend_work(); 让设备进入suspend 状态。
static DECLARE_WORK(suspend_work, try_to_suspend);
调用try_to_suspend 函数。
pm_wakep_autosleep_enabled 这个函数还是很重要的,我们在下面的wake_lock 章节会详细讲解。
在底层里面的用autosleep_state 这个全部变量去保存目前的suspend 的状态。
if (autosleep_state >= PM_SUSPEND_MAX)
hibernate(); //进入冬眠模式
else
pm_suspend(autosleep_state); 进入suspend 的模式
我们主要看下pm_suspend 函数的实现:
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);
然后调用enter_state(state);函数进入所要进入的状态。
主要调用下面两个函数:
error = suspend_prepare
分配console ,发送PM_SUSPEND_PREPARE这个notify 事件。最后还有的是调用suspend_freeze_processes 冻结所有的进程。
error = suspend_devices_and_enter(state);
函数实现如下:
int suspend_devices_and_enter(suspend_state_t state)
{
int error;
bool wakeup = false;
if (!suspend_ops)
return -ENOSYS;
trace_machine_suspend(state);
if (suspend_ops->begin) {//判断suspend_ops 里面有没有begin 函数,关于suspend_ops 的赋值,我们会单独有一个标题讲解
error = suspend_ops->begin(state);
if (error)
goto Close;
}
//Add a timer to trigger wakelock debug
pr_info([PM]unattended_timer: del_timer
);
del_timer ( &unattended_timer );
suspend_console();//console 进行冬眠
suspend_test_start();
error = dpm_suspend_start(PMSG_SUSPEND);
if (error) {
printk(KERN_ERR PM: Some devic