电源管理之睡眠和唤醒流程
这里没有大堆的文字说明,只是罗列了一下睡眠和唤醒的主要流程,具体细节还需要自己去分析。
关键的一点:
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); } }