设备频率调节

简介

此框架为任意设备的动态电压和频率切换提供了一个标准的内核接口。

它通过 sysfs 文件公开用于调整频率的控件,这些文件与 cpufreq 子系统类似。

可以测量当前使用情况的设备可以通过调速器自动调整其频率。

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

设备在 total_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 高于任何可操作的频率,则设置为最大值。在返回之前,target 函数应将 freq 设置为当前频率。“flags”参数的可能值在上面用“DEVFREQ_FLAG_*”宏进行了解释。

get_dev_status

设备应向 devfreq 提供当前的性能状态。建议调速器不要直接使用此项。相反,建议调速器使用 devfreq_update_stats() 以及 devfreq.last_status。

get_cur_freq

设备应提供其当前运行的频率。

exit

当 devfreq 由于错误或从 devfreq_remove_device() 调用而删除 devfreq 对象时,调用的可选回调。如果用户在 notifier-head 中注册了 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 描述了将在寄存器中计数的内容。它可以选择计数例如读取请求、以字节为单位的写入数据等。完整的支持类型列表位于以下 specyfic 标头中: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

最大频率

描述

这考虑了所有约束。

int devfreq_update_status(struct devfreq *devfreq, unsigned long freq)

更新 devfreq 行为的统计信息

参数

struct devfreq *devfreq

devfreq 实例

unsigned long freq

更新目标频率

int devfreq_update_target(struct devfreq *devfreq, unsigned long freq)

重新评估设备并在最后阶段配置频率。

参数

struct devfreq *devfreq

devfreq 实例。

unsigned long freq

父设备的新频率。此参数仅用于使用被动调速器的 devfreq 设备。

注意

在调用 devfreq_update_target 之前锁定 devfreq->lock。此函数

应仅由 update_devfreq() 和 devfreq 调速器使用。

int update_devfreq(struct devfreq *devfreq)

重新评估设备并配置频率。

参数

struct devfreq *devfreq

devfreq 实例。

注意

在调用 update_devfreq 之前锁定 devfreq->lock

此函数导出给调速器使用。

void devfreq_monitor_start(struct devfreq *devfreq)

启动 devfreq 实例的负载监控

参数

struct devfreq *devfreq

devfreq 实例。

描述

用于启动 devfreq 设备负载监控的辅助函数。默认情况下,可延迟定时器用于负载监控。但是,用户可以使用 devfreq_dev_profile 中的 “timer” 类型更改此行为。当将设备添加到 devfreq 框架时,响应生成的 DEVFREQ_GOV_START 事件,devfreq 调速器将调用此函数。

void devfreq_monitor_stop(struct devfreq *devfreq)

停止 devfreq 实例的负载监控

参数

struct devfreq *devfreq

devfreq 实例。

描述

用于停止 devfreq 设备负载监控的辅助函数。当设备从 devfreq 框架中移除时,响应 DEVFREQ_GOV_STOP 事件从调速器调用的函数。

void devfreq_monitor_suspend(struct devfreq *devfreq)

暂停 devfreq 实例的负载监控

参数

struct devfreq *devfreq

devfreq 实例。

描述

用于暂停 devfreq 设备负载监控的辅助函数。响应 DEVFREQ_GOV_SUSPEND 事件或当轮询间隔设置为零时从调速器调用的函数。

注意

尽管此函数与 devfreq_monitor_stop() 相同,但有意保持分开,以便为收集转换统计信息提供钩子。

void devfreq_monitor_resume(struct devfreq *devfreq)

恢复 devfreq 实例的负载监控

参数

struct devfreq *devfreq

devfreq 实例。

描述

用于恢复 devfreq 设备负载监控的辅助函数。响应 DEVFREQ_GOV_RESUME 事件或当轮询间隔设置为非零时从调速器调用的函数。

void devfreq_update_interval(struct devfreq *devfreq, unsigned int *delay)

更新设备 devfreq 监控间隔

参数

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 驱动程序传递给调速器,调速器不应更改它。

int devfreq_remove_device(struct devfreq *devfreq)

从设备中移除 devfreq 功能。

参数

struct devfreq *devfreq

要移除的 devfreq 实例

描述

devfreq_add_device() 相反的操作。

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 实例

int devfreq_suspend_device(struct devfreq *devfreq)

挂起设备的 devfreq。

参数

struct devfreq *devfreq

要挂起的 devfreq 实例

描述

此函数旨在由持有 devfreq 的设备驱动程序的 pm 回调(例如,runtime_suspend,suspend)调用。

int devfreq_resume_device(struct devfreq *devfreq)

恢复设备的 devfreq。

参数

struct devfreq *devfreq

要恢复的 devfreq 实例

描述

此函数旨在由持有 devfreq 的设备驱动程序的 pm 回调(例如,runtime_resume,resume)调用。

int devfreq_add_governor(struct devfreq_governor *governor)

添加 devfreq governor

参数

struct devfreq_governor *governor

要添加的 devfreq governor

int devm_devfreq_add_governor(struct device *dev, struct devfreq_governor *governor)

添加 devfreq governor

参数

struct device *dev

添加 devfreq governor 的设备

struct devfreq_governor *governor

要添加的 devfreq governor

描述

这是 devfreq_add_governor() 的资源管理变体。

int devfreq_remove_governor(struct devfreq_governor *governor)

从设备中移除 devfreq 功能。

参数

struct devfreq_governor *governor

要移除的 devfreq governor

辅助函数,用于获取给定给目标回调的频率值的正确 OPP。

参数

struct device *dev

devfreq 用户设备。(devfreq 的父级)

unsigned long *freq

给定给目标函数的频率

u32 flags

从 devfreq 框架传递的标志。

描述

调用者在使用后需要调用 dev_pm_opp_put() 来释放返回的 OPP。

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,则必须包含此项。

int devm_devfreq_register_opp_notifier(struct device *dev, struct devfreq *devfreq)

资源管理的 devfreq_register_opp_notifier()

参数

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-event 设备应在 devfreq 设备使用之前启用。

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 设备将无法使用 devfreq-event 设备进行 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 事件设备。

参数

struct device *dev

拥有要创建的 devfreq 事件设备的设备

struct devfreq_event_desc *desc

devfreq 事件设备的描述符,其中包含 devfreq 事件设备的基本数据。

描述

请注意,此函数将新的 devfreq 事件设备添加到 devfreq 事件类列表,并注册 devfreq 事件设备的设备。

int devfreq_event_remove_edev(struct devfreq_event_dev *edev)

移除已注册的 devfreq 事件设备。

参数

struct devfreq_event_dev *edev

devfreq-event 设备

描述

请注意,此函数会移除已注册的 devfreq 事件设备。

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 事件设备的设备

struct devfreq_event_desc *desc

devfreq 事件设备的描述符,其中包含 devfreq 事件设备的基本数据。

描述

请注意,此函数使用设备资源管理自动管理 devfreq 事件设备的内存,并简化 devfreq 事件设备内存的释放操作。

void devm_devfreq_event_remove_edev(struct device *dev, struct devfreq_event_dev *edev)

资源管理的 devfreq_event_remove_edev()

参数

struct device *dev

拥有要创建的 devfreq 事件设备的设备

struct devfreq_event_dev *edev

devfreq-event 设备

描述

请注意,此函数使用设备资源管理自动管理 devfreq 事件设备的内存。