linux devfreq框架

介绍

devfreq: Generic Dynamic Voltage and Frequency Scaling (DVFS) Framework for Non-CPU Devices
在Linux 里面,CPU调频有cpufreq框架,那么其他模块调频用什么框架呢?比如DDR、DSP、GPU等等,答案是devfreq框架。

这个框架提供了以下功能:

  • 提供了一套标准框架,用于任意设备的调频调压功能
    • 提供了几个governor。也可以自定义governor并注册
    • 提供了工作队列机制,用于周期性进行load monitor,并调整频率
  • 在用户层提供了sysfs,类似于cpufreq的功能

软件框架

与cpufreq框架类似,

  • 对上:devfreq对上提供sysfs节点,供用户空间配置,包括频率范围、调频周期、调频governor
  • 内部:维护devfeq、governord等信息、suspend/resume流程、通知机制、load monitor机制等等
  • 对下,devfreq实现了统一的接口,包括devfreq注册、governor注册等

几个重要的概念和模块,

  • governor
    与cpufreq类似,调频策略的实现,目前有simple_ondemand、powersave、performance、passive等。还可以自己实现更多的governor,并注册到devfreq core。

  • devfreq driver
    驱动开发者为了实现DDR、DSP、GPU等设备实现的具体驱动。主要功能是调整频率、获取频率、选择governor等

  • devfreq event
    如果可以调频的设备,拥有一套load monitor的机制,比如使能、去使能、设置事件、获取事件,那么可以使用此框架进行注册和管理。

工作流程

sequenceDiagram devfreq_core ->> devfreq_core: subsys_initcall阶段创建文件节点 governors ->> devfreq_core: subsys_initcall阶段注册governor devfeq_driver ->> devfreq_core: 调用devfreq_add_device注册devfreq devfreq_core ->> governors: DEVFREQ_GOV_START启动load monitor任务 governors ->> +devfreq_core: 调用devfreq_monitor_start,启动周期性workqueue任务`devfreq_monitor` loop devfreq_monitor devfreq_core ->> devfreq_core: update_devfreq devfreq_core ->> devfreq_core: devfreq_update_target devfreq_core ->> +governors: get_target_freq获取新的频率 governors ->> devfeq_driver: devfreq_update_stats获取负载相关信息 devfeq_driver ->> +devfeq_event:devfreq_event_get_event devfeq_event ->> -devfeq_driver: 返回负载信息 governors ->> -devfreq_core:返回target频率 devfreq_core ->> devfreq_core: devfreq_get_freq_range综合pm qos结果,返回最大最小频率范围 devfreq_core ->> -devfeq_driver: devfreq_set_target调用驱动回调配置频率profile->target end

文件

文件 作用
drivers/devfreq/devfreq.c devfreq core功能,sysfs文件节点、devfreq注册、governor注册公共接口、
include/linux/devfreq.h
drivers/devfreq/devfreq-event.c devfreq event对硬件负载监控单元功能进行了封装,使能、去使能、获取设置事件等功能

主要数据结构

struct devfreq_dev_profile

struct devfreq_dev_profile {
	unsigned long initial_freq;
	unsigned int polling_ms;
	enum devfreq_timer timer;
	bool is_cooling_device;

	int (*target)(struct device *dev, unsigned long *freq, u32 flags);
	int (*get_dev_status)(struct device *dev,
			      struct devfreq_dev_status *stat);
	int (*get_cur_freq)(struct device *dev, unsigned long *freq);
	void (*exit)(struct device *dev);

	unsigned long *freq_table;
	unsigned int max_state;
};
  • 作用
    驱动程序需要实现和定义的内容

    • 初始频率
    • 调频周期
    • 修改频率函数
    • 获取频率函数
  • 主要字段说明

字段 说明
initial_freq 初始频率
timer 调频使用的定时器timer
target 修改频率函数
get_dev_status 获取设备状态
get_cur_freq 通过硬件获取频率,不是软件保存的当前频率值
exit 可选, 驱动退出时,回调函数

struct devfreq

struct devfreq {
	struct list_head node;

	struct mutex lock;
	struct device dev;
	struct devfreq_dev_profile *profile;
	const struct devfreq_governor *governor;
	struct opp_table *opp_table;
	struct notifier_block nb;
	struct delayed_work work;

	unsigned long *freq_table;
	unsigned int max_state;

	unsigned long previous_freq;
	struct devfreq_dev_status last_status;

	void *data; /* private data for governors */

	struct dev_pm_qos_request user_min_freq_req;
	struct dev_pm_qos_request user_max_freq_req;
	unsigned long scaling_min_freq;
	unsigned long scaling_max_freq;
	bool stop_polling;

	unsigned long suspend_freq;
	unsigned long resume_freq;
	atomic_t suspend_count;

	/* information for device frequency transitions */
	struct devfreq_stats stats;

	struct srcu_notifier_head transition_notifier_list;

	/* Pointer to the cooling device if used for thermal mitigation */
	struct thermal_cooling_device *cdev;

	struct notifier_block nb_min;
	struct notifier_block nb_max;
};
  • 作用
    devfreq core维护的各设备的资源集合体。devm_devfreq_add_device添加调频device后返回此资源体。

    • 具体设备的调频驱动
    • 频率电压表opp
    • 调度work
  • 重要字段说明

字段 说明
node devfreq core会把各设备添加个一个大的链表中
profile 此devfreq绑定的调频驱动
governor 此devfreq绑定的调频governor
opp_table 此devfreq使用的opp
work 创建周期的work
previous_freq 上一次的频率
user_min_freq_req 通过sysfs设置的最低频率
user_max_freq_req 通过sysfs设置的最高频率
scaling_min_freq 设备支持的最低频率
scaling_max_freq 设备支持的最高频率
data governor使用的私有数据,比如simple_ondemand设置的上下阈值。passive需要的parent,获取频率

主要函数

devm_devfreq_add_device

参数1:设备指针
参数2:设备驱动实现的调频功能,主要实现部分
参数3:设备驱动选择的governor
参数4:governor使用的私有数据

struct devfreq *devm_devfreq_add_device(struct device *dev,
					struct devfreq_dev_profile *profile,
					const char *governor_name,
					void *data)

devfreq_add_governor

注册新的governor

int devfreq_add_governor(struct devfreq_governor *governor)

调试

用户节点说明 https://github.com/torvalds/linux/blob/master/Documentation/ABI/testing/sysfs-class-devfreq

/sys/class/devfreq/

available_frequencies: 可用的频率列表
available_governors:可用的governor
cur_freq:当前频率
governor: 当前governor
max_freq:最大频率,综合qos(sysfs配置/其他模块请求)、hardware的结果
min_freq :最小频率,综合qos(sysfs配置/其他模块请求)、hardware的结果
polling_interval:governor调度的时间间隔,单位是ms
target_freq:目标频率
trans_stat:状态调整表

/sys/kernel/debug/devfreq

posted @ 2023-07-14 20:28  zephyr~  阅读(473)  评论(0编辑  收藏  举报