aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/probe.c56
1 files changed, 47 insertions, 9 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 446e4a94d7d3..dd64310a735e 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1081,6 +1081,37 @@ struct pci_dev *__ref pci_scan_single_device(struct pci_bus *bus, int devfn)
1081} 1081}
1082EXPORT_SYMBOL(pci_scan_single_device); 1082EXPORT_SYMBOL(pci_scan_single_device);
1083 1083
1084static unsigned next_ari_fn(struct pci_dev *dev, unsigned fn)
1085{
1086 u16 cap;
1087 unsigned pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI);
1088 if (!pos)
1089 return 0;
1090 pci_read_config_word(dev, pos + 4, &cap);
1091 return cap >> 8;
1092}
1093
1094static unsigned next_trad_fn(struct pci_dev *dev, unsigned fn)
1095{
1096 return (fn + 1) % 8;
1097}
1098
1099static unsigned no_next_fn(struct pci_dev *dev, unsigned fn)
1100{
1101 return 0;
1102}
1103
1104static int only_one_child(struct pci_bus *bus)
1105{
1106 struct pci_dev *parent = bus->self;
1107 if (!parent || !pci_is_pcie(parent))
1108 return 0;
1109 if (parent->pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
1110 parent->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)
1111 return 1;
1112 return 0;
1113}
1114
1084/** 1115/**
1085 * pci_scan_slot - scan a PCI slot on a bus for devices. 1116 * pci_scan_slot - scan a PCI slot on a bus for devices.
1086 * @bus: PCI bus to scan 1117 * @bus: PCI bus to scan
@@ -1094,21 +1125,28 @@ EXPORT_SYMBOL(pci_scan_single_device);
1094 */ 1125 */
1095int pci_scan_slot(struct pci_bus *bus, int devfn) 1126int pci_scan_slot(struct pci_bus *bus, int devfn)
1096{ 1127{
1097 int fn, nr = 0; 1128 unsigned fn, nr = 0;
1098 struct pci_dev *dev; 1129 struct pci_dev *dev;
1130 unsigned (*next_fn)(struct pci_dev *, unsigned) = no_next_fn;
1131
1132 if (only_one_child(bus) && (devfn > 0))
1133 return 0; /* Already scanned the entire slot */
1099 1134
1100 dev = pci_scan_single_device(bus, devfn); 1135 dev = pci_scan_single_device(bus, devfn);
1101 if (dev && !dev->is_added) /* new device? */ 1136 if (dev && !dev->is_added) /* new device? */
1102 nr++; 1137 nr++;
1103 1138
1104 if (dev && dev->multifunction) { 1139 if (pci_ari_enabled(bus))
1105 for (fn = 1; fn < 8; fn++) { 1140 next_fn = next_ari_fn;
1106 dev = pci_scan_single_device(bus, devfn + fn); 1141 else if (dev && dev->multifunction)
1107 if (dev) { 1142 next_fn = next_trad_fn;
1108 if (!dev->is_added) 1143
1109 nr++; 1144 for (fn = next_fn(dev, 0); fn > 0; fn = next_fn(dev, fn)) {
1110 dev->multifunction = 1; 1145 dev = pci_scan_single_device(bus, devfn + fn);
1111 } 1146 if (dev) {
1147 if (!dev->is_added)
1148 nr++;
1149 dev->multifunction = 1;
1112 } 1150 }
1113 } 1151 }
1114 1152