Commit b9027516 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ppc64: irq cleanups

From: Paul Mackerras <paulus@samba.org>

Create and use irq_offset_up/down, get_irq_desc, for_each_irq
parent 23f217fa
...@@ -252,7 +252,7 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -252,7 +252,7 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.setup_arch = chrp_setup_arch; ppc_md.setup_arch = chrp_setup_arch;
ppc_md.get_cpuinfo = chrp_get_cpuinfo; ppc_md.get_cpuinfo = chrp_get_cpuinfo;
if(naca->interrupt_controller == IC_OPEN_PIC) { if (naca->interrupt_controller == IC_OPEN_PIC) {
ppc_md.init_IRQ = pSeries_init_openpic; ppc_md.init_IRQ = pSeries_init_openpic;
ppc_md.get_irq = openpic_get_irq; ppc_md.get_irq = openpic_get_irq;
} else { } else {
......
...@@ -124,8 +124,8 @@ static void i8259_unmask_irq(unsigned int irq_nr) ...@@ -124,8 +124,8 @@ static void i8259_unmask_irq(unsigned int irq_nr)
static void i8259_end_irq(unsigned int irq) static void i8259_end_irq(unsigned int irq)
{ {
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) && if (!(get_irq_desc(irq)->status & (IRQ_DISABLED|IRQ_INPROGRESS)) &&
irq_desc[irq].action) get_irq_desc(irq)->action)
i8259_unmask_irq(irq); i8259_unmask_irq(irq);
} }
......
...@@ -122,8 +122,8 @@ void __init iSeries_activate_IRQs() ...@@ -122,8 +122,8 @@ void __init iSeries_activate_IRQs()
int irq; int irq;
unsigned long flags; unsigned long flags;
for (irq = 0; irq < NR_IRQS; irq++) { for_each_irq (irq) {
irq_desc_t *desc = &irq_desc[irq]; irq_desc_t *desc = get_irq_desc(irq);
if (desc && desc->handler && desc->handler->startup) { if (desc && desc->handler && desc->handler->startup) {
spin_lock_irqsave(&desc->lock, flags); spin_lock_irqsave(&desc->lock, flags);
......
...@@ -19,8 +19,6 @@ ...@@ -19,8 +19,6 @@
#ifndef __ISERIES_SETUP_H__ #ifndef __ISERIES_SETUP_H__
#define __ISERIES_SETUP_H__ #define __ISERIES_SETUP_H__
#include <linux/irq.h> /* for irq_desc_t */
extern void iSeries_init_early(void); extern void iSeries_init_early(void);
extern void iSeries_init(unsigned long r3, unsigned long ird_start, extern void iSeries_init(unsigned long r3, unsigned long ird_start,
unsigned long ird_end, unsigned long cline_start, unsigned long ird_end, unsigned long cline_start,
...@@ -29,7 +27,6 @@ extern void iSeries_setup_arch(void); ...@@ -29,7 +27,6 @@ extern void iSeries_setup_arch(void);
extern void iSeries_setup_residual(struct seq_file *m, int cpu_id); extern void iSeries_setup_residual(struct seq_file *m, int cpu_id);
extern void iSeries_get_cpuinfo(struct seq_file *m); extern void iSeries_get_cpuinfo(struct seq_file *m);
extern void iSeries_init_IRQ(void); extern void iSeries_init_IRQ(void);
extern void iSeries_init_irq_desc(irq_desc_t *);
extern int iSeries_get_irq(struct pt_regs *regs); extern int iSeries_get_irq(struct pt_regs *regs);
extern void iSeries_restart(char *cmd); extern void iSeries_restart(char *cmd);
extern void iSeries_power_off(void); extern void iSeries_power_off(void);
......
...@@ -67,6 +67,7 @@ irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { ...@@ -67,6 +67,7 @@ irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = {
} }
}; };
int __irq_offset_value;
int ppc_spurious_interrupts = 0; int ppc_spurious_interrupts = 0;
unsigned long lpEvent_count = 0; unsigned long lpEvent_count = 0;
...@@ -76,7 +77,7 @@ setup_irq(unsigned int irq, struct irqaction * new) ...@@ -76,7 +77,7 @@ setup_irq(unsigned int irq, struct irqaction * new)
int shared = 0; int shared = 0;
unsigned long flags; unsigned long flags;
struct irqaction *old, **p; struct irqaction *old, **p;
irq_desc_t *desc = irq_desc + irq; irq_desc_t *desc = get_irq_desc(irq);
/* /*
* Some drivers like serial.c use request_irq() heavily, * Some drivers like serial.c use request_irq() heavily,
...@@ -134,7 +135,7 @@ setup_irq(unsigned int irq, struct irqaction * new) ...@@ -134,7 +135,7 @@ setup_irq(unsigned int irq, struct irqaction * new)
inline void synchronize_irq(unsigned int irq) inline void synchronize_irq(unsigned int irq)
{ {
while (irq_desc[irq].status & IRQ_INPROGRESS) while (get_irq_desc(irq)->status & IRQ_INPROGRESS)
cpu_relax(); cpu_relax();
} }
...@@ -148,11 +149,10 @@ EXPORT_SYMBOL(synchronize_irq); ...@@ -148,11 +149,10 @@ EXPORT_SYMBOL(synchronize_irq);
static int static int
do_free_irq(int irq, void* dev_id) do_free_irq(int irq, void* dev_id)
{ {
irq_desc_t *desc; irq_desc_t *desc = get_irq_desc(irq);
struct irqaction **p; struct irqaction **p;
unsigned long flags; unsigned long flags;
desc = irq_desc + irq;
spin_lock_irqsave(&desc->lock,flags); spin_lock_irqsave(&desc->lock,flags);
p = &desc->action; p = &desc->action;
for (;;) { for (;;) {
...@@ -247,7 +247,7 @@ EXPORT_SYMBOL(free_irq); ...@@ -247,7 +247,7 @@ EXPORT_SYMBOL(free_irq);
inline void disable_irq_nosync(unsigned int irq) inline void disable_irq_nosync(unsigned int irq)
{ {
irq_desc_t *desc = irq_desc + irq; irq_desc_t *desc = get_irq_desc(irq);
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&desc->lock, flags); spin_lock_irqsave(&desc->lock, flags);
...@@ -276,7 +276,7 @@ EXPORT_SYMBOL(disable_irq_nosync); ...@@ -276,7 +276,7 @@ EXPORT_SYMBOL(disable_irq_nosync);
void disable_irq(unsigned int irq) void disable_irq(unsigned int irq)
{ {
irq_desc_t *desc = irq_desc + irq; irq_desc_t *desc = get_irq_desc(irq);
disable_irq_nosync(irq); disable_irq_nosync(irq);
if (desc->action) if (desc->action)
synchronize_irq(irq); synchronize_irq(irq);
...@@ -296,7 +296,7 @@ EXPORT_SYMBOL(disable_irq); ...@@ -296,7 +296,7 @@ EXPORT_SYMBOL(disable_irq);
void enable_irq(unsigned int irq) void enable_irq(unsigned int irq)
{ {
irq_desc_t *desc = irq_desc + irq; irq_desc_t *desc = get_irq_desc(irq);
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&desc->lock, flags); spin_lock_irqsave(&desc->lock, flags);
...@@ -327,6 +327,7 @@ int show_interrupts(struct seq_file *p, void *v) ...@@ -327,6 +327,7 @@ int show_interrupts(struct seq_file *p, void *v)
{ {
int i = *(loff_t *) v, j; int i = *(loff_t *) v, j;
struct irqaction * action; struct irqaction * action;
irq_desc_t *desc;
unsigned long flags; unsigned long flags;
if (i == 0) { if (i == 0) {
...@@ -339,8 +340,9 @@ int show_interrupts(struct seq_file *p, void *v) ...@@ -339,8 +340,9 @@ int show_interrupts(struct seq_file *p, void *v)
} }
if (i < NR_IRQS) { if (i < NR_IRQS) {
spin_lock_irqsave(&irq_desc[i].lock, flags); desc = get_irq_desc(i);
action = irq_desc[i].action; spin_lock_irqsave(&desc->lock, flags);
action = desc->action;
if (!action || !action->handler) if (!action || !action->handler)
goto skip; goto skip;
seq_printf(p, "%3d: ", i); seq_printf(p, "%3d: ", i);
...@@ -352,17 +354,17 @@ int show_interrupts(struct seq_file *p, void *v) ...@@ -352,17 +354,17 @@ int show_interrupts(struct seq_file *p, void *v)
#else #else
seq_printf(p, "%10u ", kstat_irqs(i)); seq_printf(p, "%10u ", kstat_irqs(i));
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
if (irq_desc[i].handler) if (desc->handler)
seq_printf(p, " %s ", irq_desc[i].handler->typename ); seq_printf(p, " %s ", desc->handler->typename );
else else
seq_printf(p, " None "); seq_printf(p, " None ");
seq_printf(p, "%s", (irq_desc[i].status & IRQ_LEVEL) ? "Level " : "Edge "); seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge ");
seq_printf(p, " %s",action->name); seq_printf(p, " %s",action->name);
for (action=action->next; action; action = action->next) for (action=action->next; action; action = action->next)
seq_printf(p, ", %s", action->name); seq_printf(p, ", %s", action->name);
seq_putc(p, '\n'); seq_putc(p, '\n');
skip: skip:
spin_unlock_irqrestore(&irq_desc[i].lock, flags); spin_unlock_irqrestore(&desc->lock, flags);
} else if (i == NR_IRQS) } else if (i == NR_IRQS)
seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts); seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts);
return 0; return 0;
...@@ -482,7 +484,7 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) ...@@ -482,7 +484,7 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
int status; int status;
struct irqaction *action; struct irqaction *action;
int cpu = smp_processor_id(); int cpu = smp_processor_id();
irq_desc_t *desc = irq_desc + irq; irq_desc_t *desc = get_irq_desc(irq);
irqreturn_t action_ret; irqreturn_t action_ret;
kstat_cpu(cpu).irqs[irq]++; kstat_cpu(cpu).irqs[irq]++;
...@@ -564,11 +566,11 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) ...@@ -564,11 +566,11 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
* The ->end() handler has to deal with interrupts which got * The ->end() handler has to deal with interrupts which got
* disabled while the handler was running. * disabled while the handler was running.
*/ */
if (irq_desc[irq].handler) { if (desc->handler) {
if (irq_desc[irq].handler->end) if (desc->handler->end)
irq_desc[irq].handler->end(irq); desc->handler->end(irq);
else if (irq_desc[irq].handler->enable) else if (desc->handler->enable)
irq_desc[irq].handler->enable(irq); desc->handler->enable(irq);
} }
spin_unlock(&desc->lock); spin_unlock(&desc->lock);
} }
...@@ -683,7 +685,7 @@ static struct proc_dir_entry * root_irq_dir; ...@@ -683,7 +685,7 @@ static struct proc_dir_entry * root_irq_dir;
static struct proc_dir_entry * irq_dir [NR_IRQS]; static struct proc_dir_entry * irq_dir [NR_IRQS];
static struct proc_dir_entry * smp_affinity_entry [NR_IRQS]; static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
/* Protected by irq descriptor spinlock */ /* Protected by get_irq_desc(irq)->lock. */
#ifdef CONFIG_IRQ_ALL_CPUS #ifdef CONFIG_IRQ_ALL_CPUS
cpumask_t irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL }; cpumask_t irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL };
#else /* CONFIG_IRQ_ALL_CPUS */ #else /* CONFIG_IRQ_ALL_CPUS */
...@@ -703,12 +705,13 @@ static int irq_affinity_read_proc (char *page, char **start, off_t off, ...@@ -703,12 +705,13 @@ static int irq_affinity_read_proc (char *page, char **start, off_t off,
static int irq_affinity_write_proc (struct file *file, const char *buffer, static int irq_affinity_write_proc (struct file *file, const char *buffer,
unsigned long count, void *data) unsigned long count, void *data)
{ {
int irq = (long)data; unsigned int irq = (long)data;
irq_desc_t *desc = get_irq_desc(irq);
int ret; int ret;
cpumask_t new_value, tmp; cpumask_t new_value, tmp;
cpumask_t allcpus = CPU_MASK_ALL; cpumask_t allcpus = CPU_MASK_ALL;
if (!irq_desc[irq].handler->set_affinity) if (!desc->handler->set_affinity)
return -EIO; return -EIO;
ret = cpumask_parse(buffer, count, new_value); ret = cpumask_parse(buffer, count, new_value);
...@@ -727,7 +730,7 @@ static int irq_affinity_write_proc (struct file *file, const char *buffer, ...@@ -727,7 +730,7 @@ static int irq_affinity_write_proc (struct file *file, const char *buffer,
* Grab lock here so cpu_online_map can't change, and also * Grab lock here so cpu_online_map can't change, and also
* protect irq_affinity[]. * protect irq_affinity[].
*/ */
spin_lock(&irq_desc[irq].lock); spin_lock(&desc->lock);
/* /*
* Do not allow disabling IRQs completely - it's a too easy * Do not allow disabling IRQs completely - it's a too easy
...@@ -741,11 +744,11 @@ static int irq_affinity_write_proc (struct file *file, const char *buffer, ...@@ -741,11 +744,11 @@ static int irq_affinity_write_proc (struct file *file, const char *buffer,
} }
irq_affinity[irq] = new_value; irq_affinity[irq] = new_value;
irq_desc[irq].handler->set_affinity(irq, new_value); desc->handler->set_affinity(irq, new_value);
ret = count; ret = count;
out: out:
spin_unlock(&irq_desc[irq].lock); spin_unlock(&desc->lock);
return ret; return ret;
} }
...@@ -841,8 +844,8 @@ void init_irq_proc (void) ...@@ -841,8 +844,8 @@ void init_irq_proc (void)
/* /*
* Create entries for all existing IRQs. * Create entries for all existing IRQs.
*/ */
for (i = 0; i < NR_IRQS; i++) { for_each_irq(i) {
if (irq_desc[i].handler == NULL) if (get_irq_desc(i)->handler == NULL)
continue; continue;
register_irq_proc(i); register_irq_proc(i);
} }
...@@ -870,7 +873,7 @@ unsigned int virt_irq_to_real_map[NR_IRQS]; ...@@ -870,7 +873,7 @@ unsigned int virt_irq_to_real_map[NR_IRQS];
* we don't end up with an interrupt number >= NR_IRQS. * we don't end up with an interrupt number >= NR_IRQS.
*/ */
#define MIN_VIRT_IRQ 3 #define MIN_VIRT_IRQ 3
#define MAX_VIRT_IRQ (NR_IRQS - NUM_8259_INTERRUPTS - 1) #define MAX_VIRT_IRQ (NR_IRQS - NUM_ISA_INTERRUPTS - 1)
#define NR_VIRT_IRQS (MAX_VIRT_IRQ - MIN_VIRT_IRQ + 1) #define NR_VIRT_IRQS (MAX_VIRT_IRQ - MIN_VIRT_IRQ + 1)
void void
......
...@@ -67,7 +67,6 @@ static void openpic_disable_irq(u_int irq); ...@@ -67,7 +67,6 @@ static void openpic_disable_irq(u_int irq);
static void openpic_initirq(u_int irq, u_int pri, u_int vector, int polarity, static void openpic_initirq(u_int irq, u_int pri, u_int vector, int polarity,
int is_level); int is_level);
static void openpic_mapirq(u_int irq, u_int cpumask); static void openpic_mapirq(u_int irq, u_int cpumask);
static void openpic_set_sense(u_int irq, int sense);
static void find_ISUs(void); static void find_ISUs(void);
...@@ -170,7 +169,7 @@ void __init pSeries_init_openpic(void) ...@@ -170,7 +169,7 @@ void __init pSeries_init_openpic(void)
int i; int i;
unsigned int *addrp; unsigned int *addrp;
unsigned char* chrp_int_ack_special = 0; unsigned char* chrp_int_ack_special = 0;
unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS]; unsigned char init_senses[NR_IRQS - NUM_ISA_INTERRUPTS];
int nmi_irq = -1; int nmi_irq = -1;
#if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD) && defined(XMON) #if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD) && defined(XMON)
struct device_node *kbd; struct device_node *kbd;
...@@ -185,12 +184,12 @@ void __init pSeries_init_openpic(void) ...@@ -185,12 +184,12 @@ void __init pSeries_init_openpic(void)
__ioremap(addrp[prom_n_addr_cells(np)-1], 1, _PAGE_NO_CACHE); __ioremap(addrp[prom_n_addr_cells(np)-1], 1, _PAGE_NO_CACHE);
/* hydra still sets OpenPIC_InitSenses to a static set of values */ /* hydra still sets OpenPIC_InitSenses to a static set of values */
if (OpenPIC_InitSenses == NULL) { if (OpenPIC_InitSenses == NULL) {
prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS); prom_get_irq_senses(init_senses, NUM_ISA_INTERRUPTS, NR_IRQS);
OpenPIC_InitSenses = init_senses; OpenPIC_InitSenses = init_senses;
OpenPIC_NumInitSenses = NR_IRQS - NUM_8259_INTERRUPTS; OpenPIC_NumInitSenses = NR_IRQS - NUM_ISA_INTERRUPTS;
} }
openpic_init(1, NUM_8259_INTERRUPTS, chrp_int_ack_special, nmi_irq); openpic_init(1, NUM_ISA_INTERRUPTS, chrp_int_ack_special, nmi_irq);
for ( i = 0 ; i < NUM_8259_INTERRUPTS ; i++ ) for (i = 0; i < NUM_ISA_INTERRUPTS; i++)
irq_desc[i].handler = &i8259_pic; irq_desc[i].handler = &i8259_pic;
of_node_put(np); of_node_put(np);
} }
...@@ -441,7 +440,7 @@ static int __init openpic_setup_i8259(void) ...@@ -441,7 +440,7 @@ static int __init openpic_setup_i8259(void)
if (naca->interrupt_controller == IC_OPEN_PIC) { if (naca->interrupt_controller == IC_OPEN_PIC) {
/* Initialize the cascade */ /* Initialize the cascade */
if (request_irq(NUM_8259_INTERRUPTS, no_action, SA_INTERRUPT, if (request_irq(NUM_ISA_INTERRUPTS, no_action, SA_INTERRUPT,
"82c59 cascade", NULL)) "82c59 cascade", NULL))
printk(KERN_ERR "Unable to get OpenPIC IRQ 0 for cascade\n"); printk(KERN_ERR "Unable to get OpenPIC IRQ 0 for cascade\n");
i8259_init(); i8259_init();
...@@ -820,13 +819,21 @@ static void openpic_mapirq(u_int irq, u_int physmask) ...@@ -820,13 +819,21 @@ static void openpic_mapirq(u_int irq, u_int physmask)
* *
* sense: 1 for level, 0 for edge * sense: 1 for level, 0 for edge
*/ */
static inline void openpic_set_sense(u_int irq, int sense) #if 0 /* not used */
static void openpic_set_sense(u_int irq, int sense)
{ {
openpic_safe_writefield(&GET_ISU(irq).Vector_Priority, openpic_safe_writefield(&GET_ISU(irq).Vector_Priority,
OPENPIC_SENSE_LEVEL, OPENPIC_SENSE_LEVEL,
(sense ? OPENPIC_SENSE_LEVEL : 0)); (sense ? OPENPIC_SENSE_LEVEL : 0));
} }
static int openpic_get_sense(u_int irq)
{
return openpic_readfield(&GET_ISU(irq).Vector_Priority,
OPENPIC_SENSE_LEVEL) != 0;
}
#endif
static void openpic_end_irq(unsigned int irq_nr) static void openpic_end_irq(unsigned int irq_nr)
{ {
openpic_eoi(); openpic_eoi();
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/cpumask.h> #include <linux/cpumask.h>
#include <linux/irq.h>
#define OPENPIC_SIZE 0x40000 #define OPENPIC_SIZE 0x40000
...@@ -38,11 +39,4 @@ extern void openpic_init_processor(u_int cpumask); ...@@ -38,11 +39,4 @@ extern void openpic_init_processor(u_int cpumask);
extern void openpic_setup_ISU(int isu_num, unsigned long addr); extern void openpic_setup_ISU(int isu_num, unsigned long addr);
extern void openpic_cause_IPI(u_int ipi, u_int cpumask); extern void openpic_cause_IPI(u_int ipi, u_int cpumask);
extern inline int openpic_to_irq(int irq)
{
if (systemcfg->platform == PLATFORM_POWERMAC)
return irq;
return irq += NUM_8259_INTERRUPTS;
}
/*extern int open_pic_irq_offset;*/
#endif /* _PPC64_KERNEL_OPEN_PIC_H */ #endif /* _PPC64_KERNEL_OPEN_PIC_H */
...@@ -2191,7 +2191,7 @@ finish_node_interrupts(struct device_node *np, unsigned long mem_start) ...@@ -2191,7 +2191,7 @@ finish_node_interrupts(struct device_node *np, unsigned long mem_start)
printk(KERN_CRIT "Could not allocate interrupt " printk(KERN_CRIT "Could not allocate interrupt "
"number for %s\n", np->full_name); "number for %s\n", np->full_name);
} else } else
np->intrs[i].line = openpic_to_irq(virq); np->intrs[i].line = irq_offset_up(virq);
/* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */
if (systemcfg->platform == PLATFORM_POWERMAC && ic && ic->parent) { if (systemcfg->platform == PLATFORM_POWERMAC && ic && ic->parent) {
...@@ -3019,7 +3019,7 @@ static int of_finish_dynamic_node_interrupts(struct device_node *node) ...@@ -3019,7 +3019,7 @@ static int of_finish_dynamic_node_interrupts(struct device_node *node)
"number for %s\n", node->full_name); "number for %s\n", node->full_name);
return -ENOMEM; return -ENOMEM;
} }
node->intrs[i].line = openpic_to_irq(virq); node->intrs[i].line = irq_offset_up(virq);
if (n > 1) if (n > 1)
node->intrs[i].sense = irq[1]; node->intrs[i].sense = irq[1];
if (n > 2) { if (n > 2) {
......
/* /*
* ras.c * ras.c
* Copyright (C) 2001 Dave Engebretsen IBM Corporation * Copyright (C) 2001 Dave Engebretsen IBM Corporation
...@@ -80,7 +79,7 @@ static int __init init_ras_IRQ(void) ...@@ -80,7 +79,7 @@ static int __init init_ras_IRQ(void)
"number for %s\n", np->full_name); "number for %s\n", np->full_name);
break; break;
} }
request_irq(virq + NUM_8259_INTERRUPTS, request_irq(irq_offset_up(virq),
ras_error_interrupt, 0, ras_error_interrupt, 0,
"RAS_ERROR", NULL); "RAS_ERROR", NULL);
ireg++; ireg++;
...@@ -98,7 +97,7 @@ static int __init init_ras_IRQ(void) ...@@ -98,7 +97,7 @@ static int __init init_ras_IRQ(void)
" number for %s\n", np->full_name); " number for %s\n", np->full_name);
break; break;
} }
request_irq(virq + NUM_8259_INTERRUPTS, request_irq(irq_offset_up(virq),
ras_epow_interrupt, 0, ras_epow_interrupt, 0,
"RAS_EPOW", NULL); "RAS_EPOW", NULL);
ireg++; ireg++;
......
...@@ -25,8 +25,8 @@ ...@@ -25,8 +25,8 @@
#include <linux/version.h> #include <linux/version.h>
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/root_dev.h> #include <linux/root_dev.h>
#include <linux/cpu.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/cpu.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/processor.h> #include <asm/processor.h>
...@@ -224,6 +224,7 @@ void setup_system(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -224,6 +224,7 @@ void setup_system(unsigned long r3, unsigned long r4, unsigned long r5,
if (systemcfg->platform & PLATFORM_PSERIES) { if (systemcfg->platform & PLATFORM_PSERIES) {
early_console_initialized = 1; early_console_initialized = 1;
register_console(&udbg_console); register_console(&udbg_console);
__irq_offset_value = NUM_ISA_INTERRUPTS;
finish_device_tree(); finish_device_tree();
chrp_init(r3, r4, r5, r6, r7); chrp_init(r3, r4, r5, r6, r7);
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include <asm/ppcdebug.h> #include <asm/ppcdebug.h>
#include <asm/vio.h> #include <asm/vio.h>
#include <asm/hvcall.h> #include <asm/hvcall.h>
#include "open_pic.h"
#define DBGENTER() pr_debug("%s entered\n", __FUNCTION__) #define DBGENTER() pr_debug("%s entered\n", __FUNCTION__)
...@@ -256,7 +255,7 @@ struct vio_dev * __devinit vio_register_device(struct device_node *of_node) ...@@ -256,7 +255,7 @@ struct vio_dev * __devinit vio_register_device(struct device_node *of_node)
printk(KERN_ERR "Unable to allocate interrupt " printk(KERN_ERR "Unable to allocate interrupt "
"number for %s\n", of_node->full_name); "number for %s\n", of_node->full_name);
} else } else
viodev->irq = openpic_to_irq(virq); viodev->irq = irq_offset_up(virq);
} }
/* init generic 'struct device' fields: */ /* init generic 'struct device' fields: */
......
...@@ -59,7 +59,6 @@ struct hw_interrupt_type xics_8259_pic = { ...@@ -59,7 +59,6 @@ struct hw_interrupt_type xics_8259_pic = {
static struct radix_tree_root irq_map = RADIX_TREE_INIT(GFP_KERNEL); static struct radix_tree_root irq_map = RADIX_TREE_INIT(GFP_KERNEL);
#define XICS_IPI 2 #define XICS_IPI 2
#define XICS_IRQ_OFFSET 0x10
#define XICS_IRQ_SPURIOUS 0 #define XICS_IRQ_SPURIOUS 0
/* Want a priority other than 0. Various HW issues require this. */ /* Want a priority other than 0. Various HW issues require this. */
...@@ -217,7 +216,7 @@ xics_ops pSeriesLP_ops = { ...@@ -217,7 +216,7 @@ xics_ops pSeriesLP_ops = {
static unsigned int xics_startup(unsigned int virq) static unsigned int xics_startup(unsigned int virq)
{ {
virq -= XICS_IRQ_OFFSET; virq = irq_offset_down(virq);
if (radix_tree_insert(&irq_map, virt_irq_to_real(virq), if (radix_tree_insert(&irq_map, virt_irq_to_real(virq),
&virt_irq_to_real_map[virq]) == -ENOMEM) &virt_irq_to_real_map[virq]) == -ENOMEM)
printk(KERN_CRIT "Out of memory creating real -> virtual" printk(KERN_CRIT "Out of memory creating real -> virtual"
...@@ -242,8 +241,7 @@ static void xics_enable_irq(unsigned int virq) ...@@ -242,8 +241,7 @@ static void xics_enable_irq(unsigned int virq)
long call_status; long call_status;
unsigned int server; unsigned int server;
virq -= XICS_IRQ_OFFSET; irq = virt_irq_to_real(irq_offset_down(virq));
irq = virt_irq_to_real(virq);
if (irq == XICS_IPI) if (irq == XICS_IPI)
return; return;
...@@ -301,25 +299,25 @@ static void xics_disable_irq(unsigned int virq) ...@@ -301,25 +299,25 @@ static void xics_disable_irq(unsigned int virq)
{ {
unsigned int irq; unsigned int irq;
virq -= XICS_IRQ_OFFSET; irq = virt_irq_to_real(irq_offset_down(virq));
irq = virt_irq_to_real(virq);
xics_disable_real_irq(irq); xics_disable_real_irq(irq);
} }
static void xics_end_irq(unsigned int irq) static void xics_end_irq(unsigned int irq)
{ {
int cpu = smp_processor_id(); int cpu = smp_processor_id();
iosync(); iosync();
ops->xirr_info_set(cpu, ((0xff<<24) | ops->xirr_info_set(cpu, ((0xff << 24) |
(virt_irq_to_real(irq-XICS_IRQ_OFFSET)))); (virt_irq_to_real(irq_offset_down(irq)))));
} }
static void xics_mask_and_ack_irq(unsigned int irq) static void xics_mask_and_ack_irq(unsigned int irq)
{ {
int cpu = smp_processor_id(); int cpu = smp_processor_id();
if (irq < XICS_IRQ_OFFSET) { if (irq < irq_offset_value()) {
i8259_pic.ack(irq); i8259_pic.ack(irq);
iosync(); iosync();
ops->xirr_info_set(cpu, ((0xff<<24) | ops->xirr_info_set(cpu, ((0xff<<24) |
...@@ -345,7 +343,8 @@ int xics_get_irq(struct pt_regs *regs) ...@@ -345,7 +343,8 @@ int xics_get_irq(struct pt_regs *regs)
irq = i8259_irq(cpu); irq = i8259_irq(cpu);
if (irq == -1) { if (irq == -1) {
/* Spurious cascaded interrupt. Still must ack xics */ /* Spurious cascaded interrupt. Still must ack xics */
xics_end_irq(XICS_IRQ_OFFSET + xics_irq_8259_cascade); xics_end_irq(irq_offset_up(xics_irq_8259_cascade));
irq = -1; irq = -1;
} }
} else if (vec == XICS_IRQ_SPURIOUS) { } else if (vec == XICS_IRQ_SPURIOUS) {
...@@ -359,7 +358,7 @@ int xics_get_irq(struct pt_regs *regs) ...@@ -359,7 +358,7 @@ int xics_get_irq(struct pt_regs *regs)
" disabling it.\n", vec); " disabling it.\n", vec);
xics_disable_real_irq(vec); xics_disable_real_irq(vec);
} else } else
irq += XICS_IRQ_OFFSET; irq = irq_offset_up(irq);
} }
return irq; return irq;
} }
...@@ -541,9 +540,9 @@ void xics_init_IRQ(void) ...@@ -541,9 +540,9 @@ void xics_init_IRQ(void)
xics_8259_pic.enable = i8259_pic.enable; xics_8259_pic.enable = i8259_pic.enable;
xics_8259_pic.disable = i8259_pic.disable; xics_8259_pic.disable = i8259_pic.disable;
for (i = 0; i < 16; ++i) for (i = 0; i < 16; ++i)
irq_desc[i].handler = &xics_8259_pic; get_irq_desc(i)->handler = &xics_8259_pic;
for (; i < NR_IRQS; ++i) for (; i < NR_IRQS; ++i)
irq_desc[i].handler = &xics_pic; get_irq_desc(i)->handler = &xics_pic;
ops->cppr_info(boot_cpuid, 0xff); ops->cppr_info(boot_cpuid, 0xff);
iosync(); iosync();
...@@ -559,7 +558,7 @@ static int __init xics_setup_i8259(void) ...@@ -559,7 +558,7 @@ static int __init xics_setup_i8259(void)
{ {
if (naca->interrupt_controller == IC_PPC_XIC && if (naca->interrupt_controller == IC_PPC_XIC &&
xics_irq_8259_cascade != -1) { xics_irq_8259_cascade != -1) {
if (request_irq(xics_irq_8259_cascade + XICS_IRQ_OFFSET, if (request_irq(irq_offset_up(xics_irq_8259_cascade),
no_action, 0, "8259 cascade", 0)) no_action, 0, "8259 cascade", 0))
printk(KERN_ERR "xics_init_IRQ: couldn't get 8259 cascade\n"); printk(KERN_ERR "xics_init_IRQ: couldn't get 8259 cascade\n");
i8259_init(); i8259_init();
...@@ -574,9 +573,9 @@ void xics_request_IPIs(void) ...@@ -574,9 +573,9 @@ void xics_request_IPIs(void)
virt_irq_to_real_map[XICS_IPI] = XICS_IPI; virt_irq_to_real_map[XICS_IPI] = XICS_IPI;
/* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */ /* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */
request_irq(XICS_IPI + XICS_IRQ_OFFSET, xics_ipi_action, SA_INTERRUPT, request_irq(irq_offset_up(XICS_IPI), xics_ipi_action, SA_INTERRUPT,
"IPI", 0); "IPI", 0);
irq_desc[XICS_IPI+XICS_IRQ_OFFSET].status |= IRQ_PER_CPU; get_irq_desc(irq_offset_up(XICS_IPI))->status |= IRQ_PER_CPU;
} }
#endif #endif
...@@ -589,8 +588,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) ...@@ -589,8 +588,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
cpumask_t allcpus = CPU_MASK_ALL; cpumask_t allcpus = CPU_MASK_ALL;
cpumask_t tmp = CPU_MASK_NONE; cpumask_t tmp = CPU_MASK_NONE;
virq -= XICS_IRQ_OFFSET; irq = virt_irq_to_real(irq_offset_down(virq));
irq = virt_irq_to_real(virq);
if (irq == XICS_IPI) if (irq == XICS_IPI)
return; return;
......
...@@ -75,9 +75,24 @@ static inline void __do_save_and_cli(unsigned long *flags) ...@@ -75,9 +75,24 @@ static inline void __do_save_and_cli(unsigned long *flags)
#endif /* CONFIG_PPC_ISERIES */ #endif /* CONFIG_PPC_ISERIES */
#define mask_irq(irq) ({if (irq_desc[irq].handler && irq_desc[irq].handler->disable) irq_desc[irq].handler->disable(irq);}) #define mask_irq(irq) \
#define unmask_irq(irq) ({if (irq_desc[irq].handler && irq_desc[irq].handler->enable) irq_desc[irq].handler->enable(irq);}) ({ \
#define ack_irq(irq) ({if (irq_desc[irq].handler && irq_desc[irq].handler->ack) irq_desc[irq].handler->ack(irq);}) irq_desc_t *desc = get_irq_desc(irq); \
if (desc->handler && desc->handler->disable) \
desc->handler->disable(irq); \
})
#define unmask_irq(irq) \
({ \
irq_desc_t *desc = get_irq_desc(irq); \
if (desc->handler && desc->handler->enable) \
desc->handler->enable(irq); \
})
#define ack_irq(irq) \
({ \
irq_desc_t *desc = get_irq_desc(irq); \
if (desc->handler && desc->handler->ack) \
desc->handler->ack(irq); \
})
/* Should we handle this via lost interrupts and IPIs or should we don't care like /* Should we handle this via lost interrupts and IPIs or should we don't care like
* we do now ? --BenH. * we do now ? --BenH.
......
...@@ -11,6 +11,11 @@ ...@@ -11,6 +11,11 @@
#include <asm/atomic.h> #include <asm/atomic.h>
/*
* Maximum number of interrupt sources that we can handle.
*/
#define NR_IRQS 512
extern void disable_irq(unsigned int); extern void disable_irq(unsigned int);
extern void disable_irq_nosync(unsigned int); extern void disable_irq_nosync(unsigned int);
extern void enable_irq(unsigned int); extern void enable_irq(unsigned int);
...@@ -18,12 +23,11 @@ extern void enable_irq(unsigned int); ...@@ -18,12 +23,11 @@ extern void enable_irq(unsigned int);
/* this number is used when no interrupt has been assigned */ /* this number is used when no interrupt has been assigned */
#define NO_IRQ (-1) #define NO_IRQ (-1)
/* #define get_irq_desc(irq) (&irq_desc[(irq)])
* this is the maximum number of virtual irqs we will use.
*/
#define NR_IRQS 512
#define NUM_8259_INTERRUPTS 16 /* Define a way to iterate across irqs. */
#define for_each_irq(i) \
for ((i) = 0; (i) < NR_IRQS; ++(i))
/* Interrupt numbers are virtual in case they are sparsely /* Interrupt numbers are virtual in case they are sparsely
* distributed by the hardware. * distributed by the hardware.
...@@ -41,12 +45,35 @@ static inline unsigned int virt_irq_to_real(unsigned int virt_irq) ...@@ -41,12 +45,35 @@ static inline unsigned int virt_irq_to_real(unsigned int virt_irq)
return virt_irq_to_real_map[virt_irq]; return virt_irq_to_real_map[virt_irq];
} }
/*
* Because many systems have two overlapping names spaces for
* interrupts (ISA and XICS for example), and the ISA interrupts
* have historically not been easy to renumber, we allow ISA
* interrupts to take values 0 - 15, and shift up the remaining
* interrupts by 0x10.
*/
#define NUM_ISA_INTERRUPTS 0x10
extern int __irq_offset_value;
static inline int irq_offset_up(int irq)
{
return(irq + __irq_offset_value);
}
static inline int irq_offset_down(int irq)
{
return(irq - __irq_offset_value);
}
static inline int irq_offset_value(void)
{
return __irq_offset_value;
}
static __inline__ int irq_canonicalize(int irq) static __inline__ int irq_canonicalize(int irq)
{ {
return irq; return irq;
} }
#define NR_MASK_WORDS ((NR_IRQS + 63) / 64)
#endif /* _ASM_IRQ_H */ #endif /* _ASM_IRQ_H */
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
...@@ -67,6 +67,8 @@ extern cpumask_t cpu_available_map; ...@@ -67,6 +67,8 @@ extern cpumask_t cpu_available_map;
#endif #endif
#define PPC_MSG_DEBUGGER_BREAK 3 #define PPC_MSG_DEBUGGER_BREAK 3
extern cpumask_t irq_affinity[];
void smp_init_iSeries(void); void smp_init_iSeries(void);
void smp_init_pSeries(void); void smp_init_pSeries(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment