Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PCI: Move jailhouse's isolated function handling to pci_scan_slot()

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 <bhelgaas@google.com>
Link: https://lore.kernel.org/r/20220628143100.3228092-4-schnelle@linux.ibm.com
Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Pierre Morel <pmorel@linux.ibm.com>
Cc: Jan Kiszka <jan.kiszka@siemens.com>

authored by

Niklas Schnelle and committed by
Bjorn Helgaas
db360b1e fbed59ed

+10 -20
+10 -20
drivers/pci/probe.c
··· 2663 2663 if (fn > 0) 2664 2664 dev->multifunction = 1; 2665 2665 } else if (fn == 0) { 2666 - /* function 0 is required */ 2667 - break; 2666 + /* 2667 + * Function 0 is required unless we are running on 2668 + * a hypervisor that passes through individual PCI 2669 + * functions. 2670 + */ 2671 + if (!jailhouse_paravirt()) 2672 + break; 2668 2673 } 2669 2674 fn = next_fn(bus, dev, fn); 2670 2675 } while (fn >= 0); ··· 2868 2863 { 2869 2864 unsigned int used_buses, normal_bridges = 0, hotplug_bridges = 0; 2870 2865 unsigned int start = bus->busn_res.start; 2871 - unsigned int devfn, fn, cmax, max = start; 2866 + unsigned int devfn, cmax, max = start; 2872 2867 struct pci_dev *dev; 2873 - int nr_devs; 2874 2868 2875 2869 dev_dbg(&bus->dev, "scanning bus\n"); 2876 2870 2877 2871 /* Go find them, Rover! */ 2878 - for (devfn = 0; devfn < 256; devfn += 8) { 2879 - nr_devs = pci_scan_slot(bus, devfn); 2880 - 2881 - /* 2882 - * The Jailhouse hypervisor may pass individual functions of a 2883 - * multi-function device to a guest without passing function 0. 2884 - * Look for them as well. 2885 - */ 2886 - if (jailhouse_paravirt() && nr_devs == 0) { 2887 - for (fn = 1; fn < 8; fn++) { 2888 - dev = pci_scan_single_device(bus, devfn + fn); 2889 - if (dev) 2890 - dev->multifunction = 1; 2891 - } 2892 - } 2893 - } 2872 + for (devfn = 0; devfn < 256; devfn += 8) 2873 + pci_scan_slot(bus, devfn); 2894 2874 2895 2875 /* Reserve buses for SR-IOV capability */ 2896 2876 used_buses = pci_iov_bus_range(bus);