冲环成功了,正式发包还是死——I219 那十一刀
现象
NUC 上 I219 已经认卡、链路也起来了,lsdev 能看到 i219 net link=up。一发 ping,发送路径却停在「描述符写进去了、硬件不给完成」:TDT 往前走,TDH 不动,last_rc=-3。串口上 tx_ok 长期是 0。课路径卡在「看得见网卡、发不出包」。
初始假说
我先按「寄存器没开到位」想:是不是 I219 要额外写 TXDCTL、TARC0 之类门控?很多 Intel 千兆变体文档里这些位看起来很像开关。第一刀就奔着「补写门控就能动」去了。
尝试与失败
TXDCTL 写了,还是 -3。加上 TARC0,一样。说明门控假说不成立,至少不是主因。
后来试了哑元 TX 冲环:环一就绪就灌一帧 flush。串口终于出现 Flush OK——硬件其实会给 Descriptor Done。可正式 Send 仍然 -3。我否定的是「硬件彻底坏了 / 根本不会出 DD」;没否定的是「正式路径在某处把发送态改坏了」。
接着一串否证:冲环后不恢复 FEXTNVM11,仍死;把冲环挪到等链路之后,反而 Flush NoDD;先满配 TCTL 再冲环,冲环也死;禁 MSI 改 poll,冲环问题还在,只说明 MSI 不是主因;「冲环时只开 TCTL.EN、冲完再满配」也不够;把冲环提前到环基址刚写完,Flush 又能 OK,正式 Send 还是 -3。
到这里我手里有一张很拧巴的图:早冲能 OK,正式发包前某处又把硬件弄哑了。
转折
真正转弯的是把目光从「还要再写什么」换成「冲环成功之后不该再写什么」。对照失败刀史:凡是 Flush 之后又拿一份「满配 / 旧值」去盖 TCTL 的路径,正式发送就容易回到死态;反过来,冲环成功后只保住 TCTL.EN、不再用满配值盖回去,计数才开始动。
根因
根因很短:冲环后重写 TCTL,清掉了有效发送态。冲环把硬件推到一个能出 DD 的状态;随后那次「看起来更正确」的满配 TCTL 写回,把刚建立好的发送态抹掉了。所以才会出现 Flush OK、正式 Send 永远 -3 的分裂现象。
修完后 NUC 上 tx_ok 起来,静态 ping 网关有 reply,再清 netif 做 DHCP 也能拿到地址。课路径才算接通。
教训
- 一刀只验一个假说;失败要写清「否定了什么」,别同一刀连试全家桶。
- 诊断优先序很重要:认卡 → MAC → TX 计数/寄存器 → 最小 TX 假说;别跳过静态 ping 直接上真机 DHCP。
- 「多写一点寄存器」不总是更安全;有时正确动作是少写。冲环成功后的保持,比再盖一层「完整配置」更关键。
- QEMU 绿不算真机进度;动 TX 路径必须 NUC 验。已经否掉的假说不要无记录地重试。