设备频率缩放

简介

该框架为任意设备上的动态电压和频率切换(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

最大频率

描述

这考虑了所有约束。

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 调频器会响应 DEVFREQ_GOV_START 事件调用此函数。

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 调频器

参数

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 调频器

获取目标回调函数给定频率值的合适 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,则必须包含此项。

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 设备在使用 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)

资源管理的 devfreq_event_remove_edev()

参数

struct device *dev

拥有正在创建的 devfreq-event 设备的设备

struct devfreq_event_dev *edev

devfreq-event 设备

描述

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