我不明白插槽是什么意思。 它是来自 dbdf(Domain:bus:device:function) 的设备号?
来自这里的代码:: https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/pci.h#L32
/*
* The PCI interface treats multi-function devices as independent
* devices. The slot/function address of each device is encoded
* in a single byte as follows:
*
* 7:3 = slot
* 2:0 = function
*/
#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
#define PCI_FUNC(devfn) ((devfn) & 0x07)
每个 PCI 外围设备由总线号、设备号和功能标识 数字。每辆巴士最多可容纳 32 设备,每个设备可以是一个多功能板(如音频设备与 随附的 CD-ROM 驱动器)最多具有八个功能。所以, 每个功能都可以通过 16 位地址或密钥在硬件级别进行识别。
不过,为 Linux 编写的设备驱动程序不需要处理这些二进制地址, 因为它们使用特定的数据结构,称为 pci_dev,来作用于设备。
如评论所述:
PCI接口将多功能设备视为独立设备。
多功能板中的独立设备具有相同的设备号,又名PCI_SLOT(devfn),被视为一个物理插槽,称为pci_slot。
让我们深入研究代码以展示 PCI 外设的组织方式。
//in drivers/pci/probe.c
pci_scan_child_bus_extend()
//...
dev_dbg(&bus->dev, "scanning bus\n");
/* Go find them, Rover! */
for (devfn = 0; devfn < 256; devfn += 8)
pci_scan_slot(bus, devfn);
//...
每个设备可以是一个最多八个功能的多功能板,也就是说一个物理pci_slot最多可以承载8个独立的pci_dev,所以linux扫描slot的步骤是8.
// in drivers/pci/probe.c
int pci_scan_slot(struct pci_bus *bus, int devfn)
{
//...
do {
dev = pci_scan_single_device(bus, devfn + fn);
if (dev) {
if (!pci_dev_is_added(dev))
nr++;
if (fn > 0)
dev->multifunction = 1;
} else if (fn == 0) {
/*
* Function 0 is required unless we are running on
* a hypervisor that passes through individual PCI
* functions.
*/
if (!hypervisor_isolated_pci_functions())
break;
}
fn = next_fn(bus, dev, fn);
} while (fn >= 0);
如果多功能板有多个功能,Linux 将扫描每个功能并为其分配一个 pci_dev 结构。对于非多功能板,只会分配一个 pci_dev。
pci_scan_child_bus()
+-> pci_scan_child_bus_extend()
+-> for (devfn = 0; devfn < 256; devfn += 8)
pci_scan_slot()
+-> pci_scan_single_device()
+-> pci_scan_device()
+-> pci_bus_read_dev_vendor_id()
+-> pci_alloc_dev()
+-> pci_setup_device()
+-> pci_dev_assign_slot(dev);
dev->slot = slot;
最后,多功能板中所有具有相同设备号的pci_dev将链接到同一个pci_slot。
参考: