diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index b706cb3ad99..360260d1352 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c @@ -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); diff --git a/arch/powerpc/platforms/powermac/pmac.h b/arch/powerpc/platforms/powermac/pmac.h index 20468f49aec..8327cce2bdb 100644 --- a/arch/powerpc/platforms/powermac/pmac.h +++ b/arch/powerpc/platforms/powermac/pmac.h @@ -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); diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index 67b6e1432be..db092d7c4c5 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c @@ -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", };