powerpc/psurge: Create a irq_host for secondary cpus
authorMilton Miller <miltonm@bga.com>
Tue, 10 May 2011 19:30:22 +0000 (19:30 +0000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Thu, 19 May 2011 05:31:51 +0000 (15:31 +1000)
Create a dummy irq_host using the generic dummy irq chip for the secondary
cpus to use.  Create a direct irq mapping for the ipi and register the
ipi action handler against it.  If for some unlikely reason part of this
fails then don't detect the secondary cpus.

This removes another instance of NO_IRQ_IGNORE, records the ipi stats
for the secondary cpus, and runs the ipi on the interrupt stack.

Signed-off-by: Milton Miller <miltonm@bga.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/platforms/powermac/pic.c
arch/powerpc/platforms/powermac/pmac.h
arch/powerpc/platforms/powermac/smp.c

index b706cb3ad99c91ae7bbcfe91a123be5a20f3d158..360260d1352d9144331a01e4c364dfcf12143f1b 100644 (file)
@@ -240,12 +240,9 @@ static unsigned int pmac_pic_get_irq(void)
        unsigned long flags;
 
 #ifdef CONFIG_PPC_PMAC32_PSURGE
-       void psurge_smp_message_recv(void);
-
-               /* IPI's are a hack on the powersurge -- Cort */
-               if ( smp_processor_id() != 0 ) {
-               psurge_smp_message_recv();
-               return NO_IRQ_IGNORE;   /* ignore, already handled */
+       /* IPI's are a hack on the powersurge -- Cort */
+       if (smp_processor_id() != 0) {
+               return  psurge_secondary_virq;
         }
 #endif /* CONFIG_PPC_PMAC32_PSURGE */
        raw_spin_lock_irqsave(&pmac_pic_lock, flags);
index 20468f49aec072f40cf448dd92ee6204b1c7eb38..8327cce2bdb01510fe4bbd54fbb805a9041ad7cd 100644 (file)
@@ -33,6 +33,7 @@ extern void pmac_setup_pci_dma(void);
 extern void pmac_check_ht_link(void);
 
 extern void pmac_setup_smp(void);
+extern int psurge_secondary_virq;
 extern void low_cpu_die(void) __attribute__((noreturn));
 
 extern int pmac_nvram_init(void);
index 67b6e1432be2a15c26152079e31b6b2e99b2d380..db092d7c4c5b3ee41062af909af2e3a355bc06b7 100644 (file)
@@ -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",
 };