Merge branch 'urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/rric/oprofile...
[pandora-kernel.git] / arch / powerpc / platforms / powermac / smp.c
index a340107..db092d7 100644 (file)
@@ -70,7 +70,7 @@ static void (*pmac_tb_freeze)(int freeze);
 static u64 timebase;
 static int tb_req;
 
-#ifdef CONFIG_PPC32
+#ifdef CONFIG_PPC_PMAC32_PSURGE
 
 /*
  * Powersurge (old powermac SMP) support.
@@ -124,6 +124,10 @@ static volatile u32 __iomem *psurge_start;
 /* what sort of powersurge board we have */
 static int psurge_type = PSURGE_NONE;
 
+/* irq for secondary cpus to report */
+static struct irq_host *psurge_host;
+int psurge_secondary_virq;
+
 /*
  * Set and clear IPIs for powersurge.
  */
@@ -159,15 +163,11 @@ static inline void psurge_clr_ipi(int cpu)
  * use the generic demux helpers
  *  -- paulus.
  */
-void psurge_smp_message_recv(void)
+static irqreturn_t psurge_ipi_intr(int irq, void *d)
 {
        psurge_clr_ipi(smp_processor_id());
        smp_ipi_demux();
-}
 
-irqreturn_t psurge_primary_intr(int irq, void *d)
-{
-       psurge_smp_message_recv();
        return IRQ_HANDLED;
 }
 
@@ -176,6 +176,38 @@ static void smp_psurge_cause_ipi(int cpu, unsigned long data)
        psurge_set_ipi(cpu);
 }
 
+static int psurge_host_map(struct irq_host *h, unsigned int virq,
+                        irq_hw_number_t hw)
+{
+       irq_set_chip_and_handler(virq, &dummy_irq_chip, handle_percpu_irq);
+
+       return 0;
+}
+
+struct irq_host_ops psurge_host_ops = {
+       .map    = psurge_host_map,
+};
+
+static int psurge_secondary_ipi_init(void)
+{
+       int rc = -ENOMEM;
+
+       psurge_host = irq_alloc_host(NULL, IRQ_HOST_MAP_NOMAP, 0,
+               &psurge_host_ops, 0);
+
+       if (psurge_host)
+               psurge_secondary_virq = irq_create_direct_mapping(psurge_host);
+
+       if (psurge_secondary_virq)
+               rc = request_irq(psurge_secondary_virq, psurge_ipi_intr,
+                       IRQF_DISABLED|IRQF_PERCPU, "IPI", NULL);
+
+       if (rc)
+               pr_err("Failed to setup secondary cpu IPI\n");
+
+       return rc;
+}
+
 /*
  * Determine a quad card presence. We read the board ID register, we
  * force the data bus to change to something else, and we read it again.
@@ -284,6 +316,9 @@ static int __init smp_psurge_probe(void)
                ncpus = 2;
        }
 
+       if (psurge_secondary_ipi_init())
+               return 1;
+
        psurge_start = ioremap(PSURGE_START, 4);
        psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4);
 
@@ -372,8 +407,8 @@ static int __init smp_psurge_kick_cpu(int nr)
 }
 
 static struct irqaction psurge_irqaction = {
-       .handler = psurge_primary_intr,
-       .flags = IRQF_DISABLED,
+       .handler = psurge_ipi_intr,
+       .flags = IRQF_DISABLED|IRQF_PERCPU,
        .name = "primary IPI",
 };
 
@@ -420,7 +455,7 @@ struct smp_ops_t psurge_smp_ops = {
        .give_timebase  = smp_psurge_give_timebase,
        .take_timebase  = smp_psurge_take_timebase,
 };
-#endif /* CONFIG_PPC32 - actually powersurge support */
+#endif /* CONFIG_PPC_PMAC32_PSURGE */
 
 /*
  * Core 99 and later support
@@ -980,7 +1015,7 @@ void __init pmac_setup_smp(void)
                of_node_put(np);
                smp_ops = &core99_smp_ops;
        }
-#ifdef CONFIG_PPC32
+#ifdef CONFIG_PPC_PMAC32_PSURGE
        else {
                /* We have to set bits in cpu_possible_mask here since the
                 * secondary CPU(s) aren't in the device tree. Various
@@ -993,7 +1028,7 @@ void __init pmac_setup_smp(void)
                        set_cpu_possible(cpu, true);
                smp_ops = &psurge_smp_ops;
        }
-#endif /* CONFIG_PPC32 */
+#endif /* CONFIG_PPC_PMAC32_PSURGE */
 
 #ifdef CONFIG_HOTPLUG_CPU
        ppc_md.cpu_die = pmac_cpu_die;