summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/pseries')
-rw-r--r--arch/powerpc/platforms/pseries/Kconfig9
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c14
-rw-r--r--arch/powerpc/platforms/pseries/eeh_driver.c10
-rw-r--r--arch/powerpc/platforms/pseries/pci_dlpar.c64
-rw-r--r--arch/powerpc/platforms/pseries/setup.c2
-rw-r--r--arch/powerpc/platforms/pseries/smp.c2
6 files changed, 70 insertions, 31 deletions
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
index e3fc3407bb1..a57032cf6f1 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -9,13 +9,6 @@ config PPC_SPLPAR
processors, that is, which share physical processors between
two or more partitions.
-config HMT
- bool "Hardware multithreading"
- depends on SMP && PPC_PSERIES && BROKEN
- help
- This option enables hardware multithreading on RS64 cpus.
- pSeries systems p620 and p660 have such a cpu type.
-
config EEH
bool "PCI Extended Error Handling (EEH)" if EMBEDDED
depends on PPC_PSERIES
@@ -26,7 +19,7 @@ config SCANLOG
depends on RTAS_PROC && PPC_PSERIES
config LPARCFG
- tristate "LPAR Configuration Data"
+ bool "LPAR Configuration Data"
depends on PPC_PSERIES || PPC_ISERIES
help
Provide system capacity information via human readable
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 83578313ee7..2ab9dcdfb41 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -893,6 +893,20 @@ void eeh_add_device_tree_early(struct device_node *dn)
}
EXPORT_SYMBOL_GPL(eeh_add_device_tree_early);
+void eeh_add_device_tree_late(struct pci_bus *bus)
+{
+ struct pci_dev *dev;
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ eeh_add_device_late(dev);
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+ struct pci_bus *subbus = dev->subordinate;
+ if (subbus)
+ eeh_add_device_tree_late(subbus);
+ }
+ }
+}
+
/**
* eeh_add_device_late - perform EEH initialization for the indicated pci device
* @dev: pci device for which to set up EEH
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index 6373372932b..b811d5ff92f 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -37,7 +37,7 @@
static inline const char * pcid_name (struct pci_dev *pdev)
{
- if (pdev->dev.driver)
+ if (pdev && pdev->dev.driver)
return pdev->dev.driver->name;
return "";
}
@@ -333,7 +333,7 @@ void handle_eeh_events (struct eeh_event *event)
rc = eeh_reset_device(frozen_pdn, NULL);
if (rc)
goto hard_fail;
- pci_walk_bus(frozen_bus, eeh_report_reset, 0);
+ pci_walk_bus(frozen_bus, eeh_report_reset, NULL);
}
/* If all devices reported they can proceed, the re-enable PIO */
@@ -342,11 +342,11 @@ void handle_eeh_events (struct eeh_event *event)
rc = eeh_reset_device(frozen_pdn, NULL);
if (rc)
goto hard_fail;
- pci_walk_bus(frozen_bus, eeh_report_reset, 0);
+ pci_walk_bus(frozen_bus, eeh_report_reset, NULL);
}
/* Tell all device drivers that they can resume operations */
- pci_walk_bus(frozen_bus, eeh_report_resume, 0);
+ pci_walk_bus(frozen_bus, eeh_report_resume, NULL);
return;
@@ -367,7 +367,7 @@ hard_fail:
eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */);
/* Notify all devices that they're about to go down. */
- pci_walk_bus(frozen_bus, eeh_report_failure, 0);
+ pci_walk_bus(frozen_bus, eeh_report_failure, NULL);
/* Shut down the device drivers for good. */
pcibios_remove_pci_devices(frozen_bus);
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
index bdaa8aabdaa..44abdeb9ca0 100644
--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -27,6 +27,7 @@
#include <linux/pci.h>
#include <asm/pci-bridge.h>
+#include <asm/ppc-pci.h>
static struct pci_bus *
find_bus_among_children(struct pci_bus *bus,
@@ -106,6 +107,8 @@ pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
}
}
}
+
+ eeh_add_device_tree_late(bus);
}
EXPORT_SYMBOL_GPL(pcibios_fixup_new_pci_devices);
@@ -114,7 +117,6 @@ pcibios_pci_config_bridge(struct pci_dev *dev)
{
u8 sec_busno;
struct pci_bus *child_bus;
- struct pci_dev *child_dev;
/* Get busno of downstream bus */
pci_read_config_byte(dev, PCI_SECONDARY_BUS, &sec_busno);
@@ -129,10 +131,6 @@ pcibios_pci_config_bridge(struct pci_dev *dev)
pci_scan_child_bus(child_bus);
- list_for_each_entry(child_dev, &child_bus->devices, bus_list) {
- eeh_add_device_late(child_dev);
- }
-
/* Fixup new pci devices without touching bus struct */
pcibios_fixup_new_pci_devices(child_bus, 0);
@@ -160,18 +158,52 @@ pcibios_add_pci_devices(struct pci_bus * bus)
eeh_add_device_tree_early(dn);
- /* pci_scan_slot should find all children */
- slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
- num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
- if (num) {
- pcibios_fixup_new_pci_devices(bus, 1);
- pci_bus_add_devices(bus);
- }
+ if (_machine == PLATFORM_PSERIES_LPAR) {
+ /* use ofdt-based probe */
+ of_scan_bus(dn, bus);
+ if (!list_empty(&bus->devices)) {
+ pcibios_fixup_new_pci_devices(bus, 0);
+ pci_bus_add_devices(bus);
+ }
+ } else {
+ /* use legacy probe */
+ slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
+ num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
+ if (num) {
+ pcibios_fixup_new_pci_devices(bus, 1);
+ pci_bus_add_devices(bus);
+ }
- list_for_each_entry(dev, &bus->devices, bus_list) {
- eeh_add_device_late (dev);
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
- pcibios_pci_config_bridge(dev);
+ list_for_each_entry(dev, &bus->devices, bus_list)
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
+ pcibios_pci_config_bridge(dev);
}
}
EXPORT_SYMBOL_GPL(pcibios_add_pci_devices);
+
+struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
+{
+ struct pci_controller *phb;
+ int primary;
+
+ primary = list_empty(&hose_list);
+ phb = pcibios_alloc_controller(dn);
+ if (!phb)
+ return NULL;
+ setup_phb(dn, phb);
+ pci_process_bridge_OF_ranges(phb, dn, 0);
+
+ pci_setup_phb_io_dynamic(phb, primary);
+
+ pci_devs_phb_init_dynamic(phb);
+
+ if (dn->child)
+ eeh_add_device_tree_early(dn);
+
+ scan_phb(phb);
+ pcibios_fixup_new_pci_devices(phb->bus, 0);
+ pci_bus_add_devices(phb->bus);
+
+ return phb;
+}
+EXPORT_SYMBOL_GPL(init_phb_dynamic);
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index da6cebaf72c..9edeca83f43 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -585,7 +585,7 @@ static int pSeries_pci_probe_mode(struct pci_bus *bus)
static void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
{
/* Don't risk a hypervisor call if we're crashing */
- if (!crash_shutdown) {
+ if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) {
unsigned long vpa = __pa(get_lppaca());
if (unregister_vpa(hard_smp_processor_id(), vpa)) {
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
index 8e6b1ed1396..8d710af5075 100644
--- a/arch/powerpc/platforms/pseries/smp.c
+++ b/arch/powerpc/platforms/pseries/smp.c
@@ -292,7 +292,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
if (start_cpu == RTAS_UNKNOWN_SERVICE)
return 1;
- status = rtas_call(start_cpu, 3, 1, NULL, pcpu, start_here, lcpu);
+ status = rtas_call(start_cpu, 3, 1, NULL, pcpu, start_here, pcpu);
if (status != 0) {
printk(KERN_ERR "start-cpu failed: %i\n", status);
return 0;