Skip to content

Commit

Permalink
PCI: Move jailhouse's isolated function handling to pci_scan_slot()
Browse files Browse the repository at this point in the history
The special case of the jailhouse hypervisor passing through individual PCI
functions handles scanning for PCI functions even if function 0 does not
exist. Previously this was done with an extra loop duplicating the one in
pci_scan_slot(). By incorporating the check for jailhouse_paravirt() into
pci_scan_slot() we can instead do this as part of the normal slot scan.
Note that with the assignment of dev->multifunction gated by fn > 0 we set
dev->multifunction unconditionally for all functions if function 0 is
missing just as in the existing jailhouse loop.

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 <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Niklas Schnelle <[email protected]>
Signed-off-by: Bjorn Helgaas <[email protected]>
Reviewed-by: Pierre Morel <[email protected]>
Cc: Jan Kiszka <[email protected]>
  • Loading branch information
niklas88 authored and bjorn-helgaas committed Jul 22, 2022
1 parent fbed59e commit db360b1
Showing 1 changed file with 10 additions and 20 deletions.
30 changes: 10 additions & 20 deletions drivers/pci/probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -2663,8 +2663,13 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
if (fn > 0)
dev->multifunction = 1;
} else if (fn == 0) {
/* function 0 is required */
break;
/*
* Function 0 is required unless we are running on
* a hypervisor that passes through individual PCI
* functions.
*/
if (!jailhouse_paravirt())
break;
}
fn = next_fn(bus, dev, fn);
} while (fn >= 0);
Expand Down Expand Up @@ -2863,29 +2868,14 @@ 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) {
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;
}
}
}
for (devfn = 0; devfn < 256; devfn += 8)
pci_scan_slot(bus, devfn);

/* Reserve buses for SR-IOV capability */
used_buses = pci_iov_bus_range(bus);
Expand Down

0 comments on commit db360b1

Please sign in to comment.