Linux 自定义 Bus Type 与设备模型
1. 何时需要自定义总线
platform bus适合固件已描述的MMIO设备。若设备由controller固件动态发现、使用非DT匹配规则,或需要专用modalias和I/O API,就会注册struct bus_type。
本目录典型包括:
mhi与mhi_ep;fsl-mc;sunxi-rsb;moxtet;mips_cdmm。
2. 基本组成
1 | bus_register |
专用device通常内嵌struct device;专用driver内嵌struct device_driver。Core仍由drivers/base提供,bus driver只实现策略和协议。
3. Match
常见匹配键:
| Bus | 匹配对象 |
|---|---|
| MHI Host | channel name和mhi_device_id |
| MHI Endpoint | endpoint channel/device name |
| FSL-MC | vendor/object type/version |
| Sunxi RSB | RSB device ID/compatible |
| MOXTET | module type |
| MIPS CDMM | device type和revision |
Match必须稳定,因为它决定module autoload alias及哪个功能driver获得设备。
4. Controller与功能设备
通常存在两级device:
1 | physical parent (PCI/platform) |
Controller负责:
- transport寄存器和中断;
- DMA/ring或command portal;
- 发现/销毁children;
- PM和错误恢复。
Function driver只使用导出的queue/command API,不直接接管底层硬件生命周期。
5. Uevent与模块加载
自定义bus实现uevent()生成:
1 | MODALIAS=<bus>:<id> |
用户空间udev据MODULE_DEVICE_TABLE加载功能driver。若modalias缺失或匹配表命名不同,device会存在于sysfs但没有driver。
6. Probe/Remove顺序
Controller删除前必须先删除所有child:
1 | stop discovery/IRQ |
device_unregister()可能触发功能driver remove和异步引用释放,不能在child release前释放其parent私有内存。
7. 并发
自定义bus通常至少有:
- bus/device model mutex;
- controller状态锁;
- channel/ring spinlock;
- IRQ/tasklet/workqueue;
- completion或waitqueue;
- runtime PM引用。
Bus match/probe在可睡眠上下文,数据完成常在IRQ线程/tasklet;API必须明确callback上下文。
8. 安全边界
动态枚举ID来自硬件/固件。恶意或故障controller可能报告异常channel、object数、ring长度或DMA地址。Controller driver必须在创建设备和分配内存前验证:
- ID范围;
- 数量上限;
- descriptor长度;
- DMA窗口;
- doorbell/ring索引;
- 固件版本。
9. 与普通simple-bus区别
DT中的simple-bus只是地址层次和OF child枚举约定,不会注册名为simple-bus的Linux bus type。其children通常仍挂platform bus。
因此“DT bus node”和“struct bus_type”是两个不同概念。
正在加载留言…