OSDN Git Service

Merge branch 'x86/x2apic' into x86/core
[linux-kernel-docs/linux-2.6.git] / arch / powerpc / platforms / pseries / setup.c
index 65e8795..063a0d2 100644 (file)
@@ -16,8 +16,6 @@
  * bootup setup stuff..
  */
 
-#undef DEBUG
-
 #include <linux/cpu.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
@@ -111,7 +109,7 @@ static void __init fwnmi_init(void)
                fwnmi_active = 1;
 }
 
-void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc)
+static void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc)
 {
        unsigned int cascade_irq = i8259_irq();
        if (cascade_irq != NO_IRQ)
@@ -316,6 +314,76 @@ static int pseries_set_xdabr(unsigned long dabr)
                        H_DABRX_KERNEL | H_DABRX_USER);
 }
 
+#define CMO_CHARACTERISTICS_TOKEN 44
+#define CMO_MAXLENGTH 1026
+
+/**
+ * fw_cmo_feature_init - FW_FEATURE_CMO is not stored in ibm,hypertas-functions,
+ * handle that here. (Stolen from parse_system_parameter_string)
+ */
+void pSeries_cmo_feature_init(void)
+{
+       char *ptr, *key, *value, *end;
+       int call_status;
+       int PrPSP = -1;
+       int SecPSP = -1;
+
+       pr_debug(" -> fw_cmo_feature_init()\n");
+       spin_lock(&rtas_data_buf_lock);
+       memset(rtas_data_buf, 0, RTAS_DATA_BUF_SIZE);
+       call_status = rtas_call(rtas_token("ibm,get-system-parameter"), 3, 1,
+                               NULL,
+                               CMO_CHARACTERISTICS_TOKEN,
+                               __pa(rtas_data_buf),
+                               RTAS_DATA_BUF_SIZE);
+
+       if (call_status != 0) {
+               spin_unlock(&rtas_data_buf_lock);
+               pr_debug("CMO not available\n");
+               pr_debug(" <- fw_cmo_feature_init()\n");
+               return;
+       }
+
+       end = rtas_data_buf + CMO_MAXLENGTH - 2;
+       ptr = rtas_data_buf + 2;        /* step over strlen value */
+       key = value = ptr;
+
+       while (*ptr && (ptr <= end)) {
+               /* Separate the key and value by replacing '=' with '\0' and
+                * point the value at the string after the '='
+                */
+               if (ptr[0] == '=') {
+                       ptr[0] = '\0';
+                       value = ptr + 1;
+               } else if (ptr[0] == '\0' || ptr[0] == ',') {
+                       /* Terminate the string containing the key/value pair */
+                       ptr[0] = '\0';
+
+                       if (key == value) {
+                               pr_debug("Malformed key/value pair\n");
+                               /* Never found a '=', end processing */
+                               break;
+                       }
+
+                       if (0 == strcmp(key, "PrPSP"))
+                               PrPSP = simple_strtol(value, NULL, 10);
+                       else if (0 == strcmp(key, "SecPSP"))
+                               SecPSP = simple_strtol(value, NULL, 10);
+                       value = key = ptr + 1;
+               }
+               ptr++;
+       }
+
+       if (PrPSP != -1 || SecPSP != -1) {
+               pr_info("CMO enabled\n");
+               pr_debug("CMO enabled, PrPSP=%d, SecPSP=%d\n", PrPSP, SecPSP);
+               powerpc_firmware_features |= FW_FEATURE_CMO;
+       } else
+               pr_debug("CMO not enabled, PrPSP=%d, SecPSP=%d\n", PrPSP, SecPSP);
+       spin_unlock(&rtas_data_buf_lock);
+       pr_debug(" <- fw_cmo_feature_init()\n");
+}
+
 /*
  * Early initialization.  Relocation is on but do not reference unbolted pages
  */
@@ -331,6 +399,7 @@ static void __init pSeries_init_early(void)
        else if (firmware_has_feature(FW_FEATURE_XDABR))
                ppc_md.set_dabr = pseries_set_xdabr;
 
+       pSeries_cmo_feature_init();
        iommu_init_early_pSeries();
 
        pr_debug(" <- pSeries_init_early()\n");
@@ -484,7 +553,7 @@ static int pSeries_pci_probe_mode(struct pci_bus *bus)
  * possible with power button press. If ibm,power-off-ups token is used
  * it will allow auto poweron after power is restored.
  */
-void pSeries_power_off(void)
+static void pSeries_power_off(void)
 {
        int rc;
        int rtas_poweroff_ups_token = rtas_token("ibm,power-off-ups");