@@ -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);
+}
@@ -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);
@@ -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);
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@gmail.com> CC: Sam Bobroff <sbobroff@linux.ibm.com> Signed-off-by: Sergey Miroshnichenko <s.miroshnichenko@yadro.com> --- arch/powerpc/kernel/pci-hotplug.c | 43 +++++++++++++++++++++++++++++++ drivers/pci/probe.c | 10 +++++++ include/linux/pci.h | 3 +++ 3 files changed, 56 insertions(+)