linux驱动程序之电源管理之标准linux休眠和唤醒机制分析(二)
三、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休眠和唤醒机制分析(二)的更多相关文章
- linux驱动程序之电源管理之标准linux休眠与唤醒机制分析(一)
1. Based on linux2.6.32, only for mem(SDR) 2. 有兴趣请先参考阅读: 电源管理方案APM和ACPI比较.doc Linux系统的休眠与唤醒简介.doc 3 ...
- linux驱动程序之电源管理之新版linux系统设备架构中关于电源管理方式的变更
新版linux系统设备架构中关于电源管理方式的变更 based on linux-2.6.32 一.设备模型各数据结构中电源管理的部分 linux的设备模型通过诸多结构体来联合描述,如struct d ...
- 标准linu休眠和唤醒机制分析(四)【转】
转自:http://blog.csdn.net/lizhiguo0532/article/details/6453552 suspend第三.四.五阶段:platform.processor.core ...
- linux驱动程序之电源管理之linux的电源管理架构(3)
设备电源管理 Copyright (c) 2010 Rafael J. Wysocki<rjw@sisk.pl>, Novell Inc. Copyright (c) 2010 Alan ...
- linux驱动程序之电源管理 之linux休眠与唤醒(2)
在Linux中,休眠主要分三个主要的步骤:(1)冻结用户态进程和内核态任务:(2)调用注册的设备的suspend的回调函数:(3)按照注册顺序休眠核心设备和使CPU进入休眠态. 冻结进程是 ...
- linux驱动程序之电源管理之Run-time PM 详解(4)
Run-time PM. 每个device或者bus都会向run-time PM core注册3个callback struct dev_pm_ops { ... int (*runtime_su ...
- linux驱动程序之电源管理之regulator机制流程 (1)
电源管理芯片可以为多设备供电,且这些设备电压电流有所同.为这些设备提供的稳压器代码模型即为regulator. 下面通过下面三个过程分析regulartor供电机制: 1.分析regulator结构体 ...
- linux关闭ACPI电源管理模块
一.运行环境 # cat /etc/redhat-release CentOS release 6.2 (Final) # uname -a Linux web-server- -.el6.x86_6 ...
- linux电源管理系列(一)
本系列将逐步介绍linux电源管理相关的知识,涉及到常见电源管理机制.linux电源管理机制.linux驱动中有关电源管理的相关接口.内核文档中关于Linux电源管理架构文档的分析.以下将以此来介绍相 ...
随机推荐
- dataTable 禁止排序
$("#id").DataTable({ "ordering": false, // 禁止排序 });
- 一次Oracle数据迁移
目标数据库:Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 源数据库 : Oracle Database 11g Enterpri ...
- csv转json文件
今天因为需要帮一个同事的新闻内容录入为html, 每次手改不方便,所以就弄了个csv(excel)转json的c++程序,然后再利用ejs把它渲染成网页,打开渲染好的网页再保存(不能保存源文件,不然还 ...
- ASP.NET MVC Spring.NET 整合
请注明转载地址:http://www.cnblogs.com/arhat 在整合这三个技术之前,首先得说明一下整合的步骤,俗话说汗要一口一口吃,事要一件一件做.同理这个三个技术也是.那么在整合之前,需 ...
- Net中的AOP
.Net中的AOP系列之<单元测试切面> 返回<.Net中的AOP>系列学习总目录 本篇目录 使用NUnit编写测试 编写和运行NUnit测试 切面的测试策略 Castle ...
- <一> MVC - HtmlHelper
HtmlHelper类位于System.Web.Mvc.Html之中主要有七个静态类组成: FormExtensions - BeginForm, BeginRouteForm, EndForm In ...
- iOS崩溃日志分析-b
1名词解释 1.1. UUID 一个字符串,在iOS上每个可执行文件或库文件都包含至少一个UUID,目的是为了唯一识别这个文件. 1.2. dwarfdump 苹果提供的命令行工具,其中一些功能就是查 ...
- joda jar日期处理类的学习
转载:http://www.open-open.com/lib/view/open1348032952724.html 任何企业应用程序都需要处理时间问题.应用程序需要知道当前的时间点和下一个时间点, ...
- shell脚本中>/dev/null的含义
shell脚本中>/dev/null的含义 shell脚本中有段使用sqlplus的部分: sqlplus ${user_id} <<! >/dev/null spool sp ...
- BZOJ 3713: [PA2014]Iloczyn
Description 斐波那契数列的定义为:k=0或1时,F[k]=k:k>1时,F[k]=F[k-1]+F[k-2].数列的开头几项为0,1,1,2,3,5,8,13,21,34,55,-你 ...