Auxiliary Bus

84 篇文章 6 订阅
40 篇文章 9 订阅

Auxiliary 总线

在某些子系统中,核心设备(PCI/ACPI/其他)的功能对于单个设备来说过于复杂,无法由单个某驱动程序(例如 Sound Open Firmware)管理,多个设备可能会实现共同的功能交集(例如 NIC + RDMA),或者驱动程序可能想导出一个接口供另一个子系统驱动(例如 SIOV Physical Function export Virtual Function management)。将功能拆分为代表sub-domains功能的child- devices,可以通过 Linux 设备驱动程序模型划分、分层和分发 domain-specific 的关注点。

此类需求的一个示例是音频子系统,其中单个 IP 处理多个实体,例如 HDMI、Soundwire、本地设备(例如麦克风/扬声器等)。内核功能的拆分可以是任意的,也可以由 DSP 固件定义拓扑并包含用于test/debug 的钩子。这允许音频核心 device 最小化并专注于硬件特定的控制和通信。

每个auxiliary_device 代表其父功能的一部分。通过在其他domain-specific 的结构中封装一个 auxiliary_device  并使用 .ops 回调,可以根据需要扩展和专门化通用行为。辅助总线上的设备不共享任何结构,并且与父级的通信通道的使用是domain-specific的。

请注意,ops 旨在作为增强一类auxiliary devices内的实例行为的一种方式,它不是从父设备导出通用基础设施的机制。考虑 EXPORT_SYMBOL_NS() 将基础结构从parent module传送到auxiliary module。

什么时候应该使用Auxiliary Bus

当驱动程序和一个或多个与驱动程序共享公共头文件的内核模块需要一种机制来连接并提供对auxiliary_device 的注册驱动程序分配的共享对象的访问时,将使用auxiliary bus。注册auxiliary_device 的驱动程序和注册auxiliary_drivers  的内核模块可以来自同一个子系统,也可以来自多个子系统。

这里的重点是一个通用的generic 接口,它使子系统定制不受总线infrastructure 的影响。

一个例子是一个 PCI 网络设备,它具有 RDMA 能力并导出一个child device,由 RDMA 子系统中的auxiliary_driver 驱动。 PCI 驱动为 NIC 上的每个PF分配并注册一个auxiliary_device 。 RDMA 驱动程序注册了一个auxiliary_driver ,该驱动可以驱动这些auxiliary_devices。这会将父 PCI 设备/驱动程序发布的数据/操作传送到 RDMA auxiliary_driver。

另一个用例是将 PCI 设备拆分为多个sub functions。对于每个sub functions,都会创建一个auxiliary_device。 PCI sub function 驱动程序绑定到创建自己的一个或多个类设备的此类设备。 PCI  sub function auxiliary device 可能包含在具有附加属性(例如用户定义的子功能编号)和可选属性(例如资源和到父设备的链接)的结构中。 systemd/udev 可以使用这些属性;因此应该在驱动程序绑定到auxiliary_device之前初始化。

使用auxiliary bus 的一个关键要求是不依赖于物理总线、设备、寄存器访问或 regmap 支持。这些从核心分离出来的独立设备不能存在于平台总线上,因为它们不是由 DT/ACPI 控制的物理设备。同样的论点也适用于在这种情况下不能使用 MFD,因为 MFD 依赖于作为物理设备的单个function设备。

Auxiliary Device

auxiliary_device 代表其父设备功能的一部分。它被赋予一个名称,该名称与注册驱动程序 KBUILD_MODNAME 相结合,创建用于驱动程序绑定的 match_name,以及与 match_name 组合的 id 提供唯一名称以向总线子系统注册。

注册一个auxiliary_device 是一个两步过程。首先调用auxiliary_device_init(),它检查auxiliary_device  结构的几个方面并执行device_initialize()。此步骤完成后,任何错误状态都必须在其解析路径中调用auxiliary_device_uninit()。注册auxiliary_device 的第二步是执行对auxiliary_device_add() 的调用,它设置设备的名称并将设备添加到总线。

注销一个auxiliary_device 也是镜像注册过程的两步过程。首先调用auxiliary_device_delete(),然后调用auxiliary_device_uninit()。


如果两个带有 match_name “mod.foo”的辅助设备都注册到总线上,它们必须具有唯一的 id 值(例如“x”和“y”),所以注册的设备名称是“mod.foo.x”和“ mod.foo.y”。如果 match_name + id 不是唯一的,则 device_add 失败并生成错误消息。

auxiliary_device.dev.type.release 或者 auxiliary_device.dev.release 必须使用非空指针填充才能成功注册auxiliary_device。

还必须填充 auxiliary_device.dev.parent。

Auxiliary Device 内存模型和声明周期

注册的驱动是为auxiliary_device 分配内存并将其注册到auxiliary bus上的entity 。需要注意的是,与平台总线相反,注册驱动程序完全负责管理用于驱动程序对象的内存。

在共享头文件中定义的父对象包含auxiliary_device。它还包含一个指向shared object 的指针,shared object 也在共享头中定义。parent object 和shared object 都由注册驱动程序分配。这种布局允许auxiliary_driver 的注册模块执行container_of() 调用,从指针转换到auxiliary_device,即在auxiliary_driver 的probe 函数期间传递,up到父对象,然后访问shared object。

仅在其注册驱动程序定义的 release() 回调流中释放auxiliary_device 的内存。

shared object 的内存声明周期必须等于或大于auxiliary_device的内存声明周期。auxiliary_driver 应该只考虑这个shared object是有效的,只要auxiliary_device 仍然注册在auxiliary bus上。shared object 可以 up 转换到注册的驱动,然后访问 shared object

已注册驱动必须在其自己的 driver.remove() 完成之前注销所有auxiliary devices 

Auxiliary Drivers

Auxiliary 驱动程序遵循标准驱动程序模型约定,相关的discovery/enumeration 由core 处理,驱动程序提供 probe() 和 remove() 方法。它们支持使用标准约定的电源管理和关机通知。

Auxiliary 驱动通过调用auxiliary_driver_register() 向总线注册自己。 id_table 包含驱动程序可以绑定的auxiliary 设备的 match_names。

示例用法

Auxiliary 设备由子系统级core设备创建和注册,该core设备需要将其功能分解为更小的片段。扩展auxiliary_device 范围的一种方法是将其封装在父设备定义的domain- pecific结构中。该结构包含auxiliary_device 以及与父设备建立连接所需的任何相关shared data/callbacks。

一个例子:


然后父设备通过调用auxiliary_device_init(),然后是auxiliary_device_add()来注册auxiliary_device,并使用指向上述结构的auxdev成员的指针。父级为辅助设备提供一个名称,该名称与父级的 KBUILD_MODNAME 相结合,创建用于匹配和绑定驱动程序的 match_name。

每当注册一个auxiliary_driver 时,根据 match_name,auxiliary_driver 的 probe() 就会为匹配的设备调用。auxiliary_driver 也可以封装在客户自定义驱动程序中,通过添加额外的domain-specific 的操作,使core设备的功能可扩展,如下所示:

 
这种用法的一个例子是:

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值