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() 注册一个硬件监控设备。此函数的参数是

struct device *dev

指向父设备的指针

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 获取指向此结构的指针。其参数是属性所附加到的设备。