设备驱动程序基础设施

基本设备驱动程序模型结构

struct subsys_interface

设备功能的接口

定义:

struct subsys_interface {
    const char *name;
    const struct bus_type *subsys;
    struct list_head node;
    int (*add_dev)(struct device *dev, struct subsys_interface *sif);
    void (*remove_dev)(struct device *dev, struct subsys_interface *sif);
};

成员

name

设备功能的名称

subsys

要附加到的设备的子系统

node

在子系统注册的函数列表

add_dev

设备连接到设备功能处理程序

remove_dev

设备连接到设备功能处理程序

描述

附加到子系统的简单接口。多个接口可以附加到子系统及其设备。与驱动程序不同,它们不独占声明或控制设备。接口通常表示子系统/设备类别的特定功能。

struct device_attribute

用于导出设备属性的接口。

定义:

struct device_attribute {
    struct attribute        attr;
    ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf);
    ssize_t (*store)(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
};

成员

attr

sysfs 属性定义。

show

显示处理程序。

store

存储处理程序。

struct dev_ext_attribute

带有额外上下文的导出的设备属性。

定义:

struct dev_ext_attribute {
    struct device_attribute attr;
    void *var;
};

成员

attr

导出的设备属性。

var

指向上下文的指针。

DEVICE_ATTR

DEVICE_ATTR (_name, _mode, _show, _store)

定义一个设备属性。

参数

_name

属性名称。

_mode

文件模式。

_show

显示处理程序。可选,但如果属性是可读的则必须。

_store

存储处理程序。可选,但如果属性是可写的则必须。

描述

用于定义 struct device_attribute 的便捷宏。

例如,DEVICE_ATTR(foo, 0644, foo_show, foo_store); 展开为

struct device_attribute dev_attr_foo = {
        .attr   = { .name = "foo", .mode = 0644 },
        .show   = foo_show,
        .store  = foo_store,
};
DEVICE_ATTR_PREALLOC

DEVICE_ATTR_PREALLOC (_name, _mode, _show, _store)

定义一个预先分配的设备属性。

参数

_name

属性名称。

_mode

文件模式。

_show

显示处理程序。可选,但如果属性是可读的则必须。

_store

存储处理程序。可选,但如果属性是可写的则必须。

描述

DEVICE_ATTR() 类似,但在 _mode 上设置 SYSFS_PREALLOC

DEVICE_ATTR_RW

DEVICE_ATTR_RW (_name)

定义一个读写设备属性。

参数

_name

属性名称。

描述

DEVICE_ATTR() 类似,但 _mode 为 0644,_show 为 <_name>_show,_store 为 <_name>_store。

DEVICE_ATTR_ADMIN_RW

DEVICE_ATTR_ADMIN_RW (_name)

定义一个仅管理员可读写的设备属性。

参数

_name

属性名称。

描述

DEVICE_ATTR_RW() 类似,但 _mode 为 0600。

DEVICE_ATTR_RO

DEVICE_ATTR_RO (_name)

定义一个可读的设备属性。

参数

_name

属性名称。

描述

DEVICE_ATTR() 类似,但 _mode 为 0444,_show 为 <_name>_show。

DEVICE_ATTR_ADMIN_RO

DEVICE_ATTR_ADMIN_RO (_name)

定义一个仅管理员可读的设备属性。

参数

_name

属性名称。

描述

DEVICE_ATTR_RO() 类似,但 _mode 为 0400。

DEVICE_ATTR_WO

DEVICE_ATTR_WO (_name)

定义一个仅管理员可写的设备属性。

参数

_name

属性名称。

描述

DEVICE_ATTR() 类似,但 _mode 为 0200,_store 为 <_name>_store。

DEVICE_ULONG_ATTR

DEVICE_ULONG_ATTR (_name, _mode, _var)

定义一个由无符号长整型支持的设备属性。

参数

_name

属性名称。

_mode

文件模式。

_var

无符号长整型的标识符。

描述

DEVICE_ATTR() 类似,但会自动提供 _show_store,以便从用户空间读取和写入属性会影响 _var

DEVICE_INT_ATTR

DEVICE_INT_ATTR (_name, _mode, _var)

定义一个由 int 支持的设备属性。

参数

_name

属性名称。

_mode

文件模式。

_var

int 的标识符。

描述

DEVICE_ULONG_ATTR() 类似,但 _var 是一个 int。

DEVICE_BOOL_ATTR

DEVICE_BOOL_ATTR (_name, _mode, _var)

定义一个由布尔值支持的设备属性。

参数

_name

属性名称。

_mode

文件模式。

_var

布尔值的标识符。

描述

DEVICE_ULONG_ATTR() 类似,但 _var 是一个布尔值。

DEVICE_STRING_ATTR_RO

DEVICE_STRING_ATTR_RO (_name, _mode, _var)

定义一个由 r/o 字符串支持的设备属性。

参数

_name

属性名称。

_mode

文件模式。

_var

字符串的标识符。

描述

DEVICE_ULONG_ATTR() 类似,但 _var 是一个字符串。由于字符串分配的长度未知,因此该属性必须是只读的。

devm_alloc_percpu

devm_alloc_percpu (dev, type)

资源托管的 alloc_percpu

参数

dev

为其分配每个 CPU 内存的设备

type

为其分配每个 CPU 内存的类型

描述

托管的 alloc_percpu。使用此函数分配的每个 CPU 内存会在驱动程序分离时自动释放。

返回

成功时指向已分配内存的指针,失败时为 NULL。

enum dl_dev_state

设备驱动程序存在跟踪信息。

常量

DL_DEV_NO_DRIVER

没有驱动程序附加到设备。

DL_DEV_PROBING

驱动程序正在探测。

DL_DEV_DRIVER_BOUND

驱动程序已绑定到设备。

DL_DEV_UNBINDING

驱动程序正在从设备解除绑定。

enum device_removable

设备是否可移动。设备被分类为可移动的标准由其子系统或总线确定。

常量

DEVICE_REMOVABLE_NOT_SUPPORTED

此设备不支持此属性(默认)。

DEVICE_REMOVABLE_UNKNOWN

设备位置未知。

DEVICE_FIXED

用户不可移动设备。

DEVICE_REMOVABLE

用户可移动设备。

与设备链接相关的设备数据。

定义:

struct dev_links_info {
    struct list_head suppliers;
    struct list_head consumers;
    struct list_head defer_sync;
    enum dl_dev_state status;
};

成员

suppliers

到供应商设备的链接列表。

consumers

到消费者设备的链接列表。

defer_sync

挂接到具有延迟 sync_state 的设备的全局列表。

status

驱动程序状态信息。

struct dev_msi_info

与 MSI 相关的设备数据

定义:

struct dev_msi_info {
#ifdef CONFIG_GENERIC_MSI_IRQ;
    struct irq_domain       *domain;
    struct msi_device_data  *data;
#endif;
};

成员

domain

与设备关联的 MSI 中断域

data

指向 MSI 设备数据的指针

enum device_physical_location_panel

描述设备连接点所在的系统外壳的面板表面。

常量

DEVICE_PANEL_TOP

设备连接点在顶部面板上。

DEVICE_PANEL_BOTTOM

设备连接点在底部面板上。

DEVICE_PANEL_LEFT

设备连接点在左侧面板上。

DEVICE_PANEL_RIGHT

设备连接点在右侧面板上。

DEVICE_PANEL_FRONT

设备连接点在前面板上。

DEVICE_PANEL_BACK

设备连接点在后面板上。

DEVICE_PANEL_UNKNOWN

设备连接点所在的面板未知。

enum device_physical_location_vertical_position

描述设备连接点在面板表面上的垂直位置。

常量

DEVICE_VERT_POS_UPPER

设备连接点在面板的上部。

DEVICE_VERT_POS_CENTER

设备连接点在面板的中心部分。

DEVICE_VERT_POS_LOWER

设备连接点在面板的下部。

enum device_physical_location_horizontal_position

描述设备连接点在面板表面上的水平位置。

常量

DEVICE_HORI_POS_LEFT

设备连接点在面板的左侧。

DEVICE_HORI_POS_CENTER

设备连接点在面板的中心部分。

DEVICE_HORI_POS_RIGHT

设备连接点在面板的右侧。

struct device_physical_location

与设备连接点的物理位置相关的设备数据。

定义:

struct device_physical_location {
    enum device_physical_location_panel panel;
    enum device_physical_location_vertical_position vertical_position;
    enum device_physical_location_horizontal_position horizontal_position;
    bool dock;
    bool lid;
};

成员

panel

设备连接点所在的系统外壳的面板表面。

vertical_position

设备连接点在面板内的垂直位置。

horizontal_position

设备连接点在面板内的水平位置。

dock

如果设备连接点位于扩展坞或端口复制器中,则设置此项。

lid

如果此设备连接点位于笔记本电脑系统的盖子上,则设置此项。

struct device

基本的设备结构

定义:

struct device {
    struct kobject kobj;
    struct device           *parent;
    struct device_private   *p;
    const char              *init_name;
    const struct device_type *type;
    const struct bus_type   *bus;
    struct device_driver *driver;
    void *platform_data;
    void *driver_data;
    struct mutex            mutex;
    struct dev_links_info   links;
    struct dev_pm_info      power;
    struct dev_pm_domain    *pm_domain;
#ifdef CONFIG_ENERGY_MODEL;
    struct em_perf_domain   *em_pd;
#endif;
#ifdef CONFIG_PINCTRL;
    struct dev_pin_info     *pins;
#endif;
    struct dev_msi_info     msi;
#ifdef CONFIG_ARCH_HAS_DMA_OPS;
    const struct dma_map_ops *dma_ops;
#endif;
    u64 *dma_mask;
    u64 coherent_dma_mask;
    u64 bus_dma_limit;
    const struct bus_dma_region *dma_range_map;
    struct device_dma_parameters *dma_parms;
    struct list_head        dma_pools;
#ifdef CONFIG_DMA_DECLARE_COHERENT;
    struct dma_coherent_mem *dma_mem;
#endif;
#ifdef CONFIG_DMA_CMA;
    struct cma *cma_area;
#endif;
#ifdef CONFIG_SWIOTLB;
    struct io_tlb_mem *dma_io_tlb_mem;
#endif;
#ifdef CONFIG_SWIOTLB_DYNAMIC;
    struct list_head dma_io_tlb_pools;
    spinlock_t dma_io_tlb_lock;
    bool dma_uses_io_tlb;
#endif;
    struct dev_archdata     archdata;
    struct device_node      *of_node;
    struct fwnode_handle    *fwnode;
#ifdef CONFIG_NUMA;
    int numa_node;
#endif;
    dev_t devt;
    u32 id;
    spinlock_t devres_lock;
    struct list_head        devres_head;
    const struct class      *class;
    const struct attribute_group **groups;
    void (*release)(struct device *dev);
    struct iommu_group      *iommu_group;
    struct dev_iommu        *iommu;
    struct device_physical_location *physical_location;
    enum device_removable   removable;
    bool offline_disabled:1;
    bool offline:1;
    bool of_node_reused:1;
    bool state_synced:1;
    bool can_match:1;
#if defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE) ||     defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU) ||     defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU_ALL);
    bool dma_coherent:1;
#endif;
#ifdef CONFIG_DMA_OPS_BYPASS;
    bool dma_ops_bypass : 1;
#endif;
#ifdef CONFIG_DMA_NEED_SYNC;
    bool dma_skip_sync:1;
#endif;
#ifdef CONFIG_IOMMU_DMA;
    bool dma_iommu:1;
#endif;
};

成员

kobj

一个顶级的抽象类,其他类由此派生。

parent

该设备的“父”设备,即它所连接的设备。在大多数情况下,父设备是某种总线或主机控制器。如果 parent 为 NULL,则该设备是顶层设备,这通常不是你想要的。

p

保存设备驱动程序核心部分的私有数据。有关详细信息,请参阅 struct device_private 的注释。

init_name

设备的初始名称。

type

设备类型。这标识了设备类型并携带特定于类型的信息。

bus

设备所在的总线类型。

driver

哪个驱动程序分配了这个

platform_data

特定于设备的平台数据。

driver_data

驱动程序特定信息的私有指针。

mutex

用于同步对其驱动程序的调用的互斥锁。

links

指向此设备的供应商和消费者的链接。

power

用于设备电源管理。有关详细信息,请参阅 设备电源管理基础

pm_domain

提供在系统挂起、休眠、系统恢复以及运行时 PM 转换期间执行的回调,以及子系统级和驱动程序级回调。

em_pd

设备的能量模型性能域

pins

用于设备引脚管理。有关详细信息,请参阅 PINCTRL(引脚控制)子系统

msi

MSI 相关数据

dma_ops

此设备的 DMA 映射操作。

dma_mask

DMA 掩码(如果设备支持 DMA)。

coherent_dma_mask

类似于 dma_mask,但用于 alloc_coherent 映射,因为并非所有硬件都支持 64 位地址用于一致分配的描述符。

bus_dma_limit

上游桥或总线的限制,该限制施加的 DMA 限制小于设备本身支持的限制。

dma_range_map

用于相对于 RAM 的 DMA 内存范围的映射

dma_parms

低级别驱动程序可以设置这些来告知 IOMMU 代码有关段限制的信息。

dma_pools

DMA 池(如果设备支持 DMA)。

dma_mem

内部用于一致内存覆盖。

cma_area

用于 DMA 分配的连续内存区域

dma_io_tlb_mem

软件 IO TLB 分配器。不供驱动程序使用。

dma_io_tlb_pools

瞬态 swiotlb 内存池的列表。

dma_io_tlb_lock

保护对活动池列表的更改。

dma_uses_io_tlb

如果设备使用了软件 IO TLB,则为 true

archdata

用于特定于架构的添加。

of_node

关联的设备树节点。

fwnode

平台固件提供的关联设备节点。

numa_node

此设备所靠近的 NUMA 节点。

devt

用于创建 sysfs “dev”。

id

设备实例

devres_lock

用于保护设备资源的自旋锁。

devres_head

设备的资源列表。

class

设备类别。

groups

可选的属性组。

release

在所有引用消失后释放设备的回调。这应由设备分配器(即发现该设备的总线驱动程序)设置。

iommu_group

设备所属的 IOMMU 组。

iommu

每个设备的通用 IOMMU 运行时数据

physical_location

描述设备连接点在系统外壳中的物理位置。

removable

设备是否可以从系统中移除。这应由发现该设备的子系统/总线驱动程序设置。

offline_disabled

如果设置,则设备永久在线。

offline

在成功调用总线类型的 .offline() 之后设置。

of_node_reused

如果设备树节点与祖先设备共享,则设置此项。

state_synced

此设备的硬件状态已通过调用驱动程序/总线 sync_state() 回调同步,以匹配此设备的软件状态。

can_match

该设备至少与一个驱动程序匹配过,或者它位于一个总线(如 AMBA)中,该总线在其他设备成功探测之前无法检查匹配的驱动程序。

dma_coherent

此特定设备是 DMA 一致的,即使该架构支持非一致的设备。

dma_ops_bypass

如果设置为 true,则对于流式 DMA 操作(->map_* / ->unmap_* / ->sync_*)会绕过 dma_ops,并且对于 DMA 分配(如果一致掩码足够大)也会绕过。此标志由来自 ->dma_supported 的 dma ops 实例管理。

dma_skip_sync

可以跳过一致缓冲区的 DMA 同步操作。

dma_iommu

设备正在使用默认的 IOMMU 实现进行 DMA,而不依赖于 dma_ops 结构。

示例

对于自定义板上的设备,如嵌入式设备中的典型设备

和基于 SOC 的硬件,Linux 通常使用 platform_data 来指向描述设备及其连接方式的特定于板的结构。这可以包括哪些端口可用、芯片变体、哪些 GPIO 引脚在哪些其他角色中起作用等等。这缩小了“板支持包”(BSP)并最大限度地减少了驱动程序中特定于板的 #ifdef。

描述

在最低级别,Linux 系统中的每个设备都由 struct device 的实例表示。设备结构包含设备模型核心对系统建模所需的信息。但是,大多数子系统会跟踪有关其托管设备的其他信息。因此,很少有设备仅由裸设备结构表示;相反,像 kobject 结构一样,该结构通常嵌入在设备的高级表示中。

设备链接表示。

定义:

struct device_link {
    struct device *supplier;
    struct list_head s_node;
    struct device *consumer;
    struct list_head c_node;
    struct device link_dev;
    enum device_link_state status;
    u32 flags;
    refcount_t rpm_active;
    struct kref kref;
    struct work_struct rm_work;
    bool supplier_preactivated;
};

成员

supplier

链接的供应商端的设备。

s_node

挂钩到供应商设备的消费者链接列表。

consumer

链接的消费者端的设备。

c_node

挂钩到消费者设备的供应商链接列表。

link_dev

用于在 sysfs 中公开链接详细信息的设备

status

链接的状态(关于驱动程序的存在)。

flags

链接标志。

rpm_active

消费者设备是否处于运行时 PM 活动状态。

kref

计算重复添加的同一链接。

rm_work

用于删除链接的工作结构。

supplier_preactivated

供应商在消费者探测之前已激活。

bool device_iommu_mapped(struct device *dev)

当设备的 DMA 由 IOMMU 转换时返回 true

参数

struct device *dev

要执行检查的设备

const char *dev_name(const struct device *dev)

返回设备的名称。

参数

const struct device *dev

要获取名称的设备。

返回

设备的 kobject 名称,如果不可用,则为其初始名称。

const char *dev_bus_name(const struct device *dev)

尽可能返回设备的总线/类名称

参数

const struct device *dev

要获取总线/类名称的struct device

描述

将返回设备所连接的总线/类的名称。如果未连接到总线/类,将返回空字符串。

device_lock_set_class

device_lock_set_class (dev, key)

当设备连接到驱动程序时,指定一个临时的锁类

参数

dev

要修改的设备

锁类键数据

描述

必须在已经持有 device_lock() 的情况下调用,例如从驱动程序的 ->probe() 中调用。请注意仅覆盖默认的 lockdep_no_validate 类。

device_lock_reset_class

device_lock_reset_class (dev)

将设备恢复到默认的 lockdep novalidate 状态

参数

dev

要修改的设备

描述

必须在已经持有 device_lock() 的情况下调用,例如从驱动程序的 ->remove() 中调用。

struct bus_type

设备的总线类型

定义:

struct bus_type {
    const char              *name;
    const char              *dev_name;
    const struct attribute_group **bus_groups;
    const struct attribute_group **dev_groups;
    const struct attribute_group **drv_groups;
    int (*match)(struct device *dev, const struct device_driver *drv);
    int (*uevent)(const struct device *dev, struct kobj_uevent_env *env);
    int (*probe)(struct device *dev);
    void (*sync_state)(struct device *dev);
    void (*remove)(struct device *dev);
    void (*shutdown)(struct device *dev);
    int (*online)(struct device *dev);
    int (*offline)(struct device *dev);
    int (*suspend)(struct device *dev, pm_message_t state);
    int (*resume)(struct device *dev);
    int (*num_vf)(struct device *dev);
    int (*dma_configure)(struct device *dev);
    void (*dma_cleanup)(struct device *dev);
    const struct dev_pm_ops *pm;
    bool need_parent_lock;
};

成员

name

总线的名称。

dev_name

用于子系统枚举设备,如 (“foo``u``”, dev->id)。

bus_groups

总线的默认属性。

dev_groups

总线上设备的默认属性。

drv_groups

总线上设备驱动程序的默认属性。

match

当为此总线添加新设备或驱动程序时可能会多次调用。如果给定的设备可以由给定的驱动程序处理,则应返回一个正值,否则返回零。如果无法确定驱动程序是否支持该设备,它也可能返回错误代码。如果返回 -EPROBE_DEFER,则会将设备排队以进行延迟探测。

uevent

当添加、删除设备或发生其他生成 uevent 的事件时调用,以添加环境变量。

probe

当为此总线添加新设备或驱动程序时调用,并回调特定驱动程序的探测以初始化匹配的设备。

sync_state

在所有链接到此设备(在 late_initcall 时存在)的状态跟踪消费者成功绑定到驱动程序之后,调用以将设备状态同步到软件状态。如果设备没有消费者,则此函数将在 late_initcall_sync 级别调用。如果设备有从不绑定到驱动程序的消费者,则此函数永远不会被调用,直到它们绑定为止。

remove

当从总线移除设备时调用。

shutdown

在关闭时调用以使设备静止。

online

调用以将设备重新置于在线状态(在离线后)。

offline

调用以使设备离线以进行热移除。可能会失败。

suspend

当该总线上的设备想要进入睡眠模式时调用。

resume

调用以将该总线上的设备从睡眠模式唤醒。

num_vf

调用以查找该总线上的设备支持多少个虚拟函数。

dma_configure

调用以设置该总线上的设备的 DMA 配置。

dma_cleanup

调用以清理该总线上的设备的 DMA 配置。

pm

此总线的电源管理操作,回调特定设备驱动程序的 pm-ops。

need_parent_lock

当探测或移除此总线上的设备时,设备核心应锁定该设备的父设备。

描述

总线是处理器和一个或多个设备之间的通道。就设备模型而言,所有设备都通过总线连接,即使它是内部的、虚拟的“平台”总线。总线可以相互插入。例如,USB 控制器通常是 PCI 设备。设备模型表示总线和它们控制的设备之间的实际连接。总线由 bus_type 结构表示。它包含名称、默认属性、总线的方法、PM 操作以及驱动程序核心的私有数据。

enum bus_notifier_event

已发生的总线通知器事件

常量

BUS_NOTIFY_ADD_DEVICE

设备已添加到此总线

BUS_NOTIFY_DEL_DEVICE

设备即将从此总线移除

BUS_NOTIFY_REMOVED_DEVICE

设备已成功从此总线移除

BUS_NOTIFY_BIND_DRIVER

驱动程序即将绑定到此总线上此设备

BUS_NOTIFY_BOUND_DRIVER

驱动程序已成功绑定到此总线上此设备

BUS_NOTIFY_UNBIND_DRIVER

驱动程序即将从此总线上此设备解除绑定

BUS_NOTIFY_UNBOUND_DRIVER

驱动程序已成功从此总线上此设备解除绑定

BUS_NOTIFY_DRIVER_NOT_BOUND

驱动程序未能绑定到此总线上此设备

描述

这些是当特定事件发生时传递给总线通知器的值。

请注意,总线通知器很可能会在驱动程序核心已经持有设备锁的情况下被调用,因此请在任何通知器回调中谨慎处理设备结构。

所有总线通知器都以目标 struct device * 作为参数调用。

struct class

设备类

定义:

struct class {
    const char              *name;
    const struct attribute_group    **class_groups;
    const struct attribute_group    **dev_groups;
    int (*dev_uevent)(const struct device *dev, struct kobj_uevent_env *env);
    char *(*devnode)(const struct device *dev, umode_t *mode);
    void (*class_release)(const struct class *class);
    void (*dev_release)(struct device *dev);
    int (*shutdown_pre)(struct device *dev);
    const struct kobj_ns_type_operations *ns_type;
    const void *(*namespace)(const struct device *dev);
    void (*get_ownership)(const struct device *dev, kuid_t *uid, kgid_t *gid);
    const struct dev_pm_ops *pm;
};

成员

name

类的名称。

class_groups

此类的默认属性。

dev_groups

属于该类的设备的默认属性。

dev_uevent

当设备添加、从此类移除或发生其他生成 uevent 的事件时调用,以添加环境变量。

devnode

回调以提供 devtmpfs。

class_release

调用以释放此类。

dev_release

调用以释放设备。

shutdown_pre

在驱动程序关闭之前在关闭时调用。

ns_type

回调,以便 sysfs 可以确定命名空间。

namespace

属于此类的设备的命名空间。

get_ownership

允许类指定属于该类的设备的 sysfs 目录的 uid/gid。通常与设备的命名空间相关。

pm

此类的默认设备电源管理操作。

描述

类是设备的更高层次的视图,它抽象出低级实现细节。驱动程序可能会看到 SCSI 磁盘或 ATA 磁盘,但在类级别,它们都只是磁盘。类允许用户空间根据设备的功能而不是它们的连接方式或工作方式来使用设备。

enum probe_type

设备驱动程序探测类型,用于尝试。设备驱动程序可以选择对其各自的探测例程进行特殊处理。这告诉核心预期和偏好。

常量

PROBE_DEFAULT_STRATEGY

由同步或异步探测都能正常工作的驱动程序使用。

PROBE_PREFER_ASYNCHRONOUS

对于启动系统来说探测顺序不是至关重要的“慢速”设备的驱动程序,可以选择异步执行其探测。

PROBE_FORCE_SYNCHRONOUS

使用此注释需要其探测例程与驱动程序和设备注册同步运行的驱动程序(除了 -EPROBE_DEFER 处理 - 重新探测总是最终异步完成)。

描述

请注意,最终目标是切换内核默认使用异步探测,因此用 PROBE_PREFER_ASYNCHRONOUS 注释驱动程序是一种临时措施,允许我们在验证其余驱动程序时加快启动过程。

struct device_driver

基本的设备驱动程序结构

定义:

struct device_driver {
    const char              *name;
    const struct bus_type   *bus;
    struct module           *owner;
    const char              *mod_name;
    bool suppress_bind_attrs;
    enum probe_type probe_type;
    const struct of_device_id       *of_match_table;
    const struct acpi_device_id     *acpi_match_table;
    int (*probe) (struct device *dev);
    void (*sync_state)(struct device *dev);
    int (*remove) (struct device *dev);
    void (*shutdown) (struct device *dev);
    int (*suspend) (struct device *dev, pm_message_t state);
    int (*resume) (struct device *dev);
    const struct attribute_group **groups;
    const struct attribute_group **dev_groups;
    const struct dev_pm_ops *pm;
    void (*coredump) (struct device *dev);
    struct driver_private *p;
};

成员

name

设备驱动程序的名称。

bus

此驱动程序的设备所属的总线。

owner

模块所有者。

mod_name

用于内置模块。

suppress_bind_attrs

禁用通过 sysfs 进行绑定/解除绑定。

probe_type

要使用的探测类型(同步或异步)。

of_match_table

开放固件表。

acpi_match_table

ACPI 匹配表。

probe

调用以查询特定设备的存在,此驱动程序是否可以使用它,并将驱动程序绑定到特定设备。

sync_state

在所有链接到此设备(在 late_initcall 时存在)的状态跟踪消费者成功绑定到驱动程序之后,调用以将设备状态同步到软件状态。如果设备没有消费者,则此函数将在 late_initcall_sync 级别调用。如果设备有从不绑定到驱动程序的消费者,则此函数永远不会被调用,直到它们绑定为止。

remove

当设备从系统中移除以解除设备与此驱动程序的绑定时调用。

shutdown

在关闭时调用以使设备静止。

suspend

调用以将设备置于睡眠模式。通常是低功耗状态。

resume

调用以将设备从睡眠模式唤醒。

groups

由驱动程序核心自动创建的默认属性。

dev_groups

一旦设备绑定到驱动程序,附加到设备实例的其他属性。

pm

与此驱动程序匹配的设备的电源管理操作。

coredump

当写入 sysfs 条目时调用。设备驱动程序应调用 dev_coredump API,从而导致 uevent。

p

驱动程序核心的私有数据,除了驱动程序核心之外,任何人都不能触摸此数据。

描述

设备驱动程序模型跟踪系统中已知的所有驱动程序。此跟踪的主要原因是使驱动程序核心能够将驱动程序与新设备匹配。但是,一旦驱动程序成为系统中的已知对象,许多其他事情就会变得可能。设备驱动程序可以导出独立于任何特定设备的信息和配置变量。

设备驱动程序基础

void driver_init(void)

初始化驱动程序模型。

参数

void

无参数

描述

调用驱动程序模型初始化函数以初始化其子系统。在 init/main.c 中早期调用。

struct device *driver_find_device_by_name(const struct device_driver *drv, const char *name)

设备迭代器,用于查找具有特定名称的特定设备。

参数

const struct device_driver *drv

正在迭代的驱动程序

const char *name

要匹配的设备名称

struct device *driver_find_device_by_of_node(const struct device_driver *drv, const struct device_node *np)

设备迭代器,用于通过 of_node 指针查找特定设备。

参数

const struct device_driver *drv

正在迭代的驱动程序

const struct device_node *np

要匹配的 of_node 指针。

struct device *driver_find_device_by_fwnode(struct device_driver *drv, const struct fwnode_handle *fwnode)

设备迭代器,用于通过 fwnode 指针查找特定设备。

参数

struct device_driver *drv

正在迭代的驱动程序

const struct fwnode_handle *fwnode

要匹配的 fwnode 指针。

struct device *driver_find_device_by_devt(const struct device_driver *drv, dev_t devt)

设备迭代器,用于通过 devt 查找特定设备。

参数

const struct device_driver *drv

正在迭代的驱动程序

dev_t devt

要匹配的 devt 指针。

struct device *driver_find_device_by_acpi_dev(const struct device_driver *drv, const struct acpi_device *adev)

设备迭代器,用于查找与 ACPI_COMPANION 设备匹配的特定设备。

参数

const struct device_driver *drv

正在迭代的驱动程序

const struct acpi_device *adev

要匹配的 ACPI_COMPANION 设备。

module_driver

module_driver (__driver, __register, __unregister, ...)

用于在模块初始化/退出时不做任何特殊处理的驱动程序的辅助宏。这消除了大量的样板代码。每个模块只能使用此宏一次,调用它会替换 module_init()module_exit()

参数

__driver

驱动程序名称

__register

此驱动程序类型的注册函数

__unregister

此驱动程序类型的注销函数

...

要传递给 __register 和 __unregister 的其他参数。

描述

使用此宏来构建用于注册驱动程序的特定于总线的宏,不要单独使用它。

builtin_driver

builtin_driver (__driver, __register, ...)

用于在初始化时不做任何特殊处理且没有退出的驱动程序的辅助宏。这消除了一些样板代码。每个驱动程序只能使用此宏一次,调用它会替换 device_initcall (或在某些情况下,替换旧的 __initcall)。这旨在与上面的 module_driver() 直接并行,但没有用于内置情况的 __exit 部分。

参数

__driver

驱动程序名称

__register

此驱动程序类型的注册函数

...

要传递给 __register 的其他参数

描述

使用此宏来构建用于注册驱动程序的特定于总线的宏,不要单独使用它。

int driver_set_override(struct device *dev, const char **override, const char *s, size_t len)

用于设置或清除驱动程序覆盖的辅助函数。

参数

struct device *dev

要更改的设备

const char **override

要更改的字符串的地址(例如 device->driver_override);内容将被释放并保存新分配的覆盖。

const char *s

以 NULL 结尾的字符串,强制匹配的新驱动程序名称,传递空字符串以清除它(“” 或 “n”,其中后者仅用于 sysfs 接口)。

size_t len

s 的长度

描述

用于在设备中设置或清除驱动程序覆盖的辅助函数,适用于驱动程序/总线代码分配 driver_override 字段的情况。

返回

成功时返回 0,失败时返回负错误代码。

int driver_for_each_device(struct device_driver *drv, struct device *start, void *data, int (*fn)(struct device*, void*))

用于绑定到驱动程序的设备的迭代器。

参数

struct device_driver *drv

正在迭代的驱动程序。

struct device *start

开始的设备

void *data

要传递给回调的数据。

int (*fn)(struct device *, void *)

为每个设备调用的函数。

描述

遍历 drv 的设备列表,为每个设备调用 fn

struct device *driver_find_device(const struct device_driver *drv, struct device *start, const void *data, device_match_t match)

用于查找特定设备的设备迭代器。

参数

const struct device_driver *drv

设备的驱动程序

struct device *start

开始的设备

const void *data

要传递给匹配函数的数据

device_match_t match

用于检查设备的回调函数

描述

这类似于上面的 driver_for_each_device() 函数,但它会返回一个对“找到”的设备的引用,以便后续使用,这由 match 回调确定。

如果设备不匹配,回调应返回 0;如果匹配,则返回非零值。 如果回调返回非零值,则此函数将返回给调用者,并且不会迭代任何其他设备。

int driver_create_file(const struct device_driver *drv, const struct driver_attribute *attr)

为驱动程序创建 sysfs 文件。

参数

const struct device_driver *drv

驱动程序。

const struct driver_attribute *attr

驱动程序属性描述符。

void driver_remove_file(const struct device_driver *drv, const struct driver_attribute *attr)

为驱动程序删除 sysfs 文件。

参数

const struct device_driver *drv

驱动程序。

const struct driver_attribute *attr

驱动程序属性描述符。

int driver_register(struct device_driver *drv)

向总线注册驱动程序

参数

struct device_driver *drv

要注册的驱动程序

描述

我们将大部分工作传递给 bus_add_driver() 调用,因为我们必须做的大部分事情都与总线结构有关。

void driver_unregister(struct device_driver *drv)

从系统中移除驱动程序。

参数

struct device_driver *drv

驱动程序。

描述

同样,我们将大部分工作传递给总线级别的调用。

等待正在进行的 devlink 删除作业终止

参数

void

无参数

在两个设备之间创建链接。

参数

struct device *consumer

链接的消费者端。

struct device *supplier

链接的提供者端。

u32 flags

链接标志。

返回

成功后,将返回一个 device_link 结构。

如果发生错误或标志设置无效,将返回 NULL。

描述

调用者负责使链接创建与运行时 PM 正确同步。 首先,设置 DL_FLAG_PM_RUNTIME 标志将导致运行时 PM 框架将链接考虑在内。 其次,如果除了设置 DL_FLAG_PM_RUNTIME 之外还设置了 DL_FLAG_RPM_ACTIVE 标志,则在创建链接时,供应商设备将被强制进入活动元状态并进行引用计数。 如果未设置 DL_FLAG_PM_RUNTIME,则将忽略 DL_FLAG_RPM_ACTIVE。

如果在 flags 中设置了 DL_FLAG_STATELESS,则此函数的调用者应借助 device_link_del()device_link_remove() 直接释放其返回的链接。

但是,如果未设置该标志,则此函数的调用者会将链接的管理完全移交给驱动程序核心,并且其返回值只能用于检查链接是否存在。 在这种情况下,可以使用 DL_FLAG_AUTOREMOVE_CONSUMER 和 DL_FLAG_AUTOREMOVE_SUPPLIER 设备链接标志来向驱动程序核心指示何时可以安全地删除链接。 即,在 flags 中设置其中一个标志,向驱动程序核心指示,在分别从其设备取消绑定消费者或供应商驱动程序后,此链接将不会被(此函数的给定调用者)使用,因此可以在该点删除该链接。 如果没有设置其中任何一个标志,则该链接将一直保留,直到它指向的其中一个设备(消费者或供应商)被注销。

此外,如果 flags 中未设置 DL_FLAG_STATELESS、DL_FLAG_AUTOREMOVE_CONSUMER 和 DL_FLAG_AUTOREMOVE_SUPPLIER(即,正在添加持久托管设备链接),则可以使用 DL_FLAG_AUTOPROBE_CONSUMER 标志来请求驱动程序核心在成功将驱动程序绑定到供应商设备后自动探测消费者驱动程序。

DL_FLAG_STATELESS 与 flags 中设置的 DL_FLAG_AUTOREMOVE_CONSUMER、DL_FLAG_AUTOREMOVE_SUPPLIER 或 DL_FLAG_AUTOPROBE_CONSUMER 之一的组合无效,将导致提前返回 NULL。 但是,如果在此函数被调用时,给定的 consumersupplier 对之间已经存在设备链接,则将返回现有链接,而与其当前类型和状态无关(然后可以修改链接的标志)。 然后,此函数的调用者应将链接视为刚创建的链接,因此(尤其)如果 flags 中传递了 DL_FLAG_STATELESS,则在不再需要时需要显式释放该链接(如上所述)。

链接创建的一个副作用是通过将消费者设备和所有依赖于它的设备移动到这些列表的末尾来重新排序 dpm_list 和 devices_kset 列表(这不会发生在调用此函数时尚未注册的设备上)。

调用此函数时,要求供应商设备已注册,否则将返回 NULL。 但是,不需要注册消费者设备。

删除两个设备之间的无状态链接。

参数

struct device_link *link

要删除的设备链接。

描述

调用者必须确保此函数与运行时 PM 正确同步。 如果该链接被添加多次,则需要多次删除。 需要注意热插拔设备:它们的链接在删除时会被清除,并且不再允许调用 device_link_del()

删除两个设备之间的无状态链接。

参数

void *consumer

链接的消费者端。

struct device *supplier

链接的提供者端。

描述

调用者必须确保此函数与运行时 PM 正确同步。

const char *dev_driver_string(const struct device *dev)

返回设备驱动程序的名称(如果可能)

参数

const struct device *dev

要获取名称的struct device

描述

如果设备绑定到驱动程序,则会返回设备的驱动程序名称。 如果设备未绑定到驱动程序,则会返回它所连接的总线的名称。 如果它也没有连接到总线,则会返回一个空字符串。

int devm_device_add_group(struct device *dev, const struct attribute_group *grp)

给定一个设备,创建一个托管的属性组

参数

struct device *dev

要为其创建组的设备

const struct attribute_group *grp

要创建的属性组

描述

此函数首次创建一个组。如果正在创建的任何属性文件已存在,它将明确发出警告并报错。

成功返回 0,失败返回错误代码。

int device_create_file(struct device *dev, const struct device_attribute *attr)

为设备创建 sysfs 属性文件。

参数

struct device *dev

设备。

const struct device_attribute *attr

设备属性描述符。

void device_remove_file(struct device *dev, const struct device_attribute *attr)

删除 sysfs 属性文件。

参数

struct device *dev

设备。

const struct device_attribute *attr

设备属性描述符。

bool device_remove_file_self(struct device *dev, const struct device_attribute *attr)

从其自身的方法中删除 sysfs 属性文件。

参数

struct device *dev

设备。

const struct device_attribute *attr

设备属性描述符。

描述

有关详细信息,请参阅 kernfs_remove_self()。

int device_create_bin_file(struct device *dev, const struct bin_attribute *attr)

为设备创建 sysfs 二进制属性文件。

参数

struct device *dev

设备。

const struct bin_attribute *attr

设备二进制属性描述符。

void device_remove_bin_file(struct device *dev, const struct bin_attribute *attr)

删除 sysfs 二进制属性文件

参数

struct device *dev

设备。

const struct bin_attribute *attr

设备二进制属性描述符。

void device_initialize(struct device *dev)

初始化设备结构。

参数

struct device *dev

设备。

描述

这通过初始化其字段来准备设备以供其他层使用。它是 device_register() 的前半部分(如果由该函数调用),尽管也可以单独调用,因此可以使用 dev 的字段。特别是,在调用此函数后,get_device()/put_device() 可用于 dev 的引用计数。

dev 中的所有字段必须由调用者初始化为 0,但明确设置为某些其他值的字段除外。最简单的方法是使用 kzalloc() 来分配包含 dev 的结构。

注意

一旦调用此函数,请使用 put_device() 来放弃您的引用,而不是直接释放 dev

int dev_set_name(struct device *dev, const char *fmt, ...)

设置设备名称

参数

struct device *dev

设备

const char *fmt

设备名称的格式字符串

...

可变参数

int device_add(struct device *dev)

将设备添加到设备层次结构中。

参数

struct device *dev

设备。

描述

这是 device_register() 的第 2 部分,尽管如果已单独调用 device_initialize(),则可以单独调用。

这通过 kobject_add()dev 添加到 kobject 层次结构中,将其添加到设备的全局列表和兄弟列表,然后将其添加到驱动程序模型的其他相关子系统中。

不要对任何设备结构多次调用此例程或 device_register()。驱动程序模型核心并非设计为与取消注册然后又恢复活动的设备一起工作。(除此之外,很难保证已放弃对 dev 以前版本的所有引用。)请分配并注册一个全新的 struct device

经验法则是:如果 device_add() 成功,则当您想要摆脱它时,应调用 device_del()。如果 device_add() 没有成功,则仅使用 put_device() 来减少引用计数。

注意

即使它返回错误,也 _永远不要_ 在调用此函数后直接释放 dev!始终使用 put_device() 来放弃您的引用。

int device_register(struct device *dev)

向系统注册设备。

参数

struct device *dev

指向设备结构的指针

描述

这分为两个清晰的步骤 - 初始化设备并将其添加到系统中。这两个步骤可以单独调用,但这是最简单和最常见的方法。即,如果您在将设备添加到层次结构之前有明确定义的需求来使用和引用计数该设备,则应仅单独调用两个辅助函数。

有关详细信息,请参阅 device_initialize()device_add() 的 kerneldoc。

注意

即使它返回错误,也 _永远不要_ 在调用此函数后直接释放 dev!始终使用 put_device() 来放弃此函数中初始化的引用。

struct device *get_device(struct device *dev)

增加设备的引用计数。

参数

struct device *dev

设备。

描述

这只是简单地将调用转发到 kobject_get(),尽管我们会注意处理传入 NULL 指针的情况。

void put_device(struct device *dev)

减少引用计数。

参数

struct device *dev

有问题的设备。

void device_del(struct device *dev)

从系统中删除设备。

参数

struct device *dev

设备。

描述

这是设备注销序列的第一部分。它从我们在此处控制的列表中删除设备,使其从 device_add() 中添加的其他驱动程序模型子系统中删除,并将其从 kobject 层次结构中删除。

注意

只有在手动调用了 device_add() 的情况下才应手动调用此函数。

void device_unregister(struct device *dev)

从系统中注销设备。

参数

struct device *dev

设备即将消失。

描述

我们像 device_register() 一样分两部分执行此操作。首先,我们使用 device_del() 将其从所有子系统中删除,然后通过 put_device() 减少引用计数。如果这是最终的引用计数,则会通过上面的 device_release() 清理设备。否则,该结构将一直存在,直到最终对设备的引用被删除。

int device_for_each_child(struct device *parent, void *data, int (*fn)(struct device *dev, void *data))

设备子项迭代器。

参数

struct device *parent

struct device

void *data

回调的数据。

int (*fn)(struct device *dev, void *data)

为每个设备调用的函数。

描述

迭代 parent 的子设备,并为每个设备调用 fn,并传递 data

我们每次都会检查 fn 的返回值。如果它返回除 0 之外的任何值,我们将中断并返回该值。

int device_for_each_child_reverse(struct device *parent, void *data, int (*fn)(struct device *dev, void *data))

按相反顺序的设备子项迭代器。

参数

struct device *parent

struct device

void *data

回调的数据。

int (*fn)(struct device *dev, void *data)

为每个设备调用的函数。

描述

迭代 parent 的子设备,并为每个设备调用 fn,并传递 data

我们每次都会检查 fn 的返回值。如果它返回除 0 之外的任何值,我们将中断并返回该值。

int device_for_each_child_reverse_from(struct device *parent, struct device *from, const void *data, int (*fn)(struct device*, const void*))

按相反顺序的设备子项迭代器。

参数

struct device *parent

struct device

struct device *from

子列表中的可选起始点

const void *data

回调的数据。

int (*fn)(struct device *, const void *)

为每个设备调用的函数。

描述

迭代 parent 的子设备,从 from 开始,并为每个设备调用 fn,并传递 data。当 from 为 NULL 时,此辅助函数与 device_for_each_child_reverse() 完全相同。

每次迭代都会检查 fn。如果它返回除 0 之外的任何值,则迭代停止,并将该值返回给 device_for_each_child_reverse_from() 的调用者;

struct device *device_find_child(struct device *parent, void *data, int (*match)(struct device *dev, void *data))

用于查找特定设备的设备迭代器。

参数

struct device *parent

struct device

void *data

要传递给匹配函数的数据

int (*match)(struct device *dev, void *data)

用于检查设备的回调函数

描述

这类似于上面的 device_for_each_child() 函数,但它返回一个对 “已找到” 的设备的引用,供以后使用,由 match 回调确定。

如果设备不匹配,回调应返回 0,如果匹配,则应返回非零值。如果回调返回非零值并且可以获取对当前设备的引用,则此函数将返回给调用者,并且不会迭代任何其他设备。

注意

使用后,您需要使用 put_device() 来释放引用。

struct device *device_find_child_by_name(struct device *parent, const char *name)

用于查找子设备的设备迭代器。

参数

struct device *parent

struct device

const char *name

子设备的名称

描述

这类似于上面的 device_find_child() 函数,但它返回对具有名称 name 的设备的引用。

注意

使用后,您需要使用 put_device() 来释放引用。

struct device *device_find_any_child(struct device *parent)

用于查找子设备(如果有)的设备迭代器。

参数

struct device *parent

struct device

描述

这类似于上面的 device_find_child() 函数,但它返回对子设备(如果有)的引用。

注意

使用后,您需要使用 put_device() 来释放引用。

struct device *__root_device_register(const char *name, struct module *owner)

分配并注册一个根设备

参数

const char *name

根设备名称

struct module *owner

根设备的所属模块,通常是 THIS_MODULE

描述

此函数分配一个根设备,并使用 device_register() 注册它。 为了释放返回的设备,请使用 root_device_unregister()

根设备是虚拟设备,允许其他设备分组在 /sys/devices 下。使用此函数分配一个根设备,然后将其用作应显示在 /sys/devices/{name} 下的任何设备的父设备。

/sys/devices/{name} 目录还将包含一个指向 sysfs 中 owner 目录的 ‘module’ 符号链接。

成功时返回 struct device 指针,出错时返回 ERR_PTR()

注意

您可能需要使用 root_device_register()。

void root_device_unregister(struct device *dev)

注销并释放根设备

参数

struct device *dev

要释放的设备

描述

此函数注销并清理由 root_device_register() 创建的设备。

struct device *device_create(const struct class *class, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...)

创建设备并将其注册到 sysfs

参数

const struct class *class

指向此设备应注册到的 struct class 的指针

struct device *parent

指向此新设备的父 struct device(如果有)的指针

dev_t devt

要添加的字符设备的 dev_t

void *drvdata

要添加到设备以进行回调的数据

const char *fmt

设备的名称字符串

...

可变参数

描述

字符设备类可以使用此函数。将在 sysfs 中创建一个 struct device,并注册到指定的类。

如果 dev_t 不为 0,0,则将创建一个 “dev” 文件,显示设备的 dev_t。如果传入指向父 struct device 的指针,则新创建的 struct device 将成为 sysfs 中该设备的子设备。指向 struct device 的指针将从调用中返回。可以使用此指针创建可能需要的任何其他 sysfs 文件。

成功时返回 struct device 指针,出错时返回 ERR_PTR()

struct device *device_create_with_groups(const struct class *class, struct device *parent, dev_t devt, void *drvdata, const struct attribute_group **groups, const char *fmt, ...)

创建设备并将其注册到 sysfs

参数

const struct class *class

指向此设备应注册到的 struct class 的指针

struct device *parent

指向此新设备的父 struct device(如果有)的指针

dev_t devt

要添加的字符设备的 dev_t

void *drvdata

要添加到设备以进行回调的数据

const struct attribute_group **groups

要创建的属性组的 NULL 终止列表

const char *fmt

设备的名称字符串

...

可变参数

描述

字符设备类可以使用此函数。将在 sysfs 中创建一个 struct device,并注册到指定的类。还将自动创建在 groups 参数中指定的其他属性。

如果 dev_t 不为 0,0,则将创建一个 “dev” 文件,显示设备的 dev_t。如果传入指向父 struct device 的指针,则新创建的 struct device 将成为 sysfs 中该设备的子设备。指向 struct device 的指针将从调用中返回。可以使用此指针创建可能需要的任何其他 sysfs 文件。

成功时返回 struct device 指针,出错时返回 ERR_PTR()

void device_destroy(const struct class *class, dev_t devt)

删除使用 device_create() 创建的设备

参数

const struct class *class

指向此设备注册到的 struct class 的指针

dev_t devt

先前注册的设备的 dev_t

描述

此调用注销并清理通过调用 device_create() 创建的设备。

int device_rename(struct device *dev, const char *new_name)

重命名设备

参数

struct device *dev

指向要重命名的 struct device 的指针

const char *new_name

设备的新名称

描述

调用方有责任在同一设备上两次不同的 device_rename 调用之间提供互斥,以确保 new_name 有效,并且不会与其他设备冲突。

但是,如果您正在编写新代码,请不要调用此函数。 Kay Sievers 的以下文字提供了一些见解

在许多级别重命名设备都是竞争的,符号链接和其他内容不是原子替换的,并且您会得到一个“移动” uevent,但是将该事件连接到旧设备和新设备并不容易。 设备节点根本不会重命名,内核现在甚至不支持。

同时,在重命名期间,你的目标名称可能会被另一个驱动程序占用,从而产生冲突。或者旧名称在你重命名后立即被占用——那么在你看到“移动”事件之前,你就会收到同一 DEVPATH 的事件。这简直是一团糟,任何新的东西都不应该依赖内核设备重命名。除此之外,它现在甚至没有为(驱动核心方面非常简单的)网络设备以外的其他东西实现。

在注册任何内容之前,在驱动程序中创建一个“真实”名称,或者添加一些其他属性供用户空间查找设备,或者使用 udev 添加符号链接——但永远不要在以后重命名内核设备,那完全是一团糟。我们甚至不想深入研究并尝试在核心中实现缺失的部分。我们真的有其他部分需要在驱动程序核心中修复。:)

注意

鉴于某些子系统(网络和 InfiniBand)使用此函数,并且没有立即更改的计划,我们不能假设或要求完全不调用此函数。

int device_move(struct device *dev, struct device *new_parent, enum dpm_order dpm_order)

将设备移动到新的父设备

参数

struct device *dev

要移动的 struct device 的指针

struct device *new_parent

设备的新父设备(可以为 NULL)

enum dpm_order dpm_order

如何重新排序 dpm_list

int device_change_owner(struct device *dev, kuid_t kuid, kgid_t kgid)

更改现有设备的所有者。

参数

struct device *dev

设备。

kuid_t kuid

新所有者的 kuid

kgid_t kgid

新所有者的 kgid

描述

这将 dev 及其对应的 sysfs 条目的所有者更改为 kuid/kgid。此函数与通过驱动程序核心添加 dev 的方式非常相似。

成功返回 0,失败返回错误代码。

int dev_err_probe(const struct device *dev, int err, const char *fmt, ...)

探测错误检查和日志助手

参数

const struct device *dev

指向 struct device 的指针

int err

要测试的错误值

const char *fmt

printf 风格的格式字符串

...

格式字符串中指定的参数

描述

此助手实现了探测函数中用于错误检查的常见模式:如果错误值为 -EPROBE_DEFER,则打印调试或错误消息,并将错误向上传播。 如果是 -EPROBE_DEFER,它还会设置延迟探测原因,该原因稍后可以通过读取 devices_deferred debugfs 属性来检查。它替换了以下代码序列

if (err != -EPROBE_DEFER)
        dev_err(dev, ...);
else
        dev_dbg(dev, ...);
return err;

return dev_err_probe(dev, err, ...);

即使已知 err 永远不会是 -EPROBE_DEFER,在你的探测函数中使用此助手也完全没问题。与普通的 dev_err() 相比,好处是错误代码的标准化格式,它是以符号方式发出的(即,你会得到“EAGAIN”而不是“-35”),并且返回错误代码允许更紧凑的错误路径。

返回 err

int dev_warn_probe(const struct device *dev, int err, const char *fmt, ...)

探测错误检查和日志助手

参数

const struct device *dev

指向 struct device 的指针

int err

要测试的错误值

const char *fmt

printf 风格的格式字符串

...

格式字符串中指定的参数

描述

此助手实现了探测函数中用于错误检查的常见模式:如果错误值为 -EPROBE_DEFER,则打印调试或警告消息,并将错误向上传播。 如果是 -EPROBE_DEFER,它还会设置延迟探测原因,该原因稍后可以通过读取 devices_deferred debugfs 属性来检查。它替换了以下代码序列

if (err != -EPROBE_DEFER)
        dev_warn(dev, ...);
else
        dev_dbg(dev, ...);
return err;

return dev_warn_probe(dev, err, ...);

即使已知 err 永远不会是 -EPROBE_DEFER,在你的探测函数中使用此助手也完全没问题。与普通的 dev_warn() 相比,好处是错误代码的标准化格式,它是以符号方式发出的(即,你会得到“EAGAIN”而不是“-35”),并且返回错误代码允许更紧凑的错误路径。

返回 err

void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode)

更改给定设备的主固件节点。

参数

struct device *dev

要处理的设备。

struct fwnode_handle *fwnode

设备新的主固件节点。

描述

将设备的固件节点指针设置为 fwnode,但如果存在设备的辅助固件节点,则保留它。

有效的 fwnode 情况是
  • 主要 -> 次要 -> -ENODEV

  • 主要 -> NULL

  • 次要 -> -ENODEV

  • NULL

void set_secondary_fwnode(struct device *dev, struct fwnode_handle *fwnode)

更改给定设备的辅助固件节点。

参数

struct device *dev

要处理的设备。

struct fwnode_handle *fwnode

设备新的辅助固件节点。

描述

如果存在设备的主固件节点,则将其辅助指针设置为 fwnode。 否则,将设备的固件节点指针设置为 fwnode

void device_set_of_node_from_dev(struct device *dev, const struct device *dev2)

重用另一个设备的设备树节点

参数

struct device *dev

要设置其设备树节点的设备

const struct device *dev2

正在重用其设备树节点的设备

描述

在首先删除对旧节点持有的任何引用之后,获取对新设备树节点的另一个引用。

void register_syscore_ops(struct syscore_ops *ops)

注册一组系统核心操作。

参数

struct syscore_ops *ops

要注册的系统核心操作。

void unregister_syscore_ops(struct syscore_ops *ops)

注销一组系统核心操作。

参数

struct syscore_ops *ops

要注销的系统核心操作。

int syscore_suspend(void)

执行所有已注册的系统核心挂起回调。

参数

void

无参数

描述

此函数在单个 CPU 联机且中断禁用的情况下执行。

void syscore_resume(void)

执行所有已注册的系统核心恢复回调。

参数

void

无参数

描述

此函数在单个 CPU 联机且中断禁用的情况下执行。

struct device *class_find_device_by_name(const struct class *class, const char *name)

设备迭代器,用于查找具有特定名称的特定设备。

参数

const struct class *class

类类型

const char *name

要匹配的设备名称

struct device *class_find_device_by_of_node(const struct class *class, const struct device_node *np)

用于定位与 of_node 匹配的特定设备的设备迭代器。

参数

const struct class *class

类类型

const struct device_node *np

要匹配的设备的 of_node。

struct device *class_find_device_by_fwnode(const struct class *class, const struct fwnode_handle *fwnode)

用于定位与 fwnode 匹配的特定设备的设备迭代器。

参数

const struct class *class

类类型

const struct fwnode_handle *fwnode

要匹配的设备的 fwnode。

struct device *class_find_device_by_devt(const struct class *class, dev_t devt)

用于定位与设备类型匹配的特定设备的设备迭代器。

参数

const struct class *class

类类型

dev_t devt

要匹配的设备的设备类型。

struct device *class_find_device_by_acpi_dev(const struct class *class, const struct acpi_device *adev)

设备迭代器,用于查找与 ACPI_COMPANION 设备匹配的特定设备。

参数

const struct class *class

类类型

const struct acpi_device *adev

要匹配的 ACPI_COMPANION 设备。

struct class *class_create(const char *name)

创建一个 struct class 结构体

参数

const char *name

指向此类的名称字符串的指针。

描述

这用于创建一个 struct class 指针,该指针随后可在调用 device_create() 中使用。

成功时返回 struct class 指针,或在错误时返回 ERR_PTR()

请注意,此处创建的指针在完成后需要通过调用 class_destroy() 来销毁。

void class_destroy(const struct class *cls)

销毁一个 struct class 结构体

参数

const struct class *cls

指向要销毁的 struct class 的指针

描述

请注意,要销毁的指针必须是通过调用 class_create() 创建的。

void class_dev_iter_init(struct class_dev_iter *iter, const struct class *class, const struct device *start, const struct device_type *type)

初始化类设备迭代器

参数

struct class_dev_iter *iter

要初始化的类迭代器

const struct class *class

我们要迭代的类

const struct device *start

开始迭代的设备(如果有)

const struct device_type *type

要迭代的设备的 device_type,NULL 表示所有

描述

初始化类迭代器 iter,使其迭代 class 的设备。如果设置了 start,则列表迭代将从此处开始,否则如果为 NULL,则迭代从列表的开头开始。

struct device *class_dev_iter_next(struct class_dev_iter *iter)

迭代到下一个设备

参数

struct class_dev_iter *iter

要继续的类迭代器

描述

iter 移到下一个设备并返回它。如果迭代完成,则返回 NULL。

返回的设备被引用,并且在迭代器移到下一个设备或退出之前不会被释放。调用方可以自由地对设备执行任何操作,包括回调到类代码中。

void class_dev_iter_exit(struct class_dev_iter *iter)

完成迭代

参数

struct class_dev_iter *iter

要完成的类迭代器

描述

完成迭代。无论迭代是否运行到最后,都请在迭代完成后始终调用此函数。

int class_for_each_device(const struct class *class, const struct device *start, void *data, int (*fn)(struct device*, void*))

设备迭代器

参数

const struct class *class

我们正在迭代的类

const struct device *start

列表中要开始的设备,如果有的话。

void *data

回调的数据

int (*fn)(struct device *, void *)

为每个设备调用的函数

描述

迭代 **class** 的设备列表,并为每个设备调用 **fn**,传递 **data**。如果设置了 **start**,列表迭代将从那里开始,否则,如果它是 NULL,则迭代从列表的开头开始。

我们每次都会检查 fn 的返回值。如果它返回除 0 之外的任何值,我们将中断并返回该值。

**fn** 允许执行任何操作,包括回调到类代码。没有锁定限制。

struct device *class_find_device(const struct class *class, const struct device *start, const void *data, device_match_t match)

用于定位特定设备的设备迭代器

参数

const struct class *class

我们正在迭代的类

const struct device *start

开始的设备

const void *data

匹配函数的数据

device_match_t match

检查设备的函数

描述

这类似于上面的 class_for_each_dev() 函数,但它返回一个对“找到”的设备的引用,供以后使用,这由 **match** 回调确定。

如果设备不匹配,回调应返回 0;如果匹配,则返回非零值。 如果回调返回非零值,则此函数将返回给调用者,并且不会迭代任何其他设备。

请注意,使用后您需要使用 put_device() 来删除引用。

**match** 允许执行任何操作,包括回调到类代码。没有锁定限制。

struct class_compat *class_compat_register(const char *name)

注册一个兼容类

参数

const char *name

类的名称

描述

当将一类类设备转换为总线设备时,兼容类旨在作为临时的用户空间兼容性解决方法。

void class_compat_unregister(struct class_compat *cls)

注销一个兼容类

参数

struct class_compat *cls

要注销的类

创建到总线设备的兼容类设备链接

参数

struct class_compat *cls

兼容类

struct device *dev

目标总线设备

struct device *device_link

一个可选的设备,应该为其创建“device”链接

删除到总线设备的兼容类设备链接

参数

struct class_compat *cls

兼容类

struct device *dev

目标总线设备

struct device *device_link

一个可选的设备,之前已为其创建了“device”链接

bool class_is_registered(const struct class *class)

确定此时此刻,类是否已在驱动程序核心中注册。

参数

const struct class *class

要检查的类

描述

返回一个布尔值,指示该类是否已在驱动程序核心中注册。请注意,该值可能会在调用后立即切换,因此仅在您“知道”这样做是安全的地方使用它(通常用于确定是否已注册特定的类)。

请谨慎使用此功能。

struct node_access_nodes

访问类设备以保持用户可见的与其他节点的关系。

定义:

struct node_access_nodes {
    struct device           dev;
    struct list_head        list_node;
    unsigned int            access;
#ifdef CONFIG_HMEM_REPORTING;
    struct access_coordinate        coord;
#endif;
};

成员

dev

此内存访问类的设备

list_node

节点访问列表中的列表元素

access

访问类等级

coord

异构内存性能坐标

struct node_cache_info

内存节点缓存的内部跟踪

定义:

struct node_cache_info {
    struct device dev;
    struct list_head node;
    struct node_cache_attrs cache_attrs;
};

成员

dev

表示缓存级别的设备

node

用于在节点中跟踪的列表元素

cache_attrs

此缓存级别的属性

void node_add_cache(unsigned int nid, struct node_cache_attrs *cache_attrs)

向内存节点添加缓存属性

参数

unsigned int nid

具有新缓存属性的节点标识符

struct node_cache_attrs *cache_attrs

正在添加的缓存的属性

void unregister_node(struct node *node)

注销节点设备

参数

struct node *node

即将消失的节点

描述

注销节点设备 **node**。在调用此函数之前,必须注销节点上的所有设备。

int register_memory_node_under_compute_node(unsigned int mem_nid, unsigned int cpu_nid, enum access_coordinate_class access)

将内存节点链接到其计算节点,用于给定的访问类。

参数

unsigned int mem_nid

内存节点号

unsigned int cpu_nid

CPU 节点号

enum access_coordinate_class access

要注册的访问类

描述

用于可能具有单独的内存和计算节点的平台。此函数将导出节点关系,链接哪个内存启动器节点可以在给定的排名访问类中访问内存目标。

int transport_class_register(struct transport_class *tclass)

注册一个初始传输类

参数

struct transport_class *tclass

指向要初始化的传输类结构的指针

描述

传输类包含一个用于标识它的嵌入类。调用者应使用零初始化此结构,然后必须使用实际传输类的唯一名称初始化通用类。有一个宏 DECLARE_TRANSPORT_CLASS() 可以执行此操作(声明的类仍然必须注册)。

成功返回 0,失败返回错误。

void transport_class_unregister(struct transport_class *tclass)

注销先前注册的类

参数

struct transport_class *tclass

要注销的传输类

描述

必须在释放传输类内存之前调用。

int anon_transport_class_register(struct anon_transport_class *atc)

注册一个匿名类

参数

struct anon_transport_class *atc

要注册的匿名传输类

描述

匿名传输类包含传输类和容器。匿名类的想法是它实际上没有任何与之关联的设备属性(从而节省了容器存储)。因此,它只能用于触发事件。使用 prezero,然后使用 DECLARE_ANON_TRANSPORT_CLASS() 来初始化匿名传输类存储。

void anon_transport_class_unregister(struct anon_transport_class *atc)

注销一个匿名类

参数

struct anon_transport_class *atc

指向要注销的匿名传输类的指针

描述

必须在释放匿名传输类的内存之前调用。

void transport_setup_device(struct device *dev)

声明一个新的设备,用于传输类关联,但暂时不要使其可见。

参数

struct device *dev

表示要添加的实体的通用设备

描述

通常,dev 表示 HBA 系统中的某些组件(HBA 本身或跨 HBA 总线的远程设备)。此例程只是一个触发点,用于查看任何一组传输类是否希望与添加的设备关联。这会为类设备分配存储并初始化它,但不会将其添加到系统或向其添加属性(您可以使用 transport_add_device 执行此操作)。如果您不需要单独的设置和添加操作,请使用 transport_register_device(请参阅 transport_class.h)。

int transport_add_device(struct device *dev)

声明一个新的设备,用于传输类关联

参数

struct device *dev

表示要添加的实体的通用设备

描述

通常,dev 表示 HBA 系统中的某些组件(HBA 本身或跨 HBA 总线的远程设备)。此例程只是一个触发点,用于将设备添加到系统并为其注册属性。

void transport_configure_device(struct device *dev)

配置已设置的设备

参数

struct device *dev

表示要配置的设备的通用设备

描述

配置的想法只是在设置过程中提供一个点,以允许传输类在设备设置后从中提取信息。这在 SCSI 中使用,因为我们必须有一个设置设备才能开始使用 HBA,但是在我们发送初始查询后,我们使用配置来提取设备参数。该设备不需要为了被配置而被添加。

void transport_remove_device(struct device *dev)

删除设备的可见性

参数

struct device *dev

要删除的通用设备

描述

此调用会删除设备(从 sysfs 向用户)的可见性,但不会销毁它。要完全删除设备,您还必须调用 transport_destroy_device。如果您不需要将删除和销毁作为单独的操作执行,请使用 transport_unregister_device()(请参阅 transport_class.h),它将为您执行这两个调用。

void transport_destroy_device(struct device *dev)

销毁已删除的设备

参数

struct device *dev

要从传输类中删除的设备。

描述

此调用会触发与传输类设备关联的存储的删除。注意:它实际上只是放弃对类设备的引用。在最后一个引用变为零之前,不会释放内存。另请注意,类设备保留对 dev 的引用计数,因此只要传输类设备存在,dev 也将保留。

int driver_deferred_probe_check_state(struct device *dev)

检查延迟探测状态

参数

struct device *dev

要检查的设备

返回

  • 如果 initcalls 已完成且模块已禁用,则为 -ENODEV。

  • 如果已设置延迟探测超时并且已过期且模块已启用,则为 -ETIMEDOUT。

  • 在其他情况下为 -EPROBE_DEFER。

描述

驱动程序或子系统可以选择调用此函数,而不是直接返回 -EPROBE_DEFER。

bool device_is_bound(struct device *dev)

检查设备是否绑定到驱动程序

参数

struct device *dev

要检查的设备

描述

如果传递的设备已成功完成针对驱动程序的探测,则返回 true。

必须在持有设备锁的情况下调用此函数。

int device_bind_driver(struct device *dev)

将驱动程序绑定到一个设备。

参数

struct device *dev

设备。

描述

允许手动将驱动程序附加到设备。调用者必须已设置 dev->driver

请注意,这不会修改总线引用计数。请在调用此函数之前验证是否已考虑此因素。(从驱动程序的 probe() 方法调用时,无需其他操作。)

必须在持有设备锁的情况下调用此函数。

调用者应首选使用 device_driver_attach()

void wait_for_device_probe(void)

参数

void

无参数

描述

等待设备探测完成。

int device_attach(struct device *dev)

尝试将设备附加到驱动程序。

参数

struct device *dev

设备。

描述

遍历总线拥有的驱动程序列表,并为每一对调用 driver_probe_device()。如果找到兼容对,则退出并返回。

如果设备已绑定到驱动程序,则返回 1;如果未找到匹配的驱动程序,则返回 0;如果设备未注册,则返回 -ENODEV。

当为 USB 接口调用时,必须持有 dev->parent 锁。

int device_driver_attach(const struct device_driver *drv, struct device *dev)

将特定驱动程序附加到特定设备。

参数

const struct device_driver *drv

要附加的驱动程序。

struct device *dev

要附加到的设备。

描述

手动将驱动程序附加到设备。如果需要,将获取 **dev** 锁和 **dev->parent** 锁。成功时返回 0,失败时返回 -ERR。

int driver_attach(const struct device_driver *drv)

尝试将驱动程序绑定到设备。

参数

const struct device_driver *drv

驱动程序。

描述

遍历总线上拥有的设备列表,并尝试将驱动程序与每个设备进行匹配。如果 driver_probe_device() 返回 0 且 **dev->driver** 已设置,则表示已找到兼容的对。

void device_release_driver(struct device *dev)

手动从驱动程序分离设备。

参数

struct device *dev

设备。

描述

手动从驱动程序分离设备。当为 USB 接口调用时,必须持有 **dev->parent** 锁。

如果此函数要在持有 **dev->parent** 锁的情况下调用,请确保提前解除绑定设备的消费者,或者可以在 **dev->parent** 锁下获取它们的锁。

struct platform_device *platform_device_register_resndata(struct device *parent, const char *name, int id, const struct resource *res, unsigned int num, const void *data, size_t size)

添加具有资源和平台特定数据的平台级设备。

参数

struct device *parent

我们要添加的设备的父设备。

const char *name

我们要添加的设备的基本名称。

int id

实例 ID。

const struct resource *res

需要为设备分配的资源集。

unsigned int num

资源数量。

const void *data

此平台设备的平台特定数据。

size_t size

平台特定数据的大小。

描述

成功时返回 struct platform_device 指针,失败时返回 ERR_PTR()

struct platform_device *platform_device_register_simple(const char *name, int id, const struct resource *res, unsigned int num)

添加平台级设备及其资源。

参数

const char *name

我们要添加的设备的基本名称。

int id

实例 ID。

const struct resource *res

需要为设备分配的资源集。

unsigned int num

资源数量。

描述

此函数创建一个简单的平台设备,该设备需要最少的资源和内存管理。罐装释放函数释放为设备分配的内存,允许卸载使用此类设备的驱动程序,而无需等待对设备的最后一个引用被删除。

此接口主要用于直接探测硬件的旧驱动程序。由于此类驱动程序自己创建 sysfs 设备节点,而不是让系统基础架构处理此类设备枚举任务,因此它们不完全符合 Linux 驱动程序模型。特别是,当此类驱动程序作为模块构建时,它们无法“热插拔”。

成功时返回 struct platform_device 指针,失败时返回 ERR_PTR()

struct platform_device *platform_device_register_data(struct device *parent, const char *name, int id, const void *data, size_t size)

添加具有平台特定数据的平台级设备。

参数

struct device *parent

我们要添加的设备的父设备。

const char *name

我们要添加的设备的基本名称。

int id

实例 ID。

const void *data

此平台设备的平台特定数据。

size_t size

平台特定数据的大小。

描述

此函数创建一个简单的平台设备,该设备需要最少的资源和内存管理。罐装释放函数释放为设备分配的内存,允许卸载使用此类设备的驱动程序,而无需等待对设备的最后一个引用被删除。

成功时返回 struct platform_device 指针,失败时返回 ERR_PTR()

struct resource *platform_get_resource(struct platform_device *dev, unsigned int type, unsigned int num)

获取设备的资源。

参数

struct platform_device *dev

平台设备。

unsigned int type

资源类型。

unsigned int num

资源索引。

返回

指向资源的指针,如果失败则为 NULL。

void __iomem *devm_platform_get_and_ioremap_resource(struct platform_device *pdev, unsigned int index, struct resource **res)

为平台设备调用 devm_ioremap_resource() 并获取资源。

参数

struct platform_device *pdev

用于内存资源查找和资源管理的平台设备。

unsigned int index

资源索引。

struct resource **res

可选输出参数,用于存储指向所获取资源的指针。

返回

指向重新映射的内存的指针,如果失败,则返回 ERR_PTR() 编码的错误代码。

void __iomem *devm_platform_ioremap_resource(struct platform_device *pdev, unsigned int index)

为平台设备调用 devm_ioremap_resource()。

参数

struct platform_device *pdev

用于内存资源查找和资源管理的平台设备。

unsigned int index

资源索引。

返回

指向重新映射的内存的指针,如果失败,则返回 ERR_PTR() 编码的错误代码。

void __iomem *devm_platform_ioremap_resource_byname(struct platform_device *pdev, const char *name)

为平台设备调用 devm_ioremap_resource,按名称检索资源。

参数

struct platform_device *pdev

用于内存资源查找和资源管理的平台设备。

const char *name

资源的名称。

返回

指向重新映射的内存的指针,如果失败,则返回 ERR_PTR() 编码的错误代码。

int platform_get_irq_optional(struct platform_device *dev, unsigned int num)

获取设备的可选 IRQ

参数

struct platform_device *dev

平台设备。

unsigned int num

IRQ 编号索引

描述

获取平台设备的 IRQ。设备驱动程序应检查返回值是否有错误,以避免将负整数值传递给 request_irq() API。这与 platform_get_irq() 相同,只是如果无法获取 IRQ,它不会打印错误消息。

例如

int irq = platform_get_irq_optional(pdev, 0);
if (irq < 0)
        return irq;

返回

成功时返回非零 IRQ 编号,失败时返回负错误编号。

int platform_get_irq(struct platform_device *dev, unsigned int num)

获取设备的 IRQ

参数

struct platform_device *dev

平台设备。

unsigned int num

IRQ 编号索引

描述

获取平台设备的 IRQ,如果查找 IRQ 失败,则打印错误消息。设备驱动程序应检查返回值是否有错误,以避免将负整数值传递给 request_irq() API。

例如

int irq = platform_get_irq(pdev, 0);
if (irq < 0)
        return irq;

返回

成功时返回非零 IRQ 编号,失败时返回负错误编号。

int platform_irq_count(struct platform_device *dev)

计算平台设备使用的 IRQ 数量

参数

struct platform_device *dev

平台设备。

返回

平台设备使用的 IRQ 数量或 EPROBE_DEFER

int devm_platform_get_irqs_affinity(struct platform_device *dev, struct irq_affinity *affd, unsigned int minvec, unsigned int maxvec, int **irqs)

devm 方法,用于使用中断亲和性描述符获取设备的 IRQ 集

参数

struct platform_device *dev

平台设备指针

struct irq_affinity *affd

亲和性描述符

unsigned int minvec

中断向量的最小计数

unsigned int maxvec

中断向量的最大计数

int **irqs

用于保存 IRQ 编号的指针

描述

获取平台设备的一组 IRQ,并根据传递的亲和性描述符更新 IRQ 亲和性

返回

成功时返回向量数,失败时返回负错误编号。

struct resource *platform_get_resource_byname(struct platform_device *dev, unsigned int type, const char *name)

按名称获取设备的资源

参数

struct platform_device *dev

平台设备。

unsigned int type

资源类型。

const char *name

资源名称

int platform_get_irq_byname(struct platform_device *dev, const char *name)

按名称获取设备的 IRQ

参数

struct platform_device *dev

平台设备。

const char *name

IRQ 名称

描述

platform_get_irq() 一样获取 IRQ,但通过名称而不是索引获取。

返回

成功时返回非零 IRQ 编号,失败时返回负错误编号。

int platform_get_irq_byname_optional(struct platform_device *dev, const char *name)

按名称获取设备的可选 IRQ

参数

struct platform_device *dev

平台设备。

const char *name

IRQ 名称

描述

platform_get_irq_byname() 一样按名称获取可选 IRQ。除非无法获取 IRQ,否则它不会打印错误消息。

返回

成功时返回非零 IRQ 编号,失败时返回负错误编号。

int platform_add_devices(struct platform_device **devs, int num)

添加多个平台设备

参数

struct platform_device **devs

要添加的平台设备数组

int num

数组中平台设备的数量

返回

成功时返回 0,失败时返回负错误编号。

void platform_device_put(struct platform_device *pdev)

销毁平台设备

参数

struct platform_device *pdev

要释放的平台设备

描述

释放与平台设备关联的所有内存。此函数必须 _仅_ 在错误情况下从外部调用。所有其他用法都是错误。

struct platform_device *platform_device_alloc(const char *name, int id)

创建平台设备

参数

const char *name

我们要添加的设备的基本名称。

int id

实例 ID。

描述

创建一个平台设备对象,该对象可以附加其他对象,并且在释放时将释放附加的对象。

int platform_device_add_resources(struct platform_device *pdev, const struct resource *res, unsigned int num)

向平台设备添加资源

参数

struct platform_device *pdev

由 platform_device_alloc 分配的平台设备,用于向其添加资源

const struct resource *res

需要为设备分配的资源集。

unsigned int num

资源数量。

描述

将资源的副本添加到平台设备。当平台设备释放时,将释放与资源关联的内存。

int platform_device_add_data(struct platform_device *pdev, const void *data, size_t size)

向平台设备添加特定于平台的数据

参数

struct platform_device *pdev

由 platform_device_alloc 分配的平台设备,用于向其添加资源

const void *data

此平台设备的平台特定数据。

size_t size

平台特定数据的大小。

描述

将平台特定数据的副本添加到平台设备的 platform_data 指针。当平台设备被释放时,与平台数据关联的内存将被释放。

int platform_device_add(struct platform_device *pdev)

将平台设备添加到设备层次结构

参数

struct platform_device *pdev

我们要添加的平台设备

描述

这是 platform_device_register() 的第 2 部分,但如果 pdev 是通过 platform_device_alloc() 分配的,则可以单独调用。

void platform_device_del(struct platform_device *pdev)

移除平台级设备

参数

struct platform_device *pdev

我们要移除的平台设备

描述

请注意,此函数还将释放设备拥有的所有基于内存和端口的资源(dev->resource)。此函数必须_仅_在错误情况下从外部调用。所有其他用法都是错误。

int platform_device_register(struct platform_device *pdev)

添加平台级设备

参数

struct platform_device *pdev

我们要添加的平台设备

注意

调用此函数后,_永远不要_直接释放 pdev,即使它返回错误!始终使用 platform_device_put() 来放弃在此函数中初始化的引用。

void platform_device_unregister(struct platform_device *pdev)

注销平台级设备

参数

struct platform_device *pdev

我们要注销的平台设备

描述

注销分两步完成。首先,我们释放所有资源并将其从子系统中删除,然后我们通过调用 platform_device_put() 来删除引用计数。

struct platform_device *platform_device_register_full(const struct platform_device_info *pdevinfo)

添加具有资源和平台特定数据的平台级设备。

参数

const struct platform_device_info *pdevinfo

用于创建设备的数据

描述

成功时返回 struct platform_device 指针,失败时返回 ERR_PTR()

int __platform_driver_register(struct platform_driver *drv, struct module *owner)

为平台级设备注册驱动程序

参数

struct platform_driver *drv

平台驱动程序结构

struct module *owner

所有者模块/驱动程序

void platform_driver_unregister(struct platform_driver *drv)

注销平台级设备的驱动程序

参数

struct platform_driver *drv

平台驱动程序结构

int __platform_driver_probe(struct platform_driver *drv, int (*probe)(struct platform_device*), struct module *module)

为非热插拔设备注册驱动程序

参数

struct platform_driver *drv

平台驱动程序结构

int (*probe)(struct platform_device *)

驱动程序的探测例程,可能来自 __init 部分

struct module *module

将成为驱动程序所有者的模块

描述

当您知道设备不是热插拔的并且已经注册时,并且您希望在驱动程序绑定到设备后从内存中删除其一次性 probe() 基础结构时,请使用此方法代替 platform_driver_register()。

一个典型的用途是用于集成到片上系统处理器中的控制器的驱动程序,其中控制器设备已配置为板设置的一部分。

请注意,这与延迟探测不兼容。

如果驱动程序注册并绑定到设备,则返回零,否则返回负错误代码,并且不注册驱动程序。

struct platform_device *__platform_create_bundle(struct platform_driver *driver, int (*probe)(struct platform_device*), struct resource *res, unsigned int n_res, const void *data, size_t size, struct module *module)

注册驱动程序并创建相应的设备

参数

struct platform_driver *driver

平台驱动程序结构

int (*probe)(struct platform_device *)

驱动程序的探测例程,可能来自 __init 部分

struct resource *res

需要为设备分配的资源集。

unsigned int n_res

资源数量。

const void *data

此平台设备的平台特定数据。

size_t size

平台特定数据的大小。

struct module *module

将成为驱动程序所有者的模块

描述

在旧式模块中使用此方法,这些模块直接探测硬件并注册单个平台设备和相应的平台驱动程序。

成功时返回 struct platform_device 指针,失败时返回 ERR_PTR()

int __platform_register_drivers(struct platform_driver *const *drivers, unsigned int count, struct module *owner)

注册平台驱动程序数组

参数

struct platform_driver * const *drivers

要注册的驱动程序数组

unsigned int count

要注册的驱动程序数量

struct module *owner

拥有驱动程序的模块

描述

注册由数组指定的平台驱动程序。如果注册驱动程序失败,将注销所有先前注册的驱动程序。此 API 的调用者应使用 platform_unregister_drivers() 以相反的顺序注销驱动程序。

返回

成功时返回 0,失败时返回负错误代码。

void platform_unregister_drivers(struct platform_driver *const *drivers, unsigned int count)

注销平台驱动程序数组

参数

struct platform_driver * const *drivers

要注销的驱动程序数组

unsigned int count

要注销的驱动程序数量

描述

注销由数组指定的平台驱动程序。这通常用于补充之前对 platform_register_drivers() 的调用。驱动程序按照注册顺序的相反顺序注销。

struct device *platform_find_device_by_driver(struct device *start, const struct device_driver *drv)

查找具有给定驱动程序的平台设备。

参数

struct device *start

开始搜索的设备。

const struct device_driver *drv

要查找的设备驱动程序。

struct device *bus_find_device_by_name(const struct bus_type *bus, struct device *start, const char *name)

设备迭代器,用于查找具有特定名称的特定设备。

参数

const struct bus_type *bus

总线类型

struct device *start

开始的设备

const char *name

要匹配的设备名称

struct device *bus_find_device_by_of_node(const struct bus_type *bus, const struct device_node *np)

用于定位与 of_node 匹配的特定设备的设备迭代器。

参数

const struct bus_type *bus

总线类型

const struct device_node *np

要匹配的设备的 of_node。

struct device *bus_find_device_by_fwnode(const struct bus_type *bus, const struct fwnode_handle *fwnode)

用于定位与 fwnode 匹配的特定设备的设备迭代器。

参数

const struct bus_type *bus

总线类型

const struct fwnode_handle *fwnode

要匹配的设备的 fwnode。

struct device *bus_find_device_by_devt(const struct bus_type *bus, dev_t devt)

用于定位与设备类型匹配的特定设备的设备迭代器。

参数

const struct bus_type *bus

总线类型

dev_t devt

要匹配的设备的设备类型。

struct device *bus_find_next_device(const struct bus_type *bus, struct device *cur)

查找给定总线上给定设备之后的下一个设备。

参数

const struct bus_type *bus

总线类型

struct device *cur

开始搜索的设备。

struct device *bus_find_device_by_acpi_dev(const struct bus_type *bus, const struct acpi_device *adev)

用于定位与 ACPI COMPANION 设备匹配的特定设备的设备迭代器。

参数

const struct bus_type *bus

总线类型

const struct acpi_device *adev

要匹配的 ACPI COMPANION 设备。

int bus_for_each_dev(const struct bus_type *bus, struct device *start, void *data, int (*fn)(struct device*, void*))

设备迭代器。

参数

const struct bus_type *bus

总线类型。

struct device *start

开始迭代的设备。

void *data

回调的数据。

int (*fn)(struct device *, void *)

为每个设备调用的函数。

描述

遍历 **bus** 的设备列表,并为每个设备调用 **fn**,并向其传递 **data**。如果 **start** 不为 NULL,我们使用该设备开始迭代。

我们每次都会检查 fn 的返回值。如果它返回除 0 之外的任何值,我们将中断并返回该值。

注意

返回非零值的设备不会以任何方式保留,也不会递增其引用计数。如果调用者需要保留此数据,它应该这样做,并在提供的回调中递增引用计数。

struct device *bus_find_device(const struct bus_type *bus, struct device *start, const void *data, device_match_t match)

用于查找特定设备的设备迭代器。

参数

const struct bus_type *bus

总线类型

struct device *start

开始的设备

const void *data

要传递给匹配函数的数据

device_match_t match

用于检查设备的回调函数

描述

这与上面的 bus_for_each_dev() 函数类似,但它返回一个对“找到”的设备的引用,供以后使用,由 **match** 回调确定。

如果设备不匹配,回调应返回 0;如果匹配,则返回非零值。 如果回调返回非零值,则此函数将返回给调用者,并且不会迭代任何其他设备。

int bus_for_each_drv(const struct bus_type *bus, struct device_driver *start, void *data, int (*fn)(struct device_driver*, void*))

驱动程序迭代器

参数

const struct bus_type *bus

我们正在处理的总线。

struct device_driver *start

开始迭代的驱动程序。

void *data

要传递给回调的数据。

int (*fn)(struct device_driver *, void *)

为每个驱动程序调用的函数。

描述

这与上面的设备迭代器几乎相同。我们迭代属于 bus 的每个驱动程序,并为每个驱动程序调用 fn。如果 fn 返回除 0 之外的任何值,我们将跳出并返回该值。如果 start 不为 NULL,我们将其用作列表的头部。

注意

我们不会返回返回非零值的驱动程序,也不会为该驱动程序增加引用计数。如果调用者需要知道该信息,则必须在回调中设置。它还必须确保增加引用计数,使其不会在返回给调用者之前消失。

int bus_rescan_devices(const struct bus_type *bus)

重新扫描总线上的设备,查找可能的驱动程序

参数

const struct bus_type *bus

要扫描的总线。

描述

此函数将查找总线上未连接驱动程序的设备,并针对现有驱动程序重新扫描,以查看是否通过调用 device_attach() 与任何驱动程序匹配(对于未绑定的设备)。

int device_reprobe(struct device *dev)

删除设备的驱动程序并探测新的驱动程序

参数

struct device *dev

要重新探测的设备

描述

此函数分离给定设备的已连接驱动程序(如果有),并重新启动驱动程序探测过程。如果设备生命周期内的探测标准发生变化,并且驱动程序连接应相应更改,则应使用此函数。

int bus_register(const struct bus_type *bus)

注册驱动程序核心子系统

参数

const struct bus_type *bus

要注册的总线

描述

一旦有了这些,我们将总线注册到 kobject 基础结构中,然后注册它拥有的子系统:属于该子系统的设备和驱动程序。

void bus_unregister(const struct bus_type *bus)

从系统中删除总线

参数

const struct bus_type *bus

总线。

描述

取消注册子系统和总线本身。最后,我们调用 bus_put() 来释放引用计数

int subsys_system_register(const struct bus_type *subsys, const struct attribute_group **groups)

在 /sys/devices/system/ 注册一个子系统

参数

const struct bus_type *subsys

系统子系统

const struct attribute_group **groups

根设备的默认属性

描述

所有“系统”子系统都有一个 /sys/devices/system/<name> 根设备,其名称为子系统的名称。根设备可以携带子系统范围的属性。所有已注册的设备都位于此单个根设备下,并以子系统名称命名,附加一个简单的枚举数字。已注册的设备未明确命名;只需要设置设备中的“id”。

不要将此接口用于任何新事物,它仅为了与不好的想法兼容而存在。新的子系统应使用普通的子系统;并且应将子系统范围的属性添加到子系统目录本身,而不是添加到位于 /sys/devices/system/<name> 中的某个创建的虚拟根设备。

int subsys_virtual_register(const struct bus_type *subsys, const struct attribute_group **groups)

在 /sys/devices/virtual/ 注册一个子系统

参数

const struct bus_type *subsys

虚拟子系统

const struct attribute_group **groups

根设备的默认属性

描述

所有“虚拟”子系统都有一个 /sys/devices/system/<name> 根设备,其名称为子系统的名称。根设备可以携带子系统范围的属性。所有已注册的设备都位于此单个根设备下。对设备命名没有任何限制。这适用于需要 sysfs 接口的内核软件结构。

struct device_driver *driver_find(const char *name, const struct bus_type *bus)

按名称查找总线上的驱动程序。

参数

const char *name

驱动程序的名称。

const struct bus_type *bus

要扫描驱动程序的总线。

描述

调用 kset_find_obj() 遍历总线上的驱动程序列表,以按名称查找驱动程序。如果找到,则返回驱动程序。

此例程不提供任何锁定,以防止其返回的驱动程序在调用者使用时被取消注册或卸载。调用者负责防止这种情况发生。

struct device *bus_get_dev_root(const struct bus_type *bus)

返回指向总线的“设备根”的指针

参数

const struct bus_type *bus

要返回设备根的总线。

描述

如果总线具有“设备根”结构,则返回它,并增加引用计数。

请注意,在完成对设备的操作后,需要调用 put_device()

如果设备根不存在(或总线不是有效指针),则将返回 NULL。

设备驱动程序 DMA 管理

void dmam_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle)

托管的 dma_free_coherent()

参数

struct device *dev

要释放相干内存的设备

size_t size

分配的大小

void *vaddr

要释放的内存的虚拟地址

dma_addr_t dma_handle

要释放的内存的 DMA 句柄

描述

托管的 dma_free_coherent()。

void *dmam_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)

托管的 dma_alloc_attrs()

参数

struct device *dev

要为其分配非相干内存的设备

size_t size

分配的大小

dma_addr_t *dma_handle

已分配 DMA 句柄的输出参数

gfp_t gfp

分配标志

unsigned long attrs

DMA_ATTR_* 命名空间中的标志。

描述

托管的 dma_alloc_attrs()。使用此函数分配的内存将在驱动程序分离时自动释放。

返回

成功时指向已分配内存的指针,失败时为 NULL。

unsigned int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction dir, unsigned long attrs)

为 DMA 映射给定的缓冲区

参数

struct device *dev

执行 DMA 操作的设备

struct scatterlist *sg

描述缓冲区的 sg_table 对象

int nents

要映射的条目数

enum dma_data_direction dir

DMA 方向

unsigned long attrs

映射操作的可选 DMA 属性

描述

映射由 sg 参数中传递的散列表描述的缓冲区,其中包含 nents 段,用于 dev 设备的 dir DMA 操作。

成功时返回映射的条目数(可能小于 nents)。如果发生任何错误,则返回零。

应使用 dma_unmap_sg_attrs() 解除缓冲区的映射,并使用原始的 sg 和原始的 nents(而不是此函数返回的值)。

int dma_map_sgtable(struct device *dev, struct sg_table *sgt, enum dma_data_direction dir, unsigned long attrs)

为 DMA 映射给定的缓冲区

参数

struct device *dev

执行 DMA 操作的设备

struct sg_table *sgt

描述缓冲区的 sg_table 对象

enum dma_data_direction dir

DMA 方向

unsigned long attrs

映射操作的可选 DMA 属性

描述

映射由给定的 sg_table 对象中存储的散列表描述的缓冲区,用于 dev 设备的 dir DMA 操作。成功后,缓冲区的拥有权将转移到 DMA 域。必须调用 dma_sync_sgtable_for_cpu() 或 dma_unmap_sgtable() 将缓冲区的拥有权移回 CPU 域,然后再由 CPU 访问缓冲区。

成功时返回 0,如果出错则返回负错误代码。支持以下错误代码及其含义

-EINVAL

无效的参数、未对齐的访问或使用中的其他错误。重试不会成功。

-ENOMEM

资源不足(例如内存或 IOVA 空间)以完成映射。如果稍后重试,应该会成功。

-EIO

具有未知含义的旧错误代码。例如,如果较低级别的调用返回 DMA_MAPPING_ERROR,则会返回此代码。

-EREMOTEIO

DMA 设备无法访问 sg_table 中指定的 P2PDMA 内存。如果重试,则不会成功。

bool dma_can_mmap(struct device *dev)

检查给定设备是否支持 dma_mmap_*

参数

struct device *dev

要检查的设备

描述

如果 dev 支持 dma_mmap_coherent() 和 dma_mmap_attrs() 将 DMA 分配映射到用户空间,则返回 true

int dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma, void *cpu_addr, dma_addr_t dma_addr, size_t size, unsigned long attrs)

将一致的 DMA 分配映射到用户空间

参数

struct device *dev

有效的 struct device 指针,或者对于类似 ISA 和 EISA 的设备为 NULL

struct vm_area_struct *vma

描述请求的用户映射的 vm_area_struct

void *cpu_addr

从 dma_alloc_attrs 返回的内核 CPU 视图地址

dma_addr_t dma_addr

从 dma_alloc_attrs 返回的设备视图地址

size_t size

最初在 dma_alloc_attrs 中请求的内存大小

unsigned long attrs

在 dma_alloc_attrs 中请求的映射属性的属性

描述

将先前由 dma_alloc_attrs 分配的一致 DMA 缓冲区映射到用户空间。在用户空间映射被释放之前,驱动程序不得释放一致的 DMA 缓冲区。

bool dma_addressing_limited(struct device *dev)

返回设备是否寻址受限

参数

struct device *dev

要检查的设备

描述

如果设备的 DMA 掩码太小,无法寻址系统中的所有内存,则返回 true,否则返回 false。缺少寻址位是反弹缓冲的主要原因,但可能不是唯一的原因。

设备驱动程序 PnP 支持

int pnp_register_protocol(struct pnp_protocol *protocol)

将 pnp 协议添加到 pnp 层

参数

struct pnp_protocol *protocol

指向相应 pnp_protocol 结构的指针

示例协议:ISAPNP、PNPBIOS 等

void pnp_unregister_protocol(struct pnp_protocol *protocol)

从 pnp 层删除 pnp 协议

参数

struct pnp_protocol *protocol

指向相应 pnp_protocol 结构的指针

struct pnp_dev *pnp_request_card_device(struct pnp_card_link *clink, const char *id, struct pnp_dev *from)

在指定的卡下搜索 PnP 设备

参数

struct pnp_card_link *clink

指向卡链接的指针,不能为 NULL

const char *id

指向 PnP ID 结构的指针,该结构解释了查找设备的规则

struct pnp_dev *from

开始搜索的位置。如果为 NULL,则将从头开始。

void pnp_release_card_device(struct pnp_dev *dev)

当驱动程序不再需要设备时调用此函数

参数

struct pnp_dev *dev

指向 PnP 设备结构的指针

int pnp_register_card_driver(struct pnp_card_driver *drv)

向 PnP 层注册 PnP 卡驱动程序

参数

struct pnp_card_driver *drv

指向要注册的驱动程序的指针

void pnp_unregister_card_driver(struct pnp_card_driver *drv)

从 PnP 层注销 PnP 卡驱动程序

参数

struct pnp_card_driver *drv

指向要注销的驱动程序的指针

struct pnp_id *pnp_add_id(struct pnp_dev *dev, const char *id)

向指定的设备添加 EISA id

参数

struct pnp_dev *dev

指向目标设备的指针

const char *id

指向 EISA id 字符串的指针

int pnp_start_dev(struct pnp_dev *dev)

PnP 设备的底层启动

参数

struct pnp_dev *dev

指向目标设备的指针

描述

假设资源已经分配

int pnp_stop_dev(struct pnp_dev *dev)

PnP 设备的底层禁用

参数

struct pnp_dev *dev

指向目标设备的指针

描述

不释放资源

int pnp_activate_dev(struct pnp_dev *dev)

激活 PnP 设备以供使用

参数

struct pnp_dev *dev

指向目标设备的指针

描述

不验证或设置资源,因此请小心。

int pnp_disable_dev(struct pnp_dev *dev)

禁用设备

参数

struct pnp_dev *dev

指向目标设备的指针

描述

通知正确的 pnp 协议,以便其他设备可以使用资源

int pnp_is_active(struct pnp_dev *dev)

根据其当前资源确定设备是否处于活动状态

参数

struct pnp_dev *dev

指向目标 PnP 设备的指针

用户空间 IO 设备

void uio_event_notify(struct uio_info *info)

触发一个中断事件

参数

struct uio_info *info

UIO 设备功能

int __uio_register_device(struct module *owner, struct device *parent, struct uio_info *info)

注册一个新的用户空间 IO 设备

参数

struct module *owner

创建新设备的模块

struct device *parent

父设备

struct uio_info *info

UIO 设备功能

描述

成功时返回零,或返回一个负数的错误代码。

int __devm_uio_register_device(struct module *owner, struct device *parent, struct uio_info *info)

资源管理的 uio_register_device()

参数

struct module *owner

创建新设备的模块

struct device *parent

父设备

struct uio_info *info

UIO 设备功能

描述

成功时返回零,或返回一个负数的错误代码。

void uio_unregister_device(struct uio_info *info)

注销工业 IO 设备

参数

struct uio_info *info

UIO 设备功能

struct uio_mem

UIO 内存区域的描述

定义:

struct uio_mem {
    const char              *name;
    phys_addr_t addr;
    dma_addr_t dma_addr;
    unsigned long           offs;
    resource_size_t size;
    int memtype;
    void __iomem            *internal_addr;
    struct device           *dma_device;
    struct uio_map          *map;
};

成员

name

用于标识的内存区域名称

addr

设备内存的地址,四舍五入到页面大小(使用 phys_addr,因为 addr 可以是逻辑地址、虚拟地址或物理地址,并且 phys_addr_t 应始终足够大以处理任何地址类型)

dma_addr

由 dma_alloc_coherent 设置的 DMA 句柄,仅与 UIO_MEM_DMA_COHERENT 一起使用(**addr** 应该是来自相同 dma_alloc_coherent 调用的 void * 返回值)

offs

页面内设备内存的偏移量

size

IO 的大小(页面大小的倍数)

memtype

addr 指向的内存类型

internal_addr

addr 的 ioremap 版本,供驱动程序内部使用

dma_device

传递给 dma_alloc_coherent 的设备结构,仅与 UIO_MEM_DMA_COHERENT 一起使用

map

仅供 UIO 核心使用。

struct uio_port

UIO 端口区域的描述

定义:

struct uio_port {
    const char              *name;
    unsigned long           start;
    unsigned long           size;
    int porttype;
    struct uio_portio       *portio;
};

成员

name

用于标识的端口区域名称

start

端口区域的起始位置

size

端口区域的大小

porttype

端口类型(请参阅下面的 UIO_PORT_*)

portio

仅供 UIO 核心使用。

struct uio_info

UIO 设备功能

定义:

struct uio_info {
    struct uio_device       *uio_dev;
    const char              *name;
    const char              *version;
    struct uio_mem          mem[MAX_UIO_MAPS];
    struct uio_port         port[MAX_UIO_PORT_REGIONS];
    long irq;
    unsigned long           irq_flags;
    void *priv;
    irqreturn_t (*handler)(int irq, struct uio_info *dev_info);
    int (*mmap)(struct uio_info *info, struct vm_area_struct *vma);
    int (*open)(struct uio_info *info, struct inode *inode);
    int (*release)(struct uio_info *info, struct inode *inode);
    int (*irqcontrol)(struct uio_info *info, s32 irq_on);
};

成员

uio_dev

此 info 所属的 UIO 设备

name

设备名称

version

设备驱动程序版本

mem

可映射内存区域的列表,列表末尾的 size==0

port

端口区域的列表,列表末尾的 size==0

irq

中断号或 UIO_IRQ_CUSTOM

irq_flags

request_irq() 的标志

priv

可选的私有数据

handler

设备的 irq 处理程序

mmap

此 uio 设备的 mmap 操作

open

此 uio 设备的 open 操作

release

此 uio 设备的 release 操作

irqcontrol

当 0/1 被写入 /dev/uioX 时禁用/启用 irq

uio_register_device

uio_register_device (parent, info)

注册一个新的用户空间 IO 设备

参数

parent

父设备

info

UIO 设备功能

描述

成功时返回零,或返回一个负数的错误代码。

devm_uio_register_device

devm_uio_register_device (parent, info)

资源管理的 uio_register_device()

参数

parent

父设备

info

UIO 设备功能

描述

成功时返回零,或返回一个负数的错误代码。