首页/目录/全部文章

全部文章

八个专题的源码、算法与协议笔记都在这里。

笔记列表

07 PTP 与硬件时间戳

07 PTP 与硬件时间戳

源码:stmmac_ptp.cstmmac_hwtstamp.cstmmac_ptp.h
核心协作:stmmac_main.c(RX/TX 时间戳提取)

1. 模块职责

功能 说明
PTP 时钟设备 向内核注册 /dev/ptpX,供 ptp4l 等同步
硬件 TX/RX 时间戳 精确到 ns 的报文时间标记
ioctl 配置 SIOCSHWTSTAMP / SIOCGHWTSTAMP

2. 架构

ptp4l / chrony/dev/ptpXptp_clock_opsPTP 寄存器 via ptp opsskb hwtstampsstmmac_get_rx/tx_hwtstampdescriptor timestamp 域

3. PTP 时钟(stmmac_ptp.c)

3.1 注册

1
2
3
stmmac_init_ptp()
→ stmmac_init_tstamp_counter()
→ ptp_clock_register(&priv->ptp_clock_ops)

priv->ptp_clock 为内核 struct ptp_clock *

3.2 ptp_clock_ops

回调 作用
adjfreq stmmac_adjust_freq() — 调整 addend 微调频率
adjtime 步进调整系统时间
gettime64 读硬件时间
settime64 设置硬件时间
enable PPS 输出等

3.3 频率调整

通过 stmmac_config_addend() 修改 sub-nanosecond increment 寄存器,实现 ppb 级频率校正。

4. 硬件时间戳 ops

stmmac_hwtstamp.c 提供 stmmac_ptpstmmac_hwtimestamp 结构):

方法 说明
config_hw_tstamping 使能 TX/RX timestamp
config_sub_second_increment 亚秒增量
init_systime 初始化系统时间
adjust_systime 加减时间
get_systime 读取 64 位时间

PTP 寄存器基址:priv->ptpaddr = ioaddr + PTP_GMAC4_OFFSET(GMAC4)。

5. TX/RX 报文时间戳

5.1 TX

  1. stmmac_enable_tx_timestamp() 在 descriptor 设 TS bit
  2. 发送完成后 get_tx_timestamp_status() 检查有效
  3. stmmac_get_tx_hwtstamp() 从 descriptor 或 MAC 寄存器取时间
  4. 填入 skb_shinfo(skb)->tx_flags / hwtstamps

5.2 RX

  1. rx_status / extended status 指示 PTP 报文类型
  2. stmmac_get_rx_hwtstamp() 解析 RDES 时间戳字段
  3. skb_hwtstamps 交给上层

5.3 ioctl

stmmac_hwtstamp_set/get() 处理 struct hwtstamp_config

  • HWTSTAMP_FILTER_*:哪些报文打戳
  • tx_type / rx_filter:one-step / two-step 等

6. 与描述符关系

GMAC4 extended descriptor 含:

  • PTP 报文类型(Sync、Follow_Up、Delay_Req 等)
  • Timestamp valid / dropped 标志

统计计数在 stmmac_extra_statsptp_rx_msg_type_*)。

7. RK3588 注意点

  • CONFIG_PTP_1588_CLOCK 内核选项
  • PTP 参考时钟由平台 clk_ptp_ref / ptp_clk_freq_config 提供
  • ethtool -T eth0 查看时间戳能力

8. 相关文档

08 TC 流量控制卸载

08 TC 流量控制卸载

源码:stmmac_tc.c
HWIF:stmmac_tc_opsdwmac510_tc_ops 等)
依赖:内核 net/schedtc flowertaprio

1. 模块职责

将 Linux Traffic Control 部分规则卸载到 DWMAC 硬件:

卸载类型 内核接口 硬件能力
cls_u32 TC_SETUP_CLSU32 Flexible RX Parser (RXP)
flower TC_SETUP_CLSFLOWER L3/L4 filter + action
CBS TC_SETUP_QDISC_CBS MTL Credit-Based Shaper
TAPRIO TC_SETUP_QDISC_TAPRIO EST (Enhanced Scheduled Traffic)
ETF TC_SETUP_QDISC_ETF 发射时间调度

成功初始化后 ndev->hw_features |= NETIF_F_HW_TC

2. 入口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
static int stmmac_setup_tc(struct net_device *dev, enum tc_setup_type type, void *type_data)
{
switch (type) {
case TC_SETUP_CLSU32:
return stmmac_tc_setup_cls_u32(priv, priv, cls);
case TC_SETUP_CLSFLOWER:
return stmmac_tc_setup_cls(priv, priv, cls);
case TC_SETUP_QDISC_CBS:
return stmmac_tc_setup_cbs(priv, priv, qopt);
case TC_SETUP_QDISC_TAPRIO:
return stmmac_tc_setup_taprio(priv, priv, qopt);
// ...
}
}

3. Flexible RX Parser (RXP)

3.1 数据结构

1
2
3
4
5
6
7
8
9
10
11
struct stmmac_tc_entry {
bool in_use;
u32 handle;
struct {
u32 match_data;
u32 match_en;
u8 dma_ch_no; // 重定向到 RX queue
u8 ok_index; // 下一规则索引
// ...
} val;
};

priv->tc_entries[] 数组,上限由 HW 决定。

3.2 cls_u32 流程

  1. tc_find_entry() 分配/查找表项
  2. tc_fill_actions() 解析 action(drop、redirect queue)
  3. stmmac_rxp_config() → mac ops 写硬件 RXP RAM

3.3 flower

匹配 L2/L3/L4 字段,支持:

  • STMMAC_FLOW_ACTION_DROP
  • 重定向到指定 RX queue(RSS 协同)

4. CBS(Credit-Based Shaper)

用于 AVB/IEEE 802.1Qav:

  • stmmac_config_cbs() 配置 idle slope、send slope、credit
  • 绑定到指定 MTL TX queue

5. TAPRIO / EST

IEEE 802.1Qbv 时间感知调度:

  1. stmmac_tc_setup_taprio() 解析 gate control list
  2. stmmac_est_configure() 写 EST 寄存器
  3. stmmac_calc_tas_basetime() 计算 cycle 基准时间(与 PTP 对齐)

需要 DWMAC 5.x + dma_cap.estsel

6. ETF

Early Transmit Feature:按 tc_etf_qopt_offload 指定发射时间,配合 TBS(Time-Based Scheduling)。

7. 初始化

1
2
3
4
stmmac_dvr_probe()
→ stmmac_tc_init(priv, priv)
→ 分配 tc_entries / flow_entries / rfs_entries
→ 默认 all-pass 规则

8. 限制与版本

特性 最低 Core
RXP cls_u32 GMAC4.10+
flower L3/L4 GMAC4 + filter 数量限制
CBS MTL AVB
TAPRIO/EST DWMAC 5.10+
TBS 5.20+ descriptor

RK3588 是否启用取决于具体 Core 版本与 CONFIG_STMMAC_FULL

9. 用户态示例

1
2
3
4
5
6
# CBS(示意)
tc qdisc add dev eth0 parent root handle 100 mqprio ...
tc qdisc replace dev eth0 parent 100:1 cbs ...

# TAPRIO(示意,需硬件支持)
tc qdisc replace dev eth0 parent root taprio ...

10. 相关文档

09 XDP 与 AF_XDP

09 XDP 与 AF_XDP

源码:stmmac_xdp.cstmmac_xdp.h
数据面:stmmac_main.cstmmac_rxstmmac_rx_zcstmmac_xdp_xmit

1. 模块划分

文件 职责
控制面 stmmac_xdp.c 挂载 BPF、绑定 XSK pool、队列模式切换
数据面 stmmac_main.c RX 运行 BPF、XDP_TX、AF_XDP zero-copy

2. XDP 挂载

2.1 ndo_bpf

1
.ndo_bpf = stmmac_bpf,

处理:

  • XDP_SETUP_PROGstmmac_xdp_set_prog()
  • XDP_SETUP_XSK_POOLstmmac_xdp_setup_pool()

2.2 stmmac_xdp_set_prog()

  1. 替换 priv->xdp_progbpf_prog_put 旧程序)
  2. 若从无 XDP 到有 XDP:可能需调整 RX headroom(stmmac_rx_offset()
  3. rx_copybreak 策略交互

3. AF_XDP Zero-Copy

3.1 启用 pool

stmmac_xdp_enable_pool()

  1. 校验 queue 同时具有 RX+TX 能力
  2. 校验 frame size 与 MTU/buffer 一致
  3. 绑定 rx_q->xsk_pool / tx_q->xsk_pool
  4. 设置 af_xdp_zc_qps bitmap
  5. 重启队列:释放旧 page_pool ring,按 XSK umem 重建 descriptor

3.2 NAPI 模式切换

启用 XSK 后 channel 使用 rxtx_napi(合并 poll):

1
rx_napi = rx_q->xsk_pool ? &ch->rxtx_napi : &ch->rx_napi;

stmmac_napi_poll_rxtx() 同时处理 TX clean 与 stmmac_rx_zc()

3.3 stmmac_rx_zc()

  • DMA 直接写入 XSK buffer(用户态 umem)
  • 通过 xsk_buff_alloc / xsk_buff_free 管理
  • 完成后 xsk_tx_completed() / xsk_wake_up() 通知用户态

4. XDP 数据路径(非 zero-copy)

stmmac_rx() 中:

1
2
3
4
5
6
7
8
9
10
11
if (stmmac_xdp_is_enabled(priv)) {
xdp.data = page_address(buf->page) + offset;
xdp.frame_sz = frame_size;
act = bpf_prog_run_xdp(priv->xdp_prog, &xdp);
switch (act) {
case XDP_PASS: /* 继续建 skb */
case XDP_DROP: /* 回收 page */
case XDP_TX: /* stmmac_xdp_xmit */
case XDP_REDIRECT: /* bpf_redirect */
}
}

5. XDP 发送

入口 说明
ndo_xdp_xmit stmmac_xdp_xmit() — bulk XDP 帧发送
XDP_TX action RX 中直接转发到 TX ring
ndo_xsk_wakeup stmmac_xsk_wakeup() — 用户态 kick

stmmac_tx_info.buf_type 区分:

  • STMMAC_TXBUF_T_SKB
  • STMMAC_TXBUF_T_XDP_TX
  • STMMAC_TXBUF_T_XDP_NDO
  • STMMAC_TXBUF_T_XSK_TX

6. 队列要求

AF_XDP zero-copy 要求:

  • 同一 queue index 必须 RX 和 TX 均启用
  • 通常 dedicated queue(如 queue 0 给 XDP,其它给内核栈)

7. 与 page_pool 关系

模式 RX 缓冲来源
普通 page_pool
XDP(无 ZC) page_pool + XDP headroom
AF_XDP ZC xsk_buff_pool(umem)

模式切换需 down/up 接口 或驱动内部 queue reset。

8. 调试

1
2
3
4
5
# 加载 XDP 程序
ip link set dev eth0 xdp obj prog.o sec xdp

# AF_XDP
xdp-loader load eth0 prog.o

9. 相关文档

10 ethtool 与 MMC 统计

10 ethtool 与 MMC 统计

源码:stmmac_ethtool.cmmc_core.cmmc.h
编译:CONFIG_STMMAC_ETHTOOL

1. ethtool 模块

1.1 注册

1
2
3
4
void stmmac_set_ethtool_ops(struct net_device *netdev)
{
netdev->ethtool_ops = &stmmac_ethtool_ops;
}

stmmac_dvr_probe() 早期调用。

1.2 主要接口

ethtool 操作 函数 说明
get_drvinfo stmmac_ethtool_getdrvinfo 驱动名、版本、bus
get_link phylink 委托 链路状态
get/set_link_ksettings stmmac_ethtool_get/set_link_ksettings 速率双工
get/set_ringparam stmmac_get/set_ringparam RX/TX ring 大小
get/set_pauseparam stmmac_get/set_pauseparam 流控
get_ethtool_stats stmmac_get_ethtool_stats 软件+硬件统计
get_sset_count / get_strings 统计项名称与数量
get/set_coalesce 中断合并参数
get/set_rxfh RSS indirection table
get/set_channels 队列数
get_ts_info PTP 时间戳信息
get/set_eee EEE 配置
get/set_wol Wake-on-LAN
self_test stmmac_selftest_run(可选)

1.3 统计数据源

软件统计stmmac_extra_statscommon.h):

  • TX/RX 错误分类(underflow、CRC、watchdog…)
  • IRQ 计数、NAPI poll 次数
  • PTP 报文类型计数
  • MTL/MAC debug 寄存器快照

队列统计stmmac_txq_stats / stmmac_rxq_stats

硬件统计 — 通过 MMC 读取(见下文)

stmmac_get_ethtool_stats() 合并上述来源到 u64 数组。

1.4 ring 参数

1
2
stmmac_get_ringparam()  → dma_rx_size, dma_tx_size
stmmac_set_ringparam() → 需 down 设备后 stmmac_reinit_ringparam()

范围:DMA_MIN_* (64) ~ DMA_MAX_* (1024)。

1.5 coalesce

Per-queue:

  • rx_coal_frames / rx_coal_timer → RIWT、RX IC bit
  • tx_coal_frames / tx_coal_timer → TX IC bit、hrtimer

2. MMC(MAC Management Counters)

2.1 模块职责

mmc_core.c 实现 stmmac_mmc_ops

  • 读 HW 计数寄存器到 struct stmmac_counters
  • 控制 reset-on-read、preset 等模式

2.2 寄存器布局

基址 priv->mmcaddr(GMAC4:MMC_GMAC4_OFFSET

类别 示例寄存器
TX MMC_TX_FRAMECOUNT_GBMMC_TX_OCTETCOUNT_GB
RX MMC_RX_FRAMECOUNT_GBMMC_RX_CRC_ERROR
IPC checksum offload 相关计数

2.3 使用策略

stmmac_mmc_setup() 在 open 时:

1
2
stmmac_mmc_intr_all_mask(priv, priv->mmcaddr);  // 屏蔽 MMC 中断
stmmac_mmc_ctrl(priv, priv->mmcaddr, mode); // reset-on-read 等

驱动 轮询读取 MMC 合并到 ethtool,而非 MMC 中断驱动。

2.4 mmc_ops

方法 说明
ctrl 控制寄存器模式
intr_all_mask 屏蔽所有 MMC 中断
read 批量读计数到 stmmac_counters

XGMAC 使用 dwxgmac_mmc_ops(扩展计数集)。

3. Selftests

CONFIG_STMMAC_SELFTESTS 启用 stmmac_selftests.c

  • ethtool -t 触发
  • MAC loopback、寄存器读写等

4. 常用命令

1
2
3
4
5
6
7
ethtool -i eth0          # 驱动信息
ethtool -S eth0 # 统计
ethtool -g eth0 # ring 参数
ethtool -c eth0 # coalesce
ethtool -k eth0 # offload
ethtool -T eth0 # 时间戳
ethtool -t eth0 online # 自测(若编译启用)

5. debugfs

CONFIG_DEBUG_FSstmmac_init_fs() 创建 debugfs 节点,可 dump MAC/DMA 寄存器(开发调试用)。

6. 相关文档

11 dwmac-rockchip RK3588 平台

11 dwmac-rockchip RK3588 平台

源码:dwmac-rk.cdwmac-rk-tool.cdwmac-rk-tool.h
模块:dwmac-rockchip.koCONFIG_DWMAC_ROCKCHIP
DT compatible:rockchip,rk3588-gmac

1. 模块职责

Rockchip Platform Glue 负责 RK 全系列 SoC 的 DWMAC 适配,RK3588 为其中一代:

  • GRF/PHP GRF 引脚复用(RGMII/RMII/SGMII)
  • 多路时钟树管理与速率相关分频
  • XPCS SerDes(SGMII/QSGMII)
  • OTP / vendor storage MAC 地址
  • 内置 PHY 供电、CSU 时钟隔离
  • 调用 stmmac_dvr_probe() 进入通用核心

2. 数据结构

2.1 rk_gmac_ops

SoC 差异通过 ops 表抽象:

1
2
3
4
5
6
7
8
9
10
struct rk_gmac_ops {
void (*set_to_rgmii)(struct rk_priv_data *bsp, int tx_delay, int rx_delay);
void (*set_to_rmii)(struct rk_priv_data *bsp);
void (*set_to_sgmii)(struct rk_priv_data *bsp);
void (*set_to_qsgmii)(struct rk_priv_data *bsp);
void (*set_rgmii_speed)(struct rk_priv_data *bsp, int speed);
void (*set_rmii_speed)(struct rk_priv_data *bsp, int speed);
void (*set_clock_selection)(struct rk_priv_data *bsp, bool input, bool enable);
void (*integrated_phy_power)(struct rk_priv_data *bsp, bool up);
};

RK3588:rk3588_ops(约 2270 行起)。

2.2 rk_priv_data

1
2
3
4
5
6
7
8
9
10
struct rk_priv_data {
phy_interface_t phy_iface;
struct clk *clk_mac, *mac_clk_rx, *mac_clk_tx;
struct clk *aclk_mac, *pclk_mac, *clk_phy;
struct regmap *grf, *php_grf, *xpcs;
int tx_delay, rx_delay;
struct regulator *regulator;
const struct rk_gmac_ops *ops;
// ...
};

存入 plat_dat->bsp_priv,核心通过 get_stmmac_bsp_priv(dev) 取回。

3. Probe 流程

stmmac_dvr_proberk_gmac_setupstmmac_platformrk_gmac_probestmmac_dvr_proberk_gmac_setupstmmac_platformrk_gmac_probestmmac_get_platform_resourcesstmmac_probe_config_dthas_gmac4 兜底sph_disable = truerk_gmac_setup (时钟/GRF)rk_gmac_csu_init / clk_init / powerupstmmac_dvr_probedwmac_rk_create_loopback_sysfs

3.1 平台特有设置

1
2
3
4
plat_dat->fix_mac_speed = rk_fix_speed;
plat_dat->get_eth_addr = rk_get_eth_addr;
plat_dat->integrated_phy_power = rk_integrated_phy_power;
plat_dat->sph_disable = true;
  • sph_disable:RK 平台默认关闭 Split Header
  • has_gmac4:DT 未指定时 fallback 到 legacy GMAC

4. 接口模式配置

4.1 RGMII

rk3588_set_to_rgmii()

  • 写 GRF 切换 RGMII 模式
  • 配置 tx_delay / rx_delay(DT 属性 tx_delayrx_delay

4.2 RMII

rk3588_set_to_rmii() + 共享 speed 配置。

4.3 SGMII / QSGMII

  • 配置 XPCS 寄存器(xpcs_read/write
  • PCS 模式、自协商使能
  • 可能涉及 php_grf SerDes 电源

5. 速率切换

rk_fix_speed() → phylink link up 时调用:

1
2
3
rk3588_set_gmac_speed(bsp_priv, speed)
→ 100/1000/2500 对应不同 clock mux
→ 写 GRF speed 位

stmmac_mac_link_up() 配合完成 MAC 侧速率匹配。

6. 时钟

rk_gmac_clk_init() 获取并 prepare/enabled:

时钟 用途
clk_mac MAC 主时钟
mac_clk_rx / mac_clk_tx RGMII RX/TX
aclk_mac / pclk_mac AXI/APB
clk_phy 外接 PHY 参考
pclk_xpcs XPCS APB

rk_gmac_powerup/powerdown 配合 runtime PM。

7. MAC 地址

rk_get_eth_addr() 优先级:

  1. Device Tree local-mac-address
  2. Rockchip vendor storage / OTP
  3. 随机 MAC(核心 fallback)

8. RK3588 硬件拓扑

RK3588 通常有 两个 GMAC

控制器 DT 节点 常见用途
GMAC0 gmac0 RGMII + 外接 PHY
GMAC1 gmac1 RGMII 或 SGMII

具体以板级 DTS(rk3588-*.dtsi)为准。

9. 环回测试工具

CONFIG_DWMAC_ROCKCHIP_TOOL 启用 dwmac-rk-tool.c

  • sysfs 接口创建环回测试
  • 用于产测/驱动验证

10. DTS 配置示例要点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
gmac0: ethernet@fe1b0000 {
compatible = "rockchip,rk3588-gmac";
reg = <0x0 0xfe1b0000 0x0 0x10000>;
interrupts = <GIC_SPI ...>;
clocks = <&cru ...>, ...;
clock-names = "stmmaceth", "mac_clk_rx", ...;
resets = <&cru SRST_A_GMAC0>;
reset-names = "stmmaceth";
rockchip,grf = <&grf>;
snps,axi-config = <&gmac0_axi_setup>;
snps,mtl-rx-config = <&gmac0_mtl_rx>;
snps,mtl-tx-config = <&gmac0_mtl_tx>;
phy-mode = "rgmii";
phy-handle = <&rgmii_phy0>;
tx_delay = <0x30>;
rx_delay = <0x10>;
};

11. 调试建议

现象 排查
无链路 PHY 供电、phy-mode、delay 参数
千兆不稳 tx_delay/rx_delay 微调
SGMII 不通 XPCS 寄存器、SerDes 时钟
无 MAC 地址 vendor storage、DT local-mac-address
1
2
3
dmesg | grep stmmac
ethtool eth0
cat /sys/class/net/eth0/device/uevent

12. 相关文档

12 Legacy GMAC 与 XGMAC 扩展

12 Legacy GMAC 与 XGMAC 扩展

源码:GMAC3 系列、DWMAC5、DWXGMAC2、DWXLGMAC2
编译:依赖 CONFIG_STMMAC_FULL

1. 概述

除 RK3588 主要使用的 GMAC4 (Core 4.10+) 外,STMMAC 仍保留对老 IP 与高端 IP 的支持。这些实现通过 hwif.cstmmac_hw[] 表挂接,核心数据路径逻辑复用 stmmac_main.c

2. Legacy GMAC3 系列

2.1 DWMAC100 / DWMAC1000

文件 Core 说明
dwmac100_core.c 10/100 最老 IP,无 MTL
dwmac100_dma.c 简单 DMA
dwmac1000_core.c 10/100/1000 GMAC 经典 GMAC
dwmac1000_dma.c 单队列 DMA

版本寄存器:GMAC_VERSION(非 GMAC4_VERSION)。

平台标志:plat->has_gmac = true

2.2 描述符变体

文件 类型
norm_desc.c 普通 descriptor(ndesc_ops
enh_desc.c 增强 descriptor(enh_desc_ops

stmmac_dwmac1_quirks() 根据 plat->enh_desc 和 Core ≥ 3.50 选择,决定是否 extend_desc

2.3 Ring / Chain 模式

文件 说明
ring_mode.c 环形 desc3
chain_mode.c 链式 desc3

模块参数 chain_modehas_sun8i 强制 chain。
GMAC4 使用 dwmac4_ring_mode_ops(独立实现)。

3. DWMAC4 早期版本

Core ID ops 说明
0x40 dwmac4_ops 首个 GMAC4
0x41+ dwmac410_ops 4.10,RK3588 类

差异主要在 MTL 特性、filter 数量、TC 支持。

4. DWMAC5 扩展

文件dwmac5.cdwmac5.h

Core ID:0x50、0x51、0x52

新增能力:

特性 说明
FPE Frame Preemption(802.1Qbu),fpe_configure
Safety ECC/parity,safety_feat_*
EST Enhanced Scheduled Traffic(TAPRIO 硬件)
TBS Time-Based Scheduling descriptor
DCHE Descriptor cache / HW prefetch(≥ 5.20)

stmmac_main.c 中 FPE 使用独立 workqueue fpe_wq 处理握手。

5. DWXGMAC(2.5G / 10G)

文件

  • dwxgmac2_core.c
  • dwxgmac2_dma.c
  • dwxgmac2_descs.c
  • dwxgmac2.h

匹配has_xgmac=true,Synopsys ID 0x21,dev_id 0x76(DWXGMAC_ID)

特点:

  • 10G 速率掩码(mac_link.xgmii
  • 独立 MDIO 格式(MII_XGMAC_*
  • XPCS 集成常见
  • dwxgmac210_desc_ops 扩展描述符

6. DWXLGMAC(25G+)

文件dwxlgmac2.h + dwxlgmac2_setup()

匹配:min_id 0x20,dev_id 0x27(DWXLGMAC_ID)

  • mac_device_info.xlgmac = true
  • 支持 25G/40G/50G/100G 链路掩码(mac_link.xlgmii
  • 复用 XGMAC DMA/desc ops

7. 版本选择逻辑小结

plat->has_xgmac?读 GMAC4_VERSION + dev_idplat->has_gmac4?读 GMAC4_VERSION读 GMAC_VERSION legacystmmac_hw[] 匹配

8. RK3588 与 FULL 配置

Rockchip defconfig 通常:

1
2
3
CONFIG_STMMAC_ETH=y
CONFIG_STMMAC_FULL=y
CONFIG_DWMAC_ROCKCHIP=y

FULL 使内核包含全部 IP 变体代码,运行时仍按实际 Core ID 只绑定一套 ops。
CONFIG_STMMAC_FULL=n,仅保留 GMAC4.10 最小集,减小镜像体积。

9. 何时阅读这些模块

场景 阅读
RK3588 千兆以太 04 + 11 文档即可
移植老 SoC(GMAC3) dwmac1000_* + norm/enh_desc
2.5G/10G Rockchip 新芯片 dwxgmac2_*
TAS/FPE 工业网络 dwmac5 + stmmac_tc

10. 相关文档

stmmac 文档索引(RK3588 树)

stmmac 文档索引(RK3588 树)

Linux 6.1(RK3588)内核 Synopsys DWMAC / STMMAC 以太网驱动 源码分析与原理说明。

源码路径:rk3588/kernel-6.1/drivers/net/ethernet/stmicro/stmmac/(约 78 文件)。

总览文档

文档 说明
stmmac网卡驱动机制与原理详解.md 总览:分层架构、数据路径、编译产物、RK3588 关联
源码目录与模块索引.md 目录树、Makefile/Kconfig、文件职责速查

功能组专题(原理 + 实现)

编号 文档 源码重点
01 总体架构与分层设计.md 三层架构、核心数据结构、设计模式
02 stmmac_main核心驱动.md probe/open/xmit/rx/NAPI/中断/ndo
03 hwif硬件抽象层.md ops 表、版本探测、stmmac_hwif_init
04 dwmac4与描述符DMA.md GMAC4 core/dma/desc、ring/chain 模式
05 Platform平台Glue层.md stmmac_platform.c、DT 解析、PCI
06 mdio与phylink.md MDIO 总线、phylink 链路管理
07 PTP与硬件时间戳.md PTP 时钟、TX/RX hwtstamp
08 TC流量控制卸载.md CBS/TAPRIO/flower/cls_u32
09 XDP与AF_XDP.md BPF、zero-copy、xsk pool
10 ethtool与MMC统计.md ethtool ops、MMC 硬件计数器
11 dwmac-rockchip-RK3588.md 时钟/GRF/XPCS、DT、probe 流程
12 legacyGMAC与XGMAC扩展.md GMAC3/1000、DWXGMAC2、DWXLGMAC

源码路径

1
2
3
rk3588/kernel-6.1/drivers/net/ethernet/stmicro/stmmac/
include/linux/stmmac.h # plat_stmmacenet_data
arch/arm64/boot/dts/rockchip/rk3588*.dtsi # gmac 节点

阅读顺序建议

总览01 架构02 stmmac_main03 hwif04 dwmac405 Platform11 RK358806 phylink07 PTP08 TC09 XDP10 ethtool12 XGMAC

速查

需求 入口
驱动 probe stmmac_dvr_probe()stmmac_main.c
RK3588 平台 probe rk_gmac_probe()dwmac-rk.c
设备 UP stmmac_open()__stmmac_open()
发包 stmmac_xmit() / stmmac_tso_xmit()
收包 stmmac_rx() / stmmac_rx_zc()
中断/NAPI stmmac_dma_interrupt()stmmac_napi_poll_rx/tx()
HW 版本选择 stmmac_hwif_init()hwif.c
DT 兼容 rockchip,rk3588-gmac

关联文档

STMMAC 网卡驱动机制与原理详解

STMMAC 网卡驱动机制与原理详解

源码:rk3588/kernel-6.1/drivers/net/ethernet/stmicro/stmmac/
适用平台:Synopsys DesignWare Ethernet MAC(DWMAC),RK3588 使用 GMAC4 (Core 4.10+)

1. 驱动定位

STMMAC 是 Linux 内核中对 Synopsys DWMAC IP 的通用 netdev 驱动,最初由 STMicroelectronics 维护,现由 Synopsys/社区共同演进。Rockchip RK3588 内置两个 GMAC 控制器,通过 dwmac-rockchip.kodwmac-rk.c)接入本驱动栈。

属性 说明
总线 Platform(SoC 内置)、PCI(部分 x86/Intel)
网络接口 标准 struct net_device,多 TX/RX 队列
链路管理 phylink(统一 RGMII/RMII/SGMII/PCS)
RX 缓冲 page_pool(页级分配,支持 GRO/XDP)
硬件抽象 HWIF ops 表(按 Synopsys Core ID 选择实现)

2. 硬件 IP 结构

Synopsys DWMAC 自 Core 4.0 起采用 MAC + MTL + DMA 三层结构:

PHY / PCS / SerDesMAC CoreMTL 多队列调度DMA + Descriptor RingAXI/AHB
  • MAC:地址过滤、VLAN、流控、RSS、PTP 时间戳
  • MTL(MAC Transaction Layer):TX/RX 队列、调度算法(DWRR/WRR/SP 等)
  • DMA:descriptor ring 管理,与 Linux DMA API 对接

3. 软件分层架构

flowchart TB
    subgraph L1["L1 Platform Glue"]
        RK["dwmac-rk.c"]
        PLAT["stmmac_platform.c"]
    end

    subgraph L2["L2 Core Driver"]
        MAIN["stmmac_main.c"]
        FEAT["mdio / ptp / tc / xdp / ethtool"]
    end

    subgraph L3["L3 HWIF"]
        HWIF["hwif.c"]
        IMPL["dwmac4_* / dwxgmac2_*"]
    end

    L1 -->|"stmmac_dvr_probe()"| L2
    L2 -->|"stmmac_hwif_init()"| L3
    L3 --> HW["Synopsys IP 寄存器"]

各层职责

层级 代表文件 职责
L1 Glue dwmac-rk.c DT、时钟、复位、GRF 引脚复用、MAC 地址
L2 Core stmmac_main.c netdev 生命周期、DMA ring、NAPI、数据路径
L3 HWIF hwif.c + dwmac4_*.c 屏蔽 IP 版本差异,提供 ops 回调

4. 核心数据结构

4.1 stmmac_priv

驱动私有上下文,挂载在 netdev_priv()

  • ioaddr:MMIO 基址
  • hwmac_device_info:HWIF ops 集合
  • dma_conf:TX/RX queue 与 descriptor ring
  • channel[]:每通道 NAPI 结构
  • phylink:链路状态机
  • platplat_stmmacenet_data:平台配置与回调

4.2 mac_device_info

聚合六类 ops:

ops 职责
mac MAC 寄存器:过滤、流控、MTL、VLAN、RSS
dma DMA 启停、IRQ、tail pointer
desc 描述符格式:init/prepare/status
mode Ring/Chain 模式 desc3 管理
ptp 硬件时间戳寄存器
tc Traffic Control 硬件卸载
mmc 管理计数器

4.3 plat_stmmacenet_data

定义于 include/linux/stmmac.h,Platform Glue 填充后传入 stmmac_dvr_probe(),包含队列数、DMA 大小、PHY 接口、fix_mac_speed() 等回调。

5. 生命周期

5.1 Probe(以 RK3588 为例)

1
2
3
4
5
6
7
8
rk_gmac_probe()
→ stmmac_get_platform_resources() # MMIO/IRQ
→ stmmac_probe_config_dt() # plat_stmmacenet_data
→ rk_gmac_setup() # 时钟/GRF/bsp_priv
→ stmmac_dvr_probe()
→ stmmac_hw_init() / stmmac_hwif_init()
→ stmmac_phy_setup() # phylink + MDIO
→ register_netdev()

5.2 Open / Stop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ip link set eth0 up
→ stmmac_open()
→ stmmac_setup_dma_desc() # 分配 ring
→ __stmmac_open()
→ init RX buffers (page_pool)
→ 配置 MAC/DMA/MTL
→ request_irq + napi_enable
→ phylink_start()
→ stmmac_start_all_dma()

ip link set eth0 down
→ stmmac_release()
→ phylink_stop / disable queues
→ free_irq / napi_disable
→ stmmac_stop_all_dma()
→ free_dma_desc_resources()

6. 数据路径概要

6.1 TX

1
2
3
4
5
6
7
8
dev_queue_xmit()
→ stmmac_xmit()
→ [TSO] stmmac_tso_xmit()
→ DMA map skb
→ stmmac_prepare_tx_desc()
→ set_tx_owner + set_tx_tail_ptr
← TX IRQ → stmmac_napi_poll_tx()
→ stmmac_tx_clean() → 释放 skb

6.2 RX

1
2
3
4
5
6
RX DMA 写 descriptor
→ RX IRQ → stmmac_napi_poll_rx()
→ stmmac_rx()
→ [XDP] bpf 程序
→ build skb → napi_gro_receive()
→ refill RX descriptor

7. 特性支持矩阵(RK3588 / GMAC4)

特性 支持 模块
多队列 TX/RX stmmac_main + dwmac4
TSO/GSO ✓(需 tso_en) stmmac_xmit
RX checksum offload dwmac4_descs
VLAN HW filter/insert dwmac4_core
RSS ✓(需 rss_en) dwmac4_core
PTP 1588 stmmac_ptp
TC CBS/TAPRIO ✓(Core 5.10+) stmmac_tc
XDP / AF_XDP stmmac_xdp + stmmac_main
EEE LPI stmmac_main
WoL ✓(平台配置) stmmac_main

8. RK3588 平台要点

  • DT compatible:rockchip,rk3588-gmac
  • Glue ops:rk3588_ops(RGMII/RMII 引脚复用、时钟、速率)
  • 双 GMAC:gmac0 / gmac1,独立 rk_priv_data
  • 常见接口:RGMII(外接 PHY)、SGMII/QSGMII(经 XPCS)
  • 平台默认:plat_dat->sph_disable = true(禁用 Split Header)

9. 调试入口

手段 说明
ethtool -S eth0 驱动统计 + MMC
ethtool -g/-G eth0 ring 参数
ethtool -k eth0 offload 开关
debugfs CONFIG_DEBUG_FS 下寄存器 dump
dynamic_debug netif_msg_* 控制
dwmac-rk-tool RK 环回 sysfs 测试

10. 专题文档索引

详见 README.md 中编号 01–12 专题文档。

STMMAC 源码目录与模块索引

STMMAC 源码目录与模块索引

源码根目录:rk3588/kernel-6.1/drivers/net/ethernet/stmicro/stmmac/

1. 编译产物(Makefile)

内核模块 对象文件 Kconfig
stmmac.ko 核心驱动 CONFIG_STMMAC_ETH
stmmac-platform.ko 平台总线框架 CONFIG_STMMAC_PLATFORM
dwmac-rockchip.ko Rockchip glue CONFIG_DWMAC_ROCKCHIP
stmmac-pci.ko PCI 入口 CONFIG_STMMAC_PCI

stmmac.ko 组成

1
2
3
stmmac_main.o stmmac_mdio.o dwmac_lib.o mmc_core.o
stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o dwmac4_dma.o
dwmac4_lib.o dwmac4_core.o hwif.o stmmac_tc.o stmmac_xdp.o

CONFIG_STMMAC_FULL=y 时额外链接:

1
2
3
ring_mode.o chain_mode.o dwmac1000_core.o dwmac1000_dma.o
dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o
dwmac5.o dwxgmac2_core.o dwxgmac2_dma.o dwxgmac2_descs.o

可选:

  • CONFIG_STMMAC_ETHTOOLstmmac_ethtool.o
  • CONFIG_STMMAC_SELFTESTSstmmac_selftests.o

2. 文件分类索引

2.1 核心与公共头文件

文件 行数级 职责
stmmac_main.c ~8360 probe/open/stop/xmit/rx/NAPI/IRQ/phylink/EEE
stmmac.h ~410 stmmac_priv、队列结构、对外 API
common.h ~580 统计结构、mac_device_info、版本常量
hwif.h / hwif.c ~640 / ~350 ops 定义与 HW 版本匹配
descs.h / descs_com.h 描述符位域定义

2.2 GMAC4(RK3588 主要路径)

文件 职责
dwmac4.h GMAC4 寄存器偏移与常量
dwmac4_core.c MAC 层:过滤、VLAN、RSS、MTL 队列
dwmac4_dma.c DMA 通道启停、IRQ、ring 指针
dwmac4_descs.c GMAC4 描述符 prepare/status
dwmac4_lib.c 公共辅助函数
dwmac5.c / dwmac5.h DWMAC 5.x 扩展(FPE、safety 等)

2.3 Legacy GMAC / XGMAC

文件 适用 Core
dwmac100_core.c / dwmac100_dma.c DWMAC100
dwmac1000_core.c / dwmac1000_dma.c DWMAC1000 (GMAC)
norm_desc.c / enh_desc.c GMAC3 普通/增强描述符
dwxgmac2_core.c / dwxgmac2_dma.c / dwxgmac2_descs.c DWXGMAC 2.5G/10G
dwxlgmac2.h + setup DWXLGMAC 25G+

2.4 Ring 模式

文件 职责
ring_mode.c 环形 descriptor 链表
chain_mode.c 链式 descriptor(sun8i 等强制)
dwmac_lib.c 跨版本 DMA 公共例程

2.5 功能模块

文件 职责
stmmac_mdio.c MDIO/MII 总线、Clause 45
stmmac_ptp.c ptp_clock 注册、频率/时间调整
stmmac_hwtstamp.c ioctl 时间戳配置、PTP 寄存器 ops
stmmac_ptp.h PTP 寄存器操作表
stmmac_tc.c TC offload(CBS/TAPRIO/flower)
stmmac_xdp.c / stmmac_xdp.h XDP/AF_XDP 控制面
stmmac_ethtool.c ethtool 全量接口
mmc_core.c / mmc.h MMC 硬件计数器读写
stmmac_selftests.c ethtool 自测
stmmac_uio.c UIO 接口(DPDK)
stmmac_pcs.h PCS 内联辅助
altr_tse_pcs.c Altera PCS

2.6 Platform Glue

文件 SoC/平台
stmmac_platform.c 通用 DT 解析、stmmac_probe_config_dt
stmmac_platform.h 平台 API
dwmac-rk.c Rockchip 全系列含 RK3588
dwmac-rk-tool.c RK 环回测试 sysfs
dwmac-generic.c 无特殊逻辑通用平台
dwmac-imx.c NXP i.MX
dwmac-qcom-ethqos.c Qualcomm
dwmac-intel.c / dwmac-intel-plat.c Intel
dwmac-stm32.c / dwmac-sti.c ST
dwmac-meson.c / dwmac-sunxi.c 其它 SoC
stmmac_pci.c PCI 探测

3. 外部头文件依赖

头文件 用途
include/linux/stmmac.h plat_stmmacenet_data、DMA/队列配置
include/linux/netdevice.h net_devicenapi_struct
include/linux/phylink.h 链路抽象
include/linux/ptp_clock_kernel.h PTP 时钟
include/net/page_pool.h RX 页池
include/net/xdp_sock_drv.h AF_XDP

4. RK3588 相关文件清单

类型 路径
驱动 dwmac-rk.c, dwmac-rk-tool.c
Kconfig CONFIG_DWMAC_ROCKCHIP, CONFIG_DWMAC_ROCKCHIP_TOOL
DTS rk3588.dtsigmac0/gmac1 节点
公共 API include/linux/stmmac.h

5. 关键符号速查

符号 文件
stmmac_dvr_probe stmmac_main.c
stmmac_hwif_init hwif.c
stmmac_hw[] hwif.c(版本表)
stmmac_netdev_ops stmmac_main.c
dwmac4_ops / dwmac410_dma_ops dwmac4_core.c / dwmac4_dma.c
rk_gmac_probe dwmac-rk.c
rk3588_ops dwmac-rk.c
stmmac_set_ethtool_ops stmmac_ethtool.c

Host Bridge、枚举与 PCI 设备生命周期

Host Bridge、枚举与 PCI 设备生命周期

1. 三类核心对象

  • struct pci_host_bridge:一个 Root Complex 对 PCI Core 的入口,提供配置访问ops、总线号范围、CPU/PCI 地址窗口和固件节点。
  • struct pci_bus:一段 PCI 总线,保存numberprimary/secondary/subordinate、上游桥、设备及子总线链表。
  • struct pci_dev:一个 Function,而不是一张物理卡;0000:01:00.1会对应独立对象。

父子关系是:

1
2
3
4
5
6
pci_host_bridge
-> root pci_bus
-> pci_dev(endpoint)
-> pci_dev(bridge)
-> subordinate pci_bus
-> pci_dev(...)

2. Host 注册主链

平台控制器准备好配置空间访问和地址窗口后调用:

1
2
3
4
5
6
7
8
pci_host_probe()
-> pci_scan_root_bus_bridge()
-> pci_register_host_bridge()
-> pci_scan_child_bus()
-> claim firmware resources
或 size bridges + assign resources
-> pcie_bus_configure_settings()
-> pci_bus_add_devices()

关键入口在probe.c

  • pci_host_probe():3096 行;
  • pci_scan_root_bus_bridge():3190 行;
  • pci_scan_slot():2701 行。

Host Bridge 注册与设备扫描是两个阶段。前者把 Root Bus 纳入设备模型,后者才通过配置读发现 Function。

3. 单个 Function 如何被发现

扫描本质是配置空间访问,不是广播“请设备上报”:

1
2
3
4
5
6
7
8
pci_scan_child_bus()
-> pci_scan_slot(bus, devfn)
-> pci_scan_single_device()
-> pci_scan_device()
-> pci_bus_read_dev_vendor_id()
-> pci_alloc_dev()
-> pci_setup_device()
-> pci_device_add()

第一次关键读取是偏移PCI_VENDOR_ID的 32 位值。无设备通常返回0xffffffff;CRS 响应则按超时策略重试。随后读取 Header Type、Class、BAR、Subsystem ID 和 Capability。

access.c中的pci_bus_read_config_*()最终调用bus->ops->read()。因此 PCI Core 决定“读哪个 BDF/偏移”,RK3588 DWC Host 决定“如何把它变成 CFG0/CFG1 事务”。

4. 桥递归

发现 PCI-to-PCI Bridge 后,pci_scan_bridge()处理:

  1. 读取或分配 secondary/subordinate bus number;
  2. 创建 subordinate pci_bus
  3. 递归pci_scan_child_bus()
  4. 回填 subordinate 范围;
  5. 后续资源阶段为桥配置 I/O、MEM、Prefetchable MEM 窗口。

PCIe Root Port、Downstream Port 在 Linux 枚举层仍按桥处理。典型点到点 PCIe 链路只扫描 Device 0,但 quirk、ARI 或扫描标志可改变策略。

5. 加入设备模型与驱动绑定

pci_device_add()先将对象加入 PCI 拓扑;pci_bus_add_devices()再递归调用pci_bus_add_device()。设备进入 Linux Driver Core 后:

1
2
3
4
5
device_attach()
-> pci_bus_match()
-> pci_device_probe()
-> local_pci_probe()
-> pci_driver->probe()

__pci_register_driver()位于pci-driver.c:1447,把drv->driver.bus设为pci_bus_type并调用driver_register()。匹配依据静态pci_device_id、动态 ID 和driver_override,不是 DT compatible。

6. 引用、锁与并发

  • pci_dev_get()/pci_dev_put()保护pci_dev引用;
  • pci_bus_sem保护全局和总线设备链表的读写;
  • pci_lock_rescan_remove()串行化 rescan 与 remove;
  • 配置空间访问通常由pci_lock串行化;
  • 遍历期间若跨越可能睡眠或设备删除的操作,必须持有引用,不能只保存裸指针。

search.c中的pci_get_device()pci_get_slot()搜索的是已注册对象,并返回带引用的pci_dev。它们不会访问硬件。

7. 移除路径

remove.c的公开入口:

  • pci_stop_and_remove_bus_device():115 行;
  • 带全局 rescan/remove 锁版本:122 行。

逻辑分为 stop 和 remove:

1
2
3
4
5
6
7
8
pci_stop_bus_device()
-> 先递归停止下游
-> device_release_driver()

pci_remove_bus_device()
-> 先递归删除下游
-> sysfs/IRQ/resources/proc 清理
-> device_unregister()

必须先停止 DMA 和功能驱动,再拆资源与对象。物理拔卡、sysfs remove及错误恢复失败最终都可能进入该路径。

8. Rescan

rescan 在持pci_lock_rescan_remove()时重新扫描槽位或总线,并调用pci_bus_add_devices()。它只能发现“链路和供电已经可访问”的设备,不能替代控制器上电、PERST#释放或链路训练。

9. 生命周期不变量

  1. 配置访问可用后才能扫描;
  2. 桥下游对象不得晚于上游桥停止;
  3. BAR 与 IRQ 必须在设备注销前释放;
  4. pci_driver->remove()返回后驱动不能继续 DMA;
  5. sysfs rescan/remove 与热插拔必须使用同一全局锁避免重复对象和 use-after-free。