cpsw-proxy-client.c 驱动代码解析
一、驱动定位与核心架构
这是 TI CPSW(Common Platform Ethernet Switch)代理客户端驱动 ,运行在 A72 Linux 侧 ,通过 RPMsg 与运行在 MAIN R5F 核上的 EthFw(Ethernet Firmware)服务器通信,间接控制 CPSW 以太网交换机硬件。
核心设计思想:Linux 不直接操作 CPSW 硬件,而是作为"客户端"向 R5F 上的 EthFw 服务器发送请求,由服务器分配资源并管理底层硬件。这就是"Proxy Client"的含义。
二、数据结构层次
cpsw_proxy_priv (全局驱动实例)
├── rpmsg_device --- RPMsg 通信端点
├── virt_ports[] --- 虚拟端口数组
│ └── virtual_port --- 单个虚拟端口
│ ├── net_device --- Linux 网络设备(eth0/eth1/eth2...)
│ ├── rx_chans[] --- RX DMA 通道数组
│ │ └── rx_dma_chan --- NAPI + hrtimer + UDMA RX通道 + CPPI描述符池
│ ├── tx_chans[] --- TX DMA 通道数组
│ │ └── tx_dma_chan --- NAPI + hrtimer + UDMA TX通道 + CPPI描述符池
│ ├── mcast_list --- 组播地址列表
│ └── vlan_mcast_list[] --- 每VLAN组播列表
├── req_params --- 请求参数(互斥保护)
└── resp_msg --- 响应消息缓冲
两种虚拟端口类型(第41-44行):
VIRT_SWITCH_PORT--- 交换端口,ALE决定转发目的VIRT_MAC_ONLY_PORT--- 纯MAC端口,定向发送到物理MAC口
三、模块功能分块
1. RPMsg 通信层(第226-502行)
回调函数 cpsw_proxy_client_cb(第226行):
- 接收 EthFw 服务器发来的消息
ETHFW_MSG_NOTIFY:处理异步通知ETHFW_NOTIFYCLIENT_HWERROR:硬件错误 → 关闭网络设备ETHFW_NOTIFYCLIENT_RECOVERED:恢复 → 重新打开网络设备
ETHFW_MSG_RESPONSE:请求-响应模式的回复,通过completion唤醒等待者
请求-响应机制 send_request_get_response(第447行):
- 构造请求消息 →
rpmsg_send发送 →wait_for_completion_timeout等待(500ms超时)→ 回调填充响应 → 返回 - 所有请求串行化(
req_params_mutex保护)
消息构造 create_request_message(第300行):支持 15 种请求类型,涵盖:
- RX/TX DMA 通道分配与释放
- MAC 地址分配/注册/注销
- VLAN 加入/离开
- 组播过滤添加/删除
- IPv4 地址注册/注销
- 虚拟端口附加/分离/信息查询/链路状态
2. 虚拟端口生命周期管理(第504-813行)
初始化流程(probe 中依次调用):
get_virtual_port_info() → 向EthFw查询可用端口信息
↓ → 获得 vswitch_ports/vmac_ports 位掩码
attach_virtual_ports() → 逐个附加端口,获取 token/features/通道数
↓
allocate_port_resources() → 分配RX流、TX线程、MAC地址
↓
init_tx_chans() / init_rx_chans() → 创建UDMA通道和CPPI描述符池
↓
init_netdevs() → 创建net_device并注册
↓
register_dma_irq_handlers() → 注册DMA中断
清理流程 :反向释放,包含 detach_virtual_ports() 通知 EthFw 释放远端资源。
3. TX 发送路径(第1845-2000行)
vport_ndo_xmit --- 核心发送函数:
skb → DMA映射 → 分配CPPI5描述符 → 填充psdata(校验和卸载) →
处理非线性skb的frags → skb_tx_timestamp() → BQL更新 →
k3_udma_glue_push_tx_chn() 推送到UDMA → 流控检查
关键细节:
- 第1891-1894行:Switch端口由ALE路由,MAC端口则设置
port_id定向发送 - 第1903-1913行:TX 校验和卸载,通过
psdata[2]传递偏移信息给硬件 - 第1954行:
skb_tx_timestamp(skb)--- 软件发送时间戳(已在主线代码中) - 第1972-1983行:描述符池不足时停队列,带 SMP 内存屏障防竞态
TX 完成路径 tx_compl_packets(第1068行):
- 从 UDMA 完成队列
pop描述符 →vport_xmit_free释放 DMA 映射和描述符 →napi_consume_skb释放 skb → BQL 更新 → 唤醒停住的队列
4. RX 接收路径(第1195-1356行)
接收轮询 vport_rx_poll(第1323行):
- NAPI 轮询,每轮 budget 个包
- 调用
vport_rx_packets:从 UDMA pop 描述符 → 解析 psdata 获取校验和信息 →dma_unmap_single→skb_put设置数据长度 →vport_rx_csum处理校验和 →napi_gro_receive送协议栈 - 完成后分配新 skb 通过
vport_rx_push推回给硬件
RX 校验和 vport_rx_csum(第1170行):解析 psdata2 中的硬件校验和结果,对非分片的 IPv4/IPv6 TCP/UDP 包设置 CHECKSUM_UNNECESSARY。
- 网络设备操作(第1810-2093行)
| NDO 回调 | 函数 | 功能 |
|---|---|---|
ndo_open |
vport_ndo_open |
开启DMA通道、NAPI、注册MAC到EthFw |
ndo_stop |
vport_ndo_stop |
注销MAC、停止DMA、teardown |
ndo_start_xmit |
vport_ndo_xmit |
发送数据包 |
ndo_get_stats64 |
vport_ndo_get_stats |
per-CPU 统计聚合 |
ndo_tx_timeout |
vport_ndo_tx_timeout |
超时诊断与恢复 |
ndo_set_rx_mode |
vport_set_rx_mode |
组播过滤(通过workqueue) |
ndo_vlan_rx_add_vid |
vport_add_vid |
加入VLAN |
ndo_vlan_rx_kill_vid |
vport_del_vid |
离开VLAN |
组播管理 (第1588-1691行):不支持混杂模式,组播过滤由 EthFw 服务器执行。Switch 端口需要 ETHFW_MCAST_FILTERING feature 才支持。
6. Ethtool 操作(第1374-1503行)
| 回调 | 功能 |
|---|---|
get_link |
MAC端口通过RPMsg查询链路状态;Switch端口用通用实现 |
get/set_coalesce |
配置 RX/TX 中断合并(hrtimer pacing),最小 20us |
get/set_per_queue_coalesce |
按队列配置中断合并 |
get_ts_info |
声明软件时间戳能力(本次新增) |
7. IPv4 地址同步(第2398-2516行)
Switch 端口注册 inetaddr_notifier,当 IP 地址变化时自动向 EthFw 注册/注销 IPv4 地址(用于硬件路由)。
8. 驱动注册与平台适配(第2541-2665行)
SoC 适配:
| SoC | DMA 兼容字符串 | |
|---|---|---|
| J7200/J721E/J784S4 | ti,j721e-navss-main-udmap |
|
| AM62PX | ti,am64-dmss-pktdma |
|
驱动以 rpmsg_driver 形式注册(module_rpmsg_driver),匹配 ETHFW_SERVICE_EP_NAME 端点名。
四、中断与 NAPI 架构
硬中断 → disable_irq_nosync → napi_schedule
↓
NAPI poll → 批量处理描述符 → napi_complete_done
↓
┌─ 有 pacing → hrtimer 延迟 enable_irq
└─ 无 pacing → 直接 enable_irq
hrtimer pacing 机制允许在高低负载间平衡中断频率,通过 ethtool coalesce 配置。
五、与 EthFw 的关系图
┌─────────────────────────────┐
│ A72 Linux │ 本驱动
│ cpsw-proxy-client │
│ ┌───────────┐ ┌─────────┐ │
│ │ eth0 (SW) │ │eth2(MAC)│ │
│ └─────┬─────┘ └────┬────┘ │
│ │ RPMsg通道 │ │
├────────┼──────────────────┤
│ R5F EthFw Server │
│ ┌─────┴─────┐ ┌────┴────┐│
│ │ CPSW ALE │ │PHY 接口 ││
│ │ 交换逻辑 │ │ MAC ││
│ └───────────┘ └─────────┘│
└─────────────────────────────┘
Linux 侧的每个 virtual_port 对应 EthFw 分配的一个虚拟端口,DMA 通道由 EthFw 远端配置(k3_udma_glue_request_remote_rx_chn_for_thread_id),Linux 侧只负责描述符池管理和数据收发。
六、数据流总结
发送 :skb → DMA映射 → CPPI5描述符链 → UDMA TX推入 → 硬件发送 → 完成中断 → NAPI回收
接收:预分配skb → UDMA RX推入 → 硬件接收 → 完成中断 → NAPI pop → 解析校验和 → 协议栈 → 补充新skb