您的位置:首页 > 其它

电源管理之睡眠和唤醒流程

2016-10-09 17:32 363 查看
这里没有大堆的文字说明,只是罗列了一下睡眠和唤醒的主要流程,具体细节还需要自己去分析。

关键的一点:

Android上层和底层间“通信”是通过它的虚拟文件系统中的属性,上层对该属性执行写操作,底层对应的调用该属性的store方法。

一、上层的一些流程

updatePowerStateLocked();
updateSuspendBlockerLocked();
setHalAutoSuspendModeLocked();
nativeSetAutoSuspend();
autosuspend_enable();
autosuspend_init();
autosuspend_ops->enable();
autosuspend_earlysuspend_enable();
#define EARLYSUSPEND_SYS_POWER_STATE "/sys/power/state"
static const char *pwr_state_mem = "mem";
sPowerStatefd = open(EARLYSUSPEND_SYS_POWER_STATE, O_RDWR);
write(sPowerStatefd, pwr_state_mem, strlen(pwr_state_mem));


二、底层函数执行流程

power_attr(state);            // /kernel/power/main.c
#ifdef CONFIG_MTK_LDVT                    //在现有的代码中,走的是下面的函数
state_store();{
decode_state();                //根据写入的字符串,转换得到状态
pm_suspend(state);{
enter_state(state);{
suspend_prepare(state);{    //这个不是我想要的重点,忽略它

}
suspend_devices_and_enter(state);{
suspend_console();            //挂起终端,非重点
dpm_suspend_start(PMSG_SUSPEND);{
dpm_prepare(state);{
while (!list_empty(&dpm_list)){        //如果 dpm_list 链表不为空
struct device *dev = to_device(dpm_list.next);        //根据链表节点获取对应的设备
device_prepare(dev, state);        //执行电源管理操作函数集中的prepare函数,具体执行的顺序见下面列表。
list_move_tail(&dev->power.entry, &dpm_prepared_list);    //把dev元素,移到dpm_prepared_list链表后面
}
}
dpm_suspend(state);    {
while (!list_empty(&dpm_prepared_list))    {    //遍历dpm_prepared_list链表
struct device *dev = to_device(dpm_prepared_list.prev);
device_suspend(dev);{    //分为同步和异步执行,此处分析同步执行
__device_suspend(dev, pm_transition, false);    //执行电源管理操作函数集中的suspend函数,具体执行的顺序见下面列表。
}
list_move(&dev->power.entry, &dpm_suspended_list);
}
}
}
suspend_enter(state, &wakeup);{
suspend_ops->prepare();
dpm_suspend_end(PMSG_SUSPEND);{
dpm_suspend_late(state);{
while (!list_empty(&dpm_suspended_list)){    //遍历链表dpm_suspended_list
struct device *dev = to_device(dpm_suspended_list.prev);
device_suspend_late(dev, state); //执行电源管理操作函数集中的suspend_late函数,具体执行顺序见下面说明。
list_move(&dev->power.entry, &dpm_late_early_list);
}
}
dpm_suspend_noirq(state);{
cpuidle_pause();
suspend_device_irqs();
while (!list_empty(&dpm_late_early_list)){
struct device *dev = to_device(dpm_late_early_list.prev);
device_suspend_noirq(dev, state);    //执行电源管理操作函数集中的suspend_noirq函数,具体执行顺序见下面说明。
list_move(&dev->power.entry, &dpm_noirq_list);
}
}
}
suspend_ops->prepare_late();
disable_nonboot_cpus();
arch_suspend_disable_irqs();
syscore_suspend();{
list_for_each_entry_reverse(ops, &syscore_ops_list, node){
ops->suspend();
}
}

pm_wakeup_pending();
suspend_ops->enter(state);

//后续环节即为唤醒流程
syscore_resume();
arch_suspend_enable_irqs();
enable_nonboot_cpus();
suspend_ops->wake();
dpm_resume_start(PMSG_RESUME);
suspend_ops->finish();
}

//睡眠被打断之后继续执行其后的唤醒流程
dpm_resume_end(PMSG_RESUME);
dpm_resume(state);
while (!list_empty(&dpm_suspended_list))    //遍历链表dpm_suspended_list
device_resume(dev, state, false);
pm_op(dev->driver->pm, state);    //可能有多种情形,视具体情况而定
ops->resume;
dpm_complete(state);
while (!list_empty(&dpm_prepared_list))
device_complete(dev, state);
dev->driver->pm->complete;    //可能有多种情形,视具体情况而定
resume_console();
}
}
}
}
#else
state_store();{
#ifdef CONFIG_EARLYSUSPEND    //现有的代码中,有该定义,所以没有使用enter_state函数
request_suspend_state(new_state);{                //Earlysuspend.c (kernel-3.10\kernel\power)
if (new_state != PM_SUSPEND_ON){                //该状态分支执行挂起操作,即suspend
queue_work(sys_sync_work_queue, &early_sys_sync_work);{        //挂起操作之前,先执行同步操作。
static DECLARE_WORK(early_sys_sync_work, early_sys_sync);
early_sys_sync(struct work_struct *work){
sys_sync();
}
}
queue_work(suspend_work_queue, &early_suspend_work);{
static DECLARE_WORK(early_suspend_work, early_suspend);
early_suspend(struct work_struct *work){
list_for_each_entry(pos, &early_suspend_handlers, link){
pos->suspend(pos);
}
}
}
}else if(new_state == PM_SUSPEND_ON){        //该状态分支执行恢复操作,即resume
queue_work(suspend_work_queue, &late_resume_work);{
static DECLARE_WORK(late_resume_work, late_resume);
late_resume(struct work_struct *work){
list_for_each_entry_reverse(pos, &early_suspend_handlers, link){
pos->resume(pos);
}
}
}
}
}
#else
enter_state(state);
#endif
}
#endif


三、涉及到的几个链表结构中成员的转移关系

从左到右为suspend过程,从右到左为resume过程
dpm_list dpm_prepared_list dpm_suspended_list dpm_late_early_list dpm_noirq_list

四、dpm_list的成员添加流程:

device_create();
device_create_vargs();
device_register(struct device *dev);
device_add(dev);
device_pm_add(dev);    //kernel-3.10\drivers\base\Core.c
list_add_tail(&dev->power.entry, &dpm_list);    //kernel-3.10\drivers\base\power\Main.c


只要调用其中的函数就可以了,没有必要说是必须调用那个函数;
只是列出了它的可能调用流程,明白那些操作可以添加dpm_list的成员。

五、suspend过程函数执行流程

prepare执行的先后顺序
if (dev->power.syscore)
return 0;
callback = dev->pm_domain->ops.prepare;
callback = dev->type->pm->prepare;
callback = dev->class->pm->prepare;
callback = dev->bus->pm->prepare;
callback = dev->driver->pm->prepare;
error = callback(dev);

suspend的执行顺序
if (dev->power.syscore)
goto Complete;
callback = pm_op(&dev->pm_domain->ops, state);
callback = pm_op(dev->type->pm, state);
callback = pm_op(dev->class->pm, state);
dev->class->suspend;
callback = pm_op(dev->bus->pm, state);
dev->bus->suspend;
callback = pm_op(dev->driver->pm, state);

suspend_late的执行顺序
if (dev->power.syscore)
return 0;
callback = pm_late_early_op(&dev->pm_domain->ops, state);
callback = pm_late_early_op(dev->type->pm, state);
callback = pm_late_early_op(dev->class->pm, state);
callback = pm_late_early_op(dev->bus->pm, state);
callback = pm_late_early_op(dev->driver->pm, state);

suspend_noirq的执行顺序
if (dev->power.syscore)
return 0;
callback = pm_noirq_op(&dev->pm_domain->ops, state);
callback = pm_noirq_op(dev->type->pm, state);
callback = pm_noirq_op(dev->class->pm, state);
callback = pm_noirq_op(dev->bus->pm, state);
callback = pm_noirq_op(dev->driver->pm, state);


六、resume过程函数执行流程

暂时未分析,后续补齐

七、部分结构对应的操作方法集

dev->pm_domain->ops         函数操作集合
dev->type->pm                      函数操作集合
dev->class->pm                    函数操作集合
dev->bus->pm                        函数操作集合
dev->driver->pm                    函数操作集合

struct dev_pm_ops {
int (*prepare)(struct device *dev);
void (*complete)(struct device *dev);
int (*suspend)(struct device *dev);
int (*resume)(struct device *dev);
int (*freeze)(struct device *dev);
int (*thaw)(struct device *dev);
int (*poweroff)(struct device *dev);
int (*restore)(struct device *dev);
int (*suspend_late)(struct device *dev);
int (*resume_early)(struct device *dev);
int (*freeze_late)(struct device *dev);
int (*thaw_early)(struct device *dev);
int (*poweroff_late)(struct device *dev);
int (*restore_early)(struct device *dev);
int (*suspend_noirq)(struct device *dev);
int (*resume_noirq)(struct device *dev);
int (*freeze_noirq)(struct device *dev);
int (*thaw_noirq)(struct device *dev);
int (*poweroff_noirq)(struct device *dev);
int (*restore_noirq)(struct device *dev);
int (*runtime_suspend)(struct device *dev);
int (*runtime_resume)(struct device *dev);
int (*runtime_idle)(struct device *dev);
};

dev->pm_domain 函数操作集合
无

dev->type        函数操作集合
int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
char *(*devnode)(struct device *dev, umode_t *mode, kuid_t *uid, kgid_t *gid);
void (*release)(struct device *dev);

dev->class    函数操作集合
int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
char *(*devnode)(struct device *dev, umode_t *mode);
void (*class_release)(struct class *class);
void (*dev_release)(struct device *dev);
int (*suspend)(struct device *dev, pm_message_t state);
int (*resume)(struct device *dev);

const void *(*namespace)(struct device *dev);

dev->bus        函数操作集合
int (*match)(struct device *dev, struct device_driver *drv);
int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
int (*probe)(struct device *dev);
int (*remove)(struct device *dev);
void (*shutdown)(struct device *dev);
int (*suspend)(struct device *dev, pm_message_t state);
int (*resume)(struct device *dev);

dev->driver 函数操作集合
int (*probe) (struct device *dev);
int (*remove) (struct device *dev);
void (*shutdown) (struct device *dev);
int (*suspend) (struct device *dev, pm_message_t state);
int (*resume) (struct device *dev);


八、MTK平台的register_early_suspend函数分析

struct early_suspend {
#ifdef CONFIG_HAS_EARLYSUSPEND
struct list_head link;
int level;
void (*suspend) (struct early_suspend *h);
void (*resume) (struct early_suspend *h);
#endif
};

register_early_suspend(struct early_suspend *handler)        //Earlysuspend.c (kernel-3.10\kernel\power)
list_for_each(pos, &early_suspend_handlers){
//根据handler->level的等级,在链表early_suspend_handlers中选择合适的插入位置。
}
list_add_tail(&handler->link, pos);
early_suspend_count++;

register_early_suspend函数的主要任务是把early_suspend结构体添加到early_suspend_handlers链表中。
现在存在的一个疑问是在什么时候调用链表中的相关函数。

static DECLARE_WORK(early_suspend_work, early_suspend);
static DECLARE_WORK(late_resume_work, late_resume);

static void early_suspend(struct work_struct *work){
list_for_each_entry(pos, &early_suspend_handlers, link){
pos->suspend(pos);
}
}

static void late_resume(struct work_struct *work){
list_for_each_entry_reverse(pos, &early_suspend_handlers, link){
pos->resume(pos);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: