On Tue, 2022-04-12 at 16:30 +0200, Niklas Schnelle wrote: > While determining the next PCI function is factored out of > pci_scan_slot() into next_fn() the former still handles the first > function as a special case duplicating the code from the scan loop and > splitting the condition that the first function exits from it being > multifunction which is tested in next_fn(). > > Furthermore the non ARI branch of next_fn() mixes the case that > multifunction devices may have non-contiguous function ranges and dev > may thus be NULL with the multifunction requirement. It also signals > that no further functions need to be scanned by returning 0 which is > a valid function number. > > Improve upon this by moving all conditions for having to scan for more > functions into next_fn() and make them obvious and commented. > > By changing next_fn() to return -ENODEV instead of 0 when there is no > next function we can then handle the initial function inside the loop > and deduplicate the shared handling. > > No functional change is intended. > > Signed-off-by: Niklas Schnelle <schnelle@xxxxxxxxxxxxx> > --- > drivers/pci/probe.c | 41 +++++++++++++++++++---------------------- > 1 file changed, 19 insertions(+), 22 deletions(-) > > diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c > index 17a969942d37..389aa1f9cb2c 100644 > --- a/drivers/pci/probe.c > +++ b/drivers/pci/probe.c > @@ -2579,33 +2579,35 @@ struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn) > } > EXPORT_SYMBOL(pci_scan_single_device); > > -static unsigned int next_fn(struct pci_bus *bus, struct pci_dev *dev, > - unsigned int fn) > +static int next_fn(struct pci_bus *bus, struct pci_dev *dev, int fn) > { > int pos; > u16 cap = 0; > unsigned int next_fn; > > - if (pci_ari_enabled(bus)) { > - if (!dev) > - return 0; This part here theoretically changes the behavior slightly. If the ARI information is wrong/lands us in a "hole" we may look for more functions via the non-ARI path. Not sure if that is relevant though as in the worst case we might find functions that we otherwise wouldn't have seen. Seems rather obsure to me but I might be wrong, we currently don't see the ARI capability in Linux on IBM Z so I have less experience with this. I did of course boot test on my x86_64 workstation. > + if (dev && pci_ari_enabled(bus)) { > pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI); > if (!pos) > - return 0; > + return -ENODEV; > > pci_read_config_word(dev, pos + PCI_ARI_CAP, &cap); > next_fn = PCI_ARI_CAP_NFN(cap); > if (next_fn <= fn) > - return 0; /* protect against malformed list */ > + return -ENODEV; /* protect against malformed list */ > > return next_fn; > } > > - /* dev may be NULL for non-contiguous multifunction devices */ > - if (!dev || dev->multifunction) > - return (fn + 1) % 8; > - > - return 0; > + /* only multifunction devices may have more functions */ > + if (dev && !dev->multifunction) > + return -ENODEV; > + /* > + * A function 0 is required but multifunction devices may > + * be non-contiguous so dev can be NULL otherwise. > + */ > + if (!fn && !dev) > + return -ENODEV; > + return (fn <= 6) ? fn + 1 : -ENODEV; > } > > ---8<---