linux2.6.32内核Suspend流程

本文详细解析了Linux系统中Suspend流程,从Suspend锁流程到Suspend & Resume流程,包括main.c(kernel/power)文件中state_store函数的作用,以及如何通过上层属性节点命令触发系统进入休眠状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文地址:http://blog.youkuaiyun.com/coolraining/article/details/6677888

Suspend流程

参考linux2.6.32

Suspend锁流程

Suspend&resume流程

具体看main.c(kernel/power);上层通过属性节点写命令,最终会调到此文件中的state_store函数。

state_store()
{
   request_suspend_state();
}

request_suspend_state()@ kernel/power/ earlysuspend.c
{
  //early_suspend_work-> early_suspend,suspend处理
  queue_work(suspend_work_queue, &early_suspend_work);
  //early_suspend_work-> late_resume,resume处理,early suspend的模块resume
  queue_work(suspend_work_queue, &late_resume_work);
}

static void early_suspend(struct work_struct *work) @
{
        //处理earlysuspend,即一级休眠
    list_for_each_entry(pos, &early_suspend_handlers, link) {
        if (pos->suspend != NULL)
               pos->suspend(pos);
       }
        // 系统suspend
    wake_unlock(&main_wake_lock);
}

void wake_unlock(struct wake_lock *lock)@wakelock.c

{
        // suspend_work-> suspend()
        queue_work(suspend_work_queue, &suspend_work);
}

suspend()@wakelock.c
{
        //判断系统suspend有没有被锁,如果被锁,则中断二级休眠处理
       if (has_wake_lock(WAKE_LOCK_SUSPEND)) {
               return;
        }
        // suspend系统
        pm_suspend();
}

pm_suspend()@kernel/power/suspend.c
{
    enter_state();
}

int enter_state(suspend_state_t state)
{
    error = suspend_devices_and_enter(state);
}

suspend_devices_and_enter()
{
    error = dpm_suspend_start(PMSG_SUSPEND);//devices suspend
    {
        error = dpm_suspend(state);
    }
 suspend_enter();// 系统相关suspend
}

static int suspend_enter(suspend_state_t state)
{
    //disable all irq
    error = dpm_suspend_noirq(PMSG_SUSPEND);
    // system dev suspend
    error = sysdev_suspend(PMSG_SUSPEND);
}
注意:    evdev.c中的evdev_event()->evdev_pass_event ()函数会调用wake_lock_timeout()。功能还不知道

 

设备处理

int device_add(struct device *dev) ()@drivers/base/core.c
{
    device_pm_add(dev);@drivers/base/power/main.c
}


中断处理

原理

系统通过enable_irq_wake()标记中断在系统suspend时不disable,没有标记的irq在系统suspend时会被disable。

static inline int enable_irq_wake(unsigned int irq)
{
       return set_irq_wake(irq, 1);
}

int set_irq_wake(unsigned int irq, unsigned int on)
{
       if (on) {
              desc->status |= IRQ_WAKEUP;// 系统suspend是该中断不会被disable
       }
}


实现过程

系统suspend时,先通过dpm_suspend_noirq()disable所有的中断,然后再sysdev_suspend()调用intc的sysdev的suspend函数,恢复desc->status |= IRQ_WAKEUP标记的中断。

/*

*@kernel/power/suspend.c

*/

static int suspend_enter(suspend_state_t state)
{
    dpm_suspend_noirq();// 关掉所有的中断
    {
       suspend_device_irqs();
    }

/*

*在sys_device的suspend回调函数中唤醒系统suspend时需要保持有效的中断

*rk的架构参考arch/arm/mach-rk2818/gpio.c的

*struct sysdev_class rk2818_gpio_sysclass.suspend= rk2818_gpio_suspend();但是该架构

*的实现函数rk2818_gpio_suspend()实现的不太标准。标准实现见下面的intc_suspend()

*/
    sysdev_suspend();
    dpm_resume_noirq();//恢复所有被disable的中断
}

其他参考模式

/*
*drivers/sh/intc.c
* intc_sysdev_class. suspend = intc_suspend;@ drivers/sh/intc.c
*/

intc_suspend()
{
       switch (state.event) {
              case PM_EVENT_SUSPEND:
        //将通过enable_irq_wake()函数设置的irq还原为enable状态
        for_each_irq_desc(irq, desc) {
               if ((desc->status & IRQ_WAKEUP) && (desc->chip == &d->chip))
                      intc_enable(irq);
               }
        break;
       }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值