summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/eeh.h8
-rw-r--r--arch/powerpc/include/asm/pci.h5
-rw-r--r--arch/powerpc/kernel/pci-common.c54
-rw-r--r--arch/powerpc/kernel/pci_64.c27
4 files changed, 58 insertions, 36 deletions
diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index b886bec67016..66ea9b8b95c5 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -17,8 +17,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _PPC64_EEH_H
-#define _PPC64_EEH_H
+#ifndef _POWERPC_EEH_H
+#define _POWERPC_EEH_H
#ifdef __KERNEL__
#include <linux/init.h>
@@ -110,6 +110,7 @@ static inline void eeh_remove_bus_device(struct pci_dev *dev) { }
#define EEH_IO_ERROR_VALUE(size) (-1UL)
#endif /* CONFIG_EEH */
+#ifdef CONFIG_PPC64
/*
* MMIO read/write operations with EEH support.
*/
@@ -207,5 +208,6 @@ static inline void eeh_readsl(const volatile void __iomem *addr, void * buf,
eeh_check_failure(addr, *(u32*)buf);
}
+#endif /* CONFIG_PPC64 */
#endif /* __KERNEL__ */
-#endif /* _PPC64_EEH_H */
+#endif /* _POWERPC_EEH_H */
diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h
index 55542ac3eadb..32e03e6d25c5 100644
--- a/arch/powerpc/include/asm/pci.h
+++ b/arch/powerpc/include/asm/pci.h
@@ -221,6 +221,7 @@ extern void of_scan_pci_bridge(struct device_node *node,
struct pci_dev *dev);
extern void of_scan_bus(struct device_node *node, struct pci_bus *bus);
+extern void of_rescan_bus(struct device_node *node, struct pci_bus *bus);
extern int pci_read_irq_line(struct pci_dev *dev);
@@ -235,8 +236,8 @@ extern void pci_resource_to_user(const struct pci_dev *dev, int bar,
const struct resource *rsrc,
resource_size_t *start, resource_size_t *end);
-extern void pcibios_fixup_of_probed_bus(struct pci_bus *bus);
-
+extern void pcibios_setup_bus_devices(struct pci_bus *bus);
+extern void pcibios_setup_bus_self(struct pci_bus *bus);
#endif /* __KERNEL__ */
#endif /* __ASM_POWERPC_PCI_H */
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 780db386c1f0..0eaabd41474f 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -37,6 +37,7 @@
#include <asm/machdep.h>
#include <asm/ppc-pci.h>
#include <asm/firmware.h>
+#include <asm/eeh.h>
static DEFINE_SPINLOCK(hose_spinlock);
@@ -1074,31 +1075,17 @@ static void __devinit pcibios_fixup_bridge(struct pci_bus *bus)
}
}
-static void __devinit __pcibios_fixup_bus(struct pci_bus *bus)
+void __devinit pcibios_setup_bus_devices(struct pci_bus *bus)
{
struct pci_dev *dev;
pr_debug("PCI: Fixup bus %d (%s)\n",
bus->number, bus->self ? pci_name(bus->self) : "PHB");
- /* Fixup PCI<->PCI bridges. Host bridges are handled separately, for
- * now differently between 32 and 64 bits.
- */
- if (bus->self != NULL)
- pcibios_fixup_bridge(bus);
-
- /* Setup bus DMA mappings */
- if (ppc_md.pci_dma_bus_setup)
- ppc_md.pci_dma_bus_setup(bus);
-
/* Setup DMA for all PCI devices on that bus */
list_for_each_entry(dev, &bus->devices, bus_list)
pcibios_setup_new_device(dev);
- /* Platform specific bus fixups */
- if (ppc_md.pcibios_fixup_bus)
- ppc_md.pcibios_fixup_bus(bus);
-
/* Read default IRQs and fixup if necessary */
list_for_each_entry(dev, &bus->devices, bus_list) {
pci_read_irq_line(dev);
@@ -1107,25 +1094,39 @@ static void __devinit __pcibios_fixup_bus(struct pci_bus *bus)
}
}
+void __devinit pcibios_setup_bus_self(struct pci_bus *bus)
+{
+ /* Fix up the bus resources */
+ if (bus->self != NULL)
+ pcibios_fixup_bridge(bus);
+
+ /* Platform specific bus fixups. This is currently only used
+ * by fsl_pci and I'm hoping getting rid of it at some point
+ */
+ if (ppc_md.pcibios_fixup_bus)
+ ppc_md.pcibios_fixup_bus(bus);
+
+ /* Setup bus DMA mappings */
+ if (ppc_md.pci_dma_bus_setup)
+ ppc_md.pci_dma_bus_setup(bus);
+}
+
void __devinit pcibios_fixup_bus(struct pci_bus *bus)
{
/* When called from the generic PCI probe, read PCI<->PCI bridge
- * bases before proceeding
+ * bases. This isn't called when generating the PCI tree from
+ * the OF device-tree.
*/
if (bus->self != NULL)
pci_read_bridge_bases(bus);
- __pcibios_fixup_bus(bus);
-}
-EXPORT_SYMBOL(pcibios_fixup_bus);
-/* When building a bus from the OF tree rather than probing, we need a
- * slightly different version of the fixup which doesn't read the
- * bridge bases using config space accesses
- */
-void __devinit pcibios_fixup_of_probed_bus(struct pci_bus *bus)
-{
- __pcibios_fixup_bus(bus);
+ /* Now fixup the bus bus */
+ pcibios_setup_bus_self(bus);
+
+ /* Now fixup devices on that bus */
+ pcibios_setup_bus_devices(bus);
}
+EXPORT_SYMBOL(pcibios_fixup_bus);
static int skip_isa_ioresource_align(struct pci_dev *dev)
{
@@ -1392,6 +1393,7 @@ void __init pcibios_resource_survey(void)
}
#ifdef CONFIG_HOTPLUG
+
/* This is used by the pSeries hotplug driver to allocate resource
* of newly plugged busses. We can try to consolidate with the
* rest of the code later, for now, keep it as-is
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index e6e8813c364a..39fadc6e1492 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -189,8 +189,8 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
}
EXPORT_SYMBOL(of_create_pci_dev);
-void __devinit of_scan_bus(struct device_node *node,
- struct pci_bus *bus)
+static void __devinit __of_scan_bus(struct device_node *node,
+ struct pci_bus *bus, int rescan_existing)
{
struct device_node *child;
const u32 *reg;
@@ -215,8 +215,12 @@ void __devinit of_scan_bus(struct device_node *node,
pr_debug(" dev header type: %x\n", dev->hdr_type);
}
- /* Ally all fixups */
- pcibios_fixup_of_probed_bus(bus);
+ /* Apply all fixups necessary. We don't fixup the bus "self"
+ * for an existing bridge that is being rescanned
+ */
+ if (!rescan_existing)
+ pcibios_setup_bus_self(bus);
+ pcibios_setup_bus_devices(bus);
/* Now scan child busses */
list_for_each_entry(dev, &bus->devices, bus_list) {
@@ -228,7 +232,20 @@ void __devinit of_scan_bus(struct device_node *node,
}
}
}
-EXPORT_SYMBOL(of_scan_bus);
+
+void __devinit of_scan_bus(struct device_node *node,
+ struct pci_bus *bus)
+{
+ __of_scan_bus(node, bus, 0);
+}
+EXPORT_SYMBOL_GPL(of_scan_bus);
+
+void __devinit of_rescan_bus(struct device_node *node,
+ struct pci_bus *bus)
+{
+ __of_scan_bus(node, bus, 1);
+}
+EXPORT_SYMBOL_GPL(of_rescan_bus);
void __devinit of_scan_pci_bridge(struct device_node *node,
struct pci_dev *dev)