Linux devfreq framework 剖析
内核工匠 2022-09-29


当今的复杂SoC由多个子模块协同工作组成。在执行各种用例的操作系统中,并非SoC中的所有模块都需要始终保持最高性能。为方便起见,将SoC中的子模块分组为域,从而允许某些域以较低的电压和频率运行,而其他域以较高的电压/频率对运行。


对于这些设备支持的频率和电压对,我们称之为OPP(Operating Performance Point)。对于具有OPP功能的非CPU设备,本文称之为OPP device,需要通过devfreq进行动态的调频调压。


devfreq:Generic Dynamic Voltage and Frequency Scaling (DVFS) Framework for Non-CPU Devices。是由三星电子MyungJoo Ham ,提交到社区。原理和/deivers/cpufreq 非常近似。但是cpufreq驱动并不允许多个设备来注册,而且也不适合不同的设备具有不同的governor。devfreq则支持多个设备,并且允许每个设备有自己对应的governor。


如下图,devfreq framework是功耗子系统的一部分,与cpufreq,cpuidle,powermanager相互配合协作,已达到节省系统功耗的目的。


图1



标准化接口


devfreq framework作为Linux Kernel一个子系统,需要为user space和其他子系统提供接口,已完成功能交互。本章从Kernel空间和user空间的角度,介绍devfreq framework的相关接口。


1. Kernel空间数据结构和接口


1) devfreq profile结构体,是OPP device注册到devfreq framework的数据结构,主要包含OPP设备的频率相关信息和相关的回调函数,是devfreq framework和OPP device driver的交互接口。


类似设备驱动模型,将OPP device driver对devfreq使用,简化为devfreq profile结构体的填充。大大简化了开发复杂度,减少了重复的工作。


下面对devfreq_dev_profile的主要属性进一步的介绍。


2) devfreq governor结构体,是governor注册到devfreq framework的数据结构,主要包含governor的相关属性和具体的函数实现。是devfreq framework和governor交互接口。


下面对devfreq_governor 的主要属性进一步的介绍。


3) devfreq设备结构体,这个是devfreq设备的核心数据结构。将上述的OPP device driver的devfreq_dev_profile和governor的devfreq_governor连接到一起,并通过设备驱动模型中device类,为user 空间提供接口。


下面对devfreq的主要属性进一步的介绍。



2. 用户空间文件节点


devfreq framework不仅为Kernel空间的设备驱动提供了标准化接口,也为user空间提供了标准化的文件节点,方便user空间的程序,更好的监控和修改。


相关文件节点介绍:kernel/Documentation/ABI/testing/sysfs-class-devfreq。


  • available_frequencies: 可用的频率列表

  • available_governors:可用的governor

  • cur_freq:当前频率

  • governor: 当前governor

  • max_freq:最大频率

  • min_freq :最小频率

  • polling_interval:governor调度的时间间隔,单位是ms

  • target_freq:目标频率

  • trans_stat:状态调整表


代码实现:kernel/drivers/devfreq/devfreq.c



工作流程


本章节主要介绍devfreq framework在系统中的工作流程,从初始化,频率调整,退出机制几个方便介绍devfreq framework的运行机制和函数调用逻辑。


1. 初始化


初始化,主要包括devfreq framework,governor的初始化和OPP device创建devfreq设备的流程。如图2所示。下面的章节,将对各个初始化过程,进行更进一步的介绍。


图2


1) Devfreq framework初始化,逻辑非常简单清晰,主要完成以下的任务,然后为governor的初始化和OPP device 创建devfreq device做好准备。


代码实现:kernel/drivers/devfreq/


a.创建devfreq设备类


b.创建工作队列,用于负载监控work调用运行


c.加入到subsys_initcall,系统启动时初始化



2) governors 初始化


系统中可支持多个governors,在系统启动时进行初始化,并注册到devfreq framework中, 后续OPP device创建devfreq设备,会根据governor名字从已经初始化好的governor 列表中,查找对应的governor实例。


a.填充governor的结构体,不同的governor,会有不同的实现。


b.将governor加入到devfreq framework的governor列表中。


c.加入到subsys_initcall,系统启动时初始化。



目前系统默认支持下面:


  • simple_ondemand:按需调整模式;根据系统负载动态频率,平衡性能和功耗

  • Performance:性能优先模式,调整到最大频率

  • Powersave:功耗优先模式,调整到最小频率

  • Userspace:用户指定模式,调整到用户设置的频率.

  • Passive:被动模式,使用设备指定方法做调整或跟随父devfreq设备的governor


可以根据自己的设备特性,通过填充devfreq_governor结构体和实现get_target_freq方法和event_handler,完成的自己的governor。devfreq framework的架构设计对governor扩展,支持极好。


3) OPP device通过devfreq framework创建devfreq device。


以UFS设备为例,介绍OPP device用devfreq framework来添加devfreq设备的过程。


代码位置:kernel/drivers/scsi/ufs/ufshcd.c


① OPP device driver通过devfreq framework创建devfreq设备。


a.将ufs设备的core clk的添加到opp子系统中,devfreq_add_device函数中,会从opp子系统中获取clk信息。


b.将OPP device相关频率信息和回调函数,并填充devfreq profile数据结构。


c.调用devfreq_add_device函数,将devfreq profile数据结构,governor名字,添加到devfreq framework。

②devfreq_add_device 创建devfreq设备的流程如下:


a. devfreq device申请内存空间 初始化devfreq device结构体后,注册设备。


b. 根据传入的governor名字,从governor列表中,获取对应的governor实例。


c.发送DEVFREQ_GOV_START到governor,开始管理OPP device的频率。


2.频率调整过程


图3


如图3所示,频率调整过程中,分工非常明确,devfreq framework是大管家负责监控程序的运行,governor提供管理算法,OPP device提供自身的负载状态和频率设置的方法实现。


系统中有不同的governor,而且不同的governor有不同的管理算法,但是频率调整过程是一样的。本小节,以simple_ondemand governor为例,讲述governor的管理过程。


1)governor的event_handler收到 DEVFREQ_GOV_START事件,调用对应的函数,调度工作队列,运行负载监控程序。


2)负载监控程序。


a.调用governor的get_target_freq方法,获取下一次的调频结果。


b.调用OPP device注册到devfreq framework 的target函数,设置新的频率信息。


c.调度延迟工作队列,延迟OPP device 设置的轮询间隔后,再次运行。


3)governor的get_target_freq方法,调用opp device注册到devfreq framework的回调函数,获取当前device负载信息,根据算法,返回调整频率。



3. 删除devfreq设备


1)直接调用device_unregister函数注销devfreq设备。


2)device_unregister注销过程中会调用devfreq_dev_release函数,完成下面的事务。


a.发送DEVFREQ_GOV_STOP event,governor停止运行;


b.回调OPP device注册到devfreq framework的exit函数;


c.释放devfreq device申请的资源。



架构设计


devfreq framework将多种OPP device和多种governor进行抽象,对OPP device提供了统一的接口,来满足其对devfreq的需求。对governor提供统一的实现格式,为后续扩展不同governor,提供很好的架构支持。是一个典型的子系统实现模式。为后续在我们自己做子系统架构设计,提供了一个很好的参考。




综述


本文从需求背景、接口、数据结构、工作流程和架构设计几个维度,介绍Linux Kernel的devfreq framework 子系统。希望能对大家的工作学习有所帮助。因个人能力所限,如有错误,欢迎大家斧正。

声明: 本文转载自其它媒体或授权刊载,目的在于信息传递,并不代表本站赞同其观点和对其真实性负责,如有新闻稿件和图片作品的内容、版权以及其它问题的,请联系我们及时删除。(联系我们,邮箱:evan.li@aspencore.com )
0
评论
  • 【7.24 深圳】2025国际AI+IoT生态发展大会/2025全球 MCU及嵌入式技术论坛


  • 相关技术文库
  • C语言
  • 编程
  • 软件开发
  • 程序
  • 51单片机数码管显示跑马灯程序源代码讲解

    基于51单片机学习板。用S1键作为控制跑马灯的方向按键,S5键作为控制跑马灯方向的加速度按键,S9键作为控制跑马灯方向的减速度按键,S13键作为控制跑马灯方向的启动或者暂停按键。记得把输出线P0.4一直输出低电平,...

    昨天
  • 基于ARM的智能家居控制通信控制站的设计与实现

    0 引言 物体信息化是现代社会信息化建设的“催化剂”和“增倍器”。只有走集成整合信息技术以及信息数据之路,企业的信息化建设才能真正发挥作用,才能进一步推动信息建设上水平。现代物体信息化的发展,直接刺激了新生...

    前天
  • ARM中打印函数print 的几种实现方法

    1利用C库函数printf。 步骤: 1)首先需要包含头文件stdio.h。 2)然后定义文件句柄。实际上就是一个int型变量封装在结构体中。 struct__FILE{inthandle;}; 3)定义FILE__stdout;FILE即为__FILE,通过stdio.h宏定义。...

    前天
  • 高效的C编程之:C编译器及其优化(上)

    本章将帮助读者在ARM处理器上编写高效的C代码。本章涉及的一些技术不仅适用于ARM处理器,也适用于其他RISC处理器。本章首先从ARM编译器及其优化入手,讲解C编译器在优化代码时所碰到的一些问题。理解这些问题,将有...

    07-08
  • 有关C51的编程规范

    简介:编程首要是要考虑程序的可行性,然后是可读性、可移植性、健壮性以及可测试性。这是总则。但是很多人忽略了可读性、可移植性和健壮性(可调试的方法可能歌不相同),这是不对的。 下面就来说说有关C51的编程规...

    07-08
  • 光立方程序编写步骤

    基于51单片机的4*4*4光立方程序实现原理及程序代码。LED光立方的复位电路、时钟电路、每层LED灯电路控制逻辑,系统总原理图,工作流程及相关C语言源码实现。希望能够对你学习了解LED光立方程序编写及LED立方实体制...

    07-04
  • 封装继承多态

    封装: 封装是实现面向对象程序设计的第一步,封装就是将数据或函数等集合在一个个的单元中(我们称之为类)。被封装的对象通常被称为抽象数据类型。 封装的意义: 封装的意义在于保护或者防止代码(数据)被我们无意中...

    07-04
  • 封装是什么意思?

    即隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别;将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中...

    07-04
  • 超声波模块测距51程序_单片机超声波测距c语言

    超声波检测原理 超声波测距的程序流程图 程序如下: //超声波模块程序 //超声波模块程序 //Trig = P2^0 //Echo = P3^2 #include #define uchar unsigned char #define uint unsigned int // void delay(uint z) {...

    07-01
  • 大佬带你看嵌入式系统,嵌入式系统该学习什么?

    嵌入式系统是当今的热门系统之一,在诸多领域,嵌入式系统都有所应用。为增进大家对嵌入式系统的认识,小编将为大家介绍嵌入式系统是一个什么样的专业,以及学习嵌入式系统该学习哪些内容。如果你对嵌入式系统具有...

    06-27
  • c51单片机编程要点总结

    c51单片机编程要点总结 1、头文件:#include (我用的是 STC 89C54RD+) 2、预定义:sbit LED = P1^0// 定义 P1 口的 0 位为 LED 注:“P1^0”这个写法,与 A51 不同(A51 是 P1.0),P1 是一组端口,端口号范围 0~7 注2...

    06-25
下载排行榜
更多
评测报告
更多
广告