文章目录
背景
Mellanox网卡在服务器上CPU与网卡通过PCIe连接,软件上HOST是内核态驱动,NIC上是Firmware(FW)程序。HOST上通过类似“心跳机制”来确保FW还在正常工作,这个机制就是poll_health。本文以一个FW报错为例子介绍这个机制
health机制
为了确认固件(FW)的健康状态,iseg(初始化段)中暴露了一个健康计数器、综合症(syndrome)以及一个包含高级调试信息的相关缓冲区。iseg分析参考:Mellanox驱动中的iseg是什么?如何指定哪些PCIe设备绑定到驱动?
健康计数器每10毫秒由固件(FW)递增一次,并由软件(SW)进行监控。它应该由一个独立的线程进行监控,该线程不会因等待命令完成而阻塞。如果计数器未能递增,则表明系统健康状态不佳,
报错
报错:poll_health:834:(pid 0): device’s health compromised - reached miss count
详细报错信息:
可以看到这个错误是由于网卡温度过高。实际情况是服务器的风扇开启不足,造成BF2 DPU温度过高从而触发这个机制。触发机制是:health模块每隔2秒检查一次FW的状态,如果有异常通过print_health_info打印信息。打印的信息内容是硬件寄存器中的信息。详细参考health buffer章节
检查机制
网卡驱动在初始化的时候会启动一个定时器timer,每个2秒调用poll_health函数。该函数被回调后检查固件的信息。然后根据情况做出响应动作。
内核定时器机制触发定期检查
u64 poll_interval_ms = mlx5_tout_ms(dev, HEALTH_POLL_INTERVAL); #这里定义下次到期时间的定义 最终是2000ms
struct mlx5_core_health *health = &dev->priv.health;
timer_setup(&health->timer, poll_health, 0); #设置回调
health->timer.expires = jiffies + msecs_to_jiffies(poll_interval_ms); #设置下次到期时间
add_timer(&health->timer); #启动timeer
可以看到启动2s的timer定期处理
在time函数中主要处理事情
阶段1:获取状态
可以看到查看网卡状态,包括PCIe情况,网卡状态以及fw的synd
并且都是直接从寄存器获取。比如最后一个获取synd信息:
阶段2:如果有异常进行处理,并启动对应work处理
可以看到如果有异常,就会打印前面提到的信息,这些信息就是uar的接口的数据结构信息:
然后触发mlx5_trigger_health_work,相应的work进行处理。会把health的work(实际是fatal_report_work),挂到health的的workqueue上。
这个work是在health模块初始化的时候定义的:
阶段3:启动work处理异常
然后在这个work里面会进行通知以及是否进行驱动卸载。
初始化阶段何时被调用?
网卡初始化主要流程参考兄弟篇:Mellanox OFED驱动中PCIe驱动主要初始化流程函数图
可以看到是在probe阶段调用到mlx5_load_one流程中的回调function设置专用流程中挂载这个功能,mlx5_start_health_poll启动一个health poll的程序。
health buffer
具体是这个数据结构:
struct health_buffer {
__be32 assert_var[6];
__be32 rsvd0[2];
__be32 assert_exit_ptr;
__be32 assert_callra;
__be32 rsvd1[1];
__be32 time;
__be32 fw_ver;
__be32 hw_id;
u8 rfr_severity;
u8 rsvd2[3];
u8 irisc_index;
u8 synd;
__be16 ext_synd;
};
如果是Firmware Inter Error,这里的assert_va会被设置:
另外报出来的:exit_ptr是出问题时候的支持以及RA的值。这个方便对mstdump之后结合fw进行分析定位。
相关数据结构:
- healt buffer中的rft是什么?Recovery Flow Required. 恢复流程需要。
- health buffer在iseg中的位置
综述
本文以一个报错为例子,剖析了网卡的poll health机制,实际是一个2s的timer,到达timer时间检查硬件状态,如果有异常会再触发一个work处理。在work中会尝试恢复,并且启动trigger,通过其他机制通知到系统的其他模块。