PCIe设备加载
更新时间: 2026/04/23
在Gitcode上查看源码

PCIe设备加载

PCIe设备加载需要利用带内Host上报的BDF信息,匹配到对应的Slot,带内Host上报BDF又依赖BMC生成丝印。

卡加载主要流程如下:

1. 丝印的建立

拓扑建立中已经介绍了生成丝印的流程,带内host上报正确的槽位和BDF需要有正确的丝印信息,如果出现了带内有卡,但是带外没有卡的情况,可以先检查一下对应槽位的PortId是否正确。

2. 带内上报BDF

带内通过ipmi命令上报BDF,站在pcie_device的角度,不需要特别关心上报的指令,只需要关心bios组件资源树上的值即可。

如果当前使用ssh登录环境,使用mdbctl可以看到上报的BDF,一般指令如下:

mdbctl lsprop Bios_1_010101

多Host或Host路径不同的情况,请自行用 mdbctl lsobj bios查看已有的bios对象。

如果使用一键收集,也可以在/dump_info/AppDump/bios/1/bios_info下查看带内Host的上报。

带内Host上报会根据OCP卡、PCIe卡、NVME盘上报三条指令,分别根据OCPCardBDF、PcieCardBDF、PcieDiskBDF进行索引,以通过环境上查到的上报内容举例:

json
OCPCardBDF=[]

PcieCardBDF=[0,255,255,255,255,0,0,255,255,255,0,0,65,0,0,0,255,255,255,255,0,1,150,0,0,0,1,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255]
 
PcieDiskBDF=[0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255]

带内Host上报信息实际上反应了BDF和SlotID的关系,每五个数据代表一个设备,分别是SegmentSocketIdBusDeviceFunction,ssh查看和日志中记录的均为10进制,注意OCPCardBDF和PcieCardBDF的槽位号是从1开始,NVME槽位号从0开始。

例如,上表中0 0 65 0 0代表一个PCIe卡,它在带内的BDF为41:00.0,插在槽位3上。

Host上报BDF后,相应的加载信息会被持久化在数据库中,这样即使BMC重启也能正常加载卡,待下一次Host上报后刷新。

3. 触发PCIe卡加载

3.1 Host上报触发

PCIe卡加载实际由连接器完成,pcie_device组件负责将对应连接器的Presence属性置为1。加载PCIe设备需要先加载槽位,这就需要首先有IEU/EXU/SEU在位,IEU的CSR一般如下:

json
{
    "FormatVersion": "x.xx",
    "DataVersion": "x.xx",
    "ManagementTopology": {
        "Anchor": {
            "Buses": [
                "Hisport_x"
            ]
        },
        "Hisport_5": {
            "Chips": [
                "Eeprom_IEU",
                "Pca9545_IEU"
            ]
        },
        "Pca9545_IEU": {
            "Buses": [
                "I2cMux_9545Chan2",
                "I2cMux_9545Chan3",
                "I2cMux_9545Chan4"
            ]
        },
        "I2cMux_9545Chan2": {
            "Connectors": [
                "Connector_PCIe_1",
            ]
        },
        "I2cMux_9545Chan3": {
            "Connectors": [
                "Connector_PCIe_2",
                "Connector_PCIe_3",
            ]
        },
        "I2cMux_9545Chan4": {
            "Chips": [
                "Pca9555_IEU",
                "Chip_MCU"
            ]
        }
    },
    "Objects": {
        ...
    }
}

如上所示,在Riser卡的CSR的定义中,ManagementTopology的定义是CSR语法的必填项。从Topo关系可以看到,此张Riser卡上采用了Mux器件对链路进行了复用,并且支持加载多张PCIe卡。

现在考察一下IEU上的下行连接器,每个下行连接器会关联一个或两个(含天池加载方式)框架自发现连接器,也会同时关联一个PcieAddrInfo,这样就可以通过PcieAddrInfo找到对应的框架自发现连接器。

IEU下行连接器:

"BusinessConnector_1": {
    "Name": "Down_1",
    "Direction": "Downstream",
    "Slot": 1,                      // 找 PcieAddrInfo 对象的 SlotID 用到,作为数组下标去PSR的Slot数组里查找。
    "LinkWidth": "X16",
    "MaxLinkRate": "PCIe 4.0",
    "ConnectorType": "PCIe CEM",
    "UpstreamResources": [],
    "RefMgmtConnector": "#/Connector_PCIE_1",  // 关联框架自发现的连接器
    "RefPCIeAddrInfo": "#/PcieAddrInfo_1"    // 关联对应的PcieAddrInfo对象

框架自发现连接器:

json
"Connector_PCIe_1": {
  "Bom": "14140130",  // 下级器件对应的Bom_ID
  "Id": "xxxx", // 下级器件对应的id
  "AuxId": "xxxx", // 下级器件对应的AuxId
  "Slot": 2,  // 下级器件对应的卡槽号
  "Position": 2,  // 下级器件对应的Position
  "Presence": 1,  // 在位信息
  "Buses": [
    "I2cMux_9545Chan2"
  ],
  "SystemId": 1,
  "SilkText": "RiserCard${Slot}",
  "IdentifyMode": 2,  // 加载方式:非天池加载模式
  "Container": "Component_RiserCard",
  "Type": "PCIe"  // 下级器件类型
},

通过配置该PCIe设备的Connector,能够实现在Riser卡上加载PCIe卡,对于特殊的板载网卡也可以在BCU中通过如上的Connector配置PCIe卡。在上述的配置中,对BomIdAuxId进行了配置,并把Presence置为了1,这样在加载PCIe卡时就能够加载Bom_Id_AuxId.sr对应的PCIe设备。

接收到带内Host上报的BDF后,pcie_device会通过ComponentTypeSlotID去匹配对应的PcieAddrInfo,其中PCIeCard对应ComponentType = 8, OCPCard对应ComponentType = 83,NVME盘对应ComponentType = 2。之后会根据SlotID去进行匹配,PcieAddrInfoSlotID第 2 节中提到的SlotID一致。

PcieAddrInfoConnector通过下行连接器BusinessConnector匹配,一个槽位对应一个下行连接器,RefMgmtConnector关联ConnectorRefPCIeAddrInfo关联PcieAddrInfo

特别的,对于天池卡,会存在一个Connector_TianChi对象,使用RefTianChiMgmtConnectior进行关联,天池加载不通过pcie_device,但和Connector共享槽位。

3.2 BMC重启触发

BMC重启也会进行卡加载,此时会读取数据库中存储的上一次Host上报的BDF信息,加载到对应的槽位上,加载流程和Host上报一致。

4. PCIe设备的分发

4.1 资源树方式

在vpd仓库中可以看到很多PCIe卡的sr,下面介绍一下和pcie_device相关的配置部分:

json
"FormatVersion": "3.00",                                    -- CSR版本号,3.00表示通过资源树加载

...
"Object": {
    ...
    "PCIeDevice_1": {
            "DeviceName": "PCIe Card $ (BCM957508-P2100G)", -- 卡名称,中间的$占位符加载后会被替换为槽位号
            "FunctionClass": 2,                             -- PCIe设备分类代码
            "Position": "",
            "DiagnosticFault": 0,                           -- 用于告警,触发UCE告警
            "PredictiveFault": 0,                           -- 用于告警,触发CE告警
            "LinkSpeedReduced": 0,                          -- 用于告警,触发降速率告警
            "DeviceType": 8,                                -- 设备类型,同CompenentType,配置错误可能导致北向显示不对
            "Container": "${Container}",                    -- 所在设备,如果Riser、硬盘背板等
            "GroupPosition": "PCIeDevice_1_${GroupPosition}",
            "PCIeDeviceType": "MultiFunction",
            "SlotType": "FullLength",
            "FunctionProtocol": "PCIe",
            "FunctionType": "Physical"
        },
        "PCIeCard_1": {
            "SlotID": "<=/PCIeDevice_1.SlotID",             -- 表示卡所在的槽位
            "NodeID": "<=/PCIeDevice_1.SlotID |> string.format('PCIeCard%s',$1)", -- 表示卡唯一标识,用于北向显示
            "Name": "BCM957508-P2100G",                     -- 设备名称
            "BoardName": "BCM957508-P2100G",                -- 单板名称
            "Description": "NetXtreme-E Dual-port 100G QSFP56 Ethernet PCIe4.0 x16 Adapter (BCM957508-P2100G)",
            "FunctionClass": 2,
            "VendorID": 5348,                               -- 四元组中的Vid
            "DeviceID": 5968,                               -- 四元组中的Did
            "SubVendorID": 5348,                            -- 四元组中的SubVid
            "SubDeviceID": 8448,                            -- 四元组中的SubDid
            "Position": "<=/PCIeDevice_1.Position",
            "LaneOwner": "<=/PCIeDevice_1.SocketID",
            "FirmwareVersion": "N/A",
            "Manufacturer": "Broadcom",
            "PartNumber": "",
            "Health": "<=/Component_PCIeCard.Health",       -- 设备健康状态
            "Model": "BCM57508",
            "DeviceName": "<=/PCIeDevice_1.DeviceName",
            "LinkSpeed": "N/A",                             -- PCIe卡实际协商速率
            "LinkSpeedCapability": "N/A",                   -- PCIe卡最大速率
            "PcbVersion": "N/A", 
            "Bus": "<=/PCIeDevice_1.Bus",                   -- PCIe卡rootBus,由组件设置给PCIeDevice后同步过来
            "Device": "<=/PCIeDevice_1.Device",             -- PCIe卡rootDevice,由组件设置给PCIeDevice后同步过来
            "Function": "<=/PCIeDevice_1.Function",         -- PCIe卡rootFunction,由组件设置给PCIeDevice后同步过来
            "DevBus": "<=/PCIeDevice_1.DevBus",             -- PCIe卡Bus,由组件设置给PCIeDevice后同步过来
            "DevDevice": "<=/PCIeDevice_1.DevDevice",       -- PCIe卡Device,由组件设置给PCIeDevice后同步过来
            "DevFunction": "<=/PCIeDevice_1.DevFunction",   -- PCIe卡Function,由组件设置给PCIeDevice后同步过来
            "SerialNumber": ""
        },
    ...
}

加载设备时,pcie_device会根据position匹配PCIeDevice对应的PcieAddrInfo,并将PcieAddrInfo上的SlotIDBDFrootBDF等信息同步给PCIeDevice

PCIeDeviceDeviceName中间需要带一个`---

PCIe设备加载

PCIe设备加载需要利用带内Host上报的BDF信息,匹配到对应的Slot,带内Host上报BDF又依赖BMC生成丝印。

卡加载主要流程如下:

1. 丝印的建立

拓扑建立中已经介绍了生成丝印的流程,带内host上报正确的槽位和BDF需要有正确的丝印信息,如果出现了带内有卡,但是带外没有卡的情况,可以先检查一下对应槽位的PortId是否正确。

2. 带内上报BDF

带内通过ipmi命令上报BDF,站在pcie_device的角度,不需要特别关心上报的指令,只需要关心bios组件资源树上的值即可。

如果当前使用ssh登录环境,使用mdbctl可以看到上报的BDF,一般指令如下:

mdbctl lsprop Bios_1_010101

多Host或Host路径不同的情况,请自行用 mdbctl lsobj bios查看已有的bios对象。

如果使用一键收集,也可以在/dump_info/AppDump/bios/1/bios_info下查看带内Host的上报。

带内Host上报会根据OCP卡、PCIe卡、NVME盘上报三条指令,分别根据OCPCardBDF、PcieCardBDF、PcieDiskBDF进行索引,以通过环境上查到的上报内容举例:

json
OCPCardBDF=[]

PcieCardBDF=[0,255,255,255,255,0,0,255,255,255,0,0,65,0,0,0,255,255,255,255,0,1,150,0,0,0,1,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255]
 
PcieDiskBDF=[0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255]

带内Host上报信息实际上反应了BDF和SlotID的关系,每五个数据代表一个设备,分别是SegmentSocketIdBusDeviceFunction,ssh查看和日志中记录的均为10进制,注意OCPCardBDF和PcieCardBDF的槽位号是从1开始,NVME槽位号从0开始。

例如,上表中0 0 65 0 0代表一个PCIe卡,它在带内的BDF为41:00.0,插在槽位3上。

Host上报BDF后,相应的加载信息会被持久化在数据库中,这样即使BMC重启也能正常加载卡,待下一次Host上报后刷新。

3. 触发PCIe卡加载

3.1 Host上报触发

PCIe卡加载实际由连接器完成,pcie_device组件负责将对应连接器的Presence属性置为1。加载PCIe设备需要先加载槽位,这就需要首先有IEU/EXU/SEU在位,IEU的CSR一般如下:

json
{
    "FormatVersion": "x.xx",
    "DataVersion": "x.xx",
    "ManagementTopology": {
        "Anchor": {
            "Buses": [
                "Hisport_x"
            ]
        },
        "Hisport_5": {
            "Chips": [
                "Eeprom_IEU",
                "Pca9545_IEU"
            ]
        },
        "Pca9545_IEU": {
            "Buses": [
                "I2cMux_9545Chan2",
                "I2cMux_9545Chan3",
                "I2cMux_9545Chan4"
            ]
        },
        "I2cMux_9545Chan2": {
            "Connectors": [
                "Connector_PCIe_1",
            ]
        },
        "I2cMux_9545Chan3": {
            "Connectors": [
                "Connector_PCIe_2",
                "Connector_PCIe_3",
            ]
        },
        "I2cMux_9545Chan4": {
            "Chips": [
                "Pca9555_IEU",
                "Chip_MCU"
            ]
        }
    },
    "Objects": {
        ...
    }
}

如上所示,在Riser卡的CSR的定义中,ManagementTopology的定义是CSR语法的必填项。从Topo关系可以看到,此张Riser卡上采用了Mux器件对链路进行了复用,并且支持加载多张PCIe卡。

现在考察一下IEU上的下行连接器,每个下行连接器会关联一个或两个(含天池加载方式)框架自发现连接器,也会同时关联一个PcieAddrInfo,这样就可以通过PcieAddrInfo找到对应的框架自发现连接器。

IEU下行连接器:

"BusinessConnector_1": {
    "Name": "Down_1",
    "Direction": "Downstream",
    "Slot": 1,                      // 找 PcieAddrInfo 对象的 SlotID 用到,作为数组下标去PSR的Slot数组里查找。
    "LinkWidth": "X16",
    "MaxLinkRate": "PCIe 4.0",
    "ConnectorType": "PCIe CEM",
    "UpstreamResources": [],
    "RefMgmtConnector": "#/Connector_PCIE_1",  // 关联框架自发现的连接器
    "RefPCIeAddrInfo": "#/PcieAddrInfo_1"    // 关联对应的PcieAddrInfo对象

框架自发现连接器:

json
"Connector_PCIe_1": {
  "Bom": "14140130",  // 下级器件对应的Bom_ID
  "Id": "xxxx", // 下级器件对应的id
  "AuxId": "xxxx", // 下级器件对应的AuxId
  "Slot": 2,  // 下级器件对应的卡槽号
  "Position": 2,  // 下级器件对应的Position
  "Presence": 1,  // 在位信息
  "Buses": [
    "I2cMux_9545Chan2"
  ],
  "SystemId": 1,
  "SilkText": "RiserCard${Slot}",
  "IdentifyMode": 2,  // 加载方式:非天池加载模式
  "Container": "Component_RiserCard",
  "Type": "PCIe"  // 下级器件类型
},

通过配置该PCIe设备的Connector,能够实现在Riser卡上加载PCIe卡,对于特殊的板载网卡也可以在BCU中通过如上的Connector配置PCIe卡。在上述的配置中,对BomIdAuxId进行了配置,并把Presence置为了1,这样在加载PCIe卡时就能够加载Bom_Id_AuxId.sr对应的PCIe设备。

接收到带内Host上报的BDF后,pcie_device会通过ComponentTypeSlotID去匹配对应的PcieAddrInfo,其中PCIeCard对应ComponentType = 8, OCPCard对应ComponentType = 83,NVME盘对应ComponentType = 2。之后会根据SlotID去进行匹配,PcieAddrInfoSlotID第 2 节中提到的SlotID一致。

PcieAddrInfoConnector通过下行连接器BusinessConnector匹配,一个槽位对应一个下行连接器,RefMgmtConnector关联ConnectorRefPCIeAddrInfo关联PcieAddrInfo

特别的,对于天池卡,会存在一个Connector_TianChi对象,使用RefTianChiMgmtConnectior进行关联,天池加载不通过pcie_device,但和Connector共享槽位。

3.2 BMC重启触发

BMC重启也会进行卡加载,此时会读取数据库中存储的上一次Host上报的BDF信息,加载到对应的槽位上,加载流程和Host上报一致。

4. PCIe设备的分发

4.1 资源树方式

在vpd仓库中可以看到很多PCIe卡的sr,下面介绍一下和pcie_device相关的配置部分:

json
"FormatVersion": "3.00",                                    -- CSR版本号,3.00表示通过资源树加载

...
"Object": {
    ...
    "PCIeDevice_1": {
            "DeviceName": "PCIe Card $ (BCM957508-P2100G)", -- 卡名称,中间的$占位符加载后会被替换为槽位号
            "FunctionClass": 2,                             -- PCIe设备分类代码
            "Position": "",
            "DiagnosticFault": 0,                           -- 用于告警,触发UCE告警
            "PredictiveFault": 0,                           -- 用于告警,触发CE告警
            "LinkSpeedReduced": 0,                          -- 用于告警,触发降速率告警
            "DeviceType": 8,                                -- 设备类型,同CompenentType,配置错误可能导致北向显示不对
            "Container": "${Container}",                    -- 所在设备,如果Riser、硬盘背板等
            "GroupPosition": "PCIeDevice_1_${GroupPosition}",
            "PCIeDeviceType": "MultiFunction",
            "SlotType": "FullLength",
            "FunctionProtocol": "PCIe",
            "FunctionType": "Physical"
        },
        "PCIeCard_1": {
            "SlotID": "<=/PCIeDevice_1.SlotID",             -- 表示卡所在的槽位
            "NodeID": "<=/PCIeDevice_1.SlotID |> string.format('PCIeCard%s',$1)", -- 表示卡唯一标识,用于北向显示
            "Name": "BCM957508-P2100G",                     -- 设备名称
            "BoardName": "BCM957508-P2100G",                -- 单板名称
            "Description": "NetXtreme-E Dual-port 100G QSFP56 Ethernet PCIe4.0 x16 Adapter (BCM957508-P2100G)",
            "FunctionClass": 2,
            "VendorID": 5348,                               -- 四元组中的Vid
            "DeviceID": 5968,                               -- 四元组中的Did
            "SubVendorID": 5348,                            -- 四元组中的SubVid
            "SubDeviceID": 8448,                            -- 四元组中的SubDid
            "Position": "<=/PCIeDevice_1.Position",
            "LaneOwner": "<=/PCIeDevice_1.SocketID",
            "FirmwareVersion": "N/A",
            "Manufacturer": "Broadcom",
            "PartNumber": "",
            "Health": "<=/Component_PCIeCard.Health",       -- 设备健康状态
            "Model": "BCM57508",
            "DeviceName": "<=/PCIeDevice_1.DeviceName",
            "LinkSpeed": "N/A",                             -- PCIe卡实际协商速率
            "LinkSpeedCapability": "N/A",                   -- PCIe卡最大速率
            "PcbVersion": "N/A", 
            "Bus": "<=/PCIeDevice_1.Bus",                   -- PCIe卡rootBus,由组件设置给PCIeDevice后同步过来
            "Device": "<=/PCIeDevice_1.Device",             -- PCIe卡rootDevice,由组件设置给PCIeDevice后同步过来
            "Function": "<=/PCIeDevice_1.Function",         -- PCIe卡rootFunction,由组件设置给PCIeDevice后同步过来
            "DevBus": "<=/PCIeDevice_1.DevBus",             -- PCIe卡Bus,由组件设置给PCIeDevice后同步过来
            "DevDevice": "<=/PCIeDevice_1.DevDevice",       -- PCIe卡Device,由组件设置给PCIeDevice后同步过来
            "DevFunction": "<=/PCIeDevice_1.DevFunction",   -- PCIe卡Function,由组件设置给PCIeDevice后同步过来
            "SerialNumber": ""
        },
    ...
}

加载设备时,pcie_device会根据position匹配PCIeDevice对应的PcieAddrInfo,并将PcieAddrInfo上的SlotIDBDFrootBDF等信息同步给PCIeDevice

PCIeDeviceDeviceName中间需要带一个,pcie_device组件需要用这个标识符把对应的SlotID填入。

PCIeCard中和告警有关的属性由SDK调用pcie_device相关方法置位,速率和带宽相关信息由pcie_device通过IMU周期性查找。OCP卡同理,不过OCP卡会使用OCPCard对象。

NVME盘只有PCIeDevice对象,没有PCIeCardOCPCard对象。

4.2 设备树方式

设备树方式加载的卡的sr定义在component_drivers组件仓中,示例如下:

json
"FormatVersion": "5.00",                                    -- CSR版本号,5.00表示通过设备树加载
...
"Object": {
    ...
    "PCIeGpuCard_1": {
            "bmc.dev.PCIeDevice": {
                "DeviceName": "PCIe Card $ (Moore Threads MTT S4000)", -- 卡名称,中间的$占位符加载后会被替换为槽位号
                "DeviceType": "SingleFunction",
                "SlotType": "FullLength",
                "Model": "Moore Threads MTT S4000",
                "Manufacturer": "Moore Threads Technology Co.,Ltd",
                "PartNumber": "",
                "SerialNumber": "",
                "FirmwareVersion": ""
            },
            "bmc.dev.PCIeCard": {
                "Name": "Moore Threads MTT S4000",                     -- 设备名称
                "Description": "MTT S4000 Series GPU",
                "BoardName": "Moore Threads MTT S4000",                -- 单板名称
                "Health": "<=/Component_PCIeCard.Health"               -- 设备健康状态
            },
            "bmc.dev.PCIeDevice.PCIeFunction": {
                "VendorId": "0x1ed5",                                  -- 四元组中的Vid
                "DeviceId": "0x0323",                                  -- 四元组中的Did
                "SubSystemVendorId": "0x1ed5",                         -- 四元组中的SubVid
                "SubSystemDeviceId": "0x0323",                         -- 四元组中的SubDid
                "FunctionProtocol": "PCIe",
                "FunctionType": "Physical"
            },
            "bmc.dev.PCIeDevice.Oem": {
                "FunctionClass": 3,                                    -- PCIe设备分类代码
                "ComponentType": 8,                           -- 设备类型,同CompenentType,配置错误可能导致北向显示不对
                "Container": "${Container}",                           -- 所在设备,如果Riser、硬盘背板等
                "GroupPosition": "PCIeDevice_1_${GroupPosition}"
            }
        },
    ...
}

设备树加载的时会先分发到devmon,pcie_device会建立对devmon的监听,当有PCIeGpuCardPCIeNicCard被加载时,会手动创建对应的资源树对象PCIeDevicePCIeCardOCPCard

设备树对象加载和资源树很大的不同是,需要考虑跨组件的属性同步,部分属性同步还需要来回进行两次,具体见pcie_device代码中的device_mgmt部分。

5. PCIe卡不加载定位的一般流程

PCIe卡不加载的排查遵循以下流程图所示的步骤顺序进行:

5.1 步骤1:查看BDF上报情况

检查带内Host是否正常上报BDF信息,这是PCIe卡加载的前提条件。

前提说明: 带内Host是根据BMC生成的丝印文件来匹配槽位并上报BDF的。如果BDF正常上报,说明丝印文件中的SlotId、RootPortDeviceId等信息正确,无需再检查丝印,可直接进入步骤4。

判断方法:

  1. 查看bios组件日志,确认是否接收到BDF上报:

    • 日志路径:dump_info\LogDump\app.log
    • 关键字:biosget_pcie_silk_config
    • bios组件日志显示bios组件获取PCIeAddrInfo对象信息,生成丝印文件/data/opt/bmc/conf/bios/silkconfig.json
  2. 查看带内Host上报的BDF内容:

    • 日志路径:dump_info\AppDump\bios\1\bios_infodump_info\AppDump\bios\mdb_info.log
    • 关键字:PcieCardBDFOCPCardBDFPcieDiskBDF
    • 按照槽位顺序排列,每5个数据一组,分别对应SegmentSocketIdBusDeviceFunction
  3. 查看pcie_device组件是否监听到bios属性变化:

    • 日志路径:dump_info\LogDump\app.log
    • 关键字:pcie_devicePcieCardBDF

带内检查命令:

bash
# 查看带内PCIe设备树
lspci -tv

# 查看指定设备的详细信息
lspci -vv -s <设备BDF>

# 获取设备插槽物理位置
dmidecode -t 9

# 查看NVME硬盘信息
ls -l /sys/class/block/

说明:

  • OCP卡和PCIe卡的槽位号从1开始,NVME槽位号从0开始
  • 例如上报数据0 0 65 0 0代表一个PCIe卡,带内BDF为41:00.0,插在槽位3

5.2 步骤2:查看带内设备存在情况

如果没有BDF上报,需要先检查带内是否识别到该PCIe设备。

判断方法:

使用lspci -tv命令查看带内PCIe设备树,确认目标设备是否存在。如果设备在带内可见但未上报BDF,可能是bios上报流程问题;如果设备在带内不可见,需要检查硬件连接或驱动配置。

带内检查步骤:

  1. 执行lspci -tv,确认设备是否出现在PCIe设备树中
  2. 检查设备的Bus Address是否正确
  3. 确认设备是否被正确驱动加载

5.3 步骤3:查看丝印信息

带内有设备但没有BDF上报时,需要检查丝印信息是否正确。

判断方法:

  1. 查看丝印文件内容:

    • 文件路径:/data/opt/bmc/conf/bios/silkconfig.json(一键收集路径:/dump_info/AppDump/bios/1/silkconfig.json
    • 检查PCIeSilk数组中对应槽位的SlotIdRootPortDeviceIdSocketIdDeviceType是否与预期一致
    • DeviceType字段标识设备类型:"PCIe"对应PCIe卡,"OCP"对应OCP卡,"NVME"对应NVME硬盘
  2. 检查拓扑建立日志:

    • 日志路径:dump_info\LogDump\app.log
    • 关键字:BizTopoAddrInfo
    • 确认PcieAddrInfo对象的SlotIDPortIDSocketIDComponentType是否正确计算

关键日志示例:

[BizTopo] AddrInfo:SocketID: 0, PortID: 4, SlotID: 1, Bus: 1, Device: 4, Function: 0

说明:

  • RootPortDeviceId对应PortIDSlotId对应SlotID
  • DeviceType对应ComponentType"PCIe"对应ComponentType=8,"OCP"对应ComponentType=83,"NVME"对应ComponentType=2
  • 带内Host根据DeviceTypeSlotId组合索引来匹配槽位并上报对应类型的BDF
  • 如果丝印信息不正确,需要检查CSR配置或拓扑建立代码逻辑

步骤3.1:检查拓扑建立时序

如果丝印正确但仍没有BDF上报,需要检查带内Host捞取丝印时pcie_device是否已生成完毕。

判断方法:

  1. 查看拓扑建立的完成时间:

    • 日志路径:dump_info\LogDump\app.log
    • 关键字:[BizTopo] Main startconstruct_biz_topoprint_biz_topo
    • 确认拓扑建立流程是否已完成
  2. 查看PcieAddrInfo对象创建时间:

    • 日志路径:dump_info\LogDump\app.log
    • 关键字:[BizTopo] Add objectPcieAddrInfo
    • 确认PcieAddrInfo对象是否已成功创建并更新属性
  3. 对比bios获取丝印的时间:

    • 日志路径:dump_info\LogDump\app.log
    • 关键字:biosget_pcie_silk_config
    • bios组件获取PCIeAddrInfo对象信息生成丝印文件的时间

问题分析:

  • 如果带内Host捞取丝印时拓扑建立尚未完成,丝印文件可能不完整或为空,导致带内无法正确上报BDF
  • 此时应检查拓扑建立的触发条件是否正确,或等待拓扑建立完成后重新触发带内上报

5.4 步骤4:查看连接器信息置位情况

前提说明: 如果BDF正常上报,说明丝印信息正确(带内Host是根据丝印文件中的SlotId和RootPortDeviceId来匹配上报BDF的),此时直接检查Connector对象的Presence属性是否被置为1。

丝印正确后,检查Connector对象的Presence属性是否被置为1。

判断方法:

  1. 使用mdbctl查看Connector对象:

    bash
    mdbctl lsprop Connector_<name>
  2. 检查关键属性:

    • Presence:是否为1(表示在位)
    • Id:vid和did拼接的字符串(如14e417b0
    • AuxId:sub_vid和sub_did拼接的字符串
    • Bom:器件BOM号
  3. 查看框架加载日志:

    • 日志路径:dump_info\LogDump\framework.log
    • 关键字:对应卡的IdAuxId
    • 确认是否触发自发现加载PCIe卡的CSR分发对象

pcie_device关键日志:

  • 日志路径:dump_info\LogDump\app.log

  • 关键字:pcie_deviceGet id from PMU

  • 显示根据设备BDF查询到的四元组信息,设置Connector的Id、AuxId属性

  • 日志路径:dump_info\LogDump\app.log

  • 关键字:[DeviceService] Add objectclass: PCIeDevice

  • 确认PCIeDevice对象是否成功创建

说明:

  • CSR文件名由Connector的BomIdAuxId通过下划线拼接而成
  • 如果Presence未置位,继续步骤5检查IMU通信

5.5 步骤5:查看是否能通过IMU获取四元组

Connector未置位时,检查是否能通过IMU正确读取设备的VID、DID、SUB VID和SUB DID四元组信息。

判断方法:

  1. 查看pcie_device组件获取四元组的日志:

    • 日志路径:dump_info\LogDump\app.log
    • 关键字:Get id from PMU
    • 确认是否成功获取VID、DID信息
  2. 检查IMU命令执行情况:

    • 如果日志显示IMU命令执行失败,需要检查IMU通信是否正常
    • 确认设备BDF对应的IMU命令是否正确发送

说明:

  • IMU读取四元组失败会导致无法设置Connector的Id和AuxId属性
  • 如果能获取四元组,继续步骤6检查sr文件是否存在

5.6 步骤6:查看sr文件是否存在

能获取到四元组时,需要检查对应的sr文件是否存在于系统中。

判断方法:

  1. 根据四元组信息确定sr文件名:

    • sr文件名格式:Bom_Id_AuxId.sr
    • BomConnector的CSR配置(如14100513
    • Id由VID和DID拼接而成(如14e417b0
    • AuxId由SubVID和SubDID拼接而成(如14e417b0
  2. 检查sr文件路径:

    • 环境中:sr文件位于/opt/bmc/sr下
    • 资源树方式:sr文件位于vpd仓库,为带入还需要在manifest中配置
    • 设备树方式:sr文件位于component_drivers仓库,为带入还需要在manifest中配置
  3. 确认加载方式:

    • 查看FormatVersion字段:3.00表示资源树方式,5.00表示设备树方式
    • 根据加载方式确定后续排查路径

问题分析:

  • 如果sr文件不存在,说明该四元组对应的PCIe卡未被适配,需要补充sr文件
  • 如果sr文件存在,根据加载方式继续排查:
    • 资源树方式:检查框架加载日志
    • 设备树方式:检查框架加载日志,继续步骤7检查devmon状态

5.7 步骤7:查看devmon是否发生coredump

对于设备树方式加载的卡,如果Connector已置位但卡仍未加载,需要检查devmon组件状态。

判断方法:

  1. 检查devmon组件是否正常运行
  2. 查看是否有devmon相关的coredump日志
  3. 检查设备树对象创建日志:
    • 日志路径:dump_info\LogDump\app.log
    • 关键字:[device_mgmt] create_resource_obj

设备树加载关键日志:

  • 日志路径:dump_info\LogDump\app.log

  • 关键字:[device_mgmt] on_add_device_obj

  • 确认是否监听到设备树对象新增信号

  • 日志路径:dump_info\LogDump\app.log

  • 关键字:[device_mgmt_pcie_card] create_resource_obj

  • 确认PCIeCard资源树对象是否成功创建

说明:

  • 设备树方式加载时,pcie_device会先监听devmon,收到设备树对象后手动创建资源树对象
  • 如果devmon发生coredump,设备树对象无法正常分发

6. Q&A

Q: 我应该在哪里新增一张PCIe卡?

A:如果预期使用资源树方式,在vpd仓中;如果预期使用设备树方式,在component_driver中。设备树方式可定制性更高一些。