电源管理入门-15 PM QoS

张开发
2026/4/17 7:58:42 15 分钟阅读

分享文章

电源管理入门-15 PM QoS
QoS(Quality Of Service服务质量)一般在网络报文中某个报文的优先级比较高则优先传输例如我们觉得微信聊天比看网页更重要我们就可以提高微信报文的等级即服务质量QoS来提供好的网络服务解决延迟、网络阻塞等问题。在电源管理里面的策略就各种governor例如什么时候进入cpuidle、什么时候DevFreq等这些策略是很单一的算法也都是很单调的未考虑到消费者的实际需求那怎么样把用户的需求也在电源管理里面生效呢答案就是在governor中引入QoS在governor中会去查QoS的策略综合起来进行决策。1. 系统框架介绍1.1 功耗控制可能影响用户体验的一些痛点而且功耗管理会引入对性能的缺点主要两方面延时latency增加时间的开销尤其是在恢复的过程中需要时间。比如系统唤醒需要经过各驱动的恢复power domain的上电过程也有时间开销。**吞吐量Throughput**减少低功耗也会带来算力的影响会降低算力及网路的吞吐量。比如cpu dvfs、cpu hotplug、cpu idle等会影响到cpu算力。比如在usb传输的时候把dma给限制了导致传输速率下降这些是用户不希望看到的。又比如延时和性能开销影响到用户的体验比如界面操作不流畅、卡顿响应时间过长。这就像苹果手机很流畅优先响应用户的需求安卓可能更高效但是有点卡用户就觉得屏幕划不动了。但是很明显苹果手机更有市场用户体验才是王道在面对用户场景的情况下我们需要在策略中考虑到用户使用感受。在用户眼里更多的看中应用服务而且不是一味的强调功耗低为了核心业务和用户体验是可以适当的牺牲功耗的产品做出来最终还是要用户用的技术再好功耗再低不满足用户习惯就是0.如果把Linux PM当做一种服务那么他对其他模块的影响就类比为服务的质量要满足其他指标不受到影响的情况下最大化的省电这才是最终目标。那么这里PM QoS的作用就是定义一套框架以满足系统如设备驱动等对QoS的期望为终极目标通俗的讲根据实际场景这些期望可以描述为:xxx不大于某个值等等。1.2 QoS框架PM QOS使用**constraint约束**作为指标用于各模块对PM的诉求及限制。当前系统的指标主要有两类分别对应两个PM QOS framework。系统级constraint包括cpudma latency5.4内核它的实际意义是当产生一个事件之后如一个中断CPU或DMA的响应延迟。例如有些CPU的串口控制器只有几个byte的FIFO当接收数据时CPU或DMA必须在FIFO填满前将数据读走否则就可能丢失数据或者降低数据的传输速率。由PM QoS classes framework管理定义在kernel/power/qos.c中。设备级constraint包括从低功耗状态resume的latency、active状态的latency和一些QoS flag如是否允许power off。由per-device PM QoS framework管理定义在drivers/base/power/qos.c。整个PM QOS框架分为三部分需求方各service、各driver。他们根据自己的功能需求提出系统或某些功能的QOS约束比如cpudma latency。框架层PM QOS framework包含PM QOS classes、per device PM QOS。向需求方提供request的add、modify、remove等接口用于管理QoS requests。对需求方的约束进行分类计算出极值比如cpudma latency不小于某个值。向执行方提供request value的查询接口。PM QoS classes framework位于kernel/power/qos.c中负责系统级别的PM QoS管理通过misc设备/dev/cpu_dma_latency向用户空间程序提供PM QoS的request、modify、remove功能以便满足各service对PM QoS的需求。per-device PM QoS framework位于drivers/base/power/qos.c中负责per-device的PM QoS管理。执行方power management的机制比如cpuidle、cpu dvfs等。需要满足由框架层根据需求方提供的约束计算的极值才能执行相应的低功耗机制。2. 用户空间操作流程2.2 用户空间数据结构和APIstruct pm_qos_object{struct pm_qos_constraints *constraints;struct miscdevice pm_qos_power_miscdev;char *name;};struct pm_qos_object在给每个class定义pm_qos_constraints结构体的同时也为每个class定义了miscdev变量用于给用户空间提供接口。这些接口主要实现各类PM QoS需求的汇总和计算极值的工作add/update/remove等并且提供接口给到用户空间process用于用户空间的QoS需求另外还提供了一些notifier API用于跟踪指定的PM QoS的变化。主要API:void pm_qos_add_request(struct pm_qos_request *req,int pm_qos_class, s32 value)1用于向PM QoS framework添加一个QoS请求主要是根据指定的pm_qos_class向pm_qos_class链表中插入一个新的pm_qos_request节点并且更新target value。void pm_qos_update_request(struct pm_qos_request *req,s32 new_value)void pm_qos_update_request_timeout(struct pm_qos_request *req, s32 new_value, unsigned long timeout_us)//在update的基础上多出来一个定时器用于特定需求的延迟更新2 pm_qos_update_request/pm_qos_update_request_timeout,如果应用场景变化需要满足不同的要求比如串口波特率变大相应的响应延迟需要变小则需要调用该接口来更新相应的qos请求。函数体的主要部分pm_qos_update_target和Add相似这里就不再介绍。3 pm_qos_remove_request如果对该class没有需求则可以调用该接口将请求移除。4 借助misc设备向用户空间提供的接口open/read/write等调用的接口和上面提到的add/remove等类似这里就不再赘述。5 pm_qos_add_notifier/ pm_qos_remove_notifier有部分实体如cpuidle比较关注cpu_dma_latency的指标会比较关注某一个pm qos class的target value的变化kernel提供了这样一个notifier的机制该实体可以通过pm_qos_add_notifier接口添加一个notifier这样当value变化时framework便会通过notifier的回调函数通知该实体。需求方执行方2.1 struct pm_qos_constraintsstruct pm_qos_constraints{struct plist_head list;s32 target_value;/* Do not change to64bit */ s32 default_value;s32 no_constraint_value;enum pm_qos_typetype;struct blocking_notifier_head *notifiers;};struct pm_qos_request{struct plist_nodenode;int pm_qos_class;struct delayed_work work;/*forpm_qos_update_request_timeout */};struct pm_qos_request用于request的add/update/remove等操作。struct pm_qos_constraintspm qos约束用于抽象某一个特定的PM QoS class。target_value、default_value分别是该指标的目标值满足所有需求的value可以是极大值或者极小值等某一个指标关注的是极大值还是极小值在初始化的时候已经确定默认值该指标的默认值通常是0表示没有限制。3. 初始化流程**static int __init pm_qos_power_init(void){for(iPM_QOS_CPU_DMA_LATENCY;iPM_QOS_NUM_CLASSES;i){retregister_pm_qos_misc(pm_qos_array[i], d);if(ret0){printk(KERN_ERRpm_qos_param: %s setup failed\n, pm_qos_array[i]-name);returnret;}}系统支持的QOS类型enum{PM_QOS_RESERVED0, PM_QOS_CPU_DMA_LATENCY, PM_QOS_NETWORK_LATENCY, PM_QOS_NETWORK_THROUGHPUT, PM_QOS_MEMORY_BANDWIDTH, /* insert new class ID */ PM_QOS_NUM_CLASSES,};debugfs_create_file会创建sysfs供用户空间调用。4. DMA举例例如启动摄像头的时候我们系统即便在省电的情况下也需要cpu_dma允许的延迟时间不能超过50us否则影响画面质量。drivers/media/platform/via-camera.c中pm_qos_add_request在启动camera的时候这里请求了一个cpu_dma_latency的指标为50us即camera driver申请的cpu_dma允许的延迟时间不能超过50uscpuidle初始化的时候会调用static inline void latency_notifier_init(struct notifier_block *n){pm_qos_add_notifier(PM_QOS_CPU_DMA_LATENCY, n);}PM_QOS_CPU_DMA_LATENCY变化的时候会通知cpuidle在进行cpuidle决策的时候例如ladder governor中static int ladder_select_state(struct cpuidle_driver *drv, struct cpuidle_device *dev){struct ladder_device *ldevthis_cpu_ptr(ladder_devices);struct ladder_device_state *last_state;int last_residency, last_idxldev-last_state_idx;int latency_reqpm_qos_request(PM_QOS_CPU_DMA_LATENCY);pm_qos_request函数会获取target_value根据这个值来决定进行什么级别的idle。对于cpuidle idle来说一般有C1~C3几个等级在C3等级的退出延迟时间是57us不同平台会有差别那么这里camera driver需求的50us容忍延迟就可以让cpuidle退到C2 idle等级即前面章节提到的执行方需要确保自身的行为满足这些pm qos的需求就不会导致上面说的DMA transfer gets corrupted的问题了。参考资料https://blog.csdn.net/feelabclihu/article/details/116810959https://zhuanlan.zhihu.com/p/561000691https://hqber.com/archives/459/后记内核版本有时候差异也挺大的一个机制特别是小众的可能会有更新我们在找资料的时候就需要注意这点找到合适的学习资料。不过主要的思想是不变的变的就是结构体定义api函数的调用流程等。干啥都能干干啥啥不是专业入门劝退堪称程序员杂家”。欢迎各位自己有博客公众号的留言申请转载多谢后续会继续更新纯干货分析欢迎分享给朋友欢迎点赞、收藏、在看、划线和评论交流公众号“那路谈OS与SoC嵌入式软件”欢迎关注个人文章汇总https://thatway1989.github.io

更多文章