lspci 如何找出 PCI(E) 设备的物理插槽号?

How does lspci find out physical slot number of a PCI(E) device?

lspci可以在详细介绍中显示物理插槽号:

我想了解它是如何做到的。我将在我想修改的 driver 中应用此方法,因此它将枚举设备(具有相同的 ID)并根据物理插槽消除设备文件的歧义。喜欢 /dev/device_physslot 。 driver 将在 Ubuntu 18

上 运行

我试图挖掘源代码。我在 https://github.com/pciutils/pciutils/blob/master/lspci.c:

中找到了相关的第 775 行
if (p->phy_slot)
    printf("\tPhysical Slot: %s\n", p->phy_slot);

p 是 struct pci_dev。这一直很令人困惑,因为标准 linux/pci.h 没有字段 phy_slot 直到我弄清楚那是 their own (re)definition

结构is filled由函数

int
pci_fill_info_v38(struct pci_dev *d, int flags)
{
  unsigned int uflags = flags;
  if (uflags & PCI_FILL_RESCAN)
    {
      uflags &= ~PCI_FILL_RESCAN;
      pci_reset_properties(d);
    }
  if (uflags & ~d->known_fields)
    d->methods->fill_info(d, uflags);
  return d->known_fields;
}

fill_info是在https://github.com/pciutils/pciutils/blob/master/lib/internal.h(第44行)

中定义的函数指针

这就是我迷路的地方。

如果你 运行 dmidecode 它将显示存储的平台信息,它会告诉你物理插槽到 PCIe 地址的映射。例如:

Handle 0x001D, DMI type 9, 17 bytes
System Slot Information
    Designation: J6B1
    Type: x1 PCI Express
    Current Usage: In Use
    Length: Short
    ID: 1                      <== SLOT (starting at 0)
    Characteristics:
        3.3 V is provided
        Opening is shared
        PME signal is supported
    Bus Address: 0000:00:1c.3    <== PCI BUS ADDRESS

槽的编程列表:

sudo dmidecode -t 9 |awk '/ID:/ {id=} /Bus Address/ {print "Slot",id+1,"PCIe",}'
Slot 1 PCIe 0000:00:01.0
Slot 2 PCIe 0000:00:1c.3
Slot 3 PCIe 0000:00:1c.4
Slot 4 PCIe 0000:00:1c.5
Slot 5 PCIe 0000:00:1c.6

深入挖掘源代码并在调试器中成功使用 运行 lspci(感谢 Netbeans)后,我发现 lspci 使用 sysfs 来收集信息。 特别是 /sys/bus/pci/slots/slot_num/address 文件包含插槽的总线地址。这就是 lspci 在函数 sysfs_fill_slots(在 sysfs.c)

中用来将插槽归因于总线地址的方法

不幸的是,这种方法不适合我的目的,因为无法从内核模块执行文件I/O。