Linux NTB 学习笔记:IDT NTB 硬件驱动骨架解析 Linux NTB 子系统里,IDT 驱动是一个很适合入门的硬件驱动样本。它不直接实现业务传输,而是把 IDT PCIe Switch 里的 NT function 包装成 NTB core 能理解的 struct ntb_dev。
看这个驱动时,重点不是记住每个寄存器,而是理解一个 NTB hardware driver 的骨架:PCI probe 进来以后,如何映射寄存器、扫描端口、初始化 MW、doorbell、message、中断,最后注册到 NTB core。
IDT 驱动的 PCI probe 主线可以压缩成一条链路:
idt_pci_probe() -> idt_check_setup() -> idt_create_dev() -> idt_init_pci() -> idt_scan_ports() -> idt_init_link() -> idt_init_mws() -> idt_init_msg() -> idt_init_temp() -> idt_init_isr() -> idt_register_device()
这条链路说明了硬件驱动的基本职责:先确认硬件预配置,再建立本地软件对象,然后把各种 NTB 能力挂到 ntb_dev_ops 上。
idt_check_setup() 会检查 BAR、NT function 等基础配置是否符合驱动预期。IDT 驱动假设 switch 的 NT 功能、BAR 类型、端口模式等已经由 EEPROM、BIOS 或管理固件提前配置好。驱动不会从零开始配置整颗 switch,而是在既有配置上工作。
idt_create_dev() 分配驱动私有结构。这个结构里保存了 PCI 设备、NTB 设备、端口信息、peer 信息、Memory Window 信息、中断信息等。后续 所 有 操 作基本 都围绕 这个 ndev 展 开。
IDT 驱动里有 两 类 访问非常 重 要 :idt_nt_read/write 和 idt_sw_read/write。前 者访问 本地 NT function 的 BAR0 映射 空间 ,后 者通过间 接 机制访问 switch 全局 寄存器。
BAR0 在这里主 要 是 控制/配置 窗 口,不是 大数据 Memory Window。Memory Window 使用哪些 BAR、 大小 是 多少 、是 Direct 还 是 LUT, 通常 由 switch 预配置 决定 ,驱动 只 是扫描 并 记 录 。
这 也 是学习 NTB 驱动时 容易混淆 的地 方 : 读 本地 NT function 的寄存器, 和读 整颗 switch 的端口 状态 寄存器, 并 不是一个 层次 。
idt_scan_ports() 会 读取 本地 port、partition, 并 扫描预配置端口, 找出哪些 peer NT port 可 用 。驱动会 维护 port_idx_map 和 part_idx_map。 port_idx_map 用于 从端口 号找 到 peer index,part_idx_map 用于 从 partition 找 peer index。后 者更多 是 IDT 驱动 内部需要 , 比 如 message 里可能 携带 source partition, 需要转 成 NTB core 认 识 的 peer index。
对 NTB core 来说,client 关心 的是 peer index ; 对硬件来说,寄存器里经 常出 现的是 port number 或 partition。硬件驱动 要负 责在这 些编号之间转换 。
idt_init_link() 主 要 初始化 link 事 件路 径 , 清状态 、设置 mask, 让 link up/down 或 global signal 之 类 事 件能 被 驱动 感知 。 真正启用 link,一 般要 等 client 调 ntb_link_enable()。
idt_init_mws() 扫描 Memory Window。IDT 支持 Direct MW 和 LUT MW。Direct MW 是一个 BAR 对 应 一 段转换窗 口 ; LUT MW 则 把 BAR 分成 多 个 entry,每个 entry 可以 独 立配置 目标 。
idt_init_msg() 初始化 message 机制 。message 和 doorbell 都属于控制面 , 但 message 可以 携带 一个 小值 , 还带 有 状态位 。
中断入口会分 发 link event、doorbell event、message event 等,再通过 ntb_link_event、ntb_db_event、ntb_msg_event 通知 NTB core。硬件驱动不直接 调用具体 client。
最后 idt_register_device() 会 填 好 struct ntb_dev 和 struct ntb_dev_ops,然后 调用 ntb_register_device()。从这一 刻 开始,上 层 client 才 能 probe 到这个 NTB 设备。
IDT 驱动实现了 link、MW、doorbell、message 等 ops, 其 中 比较典 型的是 peer_mw_set_trans。它配置的是本地 outbound MW, 让 本地 写 MW aperture 时可以 访问 peer 提 供 的 目标 地 址 。
因此 ,IDT 驱动的骨架可以 概括 为:PCI probe 识别 NT function,映射 控制 BAR,扫描端口 和 MW,建立中断,再注册 ntb_dev。