]> Pileus Git - ~andy/linux/blobdiff - arch/powerpc/platforms/pseries/setup.c
powerpc: Enable relocation on during exceptions at boot
[~andy/linux] / arch / powerpc / platforms / pseries / setup.c
index e3cb7ae616587c4fa6239683e409fc38fce9328d..5d97553e5c226b92bcceb2de31020116c7f713be 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/cpuidle.h>
+#include <linux/of.h>
 
 #include <asm/mmu.h>
 #include <asm/processor.h>
@@ -63,7 +64,6 @@
 #include <asm/smp.h>
 #include <asm/firmware.h>
 #include <asm/eeh.h>
-#include <asm/pSeries_reconfig.h>
 
 #include "plpar_wrappers.h"
 #include "pseries.h"
@@ -258,7 +258,7 @@ static int pci_dn_reconfig_notifier(struct notifier_block *nb, unsigned long act
        int err = NOTIFY_OK;
 
        switch (action) {
-       case PSERIES_RECONFIG_ADD:
+       case OF_RECONFIG_ATTACH_NODE:
                pci = np->parent->data;
                if (pci) {
                        update_dn_pci_info(np, pci->phb);
@@ -367,6 +367,36 @@ static void pSeries_idle(void)
        }
 }
 
+/*
+ * Enable relocation on during exceptions. This has partition wide scope and
+ * may take a while to complete, if it takes longer than one second we will
+ * just give up rather than wasting any more time on this - if that turns out
+ * to ever be a problem in practice we can move this into a kernel thread to
+ * finish off the process later in boot.
+ */
+static int __init pSeries_enable_reloc_on_exc(void)
+{
+       long rc;
+       unsigned int delay, total_delay = 0;
+
+       while (1) {
+               rc = enable_reloc_on_exceptions();
+               if (!H_IS_LONG_BUSY(rc))
+                       return rc;
+
+               delay = get_longbusy_msecs(rc);
+               total_delay += delay;
+               if (total_delay > 1000) {
+                       pr_warn("Warning: Giving up waiting to enable "
+                               "relocation on exceptions (%u msec)!\n",
+                               total_delay);
+                       return rc;
+               }
+
+               mdelay(delay);
+       }
+}
+
 static void __init pSeries_setup_arch(void)
 {
        panic_timeout = 10;
@@ -389,7 +419,7 @@ static void __init pSeries_setup_arch(void)
        /* Find and initialize PCI host bridges */
        init_pci_config_tokens();
        find_and_init_phbs();
-       pSeries_reconfig_notifier_register(&pci_dn_reconfig_nb);
+       of_reconfig_notifier_register(&pci_dn_reconfig_nb);
 
        pSeries_nvram_init();
 
@@ -402,6 +432,14 @@ static void __init pSeries_setup_arch(void)
                ppc_md.enable_pmcs = pseries_lpar_enable_pmcs;
        else
                ppc_md.enable_pmcs = power4_enable_pmcs;
+
+       if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
+               long rc;
+               if ((rc = pSeries_enable_reloc_on_exc()) != H_SUCCESS) {
+                       pr_warn("Unable to enable relocation on exceptions: "
+                               "%ld\n", rc);
+               }
+       }
 }
 
 static int __init pSeries_init_panel(void)