linux休眠唤醒流程

休眠过程

系统休眠命令:echo mem > sys/power/state cat此节点获取休眠方式

state节点写入信息流程

state_store(kernel-4.19\kernel\power\main.c)

        pm_suspend(kernel-4.19\kernel\power\suspend.c)

                enter_state(kernel-4.19\kernel\power\suspend.c)

                        suspend_prepare(kernel-4.19\kernel\power\suspend.c)

                                __pm_notifier_call_chain(kernel-4.19\kernel\power\suspend.c) //通知所有关心休眠的驱动

                                suspend_freeze_processes(kernel-4.19\kernel\power\suspend.c) //冻结所有应用程序

                suspend_devices_and_enter(kernel-4.19\kernel\power\suspend.c)//让设备进入休眠状态

                        platform_suspend_begin

                                suspend_ops->begin //如果平台相关的代码有相关的begin函数就调用此函数,注1

                                        suspend_set_ops(kernel-4.19\kernel\power\suspend.c)

                suspend_console(kernel-4.19\kernel\power\suspend.c)//控制台进行休眠

                dpm_suspend_start(kernel-4.19\drivers\base\power\main.c)

                        dpm_prepare(kernel-4.19\drivers\base\power\main.c) //让各类设备休眠

                                遍历整个链表dpm_list,调用每个设备的device_prepare函数,执行完后将列表成员放入dpm_prepared_list链表中

                                对于该设备他会调用dev->pm_domain->ops.prepare或dev->type->pm->prepare或dev->class->pm->prepare或dev->bus->pm->prepare

                                遍历整个dpm_prepared_list链表,每个设备都调用device_suspend函数,执行完成将链表成员放入dpm_suspended_list链表中

                                        __device_suspend

                                                对于该设备调用dev->pm_domain->ops.suspend或dev->type->pm.suspend或dev->class->pm.suspend或dev->bus->pm.suspend

suspend_enter

        platform_suspend_prepare

                suspend_ops->prepare()及slp_suspend_ops_prepare函数

        dpm_suspend_late(kernel-4.19\drivers\base\power\main.c)

                遍历整个链表dpm_suspended_list,调用每个设备device_suspend_late函数

dpm_subsys_suspend_late_cb

                        对于该设备调用dev->pm_domain->ops.suspend_late或dev->type->pm.suspend_late或dev->class->pm.suspend_late或dev->bus->pm.suspend_late

        platform_suspend_prepare_late

                s2idle_ops->prepare //根据平台是否注册,注册则进行调用

        dpm_suspend_noirq(kernel-4.19\drivers\base\power\main.c) //关闭IRQ

                dpm_noirq_begin

                        cpuidle_pause //多核处理器系统中暂停CPU,进入低功耗状态

                        device_wakeup_arm_wake_irqs //设备唤醒源(wakeup source)启用唤醒中断,唤醒源方可唤醒cpu

                        suspend_device_irqs//暂停系统中所有设备的中断请求(IRQ)。

                 dpm_noirq_suspend_devices

                        遍历dpm_late_early_list数组,调用每一个设备device_suspend_noirq

                                __device_suspend_noirq

                                        dpm_subsys_suspend_noirq_cb

                                                对于该设备调用dev->pm_domain->ops.suspend_noirq或dev->type->pm.suspend_noirq或dev->class->pm.suspend_noirq或dev->bus->pm.suspend_noirq

                platform_suspend_prepare_noirq //预准备关闭平台IRP

                disable_nonboot_cpus //在系统休眠过程中关闭非引导CPU(Non-Boot CPUs),以避免在休眠期间产生不必要的功耗。注2

                arch_suspend_disable_irqs //关闭本地中断

                syscore_suspend //系统核心休眠

                suspend_ops->enter //调用到平台注册的enter函数(slp_suspend_ops_enter),进行真正的休眠(kernel-4.19\drivers\misc\mediatek\base\power\spm_v4\mtk_sleep.c),slp_suspend_ops_enter函数会在休眠前记录唤醒时的返回函数地址

@注1:

suspend_ops函数的赋值

        mt_spm_init(kernel-4.19\drivers\misc\mediatek\base\power\spm_v4\mtk_spm_init.c)

                slp_module_init(kernel-4.19\drivers\misc\mediatek\base\power\spm_v4\mtk_spm_init.c)

                        suspend_set_ops(kernel-4.19\kernel\power\suspend.c) //对suspend_ops进行赋值

static const struct platform_suspend_ops slp_suspend_ops = {
    .valid = slp_suspend_ops_valid,
    .begin = slp_suspend_ops_begin,
    .prepare = slp_suspend_ops_prepare,
    .enter = slp_suspend_ops_enter,
    .finish = slp_suspend_ops_finish,
    .end = slp_suspend_ops_end,
};

@注2:

        在多核处理器系统中,CPU分为引导CPU(Boot CPU)和非引导CPU(Non-Boot CPU)。引导CPU通常是第一个启动并负责初始化其他CPU的处理器。在系统休眠(suspend)过程中,为了节省能源,需要关闭这些非引导CPU。disable_nonboot_cpus函数通过调用freeze_secondary_cpus实现这一目的。该函数会遍历所有在线的CPU,跳过主CPU,并对每个非引导CPU执行_cpu_down操作,将其状态设置为离线(CPUHP_OFFLINE),从而确保它们在休眠期间不会消耗电力。

唤醒过程

        按键导致uboot运行,会继续运行suspend_enter函数(kernel-4.19\kernel\power\suspend.c)中syscore_resume函数,依次调用arch_suspend_enable_irqs,platform_resume_noirq,dpm_resume_noirq,platform_resume_early,dpm_resume_early,platform_resume_finish,唤醒的过程是休眠的反向的。

总结:PM Core会依次调用“prepare—>suspend—>suspend_late—>suspend_noirq-------wakeup--------->resume_noirq—>resume_early—>resume-->complete”

重要结构体

include/linux/pm.h
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);
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值