powerpc/psurge: Create a irq_host for secondary cpus

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>
This commit is contained in:
Milton Miller 2011-05-10 19:30:22 +00:00 committed by Benjamin Herrenschmidt
parent 67347eba15
commit 23f73a5fb0
3 changed files with 46 additions and 13 deletions

View 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);

View 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);

View 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",
};