设为首页 加入收藏

TOP

Power Management(一)
2014-11-23 21:37:42 来源: 作者: 【 】 浏览:65
Tags:Power Management
Power Management
迫切的想知道power management 的流程。
对整个流程稍微整理了下


1、autosleep 流程
上层操作底层的/sys/power/autosleep 这个接口进行操作底层。在main .c 里面会创建一个autosleep 接口,对应main.c 里面的store 函数。
所对应的source code 在:/kernel/kernel/main.c 里面

static ssize_t autosleep_store(struct kobject *kobj,
                   struct kobj_attribute *attr,
                   const char *buf, size_t n)
{
    suspend_state_t state = decode_state(buf, n);
    int error;


    if (state == PM_SUSPEND_ON
        && strcmp(buf, off) && strcmp(buf, off
))
        return -EINVAL;

    error = pm_autosleep_set_state(state);
    old_state=state;
    return error   error : n;
}



当底层接受到上层传递到的值进行一些列的操作,有很多的state 状态:
#define PM_SUSPEND_ON ((__force suspend_state_t) 0)
#define PM_SUSPEND_STANDBY ((__force suspend_state_t) 1)
#define PM_SUSPEND_MEM ((__force suspend_state_t) 3)
#define PM_SUSPEND_MAX ((__force suspend_state_t) 4)
当底层接受到上层的state 之后,主要是调用pm_autosleep_set_state 这个函数进行power management 的管理。
它的实现如下:
int pm_autosleep_set_state(suspend_state_t state)
{

#ifndef CONFIG_HIBERNATION
    if (state >= PM_SUSPEND_MAX)
        return -EINVAL;
#endif

    __pm_stay_awake(autosleep_ws);

    mutex_lock(&autosleep_lock);

    autosleep_state = state;

    __pm_relax(autosleep_ws);

    if (state > PM_SUSPEND_ON) {
        pm_wakep_autosleep_enabled(true);

        //Add a timer to trigger wakelock debug
        pr_info([PM]unattended_timer: mod_timer (auto_sleep)
);
        mod_timer(&unattended_timer, jiffies + msecs_to_jiffies(PM_UNATTENDED_TIMEOUT));

        queue_up_suspend_work();
    } else {
        pm_wakep_autosleep_enabled(false);
        //Add a timer to trigger wakelock debug
        pr_info([PM]unattended_timer: del_timer (late_resume)
);
        del_timer(&unattended_timer);
    }

    mutex_unlock(&autosleep_lock);
    return 0;
}


调用的流程:
1、 pm_wakep_autosleep_enabled 设置所注册的wake source 的auto sleep 全部设置成1,ws->autosleep_enabled = set;
2、调用queue_up_suspend_work(); 让设备进入suspend 状态。
static DECLARE_WORK(suspend_work, try_to_suspend);
调用try_to_suspend 函数。

pm_wakep_autosleep_enabled 这个函数还是很重要的,我们在下面的wake_lock 章节会详细讲解。


在底层里面的用autosleep_state 这个全部变量去保存目前的suspend 的状态。

if (autosleep_state >= PM_SUSPEND_MAX)
hibernate(); //进入冬眠模式
else
pm_suspend(autosleep_state); 进入suspend 的模式
我们主要看下pm_suspend 函数的实现:

int pm_suspend(suspend_state_t state)
{
    int error;

    if (state <= PM_SUSPEND_ON || state >= PM_SUSPEND_MAX)
        return -EINVAL;
    pm_suspend_marker(entry);
    error = enter_state(state);
    if (error) {
        suspend_stats.fail++;
        dpm_save_failed_errno(error);
    } else {
        suspend_stats.success++;
    }
    pm_suspend_marker(exit);
    return error;
}
EXPORT_SYMBOL(pm_suspend);


然后调用enter_state(state);函数进入所要进入的状态。

主要调用下面两个函数:
error = suspend_prepare
分配console ,发送PM_SUSPEND_PREPARE这个notify 事件。最后还有的是调用suspend_freeze_processes 冻结所有的进程。
error = suspend_devices_and_enter(state);
函数实现如下:

int suspend_devices_and_enter(suspend_state_t state)
{
    int error;
    bool wakeup = false;

    if (!suspend_ops)
        return -ENOSYS;

    trace_machine_suspend(state);
    if (suspend_ops->begin) {//判断suspend_ops 里面有没有begin 函数,关于suspend_ops 的赋值,我们会单独有一个标题讲解
        error = suspend_ops->begin(state);
        if (error)
            goto Close;
    }

    //Add a timer to trigger wakelock debug
    pr_info([PM]unattended_timer: del_timer
);
    del_timer ( &unattended_timer );

    suspend_console();//console 进行冬眠
    suspend_test_start();
    error = dpm_suspend_start(PMSG_SUSPEND);
    if (error) {
        printk(KERN_ERR PM: Some devic
首页 上一页 1 2 3 4 5 下一页 尾页 1/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C语言 十进制转换成二进制转换方.. 下一篇数组nice to see you again

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: