[PATCH v6 23/30] powerpc/pci: hotplug: Add support for movable BARs
Sergey Miroshnichenko
s.miroshnichenko at yadro.com
Fri Oct 25 04:12:21 AEDT 2019
Add pcibios_root_bus_rescan_prepare()/_done() hooks for the powerpc, so it
can reassign the PE numbers (which depend on BAR sizes and locations) and
update the EEH address cache during a PCI rescan.
New PE numbers are assigned during pci_setup_bridges(root) after the rescan
is done.
CC: Oliver O'Halloran <oohall at gmail.com>
CC: Sam Bobroff <sbobroff at linux.ibm.com>
Signed-off-by: Sergey Miroshnichenko <s.miroshnichenko at yadro.com>
---
arch/powerpc/kernel/pci-hotplug.c | 43 +++++++++++++++++++++++++++++++
drivers/pci/probe.c | 10 +++++++
include/linux/pci.h | 3 +++
3 files changed, 56 insertions(+)
diff --git a/arch/powerpc/kernel/pci-hotplug.c b/arch/powerpc/kernel/pci-hotplug.c
index fc62c4bc47b1..42847f5b0f08 100644
--- a/arch/powerpc/kernel/pci-hotplug.c
+++ b/arch/powerpc/kernel/pci-hotplug.c
@@ -16,6 +16,7 @@
#include <asm/ppc-pci.h>
#include <asm/firmware.h>
#include <asm/eeh.h>
+#include <asm/iommu.h>
static struct pci_bus *find_bus_among_children(struct pci_bus *bus,
struct device_node *dn)
@@ -151,3 +152,45 @@ void pci_hp_add_devices(struct pci_bus *bus)
pcibios_finish_adding_to_bus(bus);
}
EXPORT_SYMBOL_GPL(pci_hp_add_devices);
+
+static void pci_hp_bus_rescan_prepare(struct pci_bus *bus)
+{
+ struct pci_dev *dev;
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ struct pci_bus *child = dev->subordinate;
+
+ if (child)
+ pci_hp_bus_rescan_prepare(child);
+
+ iommu_del_device(&dev->dev);
+ }
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ pcibios_release_device(dev);
+ }
+}
+
+static void pci_hp_bus_rescan_done(struct pci_bus *bus)
+{
+ struct pci_dev *dev;
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ struct pci_bus *child = dev->subordinate;
+
+ pcibios_bus_add_device(dev);
+
+ if (child)
+ pci_hp_bus_rescan_done(child);
+ }
+}
+
+void pcibios_root_bus_rescan_prepare(struct pci_bus *root)
+{
+ pci_hp_bus_rescan_prepare(root);
+}
+
+void pcibios_root_bus_rescan_done(struct pci_bus *root)
+{
+ pci_hp_bus_rescan_done(root);
+}
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 73452aa81417..539f5d39bb6d 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -3235,6 +3235,14 @@ static void pci_bus_rescan_done(struct pci_bus *bus)
pci_config_pm_runtime_put(bus->self);
}
+void __weak pcibios_root_bus_rescan_prepare(struct pci_bus *root)
+{
+}
+
+void __weak pcibios_root_bus_rescan_done(struct pci_bus *root)
+{
+}
+
static void pci_setup_bridges(struct pci_bus *bus)
{
struct pci_dev *dev;
@@ -3430,6 +3438,7 @@ unsigned int pci_rescan_bus(struct pci_bus *bus)
root = root->parent;
if (pci_can_move_bars) {
+ pcibios_root_bus_rescan_prepare(root);
pci_bus_rescan_prepare(root);
pci_bus_update_immovable_range(root);
pci_bus_release_root_bridge_resources(root);
@@ -3440,6 +3449,7 @@ unsigned int pci_rescan_bus(struct pci_bus *bus)
pci_setup_bridges(root);
pci_bus_rescan_done(root);
+ pcibios_root_bus_rescan_done(root);
} else {
max = pci_scan_child_bus(bus);
pci_assign_unassigned_bus_resources(bus);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index e1edcb3fad31..b5821134bdae 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1275,6 +1275,9 @@ unsigned int pci_rescan_bus(struct pci_bus *bus);
void pci_lock_rescan_remove(void);
void pci_unlock_rescan_remove(void);
+void pcibios_root_bus_rescan_prepare(struct pci_bus *root);
+void pcibios_root_bus_rescan_done(struct pci_bus *root);
+
/* Vital Product Data routines */
ssize_t pci_read_vpd(struct pci_dev *dev, loff_t pos, size_t count, void *buf);
ssize_t pci_write_vpd(struct pci_dev *dev, loff_t pos, size_t count, const void *buf);
--
2.23.0
More information about the Linuxppc-dev
mailing list