电源管理休眠流程梳理( 三 )


是何方神圣呢?
我们可以找到他的赋值
void suspend_set_ops(const struct platform_suspend_ops *ops){suspend_state_t i;int j = 0;lock_system_sleep();suspend_ops = ops; //给suspend_ops赋值for (i = PM_SUSPEND_MEM; i >= PM_SUSPEND_STANDBY; i--)if (valid_state(i)) {pm_states[i] = pm_labels[j++];} else if (!relative_states) {pm_states[i] = NULL;j++;}pm_states[PM_SUSPEND_FREEZE] = pm_labels[j];unlock_system_sleep();}
的最终目的,是让系统进入可恢复的挂起状态,而该功能必须有平台相关代码的参与才能完成,因此内核PM Core就提供了一系列的回调函数(封装在中),让平台代码(如arch/arm/mach-xxx/pm.c)实现,然后由PM Core在合适的时机调用 。这些回调函数包含一个valid函数,就是用来告知PM Core,支持哪些state 。
例如:
在arch\arm\plat-\pm.c
函数中
(&);
= ops
例如:
= {
. = ,
. = ,
.enter = ,
. = ,
};
以上都是前的准备工作,此时,调用接口,使系统进入指定的电源状态 。该接口的内容如下:
//位于kernel\power\suspend.cstatic int suspend_enter(suspend_state_t state, bool *wakeup){int error;//调用suspend_ops的prepare回调(有的话),通知平台代码,以便让其在即将进行状态切换之时,再做一些处理(需要的话) 。该回调可能失败(平台代码出现意外),失败的话,需要跳至Platform_finish处,调用suspend_ops的finish回调,执行恢复操作 。error = platform_suspend_prepare(state);if (error)goto Platform_finish;/*dpm_suspend_late(state); (drivers/base/power/main.c) 将上述中休眠后的设备加到dpm_suspended_list链表中,对于dpm_suspended_list链表中的每一个设备,都调用device_suspend_late(dev, state),做休眠后的清理 。对于该设备,调用它的dev->pm_domain->ops->suspend_late或dev->type->pm->suspend_late或dev->class->pm->suspend_late或dev->bus->pm->suspend_late或dev->driver->pm->suspend_late*/error = dpm_suspend_late(PMSG_SUSPEND);if (error) {printk(KERN_ERR "PM: late suspend of devices failed\n");goto Platform_finish;}//调用suspend_ops的prepare_late回调(有的话),通知平台代码,以便让其在最后关头,再做一些处理(需要的话) 。该回调可能失败(平台代码出现意外),失败的话,需要跳至Platform_wake处,调用suspend_ops的wake回调,执行device的resume、调用suspend_ops的finish回调,执行恢复操作 。error = platform_suspend_prepare_late(state);if (error)goto Devices_early_resume;error = dpm_suspend_noirq(PMSG_SUSPEND);if (error) {printk(KERN_ERR "PM: noirq suspend of devices failed\n");goto Platform_early_resume;}error = platform_suspend_prepare_noirq(state);if (error)goto Platform_wake;if (suspend_test(TEST_PLATFORM))goto Platform_wake;/** PM_SUSPEND_FREEZE equals* frozen processes + suspended devices + idle processors.* Thus we should invoke freeze_enter() soon after* all the devices are suspended.*/if (state == PM_SUSPEND_FREEZE) {trace_suspend_resume(TPS("machine_suspend"), state, true);freeze_enter();trace_suspend_resume(TPS("machine_suspend"), state, false);goto Platform_wake;}//调用disable_nonboot_cpus,禁止所有的非boot cpu 。也会失败,执行恢复操作即可 。error = disable_nonboot_cpus();if (error || suspend_test(TEST_CPUS))goto Enable_cpus;//调用arch_suspend_disable_irqs,关全局中断 。如果无法关闭,则为bug 。arch_suspend_disable_irqs();BUG_ON(!irqs_disabled());//关闭核心模块error = syscore_suspend();if (!error) {*wakeup = pm_wakeup_pending();if (!(suspend_test(TEST_CORE) || *wakeup)) {trace_suspend_resume(TPS("machine_suspend"),state, true);//调用suspend_ops的enter回调,进行状态切换 。这时,系统应该已经suspend了.. 。这里会调用平台的enter接口,里面会//1.配置唤醒中断 2.设置TLB 3.自刷新ram 4.设置CLKCON的SLEEP 5.设置寄存器返回值等error = suspend_ops->enter(state);trace_suspend_resume(TPS("machine_suspend"),state, false);events_check_enabled = false;}syscore_resume();//这里开始唤醒}arch_suspend_enable_irqs();//开中断BUG_ON(irqs_disabled());Enable_cpus:enable_nonboot_cpus();//唤醒后开nonboot cpuPlatform_wake://suspend_ops->wakeplatform_resume_noirq(state);/*对于dpm_noirq_list链表中的每一个设备,调用device_resume_noirq(dev, state);对于该设备,调用它的dev->pm_domain->ops->resume_noirq或dev->type->pm->resume_noirq或dev->class->pm->resume_noirq或dev->bus->pm->resume_noirq或dev->driver->pm->resume_noirq*/dpm_resume_noirq(PMSG_RESUME);Platform_early_resume:platform_resume_early(state);Devices_early_resume:/*对于dpm_late_early_list链表中的每一个设备,调用device_resume_early(dev, state);对于该设备,调用它的dev->pm_domain->ops->resume_early或dev->type->pm->resume_early或dev->class->pm->resume_early或dev->bus->pm->resume_early或dev->driver->pm->resume_early */dpm_resume_early(PMSG_RESUME);Platform_finish:platform_resume_finish(state);return error;}