net: lan743x: speed-based and user-configurable interrupt moderation

网络 · Microchip lan743x 网卡驱动 · 中断聚合/中断调制(interrupt coalescing / moderation)

💡 一句话总结

Microchip lan743x PCIe 网卡驱动原先把固定 400us 的中断调制定时器写入全部 per-vector 寄存器,既不随链路速率变化、也无法被用户态配置;本系列(net-next,v1)把定时器改为随协商速率自适应(2.5G→64us、1G→150us、100M/10M→330us),并新增 ethtool -c 的 get/set_coalesce 接口把聚合能力开放给用户态,从而在高吞吐场景压低聚合引入的延迟、在低速率场景获得更有效的中断聚合。

📋 补丁基本信息

项目内容
补丁类型功能增强(interrupt coalescing 支持 + 默认值改进)
状态In Review(v1,目标 net-next)
当前版本v1 · cover letter / patch 1/2 / patch 2/2
版本演进v1(2026-08-03 首次提交;lore 索引中未见更早版本)
作者机构Microchip(Dhanushkalyan G 与 Thangaraj Samynathan)
提交日期2026-08-03
目标分支net-next(PATCH net-next 0/2)
改动范围3 文件 +144/-11(cover letter 自报统计);patch1 +42/-14、patch2 +117/-12
核心函数lan743x_config_int_mod() / lan743x_get_int_mod() / lan743x_ethtool_get/set_coalesce()

📊 速览卡片

核心机制
中断调制
优化目标
延迟/中断率
适用场景
lan743x 网卡
实测提升
未提供

🎯 解决什么问题

背景 / 原始动机(cover letter 原话)
"The lan743x driver programs a single fixed interrupt moderation timer into all per-vector INT_MOD_CFG registers at interrupt open, regardless of link speed and with no way for userspace to tune it."
即:当前代码在 lan743x_intr_open() 里把单个固定值 LAN743X_INT_MOD (400) 一次性写入全部 10 个 per-vector INT_MOD_CFG 寄存器,之后不再改变;链路速率变了它也不变,用户态没有任何调优入口。
系统层面:中断调制的"速率-延迟"错配
中断调制(interrupt moderation / coalescing)用硬件定时器把一段时间内到达的多个包/事件聚合成一次中断,换取向 CPU 报中断的次数下降(省 CPU),代价是每个中断批次额外引入最多一个定时器周期的聚合延迟。理想做法是让定时器值与包到达速率匹配:链路速率越高、包到达越快,定时器应越短(避免给已高频的中断再叠加大延迟);速率越低、包到达越慢,定时器应越长(聚合更多包)。lan743x 固定 400us 的方案在两种方向上都不合适——这是本系列要解决的核心系统问题。
场景层面:哪些部署会踩到缺陷
  • 2.5G/1G 高吞吐、延迟敏感场景(NVMe-oF/TCP、存储网络、RPC 负载):线速下包间隔仅亚微秒级,固定 400us 的聚合延迟占单包端到端延迟的比例显著,且每批中断的收益与其延迟代价失衡(解读(AI 分析))。
  • 100M/10M 低速率场景:400us 偏短,聚合效率一般,中断率仍有压缩空间。
  • 需要按工作负载调优的运维:无 ethtool -c 接口,无法针对低延迟或低 CPU 场景调整,与其它主流网卡驱动能力不一致。

🧩 核心机制

两枚补丁的职责划分很清晰:Patch 1(Thangaraj Samynathan)把"静态的向量映射"与"按速率的定时器值"解耦,让定时器随链路速率变化;Patch 2(Dhanushkalyan G)在此基础上补上 ethtool 用户接口与自适应/手动两种模式。涉及模块:drivers/net/ethernet/microchip/lan743x_main.c、lan743x_ethtool.c、lan743x_main.h。

Patch 1 — 速率相关的定时器:把"映射"和"数值"分开
  1. 新增 lan743x_config_int_mod(adapter, int_mod) 帮助函数:集中把定时器值写入全部 per-vector INT_MOD_CFG0-9,并把原来散落在 lan743x_intr_open() 里的 10 个寄存器写从这里移走。中断打开时只保留一次性的 INT_MOD_MAP0/1/2 向量映射(静态,不变)。
  2. 宏从单一 LAN743X_INT_MOD(400) 拆成四个按速率的宏:2.5G→64us、1G→150us、100M→330us、10M→330us。
  3. 在 lan743x_phylink_mac_link_up() 中按协商速率写入:链路 up 时根据 speed 选值并调用 lan743x_config_int_mod(),使聚合周期随实际链路速率变化。
为什么这样改:调制定时器是"每链路速率一个最优值",而向量映射是"每芯片一个固定布局",两者生命周期不同,拆开后才好在 link_up 路径单独更新数值。
Patch 2 — ethtool 接口:自适应(默认)与手动两模式
  1. 新增 .get_coalesce/.set_coalesce,并在 supported_coalesce_params 声明 ETHTOOL_COALESCE_USECS | USE_ADAPTIVE_RX | USE_ADAPTIVE_TX(向 ethtool 声明驱动支持"微秒聚合"与"自适应聚合")。
  2. 引入"自适应"语义(默认开启):adapter->use_adaptive_mod = true 时,定时器继续跟随链路速率(link_up 时按速率重算);关闭时固定为用户 rx_coalesce_usecs 指定的值。
  3. 新增速率→值映射 lan743x_get_int_mod(speed)(Patch 1 内联逻辑抽成非 static 函数),供 ethtool 在"重新开启自适应"时立即恢复当前速率对应的值。
  4. 新增 adapter->int_mod 缓存:lan743x_config_int_mod() 先判断新值与已编程值是否相同,相同则跳过寄存器写(避免每次 link_up 无谓重写全部 10 个 CSR)。
  5. 新增 adapter->link_speed 记录:link_up 时记录协商速率,供后续 ethtool 自适应请求取值。
  6. 硬件单值约束的显式校验:硬件所有向量共用一个值,因此 rx_usecs != tx_usecs、或只开单侧自适应,都会用 NL_SET_ERR_MSG_MOD 报出具体原因并返回 -EINVAL。
为什么这样改:让"合理默认"(速率自适应)与"用户覆盖"(固定值)两种运维需求都得到满足,且对硬件无法支持的不对称配置给出可读错误而非静默忽略。

🔬 关键代码

① 速率相关定时器值(Patch 1,宏定义)
-#define LAN743X_INT_MOD	(400)
+#define LAN743X_INT_MOD_2_5G		(64)
+#define LAN743X_INT_MOD_1G		(150)
+#define LAN743X_INT_MOD_100M		(330)
+#define LAN743X_INT_MOD_10M		(330)

▲ 单一固定值拆成 4 个速率档位。2.5G 用最短 64us(包到达最快、延迟代价最敏感),100M/10M 用 330us(聚合效率优先)。数值来源为作者设定,未见 datasheet 出处标注。

② 集中写寄存器的帮助函数(Patch 1)
+/* Program the interrupt moderation timer value into the per-vector
+ * INT_MOD_CFG registers. Only the timer value is written here; the vector
+ * mapping (INT_MOD_MAP) is static and is set once at interrupt open.
+ */
+static void lan743x_config_int_mod(struct lan743x_adapter *adapter, u32 int_mod)
+{
+	if (!(adapter->csr.flags & LAN743X_CSR_FLAG_IS_A0)) {
+		lan743x_csr_write(adapter, INT_MOD_CFG0, int_mod);
+		lan743x_csr_write(adapter, INT_MOD_CFG1, int_mod);
+		lan743x_csr_write(adapter, INT_MOD_CFG2, int_mod);
+		lan743x_csr_write(adapter, INT_MOD_CFG3, int_mod);
+		lan743x_csr_write(adapter, INT_MOD_CFG4, int_mod);
+		lan743x_csr_write(adapter, INT_MOD_CFG5, int_mod);
+		lan743x_csr_write(adapter, INT_MOD_CFG6, int_mod);
+		lan743x_csr_write(adapter, INT_MOD_CFG7, int_mod);
+		if (adapter->is_pci11x1x) {
+			lan743x_csr_write(adapter, INT_MOD_CFG8, int_mod);
+			lan743x_csr_write(adapter, INT_MOD_CFG9, int_mod);
+		}
+	}
+}

▲ 注意 LAN743X_CSR_FLAG_IS_A0 判断:A0 硅片版本不写调制寄存器(驱动既有约束)。is_pci11x1x 的芯片多 2 个向量寄存器(CFG8/CFG9),其余 8 个一致。

③ link_up 按速率写入(Patch 1)
 	mac_cr &= ~(MAC_CR_CFG_H_ | MAC_CR_CFG_L_);
-	if (speed == SPEED_2500)
+	if (speed == SPEED_2500) {
 		mac_cr |= MAC_CR_CFG_H_ | MAC_CR_CFG_L_;
-	else if (speed == SPEED_1000)
+		int_mod = LAN743X_INT_MOD_2_5G;
+	} else if (speed == SPEED_1000) {
 		mac_cr |= MAC_CR_CFG_H_;
-	else if (speed == SPEED_100)
+		int_mod = LAN743X_INT_MOD_1G;
+	} else if (speed == SPEED_100) {
 		mac_cr |= MAC_CR_CFG_L_;
+		int_mod = LAN743X_INT_MOD_100M;
+	} else {
+		int_mod = LAN743X_INT_MOD_10M;
+	}
 
 	lan743x_csr_write(adapter, MAC_CR, mac_cr);
 
+	lan743x_config_int_mod(adapter, int_mod);
+
 	lan743x_ptp_update_latency(adapter, speed);

▲ 原来 link_up 只配 MAC 速率位(MAC_CR_CFG_H_/L_),现在同一处把调制值也一起更新——调制周期与链路速率在同一路径上原子更新,避免"速率已变、聚合周期未变"的窗口。

④ ethtool get_coalesce(Patch 2)
+static int lan743x_ethtool_get_coalesce(struct net_device *netdev,
+					struct ethtool_coalesce *ec,
+					struct kernel_ethtool_coalesce *kernel_coal,
+					struct netlink_ext_ack *extack)
+{
+	struct lan743x_adapter *adapter = netdev_priv(netdev);
+
+	/* The driver programs the same value into every per-vector
+	 * INT_MOD_CFG register, so RX and TX moderation share one value;
+	 * report it for both.
+	 */
+	ec->rx_coalesce_usecs = adapter->int_mod;
+	ec->tx_coalesce_usecs = adapter->int_mod;
+	ec->use_adaptive_rx_coalesce = adapter->use_adaptive_mod;
+	ec->use_adaptive_tx_coalesce = adapter->use_adaptive_mod;
+
+	return 0;
+}

▲ 读取侧:因为硬件单值,RX/TX 报同一值;自适应标志也同步报出。返回的是当前已编程的 adapter->int_mod(即实际生效值)。

⑤ ethtool set_coalesce 校验逻辑(Patch 2)
+	/* RX and TX share a single moderation value, so adaptive mode must be
+	 * enabled or disabled for both together.
+	 */
+	if (ec->use_adaptive_rx_coalesce != ec->use_adaptive_tx_coalesce) {
+		NL_SET_ERR_MSG_MOD(extack,
+				   "adaptive-rx and adaptive-tx must match");
+		return -EINVAL;
+	}
+
+	if (ec->use_adaptive_rx_coalesce) {
+		/* Resume speed-adaptive moderation and apply the value for the
+		 * current link speed right away.
+		 */
+		adapter->use_adaptive_mod = true;
+		int_mod = lan743x_get_int_mod(adapter->link_speed);
+	} else {
+		if (ec->rx_coalesce_usecs != ec->tx_coalesce_usecs) {
+			NL_SET_ERR_MSG_MOD(extack,
+					   "rx-usecs and tx-usecs must be equal");
+			return -EINVAL;
+		}
+		if (ec->rx_coalesce_usecs > LAN743X_INT_MOD_MAX) {
+			NL_SET_ERR_MSG_MOD(extack,
+					   "coalesce value exceeds maximum");
+			return -EINVAL;
+		}
+		adapter->use_adaptive_mod = false;
+		int_mod = ec->rx_coalesce_usecs;
+	}
+
+	lan743x_config_int_mod(adapter, int_mod);
+
+	return 0;
+}

▲ 三条硬约束全部用 NL_SET_ERR_MSG_MOD 给出可读原因:自适应必须 RX/TX 同时开;手动模式 RX 必须等于 TX(硬件单值);上限 LAN743X_INT_MOD_MAX (8191)(13-bit 定时器字段)。

⑥ 缓存 + 自适应默认(Patch 2,三处配套)
+	/* Nothing to do if the value is already programmed in hardware. */
+	if (int_mod == adapter->int_mod)
+		return;
+
 	if (!(adapter->csr.flags & LAN743X_CSR_FLAG_IS_A0)) {
 		lan743x_csr_write(adapter, INT_MOD_CFG0, int_mod);
 		lan743x_csr_write(adapter, INT_MOD_CFG1, int_mod);
@@ -3049,6 +3068,7 @@ static void lan743x_config_int_mod(...)
 			lan743x_csr_write(adapter, INT_MOD_CFG8, int_mod);
 			lan743x_csr_write(adapter, INT_MOD_CFG9, int_mod);
 		}
+		adapter->int_mod = int_mod;
 	}
 }
 
 ...
 	lan743x_csr_write(adapter, MAC_CR, mac_cr);
 
-	lan743x_config_int_mod(adapter, int_mod);
+	/* Track the link speed so a later ethtool request to re-enable
+	 * adaptive moderation can restore the speed-based value, and refresh
+	 * the timer now when adaptive moderation is active.
+	 */
+	adapter->link_speed = speed;
+	if (adapter->use_adaptive_mod)
+		lan743x_config_int_mod(adapter, lan743x_get_int_mod(speed));
 
 	lan743x_ptp_update_latency(adapter, speed);
 
 ...
+	/* Enable speed-adaptive interrupt moderation by default and program
+	 * the timer for the default (1G) value until the link comes up.
+	 */
+	adapter->use_adaptive_mod = true;
+	adapter->link_speed = SPEED_UNKNOWN;
+	lan743x_config_int_mod(adapter, LAN743X_INT_MOD_1G);
 
 	ret = lan743x_gpio_init(adapter);

▲ int_mod 缓存避免值未变时重写全部 10 个 CSR;link_up 只在自适应开启时才重算(手动模式下用户固定值不被链路事件覆盖);hardware_init 把自适应设为默认并预写 1G 值。

📈 性能影响

作者自报数据
未提供。cover letter 与两枚补丁均未附任何 benchmark / 吞吐 / 延迟 / CPU 占用数据,也未给出实测出处。结论:无量化性能数据(本系列更偏功能完备性 + 默认值合理性调整)。
解读(AI 分析):方向性预期
  • 2.5G/1G 场景:聚合延迟从 400us 降到 64us/150us,对延迟敏感负载有利;代价是单包聚合批变小、中断率上升(CPU 开销可能略增)——属于"用中断率换延迟"的再平衡。
  • 100M/10M 场景:400us→330us 变化不大;真正收益是用户态可进一步调大或调小。
  • 默认值改动有行为面影响:原固定 400us → 默认自适应,对"已经习惯 400us 行为"的存量部署属静默行为变化。
  • 以上均为方向性推断,未经验证,需实测才能定量。

🔄 方案演进

版本与 review 状态
v1(2026-08-03,net-next):本系列是首次提交。lore 系列时间线(series_timeline)仅返回本版本,索引中未见更早版本或后续修订;元数据中无 Reviewed-by / Acked-by trailer。
讨论 / review 情况(如实说明)
本次分析尝试通过 lore 索引检索该系列的回复讨论(lore_thread / lore_explain_patch / lore_search),但检索服务多次超时,未能获取到任何 reviewer 回复内容。因此本报告无法呈现 review 讨论焦点,这一点是分析环境的限制,而非"没有讨论"的结论。后续若有 v2 出现,可据此补充分歧焦点(例如:默认值选择是否合理、是否需要独立 tx/rx 的硬件能力说明、是否应提供 adaptive 的速率表可调性等——均为解读(AI 分析)的常见关注点)。

⚠️ 风险与局限

硬件单值约束(结构性局限)
硬件所有向量共用一个调制值,驱动据此拒绝 RX/TX 不对称配置(-EINVAL)。对需要"RX 低延迟、TX 高聚合"不对称调优的用户不可用。这是硬件能力限制,驱动层面只能拒绝而非支持(解读(AI 分析):代码注释明确说明寄存器同值写入,属客观约束)。
默认行为变化与边界情况
  • 默认从固定 400us 变为自适应:存量行为变化,可能影响对延迟/中断率敏感的既有部署。
  • A0 硅片无效:LAN743X_CSR_FLAG_IS_A0 分支不写调制寄存器,此功能在 A0 版本硬件上不生效(既有约束,非本系列引入)。
  • 链路未 up 时开启自适应:adapter->link_speed 初始为 SPEED_UNKNOWN,此时开启自适应会落到 lan743x_get_int_mod() 的 default 分支 → 330us(10M 档),直到下次 link_up 才纠正。属轻微边缘行为。
  • 默认值缺少出处:64/150/330 三个数值未标注 datasheet/测试依据,review 时可能被追问。
  • 无性能数据:v1 未附 benchmark,合入前可能被 netdev 维护者要求补充。
严重度:MEDIUM(功能合理性良好,但默认行为变化 + 无性能数据是主要不确定性)

🔗 交叉引用

同类机制 / 相关代码
  • ethtool 标准接口:ETHTOOL_COALESCE_USECS / USE_ADAPTIVE_RX / USE_ADAPTIVE_TX 是内核 ethtool 对网卡聚合能力的标准声明,本系列让 lan743x 与该标准对齐。
  • 自适应聚合先例:Intel e1000e/igc/ice、Broadcom bnxt 等驱动早已支持 adaptive coalescing,本系列把 lan743x 带入同类能力。
  • 驱动现状(本次核查):本地内核 master 工作树(SHA c98e10d9)中 lan743x 仍为补丁前状态——lan743x_intr_open() 写入固定 LAN743X_INT_MOD(400) 到全部 INT_MOD_CFG0-9(寄存器 0x7C0-0x7E4),link_up() 只配 MAC_CR 速率位不更新调制值。与本系列 cover letter 描述一致。
  • 相关讨论:因 lore 检索服务本次不可用,未能获取本系列所在邮件线索的回复(详见方案演进节)。

✅ 关键洞察

  • 本质:这不是一个"换更快的代码",而是一个"把硬件能力暴露给用户 + 让默认值更合理"的功能补全——把固定 400us 拆成随速率的 64/150/330us,并补上 ethtool -c 接口。
  • 设计亮点:对硬件"单值共享"约束采用显式拒绝 + extack 可读报错,而非静默忽略;adapter->int_mod 缓存避免 link_up 时无谓重写 10 个 CSR,是干净的微优化。
  • 结构:两枚补丁职责分明(先解耦/速率化,后加用户接口),提交粒度合理,便于 review 与回退。
  • 短板:无任何性能数据,默认值(64/150/330)缺出处,A0 硅片不支持——这三项是合入 net-next 前最可能被维护者追问的点。
  • 后续关注:v2 是否补充 benchmark、是否调整默认值、review 讨论中是否有对"自适应默认开启"这一行为变化的异议(解读(AI 分析))。
⚠️ 免责声明

本站内容均由 AI 基于公开知识辅助生成,仅供学习参考,请勿直接引用作为依据。作者不对信息的准确性、完整性及适用性作保证,亦不对因使用本站内容产生的任何损失承担责任。