From: Dimitri Daskalakis <[email protected]> SDI routing IDs are computed from the PF's devfn plus an offset and stride, exactly like SR-IOV VFs. When the stride pushes routing IDs past the current bus number, additional bus numbers must be reserved during PCI bus scanning to ensure the SDIs can be enumerated.
Add pci_siov_bus_range(), which walks all SIOV-capable PFs on a bus and returns the maximum number of additional buses required. This parallels pci_iov_bus_range() for SR-IOV. The bus range is pre-computed during siov_init() by computing the bus number of the last valid SDI. Note: The PCIe 7.0 spec outlines an alternative RID assignment algorithm for SDIs. The spec states a Virtualization Intermediary (likely a hypervisor) after boot can compute the set of RIDs that are valid for SDIs. There is a six step algorithm to compute this RID allowlist. To keep things simple, we are only adding support for strided RID assignments. Assisted-by: Claude:claude-opus-4.7 Signed-off-by: Dimitri Daskalakis <[email protected]> --- drivers/pci/probe.c | 4 ++-- drivers/pci/siov.c | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index bebc32c8d374..9ef6827ab345 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -3100,8 +3100,8 @@ static unsigned int pci_scan_child_bus_extend(struct pci_bus *bus, for (devnr = 0; devnr < PCI_MAX_NR_DEVS; devnr++) pci_scan_slot(bus, PCI_DEVFN(devnr, 0)); - /* Reserve buses for SR-IOV capability */ - used_buses = pci_iov_bus_range(bus); + /* Reserve buses for SR-IOV and SIOV capability */ + used_buses = max(pci_iov_bus_range(bus), pci_siov_bus_range(bus)); max += used_buses; /* diff --git a/drivers/pci/siov.c b/drivers/pci/siov.c index 7372ce95714b..6405a8830052 100644 --- a/drivers/pci/siov.c +++ b/drivers/pci/siov.c @@ -111,3 +111,24 @@ void pci_siov_release(struct pci_dev *dev) if (dev->siov) siov_release(dev); } + +/** + * pci_siov_bus_range - find the max bus number consumed by SDIs + * @bus: the PCI bus + * + * Returns max additional buses consumed across all SIOV PFs on this bus. + */ +int pci_siov_bus_range(struct pci_bus *bus) +{ + int max = 0; + struct pci_dev *dev; + + list_for_each_entry(dev, &bus->devices, bus_list) { + if (!dev->siov) + continue; + if (dev->siov->max_SDI_buses > max) + max = dev->siov->max_SDI_buses; + } + + return max ? max - bus->number : 0; +} -- 2.52.0
