[XFS] Fix merge failures
[pandora-kernel.git] / arch / powerpc / platforms / pseries / xics.c
index c0cb356..f7a6902 100644 (file)
@@ -9,32 +9,30 @@
  *  2 of the License, or (at your option) any later version.
  */
 
-
 #include <linux/types.h>
 #include <linux/threads.h>
 #include <linux/kernel.h>
 #include <linux/irq.h>
 #include <linux/smp.h>
 #include <linux/interrupt.h>
-#include <linux/signal.h>
 #include <linux/init.h>
-#include <linux/gfp.h>
 #include <linux/radix-tree.h>
 #include <linux/cpu.h>
+#include <linux/of.h>
 
 #include <asm/firmware.h>
-#include <asm/prom.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/smp.h>
 #include <asm/rtas.h>
 #include <asm/hvcall.h>
 #include <asm/machdep.h>
-#include <asm/i8259.h>
 
 #include "xics.h"
 #include "plpar_wrappers.h"
 
+static struct irq_host *xics_host;
+
 #define XICS_IPI               2
 #define XICS_IRQ_SPURIOUS      0
 
  */
 #define IPI_PRIORITY           4
 
+static unsigned int default_server = 0xFF;
+static unsigned int default_distrib_server = 0;
+static unsigned int interrupt_server_size = 8;
+
+/* RTAS service tokens */
+static int ibm_get_xive;
+static int ibm_set_xive;
+static int ibm_int_on;
+static int ibm_int_off;
+
+
+/* Direct hardware low level accessors */
+
+/* The part of the interrupt presentation layer that we care about */
 struct xics_ipl {
        union {
                u32 word;
@@ -65,22 +77,6 @@ struct xics_ipl {
 
 static struct xics_ipl __iomem *xics_per_cpu[NR_CPUS];
 
-static unsigned int default_server = 0xFF;
-static unsigned int default_distrib_server = 0;
-static unsigned int interrupt_server_size = 8;
-
-static struct irq_host *xics_host;
-
-/* RTAS service tokens */
-static int ibm_get_xive;
-static int ibm_set_xive;
-static int ibm_int_on;
-static int ibm_int_off;
-
-
-/* Direct HW low level accessors */
-
-
 static inline unsigned int direct_xirr_info_get(void)
 {
        int cpu = smp_processor_id();
@@ -88,7 +84,7 @@ static inline unsigned int direct_xirr_info_get(void)
        return in_be32(&xics_per_cpu[cpu]->xirr.word);
 }
 
-static inline void direct_xirr_info_set(int value)
+static inline void direct_xirr_info_set(unsigned int value)
 {
        int cpu = smp_processor_id();
 
@@ -110,7 +106,6 @@ static inline void direct_qirr_info(int n_cpu, u8 value)
 
 /* LPAR low level accessors */
 
-
 static inline unsigned int lpar_xirr_info_get(void)
 {
        unsigned long lpar_rc;
@@ -122,15 +117,14 @@ static inline unsigned int lpar_xirr_info_get(void)
        return (unsigned int)return_value;
 }
 
-static inline void lpar_xirr_info_set(int value)
+static inline void lpar_xirr_info_set(unsigned int value)
 {
        unsigned long lpar_rc;
-       unsigned long val64 = value & 0xffffffff;
 
-       lpar_rc = plpar_eoi(val64);
+       lpar_rc = plpar_eoi(value);
        if (lpar_rc != H_SUCCESS)
-               panic("bad return code EOI - rc = %ld, value=%lx\n", lpar_rc,
-                     val64);
+               panic("bad return code EOI - rc = %ld, value=%x\n", lpar_rc,
+                     value);
 }
 
 static inline void lpar_cppr_info(u8 value)
@@ -152,59 +146,9 @@ static inline void lpar_qirr_info(int n_cpu , u8 value)
 }
 
 
-/* High level handlers and init code */
-
-static void xics_update_irq_servers(void)
-{
-       int i, j;
-       struct device_node *np;
-       u32 ilen;
-       const u32 *ireg, *isize;
-       u32 hcpuid;
-
-       /* Find the server numbers for the boot cpu. */
-       np = of_get_cpu_node(boot_cpuid, NULL);
-       BUG_ON(!np);
-
-       ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
-       if (!ireg) {
-               of_node_put(np);
-               return;
-       }
-
-       i = ilen / sizeof(int);
-       hcpuid = get_hard_smp_processor_id(boot_cpuid);
-
-       /* Global interrupt distribution server is specified in the last
-        * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last
-        * entry fom this property for current boot cpu id and use it as
-        * default distribution server
-        */
-       for (j = 0; j < i; j += 2) {
-               if (ireg[j] == hcpuid) {
-                       default_server = hcpuid;
-                       default_distrib_server = ireg[j+1];
-
-                       isize = of_get_property(np,
-                                       "ibm,interrupt-server#-size", NULL);
-                       if (isize)
-                               interrupt_server_size = *isize;
-               }
-       }
-
-       of_node_put(np);
-}
+/* Interface to generic irq subsystem */
 
 #ifdef CONFIG_SMP
-/*
- * XICS only has a single IPI, so encode the messages per CPU
- */
-struct xics_ipi_struct {
-        unsigned long value;
-       } ____cacheline_aligned;
-
-static struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
-
 static int get_irq_server(unsigned int virq, unsigned int strict_check)
 {
        int server;
@@ -239,7 +183,6 @@ static int get_irq_server(unsigned int virq, unsigned int strict_check)
 }
 #endif
 
-
 static void xics_unmask_irq(unsigned int virq)
 {
        unsigned int irq;
@@ -258,21 +201,28 @@ static void xics_unmask_irq(unsigned int virq)
        call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server,
                                DEFAULT_PRIORITY);
        if (call_status != 0) {
-               printk(KERN_ERR "xics_enable_irq: irq=%u: ibm_set_xive "
-                      "returned %d\n", irq, call_status);
-               printk("set_xive %x, server %x\n", ibm_set_xive, server);
+               printk(KERN_ERR
+                       "%s: ibm_set_xive irq %u server %x returned %d\n",
+                       __func__, irq, server, call_status);
                return;
        }
 
        /* Now unmask the interrupt (often a no-op) */
        call_status = rtas_call(ibm_int_on, 1, 1, NULL, irq);
        if (call_status != 0) {
-               printk(KERN_ERR "xics_enable_irq: irq=%u: ibm_int_on "
-                      "returned %d\n", irq, call_status);
+               printk(KERN_ERR "%s: ibm_int_on irq=%u returned %d\n",
+                       __func__, irq, call_status);
                return;
        }
 }
 
+static unsigned int xics_startup(unsigned int virq)
+{
+       /* unmask it */
+       xics_unmask_irq(virq);
+       return 0;
+}
+
 static void xics_mask_real_irq(unsigned int irq)
 {
        int call_status;
@@ -282,8 +232,8 @@ static void xics_mask_real_irq(unsigned int irq)
 
        call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq);
        if (call_status != 0) {
-               printk(KERN_ERR "xics_disable_real_irq: irq=%u: "
-                      "ibm_int_off returned %d\n", irq, call_status);
+               printk(KERN_ERR "%s: ibm_int_off irq=%u returned %d\n",
+                       __func__, irq, call_status);
                return;
        }
 
@@ -291,8 +241,8 @@ static void xics_mask_real_irq(unsigned int irq)
        call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq,
                                default_server, 0xff);
        if (call_status != 0) {
-               printk(KERN_ERR "xics_disable_irq: irq=%u: ibm_set_xive(0xff)"
-                      " returned %d\n", irq, call_status);
+               printk(KERN_ERR "%s: ibm_set_xive(0xff) irq=%u returned %d\n",
+                       __func__, irq, call_status);
                return;
        }
 }
@@ -309,28 +259,10 @@ static void xics_mask_irq(unsigned int virq)
        xics_mask_real_irq(irq);
 }
 
-static unsigned int xics_startup(unsigned int virq)
-{
-       /* unmask it */
-       xics_unmask_irq(virq);
-       return 0;
-}
-
-static void xics_eoi_direct(unsigned int virq)
-{
-       unsigned int irq = (unsigned int)irq_map[virq].hwirq;
-
-       iosync();
-       direct_xirr_info_set((0xff << 24) | irq);
-}
-
-
-static void xics_eoi_lpar(unsigned int virq)
+static void xics_mask_unknown_vec(unsigned int vec)
 {
-       unsigned int irq = (unsigned int)irq_map[virq].hwirq;
-
-       iosync();
-       lpar_xirr_info_set((0xff << 24) | irq);
+       printk(KERN_ERR "Interrupt %u (real) is invalid, disabling it.\n", vec);
+       xics_mask_real_irq(vec);
 }
 
 static inline unsigned int xics_xirr_vector(unsigned int xirr)
@@ -342,12 +274,6 @@ static inline unsigned int xics_xirr_vector(unsigned int xirr)
        return xirr & 0x00ffffff;
 }
 
-static void xics_mask_unknown_vec(unsigned int vec)
-{
-       printk(KERN_ERR "Interrupt %u (real) is invalid, disabling it.\n", vec);
-       xics_mask_real_irq(vec);
-}
-
 static unsigned int xics_get_irq_direct(void)
 {
        unsigned int xirr = direct_xirr_info_get();
@@ -390,91 +316,20 @@ static unsigned int xics_get_irq_lpar(void)
        return NO_IRQ;
 }
 
-#ifdef CONFIG_SMP
-static irqreturn_t xics_ipi_dispatch(int cpu)
-{
-       WARN_ON(cpu_is_offline(cpu));
-
-       while (xics_ipi_message[cpu].value) {
-               if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION,
-                                      &xics_ipi_message[cpu].value)) {
-                       mb();
-                       smp_message_recv(PPC_MSG_CALL_FUNCTION);
-               }
-               if (test_and_clear_bit(PPC_MSG_RESCHEDULE,
-                                      &xics_ipi_message[cpu].value)) {
-                       mb();
-                       smp_message_recv(PPC_MSG_RESCHEDULE);
-               }
-               if (test_and_clear_bit(PPC_MSG_CALL_FUNC_SINGLE,
-                                      &xics_ipi_message[cpu].value)) {
-                       mb();
-                       smp_message_recv(PPC_MSG_CALL_FUNC_SINGLE);
-               }
-#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
-               if (test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK,
-                                      &xics_ipi_message[cpu].value)) {
-                       mb();
-                       smp_message_recv(PPC_MSG_DEBUGGER_BREAK);
-               }
-#endif
-       }
-       return IRQ_HANDLED;
-}
-
-static inline void smp_xics_do_message(int cpu, int msg)
-{
-       set_bit(msg, &xics_ipi_message[cpu].value);
-       mb();
-       if (firmware_has_feature(FW_FEATURE_LPAR))
-               lpar_qirr_info(cpu, IPI_PRIORITY);
-       else
-               direct_qirr_info(cpu, IPI_PRIORITY);
-}
-
-void smp_xics_message_pass(int target, int msg)
-{
-       unsigned int i;
-
-       if (target < NR_CPUS) {
-               smp_xics_do_message(target, msg);
-       } else {
-               for_each_online_cpu(i) {
-                       if (target == MSG_ALL_BUT_SELF
-                           && i == smp_processor_id())
-                               continue;
-                       smp_xics_do_message(i, msg);
-               }
-       }
-}
-
-
-static irqreturn_t xics_ipi_action_direct(int irq, void *dev_id)
+static void xics_eoi_direct(unsigned int virq)
 {
-       int cpu = smp_processor_id();
-
-       direct_qirr_info(cpu, 0xff);
+       unsigned int irq = (unsigned int)irq_map[virq].hwirq;
 
-       return xics_ipi_dispatch(cpu);
+       iosync();
+       direct_xirr_info_set((0xff << 24) | irq);
 }
 
-static irqreturn_t xics_ipi_action_lpar(int irq, void *dev_id)
+static void xics_eoi_lpar(unsigned int virq)
 {
-       int cpu = smp_processor_id();
-
-       lpar_qirr_info(cpu, 0xff);
-
-       return xics_ipi_dispatch(cpu);
-}
-#endif /* CONFIG_SMP */
+       unsigned int irq = (unsigned int)irq_map[virq].hwirq;
 
-static void xics_set_cpu_priority(unsigned char cppr)
-{
-       if (firmware_has_feature(FW_FEATURE_LPAR))
-               lpar_cppr_info(cppr);
-       else
-               direct_cppr_info(cppr);
        iosync();
+       lpar_xirr_info_set((0xff << 24) | irq);
 }
 
 static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
@@ -491,8 +346,8 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
        status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
 
        if (status) {
-               printk(KERN_ERR "xics_set_affinity: irq=%u ibm,get-xive "
-                      "returns %d\n", irq, status);
+               printk(KERN_ERR "%s: ibm,get-xive irq=%u returns %d\n",
+                       __func__, irq, status);
                return;
        }
 
@@ -504,8 +359,9 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
        if (irq_server == -1) {
                char cpulist[128];
                cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask);
-               printk(KERN_WARNING "xics_set_affinity: No online cpus in "
-                               "the mask %s for irq %d\n", cpulist, virq);
+               printk(KERN_WARNING
+                       "%s: No online cpus in the mask %s for irq %d\n",
+                       __func__, cpulist, virq);
                return;
        }
 
@@ -513,28 +369,12 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
                                irq, irq_server, xics_status[1]);
 
        if (status) {
-               printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive "
-                      "returns %d\n", irq, status);
+               printk(KERN_ERR "%s: ibm,set-xive irq=%u returns %d\n",
+                       __func__, irq, status);
                return;
        }
 }
 
-void xics_setup_cpu(void)
-{
-       xics_set_cpu_priority(0xff);
-
-       /*
-        * Put the calling processor into the GIQ.  This is really only
-        * necessary from a secondary thread as the OF start-cpu interface
-        * performs this function for us on primary threads.
-        *
-        * XXX: undo of teardown on kexec needs this too, as may hotplug
-        */
-       rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
-               (1UL << interrupt_server_size) - 1 - default_distrib_server, 1);
-}
-
-
 static struct irq_chip xics_pic_direct = {
        .typename = " XICS     ",
        .startup = xics_startup,
@@ -544,7 +384,6 @@ static struct irq_chip xics_pic_direct = {
        .set_affinity = xics_set_affinity
 };
 
-
 static struct irq_chip xics_pic_lpar = {
        .typename = " XICS     ",
        .startup = xics_startup,
@@ -554,6 +393,9 @@ static struct irq_chip xics_pic_lpar = {
        .set_affinity = xics_set_affinity
 };
 
+
+/* Interface to arch irq controller subsystem layer */
+
 /* Points to the irq_chip we're actually using */
 static struct irq_chip *xics_irq_chip;
 
@@ -613,10 +455,164 @@ static void __init xics_init_host(void)
        irq_set_default_host(xics_host);
 }
 
+
+/* Inter-processor interrupt support */
+
+#ifdef CONFIG_SMP
+/*
+ * XICS only has a single IPI, so encode the messages per CPU
+ */
+struct xics_ipi_struct {
+        unsigned long value;
+       } ____cacheline_aligned;
+
+static struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
+
+static inline void smp_xics_do_message(int cpu, int msg)
+{
+       set_bit(msg, &xics_ipi_message[cpu].value);
+       mb();
+       if (firmware_has_feature(FW_FEATURE_LPAR))
+               lpar_qirr_info(cpu, IPI_PRIORITY);
+       else
+               direct_qirr_info(cpu, IPI_PRIORITY);
+}
+
+void smp_xics_message_pass(int target, int msg)
+{
+       unsigned int i;
+
+       if (target < NR_CPUS) {
+               smp_xics_do_message(target, msg);
+       } else {
+               for_each_online_cpu(i) {
+                       if (target == MSG_ALL_BUT_SELF
+                           && i == smp_processor_id())
+                               continue;
+                       smp_xics_do_message(i, msg);
+               }
+       }
+}
+
+static irqreturn_t xics_ipi_dispatch(int cpu)
+{
+       WARN_ON(cpu_is_offline(cpu));
+
+       mb();   /* order mmio clearing qirr */
+       while (xics_ipi_message[cpu].value) {
+               if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION,
+                                      &xics_ipi_message[cpu].value)) {
+                       smp_message_recv(PPC_MSG_CALL_FUNCTION);
+               }
+               if (test_and_clear_bit(PPC_MSG_RESCHEDULE,
+                                      &xics_ipi_message[cpu].value)) {
+                       smp_message_recv(PPC_MSG_RESCHEDULE);
+               }
+               if (test_and_clear_bit(PPC_MSG_CALL_FUNC_SINGLE,
+                                      &xics_ipi_message[cpu].value)) {
+                       smp_message_recv(PPC_MSG_CALL_FUNC_SINGLE);
+               }
+#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
+               if (test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK,
+                                      &xics_ipi_message[cpu].value)) {
+                       smp_message_recv(PPC_MSG_DEBUGGER_BREAK);
+               }
+#endif
+       }
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t xics_ipi_action_direct(int irq, void *dev_id)
+{
+       int cpu = smp_processor_id();
+
+       direct_qirr_info(cpu, 0xff);
+
+       return xics_ipi_dispatch(cpu);
+}
+
+static irqreturn_t xics_ipi_action_lpar(int irq, void *dev_id)
+{
+       int cpu = smp_processor_id();
+
+       lpar_qirr_info(cpu, 0xff);
+
+       return xics_ipi_dispatch(cpu);
+}
+
+static void xics_request_ipi(void)
+{
+       unsigned int ipi;
+       int rc;
+
+       ipi = irq_create_mapping(xics_host, XICS_IPI);
+       BUG_ON(ipi == NO_IRQ);
+
+       /*
+        * IPIs are marked IRQF_DISABLED as they must run with irqs
+        * disabled
+        */
+       set_irq_handler(ipi, handle_percpu_irq);
+       if (firmware_has_feature(FW_FEATURE_LPAR))
+               rc = request_irq(ipi, xics_ipi_action_lpar,
+                               IRQF_DISABLED|IRQF_PERCPU, "IPI", NULL);
+       else
+               rc = request_irq(ipi, xics_ipi_action_direct,
+                               IRQF_DISABLED|IRQF_PERCPU, "IPI", NULL);
+       BUG_ON(rc);
+}
+
+int __init smp_xics_probe(void)
+{
+       xics_request_ipi();
+
+       return cpus_weight(cpu_possible_map);
+}
+
+#endif /* CONFIG_SMP */
+
+
+/* Initialization */
+
+static void xics_update_irq_servers(void)
+{
+       int i, j;
+       struct device_node *np;
+       u32 ilen;
+       const u32 *ireg;
+       u32 hcpuid;
+
+       /* Find the server numbers for the boot cpu. */
+       np = of_get_cpu_node(boot_cpuid, NULL);
+       BUG_ON(!np);
+
+       ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
+       if (!ireg) {
+               of_node_put(np);
+               return;
+       }
+
+       i = ilen / sizeof(int);
+       hcpuid = get_hard_smp_processor_id(boot_cpuid);
+
+       /* Global interrupt distribution server is specified in the last
+        * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last
+        * entry fom this property for current boot cpu id and use it as
+        * default distribution server
+        */
+       for (j = 0; j < i; j += 2) {
+               if (ireg[j] == hcpuid) {
+                       default_server = hcpuid;
+                       default_distrib_server = ireg[j+1];
+               }
+       }
+
+       of_node_put(np);
+}
+
 static void __init xics_map_one_cpu(int hw_id, unsigned long addr,
                                     unsigned long size)
 {
-#ifdef CONFIG_SMP
        int i;
 
        /* This may look gross but it's good enough for now, we don't quite
@@ -630,11 +626,6 @@ static void __init xics_map_one_cpu(int hw_id, unsigned long addr,
                        return;
                }
        }
-#else
-       if (hw_id != 0)
-               return;
-       xics_per_cpu[0] = ioremap(addr, size);
-#endif /* CONFIG_SMP */
 }
 
 static void __init xics_init_one_node(struct device_node *np,
@@ -686,6 +677,7 @@ void __init xics_init_IRQ(void)
        struct device_node *np;
        u32 indx = 0;
        int found = 0;
+       const u32 *isize;
 
        ppc64_boot_msg(0x20, "XICS Init");
 
@@ -696,13 +688,35 @@ void __init xics_init_IRQ(void)
 
        for_each_node_by_type(np, "PowerPC-External-Interrupt-Presentation") {
                found = 1;
-               if (firmware_has_feature(FW_FEATURE_LPAR))
+               if (firmware_has_feature(FW_FEATURE_LPAR)) {
+                       of_node_put(np);
                        break;
+                       }
                xics_init_one_node(np, &indx);
        }
        if (found == 0)
                return;
 
+       /* get the bit size of server numbers */
+       found = 0;
+
+       for_each_compatible_node(np, NULL, "ibm,ppc-xics") {
+               isize = of_get_property(np, "ibm,interrupt-server#-size", NULL);
+
+               if (!isize)
+                       continue;
+
+               if (!found) {
+                       interrupt_server_size = *isize;
+                       found = 1;
+               } else if (*isize != interrupt_server_size) {
+                       printk(KERN_WARNING "XICS: "
+                              "mismatched ibm,interrupt-server#-size\n");
+                       interrupt_server_size = max(*isize,
+                                                   interrupt_server_size);
+               }
+       }
+
        xics_update_irq_servers();
        xics_init_host();
 
@@ -716,38 +730,40 @@ void __init xics_init_IRQ(void)
        ppc64_boot_msg(0x21, "XICS Done");
 }
 
+/* Cpu startup, shutdown, and hotplug */
 
-#ifdef CONFIG_SMP
-static void xics_request_ipi(void)
+static void xics_set_cpu_priority(unsigned char cppr)
 {
-       unsigned int ipi;
-       int rc;
-
-       ipi = irq_create_mapping(xics_host, XICS_IPI);
-       BUG_ON(ipi == NO_IRQ);
-
-       /*
-        * IPIs are marked IRQF_DISABLED as they must run with irqs
-        * disabled
-        */
-       set_irq_handler(ipi, handle_percpu_irq);
        if (firmware_has_feature(FW_FEATURE_LPAR))
-               rc = request_irq(ipi, xics_ipi_action_lpar, IRQF_DISABLED,
-                               "IPI", NULL);
+               lpar_cppr_info(cppr);
        else
-               rc = request_irq(ipi, xics_ipi_action_direct, IRQF_DISABLED,
-                               "IPI", NULL);
-       BUG_ON(rc);
+               direct_cppr_info(cppr);
+       iosync();
 }
 
-int __init smp_xics_probe(void)
+/* Have the calling processor join or leave the specified global queue */
+static void xics_set_cpu_giq(unsigned int gserver, unsigned int join)
 {
-       xics_request_ipi();
+       int index;
+       int status;
 
-       return cpus_weight(cpu_possible_map);
+       if (!rtas_indicator_present(GLOBAL_INTERRUPT_QUEUE, NULL))
+               return;
+
+       index = (1UL << interrupt_server_size) - 1 - gserver;
+
+       status = rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE, index, join);
+
+       WARN(status < 0, "set-indicator(%d, %d, %u) returned %d\n",
+            GLOBAL_INTERRUPT_QUEUE, index, join, status);
 }
 
-#endif /* CONFIG_SMP */
+void xics_setup_cpu(void)
+{
+       xics_set_cpu_priority(0xff);
+
+       xics_set_cpu_giq(default_distrib_server, 1);
+}
 
 void xics_teardown_cpu(void)
 {
@@ -755,9 +771,7 @@ void xics_teardown_cpu(void)
 
        xics_set_cpu_priority(0);
 
-       /*
-        * Clear IPI
-        */
+       /* Clear any pending IPI request */
        if (firmware_has_feature(FW_FEATURE_LPAR))
                lpar_qirr_info(cpu, 0xff);
        else
@@ -766,34 +780,28 @@ void xics_teardown_cpu(void)
 
 void xics_kexec_teardown_cpu(int secondary)
 {
-       unsigned int ipi;
-       struct irq_desc *desc;
-
        xics_teardown_cpu();
 
        /*
-        * we need to EOI the IPI
+        * we take the ipi irq but and never return so we
+        * need to EOI the IPI, but want to leave our priority 0
         *
-        * probably need to check all the other interrupts too
+        * should we check all the other interrupts too?
         * should we be flagging idle loop instead?
         * or creating some task to be scheduled?
         */
 
-       ipi = irq_find_mapping(xics_host, XICS_IPI);
-       if (ipi == XICS_IRQ_SPURIOUS)
-               return;
-       desc = get_irq_desc(ipi);
-       if (desc->chip && desc->chip->eoi)
-               desc->chip->eoi(ipi);
+       if (firmware_has_feature(FW_FEATURE_LPAR))
+               lpar_xirr_info_set((0x00 << 24) | XICS_IPI);
+       else
+               direct_xirr_info_set((0x00 << 24) | XICS_IPI);
 
        /*
         * Some machines need to have at least one cpu in the GIQ,
         * so leave the master cpu in the group.
         */
        if (secondary)
-               rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
-                                  (1UL << interrupt_server_size) - 1 -
-                                  default_distrib_server, 0);
+               xics_set_cpu_giq(default_distrib_server, 0);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -801,7 +809,6 @@ void xics_kexec_teardown_cpu(int secondary)
 /* Interrupts are disabled. */
 void xics_migrate_irqs_away(void)
 {
-       int status;
        int cpu = smp_processor_id(), hw_cpu = hard_smp_processor_id();
        unsigned int irq, virq;
 
@@ -812,10 +819,8 @@ void xics_migrate_irqs_away(void)
        /* Reject any interrupt that was queued to us... */
        xics_set_cpu_priority(0);
 
-       /* remove ourselves from the global interrupt queue */
-       status = rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
-               (1UL << interrupt_server_size) - 1 - default_distrib_server, 0);
-       WARN_ON(status < 0);
+       /* Remove ourselves from the global interrupt queue */
+       xics_set_cpu_giq(default_distrib_server, 0);
 
        /* Allow IPIs again... */
        xics_set_cpu_priority(DEFAULT_PRIORITY);
@@ -823,6 +828,7 @@ void xics_migrate_irqs_away(void)
        for_each_irq(virq) {
                struct irq_desc *desc;
                int xics_status[2];
+               int status;
                unsigned long flags;
 
                /* We cant set affinity on ISA interrupts */
@@ -846,9 +852,8 @@ void xics_migrate_irqs_away(void)
 
                status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
                if (status) {
-                       printk(KERN_ERR "migrate_irqs_away: irq=%u "
-                                       "ibm,get-xive returns %d\n",
-                                       virq, status);
+                       printk(KERN_ERR "%s: ibm,get-xive irq=%u returns %d\n",
+                                       __func__, irq, status);
                        goto unlock;
                }