This patch fixes two problems. One is that devices which support ARI may not have all their functions discovered. The main PCI code will find them all, if they're contiguous, but if they're hotplugged, the hotplug drivers will only call pci_scan_slot() for devfn 0, and thus will only scan the first 8 functions. The second is that the functions in an ARI device can be discovered through walking a linked list in extended config space. In this case, we don't have to check one devfn in eight, we can just stop looking when we reach the end of the linked list. I'm unconvinced this is an improvement in speed, given that there will be multiple successful reads from extended config space instead of multiple failed reads from config space which doesn't exist ... anyway, it makes the code look better. I tried a few different options for different ways to discover functions. The next_fn pointer seemed like the best way to go. This patch ignores the pcibios_scan_all_fns() work that Alex has been doing; it should probably be rebased on top of that. An improvement would note that all PCIe devices which have a Downstream Port as a parent can only be probed with a devfn of 0, and so return early in that case too, not just if ARI is set. Looking for feedback at this point ... diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 40e75f6..62fb22c 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1041,6 +1041,26 @@ struct pci_dev *__ref pci_scan_single_device(struct pci_bus *bus, int devfn) } EXPORT_SYMBOL(pci_scan_single_device); +static unsigned next_ari_fn(struct pci_dev *dev, unsigned fn) +{ + u16 cap; + unsigned pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI); + if (!pos) + return 0; + pci_read_config_word(dev, pos + 4, &cap); + return cap >> 8; +} + +static unsigned next_trad_fn(struct pci_dev *dev, unsigned fn) +{ + return (fn + 1) % 8; +} + +static unsigned no_next_fn(struct pci_dev *dev, unsigned fn) +{ + return 0; +} + /** * pci_scan_slot - scan a PCI slot on a bus for devices. * @bus: PCI bus to scan @@ -1054,22 +1074,28 @@ EXPORT_SYMBOL(pci_scan_single_device); */ int pci_scan_slot(struct pci_bus *bus, int devfn) { - int fn, nr = 0; + unsigned fn, nr = 0; struct pci_dev *dev; + unsigned (*next_fn)(struct pci_dev *, unsigned) = no_next_fn; + + if (pci_ari_enabled(bus) && (devfn > 0)) + return 0; /* Already scanned the entire slot */ dev = pci_scan_single_device(bus, devfn); if (dev && !dev->is_added) /* new device? */ nr++; - if ((dev && dev->multifunction) || - (!dev && pcibios_scan_all_fns(bus, devfn))) { - for (fn = 1; fn < 8; fn++) { - dev = pci_scan_single_device(bus, devfn + fn); - if (dev) { - if (!dev->is_added) - nr++; - dev->multifunction = 1; - } + if (pci_ari_enabled(bus)) + next_fn = next_ari_fn; + else if (dev && dev->multifunction) + next_fn = next_trad_fn; + + for (fn = next_fn(dev, 0); fn > 0; fn = next_fn(dev, fn)) { + dev = pci_scan_single_device(bus, devfn + fn); + if (dev) { + if (!dev->is_added) + nr++; + dev->multifunction = 1; } } -- Matthew Wilcox Intel Open Source Technology Centre "Bill, look, we understand that you're interested in selling us this operating system, but compare it to ours. We can't possibly take such a retrograde step." -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html