设备频率缩放¶
简介¶
该框架为任意设备上的动态电压和频率切换(Dynamic Voltage and Frequency Switching)提供了标准的内核接口。
它通过类似于 cpufreq 子系统的 sysfs 文件暴露了频率调节控制。
对于可以测量当前使用情况的设备,其频率可以由调频器(governors)自动调整。
API¶
设备驱动需要初始化一个 devfreq_profile
并调用 devfreq_add_device()
函数来创建一个 devfreq
实例。
-
struct devfreq_dev_status¶
devfreq 用户设备提供给调频器的数据。表示性能统计信息。
定义:
struct devfreq_dev_status {
unsigned long total_time;
unsigned long busy_time;
unsigned long current_frequency;
void *private_data;
};
成员
total_time
devfreq_dev_status 实例所代表的总时间
busy_time
设备在总时间中工作的时长。
current_frequency
当前工作频率。
private_data
devfreq 框架未指定的一个条目。设备和特定调频器可以通过 private_data 拥有自己的协议。然而,由于这是调频器特有的,使用它的调频器将只与了解它的设备兼容。
-
struct devfreq_dev_profile¶
devfreq 的用户设备配置文件
定义:
struct devfreq_dev_profile {
unsigned long initial_freq;
unsigned int polling_ms;
enum devfreq_timer timer;
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;
bool is_cooling_device;
};
成员
initial_freq
调用
devfreq_add_device()
时的工作频率。polling_ms
轮询间隔,单位为毫秒。0 表示禁用轮询。
timer
定时器类型可以是可延迟定时器或延迟定时器。
target
设备应将其工作频率设置为 freq 或略高于 freq 的值。如果 freq 高于任何可操作频率,则设置为最大值。在返回之前,目标函数应将 freq 设置为当前频率。“flags”参数的可能值已在上面通过“DEVFREQ_FLAG_*”宏进行解释。
get_dev_status
设备应向 devfreq 提供当前的性能状态。建议调频器不要直接使用此项。相反,建议调频器结合 devfreq.last_status 使用 devfreq_update_stats()。
get_cur_freq
设备应提供其当前的工作频率。
exit
一个可选的回调函数,当 devfreq 因错误或调用
devfreq_remove_device()
而移除 devfreq 对象时被调用。如果用户已在通知头注册了 devfreq->nb,则此时应注销它。freq_table
可选的频率列表,用于支持统计,且 freq_table 必须按升序生成。
max_state
freq_table 的大小。
is_cooling_device
一个不言自明的布尔值,赋予设备冷却效果属性。
-
struct devfreq_stats¶
devfreq 设备行为统计
定义:
struct devfreq_stats {
unsigned int total_trans;
unsigned int *trans_table;
u64 *time_in_state;
u64 last_update;
};
成员
total_trans
devfreq 转换次数。
trans_table
devfreq 转换统计。
time_in_state
devfreq 状态统计。
last_update
统计信息上次更新的时间。
-
struct devfreq¶
设备 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;
void *governor_data;
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;
struct devfreq_stats stats;
struct srcu_notifier_head transition_notifier_list;
struct thermal_cooling_device *cdev;
struct notifier_block nb_min;
struct notifier_block nb_max;
};
成员
node
列表节点 - 包含已注册的 devfreq 设备。
lock
用于保护 devfreq 访问的互斥锁。
dev
由 devfreq 类注册的设备。dev.parent 是使用 devfreq 的设备。
profile
设备特定的 devfreq 配置文件
governor
根据使用情况选择频率的方法。
opp_table
对 dev.parent 的 OPP 表的引用(如果存在)。
nb
用于通知 devfreq 对象重新评估可操作频率的通知块。devfreq 用户可以使用 devfreq.nb 注册到相应的通知器调用链。
work
用于负载监控的延迟工作。
freq_table
devfreq 驱动使用的当前频率表。
max_state
频率表中存在的条目数量。
previous_freq
先前配置的频率值。
last_status
devfreq 用户设备信息,性能统计
data
devfreq 驱动传递给调频器的数据,调频器不应修改它。
governor_data
调频器的私有数据,devfreq 核心不触及它。
user_min_freq_req
用户(通过 sysfs)发出的 PM QoS 最小频率请求
user_max_freq_req
用户(通过 sysfs)发出的 PM QoS 最大频率请求
scaling_min_freq
限制 OPP 接口请求的最小频率
scaling_max_freq
限制 OPP 接口请求的最大频率
stop_polling
设备的 devfreq 轮询状态。
suspend_freq
设备在挂起阶段设置的频率。
resume_freq
设备在恢复阶段设置的频率。
suspend_count
设备的挂起请求计数器。
stats
devfreq 设备行为统计
transition_notifier_list
DEVFREQ_TRANSITION_NOTIFIER 通知器的列表头。
cdev
如果 devfreq 具有冷却属性,则为冷却设备指针。
nb_min
DEV_PM_QOS_MIN_FREQUENCY 的通知块。
nb_max
DEV_PM_QOS_MAX_FREQUENCY 的通知块。
描述
该结构存储给定设备的 devfreq 信息。
请注意,当调频器访问 struct devfreq
的函数条目时(struct devfreq_governor 中定义的回调上下文除外),调频器应使用 struct devfreq
中的 struct mutex 锁来保护其访问。调频器也可以使用此互斥锁来保护其在 void *data
中的私有数据。
-
struct devfreq_simple_ondemand_data¶
传递给
struct devfreq
和 devfreq_add_device 的void *data
。
定义:
struct devfreq_simple_ondemand_data {
unsigned int upthreshold;
unsigned int downdifferential;
};
成员
upthreshold
如果负载超过此值,频率会跳升。指定 0 以使用默认值。有效值范围为 0 到 100。
downdifferential
如果负载低于 upthreshold - downdifferential,调频器可能会考虑降低频率。指定 0 以使用默认值。有效值范围为 0 到 100。必须满足 downdifferential < upthreshold。
描述
如果传递给调频器的 devfreq_simple_ondemand_data 指针为 NULL,调频器将使用默认值。
-
struct devfreq_passive_data¶
传递给
struct devfreq
和 devfreq_add_device 的void *data
。
定义:
struct devfreq_passive_data {
struct devfreq *parent;
int (*get_target_freq)(struct devfreq *this, unsigned long *freq);
enum devfreq_parent_dev_type parent_type;
struct devfreq *this;
struct notifier_block nb;
struct list_head cpu_data_list;
};
成员
parent
父设备的 devfreq 实例。
get_target_freq
可选回调,返回使用被动调频器的设备所需的运行频率。当被动调频器需要通过父 devfreq 设备的(除被动调频器之外的)其他调频器所设定的新频率来决定下一个频率时,会调用此函数。如果 devfreq 设备有特定的方法来决定下一个频率,则应使用此回调。
parent_type
设备的父类型。
this
本设备的 devfreq 实例。
nb
用于 DEVFREQ_TRANSITION_NOTIFIER 或 CPUFREQ_TRANSITION_NOTIFIER 列表的通知块。
cpu_data_list
所有 cpufreq_policy 的 CPU 频率数据列表。
描述
devfreq_passive_data 必须设置父设备的 devfreq 实例以及除被动调频器之外的其他调频器。但是,不需要初始化 'this' 和 'nb' 字段,因为 devfreq 核心会处理它们。
-
struct devfreq_event_dev¶
devfreq-event 设备
定义:
struct devfreq_event_dev {
struct list_head node;
struct device dev;
struct mutex lock;
u32 enable_count;
const struct devfreq_event_desc *desc;
};
成员
node
包含已注册的 devfreq-event 设备。
dev
由 devfreq-event 类注册的设备。dev.parent 是使用 devfreq-event 的设备。
lock
用于保护 devfreq-event 访问的互斥锁。
enable_count
enable 函数被调用的次数。
desc
devfreq-event 设备的描述。
描述
该结构包含 devfreq-event 设备信息。
-
struct devfreq_event_data¶
devfreq-event 数据
定义:
struct devfreq_event_data {
unsigned long load_count;
unsigned long total_count;
};
成员
load_count
devfreq-event 设备在给定周期内的负载计数。
total_count
devfreq-event 设备在给定周期内的总计数。每个计数可能表示一个时钟周期、一个时间单位(纳秒/微秒/等)或设备驱动程序希望的任何内容。通常,利用率是 load_count / total_count。
描述
该结构包含 devfreq-event 设备在轮询周期内的数据。
-
struct devfreq_event_ops¶
devfreq-event 设备的操作
定义:
struct devfreq_event_ops {
int (*enable)(struct devfreq_event_dev *edev);
int (*disable)(struct devfreq_event_dev *edev);
int (*reset)(struct devfreq_event_dev *edev);
int (*set_event)(struct devfreq_event_dev *edev);
int (*get_event)(struct devfreq_event_dev *edev, struct devfreq_event_data *edata);
};
成员
enable
启用 devfreq-event 设备。
disable
禁用 devfreq-event 设备。
reset
重置 devfreq-event 设备的所有设置。
set_event
为 devfreq-event 设备设置特定的事件类型。
get_event
获取具有特定事件类型的 devfreq-event 设备的结果。
描述
该结构包含可由 devfreq-event 设备驱动程序实现的 devfreq-event 设备操作。
-
struct devfreq_event_desc¶
devfreq-event 设备的描述符
定义:
struct devfreq_event_desc {
const char *name;
u32 event_type;
void *driver_data;
const struct devfreq_event_ops *ops;
};
成员
name
devfreq-event 设备的名称。
event_type
由驱动程序确定和使用的事件类型
driver_data
devfreq-event 驱动程序的私有数据。
ops
控制 devfreq-event 设备的操作。
描述
每个 devfreq-event 设备都由这个结构描述。该结构包含 devfreq-event 设备的各种数据。event_type 描述了将在寄存器中计数的内容。它可能选择计数,例如,读取请求、写入数据(字节)等。支持的完整类型列表位于特定头文件中:include/dt-bindings/pmu/。
-
void devfreq_get_freq_range(struct devfreq *devfreq, unsigned long *min_freq, unsigned long *max_freq)¶
获取当前频率范围
参数
struct devfreq *devfreq
devfreq 实例
unsigned long *min_freq
最小频率
unsigned long *max_freq
最大频率
描述
这考虑了所有约束。
参数
struct devfreq *devfreq
devfreq 实例
unsigned long freq
更新目标频率
参数
struct devfreq *devfreq
devfreq 实例。
unsigned long freq
父设备的新频率。此参数仅用于使用被动调频器的 devfreq 设备。
注意
- 在调用 devfreq_update_target 之前锁定 devfreq->lock。该函数
应该只由
update_devfreq()
和 devfreq 调频器使用。
参数
struct devfreq *devfreq
devfreq 实例。
注意
- 在调用 update_devfreq 之前锁定 devfreq->lock
此函数是为调频器导出的。
参数
struct devfreq *devfreq
devfreq 实例。
描述
启动 devfreq 设备负载监控的辅助函数。默认情况下,可延迟定时器用于负载监控。但用户可以使用 devfreq_dev_profile 中的“timer”类型更改此行为。在将设备添加到 devfreq 框架时,devfreq 调频器会响应 DEVFREQ_GOV_START 事件调用此函数。
参数
struct devfreq *devfreq
devfreq 实例。
描述
停止 devfreq 设备负载监控的辅助函数。当设备从 devfreq 框架中移除时,调频器会响应 DEVFREQ_GOV_STOP 事件调用此函数。
参数
struct devfreq *devfreq
devfreq 实例。
描述
挂起 devfreq 设备负载监控的辅助函数。当轮询间隔设置为零时,调频器会响应 DEVFREQ_GOV_SUSPEND 事件调用此函数。
注意
尽管此函数与 devfreq_monitor_stop()
相同,但为了提供收集转换统计信息的钩子,有意将其分开。
参数
struct devfreq *devfreq
devfreq 实例。
描述
恢复 devfreq 设备负载监控的辅助函数。当轮询间隔设置为非零时,调频器会响应 DEVFREQ_GOV_RESUME 事件调用此函数。
参数
struct devfreq *devfreq
devfreq 实例。
unsigned int *delay
要设置的新轮询间隔。
描述
设置新的负载监控轮询间隔的辅助函数。调频器会响应 DEVFREQ_GOV_UPDATE_INTERVAL 事件调用此函数。
-
struct devfreq *devfreq_add_device(struct device *dev, struct devfreq_dev_profile *profile, const char *governor_name, void *data)¶
为设备添加 devfreq 功能
参数
struct device *dev
要添加 devfreq 功能的设备。
struct devfreq_dev_profile *profile
运行 devfreq 的设备特定配置文件。
const char *governor_name
选择频率的策略名称。
void *data
devfreq 驱动传递给调频器的数据,调频器不应修改它。
-
struct devfreq *devm_devfreq_add_device(struct device *dev, struct devfreq_dev_profile *profile, const char *governor_name, void *data)¶
资源管理的
devfreq_add_device()
参数
struct device *dev
要添加 devfreq 功能的设备。
struct devfreq_dev_profile *profile
运行 devfreq 的设备特定配置文件。
const char *governor_name
选择频率的策略名称。
void *data
devfreq 驱动传递给调频器的数据,调频器不应修改它。
描述
此函数使用设备资源管理自动管理 devfreq 设备的内存,并简化 devfreq 设备内存的释放操作。
-
void devm_devfreq_remove_device(struct device *dev, struct devfreq *devfreq)¶
资源管理的
devfreq_remove_device()
参数
struct device *dev
从中移除 devfreq 功能的设备。
struct devfreq *devfreq
要移除的 devfreq 实例
参数
struct devfreq *devfreq
要挂起的 devfreq 实例
描述
此函数旨在由持有 devfreq 的设备驱动程序的 pm 回调(例如,runtime_suspend、suspend)调用。
参数
struct devfreq *devfreq
要恢复的 devfreq 实例
描述
此函数旨在由持有 devfreq 的设备驱动程序的 pm 回调(例如,runtime_resume、resume)调用。
-
int devfreq_add_governor(struct devfreq_governor *governor)¶
添加 devfreq 调频器
参数
struct devfreq_governor *governor
要添加的 devfreq 调频器
-
int devm_devfreq_add_governor(struct device *dev, struct devfreq_governor *governor)¶
添加 devfreq 调频器
参数
struct device *dev
添加 devfreq 调频器的设备
struct devfreq_governor *governor
要添加的 devfreq 调频器
描述
这是 devfreq_add_governor()
的资源管理变体。
-
int devfreq_remove_governor(struct devfreq_governor *governor)¶
从设备中移除 devfreq 功能。
参数
struct devfreq_governor *governor
要移除的 devfreq 调频器
-
struct dev_pm_opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq, u32 flags)¶
获取目标回调函数给定频率值的合适 OPP 的辅助函数。
参数
struct device *dev
devfreq 用户设备。(devfreq 的父级)
unsigned long *freq
传递给目标函数的频率
u32 flags
devfreq 框架传递的标志。
描述
调用者在使用返回的 OPP 后,需要调用 dev_pm_opp_put()。
-
int devfreq_register_opp_notifier(struct device *dev, struct devfreq *devfreq)¶
在 OPP 可用性发生任何变化时通知 devfreq 的辅助函数。
参数
struct device *dev
devfreq 用户设备。(devfreq 的父级)
struct devfreq *devfreq
devfreq 对象。
-
int devfreq_unregister_opp_notifier(struct device *dev, struct devfreq *devfreq)¶
停止在 OPP 可用性发生任何变化时通知 devfreq 的辅助函数。
参数
struct device *dev
devfreq 用户设备。(devfreq 的父级)
struct devfreq *devfreq
devfreq 对象。
描述
在 devfreq_dev_profile 的 exit() 回调中,如果使用了 devfreq_recommended_opp,则必须包含此项。
参数
struct device *dev
devfreq 用户设备。(devfreq 的父级)
struct devfreq *devfreq
devfreq 对象。
-
void devm_devfreq_unregister_opp_notifier(struct device *dev, struct devfreq *devfreq)¶
资源管理的 devfreq_unregister_opp_notifier()
参数
struct device *dev
devfreq 用户设备。(devfreq 的父级)
struct devfreq *devfreq
devfreq 对象。
-
int devfreq_register_notifier(struct devfreq *devfreq, struct notifier_block *nb, unsigned int list)¶
向 devfreq 注册驱动程序
参数
struct devfreq *devfreq
devfreq 对象。
struct notifier_block *nb
要注册的通知块。
unsigned int list
DEVFREQ_TRANSITION_NOTIFIER。
-
int devm_devfreq_register_notifier(struct device *dev, struct devfreq *devfreq, struct notifier_block *nb, unsigned int list)¶
参数
struct device *dev
devfreq 用户设备。(devfreq 的父级)
struct devfreq *devfreq
devfreq 对象。
struct notifier_block *nb
要注销的通知块。
unsigned int list
DEVFREQ_TRANSITION_NOTIFIER。
描述
-
void devm_devfreq_unregister_notifier(struct device *dev, struct devfreq *devfreq, struct notifier_block *nb, unsigned int list)¶
参数
struct device *dev
devfreq 用户设备。(devfreq 的父级)
struct devfreq *devfreq
devfreq 对象。
struct notifier_block *nb
要注销的通知块。
unsigned int list
DEVFREQ_TRANSITION_NOTIFIER。
描述
资源管理的 devfreq_unregister_notifier()
-
int devfreq_event_enable_edev(struct devfreq_event_dev *edev)¶
启用 devfreq-event 设备并增加 devfreq-event 设备的 enable_count。
参数
struct devfreq_event_dev *edev
devfreq-event 设备
描述
请注意,此函数会增加 enable_count 并启用 devfreq-event 设备。devfreq 设备在使用 devfreq-event 设备之前应先启用它。
-
int devfreq_event_disable_edev(struct devfreq_event_dev *edev)¶
禁用 devfreq-event 设备并减少 devfreq-event 设备的 enable_count。
参数
struct devfreq_event_dev *edev
devfreq-event 设备
描述
请注意,此函数会减少 enable_count 并禁用 devfreq-event 设备。devfreq-event 设备禁用后,devfreq 设备无法对其进行 get/set/reset 操作。
-
bool devfreq_event_is_enabled(struct devfreq_event_dev *edev)¶
检查 devfreq-event 设备是否已启用。
参数
struct devfreq_event_dev *edev
devfreq-event 设备
描述
请注意,此函数检查 devfreq-event 设备是否已启用。如果返回 true,则 devfreq-event 设备已启用。如果返回 false,则 devfreq-event 设备已禁用。
-
int devfreq_event_set_event(struct devfreq_event_dev *edev)¶
设置 devfreq-event 设备事件以启动。
参数
struct devfreq_event_dev *edev
devfreq-event 设备
描述
请注意,此函数将事件设置到 devfreq-event 设备以启动,从而获取可能是各种事件类型的事件数据。
-
int devfreq_event_get_event(struct devfreq_event_dev *edev, struct devfreq_event_data *edata)¶
从 devfreq-event 设备获取 {load|total}_count。
参数
struct devfreq_event_dev *edev
devfreq-event 设备
struct devfreq_event_data *edata
devfreq-event 设备的计算数据
描述
请注意,此函数在停止 devfreq-event 设备的整个序列进程后,从 devfreq-event 设备获取计算出的事件数据。
-
int devfreq_event_reset_event(struct devfreq_event_dev *edev)¶
重置 devfreq-event 设备的所有操作。
参数
struct devfreq_event_dev *edev
devfreq-event 设备
描述
请注意,此函数停止 devfreq-event 设备的所有操作,并重置当前事件数据,使 devfreq-event 设备进入初始状态。
-
struct devfreq_event_dev *devfreq_event_get_edev_by_phandle(struct device *dev, const char *phandle_name, int index)¶
从设备树获取 devfreq-event 设备。
参数
struct device *dev
指向给定设备的指针
const char *phandle_name
包含 phandle 值的属性名称
int index
devfreq-event 设备列表中的索引
描述
请注意,此函数返回 devfreq-event 设备的指针。
-
int devfreq_event_get_edev_count(struct device *dev, const char *phandle_name)¶
获取 devfreq-event 设备的数量
参数
struct device *dev
指向给定设备的指针
const char *phandle_name
包含 phandle 值的属性名称
描述
请注意,此函数返回 devfreq-event 设备的数量。
-
struct devfreq_event_dev *devfreq_event_add_edev(struct device *dev, struct devfreq_event_desc *desc)¶
添加新的 devfreq-event 设备。
参数
struct device *dev
拥有正在创建的 devfreq-event 设备的设备
struct devfreq_event_desc *desc
devfreq-event 设备的描述符,其中包含 devfreq-event 设备的基本数据。
描述
请注意,此函数将新的 devfreq-event 设备添加到 devfreq-event 类列表,并注册 devfreq-event 设备的设备。
-
int devfreq_event_remove_edev(struct devfreq_event_dev *edev)¶
移除已注册的 devfreq-event 设备。
参数
struct devfreq_event_dev *edev
devfreq-event 设备
描述
请注意,此函数移除已注册的 devfreq-event 设备。
-
struct devfreq_event_dev *devm_devfreq_event_add_edev(struct device *dev, struct devfreq_event_desc *desc)¶
资源管理的
devfreq_event_add_edev()
参数
struct device *dev
拥有正在创建的 devfreq-event 设备的设备
struct devfreq_event_desc *desc
devfreq-event 设备的描述符,其中包含 devfreq-event 设备的基本数据。
描述
请注意,此函数使用设备资源管理自动管理 devfreq-event 设备的内存,并简化 devfreq-event 设备内存的释放操作。
-
void devm_devfreq_event_remove_edev(struct device *dev, struct devfreq_event_dev *edev)¶
参数
struct device *dev
拥有正在创建的 devfreq-event 设备的设备
struct devfreq_event_dev *edev
devfreq-event 设备
描述
请注意,此函数使用设备资源管理自动管理 devfreq-event 设备的内存。