MHI Endpoint 设备侧实现
1. 角色
MHI_BUS_EP实现MHI链路的设备侧,典型是带PCIe Endpoint的modem SoC。它与Host MHI共用协议概念,但注册独立的mhi_ep bus type和endpoint API。
RK3588作为普通Linux Host时不使用该模块;只有把系统设计成MHI endpoint并提供底层controller glue时才相关。
2. 文件
main.c:controller、bus、device/driver、channel和IRQ work;mmio.c:MHI寄存器、中断状态及host context读写;ring.c:读取Host ring元素、offset推进;sm.c:RESET/READY/M0/M3/SYS_ERR转换;internal.h:channel、ring和事件内部对象。
3. 注册
底层endpoint controller driver构造mhi_ep_cntrl并调用:
1 | mhi_ep_register_controller(config) |
Host写入配置后,mhi_ep_power_up()缓存host contexts、初始化ring并进入协议状态机。
4. Bus设备
Endpoint按照配置中的UL/DL channel创建mhi_ep_device。mhi_ep_driver按mhi_device_id匹配,并在probe时获得成对channel。
方向以endpoint视角定义,使用时需特别核对DMA_TO_DEVICE和DMA_FROM_DEVICE对应Host的UL/DL,避免反向理解。
5. Ring
Host拥有TRE ring内存;Endpoint通过controller callback访问Host地址空间:
1 | read host context |
ring.c维护本地read/write offset并处理wrap。Host地址、元素数和长度必须由transport映射到受限PCIe窗口。
6. 数据API
Endpoint功能driver可:
mhi_ep_queue_skb()向Host发送;- 查询queue是否为空;
- 接收Host数据callback;
- 在channel start/stop时建立或清理资源。
当Host未提供TRE时发送返回-ENOSPC,client应做背压而不是忙循环。
7. 中断与Workqueue
MMIO IRQ读取control、command和channel doorbell状态。较重处理排入controller workqueue:
- state change;
- command ring;
- channel ring;
- reset/error。
中断路径只清状态、记录bitmap和排work,避免在hardirq执行Host内存访问和client callback。
8. 状态机
Endpoint响应Host控制寄存器变化:
1 | RESET |
协议错误进入SYS_ERR,停止channel并通知Host。Power down必须先flush work、销毁channel devices,再释放ring/context。
9. 与Gadget/PCI Endpoint区别
MHI Endpoint不是USB Gadget,也不是通用PCI endpoint function。它依赖外层transport提供:
- Host地址空间读写;
- IRQ触发;
- MMIO寄存器暴露;
- DMA能力;
- link状态。
这些底层能力不由drivers/bus/mhi/ep创建。
10. 安全
Host控制ring地址和TRE内容,endpoint必须视其为不可信输入:
- 验证地址落在允许window;
- 验证长度和channel ID;
- 防止offset/元素数溢出;
- reset时取消所有异步DMA;
- 不在释放channel后继续回调client。
11. 限制
源码仍标记部分TD分片处理为TODO。设计endpoint产品前应结合目标controller glue、Host版本和实际大包/异常reset测试,不应只依据基本loopback成功判断完备性。