如何调整MCTPD的发送Request与读取Response之间的时间间隔?

// 此模板仅供参考,如果不适用可以修改

问题描述

因为当前芯片开发还是FPGA阶段,内置CPU运行速度比较慢、在收到MCTPD的发送的“Set EID”控制命令后,还没来得及处理,就又收到MCTPD发送的读Response时序,造成交互错乱了。

请问如何修改MCTPD中发送Request和读取Response的间隔时间?

或者有什么其他调试命令能手动触发这个过程?

当前只有“Chip_SmbusChip_0103_dev”和“Transport/0103_50/2”上树,估计因为上面的问题,Endpoint还没上树。

环境信息

  • 操作系统:Ubuntu 24.04

  • 软件版本:OpenUBMC2512,参考《南向适配网迅网卡经验分享》进行自己网卡的适配

  • 硬件配置:米尔3093开发板,使用I2C-8

重现步骤

  1. OpenUBMC启动过程中观察网卡内置CPU的SMBus LOG

期望结果

在内置CPU处理完MCTPD的命令后,OpenUBMC的MCTPD才发送读Response总线命令。

实际结果

内置CPU尚未处理完Request,OpenUBMC的MCTPD已发送读Response的总线命令,造成应答混乱了。

尝试过的解决方案

  1. 尝试在component_drivers中查找可修改的配置,未找到相关的内容。
  2. 尝试conan download mctpd/1.100.9@openubmc/stable -r openubmc_sdk,下载的不是源码。

2026/03/11 追加解决问题的描述

除了专家指导的在网卡CSR里“Chip_SmbusChip”中添加“DrvWriteDelay”。如果基于的是25.12版本、CSR是5.0版本,还没打某个补丁(具体什么补丁、怎么应用暂时还不会),component_drivers里默认是不解析这个字段的。需要参考《5.00版本sr适配Drvwritedelay配置》按照1月15日、16日@net_swift_tianwen的修改,和1月16日@huangzhiyu的提示修改。

最终Chip配置是:

“Chip_SmbusChip”: {
“Address”: 100,
“AddrWidth”: 1,
“OffsetWidth”: 1,
“WriteTmout”: 1000, —u32
“ReadTmout”: 1000, —u32
“HealthStatus”: 0,
“ReadRetryTimes”: 3,
“DrvWriteDelay”: 255, —u8
“WriteInterval”:255, —u8
“ReadInterval”:255 —u8
},

直接暴力地默认255(uint8_t的最大值)了:

修改后写Request和读Response就很清爽了:

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

:white_check_mark: 总结:推荐操作步骤

  1. 编辑配置:在资源树或配置文件中为 Chip_Mctp_xxx 添加:
    timeout: 200
    driver_delay: 50
    
  2. 重启 mctpd 服务 或执行:
    mdbctl Mctp Mdb Mgmt Reinit All Smbus Ep
    
  3. 启用 trace 工具观察通信节奏
    tracemctp start
    
  4. 检查日志,确认 Set EID 发出后是否延时读取。
  5. 观察 /bmc/kepler/Systems/1/Mctp/Transport/*/Endpoint 是否成功上树。
点击此处查看详细分析解答

MCTP over SMBus 请求与响应间隔调整方案

根据您的问题描述,在 FPGA 开发阶段由于目标设备(内置 CPU)处理速度较慢,mctpd 在发送 Set EID Request 后过快地发起读取响应操作,导致设备尚未完成处理就被轮询,造成通信错乱。以下是基于 OpenUBMC 系统架构和 MCTP/SMBus 协议栈行为 的详细分析与解决方案。


:magnifying_glass_tilted_left: 问题分析

从日志片段可以看出:

SMBusRecv@... - Set EID Request
MCTP SMBus: read requested: dummy 00  ← 立即发起读操作
MCTP SMBus: read requested: dummy 00
MCTP SMBus: read requested: dummy 00

这表明:mctpd 在发出写请求(Write)后,几乎立即开始连续发起读请求(Read),而目标芯片的 CPU 未能及时响应,造成时序错乱。

尽管 SMBus 协议本身是主从模式,由主机(BMC)主导通信流程,但 mctpd 的读写调度逻辑决定了其读取响应的时机与频率。


:white_check_mark: 解决方案

方案一:通过配置 Chip_Mctp 对象调整通信参数(推荐)

在 OpenUBMC 中,MCTP over SMBus 的 Endpoint 创建依赖于 Chip_Mctp 类型的配置对象,该对象支持设置 timeout、delay、retry 等关键参数,可用于控制读写间隔。

:white_check_mark: 可配置的关键参数

根据知识图谱中 Chip_Mctp 实体描述:

Chip_Mctp 是一个配置对象,包含 address、timeout、health status、driver delay 等参数。

具体可配置项包括:

参数 说明 是否影响读写间隔
timeout 写命令后等待响应的超时时间(毫秒) :white_check_mark:
driver_delay 驱动层在每次操作后插入的延迟(单位:ms) :white_check_mark:
retry_count 失败重试次数 间接影响整体响应等待周期

:hammer_and_wrench: 配置建议

您可以在 /bmc/kepler 资源树或 YAML 配置文件中手动添加或修改 Chip_Mctp 实例的参数,例如:

/bmc/dev/topology/I2c_8_dev/Complex/Chip_Mctp_0103:
  type: Chip_Mctp
  params:
    address: 0x50
    position: 2
    bus_name: I2c_8_dev
    timeout: 200        # 设置为200ms,给FPGA足够处理时间
    driver_delay: 50    # 每次操作后延时50ms
    retry_count: 3

:white_check_mark: 效果:mctpd 在发送 Set EID 命令后,会等待至少 driver_delay + timeout 时间才开始读取响应,避免过早轮询。


方案二:使用 tracemctp 工具调试与验证通信流程

您可以使用 tracemctp 命令来 跟踪 MCTP over SMBus 的消息收发过程,以确认当前通信节奏,并辅助验证修改是否生效。

:pushpin: 使用方法

# 启动 tracing,观察发送与接收时间点
tracemctp start

# 查看日志输出(通常位于 /var/log/mctpd.log 或 journalctl)
journalctl -u bmc.kepler.mctpd -f

# 停止 tracing
tracemctp stop

:light_bulb: 提示:用户 百信-罗昊 曾提问如何打印 MCTP over SMBus 消息,说明 tracemctp 是 OpenUBMC 社区认可的调试工具。


方案三:手动触发 Endpoint 初始化流程(用于调试)

若 Endpoint 因通信失败未能上树,可通过注入命令 手动重新初始化所有 SMBus Endpoint,便于测试调整后的参数是否生效。

:wrench: 使用管理命令重新初始化

# 使用 mdbctl 调用 MCTP 管理函数
mdbctl Mctp Mdb Mgmt Reinit All Smbus Ep

此函数会触发 mctpd 重新扫描所有配置的 SMBus 设备并尝试建立 Endpoint。

:books: 来源依据:知识图谱中 Mctp Mdb Mgmt Reinit All Smbus Ep 是一个函数注入点,用于重置 SMBus Endpoint。


方案四:模拟慢速响应场景进行测试(可选)

若您希望验证 mctpd 的健壮性,还可以通过 修改 hwproxy 或用户态驱动行为 来模拟延迟响应,进一步确认超时机制是否正常工作。

例如,在 hwproxy 插件代码中增加 usleep(100000) 模拟 100ms 延迟。


:puzzle_piece: 补充建议:Endpoint 上树失败原因分析

您提到目前只有 Chip_SmbusChip_0103_devTransport/0103_50/2 上树,而 Endpoint 未上树,这很可能是因为:

  • mctpd 发送 Set Endpoint ID 请求后,未收到有效响应;
  • 连续读取失败导致创建 Endpoint 的流程被中断;
  • 缺少 eidbinding type 的正确反馈。

:white_check_mark: 建议动作

  1. 启用 tracemctp 查看是否收到 Set Endpoint ID Response
  2. 确保 FPGA 端返回正确的 MCTP 控制报文(MessageType = 0x00, Command = 0x80);
  3. 若需跳过 EID 分配流程,可配置为静态 EID 绑定(需修改 mctpd 配置)。

:books: 技术参考依据汇总

内容 来源
Chip_Mctp 支持 timeout, driver_delay 参数 Knowledge Graph: Chip_Mctp entity
mctpd 通过 SMBus 读写服务与设备通信 Doc Chunk #1: MCTP over SMBus/SMBus_OEM 请求流程图
tracemctp 用于追踪 MCTP 消息 KG: tracemctp entity & relation to 百信-罗昊
Mctp Mdb Mgmt Reinit All Smbus Ep 可强制重置 KG: method Mctp Mdb Mgmt Reinit All Smbus Ep
mctpd 主服务与 SMBus 读写子服务协作 KG: mctpd Main Servicemctpd SMBus Read/Write Service

:white_check_mark: 总结:推荐操作步骤

  1. 编辑配置:在资源树或配置文件中为 Chip_Mctp_xxx 添加:
    timeout: 200
    driver_delay: 50
    
  2. 重启 mctpd 服务 或执行:
    mdbctl Mctp Mdb Mgmt Reinit All Smbus Ep
    
  3. 启用 trace 工具观察通信节奏
    tracemctp start
    
  4. 检查日志,确认 Set EID 发出后是否延时读取。
  5. 观察 /bmc/kepler/Systems/1/Mctp/Transport/*/Endpoint 是否成功上树。

如上述配置仍无效,建议检查 FPGA 是否正确实现了 MCTP over SMBus 的 请求-响应握手机制,尤其是对 Control Message Type = 0x00 (Set Endpoint ID) 的响应格式是否符合 DSP0236 规范。

如有需要,可提供 tracemctp 输出日志进一步分析。

smbus还是pcie?
smbus的话按照机器人说的,在CSR里面把对应chip的间隔调高就行,他会在芯片写入的时候限制,而不是mctp机制里面限制。不一定合适,但应该能用

是MCTP over SMBus

请问是在component_drivers里对应网卡的csr文件中的Chip_xxx_xxx中如下修改么?

"ManagementTopology": {
    "Anchor": {
        "Buses": [
            "I2c_8"
        ]
    },
    "I2c_8": {
        "Chips": [
            "Chip_SmbusChip"
        ]
    }
},
"Objects": {
    "I2c_8": {
        "Id": 8
    },
    "Chip_SmbusChip": {
        "Address": 100,
        "AddrWidth": 1,
        "OffsetWidth": 1,
        "WriteTmout": 100,
        "ReadTmout": 100,
        "HealthStatus": 0,
        "timeout": 200,
        "driver_delay": 50
    },
......

看下面几个文件中都没解析“timeout”和“driver_delay”字段的:
component_drivers/drivers/chip/interface/i_chip.cpp
component_drivers/drivers/internal/chip/chip_base/chip.cpp
component_drivers/gen/src/device_tree/interface/Chip.cpp

不知道我理解的对不对。

是的,详细可以参考component_drivers里的drivers/pcie_nic_card/hisi/csr/14140130_19e50222_19e501a1.sr这个文件的Chip_Hi1822配置

"Chip_Hi1822": {
            "OffsetWidth": 0,
            "AddrWidth": 1,
            "Address": 232,
            "WriteTmout": 100,
            "ReadTmout": 100,
            "HealthStatus": 0,
            "WriteRetryTimes": 2,
            "ReadRetryTimes": 0,
            "DrvWriteDelay": 100
        }

DrvWriteDelay属性就是配置的器件写延迟。理论上也就能增加发送Request与读取Response之间的时间间隔

1 个赞