2. 内核源码结构分析
ECM(Ethernet Control Model)Gadget 驱动的核心源码位于 drivers/usb/gadget/function/ 目录下,由 u_ecm.c 和 u_ecm.h 两个文件构成。理解这两个文件的数据结构与函数调用链,是进行参数调优与数据传输优化的基础。
2.1 关键数据结构
u_ecm.h 定义了 ECM 驱动的核心数据结构,其中 f_ecm 是驱动实例的载体,ecm_ep_descs 管理端点描述符。
| 数据结构 | 定义文件 | 核心作用 |
|---|---|---|
struct f_ecm |
u_ecm.h | ECM 功能实例,包含网络设备、端点、配置参数等 |
struct ecm_ep_descs |
u_ecm.h | 管理控制、中断、批量端点描述符集合 |
struct ecm_notify |
u_ecm.h | 通知请求结构,用于发送连接状态变化 |
struct eth_dev |
u_ecm.h | 网络设备层封装,关联 net_device |
核心结构体:struct f_ecm
struct f_ecm {
struct usb_function func;
struct usb_ep *in_ep, *out_ep, *notify_ep;
struct ecm_ep_descs fs, hs, ss;
struct ecm_notify notify;
struct eth_dev *dev;
struct net_device *net;
u8 ctrl_id, data_id;
atomic_t online;
unsigned qmult;
unsigned mtu;
// ... 其他调优参数
};
调优关注点:qmult 和 mtu 是直接影响吞吐量的关键字段。qmult 控制每个批量端点的请求队列深度,mtu 决定网络层最大传输单元。
2.2 函数调用链分析
u_ecm.c 实现了 ECM 功能的生命周期管理、USB 请求处理、网络数据收发等核心逻辑。函数调用链可归纳为以下三大主线:
2.2.1 功能注册与绑定链
从模块初始化到功能实例绑定到 USB 配置的完整路径:
ecm_mod_init()→ 注册 USB 功能驱动ecm_bind()→ 分配f_ecm实例,初始化端点ecm_set_alt()→ 根据配置选择高速/全速描述符ecm_open()→ 激活端点,启动网络设备
2.2.2 数据发送链
从网络层到 USB 请求提交的完整路径:
eth_start_xmit()→ 网络设备发送回调ecm_xmit()→ 封装 ECM 头,准备 USB 请求usb_ep_queue()→ 将请求提交到批量输出端点- 硬件完成中断 →
ecm_tx_complete()→ 释放 skb,统计发送
2.2.3 数据接收链
从 USB 请求完成到网络协议栈的路径:
- 硬件接收中断 →
ecm_rx_complete()→ 检查数据完整性 ecm_unwrap()→ 解析 ECM 头,提取以太网帧netif_rx()→ 将 skb 送入网络协议栈- 重新分配请求 →
usb_ep_queue()→ 准备下一次接收
性能瓶颈提示:在高速传输场景下,ecm_unwrap() 中的内存拷贝操作和 usb_ep_queue() 的调用频率是主要瓶颈。调优时应关注请求队列深度和 DMA 缓冲区对齐。
2.3 核心函数调用关系图
2.4 关键函数参数调优对照表
以下表格列出了 u_ecm.c 中直接影响性能的关键函数及其可调参数:
| 函数名 | 可调参数 | 默认值 | 调优方向 |
|---|---|---|---|
ecm_bind() |
qmult |
32 | 增大可提升吞吐,但增加内存占用 |
ecm_set_alt() |
端点描述符选择 | 根据速度自动 | 高速模式下使用 HS 描述符 |
ecm_xmit() |
skb 线性区大小 | ETH_FRAME_LEN | 对齐到 DMA 缓存行可减少拷贝 |
ecm_unwrap() |
头解析逻辑 | 固定偏移 | 可优化为零拷贝解析 |
ecm_open() |
请求预分配数量 | qmult × 2 | 增加可减少运行时分配开销 |
源码阅读建议:在分析 u_ecm.c 时,重点关注 ecm_xmit() 和 ecm_unwrap() 两个函数,它们是数据路径上的核心处理函数,也是调优的主要切入点。建议结合 drivers/usb/gadget/function/u_ether.c 中的 eth_dev 管理逻辑一起阅读。
2.5 数据结构关系图
2.6 源码分析要点总结
- 数据结构层面:
f_ecm是核心结构体,包含端点、网络设备、调优参数等所有关键信息;ecm_ep_descs管理不同速度模式下的端点描述符。 - 函数调用链:分为注册绑定链、数据发送链、数据接收链三条主线,其中发送链和接收链是性能调优的重点。
- 调优入口:
qmult、mtu、请求预分配数量、DMA 对齐等参数均在u_ecm.c中定义或使用。 - 跨文件依赖:
u_ecm.c依赖u_ether.c提供的eth_dev管理功能,分析时需联动阅读。
工程实践建议:在开始调优前,建议先通过 printk 或 tracepoint 跟踪 ecm_xmit() 和 ecm_rx_complete() 的调用频率和耗时分布,定位瓶颈后再针对性调整参数。