diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-15 15:01:28 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-15 15:01:28 -0800 |
| commit | 1b6115fbe3b3db746d7baa11399dd617fc75e1c4 (patch) | |
| tree | d84d690504f0872eb8f5a1b18ed251236872fae5 /drivers/pci/probe.c | |
| parent | Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledfo... (diff) | |
| parent | Merge branch 'pci/host-xilinx' into next (diff) | |
| download | linux-1b6115fbe3b3db746d7baa11399dd617fc75e1c4.tar.gz linux-1b6115fbe3b3db746d7baa11399dd617fc75e1c4.zip | |
Merge tag 'pci-v4.15-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI updates from Bjorn Helgaas:
- detach driver before tearing down procfs/sysfs (Alex Williamson)
- disable PCIe services during shutdown (Sinan Kaya)
- fix ASPM oops on systems with no Root Ports (Ard Biesheuvel)
- fix ASPM LTR_L1.2_THRESHOLD programming (Bjorn Helgaas)
- fix ASPM Common_Mode_Restore_Time computation (Bjorn Helgaas)
- fix portdrv MSI/MSI-X vector allocation (Dongdong Liu, Bjorn
Helgaas)
- report non-fatal AER errors only to the affected endpoint (Gabriele
Paoloni)
- distribute bus numbers, MMIO, and I/O space among hotplug bridges to
allow more devices to be hot-added (Mika Westerberg)
- fix pciehp races during initialization and surprise link down (Mika
Westerberg)
- handle surprise-removed devices in PME handling (Qiang)
- support resizable BARs for large graphics devices (Christian König)
- expose SR-IOV offset, stride, and VF device ID via sysfs (Filippo
Sironi)
- create SR-IOV virtfn/physfn sysfs links before attaching driver
(Stuart Hayes)
- fix SR-IOV "ARI Capable Hierarchy" restore issue (Tony Nguyen)
- enforce Kconfig IOV/REALLOC dependency (Sascha El-Sharkawy)
- avoid slot reset if bridge itself is broken (Jan Glauber)
- clean up pci_reset_function() path (Jan H. Schönherr)
- make pci_map_rom() fail if the option ROM is invalid (Changbin Du)
- convert timers to timer_setup() (Kees Cook)
- move PCI_QUIRKS to PCI bus Kconfig menu (Randy Dunlap)
- constify pci_dev_type and intel_mid_pci_ops (Bhumika Goyal)
- remove unnecessary pci_dev, pci_bus, resource, pcibios_set_master()
declarations (Bjorn Helgaas)
- fix endpoint framework overflows and BUG()s (Dan Carpenter)
- fix endpoint framework issues (Kishon Vijay Abraham I)
- avoid broken Cavium CN8xxx bus reset behavior (David Daney)
- extend Cavium ACS capability quirks (Vadim Lomovtsev)
- support Synopsys DesignWare RC in ECAM mode (Ard Biesheuvel)
- turn off dra7xx clocks cleanly on shutdown (Keerthy)
- fix Faraday probe error path (Wei Yongjun)
- support HiSilicon STB SoC PCIe host controller (Jianguo Sun)
- fix Hyper-V interrupt affinity issue (Dexuan Cui)
- remove useless ACPI warning for Hyper-V pass-through devices (Vitaly
Kuznetsov)
- support multiple MSI on iProc (Sandor Bodo-Merle)
- support Layerscape LS1012a and LS1046a PCIe host controllers (Hou
Zhiqiang)
- fix Layerscape default error response (Minghuan Lian)
- support MSI on Tango host controller (Marc Gonzalez)
- support Tegra186 PCIe host controller (Manikanta Maddireddy)
- use generic accessors on Tegra when possible (Thierry Reding)
- support V3 Semiconductor PCI host controller (Linus Walleij)
* tag 'pci-v4.15-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (85 commits)
PCI/ASPM: Add L1 Substates definitions
PCI/ASPM: Reformat ASPM register definitions
PCI/ASPM: Use correct capability pointer to program LTR_L1.2_THRESHOLD
PCI/ASPM: Account for downstream device's Port Common_Mode_Restore_Time
PCI: xgene: Rename xgene_pcie_probe_bridge() to xgene_pcie_probe()
PCI: xilinx: Rename xilinx_pcie_link_is_up() to xilinx_pcie_link_up()
PCI: altera: Rename altera_pcie_link_is_up() to altera_pcie_link_up()
PCI: Fix kernel-doc build warning
PCI: Fail pci_map_rom() if the option ROM is invalid
PCI: Move pci_map_rom() error path
PCI: Move PCI_QUIRKS to the PCI bus menu
alpha/PCI: Make pdev_save_srm_config() static
PCI: Remove unused declarations
PCI: Remove redundant pci_dev, pci_bus, resource declarations
PCI: Remove redundant pcibios_set_master() declarations
PCI/PME: Handle invalid data when reading Root Status
PCI: hv: Use effective affinity mask
PCI: pciehp: Do not clear Presence Detect Changed during initialization
PCI: pciehp: Fix race condition handling surprise link down
PCI: Distribute available resources to hotplug-capable bridges
...
Diffstat (limited to 'drivers/pci/probe.c')
| -rw-r--r-- | drivers/pci/probe.c | 187 |
1 files changed, 173 insertions, 14 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index ff94b69738a8..14e0ea1ff38b 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -959,7 +959,21 @@ static void pci_enable_crs(struct pci_dev *pdev) PCI_EXP_RTCTL_CRSSVE); } +static unsigned int pci_scan_child_bus_extend(struct pci_bus *bus, + unsigned int available_buses); + /* + * pci_scan_bridge_extend() - Scan buses behind a bridge + * @bus: Parent bus the bridge is on + * @dev: Bridge itself + * @max: Starting subordinate number of buses behind this bridge + * @available_buses: Total number of buses available for this bridge and + * the devices below. After the minimal bus space has + * been allocated the remaining buses will be + * distributed equally between hotplug-capable bridges. + * @pass: Either %0 (scan already configured bridges) or %1 (scan bridges + * that need to be reconfigured. + * * If it's a bridge, configure it and scan the bus behind it. * For CardBus bridges, we don't scan behind as the devices will * be handled by the bridge driver itself. @@ -969,7 +983,9 @@ static void pci_enable_crs(struct pci_dev *pdev) * them, we proceed to assigning numbers to the remaining buses in * order to avoid overlaps between old and new bus numbers. */ -int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass) +static int pci_scan_bridge_extend(struct pci_bus *bus, struct pci_dev *dev, + int max, unsigned int available_buses, + int pass) { struct pci_bus *child; int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS); @@ -1076,9 +1092,13 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass) child = pci_add_new_bus(bus, dev, max+1); if (!child) goto out; - pci_bus_insert_busn_res(child, max+1, 0xff); + pci_bus_insert_busn_res(child, max+1, + bus->busn_res.end); } max++; + if (available_buses) + available_buses--; + buses = (buses & 0xff000000) | ((unsigned int)(child->primary) << 0) | ((unsigned int)(child->busn_res.start) << 8) @@ -1100,7 +1120,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass) if (!is_cardbus) { child->bridge_ctl = bctl; - max = pci_scan_child_bus(child); + max = pci_scan_child_bus_extend(child, available_buses); } else { /* * For CardBus bridges, we leave 4 bus numbers @@ -1168,6 +1188,28 @@ out: return max; } + +/* + * pci_scan_bridge() - Scan buses behind a bridge + * @bus: Parent bus the bridge is on + * @dev: Bridge itself + * @max: Starting subordinate number of buses behind this bridge + * @pass: Either %0 (scan already configured bridges) or %1 (scan bridges + * that need to be reconfigured. + * + * If it's a bridge, configure it and scan the bus behind it. + * For CardBus bridges, we don't scan behind as the devices will + * be handled by the bridge driver itself. + * + * We need to process bridges in two passes -- first we scan those + * already configured by the BIOS and after we are done with all of + * them, we proceed to assigning numbers to the remaining buses in + * order to avoid overlaps between old and new bus numbers. + */ +int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass) +{ + return pci_scan_bridge_extend(bus, dev, max, 0, pass); +} EXPORT_SYMBOL(pci_scan_bridge); /* @@ -2396,9 +2438,24 @@ void __weak pcibios_fixup_bus(struct pci_bus *bus) /* nothing to do, expected to be removed in the future */ } -unsigned int pci_scan_child_bus(struct pci_bus *bus) +/** + * pci_scan_child_bus_extend() - Scan devices below a bus + * @bus: Bus to scan for devices + * @available_buses: Total number of buses available (%0 does not try to + * extend beyond the minimal) + * + * Scans devices below @bus including subordinate buses. Returns new + * subordinate number including all the found devices. Passing + * @available_buses causes the remaining bus space to be distributed + * equally between hotplug-capable bridges to allow future extension of the + * hierarchy. + */ +static unsigned int pci_scan_child_bus_extend(struct pci_bus *bus, + unsigned int available_buses) { - unsigned int devfn, pass, max = bus->busn_res.start; + unsigned int used_buses, normal_bridges = 0, hotplug_bridges = 0; + unsigned int start = bus->busn_res.start; + unsigned int devfn, cmax, max = start; struct pci_dev *dev; dev_dbg(&bus->dev, "scanning bus\n"); @@ -2408,7 +2465,8 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus) pci_scan_slot(bus, devfn); /* Reserve buses for SR-IOV capability. */ - max += pci_iov_bus_range(bus); + used_buses = pci_iov_bus_range(bus); + max += used_buses; /* * After performing arch-dependent fixup of the bus, look behind @@ -2420,19 +2478,73 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus) bus->is_added = 1; } - for (pass = 0; pass < 2; pass++) - list_for_each_entry(dev, &bus->devices, bus_list) { - if (pci_is_bridge(dev)) - max = pci_scan_bridge(bus, dev, max, pass); + /* + * Calculate how many hotplug bridges and normal bridges there + * are on this bus. We will distribute the additional available + * buses between hotplug bridges. + */ + for_each_pci_bridge(dev, bus) { + if (dev->is_hotplug_bridge) + hotplug_bridges++; + else + normal_bridges++; + } + + /* + * Scan bridges that are already configured. We don't touch them + * unless they are misconfigured (which will be done in the second + * scan below). + */ + for_each_pci_bridge(dev, bus) { + cmax = max; + max = pci_scan_bridge_extend(bus, dev, max, 0, 0); + used_buses += cmax - max; + } + + /* Scan bridges that need to be reconfigured */ + for_each_pci_bridge(dev, bus) { + unsigned int buses = 0; + + if (!hotplug_bridges && normal_bridges == 1) { + /* + * There is only one bridge on the bus (upstream + * port) so it gets all available buses which it + * can then distribute to the possible hotplug + * bridges below. + */ + buses = available_buses; + } else if (dev->is_hotplug_bridge) { + /* + * Distribute the extra buses between hotplug + * bridges if any. + */ + buses = available_buses / hotplug_bridges; + buses = min(buses, available_buses - used_buses); } + cmax = max; + max = pci_scan_bridge_extend(bus, dev, cmax, buses, 1); + used_buses += max - cmax; + } + /* * Make sure a hotplug bridge has at least the minimum requested - * number of buses. + * number of buses but allow it to grow up to the maximum available + * bus number of there is room. */ - if (bus->self && bus->self->is_hotplug_bridge && pci_hotplug_bus_size) { - if (max - bus->busn_res.start < pci_hotplug_bus_size - 1) - max = bus->busn_res.start + pci_hotplug_bus_size - 1; + if (bus->self && bus->self->is_hotplug_bridge) { + used_buses = max_t(unsigned int, available_buses, + pci_hotplug_bus_size - 1); + if (max - start < used_buses) { + max = start + used_buses; + + /* Do not allocate more buses than we have room left */ + if (max > bus->busn_res.end) + max = bus->busn_res.end; + + dev_dbg(&bus->dev, "%pR extended by %#02x\n", + &bus->busn_res, max - start); + } } /* @@ -2445,6 +2557,18 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus) dev_dbg(&bus->dev, "bus scan returning with max=%02x\n", max); return max; } + +/** + * pci_scan_child_bus() - Scan devices below a bus + * @bus: Bus to scan for devices + * + * Scans devices below @bus including subordinate buses. Returns new + * subordinate number including all the found devices. + */ +unsigned int pci_scan_child_bus(struct pci_bus *bus) +{ + return pci_scan_child_bus_extend(bus, 0); +} EXPORT_SYMBOL_GPL(pci_scan_child_bus); /** @@ -2737,3 +2861,38 @@ void __init pci_sort_breadthfirst(void) { bus_sort_breadthfirst(&pci_bus_type, &pci_sort_bf_cmp); } + +int pci_hp_add_bridge(struct pci_dev *dev) +{ + struct pci_bus *parent = dev->bus; + int busnr, start = parent->busn_res.start; + unsigned int available_buses = 0; + int end = parent->busn_res.end; + + for (busnr = start; busnr <= end; busnr++) { + if (!pci_find_bus(pci_domain_nr(parent), busnr)) + break; + } + if (busnr-- > end) { + dev_err(&dev->dev, "No bus number available for hot-added bridge\n"); + return -1; + } + + /* Scan bridges that are already configured */ + busnr = pci_scan_bridge(parent, dev, busnr, 0); + + /* + * Distribute the available bus numbers between hotplug-capable + * bridges to make extending the chain later possible. + */ + available_buses = end - busnr; + + /* Scan bridges that need to be reconfigured */ + pci_scan_bridge_extend(parent, dev, busnr, available_buses, 1); + + if (!dev->subordinate) + return -1; + + return 0; +} +EXPORT_SYMBOL_GPL(pci_hp_add_bridge); |
