The special case of the jailhouse hypervisor passing through individual PCI functions handles scanning for PCI functions even if function 0 does not exist. Currently this is done with an extra loop duplicating the one in pci_scan_slot(). By incorporating the check for jailhouse_paravirt() into next_fn() we can instead do this as part of the normal pci_scan_slot(). The only functional change is that we now call pcie_aspm_init_link_state() for these functions but this already happened if function 0 was passed through and should not be a problem. Link: https://lore.kernel.org/linux-pci/20220408224514.GA353445@bhelgaas/ Suggested-by: Bjorn Helgaas <bhelgaas@xxxxxxxxxx> Signed-off-by: Niklas Schnelle <schnelle@xxxxxxxxxxxxx> --- drivers/pci/probe.c | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 389aa1f9cb2c..8100e044dfc5 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2602,10 +2602,11 @@ static int next_fn(struct pci_bus *bus, struct pci_dev *dev, int fn) if (dev && !dev->multifunction) return -ENODEV; /* - * A function 0 is required but multifunction devices may - * be non-contiguous so dev can be NULL otherwise. + * Usually a function 0 is required but the jailhouse hypervisor may + * pass individual functions. For non-contiguous multifunction devices + * some functions may also be missing. */ - if (!fn && !dev) + if (!fn && !dev && !jailhouse_paravirt()) return -ENODEV; return (fn <= 6) ? fn + 1 : -ENODEV; } @@ -2855,30 +2856,16 @@ static unsigned int pci_scan_child_bus_extend(struct pci_bus *bus, { unsigned int used_buses, normal_bridges = 0, hotplug_bridges = 0; unsigned int start = bus->busn_res.start; - unsigned int devfn, fn, cmax, max = start; + unsigned int devfn, cmax, max = start; struct pci_dev *dev; int nr_devs; dev_dbg(&bus->dev, "scanning bus\n"); /* Go find them, Rover! */ - for (devfn = 0; devfn < 256; devfn += 8) { + for (devfn = 0; devfn < 256; devfn += 8) nr_devs = pci_scan_slot(bus, devfn); - /* - * The Jailhouse hypervisor may pass individual functions of a - * multi-function device to a guest without passing function 0. - * Look for them as well. - */ - if (jailhouse_paravirt() && nr_devs == 0) { - for (fn = 1; fn < 8; fn++) { - dev = pci_scan_single_device(bus, devfn + fn); - if (dev) - dev->multifunction = 1; - } - } - } - /* Reserve buses for SR-IOV capability */ used_buses = pci_iov_bus_range(bus); max += used_buses; -- 2.32.0