2. 内核源码结构分析:u_ecm.c 与 u_ecm.h

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 配置的完整路径:

  1. ecm_mod_init() → 注册 USB 功能驱动
  2. ecm_bind() → 分配 f_ecm 实例,初始化端点
  3. ecm_set_alt() → 根据配置选择高速/全速描述符
  4. ecm_open() → 激活端点,启动网络设备

2.2.2 数据发送链

从网络层到 USB 请求提交的完整路径:

  1. eth_start_xmit() → 网络设备发送回调
  2. ecm_xmit() → 封装 ECM 头,准备 USB 请求
  3. usb_ep_queue() → 将请求提交到批量输出端点
  4. 硬件完成中断 → ecm_tx_complete() → 释放 skb,统计发送

2.2.3 数据接收链

从 USB 请求完成到网络协议栈的路径:

  1. 硬件接收中断 → ecm_rx_complete() → 检查数据完整性
  2. ecm_unwrap() → 解析 ECM 头,提取以太网帧
  3. netif_rx() → 将 skb 送入网络协议栈
  4. 重新分配请求 → usb_ep_queue() → 准备下一次接收

性能瓶颈提示:在高速传输场景下,ecm_unwrap() 中的内存拷贝操作和 usb_ep_queue() 的调用频率是主要瓶颈。调优时应关注请求队列深度和 DMA 缓冲区对齐。

2.3 核心函数调用关系图

ECM Gadget 核心函数调用链 ecm_mod_init() ecm_bind() ecm_set_alt() ecm_open() eth_start_xmit() ecm_xmit() usb_ep_queue() ecm_tx_complete() ecm_rx_complete() ecm_unwrap() netif_rx() usb_ep_queue() 注册与绑定链 数据发送链 数据接收链 网络层触发 USB中断触发 图例:蓝色=注册链 | 绿色=发送链 | 紫色=接收链 | 橙色/青色=完成回调 虚线表示跨模块调用关系,实线表示链内顺序调用

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 数据结构关系图

u_ecm.h 核心数据结构关系 struct f_ecm ECM 功能实例 ecm_ep_descs 端点描述符集合 ecm_notify 通知请求管理 eth_dev 网络设备封装 包含 fs/hs/ss 包含 notify 请求 关联 net_device 数据结构关系说明 f_ecm 通过指针关联端点描述符、通知请求和网络设备,形成完整的 ECM 功能实例

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() 的调用频率和耗时分布,定位瓶颈后再针对性调整参数。