Linux的电源管理架构精品版Word格式.docx
《Linux的电源管理架构精品版Word格式.docx》由会员分享,可在线阅读,更多相关《Linux的电源管理架构精品版Word格式.docx(11页珍藏版)》请在冰豆网上搜索。
2.Runtime电源管理模型:
这种模型允许设备在系统运行阶段进入低功耗状态,原则上,他可以独立于其他的电源管理活动。
不过,通常设备之间不能单独进行控制(例如,父设备不能进入suspend,除非他的所有子设备已经进入suspend状态)。
此外,依据不同的总线类型,可能必须做出一些特别的操作来达到目的。
如果设备在系统运行阶段进入了低功耗状态,在系统级别的电源状态迁移时(suspend或hibernation)就必须做出特别的处理。
正因为这个原因,不仅仅设备驱动程序本身,相应的子系统(bustype,devicetype,deviceclass)驱动程序和电源管理核心也会被卷入到rumtime电源管理的工作中来。
比如当系统睡眠时,以上的各模块必须互相合作来实现各种多样的suspend和resume方法,以便让硬件进入低功耗状态,唤醒后继续提供服务而不丢失数据。
对于低功耗状态的定义,我们没有太多可以说的,因为他们通常特定于系统,甚至特定于某个设备。
如果在系统运行状态,足够多的设备进入了低功耗状态,这时的效果其实和进入了系统级别的低功耗状态非常相像。
这样一些驱动程序可以利用rumtime电源管理让系统进入一种类似深度省电的状态。
大多数进入suspend状态的设备会停止所有的I/O操作:
不会有DMA或者IRQ请求(需要唤醒系统的除外),不会有数据的读写,不再接受上层驱动的请求。
这对于不同的总线和平台会有不同的要求。
关于硬件唤醒事件的一些例子:
由RTC发起的闹钟,网络数据包的到达,键盘或者鼠标的活动,媒体的插入或移除(PCMCIA,MMC/SD,USB,等等)。
进入系统睡眠状态的接口
===================================================
内核为各个子系统(bustype,devicetype,deviceclass)和驱动程序提供了相应的编程接口,以便它们参与它们所关心的设备的电源管理。
这些接口覆盖了系统级别的睡眠和runtime级别的管理。
设备电源管理操作
子系统和驱动程序的设备电源管理操作,都定义在dev_pm_ops结构中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
structdev_pm_ops{
int(*prepare)(structdevice*dev);
void(*complete)(structdevice*dev);
int(*suspend)(structdevice*dev);
int(*resume)(structdevice*dev);
int(*freeze)(structdevice*dev);
int(*thaw)(structdevice*dev);
int(*poweroff)(structdevice*dev);
int(*restore)(structdevice*dev);
int(*suspend_noirq)(structdevice*dev);
int(*resume_noirq)(structdevice*dev);
int(*freeze_noirq)(structdevice*dev);
int(*thaw_noirq)(structdevice*dev);
int(*poweroff_noirq)(structdevice*dev);
int(*restore_noirq)(structdevice*dev);
int(*runtime_suspend)(structdevice*dev);
int(*runtime_resume)(structdevice*dev);
int(*runtime_idle)(structdevice*dev);
};
这个结构在include/linux/pm.h中定义,它们的作用将会在接下来进行描述。
现在,我们只要记住,最后三个方法是专门用于rumtimepm的,其他的则用于系统级别的电源状态迁移。
某些子系统中,依然存在所谓“过时的”或“传统的”电源管理操作接口,这种方式不会使用到dev_pm_ops结构,而且只适用于系统级别的电源管理方法,这边文章里将不会对它进行说明,如果要了解的话请直接查看内核的源代码。
子系统级别(Subsystem-Level)方法
————————————————
设备进入suspend和resume的关键方法在bus_type结构、device_type结构和class结构的pm成员中,他是一个dev_pm_ops结构的指针。
多数情况下,这些都是那些具体总线的体系结构(例如PCI或USB或某个设备类别和设备类)的维护者们来关注的部分。
总线驱动会适当地实现这些方法以供硬件和驱动程序使用它们;
因为PCI和USB有不同的工作方式。
只有少数人会编写subsystem-level的驱动程序;
大多数的设备驱动程序是建立在各种特定总线架构的代码之上。
有关这些调用,稍后会进行更详尽的描述;
它们将会顺着父子形式的设备模型树,一个设备一个设备地被调用。
/sys/devices/…/power/wakeupfiles
————————————————-
设备模型中的所有设备都有两个标志来控制唤醒事件(可使得设备或系统退出低功耗状态)。
设两个标志位由总线或者设备驱动用device_set_wakeup_capable()和device_set_wakeup_enable()来初始化,它们在include/linux/pm_wakeup.h中定义。
“can_wakeup”标志表示设备(或驱动)物理上支持唤醒事件,device_set_wakeup_capable()函数会影响该标志。
”should_wakeup”标志控制设备是否应该尝试启用他的唤醒机制。
device_set_wakeup_enable()会影响该标志。
大部分的驱动程序不会主动修改它们的值。
大多数设备的should_wakeup的初始值都被设为false,也有例外,比如电源键、键盘和由ethtool设置了wake-on-LAN功能的网卡。
设备是否有能力发出唤醒事件是一个硬件的问题,内核只是负责持续地跟踪这些事件的发生。
另外一方面,一个有唤醒能力的设备是否应该发起唤醒事件则是一个策略问题,它是由用户空间通过sysfs的属性文件(power/wakeup)进行管理的。
用户空间可以写入”enabled”,或”disabled”来设置或清除shoule_wakeup标志,相应地,读取该文件时,如果can_wakeup标志是true则返回对应的字符串,如果can_wakeup是false,则返回一个空字符串,以此来表明设备不支持唤醒事件。
(需要注意的是,尽管返回空字符串,该文件的写入依然会影响should_wakeup标志)
只有当这两个标志都为true时,device_may_wakeup()函数才会返回true。
当系统迁移到睡眠状态时,驱动程序应该在让设备进入低功耗状态前通过这一函数检查,确定是否启用唤醒机制。
不过,在rumtime电源管理模式下,不管设备和驱动程序是否都支持,也不管should_wakeup标志是否设置,唤醒事件都会被使能。
/sys/devices/…/power/controlfiles
设备模型中的每个设备都有一个标志位来控制它是否属于runtime电源管理模式。
这个叫runtime_auto的标志由bustype(或其他子系统)用pm_rumtime_allow()或者是pm_rumtime_forbid()来初始化。
默认值是允许rumtimepm的。
用户空间可以通过向设备的sysfs文件power/control写入”on”或者”auto”来修改该标志位。
写入”auto”相当于调用了pm_rumtime_allow(),允许设备由驱动程序进行rumtimepm。
写入”on”相当于调用pm_rumtime_forbid(),标志位被清除,设备将会从低功耗状态返回全功率状态,并且阻止设备进行runtime电源管理。
用户空间也可以读取该文件来检查runtime_auto的当前值。
设备的runtime_auto标志不会影响系统级别电源状态的迁移。
特别注意的是,尽管runtime_auto标志被清除,当系统级别的电源状态迁移到睡眠状态时,设备也会被带入低功耗状态。
关于runtime电源管理架构的更多信息,请参看Documentation/power/runtime_pm.txt。
调用驱动程序进入或退出系统睡眠状态
==================================
当系统进入睡眠状态,系统会要求设备驱动程序让设备进入兼容于目标系统的一种状态来挂起(suspend)设备。
这通常是某种”off”状态。
具体情况都是特定于各系统的。
另外,可唤醒的设备一般会保持部分功能以便适当的时候可以唤醒系统。
当系统退出低功耗状态时,设备驱动程序被要求恢复(resume)设备让他进入全电源状态。
suspend和resume动作总是一起发生的,两者都可分为多个不同的阶段。
对于相对简单的驱动程序,suspend可能在suspend_noirq阶段使用上层的类代码来停止设备并尽可能让它们进入”off”状态。
唤醒时,相对应的resume调用会重新初始化硬件,然后重新激活他们的I/O活动。
对电源有特别需求的驱动程序可能会让设备做出必要的准备,以便之后可以产