Linux 硬件监控内核 API¶
Guenter Roeck
介绍¶
本文档介绍了希望使用硬件监控框架的硬件监控驱动程序可以使用的 API。
本文档不描述硬件监控 (hwmon) 驱动程序或设备是什么。它也不描述用户空间可以用来与硬件监控设备通信的 API。如果您想了解这些,请阅读以下文件:sysfs 文件的命名和数据格式标准。
有关如何编写和改进 hwmon 驱动程序的其他指南,请阅读如何使您的补丁被 hwmon 子系统接受。
API¶
每个硬件监控驱动程序都必须包含 <linux/hwmon.h>,在某些情况下还必须包含 <linux/hwmon-sysfs.h>。linux/hwmon.h 声明以下注册/注销函数
struct device *
hwmon_device_register_with_info(struct device *dev,
const char *name, void *drvdata,
const struct hwmon_chip_info *info,
const struct attribute_group **extra_groups);
struct device *
devm_hwmon_device_register_with_info(struct device *dev,
const char *name,
void *drvdata,
const struct hwmon_chip_info *info,
const struct attribute_group **extra_groups);
void hwmon_device_unregister(struct device *dev);
char *hwmon_sanitize_name(const char *name);
char *devm_hwmon_sanitize_name(struct device *dev, const char *name);
hwmon_device_register_with_info 注册一个硬件监控设备。它在硬件监控核心中创建标准 sysfs 属性,让驱动程序专注于从芯片读取和写入,而不必为 sysfs 属性而烦恼。父设备参数和芯片参数都不能为 NULL。其参数在下面更详细地描述。
devm_hwmon_device_register_with_info 与 hwmon_device_register_with_info 类似。但是,它是设备管理的,这意味着 hwmon 设备不必由删除函数显式删除。
所有其他硬件监控设备注册函数都已弃用,并且不得在新驱动程序中使用。
hwmon_device_unregister 注销已注册的硬件监控设备。此函数的参数是指向已注册的硬件监控设备结构的指针。如果硬件监控设备是用 hwmon_device_register_with_info 注册的,则必须从驱动程序删除函数调用此函数。
所有支持的 hwmon 设备注册函数只接受有效的设备名称。包含无效字符(空格、“*”或“-”)的设备名称将被拒绝。“name”参数是强制性的。
如果驱动程序不使用静态设备名称(例如,它使用dev_name()
),因此不能确保名称仅包含有效字符,则可以使用 hwmon_sanitize_name。此便利函数将复制字符串并将任何无效字符替换为下划线。它将为新字符串分配内存,并且调用者有责任在删除设备时释放内存。
devm_hwmon_sanitize_name 是 hwmon_sanitize_name 的资源管理版本;内存将在设备删除时自动释放。
使用 devm_hwmon_device_register_with_info()¶
hwmon_device_register_with_info() 注册一个硬件监控设备。此函数的参数是
|
指向父设备的指针 |
const char *name |
设备名称 |
void *drvdata |
驱动程序私有数据 |
const struct hwmon_chip_info *info |
指向芯片描述的指针。 |
const struct attribute_group **extra_groups |
其他非标准 sysfs 属性组的以 NULL 结尾的列表。 |
此函数在成功时返回指向创建的硬件监控设备的指针,并在失败时返回负错误代码。
hwmon_chip_info 结构如下所示
struct hwmon_chip_info {
const struct hwmon_ops *ops;
const struct hwmon_channel_info * const *info;
};
它包含以下字段
- ops
指向设备操作的指针。
- info
设备通道描述符的以 NULL 结尾的列表。
hwmon 操作列表定义为
struct hwmon_ops {
umode_t (*is_visible)(const void *, enum hwmon_sensor_types type,
u32 attr, int);
int (*read)(struct device *, enum hwmon_sensor_types type,
u32 attr, int, long *);
int (*write)(struct device *, enum hwmon_sensor_types type,
u32 attr, int, long);
};
它定义了以下操作。
- is_visible
指向一个函数的指针,该函数返回每个受支持属性的文件模式。此函数是强制性的。
- read
指向一个函数的指针,用于从芯片读取值。此函数是可选的,但如果存在任何可读属性,则必须提供。
- write
指向一个函数的指针,用于将值写入芯片。此函数是可选的,但如果存在任何可写属性,则必须提供。
每个传感器通道都用 struct hwmon_channel_info 描述,其定义如下
struct hwmon_channel_info {
enum hwmon_sensor_types type;
u32 *config;
};
它包含以下字段
- type
硬件监控传感器类型。
支持的传感器类型为
hwmon_chip
一种虚拟传感器类型,用于描述不绑定到特定输入或输出的属性
hwmon_temp
温度传感器
hwmon_in
电压传感器
hwmon_curr
电流传感器
hwmon_power
功率传感器
hwmon_energy
能量传感器
hwmon_humidity
湿度传感器
hwmon_fan
风扇速度传感器
hwmon_pwm
PWM 控制
- config
指向给定类型每个传感器的配置值的以 0 结尾的列表的指针。每个值都是位值的组合,描述单个传感器支持的属性。
例如,这是 LM75 兼容传感器芯片的完整描述文件。该芯片有一个温度传感器。驱动程序希望向热子系统注册(HWMON_C_REGISTER_TZ),并且它支持 update_interval 属性(HWMON_C_UPDATE_INTERVAL)。该芯片支持读取温度(HWMON_T_INPUT),它有一个最大温度寄存器(HWMON_T_MAX)以及一个最大温度滞后寄存器(HWMON_T_MAX_HYST)
static const u32 lm75_chip_config[] = {
HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL,
0
};
static const struct hwmon_channel_info lm75_chip = {
.type = hwmon_chip,
.config = lm75_chip_config,
};
static const u32 lm75_temp_config[] = {
HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST,
0
};
static const struct hwmon_channel_info lm75_temp = {
.type = hwmon_temp,
.config = lm75_temp_config,
};
static const struct hwmon_channel_info * const lm75_info[] = {
&lm75_chip,
&lm75_temp,
NULL
};
The HWMON_CHANNEL_INFO() macro can and should be used when possible.
With this macro, the above example can be simplified to
static const struct hwmon_channel_info * const lm75_info[] = {
HWMON_CHANNEL_INFO(chip,
HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL),
HWMON_CHANNEL_INFO(temp,
HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST),
NULL
};
The remaining declarations are as follows.
static const struct hwmon_ops lm75_hwmon_ops = {
.is_visible = lm75_is_visible,
.read = lm75_read,
.write = lm75_write,
};
static const struct hwmon_chip_info lm75_chip_info = {
.ops = &lm75_hwmon_ops,
.info = lm75_info,
};
include/linux/hwmon.h 中定义了指示各个属性支持的位值的完整列表。定义前缀如下。
HWMON_C_xxxx |
芯片属性,用于 hwmon_chip。 |
HWMON_T_xxxx |
温度属性,用于 hwmon_temp。 |
HWMON_I_xxxx |
电压属性,用于 hwmon_in。 |
HWMON_C_xxxx |
电流属性,用于 hwmon_curr。请注意与芯片属性的前缀重叠。 |
HWMON_P_xxxx |
功率属性,用于 hwmon_power。 |
HWMON_E_xxxx |
能量属性,用于 hwmon_energy。 |
HWMON_H_xxxx |
湿度属性,用于 hwmon_humidity。 |
HWMON_F_xxxx |
风扇速度属性,用于 hwmon_fan。 |
HWMON_PWM_xxxx |
PWM 控制属性,用于 hwmon_pwm。 |
驱动程序回调函数¶
每个驱动程序都提供 is_visible、read 和 write 函数。这些函数的参数和返回值如下
umode_t is_visible_func(const void *data, enum hwmon_sensor_types type,
u32 attr, int channel)
- 参数
- data
指向设备私有数据结构的指针。
- type
传感器类型。
- attr
与特定属性关联的属性标识符。例如,HWMON_T_INPUT 的属性值将是 hwmon_temp_input。有关位字段到属性值的完整映射,请参见 include/linux/hwmon.h。
- channel
传感器通道号。
- 返回值
此属性的文件模式。通常,这将是 0(不会创建属性)、0444 或 0644。
int read_func(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long *val)
- 参数
- dev
指向硬件监控设备的指针。
- type
传感器类型。
- attr
与特定属性关联的属性标识符。例如,HWMON_T_INPUT 的属性值将是 hwmon_temp_input。有关完整映射,请参见 include/linux/hwmon.h。
- channel
传感器通道号。
- val
指向属性值的指针。
- 返回值
成功时为 0,否则为负错误号。
int write_func(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long val)
- 参数
- dev
指向硬件监控设备的指针。
- type
传感器类型。
- attr
与特定属性关联的属性标识符。例如,HWMON_T_INPUT 的属性值将是 hwmon_temp_input。有关完整映射,请参见 include/linux/hwmon.h。
- channel
传感器通道号。
- val
要写入芯片的值。
- 返回值
成功时为 0,否则为负错误号。
驱动程序提供的 sysfs 属性¶
在大多数情况下,驱动程序不需要提供 sysfs 属性,因为硬件监控核心会在内部创建这些属性。只需要提供额外的非标准 sysfs 属性。
头文件 linux/hwmon-sysfs.h 提供了许多有用的宏来声明和使用硬件监控 sysfs 属性。
在许多情况下,您可以使用现有的定义 DEVICE_ATTR 或其变体 DEVICE_ATTR_{RW,RO,WO} 来声明此类属性。如果属性没有其他上下文,这是可行的。但是,在许多情况下,会有其他信息,例如需要传递给 sysfs 属性处理函数的传感器索引。
SENSOR_DEVICE_ATTR 和 SENSOR_DEVICE_ATTR_2 可用于定义需要此类附加上下文信息的属性。SENSOR_DEVICE_ATTR 需要一个额外的参数,SENSOR_DEVICE_ATTR_2 需要两个。
如果标准属性权限和函数名称可行,则可以使用 SENSOR_DEVICE_ATTR 和 SENSOR_DEVICE_ATTR_2 的简化变体,并且应该使用它们。标准权限对于 SENSOR_DEVICE_ATTR[_2]_RW 为 0644,对于 SENSOR_DEVICE_ATTR[_2]_RO 为 0444,对于 SENSOR_DEVICE_ATTR[_2]_WO 为 0200。与 DEVICE_ATTR_{RW,RO,WO} 类似的 standard 函数,在提供的函数名称后附加 _show 和 _store。
SENSOR_DEVICE_ATTR 及其变体定义了一个 struct sensor_device_attribute 变量。此结构具有以下字段
struct sensor_device_attribute {
struct device_attribute dev_attr;
int index;
};
您可以使用 to_sensor_dev_attr 从属性读取或写入函数获取指向此结构的指针。其参数是属性所附加到的设备。
SENSOR_DEVICE_ATTR_2 及其变体定义了一个 struct sensor_device_attribute_2 变量,其定义如下
struct sensor_device_attribute_2 {
struct device_attribute dev_attr;
u8 index;
u8 nr;
};
使用 to_sensor_dev_attr_2 获取指向此结构的指针。其参数是属性所附加到的设备。