diff options
Diffstat (limited to 'drivers/pci/probe.c')
-rw-r--r-- | drivers/pci/probe.c | 66 |
1 files changed, 38 insertions, 28 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 2dcd22d9c816..b4a6ede8f17a 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -1285,7 +1285,7 @@ static void pci_init_capabilities(struct pci_dev *dev) | |||
1285 | pci_vpd_pci22_init(dev); | 1285 | pci_vpd_pci22_init(dev); |
1286 | 1286 | ||
1287 | /* Alternative Routing-ID Forwarding */ | 1287 | /* Alternative Routing-ID Forwarding */ |
1288 | pci_enable_ari(dev); | 1288 | pci_configure_ari(dev); |
1289 | 1289 | ||
1290 | /* Single Root I/O Virtualization */ | 1290 | /* Single Root I/O Virtualization */ |
1291 | pci_iov_init(dev); | 1291 | pci_iov_init(dev); |
@@ -1348,31 +1348,31 @@ struct pci_dev *__ref pci_scan_single_device(struct pci_bus *bus, int devfn) | |||
1348 | } | 1348 | } |
1349 | EXPORT_SYMBOL(pci_scan_single_device); | 1349 | EXPORT_SYMBOL(pci_scan_single_device); |
1350 | 1350 | ||
1351 | static unsigned next_ari_fn(struct pci_dev *dev, unsigned fn) | 1351 | static unsigned next_fn(struct pci_bus *bus, struct pci_dev *dev, unsigned fn) |
1352 | { | 1352 | { |
1353 | u16 cap; | 1353 | int pos; |
1354 | unsigned pos, next_fn; | 1354 | u16 cap = 0; |
1355 | unsigned next_fn; | ||
1355 | 1356 | ||
1356 | if (!dev) | 1357 | if (pci_ari_enabled(bus)) { |
1357 | return 0; | 1358 | if (!dev) |
1359 | return 0; | ||
1360 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI); | ||
1361 | if (!pos) | ||
1362 | return 0; | ||
1358 | 1363 | ||
1359 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI); | 1364 | pci_read_config_word(dev, pos + PCI_ARI_CAP, &cap); |
1360 | if (!pos) | 1365 | next_fn = PCI_ARI_CAP_NFN(cap); |
1361 | return 0; | 1366 | if (next_fn <= fn) |
1362 | pci_read_config_word(dev, pos + 4, &cap); | 1367 | return 0; /* protect against malformed list */ |
1363 | next_fn = cap >> 8; | ||
1364 | if (next_fn <= fn) | ||
1365 | return 0; | ||
1366 | return next_fn; | ||
1367 | } | ||
1368 | 1368 | ||
1369 | static unsigned next_trad_fn(struct pci_dev *dev, unsigned fn) | 1369 | return next_fn; |
1370 | { | 1370 | } |
1371 | return (fn + 1) % 8; | 1371 | |
1372 | } | 1372 | /* dev may be NULL for non-contiguous multifunction devices */ |
1373 | if (!dev || dev->multifunction) | ||
1374 | return (fn + 1) % 8; | ||
1373 | 1375 | ||
1374 | static unsigned no_next_fn(struct pci_dev *dev, unsigned fn) | ||
1375 | { | ||
1376 | return 0; | 1376 | return 0; |
1377 | } | 1377 | } |
1378 | 1378 | ||
@@ -1405,7 +1405,6 @@ int pci_scan_slot(struct pci_bus *bus, int devfn) | |||
1405 | { | 1405 | { |
1406 | unsigned fn, nr = 0; | 1406 | unsigned fn, nr = 0; |
1407 | struct pci_dev *dev; | 1407 | struct pci_dev *dev; |
1408 | unsigned (*next_fn)(struct pci_dev *, unsigned) = no_next_fn; | ||
1409 | 1408 | ||
1410 | if (only_one_child(bus) && (devfn > 0)) | 1409 | if (only_one_child(bus) && (devfn > 0)) |
1411 | return 0; /* Already scanned the entire slot */ | 1410 | return 0; /* Already scanned the entire slot */ |
@@ -1416,12 +1415,7 @@ int pci_scan_slot(struct pci_bus *bus, int devfn) | |||
1416 | if (!dev->is_added) | 1415 | if (!dev->is_added) |
1417 | nr++; | 1416 | nr++; |
1418 | 1417 | ||
1419 | if (pci_ari_enabled(bus)) | 1418 | for (fn = next_fn(bus, dev, 0); fn > 0; fn = next_fn(bus, dev, fn)) { |
1420 | next_fn = next_ari_fn; | ||
1421 | else if (dev->multifunction) | ||
1422 | next_fn = next_trad_fn; | ||
1423 | |||
1424 | for (fn = next_fn(dev, 0); fn > 0; fn = next_fn(dev, fn)) { | ||
1425 | dev = pci_scan_single_device(bus, devfn + fn); | 1419 | dev = pci_scan_single_device(bus, devfn + fn); |
1426 | if (dev) { | 1420 | if (dev) { |
1427 | if (!dev->is_added) | 1421 | if (!dev->is_added) |
@@ -1632,6 +1626,18 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus) | |||
1632 | return max; | 1626 | return max; |
1633 | } | 1627 | } |
1634 | 1628 | ||
1629 | /** | ||
1630 | * pcibios_root_bridge_prepare - Platform-specific host bridge setup. | ||
1631 | * @bridge: Host bridge to set up. | ||
1632 | * | ||
1633 | * Default empty implementation. Replace with an architecture-specific setup | ||
1634 | * routine, if necessary. | ||
1635 | */ | ||
1636 | int __weak pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) | ||
1637 | { | ||
1638 | return 0; | ||
1639 | } | ||
1640 | |||
1635 | struct pci_bus *pci_create_root_bus(struct device *parent, int bus, | 1641 | struct pci_bus *pci_create_root_bus(struct device *parent, int bus, |
1636 | struct pci_ops *ops, void *sysdata, struct list_head *resources) | 1642 | struct pci_ops *ops, void *sysdata, struct list_head *resources) |
1637 | { | 1643 | { |
@@ -1665,6 +1671,10 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, | |||
1665 | bridge->dev.parent = parent; | 1671 | bridge->dev.parent = parent; |
1666 | bridge->dev.release = pci_release_bus_bridge_dev; | 1672 | bridge->dev.release = pci_release_bus_bridge_dev; |
1667 | dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus); | 1673 | dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus); |
1674 | error = pcibios_root_bridge_prepare(bridge); | ||
1675 | if (error) | ||
1676 | goto bridge_dev_reg_err; | ||
1677 | |||
1668 | error = device_register(&bridge->dev); | 1678 | error = device_register(&bridge->dev); |
1669 | if (error) | 1679 | if (error) |
1670 | goto bridge_dev_reg_err; | 1680 | goto bridge_dev_reg_err; |