Linux PM QoS framework(3)_per-device PM QoS
作者:wowo 发布于:2015-2-26 22:44 分类:电源管理子系统
1. 前言
per-device PM QoS是针对指定设备的QoS framework,背后的思考如下:
1)resume_latency
在Runtime PM的框架下,当device的引用计数减为0的时候,RPM会suspend该device。不过,device进入suspend状态以及从suspend状态resume是需要消耗时间的(相关信息保存在pm domain中),而系统其它实体(如用户空间程序)可能对该设备的响应时间有要求,这就是一种形式的QoS request,称作resume_latency。
per-device PM QoS framework会提供相应的接口,收集指定设备的resume_latency request,并提供给Runtime PM,它在suspend设备时,会考虑这种需求,并决定是否suspend设备。
2)latency_tolerance
一些复杂的设备,在运行状态(active)时,为了节省功耗,也有可能自行进入某些省电状态,相应的,设备的响应速度可能降低。如果该设备足够智能,可能会提供一个回调函数(.set_latency_tolerance,位于dev_pm_info结构中),以便设置最大的延迟容忍时间。这称作latency_tolerance。
对per-device PM QoS来说,需要提供一种机制,收集所有的、针对某个设备的latency_tolerance需求,并汇整出可以满足所有需求的latency_tolerance,通过设备的回调函数告知设备。
3)no power off/remote wakeup
在Runtime PM的框架下,设备suspend之后,还可以进一步通过pm domain关闭该设备的供电,以节省功耗。但关闭供电时,除了要考虑对设备resume_latency的需求之外,还要考虑该设备是否允许关闭供电,以及该设备是否需要作为一个唤醒源(remote wakeup)。
这是另一种形式的QoS request,称作per-device PM QoS flag,表示系统其它实体对该设备的一些特定行为的需求。当前的flag有两种:
PM_QOS_FLAG_NO_POWER_OFF,表示不允许设备断电
PM_QOS_FLAG_REMOTE_WAKEUP,表示设备应具备唤醒功能
这两个flag可以通过或操作,同时生效。
因此,per-device PM QoS framework的功能,就是抽象上面两类需求,包括:向requestor提供QoS request的add、update、remove等API,包括内核空间API和用户空间API;汇整、整理这些request;向电源管理有关的service(主要是pm domain framework)提供汇整后的request信息,以便这些service可以做出正确的决定。
下面将会结合source code(位于drivers/base/power/qos.c中),介绍上面的实现逻辑。
2. API汇整
2.1 struct dev_pm_qos数据结构
每个设备的per-device pm qos信息,都保存在设备的qos指针中,即:
1: struct device {
2: ...
3: struct dev_pm_info power;
4: ...
5: }
6:
7: struct dev_pm_info {
8: ...
9: struct dev_pm_qos *qos;
10: ...
11: }
该指针的数据类型struct dev_pm_qos是per-device pm qos的核心数据结构,定义如下:
1: struct dev_pm_qos {
2: struct pm_qos_constraints resume_latency;
3: struct pm_qos_constraints latency_tolerance;
4: struct pm_qos_flags flags;
5: struct dev_pm_qos_request *resume_latency_req;
6: struct dev_pm_qos_request *latency_tolerance_req;
7: struct dev_pm_qos_request *flags_req;
8: };
resume_latency,为第一种QoS request,表示其它实体对该设备从suspend状态返回的延迟的要求。struct pm_qos_constraints为pm qos要求的具体抽象,可参考“Linux PM QoS framework(2)_PM QoS class”中的描述;
latency_tolerance,为第二种QoS request,和resume_latency类似;
flags,为第三种QoS request,主要包括一个链表头,用于保存具体的flag要求,以及汇整后的、当前所有有效的flags;
resume_latency_req、latency_tolerance_req、flags_req,三个不同类型的request指针,用于保存用户空间对设备pm QoS的request请求。struct dev_pm_qos_request结构类似上一篇文章所描述的struct pm_qos_request结构,用于抽象一个具体的request。
1: struct dev_pm_qos_request {
2: enum dev_pm_qos_req_type type;
3: union {
4: struct plist_node pnode;
5: struct pm_qos_flags_request flr;
6: } data;
7: struct device *dev;
8: };
type,request的类型,当前共三类,包括在前言部分所描述的三种request(DEV_PM_QOS_RESUME_LATENCY、DEV_PM_QOS_LATENCY_TOLERANCE、DEV_PM_QOS_FLAGS);
data,不同类型的request,有不同的数据,因此这里是一个联合体。当为DEV_PM_QOS_RESUME_LATENCY、DEV_PM_QOS_LATENCY_TOLERANCE时,为一个plist_node,类似PM QoS class。为DEV_PM_QOS_FLAGS时,为struct pm_qos_flags_request类型的变量;
dev,保存了设备指针。
2.2 向kernel其它driver提供的,用于提出per-device PM QoS需求的API
int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
enum dev_pm_qos_req_type type, s32 value);
int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value);
int dev_pm_qos_remove_request(struct dev_pm_qos_request *req);
类似PM QoS class中的pm_qos_*接口,不过操作对象为设备,因而需要提供相应的设备指针。
2.3 向kernel PM有关的service(例如PM domain)提供的,用于获取、跟踪指定PM QoS需求的API
enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask);
s32 dev_pm_qos_read_value(struct device *dev);
int dev_pm_qos_add_notifier(struct device *dev,
struct notifier_block *notifier);
int dev_pm_qos_remove_notifier(struct device *dev,
struct notifier_block *notifier);
int dev_pm_qos_add_global_notifier(struct notifier_block *notifier);
int dev_pm_qos_remove_global_notifier(struct notifier_block *notifier);
由于DEV_PM_QOS_FLAGS特殊性,kernel提供了单独的API,以获取相应的flags。对于其它两个类型的QoS,和PM QoS class中的pm_qos_*接口类似。
2.4 向用户空间process提供的,用于提出per-device PM QoS需求的API
通过sysfs文件,kernel允许用户空间程序对某个设备提出QoS需求,这些sysfs文件位于各个设备的sysf目录下,默认情况下,PM QoS framework不会创建这些文件,除非具体设备驱动调用dev_pm_qos_expose_*系列接口,主动创建。具体可参考代码,这里不再详细说明。
3. 实现思路和内部逻辑
和PM QoS class类似,不再描述。
原创文章,转发请注明出处。蜗窝科技,www.wowotech.net。
标签: Linux Kernel pm_qos per-device

评论:
2015-02-28 16:47
电源管理子系统的文章篇数已经20多了,但是我有个提议,
现在Android的产品不少,在“电源管理子系统”的文章中,能否加入一些像battery,adapter,USB充电这部分的代码设计分析。
Linux总是奔向骨感,但是安卓的产品设计总是急切的要去解决现实的battery,adapter,USB充电问题。
这部分电源设计知识可能很多人感兴趣,希望WOWO有时间可以分享一下这部分。
功能
最新评论
- wangjing
写得太好了 - wangjing
写得太好了! - DRAM
圖面都沒辦法顯示出來好像掛點了。 - Simbr
bus至少是不是还有个subsystem? - troy
@testtest:只要ldrex-modify-strex... - gh
Linux 内核在 sparse 内存模型基础上实现了vme...
文章分类
随机文章
文章存档
- 2025年4月(5)
- 2024年2月(1)
- 2023年5月(1)
- 2022年10月(1)
- 2022年8月(1)
- 2022年6月(1)
- 2022年5月(1)
- 2022年4月(2)
- 2022年2月(2)
- 2021年12月(1)
- 2021年11月(5)
- 2021年7月(1)
- 2021年6月(1)
- 2021年5月(3)
- 2020年3月(3)
- 2020年2月(2)
- 2020年1月(3)
- 2019年12月(3)
- 2019年5月(4)
- 2019年3月(1)
- 2019年1月(3)
- 2018年12月(2)
- 2018年11月(1)
- 2018年10月(2)
- 2018年8月(1)
- 2018年6月(1)
- 2018年5月(1)
- 2018年4月(7)
- 2018年2月(4)
- 2018年1月(5)
- 2017年12月(2)
- 2017年11月(2)
- 2017年10月(1)
- 2017年9月(5)
- 2017年8月(4)
- 2017年7月(4)
- 2017年6月(3)
- 2017年5月(3)
- 2017年4月(1)
- 2017年3月(8)
- 2017年2月(6)
- 2017年1月(5)
- 2016年12月(6)
- 2016年11月(11)
- 2016年10月(9)
- 2016年9月(6)
- 2016年8月(9)
- 2016年7月(5)
- 2016年6月(8)
- 2016年5月(8)
- 2016年4月(7)
- 2016年3月(5)
- 2016年2月(5)
- 2016年1月(6)
- 2015年12月(6)
- 2015年11月(9)
- 2015年10月(9)
- 2015年9月(4)
- 2015年8月(3)
- 2015年7月(7)
- 2015年6月(3)
- 2015年5月(6)
- 2015年4月(9)
- 2015年3月(9)
- 2015年2月(6)
- 2015年1月(6)
- 2014年12月(17)
- 2014年11月(8)
- 2014年10月(9)
- 2014年9月(7)
- 2014年8月(12)
- 2014年7月(6)
- 2014年6月(6)
- 2014年5月(9)
- 2014年4月(9)
- 2014年3月(7)
- 2014年2月(3)
- 2014年1月(4)
2015-07-10 16:27