component_drivers组件网卡适配的smbus接口问题

问题描述

在适配网卡的ncsi over mctp over smbus路径时,已确认sr文件的chip address配置正确,之前测试网卡侧可以接收到mctp ctrl的set eid报文,但是在没有改动组件版本和chip addres的情况下同样的mctp ctrl的set eid报文无法发送成功。出现问题之后尝试回退component_drivers组件的修改也无效,最后将docker容器删除重新搭建环境才恢复,但是不久之后又出现这个问题。

sr的endpoint配置:

        "Chip_SmbusChip": {
            "Address": 92,
            "AddrWidth": 1,
            "OffsetWidth": 1,
            "WriteTmout": 100,
            "ReadTmout": 100,
            "HealthStatus": 0,
            "DrvWriteDelay":100
        },
        "MctpBinding_1": {
            "BmcSMBusEid": 8,
            "BmcSMBusPhyAddr": 16
        },
        "Endpoint_1": {
            "TargetEid": "${Slot} |> expr($1 + 8)",
            "TargetPhyAddr": 46,
            "MessageType": 2,
            "MediumType": 2,
            "RefChip": "#/Chip_SmbusChip"
        },

使用的是openUBMC 2603,libmcpp、component_drivers、devmon组件版本如下:

  - conan: "libmcpp/1.2.68@openubmc/stable"
  - conan: "component_drivers/1.2.89@openubmc/stable"
  - conan: "devmon/1.2.22@openubmc/stable"

通过mdbctl setprop命令修改Connector对象的Presence属性,网卡侧无响应,app.log打印返回result = 5,同样的方式之前网卡侧可以正常接收,app.log打印返回result = 0

1970-01-03 05:14:11.977182 devmon ERROR: chip.cpp(199): xxxxx data_access: name = Chip_SmbusChip_0103, optype = 1, result = 5

因为我暂时不清楚具体的触发原因,所以提供的信息有些简单,希望大家可以提供一些建议 :folded_hands:

环境信息

  • 操作系统:Ubuntu 24.04

  • 软件版本:OpenUBMC2603

答案内容由AI生成,仅供参考:

:pushpin: 五、总结建议

项目 建议
:magnifying_glass_tilted_right: 首要调试手段 使用 tracemctp start 捕获真实报文
:hourglass_not_done: 通信失败主因 很可能是设备响应慢 + 缺少有效延时导致 result=5
:collision: 重建容器有效的原因 清理了设备状态和 mctpd resource tree
:test_tube: 验证方式 逻辑分析仪抓 SCL/SDA 波形,确认地址和时序
:white_check_mark: 短期解决办法 data_access() 中硬编码延时(如 100ms)
:shield: 长期建议 升级至支持 DrvWriteDelay 自动解析的新版 component_drivers 并打补丁
点击此处查看详细分析解答

MCTP over SMBus 网卡适配通信失败问题分析与建议

根据您提供的信息,您在使用 OpenUBMC 2603 版本进行网卡适配时遇到了 MCTP over SMBus 通信异常的问题,具体表现为:

  • 之前正常的 MCTP Set EID 命令突然无法成功发送;
  • mdbctl setprop 操作返回 result = 5(通信失败);
  • 即使回退 component_drivers 修改仍无效,仅重建 Docker 容器可暂时恢复;
  • 故障会周期性复现。

以下是基于知识库内容的系统性分析与建议方案。


:magnifying_glass_tilted_left: 一、问题定位:关键线索解析

:white_check_mark: 已知配置信息分析

"Chip_SmbusChip": {
    "Address": 92,
    "DrvWriteDelay": 100
},
"MctpBinding_1": {
    "BmcSMBusPhyAddr": 16
},
"Endpoint_1": {
    "TargetPhyAddr": 46,
    "MessageType": 2,     // NCSI over MCTP
    "MediumType": 2       // SMBus
}
  • Address: 92:SMBus 上网卡桥接芯片的从机地址(0x5C),物理连接需确认该地址设备存在。
  • BmcSMBusPhyAddr: 16:BMC 的 SMBus 物理地址为 0x10,用于构建 MCTP 报文中的源地址字段。
  • TargetPhyAddr: 46 → 0x2E:目标设备(网卡端 MCTP 实体)的物理地址。
  • MessageType: 2MediumType: 2 → 表示 NCSI over MCTP over SMBus 的标准协议栈。

:pushpin: Source Address 计算方式:MCTP over SMBus 报文的 Source Addr = (BmcSMBusPhyAddr << 1) | 1 = (16 << 1) | 1 = 0x21
目标从机地址应为 TargetPhyAddr << 1 = 0x5C,与 Chip_SmbusChip.Address 一致。

:white_check_mark: 当前 SR 文件配置逻辑基本正确,硬件拓扑映射无明显错误。


:warning: 二、result = 5 错误原因分析

在日志中:

devmon ERROR: chip.cpp(199): data_access: name = Chip_SmbusChip_0103, optype = 1, result = 5

result = 5 通常表示 I2C/SMBus 通信超时或 ioctl 失败,对应 Linux I2C 子系统的 EIO 错误(I/O error)。在 OpenUBMC 框架中,由底层驱动(如 i2c.cppnormal_read/write)返回。

可能原因包括:

可能原因 支持证据
:white_check_mark: BMC 与目标设备之间 ACK/NACK 通信失败 类似问题见于 Topic 9:“往BMC地址0x10寻址失败,接收到NACK”
:white_check_mark: SMBus 写读时间间隔过短,设备来不及响应 Search Result #5,明确指出 MCTPD 发送 Request 后立即 Read Response 会导致慢速设备处理不过来
:warning: I2C 总线干扰或硬件复位导致总线锁死 见 [KG: Smbus.cpp 初始化时间戳],若总线未正确初始化则通信失败
:warning: Docker 容器状态残留或设备节点未释放 您提到“删除容器后恢复”,说明可能存在设备节点占用或 Uevent 监听异常

:puzzle_piece: 三、为何“重建环境”能暂时恢复?

您提到:

“最后将 docker 容器删除重新搭建环境才恢复,但是不久之后又出现这个问题。”

这表明问题 非代码变更引起,而是:

:small_blue_diamond: 1. 设备状态未清理(如 /dev/i2c-* 节点冲突)

  • OpenUBMC 使用 devmon 动态管理设备树,若旧容器未完全释放 I2C 总线设备文件,新实例可能无法正确访问。
  • 解决方法:确保容器启动前无残留内核设备,可通过 ls /dev/i2c* 验证。

:small_blue_diamond: 2. I2C 总线处于挂起状态(Bus Lock)

  • 如果某次通信失败后未重置总线,可能导致后续所有操作阻塞。
  • 建议:增加 I2C bus recovery 机制(如 GPIO bit-banging 模拟时钟恢复)。

:small_blue_diamond: 3. 状态缓存未失效(mctpd resource tree 未重置)

  • mctpd 维护了一个资源树(Resource Tree),包含 Endpoint 上下文。
  • 若 Endpoint 创建失败但未清除,可能导致后续 data_access 失败。
  • 验证方法:使用 tracemctp 查看 endpoint 是否成功上树。

:hammer_and_wrench: 四、具体排查与解决方案建议

:white_check_mark: 方案一:启用 tracemctp 跟踪通信报文(推荐)

参考社区经验 Search Result #4,使用 tracemctp 调试 MCTP over SMBus 报文:

# 在 mdbctl 中启用 MCTP 报文追踪
attach mctpd
tracemctp start
# 执行触发命令
setprop /bmc/dev/... Presence true
tracemctp stop
detach

:white_check_mark: 可观察以下信息

  • 是否发出 MCTP Set EID 报文;
  • 是否收到 Response;
  • 报文长度是否正确(例如 129 字节);
  • 是否存在 Command Code 0x1F 缺失等问题。

:light_bulb: 提示:tracemctp 是目前最直接的调试手段。其设计初衷正是为了解决 mctpd 缺少可观测性的问题(见 Result #10)。


:white_check_mark: 方案二:调整 DrvWriteDelay 并确认实际生效

尽管您配置了 "DrvWriteDelay": 100,但在某些版本的 component_drivers 中(尤其是 25.12 及之前),该字段默认不被解析

:link: 来自 [Search Result #5] 的关键信息:
“如果基于的是25.12版本、CSR是5.0版本,还没打某个补丁,component_drivers里默认是不解析这个字段的。”

:white_check_mark: 建议操作:

  1. 确认当前 component_drivers 是否真正支持 DrvWriteDelay 解析;
  2. 若不确定,主动在代码层插入延时,例如修改 chip_base::data_access() 在写后加入 usleep(100000)
  3. 使用逻辑分析仪捕获 SCL/SDA 波形,验证两次 SMBus 操作之间的时间间隔是否 ≥ 100ms;

:memo: 临时 workaround:增加硬编码延时,绕过配置解析缺陷。


:white_check_mark: 方案三:检查 BMC 物理地址配置一致性

确保如下三处 BmcSMBusPhyAddr 一致:

配置项 路径
SR 文件中 MctpBinding_1.BmcSMBusPhyAddr :white_check_mark: 已设为 16
MCTP 协议内部 Source Addr 计算 `(16 << 1 1) = 0x21`
桥接芯片期望的 BMC 地址 由网卡固件定义,需与之匹配

:warning: 若对端期待 BMC 地址为 0x20,而实际发送 0x21,可能导致忽略报文。

建议:用逻辑分析仪抓包,确认实际发送的地址是否为 0x21;必要时可修改 BmcSMBusPhyAddr15 来凑出 0x1F


:white_check_mark: 方案四:强制重建 mctpd 资源树与 Endpoint

尝试手动清理和重建 endpoint:

# 查看当前 endpoint 状态
getobj /bmc/kepler/System/1/Mctp
# 若发现 Endpoint_1 存在但不可用
delobj /bmc/kepler/System/1/Mctp/Endpoint_1

# 触发 devmon 重新扫描并创建 endpoint
setprop /bmc/dev/topology/I2c_8_dev/Chip_SmbusChip_0103_dev HealthStatus 0

:books: 注:MCTP Endpoint 是在收到 Set EID 响应后由 mctpd 创建的。若初始化失败,不会自动重试。


:white_check_mark: 方案五:添加 I2C 总线恢复机制

i2c.cpp 或平台初始化脚本中添加 I2C bus recovery

// 伪代码:通过 SCL 多次翻转恢复总线
for (int i = 0; i < 9; i++) {
    gpio_write(SCL, 0); usleep(10000);
    gpio_write(SCL, 1); usleep(10000);
}

确保每次通信前调用一次恢复逻辑,避免总线“假死”。


:pushpin: 五、总结建议

项目 建议
:magnifying_glass_tilted_right: 首要调试手段 使用 tracemctp start 捕获真实报文
:hourglass_not_done: 通信失败主因 很可能是设备响应慢 + 缺少有效延时导致 result=5
:collision: 重建容器有效的原因 清理了设备状态和 mctpd resource tree
:test_tube: 验证方式 逻辑分析仪抓 SCL/SDA 波形,确认地址和时序
:white_check_mark: 短期解决办法 data_access() 中硬编码延时(如 100ms)
:shield: 长期建议 升级至支持 DrvWriteDelay 自动解析的新版 component_drivers 并打补丁

:books: 参考资料(来自上下文)

  • tracemctp 是专用于跟踪 MCTP 报文的工具(Result #10
  • DrvWriteDelay 在部分版本中不被解析(Result #5
  • result = 5 对应 I/O error,常见于 NACK 或 timeout(Result #9
  • Endpoint 必须成功创建并上树才能通信([KG: Endpoint])

如能提供以下信息,可进一步精确定位:

  1. tracemctp 输出的完整报文;
  2. 逻辑分析仪抓取的 SMBus 波形图;
  3. 是否观察到 Slave Queue 溢出或中断丢失;

希望以上分析对您的调试有所帮助!

这个是硬件没响应,器件配置在哪个总线,linux_kernel里应该有相关的报错,有一键收集日志吗。

配置在I2c_8总线下的,有收集日志

linux_kernel_log.txt (384.6 KB)

我看linux_kernel里有i2c8 的报错,那个错误码01表示从器件未响应,可以用逻辑分析仪抓下数据,以及排查硬件链路是否正确,正常

1970-01-03T05:14:11.589910+00:00 iBMC kernel: [I2C-08-RT<-5|-5>] M<0x2e|0x0|0x0|3|10> L<16|0|0> C<16|0|0> E<0x1|0x0|0x0|0x1> I<0x0|0x710|0x0>
1970-01-03T05:14:11.740322+00:00 iBMC kernel: [I2C-08-RT<-5|-5>] M<0x2e|0x0|0x0|3|10> L<16|0|0> C<16|0|0> E<0x1|0x0|0x0|0x1> I<0x0|0x710|0x0>
1970-01-03T05:14:11.879899+00:00 iBMC kernel: [I2C-08-RT<-5|-5>] M<0x2e|0x0|0x0|3|10> L<16|0|0> C<16|0|0> E<0x1|0x0|0x0|0x1> I<0x0|0x710|0x0>

这个报错表示从器件未响应,可以用逻辑分析仪抓下数据看看

抓数据确认了,openubmc这边还是有在正常发数据,是网卡这边i2c有问题,多谢指导