TDA4时间同步3 网卡添加虚拟时间戳

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_singleskb_put 设置数据长度 → vport_rx_csum 处理校验和 → napi_gro_receive 送协议栈
  • 完成后分配新 skb 通过 vport_rx_push 推回给硬件

RX 校验和 vport_rx_csum(第1170行):解析 psdata2 中的硬件校验和结果,对非分片的 IPv4/IPv6 TCP/UDP 包设置 CHECKSUM_UNNECESSARY

  1. 网络设备操作(第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

相关推荐
User_芊芊君子1 小时前
无公网 IP 也能跨网互联:8 年技术沉淀的内网穿透 + 异地组网解决方案
网络·网络协议·tcp/ip
HAPPY酷1 小时前
STM32 两种烧录方式对比:Keil Load vs FlyMCU 串口下载
stm32·单片机·嵌入式硬件
geovindu2 小时前
go: Coroutines Pattern
开发语言·后端·设计模式·golang·协程模式
Stick_ZYZ2 小时前
A2A:让 Agent 从单兵作战走向团队协作
java·开发语言·网络·人工智能·python·ai
江屿风2 小时前
C++图论基础拓扑排序算法流食般投喂
开发语言·c++·笔记·算法·排序算法
郝学胜-神的一滴2 小时前
Qt 高级开发 030:QListWidget 右键菜单全解,从策略配置到精准删除的优雅实现
开发语言·c++·qt·程序人生·用户界面
knighthood20012 小时前
ros2-quick-runner插件v0.0.4版本发布
android·java·开发语言
All_Will_Be_Fine噻2 小时前
重建R环境
开发语言·r语言
磊 子2 小时前
二.内核讲解
开发语言·操作系统·系统