三、pm_test属性文件读写

int pm_test_level = TEST_NONE;

static const char * const  pm_tests[__TEST_AFTER_LAST] = {

[TEST_NONE] = "none",

[TEST_CORE] = "core",

[TEST_CPUS] = "processors",

[TEST_PLATFORM] = "platform",

[TEST_DEVICES] = "devices",

[TEST_FREEZER] = "freezer",

};

// core >> processors >> platform >> devices >> freezer, 控制范围示意

cat pm_test的时候最终会调用函数pm_test_show(),在终端上打印出上面数组中的字符串,当前的模式用[]表示出来。

echo devices > pm_test的时候会最终调用到函数pm_test_store()中去,该函数中设置全局变量pm_test_level的值,可以是0-5,分别代表上none ~ freezer。该全局变量会在后面的suspend和resume中被引用到。

memchr函数说明:

原型:extern void *memchr(void *buf, char ch, unsigned int count);

用法:#include <string.h>   

功能:从buf所指内存区域的前count个字节查找字符ch。   

说明:当第一次遇到字符ch时停止查找。如果成功,返回指向字符ch的指针;否则返回NULL。

四、state属性文件

power_attr(state)宏定义了一个struct kobj_attribute结构体state_attr:

static struct kobj_attribute state_attr = {

.attr = {

.name = __stringify(state),

.mode = 0644,

},

.show     = state_show,

.store      = state_store,

}

kobj_attribute结构体封装了struct attribute结构体,新建属性文件是依据struct attribute结构体。最终通过函数kobj_attr_show和kobj_attr_store回调到实际的show和store函数(kobject.c)。

state_show()函数主要是显示当前系统支持哪几种省电模式。

static ssize_t state_show(struct kobject *kobj,  struct kobj_attribute *attr,  char *buf)

{

char *s = buf;

#ifdef CONFIG_SUSPEND  //def

int i;

for (i = 0; i < PM_SUSPEND_MAX; i++) {

if (pm_states[i] && valid_state(i))

s += sprintf(s,"%s ", pm_states[i]);

}

#endif

#ifdef CONFIG_HIBERNATION       // undef, don't support STD mode

s += sprintf(s, "%s/n", "disk");

#else

if (s != buf)

/* convert the last space to a newline */

*(s-1) = '/n';

#endif

return (s - buf);

}

@ kernel/include/linux/suspend.h

#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_DISK           ((__force suspend_state_t) 4)

#define PM_SUSPEND_MAX           ((__force suspend_state_t) 5)

@ kernel/kernel/power/suspend.c

const char *const pm_states[PM_SUSPEND_MAX] = {

#ifdef CONFIG_EARLYSUSPEND    // android修改了标准linux的休眠唤醒机制,增加了eraly suspend和late resume机制,如果是android内核,则这个宏是需要定义的。

[PM_SUSPEND_ON]          = "on",

#endif

[PM_SUSPEND_STANDBY]     = "standby",

[PM_SUSPEND_MEM]      = "mem",

};

该函数中值得注意的地方应该是valid_state(i),这个函数是用户配置的支持省电模式的验证函数,如果没有这个验证过程,cat时候打印出来的模式则是on standby mem,给上层用户的使用造成困扰。

那这个valid_state()函数在哪里定义的呢?一般定义于文件kernel/kernel/power/suspend.c

static struct platform_suspend_ops   *suspend_ops;

void suspend_set_ops(struct platform_suspend_ops *ops) // 该函数调用见后面

{

mutex_lock(&pm_mutex);

suspend_ops = ops;

mutex_unlock(&pm_mutex);

}

bool valid_state(suspend_state_t state)

{

return suspend_ops && suspend_ops->valid && suspend_ops->valid(state);

}

而实际平台的platform_suspend_ops结构体一般都是在文件arch/arm/mach-xxxx/pm.c中进行定义,对于mtk的平台是文件mtkpm.c,如下:

@ kernel/include/linux/suspend.h

struct platform_suspend_ops {

int (*valid)(suspend_state_t state);

int (*begin)(suspend_state_t state);

int (*prepare)(void);

int (*prepare_late)(void);

int (*enter)(suspend_state_t state);

void (*wake)(void);

void (*finish)(void);

void (*end)(void);

void (*recover)(void);

};

经过后面的代码分析,得出了如下结论:

休眠唤醒过程依次会执行的函数是:begin,prepare,prepare_late,enter,wake, finish, end。同颜色的函数执行了恰好相反的工作。休眠的时候代码执行是停留在函数enter中,wake之后也是从suspend的时候停留的地方继续运行。

至于recover函数貌似只有在pm_test处于devices的模式下,才会被调用到。

@ kernel/arch/arm/mach-mt6516/mtkpm.c

static struct platform_suspend_ops mtk_pm_ops = {

.valid      = mtk_pm_state_valid,

.begin            = mtk_pm_begin,

.prepare  = mtk_pm_prepare,

.enter            = mtk_pm_enter,

.finish           = mtk_pm_finish,

.end        = mtk_pm_end,

};

static int mtk_pm_state_valid(suspend_state_t pm_state)

{

return pm_state == PM_SUSPEND_MEM ;

}

void mtk_pm_init(void)

{

_Chip_PM_init();

/* Register and set suspend operation */

suspend_set_ops(&mtk_pm_ops);

}

而函数mtk_pm_init()是在函数mt6516_init_irq()中调用。可以看出该平台只支持mem的省电模式。

state_store()函数:

static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,

const char *buf, size_t n)

{

#ifdef CONFIG_SUSPEND // set

#ifdef CONFIG_EARLYSUSPEND    //对标准linux而言,这个宏不存在

suspend_state_t state = PM_SUSPEND_ON;

#else

suspend_state_t state = PM_SUSPEND_STANDBY;

#endif

const char * const *s;

#endif

char *p;

int len;

int error = -EINVAL;

p = memchr(buf, '/n', n);

len = p ? p - buf : n;

/* First, check if we are requested to hibernate */

if (len == 4 && !strncmp(buf, "disk", len)) {

error = hibernate();       // 如果值是disk,那么进入STD模式,该模式暂不讨论

goto Exit;

}

#ifdef CONFIG_SUSPEND        // def

for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) {

if (*s && len == strlen(*s) && !strncmp(buf, *s, len))

break;

}

if (state < PM_SUSPEND_MAX && *s)

#ifdef CONFIG_EARLYSUSPEND

// android的linux内核会定义该宏,首先进入eraly suspend模式

if (state == PM_SUSPEND_ON || valid_state(state)) {

error = 0;

request_suspend_state(state);

}

#else       // 标准linux内核直接enter_state()函数

error = enter_state(state);    // kernel/kernel/power/suspend.c

#endif

#endif

Exit:

return error ? error : n;

}

linux驱动程序之电源管理之标准linux休眠和唤醒机制分析(二)的更多相关文章

  1. linux驱动程序之电源管理之标准linux休眠与唤醒机制分析(一)

    1. Based on linux2.6.32,  only for mem(SDR) 2. 有兴趣请先参考阅读: 电源管理方案APM和ACPI比较.doc Linux系统的休眠与唤醒简介.doc 3 ...

  2. linux驱动程序之电源管理之新版linux系统设备架构中关于电源管理方式的变更

    新版linux系统设备架构中关于电源管理方式的变更 based on linux-2.6.32 一.设备模型各数据结构中电源管理的部分 linux的设备模型通过诸多结构体来联合描述,如struct d ...

  3. 标准linu休眠和唤醒机制分析(四)【转】

    转自:http://blog.csdn.net/lizhiguo0532/article/details/6453552 suspend第三.四.五阶段:platform.processor.core ...

  4. linux驱动程序之电源管理之linux的电源管理架构(3)

    设备电源管理 Copyright (c) 2010 Rafael J. Wysocki<rjw@sisk.pl>, Novell Inc. Copyright (c) 2010 Alan ...

  5. linux驱动程序之电源管理 之linux休眠与唤醒(2)

    在Linux中,休眠主要分三个主要的步骤:(1)冻结用户态进程和内核态任务:(2)调用注册的设备的suspend的回调函数:(3)按照注册顺序休眠核心设备和使CPU进入休眠态.       冻结进程是 ...

  6. linux驱动程序之电源管理之Run-time PM 详解(4)

    Run-time PM. 每个device或者bus都会向run-time PM core注册3个callback   struct dev_pm_ops { ... int (*runtime_su ...

  7. linux驱动程序之电源管理之regulator机制流程 (1)

    电源管理芯片可以为多设备供电,且这些设备电压电流有所同.为这些设备提供的稳压器代码模型即为regulator. 下面通过下面三个过程分析regulartor供电机制: 1.分析regulator结构体 ...

  8. linux关闭ACPI电源管理模块

    一.运行环境 # cat /etc/redhat-release CentOS release 6.2 (Final) # uname -a Linux web-server- -.el6.x86_6 ...

  9. linux电源管理系列(一)

    本系列将逐步介绍linux电源管理相关的知识,涉及到常见电源管理机制.linux电源管理机制.linux驱动中有关电源管理的相关接口.内核文档中关于Linux电源管理架构文档的分析.以下将以此来介绍相 ...

随机推荐

  1. 三个PHP常用代码样例

    作为一个正常的程序员,会好几种语言是十分正常的,相信大部分程序员也都会编写几句PHP程序,如果是WEB程序员,PHP一定是必备的.尽管PHP经常被人诟病,被人贬低,被人当玩笑开,事实证明,PHP是全世 ...

  2. python上下文管理器及with语句

    with语句支持在一个叫上下文管理器的对象的控制下执行一系列语句,语法大概如下: with context as var: statements 其中的context必须是个上下文管理器,它实现了两个 ...

  3. 不相交集合ADT

    不相交集合数据结构保持一组不相交的动态集合S={S1,S2,...,SK},每个集合通过一个代表来识别,代表即集合中的某个成员. 如果x表示一个对象,不相交集合支持以下操作: MAKE-SET(x): ...

  4. Javascript的websocket的使用方法

    javascript websocket接口 web实现客户端和服务端双向发送消息的方法有: 轮询,客户端定期向服务端请求: 长轮询,客户端定期向服务端请求,服务端只有有信息发送的时候才返回respo ...

  5. 七,WPF的元素绑定

    数据绑定是一种关系,该关系告诉WPF从一个源对象提取一些信息,并使用这些信息设置目标对象的属性,目标属性总是依赖项属性,然而,源对象可以是任何内容. 源对象是WPF元素并且源属性是依赖项属性的数据绑定 ...

  6. JAVA技术体系发展路线

    JAVA技术体系 1.1 Java程序员 ·高级特性 反射.泛型.注释符.自动装箱和拆箱.枚举类.可变参数.可变返回类型.增强循环.静态导入 ·核心编程 IO.多线程.实体类.集合类.正则表达式.XM ...

  7. MVC-内容详情页显示内容

    @model InfoDataProvider.DataModel.FAQ_ContentUser 内容Content字段:如果里面有html标签. @Html.DisplayFor(p => ...

  8. BigDecimal除法

    public class TestDemo { public static void main(String[] args) { BigDecimal dataValue = new BigDecim ...

  9. Java编程思想(1)

    0:什么是JavaEE Java技术是个平台,在这个平台上跳舞 1:开发环境的搭建 jdk1.7.* JAVA_HOME  jdk的安装路径 如:C:\Java\jdk1.7.0_72 PATH:%J ...

  10. hdu 4815 Little Tiger vs. Deep Monkey

    概率dp,有点像背包的做法: dp[i][j]代表前i个数组成的j数的概率为多少 #include<cstdio> #include<cstring> #define maxn ...