diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2017-11-30 16:22:39 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2017-12-19 00:04:17 -0500 |
commit | d57f0b8c81393e7105331ac037fa465d5a45c65f (patch) | |
tree | dd39b3e48799e25ea2ca73583d63d0b8ba9ef532 | |
parent | 1291a0d5049dbc06baaaf66a9ff3f53db493b19b (diff) |
PCI: Make PCI_SCAN_ALL_PCIE_DEVS work for Root as well as Downstream Ports
PCIe Downstream Ports normally have only a Device 0 below them. To
optimize enumeration, we don't scan for other devices *unless* the
PCI_SCAN_ALL_PCIE_DEVS flag is set by set by quirks or the
"pci=pcie_scan_all" kernel parameter.
Previously PCI_SCAN_ALL_PCIE_DEVS only affected scanning below Switch
Downstream Ports, not Root Ports.
But the "Nemo" system, also known as the AmigaOne X1000, has a PA Semi Root
Port whose link leads to an AMD/ATI SB600 South Bridge. The Root Port is a
PCIe device, of course, but the SB600 contains only conventional PCI
devices with no visible PCIe port.
Simplify and restructure only_one_child() so that we scan for all possible
devices below Root Ports as well as Switch Downstream Ports when
PCI_SCAN_ALL_PCIE_DEVS is set.
This is enough to make Nemo work with "pci=pcie_scan_all". We would also
like to add a quirk to set PCI_SCAN_ALL_PCIE_DEVS automatically on Nemo so
users wouldn't have to use the "pci=pcie_scan_all" parameter, but we don't
have that yet.
Link: https://lkml.kernel.org/r/CAErSpo55Q8Q=5p6_+uu7ahnw+53ibVDNRXxrzRV9QnUr_9EUfw@mail.gmail.com
Link: https://bugzilla.kernel.org/show_bug.cgi?id=198057
Reported-and-Tested-by: Christian Zigotzky <chzigotzky@xenosoft.de>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r-- | drivers/pci/probe.c | 25 |
1 files changed, 15 insertions, 10 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 14e0ea1ff38b..303c0cb0550c 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -2215,22 +2215,27 @@ static unsigned next_fn(struct pci_bus *bus, struct pci_dev *dev, unsigned fn) | |||
2215 | 2215 | ||
2216 | static int only_one_child(struct pci_bus *bus) | 2216 | static int only_one_child(struct pci_bus *bus) |
2217 | { | 2217 | { |
2218 | struct pci_dev *parent = bus->self; | 2218 | struct pci_dev *bridge = bus->self; |
2219 | 2219 | ||
2220 | if (!parent || !pci_is_pcie(parent)) | 2220 | /* |
2221 | * Systems with unusual topologies set PCI_SCAN_ALL_PCIE_DEVS so | ||
2222 | * we scan for all possible devices, not just Device 0. | ||
2223 | */ | ||
2224 | if (pci_has_flag(PCI_SCAN_ALL_PCIE_DEVS)) | ||
2221 | return 0; | 2225 | return 0; |
2222 | if (pci_pcie_type(parent) == PCI_EXP_TYPE_ROOT_PORT) | ||
2223 | return 1; | ||
2224 | 2226 | ||
2225 | /* | 2227 | /* |
2226 | * PCIe downstream ports are bridges that normally lead to only a | 2228 | * A PCIe Downstream Port normally leads to a Link with only Device |
2227 | * device 0, but if PCI_SCAN_ALL_PCIE_DEVS is set, scan all | 2229 | * 0 on it (PCIe spec r3.1, sec 7.3.1). As an optimization, scan |
2228 | * possible devices, not just device 0. See PCIe spec r3.0, | 2230 | * only for Device 0 in that situation. |
2229 | * sec 7.3.1. | 2231 | * |
2232 | * Checking has_secondary_link is a hack to identify Downstream | ||
2233 | * Ports because sometimes Switches are configured such that the | ||
2234 | * PCIe Port Type labels are backwards. | ||
2230 | */ | 2235 | */ |
2231 | if (parent->has_secondary_link && | 2236 | if (bridge && pci_is_pcie(bridge) && bridge->has_secondary_link) |
2232 | !pci_has_flag(PCI_SCAN_ALL_PCIE_DEVS)) | ||
2233 | return 1; | 2237 | return 1; |
2238 | |||
2234 | return 0; | 2239 | return 0; |
2235 | } | 2240 | } |
2236 | 2241 | ||