diff options
Diffstat (limited to 'drivers/pci/probe.c')
-rw-r--r-- | drivers/pci/probe.c | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index ef5377438a1e..3c365dc996e7 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -16,6 +16,7 @@ #include <linux/pci-aspm.h> #include <linux/aer.h> #include <linux/acpi.h> +#include <linux/hypervisor.h> #include <linux/irqdomain.h> #include <linux/pm_runtime.h> #include "pci.h" @@ -2518,14 +2519,29 @@ 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, cmax, max = start; + unsigned int devfn, fn, 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 < 0x100; devfn += 8) - pci_scan_slot(bus, devfn); + 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); |