linux2.6.32内核Suspend流程

    技术2022-06-23  51

     

    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_suspendsuspend处理

      queue_work(suspend_work_queue, &early_suspend_work);

      //early_suspend_work-> late_resumeresume处理,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()调用intcsysdevsuspend函数,恢复desc->status |= IRQ_WAKEUP标记的中断。

    /*

    *@kernel/power/suspend.c

    */

    static int suspend_enter(suspend_state_t state)

    {

    dpm_suspend_noirq();// 关掉所有的中断

    {

           suspend_device_irqs();

    }

    /*

    *sys_devicesuspend回调函数中唤醒系统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;

           }

    }


    最新回复(0)