aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-07-03 05:32:51 -0400
committerPaul Mackerras <paulus@samba.org>2006-07-03 05:55:12 -0400
commitb9e5b4e6a991a5a6d521f2e20a65835404b4169f (patch)
treea0ac972faae4bf9133f576d842667bb134190341
parent5a43a066b11ac2fe84cf67307f20b83bea390f83 (diff)
[POWERPC] Use the genirq framework
This adapts the generic powerpc interrupt handling code, and all of the platforms except for the embedded 6xx machines, to use the new genirq framework. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r--arch/powerpc/kernel/irq.c30
-rw-r--r--arch/powerpc/kernel/misc_64.S10
-rw-r--r--arch/powerpc/platforms/cell/interrupt.c111
-rw-r--r--arch/powerpc/platforms/cell/interrupt.h4
-rw-r--r--arch/powerpc/platforms/cell/setup.c12
-rw-r--r--arch/powerpc/platforms/cell/spider-pic.c173
-rw-r--r--arch/powerpc/platforms/chrp/setup.c17
-rw-r--r--arch/powerpc/platforms/iseries/irq.c17
-rw-r--r--arch/powerpc/platforms/powermac/pic.c170
-rw-r--r--arch/powerpc/platforms/pseries/setup.c26
-rw-r--r--arch/powerpc/platforms/pseries/xics.c443
-rw-r--r--arch/powerpc/platforms/pseries/xics.h17
-rw-r--r--arch/powerpc/sysdev/i8259.c30
-rw-r--r--arch/powerpc/sysdev/mpic.c193
-rw-r--r--include/asm-powerpc/i8259.h3
-rw-r--r--include/asm-powerpc/irq.h8
-rw-r--r--include/asm-powerpc/mpic.h25
17 files changed, 673 insertions, 616 deletions
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 525baab45d2d..91248559099a 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -62,28 +62,27 @@
62#endif 62#endif
63 63
64int __irq_offset_value; 64int __irq_offset_value;
65#ifdef CONFIG_PPC32
66EXPORT_SYMBOL(__irq_offset_value);
67#endif
68
69static int ppc_spurious_interrupts; 65static int ppc_spurious_interrupts;
70 66
71#ifdef CONFIG_PPC32 67#ifdef CONFIG_PPC32
72#define NR_MASK_WORDS ((NR_IRQS + 31) / 32) 68EXPORT_SYMBOL(__irq_offset_value);
69atomic_t ppc_n_lost_interrupts;
73 70
71#ifndef CONFIG_PPC_MERGE
72#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
74unsigned long ppc_cached_irq_mask[NR_MASK_WORDS]; 73unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
75atomic_t ppc_n_lost_interrupts; 74#endif
76 75
77#ifdef CONFIG_TAU_INT 76#ifdef CONFIG_TAU_INT
78extern int tau_initialized; 77extern int tau_initialized;
79extern int tau_interrupts(int); 78extern int tau_interrupts(int);
80#endif 79#endif
80#endif /* CONFIG_PPC32 */
81 81
82#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_MERGE) 82#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_MERGE)
83extern atomic_t ipi_recv; 83extern atomic_t ipi_recv;
84extern atomic_t ipi_sent; 84extern atomic_t ipi_sent;
85#endif 85#endif
86#endif /* CONFIG_PPC32 */
87 86
88#ifdef CONFIG_PPC64 87#ifdef CONFIG_PPC64
89EXPORT_SYMBOL(irq_desc); 88EXPORT_SYMBOL(irq_desc);
@@ -219,15 +218,19 @@ void do_IRQ(struct pt_regs *regs)
219 curtp = current_thread_info(); 218 curtp = current_thread_info();
220 irqtp = hardirq_ctx[smp_processor_id()]; 219 irqtp = hardirq_ctx[smp_processor_id()];
221 if (curtp != irqtp) { 220 if (curtp != irqtp) {
221 struct irq_desc *desc = irq_desc + irq;
222 void *handler = desc->handle_irq;
223 if (handler == NULL)
224 handler = &__do_IRQ;
222 irqtp->task = curtp->task; 225 irqtp->task = curtp->task;
223 irqtp->flags = 0; 226 irqtp->flags = 0;
224 call___do_IRQ(irq, regs, irqtp); 227 call_handle_irq(irq, desc, regs, irqtp, handler);
225 irqtp->task = NULL; 228 irqtp->task = NULL;
226 if (irqtp->flags) 229 if (irqtp->flags)
227 set_bits(irqtp->flags, &curtp->flags); 230 set_bits(irqtp->flags, &curtp->flags);
228 } else 231 } else
229#endif 232#endif
230 __do_IRQ(irq, regs); 233 generic_handle_irq(irq, regs);
231 } else if (irq != -2) 234 } else if (irq != -2)
232 /* That's not SMP safe ... but who cares ? */ 235 /* That's not SMP safe ... but who cares ? */
233 ppc_spurious_interrupts++; 236 ppc_spurious_interrupts++;
@@ -245,15 +248,6 @@ void do_IRQ(struct pt_regs *regs)
245 248
246void __init init_IRQ(void) 249void __init init_IRQ(void)
247{ 250{
248#ifdef CONFIG_PPC64
249 static int once = 0;
250
251 if (once)
252 return;
253
254 once++;
255
256#endif
257 ppc_md.init_IRQ(); 251 ppc_md.init_IRQ();
258#ifdef CONFIG_PPC64 252#ifdef CONFIG_PPC64
259 irq_ctx_init(); 253 irq_ctx_init();
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index 0c3c70d115c6..bfb407fc1aa1 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -51,12 +51,14 @@ _GLOBAL(call_do_softirq)
51 mtlr r0 51 mtlr r0
52 blr 52 blr
53 53
54_GLOBAL(call___do_IRQ) 54_GLOBAL(call_handle_irq)
55 ld r8,0(r7)
55 mflr r0 56 mflr r0
56 std r0,16(r1) 57 std r0,16(r1)
57 stdu r1,THREAD_SIZE-112(r5) 58 mtctr r8
58 mr r1,r5 59 stdu r1,THREAD_SIZE-112(r6)
59 bl .__do_IRQ 60 mr r1,r6
61 bctrl
60 ld r1,0(r1) 62 ld r1,0(r1)
61 ld r0,16(r1) 63 ld r0,16(r1)
62 mtlr r0 64 mtlr r0
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c
index 22da1335445a..97936f547f19 100644
--- a/arch/powerpc/platforms/cell/interrupt.c
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -37,64 +37,51 @@
37struct iic { 37struct iic {
38 struct cbe_iic_thread_regs __iomem *regs; 38 struct cbe_iic_thread_regs __iomem *regs;
39 u8 target_id; 39 u8 target_id;
40 u8 eoi_stack[16];
41 int eoi_ptr;
40}; 42};
41 43
42static DEFINE_PER_CPU(struct iic, iic); 44static DEFINE_PER_CPU(struct iic, iic);
43 45
44void iic_local_enable(void) 46static void iic_mask(unsigned int irq)
45{ 47{
46 struct iic *iic = &__get_cpu_var(iic);
47 u64 tmp;
48
49 /*
50 * There seems to be a bug that is present in DD2.x CPUs
51 * and still only partially fixed in DD3.1.
52 * This bug causes a value written to the priority register
53 * not to make it there, resulting in a system hang unless we
54 * write it again.
55 * Masking with 0xf0 is done because the Cell BE does not
56 * implement the lower four bits of the interrupt priority,
57 * they always read back as zeroes, although future CPUs
58 * might implement different bits.
59 */
60 do {
61 out_be64(&iic->regs->prio, 0xff);
62 tmp = in_be64(&iic->regs->prio);
63 } while ((tmp & 0xf0) != 0xf0);
64}
65
66void iic_local_disable(void)
67{
68 out_be64(&__get_cpu_var(iic).regs->prio, 0x0);
69}
70
71static unsigned int iic_startup(unsigned int irq)
72{
73 return 0;
74}
75
76static void iic_enable(unsigned int irq)
77{
78 iic_local_enable();
79} 48}
80 49
81static void iic_disable(unsigned int irq) 50static void iic_unmask(unsigned int irq)
82{ 51{
83} 52}
84 53
85static void iic_end(unsigned int irq) 54static void iic_eoi(unsigned int irq)
86{ 55{
87 iic_local_enable(); 56 struct iic *iic = &__get_cpu_var(iic);
57 out_be64(&iic->regs->prio, iic->eoi_stack[--iic->eoi_ptr]);
58 BUG_ON(iic->eoi_ptr < 0);
88} 59}
89 60
90static struct hw_interrupt_type iic_pic = { 61static struct irq_chip iic_chip = {
91 .typename = " CELL-IIC ", 62 .typename = " CELL-IIC ",
92 .startup = iic_startup, 63 .mask = iic_mask,
93 .enable = iic_enable, 64 .unmask = iic_unmask,
94 .disable = iic_disable, 65 .eoi = iic_eoi,
95 .end = iic_end,
96}; 66};
97 67
68/* XXX All of this has to be reworked completely. We need to assign a real
69 * interrupt numbers to the external interrupts and remove all the hard coded
70 * interrupt maps (rely on the device-tree whenever possible).
71 *
72 * Basically, my scheme is to define the "pendings" bits to be the HW interrupt
73 * number (ignoring the data and flags here). That means we can sort-of split
74 * external sources based on priority, and we can use request_irq() on pretty
75 * much anything.
76 *
77 * For spider or axon, they have their own interrupt space. spider will just have
78 * local "hardward" interrupts 0...xx * node stride. The node stride is not
79 * necessary (separate interrupt chips will have separate HW number space), but
80 * will allow to be compatible with existing device-trees.
81 *
82 * All of thise little world will get a standard remapping scheme to map those HW
83 * numbers into the linux flat irq number space.
84*/
98static int iic_external_get_irq(struct cbe_iic_pending_bits pending) 85static int iic_external_get_irq(struct cbe_iic_pending_bits pending)
99{ 86{
100 int irq; 87 int irq;
@@ -118,9 +105,10 @@ static int iic_external_get_irq(struct cbe_iic_pending_bits pending)
118 */ 105 */
119 if (pending.class != 2) 106 if (pending.class != 2)
120 break; 107 break;
121 irq = IIC_EXT_OFFSET 108 /* TODO: We might want to silently ignore cascade interrupts
122 + spider_get_irq(node) 109 * when no cascade handler exist yet
123 + node * IIC_NODE_STRIDE; 110 */
111 irq = IIC_EXT_CASCADE + node * IIC_NODE_STRIDE;
124 break; 112 break;
125 case 0x01 ... 0x04: 113 case 0x01 ... 0x04:
126 case 0x07 ... 0x0a: 114 case 0x07 ... 0x0a:
@@ -152,6 +140,8 @@ int iic_get_irq(struct pt_regs *regs)
152 iic = &__get_cpu_var(iic); 140 iic = &__get_cpu_var(iic);
153 *(unsigned long *) &pending = 141 *(unsigned long *) &pending =
154 in_be64((unsigned long __iomem *) &iic->regs->pending_destr); 142 in_be64((unsigned long __iomem *) &iic->regs->pending_destr);
143 iic->eoi_stack[++iic->eoi_ptr] = pending.prio;
144 BUG_ON(iic->eoi_ptr > 15);
155 145
156 irq = -1; 146 irq = -1;
157 if (pending.flags & CBE_IIC_IRQ_VALID) { 147 if (pending.flags & CBE_IIC_IRQ_VALID) {
@@ -172,7 +162,7 @@ int iic_get_irq(struct pt_regs *regs)
172 162
173/* hardcoded part to be compatible with older firmware */ 163/* hardcoded part to be compatible with older firmware */
174 164
175static int setup_iic_hardcoded(void) 165static int __init setup_iic_hardcoded(void)
176{ 166{
177 struct device_node *np; 167 struct device_node *np;
178 int nodeid, cpu; 168 int nodeid, cpu;
@@ -207,12 +197,13 @@ static int setup_iic_hardcoded(void)
207 printk(KERN_INFO "IIC for CPU %d at %lx\n", cpu, regs); 197 printk(KERN_INFO "IIC for CPU %d at %lx\n", cpu, regs);
208 iic->regs = ioremap(regs, sizeof(struct cbe_iic_thread_regs)); 198 iic->regs = ioremap(regs, sizeof(struct cbe_iic_thread_regs));
209 iic->target_id = (nodeid << 4) + ((cpu & 1) ? 0xf : 0xe); 199 iic->target_id = (nodeid << 4) + ((cpu & 1) ? 0xf : 0xe);
200 iic->eoi_stack[0] = 0xff;
210 } 201 }
211 202
212 return 0; 203 return 0;
213} 204}
214 205
215static int setup_iic(void) 206static int __init setup_iic(void)
216{ 207{
217 struct device_node *dn; 208 struct device_node *dn;
218 unsigned long *regs; 209 unsigned long *regs;
@@ -248,11 +239,14 @@ static int setup_iic(void)
248 iic = &per_cpu(iic, np[0]); 239 iic = &per_cpu(iic, np[0]);
249 iic->regs = ioremap(regs[0], sizeof(struct cbe_iic_thread_regs)); 240 iic->regs = ioremap(regs[0], sizeof(struct cbe_iic_thread_regs));
250 iic->target_id = ((np[0] & 2) << 3) + ((np[0] & 1) ? 0xf : 0xe); 241 iic->target_id = ((np[0] & 2) << 3) + ((np[0] & 1) ? 0xf : 0xe);
242 iic->eoi_stack[0] = 0xff;
251 printk("IIC for CPU %d at %lx mapped to %p\n", np[0], regs[0], iic->regs); 243 printk("IIC for CPU %d at %lx mapped to %p\n", np[0], regs[0], iic->regs);
252 244
253 iic = &per_cpu(iic, np[1]); 245 iic = &per_cpu(iic, np[1]);
254 iic->regs = ioremap(regs[2], sizeof(struct cbe_iic_thread_regs)); 246 iic->regs = ioremap(regs[2], sizeof(struct cbe_iic_thread_regs));
255 iic->target_id = ((np[1] & 2) << 3) + ((np[1] & 1) ? 0xf : 0xe); 247 iic->target_id = ((np[1] & 2) << 3) + ((np[1] & 1) ? 0xf : 0xe);
248 iic->eoi_stack[0] = 0xff;
249
256 printk("IIC for CPU %d at %lx mapped to %p\n", np[1], regs[2], iic->regs); 250 printk("IIC for CPU %d at %lx mapped to %p\n", np[1], regs[2], iic->regs);
257 251
258 found++; 252 found++;
@@ -304,10 +298,10 @@ static void iic_request_ipi(int ipi, const char *name)
304 int irq; 298 int irq;
305 299
306 irq = iic_ipi_to_irq(ipi); 300 irq = iic_ipi_to_irq(ipi);
301
307 /* IPIs are marked IRQF_DISABLED as they must run with irqs 302 /* IPIs are marked IRQF_DISABLED as they must run with irqs
308 * disabled */ 303 * disabled */
309 get_irq_desc(irq)->chip = &iic_pic; 304 set_irq_chip_and_handler(irq, &iic_chip, handle_percpu_irq);
310 get_irq_desc(irq)->status |= IRQ_PER_CPU;
311 request_irq(irq, iic_ipi_action, IRQF_DISABLED, name, NULL); 305 request_irq(irq, iic_ipi_action, IRQF_DISABLED, name, NULL);
312} 306}
313 307
@@ -321,20 +315,26 @@ void iic_request_IPIs(void)
321} 315}
322#endif /* CONFIG_SMP */ 316#endif /* CONFIG_SMP */
323 317
324static void iic_setup_spe_handlers(void) 318static void __init iic_setup_builtin_handlers(void)
325{ 319{
326 int be, isrc; 320 int be, isrc;
327 321
328 /* Assume two threads per BE are present */ 322 /* XXX FIXME: Assume two threads per BE are present */
329 for (be=0; be < num_present_cpus() / 2; be++) { 323 for (be=0; be < num_present_cpus() / 2; be++) {
324 int irq;
325
326 /* setup SPE chip and handlers */
330 for (isrc = 0; isrc < IIC_CLASS_STRIDE * 3; isrc++) { 327 for (isrc = 0; isrc < IIC_CLASS_STRIDE * 3; isrc++) {
331 int irq = IIC_NODE_STRIDE * be + IIC_SPE_OFFSET + isrc; 328 irq = IIC_NODE_STRIDE * be + IIC_SPE_OFFSET + isrc;
332 get_irq_desc(irq)->chip = &iic_pic; 329 set_irq_chip_and_handler(irq, &iic_chip, handle_fasteoi_irq);
333 } 330 }
331 /* setup cascade chip */
332 irq = IIC_EXT_CASCADE + be * IIC_NODE_STRIDE;
333 set_irq_chip_and_handler(irq, &iic_chip, handle_fasteoi_irq);
334 } 334 }
335} 335}
336 336
337void iic_init_IRQ(void) 337void __init iic_init_IRQ(void)
338{ 338{
339 int cpu, irq_offset; 339 int cpu, irq_offset;
340 struct iic *iic; 340 struct iic *iic;
@@ -348,5 +348,6 @@ void iic_init_IRQ(void)
348 if (iic->regs) 348 if (iic->regs)
349 out_be64(&iic->regs->prio, 0xff); 349 out_be64(&iic->regs->prio, 0xff);
350 } 350 }
351 iic_setup_spe_handlers(); 351 iic_setup_builtin_handlers();
352
352} 353}
diff --git a/arch/powerpc/platforms/cell/interrupt.h b/arch/powerpc/platforms/cell/interrupt.h
index 799f77d98f96..c74515aeb630 100644
--- a/arch/powerpc/platforms/cell/interrupt.h
+++ b/arch/powerpc/platforms/cell/interrupt.h
@@ -38,6 +38,7 @@
38 38
39enum { 39enum {
40 IIC_EXT_OFFSET = 0x00, /* Start of south bridge IRQs */ 40 IIC_EXT_OFFSET = 0x00, /* Start of south bridge IRQs */
41 IIC_EXT_CASCADE = 0x20, /* There is no interrupt 32 on spider */
41 IIC_NUM_EXT = 0x40, /* Number of south bridge IRQs */ 42 IIC_NUM_EXT = 0x40, /* Number of south bridge IRQs */
42 IIC_SPE_OFFSET = 0x40, /* Start of SPE interrupts */ 43 IIC_SPE_OFFSET = 0x40, /* Start of SPE interrupts */
43 IIC_CLASS_STRIDE = 0x10, /* SPE IRQs per class */ 44 IIC_CLASS_STRIDE = 0x10, /* SPE IRQs per class */
@@ -51,13 +52,10 @@ extern int iic_get_irq(struct pt_regs *regs);
51extern void iic_cause_IPI(int cpu, int mesg); 52extern void iic_cause_IPI(int cpu, int mesg);
52extern void iic_request_IPIs(void); 53extern void iic_request_IPIs(void);
53extern void iic_setup_cpu(void); 54extern void iic_setup_cpu(void);
54extern void iic_local_enable(void);
55extern void iic_local_disable(void);
56 55
57extern u8 iic_get_target_id(int cpu); 56extern u8 iic_get_target_id(int cpu);
58 57
59extern void spider_init_IRQ(void); 58extern void spider_init_IRQ(void);
60extern int spider_get_irq(int node);
61 59
62#endif 60#endif
63#endif /* ASM_CELL_PIC_H */ 61#endif /* ASM_CELL_PIC_H */
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index 01ec39431fb0..70a4e903f7e2 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -80,10 +80,14 @@ static void cell_progress(char *s, unsigned short hex)
80 printk("*** %04x : %s\n", hex, s ? s : ""); 80 printk("*** %04x : %s\n", hex, s ? s : "");
81} 81}
82 82
83static void __init cell_init_irq(void)
84{
85 iic_init_IRQ();
86 spider_init_IRQ();
87}
88
83static void __init cell_setup_arch(void) 89static void __init cell_setup_arch(void)
84{ 90{
85 ppc_md.init_IRQ = iic_init_IRQ;
86 ppc_md.get_irq = iic_get_irq;
87#ifdef CONFIG_SPU_BASE 91#ifdef CONFIG_SPU_BASE
88 spu_priv1_ops = &spu_priv1_mmio_ops; 92 spu_priv1_ops = &spu_priv1_mmio_ops;
89#endif 93#endif
@@ -109,7 +113,6 @@ static void __init cell_setup_arch(void)
109 /* Find and initialize PCI host bridges */ 113 /* Find and initialize PCI host bridges */
110 init_pci_config_tokens(); 114 init_pci_config_tokens();
111 find_and_init_phbs(); 115 find_and_init_phbs();
112 spider_init_IRQ();
113 cbe_pervasive_init(); 116 cbe_pervasive_init();
114#ifdef CONFIG_DUMMY_CONSOLE 117#ifdef CONFIG_DUMMY_CONSOLE
115 conswitchp = &dummy_con; 118 conswitchp = &dummy_con;
@@ -174,6 +177,9 @@ define_machine(cell) {
174 .calibrate_decr = generic_calibrate_decr, 177 .calibrate_decr = generic_calibrate_decr,
175 .check_legacy_ioport = cell_check_legacy_ioport, 178 .check_legacy_ioport = cell_check_legacy_ioport,
176 .progress = cell_progress, 179 .progress = cell_progress,
180 .init_IRQ = cell_init_irq,
181 .get_irq = iic_get_irq,
182
177#ifdef CONFIG_KEXEC 183#ifdef CONFIG_KEXEC
178 .machine_kexec = default_machine_kexec, 184 .machine_kexec = default_machine_kexec,
179 .machine_kexec_prepare = default_machine_kexec_prepare, 185 .machine_kexec_prepare = default_machine_kexec_prepare,
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index 7c3a0b6d34fd..98425acb6cda 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -82,17 +82,20 @@ static void __iomem *spider_get_irq_config(int irq)
82 return pic + TIR_CFGA + 8 * spider_get_nr(irq); 82 return pic + TIR_CFGA + 8 * spider_get_nr(irq);
83} 83}
84 84
85static void spider_enable_irq(unsigned int irq) 85static void spider_unmask_irq(unsigned int irq)
86{ 86{
87 int nodeid = (irq / IIC_NODE_STRIDE) * 0x10; 87 int nodeid = (irq / IIC_NODE_STRIDE) * 0x10;
88 void __iomem *cfg = spider_get_irq_config(irq); 88 void __iomem *cfg = spider_get_irq_config(irq);
89 irq = spider_get_nr(irq); 89 irq = spider_get_nr(irq);
90 90
91 /* FIXME: Most of that is configuration and has nothing to do with enabling/disable,
92 * besides, it's also partially bogus.
93 */
91 out_be32(cfg, (in_be32(cfg) & ~0xf0)| 0x3107000eu | nodeid); 94 out_be32(cfg, (in_be32(cfg) & ~0xf0)| 0x3107000eu | nodeid);
92 out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq); 95 out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq);
93} 96}
94 97
95static void spider_disable_irq(unsigned int irq) 98static void spider_mask_irq(unsigned int irq)
96{ 99{
97 void __iomem *cfg = spider_get_irq_config(irq); 100 void __iomem *cfg = spider_get_irq_config(irq);
98 irq = spider_get_nr(irq); 101 irq = spider_get_nr(irq);
@@ -100,39 +103,21 @@ static void spider_disable_irq(unsigned int irq)
100 out_be32(cfg, in_be32(cfg) & ~0x30000000u); 103 out_be32(cfg, in_be32(cfg) & ~0x30000000u);
101} 104}
102 105
103static unsigned int spider_startup_irq(unsigned int irq)
104{
105 spider_enable_irq(irq);
106 return 0;
107}
108
109static void spider_shutdown_irq(unsigned int irq)
110{
111 spider_disable_irq(irq);
112}
113
114static void spider_end_irq(unsigned int irq)
115{
116 spider_enable_irq(irq);
117}
118
119static void spider_ack_irq(unsigned int irq) 106static void spider_ack_irq(unsigned int irq)
120{ 107{
121 spider_disable_irq(irq); 108 /* Should reset edge detection logic but we don't configure any edge interrupt
122 iic_local_enable(); 109 * at the moment.
110 */
123} 111}
124 112
125static struct hw_interrupt_type spider_pic = { 113static struct irq_chip spider_pic = {
126 .typename = " SPIDER ", 114 .typename = " SPIDER ",
127 .startup = spider_startup_irq, 115 .unmask = spider_unmask_irq,
128 .shutdown = spider_shutdown_irq, 116 .mask = spider_mask_irq,
129 .enable = spider_enable_irq,
130 .disable = spider_disable_irq,
131 .ack = spider_ack_irq, 117 .ack = spider_ack_irq,
132 .end = spider_end_irq,
133}; 118};
134 119
135int spider_get_irq(int node) 120static int spider_get_irq(int node)
136{ 121{
137 unsigned long cs; 122 unsigned long cs;
138 void __iomem *regs = spider_pics[node]; 123 void __iomem *regs = spider_pics[node];
@@ -145,95 +130,89 @@ int spider_get_irq(int node)
145 return cs; 130 return cs;
146} 131}
147 132
133static void spider_irq_cascade(unsigned int irq, struct irq_desc *desc,
134 struct pt_regs *regs)
135{
136 int node = (int)(long)desc->handler_data;
137 int cascade_irq;
138
139 cascade_irq = spider_get_irq(node);
140 generic_handle_irq(cascade_irq, regs);
141 desc->chip->eoi(irq);
142}
143
148/* hardcoded part to be compatible with older firmware */ 144/* hardcoded part to be compatible with older firmware */
149 145
150void spider_init_IRQ_hardcoded(void) 146static void __init spider_init_one(int node, unsigned long addr)
151{ 147{
152 int node; 148 int n, irq;
153 long spiderpic; 149
154 long pics[] = { 0x24000008000, 0x34000008000 }; 150 spider_pics[node] = ioremap(addr, 0x800);
155 int n; 151 if (spider_pics[node] == NULL)
156 152 panic("spider_pic: can't map registers !");
157 pr_debug("%s(%d): Using hardcoded defaults\n", __FUNCTION__, __LINE__); 153
158 154 printk(KERN_INFO "spider_pic: mapped for node %d, addr: 0x%lx mapped to %p\n",
159 for (node = 0; node < num_present_cpus()/2; node++) { 155 node, addr, spider_pics[node]);
160 spiderpic = pics[node]; 156
161 printk(KERN_DEBUG "SPIDER addr: %lx\n", spiderpic); 157 for (n = 0; n < IIC_NUM_EXT; n++) {
162 spider_pics[node] = ioremap(spiderpic, 0x800); 158 if (n == IIC_EXT_CASCADE)
163 for (n = 0; n < IIC_NUM_EXT; n++) { 159 continue;
164 int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE; 160 irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE;
165 get_irq_desc(irq)->chip = &spider_pic; 161 set_irq_chip_and_handler(irq, &spider_pic, handle_level_irq);
166 } 162 get_irq_desc(irq)->status |= IRQ_LEVEL;
167
168 /* do not mask any interrupts because of level */
169 out_be32(spider_pics[node] + TIR_MSK, 0x0);
170
171 /* disable edge detection clear */
172 /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */
173
174 /* enable interrupt packets to be output */
175 out_be32(spider_pics[node] + TIR_PIEN,
176 in_be32(spider_pics[node] + TIR_PIEN) | 0x1);
177
178 /* Enable the interrupt detection enable bit. Do this last! */
179 out_be32(spider_pics[node] + TIR_DEN,
180 in_be32(spider_pics[node] + TIR_DEN) | 0x1);
181 } 163 }
164
165 /* do not mask any interrupts because of level */
166 out_be32(spider_pics[node] + TIR_MSK, 0x0);
167
168 /* disable edge detection clear */
169 /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */
170
171 /* enable interrupt packets to be output */
172 out_be32(spider_pics[node] + TIR_PIEN,
173 in_be32(spider_pics[node] + TIR_PIEN) | 0x1);
174
175 /* Hook up cascade */
176 irq = IIC_EXT_CASCADE + node * IIC_NODE_STRIDE;
177 set_irq_data(irq, (void *)(long)node);
178 set_irq_chained_handler(irq, spider_irq_cascade);
179
180 /* Enable the interrupt detection enable bit. Do this last! */
181 out_be32(spider_pics[node] + TIR_DEN,
182 in_be32(spider_pics[node] + TIR_DEN) | 0x1);
182} 183}
183 184
184void spider_init_IRQ(void) 185void __init spider_init_IRQ(void)
185{ 186{
186 long spider_reg; 187 unsigned long *spider_reg;
187 struct device_node *dn; 188 struct device_node *dn;
188 char *compatible; 189 char *compatible;
189 int n, node = 0; 190 int node = 0;
190 191
192 /* XXX node numbers are totally bogus. We _hope_ we get the device nodes in the right
193 * order here but that's definitely not guaranteed, we need to get the node from the
194 * device tree instead. There is currently no proper property for it (but our whole
195 * device-tree is bogus anyway) so all we can do is pray or maybe test the address
196 * and deduce the node-id
197 */
191 for (dn = NULL; (dn = of_find_node_by_name(dn, "interrupt-controller"));) { 198 for (dn = NULL; (dn = of_find_node_by_name(dn, "interrupt-controller"));) {
192 compatible = (char *)get_property(dn, "compatible", NULL); 199 compatible = (char *)get_property(dn, "compatible", NULL);
193 200
194 if (!compatible) 201 if (!compatible)
195 continue; 202 continue;
196 203
197 if (strstr(compatible, "CBEA,platform-spider-pic")) 204 if (strstr(compatible, "CBEA,platform-spider-pic"))
198 spider_reg = *(long *)get_property(dn,"reg", NULL); 205 spider_reg = (unsigned long *)get_property(dn, "reg", NULL);
199 else if (strstr(compatible, "sti,platform-spider-pic")) { 206 else if (strstr(compatible, "sti,platform-spider-pic") && (node < 2)) {
200 spider_init_IRQ_hardcoded(); 207 static long hard_coded_pics[] = { 0x24000008000, 0x34000008000 };
201 return; 208 spider_reg = &hard_coded_pics[node];
202 } else 209 } else
203 continue; 210 continue;
204 211
205 if (!spider_reg) 212 if (spider_reg == NULL)
206 printk("interrupt controller does not have reg property !\n"); 213 printk(KERN_ERR "spider_pic: No address for node %d\n", node);
207
208 n = prom_n_addr_cells(dn);
209
210 if ( n != 2)
211 printk("reg property with invalid number of elements \n");
212
213 spider_pics[node] = ioremap(spider_reg, 0x800);
214
215 printk("SPIDER addr: %lx with %i addr_cells mapped to %p\n",
216 spider_reg, n, spider_pics[node]);
217
218 for (n = 0; n < IIC_NUM_EXT; n++) {
219 int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE;
220 get_irq_desc(irq)->chip = &spider_pic;
221 }
222
223 /* do not mask any interrupts because of level */
224 out_be32(spider_pics[node] + TIR_MSK, 0x0);
225
226 /* disable edge detection clear */
227 /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */
228
229 /* enable interrupt packets to be output */
230 out_be32(spider_pics[node] + TIR_PIEN,
231 in_be32(spider_pics[node] + TIR_PIEN) | 0x1);
232
233 /* Enable the interrupt detection enable bit. Do this last! */
234 out_be32(spider_pics[node] + TIR_DEN,
235 in_be32(spider_pics[node] + TIR_DEN) | 0x1);
236 214
215 spider_init_one(node, *spider_reg);
237 node++; 216 node++;
238 } 217 }
239} 218}
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 1f1771b212b4..a5dffc8d93a9 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -315,6 +315,21 @@ chrp_event_scan(unsigned long unused)
315 jiffies + event_scan_interval); 315 jiffies + event_scan_interval);
316} 316}
317 317
318void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc,
319 struct pt_regs *regs)
320{
321 unsigned int max = 100;
322
323 while(max--) {
324 int irq = i8259_irq(regs);
325 if (max == 99)
326 desc->chip->eoi(irq);
327 if (irq < 0)
328 break;
329 generic_handle_irq(irq, regs);
330 };
331}
332
318/* 333/*
319 * Finds the open-pic node and sets up the mpic driver. 334 * Finds the open-pic node and sets up the mpic driver.
320 */ 335 */
@@ -402,7 +417,7 @@ static void __init chrp_find_openpic(void)
402 } 417 }
403 418
404 mpic_init(chrp_mpic); 419 mpic_init(chrp_mpic);
405 mpic_setup_cascade(NUM_ISA_INTERRUPTS, i8259_irq_cascade, NULL); 420 set_irq_chained_handler(NUM_ISA_INTERRUPTS, chrp_8259_cascade);
406} 421}
407 422
408#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) 423#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index f70e820e7304..7fb6a08786c0 100644
--- a/arch/powerpc/platforms/iseries/irq.c
+++ b/arch/powerpc/platforms/iseries/irq.c
@@ -297,13 +297,13 @@ static void iseries_end_IRQ(unsigned int irq)
297 (REAL_IRQ_TO_IDSEL(rirq) << 4) + REAL_IRQ_TO_FUNC(rirq)); 297 (REAL_IRQ_TO_IDSEL(rirq) << 4) + REAL_IRQ_TO_FUNC(rirq));
298} 298}
299 299
300static hw_irq_controller iSeries_IRQ_handler = { 300static struct irq_chip iseries_pic = {
301 .typename = "iSeries irq controller", 301 .typename = "iSeries irq controller",
302 .startup = iseries_startup_IRQ, 302 .startup = iseries_startup_IRQ,
303 .shutdown = iseries_shutdown_IRQ, 303 .shutdown = iseries_shutdown_IRQ,
304 .enable = iseries_enable_IRQ, 304 .unmask = iseries_enable_IRQ,
305 .disable = iseries_disable_IRQ, 305 .mask = iseries_disable_IRQ,
306 .end = iseries_end_IRQ 306 .eoi = iseries_end_IRQ
307}; 307};
308 308
309/* 309/*
@@ -322,8 +322,7 @@ int __init iSeries_allocate_IRQ(HvBusNumber bus,
322 realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3) 322 realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3)
323 + function; 323 + function;
324 virtirq = virt_irq_create_mapping(realirq); 324 virtirq = virt_irq_create_mapping(realirq);
325 325 set_irq_chip_and_handler(virtirq, &iseries_pic, handle_fasteoi_irq);
326 irq_desc[virtirq].chip = &iSeries_IRQ_handler;
327 return virtirq; 326 return virtirq;
328} 327}
329 328
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index c9b09a9e6050..58a4c7b90b8b 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -70,18 +70,19 @@ static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE];
70 70
71#define NR_MASK_WORDS ((NR_IRQS + 31) / 32) 71#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
72static unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; 72static unsigned long ppc_lost_interrupts[NR_MASK_WORDS];
73static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
74static int pmac_irq_cascade = -1;
73 75
74/* 76static void __pmac_retrigger(unsigned int irq_nr)
75 * Mark an irq as "lost". This is only used on the pmac
76 * since it can lose interrupts (see pmac_set_irq_mask).
77 * -- Cort
78 */
79void __set_lost(unsigned long irq_nr, int nokick)
80{ 77{
81 if (!test_and_set_bit(irq_nr, ppc_lost_interrupts)) { 78 if (irq_nr >= max_real_irqs && pmac_irq_cascade > 0) {
79 __set_bit(irq_nr, ppc_lost_interrupts);
80 irq_nr = pmac_irq_cascade;
81 mb();
82 }
83 if (!__test_and_set_bit(irq_nr, ppc_lost_interrupts)) {
82 atomic_inc(&ppc_n_lost_interrupts); 84 atomic_inc(&ppc_n_lost_interrupts);
83 if (!nokick) 85 set_dec(1);
84 set_dec(1);
85 } 86 }
86} 87}
87 88
@@ -94,10 +95,10 @@ static void pmac_mask_and_ack_irq(unsigned int irq_nr)
94 if ((unsigned)irq_nr >= max_irqs) 95 if ((unsigned)irq_nr >= max_irqs)
95 return; 96 return;
96 97
97 clear_bit(irq_nr, ppc_cached_irq_mask);
98 if (test_and_clear_bit(irq_nr, ppc_lost_interrupts))
99 atomic_dec(&ppc_n_lost_interrupts);
100 spin_lock_irqsave(&pmac_pic_lock, flags); 98 spin_lock_irqsave(&pmac_pic_lock, flags);
99 __clear_bit(irq_nr, ppc_cached_irq_mask);
100 if (__test_and_clear_bit(irq_nr, ppc_lost_interrupts))
101 atomic_dec(&ppc_n_lost_interrupts);
101 out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]); 102 out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
102 out_le32(&pmac_irq_hw[i]->ack, bit); 103 out_le32(&pmac_irq_hw[i]->ack, bit);
103 do { 104 do {
@@ -109,7 +110,7 @@ static void pmac_mask_and_ack_irq(unsigned int irq_nr)
109 spin_unlock_irqrestore(&pmac_pic_lock, flags); 110 spin_unlock_irqrestore(&pmac_pic_lock, flags);
110} 111}
111 112
112static void pmac_set_irq_mask(unsigned int irq_nr, int nokicklost) 113static void pmac_ack_irq(unsigned int irq_nr)
113{ 114{
114 unsigned long bit = 1UL << (irq_nr & 0x1f); 115 unsigned long bit = 1UL << (irq_nr & 0x1f);
115 int i = irq_nr >> 5; 116 int i = irq_nr >> 5;
@@ -118,7 +119,22 @@ static void pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
118 if ((unsigned)irq_nr >= max_irqs) 119 if ((unsigned)irq_nr >= max_irqs)
119 return; 120 return;
120 121
121 spin_lock_irqsave(&pmac_pic_lock, flags); 122 spin_lock_irqsave(&pmac_pic_lock, flags);
123 if (__test_and_clear_bit(irq_nr, ppc_lost_interrupts))
124 atomic_dec(&ppc_n_lost_interrupts);
125 out_le32(&pmac_irq_hw[i]->ack, bit);
126 (void)in_le32(&pmac_irq_hw[i]->ack);
127 spin_unlock_irqrestore(&pmac_pic_lock, flags);
128}
129
130static void __pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
131{
132 unsigned long bit = 1UL << (irq_nr & 0x1f);
133 int i = irq_nr >> 5;
134
135 if ((unsigned)irq_nr >= max_irqs)
136 return;
137
122 /* enable unmasked interrupts */ 138 /* enable unmasked interrupts */
123 out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]); 139 out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
124 140
@@ -135,8 +151,7 @@ static void pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
135 * the bit in the flag register or request another interrupt. 151 * the bit in the flag register or request another interrupt.
136 */ 152 */
137 if (bit & ppc_cached_irq_mask[i] & in_le32(&pmac_irq_hw[i]->level)) 153 if (bit & ppc_cached_irq_mask[i] & in_le32(&pmac_irq_hw[i]->level))
138 __set_lost((ulong)irq_nr, nokicklost); 154 __pmac_retrigger(irq_nr);
139 spin_unlock_irqrestore(&pmac_pic_lock, flags);
140} 155}
141 156
142/* When an irq gets requested for the first client, if it's an 157/* When an irq gets requested for the first client, if it's an
@@ -144,62 +159,67 @@ static void pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
144 */ 159 */
145static unsigned int pmac_startup_irq(unsigned int irq_nr) 160static unsigned int pmac_startup_irq(unsigned int irq_nr)
146{ 161{
162 unsigned long flags;
147 unsigned long bit = 1UL << (irq_nr & 0x1f); 163 unsigned long bit = 1UL << (irq_nr & 0x1f);
148 int i = irq_nr >> 5; 164 int i = irq_nr >> 5;
149 165
166 spin_lock_irqsave(&pmac_pic_lock, flags);
150 if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0) 167 if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0)
151 out_le32(&pmac_irq_hw[i]->ack, bit); 168 out_le32(&pmac_irq_hw[i]->ack, bit);
152 set_bit(irq_nr, ppc_cached_irq_mask); 169 __set_bit(irq_nr, ppc_cached_irq_mask);
153 pmac_set_irq_mask(irq_nr, 0); 170 __pmac_set_irq_mask(irq_nr, 0);
171 spin_unlock_irqrestore(&pmac_pic_lock, flags);
154 172
155 return 0; 173 return 0;
156} 174}
157 175
158static void pmac_mask_irq(unsigned int irq_nr) 176static void pmac_mask_irq(unsigned int irq_nr)
159{ 177{
160 clear_bit(irq_nr, ppc_cached_irq_mask); 178 unsigned long flags;
161 pmac_set_irq_mask(irq_nr, 0); 179
162 mb(); 180 spin_lock_irqsave(&pmac_pic_lock, flags);
181 __clear_bit(irq_nr, ppc_cached_irq_mask);
182 __pmac_set_irq_mask(irq_nr, 0);
183 spin_unlock_irqrestore(&pmac_pic_lock, flags);
163} 184}
164 185
165static void pmac_unmask_irq(unsigned int irq_nr) 186static void pmac_unmask_irq(unsigned int irq_nr)
166{ 187{
167 set_bit(irq_nr, ppc_cached_irq_mask); 188 unsigned long flags;
168 pmac_set_irq_mask(irq_nr, 0); 189
190 spin_lock_irqsave(&pmac_pic_lock, flags);
191 __set_bit(irq_nr, ppc_cached_irq_mask);
192 __pmac_set_irq_mask(irq_nr, 0);
193 spin_unlock_irqrestore(&pmac_pic_lock, flags);
169} 194}
170 195
171static void pmac_end_irq(unsigned int irq_nr) 196static int pmac_retrigger(unsigned int irq_nr)
172{ 197{
173 if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS)) 198 unsigned long flags;
174 && irq_desc[irq_nr].action) {
175 set_bit(irq_nr, ppc_cached_irq_mask);
176 pmac_set_irq_mask(irq_nr, 1);
177 }
178}
179 199
200 spin_lock_irqsave(&pmac_pic_lock, flags);
201 __pmac_retrigger(irq_nr);
202 spin_unlock_irqrestore(&pmac_pic_lock, flags);
203 return 1;
204}
180 205
181struct hw_interrupt_type pmac_pic = { 206static struct irq_chip pmac_pic = {
182 .typename = " PMAC-PIC ", 207 .typename = " PMAC-PIC ",
183 .startup = pmac_startup_irq, 208 .startup = pmac_startup_irq,
184 .enable = pmac_unmask_irq, 209 .mask = pmac_mask_irq,
185 .disable = pmac_mask_irq, 210 .ack = pmac_ack_irq,
186 .ack = pmac_mask_and_ack_irq, 211 .mask_ack = pmac_mask_and_ack_irq,
187 .end = pmac_end_irq, 212 .unmask = pmac_unmask_irq,
188}; 213 .retrigger = pmac_retrigger,
189
190struct hw_interrupt_type gatwick_pic = {
191 .typename = " GATWICK ",
192 .startup = pmac_startup_irq,
193 .enable = pmac_unmask_irq,
194 .disable = pmac_mask_irq,
195 .ack = pmac_mask_and_ack_irq,
196 .end = pmac_end_irq,
197}; 214};
198 215
199static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs) 216static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs)
200{ 217{
218 unsigned long flags;
201 int irq, bits; 219 int irq, bits;
220 int rc = IRQ_NONE;
202 221
222 spin_lock_irqsave(&pmac_pic_lock, flags);
203 for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) { 223 for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) {
204 int i = irq >> 5; 224 int i = irq >> 5;
205 bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i]; 225 bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];
@@ -209,17 +229,20 @@ static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs)
209 if (bits == 0) 229 if (bits == 0)
210 continue; 230 continue;
211 irq += __ilog2(bits); 231 irq += __ilog2(bits);
232 spin_unlock_irqrestore(&pmac_pic_lock, flags);
212 __do_IRQ(irq, regs); 233 __do_IRQ(irq, regs);
213 return IRQ_HANDLED; 234 spin_lock_irqsave(&pmac_pic_lock, flags);
235 rc = IRQ_HANDLED;
214 } 236 }
215 printk("gatwick irq not from gatwick pic\n"); 237 spin_unlock_irqrestore(&pmac_pic_lock, flags);
216 return IRQ_NONE; 238 return rc;
217} 239}
218 240
219static int pmac_get_irq(struct pt_regs *regs) 241static int pmac_get_irq(struct pt_regs *regs)
220{ 242{
221 int irq; 243 int irq;
222 unsigned long bits = 0; 244 unsigned long bits = 0;
245 unsigned long flags;
223 246
224#ifdef CONFIG_SMP 247#ifdef CONFIG_SMP
225 void psurge_smp_message_recv(struct pt_regs *); 248 void psurge_smp_message_recv(struct pt_regs *);
@@ -230,6 +253,7 @@ static int pmac_get_irq(struct pt_regs *regs)
230 return -2; /* ignore, already handled */ 253 return -2; /* ignore, already handled */
231 } 254 }
232#endif /* CONFIG_SMP */ 255#endif /* CONFIG_SMP */
256 spin_lock_irqsave(&pmac_pic_lock, flags);
233 for (irq = max_real_irqs; (irq -= 32) >= 0; ) { 257 for (irq = max_real_irqs; (irq -= 32) >= 0; ) {
234 int i = irq >> 5; 258 int i = irq >> 5;
235 bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i]; 259 bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];
@@ -241,6 +265,7 @@ static int pmac_get_irq(struct pt_regs *regs)
241 irq += __ilog2(bits); 265 irq += __ilog2(bits);
242 break; 266 break;
243 } 267 }
268 spin_unlock_irqrestore(&pmac_pic_lock, flags);
244 269
245 return irq; 270 return irq;
246} 271}
@@ -389,7 +414,6 @@ static struct irqaction gatwick_cascade_action = {
389static void __init pmac_pic_probe_oldstyle(void) 414static void __init pmac_pic_probe_oldstyle(void)
390{ 415{
391 int i; 416 int i;
392 int irq_cascade = -1;
393 struct device_node *master = NULL; 417 struct device_node *master = NULL;
394 struct device_node *slave = NULL; 418 struct device_node *slave = NULL;
395 u8 __iomem *addr; 419 u8 __iomem *addr;
@@ -443,9 +467,16 @@ static void __init pmac_pic_probe_oldstyle(void)
443 } 467 }
444 BUG_ON(master == NULL); 468 BUG_ON(master == NULL);
445 469
446 /* Set the handler for the main PIC */ 470 /* Mark level interrupts and set handlers */
447 for ( i = 0; i < max_real_irqs ; i++ ) 471 for (i = 0; i < max_irqs; i++) {
448 irq_desc[i].chip = &pmac_pic; 472 int level = !!(level_mask[i >> 5] & (1UL << (i & 0x1f)));
473 if (level)
474 irq_desc[i].status |= IRQ_LEVEL;
475 else
476 irq_desc[i].status |= IRQ_DELAYED_DISABLE;
477 set_irq_chip_and_handler(i, &pmac_pic, level ?
478 handle_level_irq : handle_edge_irq);
479 }
449 480
450 /* Get addresses of first controller if we have a node for it */ 481 /* Get addresses of first controller if we have a node for it */
451 BUG_ON(of_address_to_resource(master, 0, &r)); 482 BUG_ON(of_address_to_resource(master, 0, &r));
@@ -472,29 +503,22 @@ static void __init pmac_pic_probe_oldstyle(void)
472 pmac_irq_hw[i++] = 503 pmac_irq_hw[i++] =
473 (volatile struct pmac_irq_hw __iomem *) 504 (volatile struct pmac_irq_hw __iomem *)
474 (addr + 0x10); 505 (addr + 0x10);
475 irq_cascade = slave->intrs[0].line; 506 pmac_irq_cascade = slave->intrs[0].line;
476 507
477 printk(KERN_INFO "irq: Found slave Apple PIC %s for %d irqs" 508 printk(KERN_INFO "irq: Found slave Apple PIC %s for %d irqs"
478 " cascade: %d\n", slave->full_name, 509 " cascade: %d\n", slave->full_name,
479 max_irqs - max_real_irqs, irq_cascade); 510 max_irqs - max_real_irqs, pmac_irq_cascade);
480 } 511 }
481 of_node_put(slave); 512 of_node_put(slave);
482 513
483 /* disable all interrupts in all controllers */ 514 /* Disable all interrupts in all controllers */
484 for (i = 0; i * 32 < max_irqs; ++i) 515 for (i = 0; i * 32 < max_irqs; ++i)
485 out_le32(&pmac_irq_hw[i]->enable, 0); 516 out_le32(&pmac_irq_hw[i]->enable, 0);
486 517
487 /* mark level interrupts */ 518 /* Hookup cascade irq */
488 for (i = 0; i < max_irqs; i++) 519 if (slave)
489 if (level_mask[i >> 5] & (1UL << (i & 0x1f))) 520 setup_irq(pmac_irq_cascade, &gatwick_cascade_action);
490 irq_desc[i].status = IRQ_LEVEL;
491 521
492 /* Setup handlers for secondary controller and hook cascade irq*/
493 if (slave) {
494 for ( i = max_real_irqs ; i < max_irqs ; i++ )
495 irq_desc[i].chip = &gatwick_pic;
496 setup_irq(irq_cascade, &gatwick_cascade_action);
497 }
498 printk(KERN_INFO "irq: System has %d possible interrupts\n", max_irqs); 522 printk(KERN_INFO "irq: System has %d possible interrupts\n", max_irqs);
499#ifdef CONFIG_XMON 523#ifdef CONFIG_XMON
500 setup_irq(20, &xmon_action); 524 setup_irq(20, &xmon_action);
@@ -502,9 +526,20 @@ static void __init pmac_pic_probe_oldstyle(void)
502} 526}
503#endif /* CONFIG_PPC32 */ 527#endif /* CONFIG_PPC32 */
504 528
505static int pmac_u3_cascade(struct pt_regs *regs, void *data) 529static void pmac_u3_cascade(unsigned int irq, struct irq_desc *desc,
530 struct pt_regs *regs)
506{ 531{
507 return mpic_get_one_irq((struct mpic *)data, regs); 532 struct mpic *mpic = desc->handler_data;
533 unsigned int max = 100;
534
535 while(max--) {
536 int cascade_irq = mpic_get_one_irq(mpic, regs);
537 if (max == 99)
538 desc->chip->eoi(irq);
539 if (irq < 0)
540 break;
541 generic_handle_irq(cascade_irq, regs);
542 };
508} 543}
509 544
510static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic) 545static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic)
@@ -612,7 +647,8 @@ static int __init pmac_pic_probe_mpic(void)
612 of_node_put(slave); 647 of_node_put(slave);
613 return 0; 648 return 0;
614 } 649 }
615 mpic_setup_cascade(slave->intrs[0].line, pmac_u3_cascade, mpic2); 650 set_irq_data(slave->intrs[0].line, mpic2);
651 set_irq_chained_handler(slave->intrs[0].line, pmac_u3_cascade);
616 652
617 of_node_put(slave); 653 of_node_put(slave);
618 return 0; 654 return 0;
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 999509d28af8..476b564a208b 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -118,6 +118,21 @@ static void __init fwnmi_init(void)
118 fwnmi_active = 1; 118 fwnmi_active = 1;
119} 119}
120 120
121void pSeries_8259_cascade(unsigned int irq, struct irq_desc *desc,
122 struct pt_regs *regs)
123{
124 unsigned int max = 100;
125
126 while(max--) {
127 int cascade_irq = i8259_irq(regs);
128 if (max == 99)
129 desc->chip->eoi(irq);
130 if (cascade_irq < 0)
131 break;
132 generic_handle_irq(cascade_irq, regs);
133 };
134}
135
121static void __init pSeries_init_mpic(void) 136static void __init pSeries_init_mpic(void)
122{ 137{
123 unsigned int *addrp; 138 unsigned int *addrp;
@@ -140,7 +155,7 @@ static void __init pSeries_init_mpic(void)
140 i8259_init(intack, 0); 155 i8259_init(intack, 0);
141 156
142 /* Hook cascade to mpic */ 157 /* Hook cascade to mpic */
143 mpic_setup_cascade(NUM_ISA_INTERRUPTS, i8259_irq_cascade, NULL); 158 set_irq_chained_handler(NUM_ISA_INTERRUPTS, pSeries_8259_cascade);
144} 159}
145 160
146static void __init pSeries_setup_mpic(void) 161static void __init pSeries_setup_mpic(void)
@@ -201,10 +216,8 @@ static void __init pSeries_setup_arch(void)
201 /* Allocate the mpic now, so that find_and_init_phbs() can 216 /* Allocate the mpic now, so that find_and_init_phbs() can
202 * fill the ISUs */ 217 * fill the ISUs */
203 pSeries_setup_mpic(); 218 pSeries_setup_mpic();
204 } else { 219 } else
205 ppc_md.init_IRQ = xics_init_IRQ; 220 ppc_md.init_IRQ = xics_init_IRQ;
206 ppc_md.get_irq = xics_get_irq;
207 }
208 221
209#ifdef CONFIG_SMP 222#ifdef CONFIG_SMP
210 smp_init_pSeries(); 223 smp_init_pSeries();
@@ -291,10 +304,7 @@ static void pSeries_mach_cpu_die(void)
291{ 304{
292 local_irq_disable(); 305 local_irq_disable();
293 idle_task_exit(); 306 idle_task_exit();
294 /* Some hardware requires clearing the CPPR, while other hardware does not 307 xics_teardown_cpu(0);
295 * it is safe either way
296 */
297 pSeriesLP_cppr_info(0, 0);
298 rtas_stop_self(); 308 rtas_stop_self();
299 /* Should never get here... */ 309 /* Should never get here... */
300 BUG(); 310 BUG();
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 2ffebe31cb2d..c7f04420066d 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -31,23 +31,6 @@
31 31
32#include "xics.h" 32#include "xics.h"
33 33
34static unsigned int xics_startup(unsigned int irq);
35static void xics_enable_irq(unsigned int irq);
36static void xics_disable_irq(unsigned int irq);
37static void xics_mask_and_ack_irq(unsigned int irq);
38static void xics_end_irq(unsigned int irq);
39static void xics_set_affinity(unsigned int irq_nr, cpumask_t cpumask);
40
41static struct hw_interrupt_type xics_pic = {
42 .typename = " XICS ",
43 .startup = xics_startup,
44 .enable = xics_enable_irq,
45 .disable = xics_disable_irq,
46 .ack = xics_mask_and_ack_irq,
47 .end = xics_end_irq,
48 .set_affinity = xics_set_affinity
49};
50
51/* This is used to map real irq numbers to virtual */ 34/* This is used to map real irq numbers to virtual */
52static struct radix_tree_root irq_map = RADIX_TREE_INIT(GFP_ATOMIC); 35static struct radix_tree_root irq_map = RADIX_TREE_INIT(GFP_ATOMIC);
53 36
@@ -98,47 +81,33 @@ static int ibm_set_xive;
98static int ibm_int_on; 81static int ibm_int_on;
99static int ibm_int_off; 82static int ibm_int_off;
100 83
101typedef struct {
102 int (*xirr_info_get)(int cpu);
103 void (*xirr_info_set)(int cpu, int val);
104 void (*cppr_info)(int cpu, u8 val);
105 void (*qirr_info)(int cpu, u8 val);
106} xics_ops;
107 84
85/* Direct HW low level accessors */
108 86
109/* SMP */
110 87
111static int pSeries_xirr_info_get(int n_cpu) 88static inline int direct_xirr_info_get(int n_cpu)
112{ 89{
113 return in_be32(&xics_per_cpu[n_cpu]->xirr.word); 90 return in_be32(&xics_per_cpu[n_cpu]->xirr.word);
114} 91}
115 92
116static void pSeries_xirr_info_set(int n_cpu, int value) 93static inline void direct_xirr_info_set(int n_cpu, int value)
117{ 94{
118 out_be32(&xics_per_cpu[n_cpu]->xirr.word, value); 95 out_be32(&xics_per_cpu[n_cpu]->xirr.word, value);
119} 96}
120 97
121static void pSeries_cppr_info(int n_cpu, u8 value) 98static inline void direct_cppr_info(int n_cpu, u8 value)
122{ 99{
123 out_8(&xics_per_cpu[n_cpu]->xirr.bytes[0], value); 100 out_8(&xics_per_cpu[n_cpu]->xirr.bytes[0], value);
124} 101}
125 102
126static void pSeries_qirr_info(int n_cpu, u8 value) 103static inline void direct_qirr_info(int n_cpu, u8 value)
127{ 104{
128 out_8(&xics_per_cpu[n_cpu]->qirr.bytes[0], value); 105 out_8(&xics_per_cpu[n_cpu]->qirr.bytes[0], value);
129} 106}
130 107
131static xics_ops pSeries_ops = {
132 pSeries_xirr_info_get,
133 pSeries_xirr_info_set,
134 pSeries_cppr_info,
135 pSeries_qirr_info
136};
137
138static xics_ops *ops = &pSeries_ops;
139 108
109/* LPAR low level accessors */
140 110
141/* LPAR */
142 111
143static inline long plpar_eoi(unsigned long xirr) 112static inline long plpar_eoi(unsigned long xirr)
144{ 113{
@@ -161,7 +130,7 @@ static inline long plpar_xirr(unsigned long *xirr_ret)
161 return plpar_hcall(H_XIRR, 0, 0, 0, 0, xirr_ret, &dummy, &dummy); 130 return plpar_hcall(H_XIRR, 0, 0, 0, 0, xirr_ret, &dummy, &dummy);
162} 131}
163 132
164static int pSeriesLP_xirr_info_get(int n_cpu) 133static inline int lpar_xirr_info_get(int n_cpu)
165{ 134{
166 unsigned long lpar_rc; 135 unsigned long lpar_rc;
167 unsigned long return_value; 136 unsigned long return_value;
@@ -172,7 +141,7 @@ static int pSeriesLP_xirr_info_get(int n_cpu)
172 return (int)return_value; 141 return (int)return_value;
173} 142}
174 143
175static void pSeriesLP_xirr_info_set(int n_cpu, int value) 144static inline void lpar_xirr_info_set(int n_cpu, int value)
176{ 145{
177 unsigned long lpar_rc; 146 unsigned long lpar_rc;
178 unsigned long val64 = value & 0xffffffff; 147 unsigned long val64 = value & 0xffffffff;
@@ -183,7 +152,7 @@ static void pSeriesLP_xirr_info_set(int n_cpu, int value)
183 val64); 152 val64);
184} 153}
185 154
186void pSeriesLP_cppr_info(int n_cpu, u8 value) 155static inline void lpar_cppr_info(int n_cpu, u8 value)
187{ 156{
188 unsigned long lpar_rc; 157 unsigned long lpar_rc;
189 158
@@ -192,7 +161,7 @@ void pSeriesLP_cppr_info(int n_cpu, u8 value)
192 panic("bad return code cppr - rc = %lx\n", lpar_rc); 161 panic("bad return code cppr - rc = %lx\n", lpar_rc);
193} 162}
194 163
195static void pSeriesLP_qirr_info(int n_cpu , u8 value) 164static inline void lpar_qirr_info(int n_cpu , u8 value)
196{ 165{
197 unsigned long lpar_rc; 166 unsigned long lpar_rc;
198 167
@@ -201,36 +170,9 @@ static void pSeriesLP_qirr_info(int n_cpu , u8 value)
201 panic("bad return code qirr - rc = %lx\n", lpar_rc); 170 panic("bad return code qirr - rc = %lx\n", lpar_rc);
202} 171}
203 172
204xics_ops pSeriesLP_ops = {
205 pSeriesLP_xirr_info_get,
206 pSeriesLP_xirr_info_set,
207 pSeriesLP_cppr_info,
208 pSeriesLP_qirr_info
209};
210 173
211static unsigned int xics_startup(unsigned int virq) 174/* High level handlers and init code */
212{
213 unsigned int irq;
214 175
215 irq = irq_offset_down(virq);
216 if (radix_tree_insert(&irq_map, virt_irq_to_real(irq),
217 &virt_irq_to_real_map[irq]) == -ENOMEM)
218 printk(KERN_CRIT "Out of memory creating real -> virtual"
219 " IRQ mapping for irq %u (real 0x%x)\n",
220 virq, virt_irq_to_real(irq));
221 xics_enable_irq(virq);
222 return 0; /* return value is ignored */
223}
224
225static unsigned int real_irq_to_virt(unsigned int real_irq)
226{
227 unsigned int *ptr;
228
229 ptr = radix_tree_lookup(&irq_map, real_irq);
230 if (ptr == NULL)
231 return NO_IRQ;
232 return ptr - virt_irq_to_real_map;
233}
234 176
235#ifdef CONFIG_SMP 177#ifdef CONFIG_SMP
236static int get_irq_server(unsigned int irq) 178static int get_irq_server(unsigned int irq)
@@ -264,17 +206,20 @@ static int get_irq_server(unsigned int irq)
264} 206}
265#endif 207#endif
266 208
267static void xics_enable_irq(unsigned int virq) 209
210static void xics_unmask_irq(unsigned int virq)
268{ 211{
269 unsigned int irq; 212 unsigned int irq;
270 int call_status; 213 int call_status;
271 unsigned int server; 214 unsigned int server;
272 215
273 irq = virt_irq_to_real(irq_offset_down(virq)); 216 irq = virt_irq_to_real(irq_offset_down(virq));
274 if (irq == XICS_IPI) 217 WARN_ON(irq == NO_IRQ);
218 if (irq == XICS_IPI || irq == NO_IRQ)
275 return; 219 return;
276 220
277 server = get_irq_server(virq); 221 server = get_irq_server(virq);
222
278 call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, 223 call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server,
279 DEFAULT_PRIORITY); 224 DEFAULT_PRIORITY);
280 if (call_status != 0) { 225 if (call_status != 0) {
@@ -293,7 +238,7 @@ static void xics_enable_irq(unsigned int virq)
293 } 238 }
294} 239}
295 240
296static void xics_disable_real_irq(unsigned int irq) 241static void xics_mask_real_irq(unsigned int irq)
297{ 242{
298 int call_status; 243 int call_status;
299 unsigned int server; 244 unsigned int server;
@@ -318,75 +263,104 @@ static void xics_disable_real_irq(unsigned int irq)
318 } 263 }
319} 264}
320 265
321static void xics_disable_irq(unsigned int virq) 266static void xics_mask_irq(unsigned int virq)
322{ 267{
323 unsigned int irq; 268 unsigned int irq;
324 269
325 irq = virt_irq_to_real(irq_offset_down(virq)); 270 irq = virt_irq_to_real(irq_offset_down(virq));
326 xics_disable_real_irq(irq); 271 WARN_ON(irq == NO_IRQ);
272 if (irq != NO_IRQ)
273 xics_mask_real_irq(irq);
274}
275
276static void xics_set_irq_revmap(unsigned int virq)
277{
278 unsigned int irq;
279
280 irq = irq_offset_down(virq);
281 if (radix_tree_insert(&irq_map, virt_irq_to_real(irq),
282 &virt_irq_to_real_map[irq]) == -ENOMEM)
283 printk(KERN_CRIT "Out of memory creating real -> virtual"
284 " IRQ mapping for irq %u (real 0x%x)\n",
285 virq, virt_irq_to_real(irq));
327} 286}
328 287
329static void xics_end_irq(unsigned int irq) 288static unsigned int xics_startup(unsigned int virq)
289{
290 xics_set_irq_revmap(virq);
291 xics_unmask_irq(virq);
292 return 0;
293}
294
295static unsigned int real_irq_to_virt(unsigned int real_irq)
296{
297 unsigned int *ptr;
298
299 ptr = radix_tree_lookup(&irq_map, real_irq);
300 if (ptr == NULL)
301 return NO_IRQ;
302 return ptr - virt_irq_to_real_map;
303}
304
305static void xics_eoi_direct(unsigned int irq)
330{ 306{
331 int cpu = smp_processor_id(); 307 int cpu = smp_processor_id();
332 308
333 iosync(); 309 iosync();
334 ops->xirr_info_set(cpu, ((0xff << 24) | 310 direct_xirr_info_set(cpu, ((0xff << 24) |
335 (virt_irq_to_real(irq_offset_down(irq))))); 311 (virt_irq_to_real(irq_offset_down(irq)))));
336
337} 312}
338 313
339static void xics_mask_and_ack_irq(unsigned int irq) 314
315static void xics_eoi_lpar(unsigned int irq)
340{ 316{
341 int cpu = smp_processor_id(); 317 int cpu = smp_processor_id();
342 318
343 if (irq < irq_offset_value()) { 319 iosync();
344 i8259_pic.ack(irq); 320 lpar_xirr_info_set(cpu, ((0xff << 24) |
345 iosync(); 321 (virt_irq_to_real(irq_offset_down(irq)))));
346 ops->xirr_info_set(cpu, ((0xff<<24) | 322
347 xics_irq_8259_cascade_real));
348 iosync();
349 }
350} 323}
351 324
352int xics_get_irq(struct pt_regs *regs) 325static inline int xics_remap_irq(int vec)
353{ 326{
354 unsigned int cpu = smp_processor_id();
355 unsigned int vec;
356 int irq; 327 int irq;
357 328
358 vec = ops->xirr_info_get(cpu);
359 /* (vec >> 24) == old priority */
360 vec &= 0x00ffffff; 329 vec &= 0x00ffffff;
361 330
362 /* for sanity, this had better be < NR_IRQS - 16 */ 331 if (vec == XICS_IRQ_SPURIOUS)
363 if (vec == xics_irq_8259_cascade_real) { 332 return NO_IRQ;
364 irq = i8259_irq(regs); 333
365 xics_end_irq(irq_offset_up(xics_irq_8259_cascade)); 334 irq = real_irq_to_virt(vec);
366 } else if (vec == XICS_IRQ_SPURIOUS) { 335 if (irq == NO_IRQ)
367 irq = -1; 336 irq = real_irq_to_virt_slowpath(vec);
368 } else { 337 if (likely(irq != NO_IRQ))
369 irq = real_irq_to_virt(vec); 338 return irq_offset_up(irq);
370 if (irq == NO_IRQ) 339
371 irq = real_irq_to_virt_slowpath(vec); 340 printk(KERN_ERR "Interrupt %u (real) is invalid,"
372 if (irq == NO_IRQ) { 341 " disabling it.\n", vec);
373 printk(KERN_ERR "Interrupt %u (real) is invalid," 342 xics_mask_real_irq(vec);
374 " disabling it.\n", vec); 343 return NO_IRQ;
375 xics_disable_real_irq(vec);
376 } else
377 irq = irq_offset_up(irq);
378 }
379 return irq;
380} 344}
381 345
382#ifdef CONFIG_SMP 346static int xics_get_irq_direct(struct pt_regs *regs)
347{
348 unsigned int cpu = smp_processor_id();
383 349
384static irqreturn_t xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs) 350 return xics_remap_irq(direct_xirr_info_get(cpu));
351}
352
353static int xics_get_irq_lpar(struct pt_regs *regs)
385{ 354{
386 int cpu = smp_processor_id(); 355 unsigned int cpu = smp_processor_id();
387 356
388 ops->qirr_info(cpu, 0xff); 357 return xics_remap_irq(lpar_xirr_info_get(cpu));
358}
359
360#ifdef CONFIG_SMP
389 361
362static irqreturn_t xics_ipi_dispatch(int cpu, struct pt_regs *regs)
363{
390 WARN_ON(cpu_is_offline(cpu)); 364 WARN_ON(cpu_is_offline(cpu));
391 365
392 while (xics_ipi_message[cpu].value) { 366 while (xics_ipi_message[cpu].value) {
@@ -418,18 +392,108 @@ static irqreturn_t xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
418 return IRQ_HANDLED; 392 return IRQ_HANDLED;
419} 393}
420 394
395static irqreturn_t xics_ipi_action_direct(int irq, void *dev_id, struct pt_regs *regs)
396{
397 int cpu = smp_processor_id();
398
399 direct_qirr_info(cpu, 0xff);
400
401 return xics_ipi_dispatch(cpu, regs);
402}
403
404static irqreturn_t xics_ipi_action_lpar(int irq, void *dev_id, struct pt_regs *regs)
405{
406 int cpu = smp_processor_id();
407
408 lpar_qirr_info(cpu, 0xff);
409
410 return xics_ipi_dispatch(cpu, regs);
411}
412
421void xics_cause_IPI(int cpu) 413void xics_cause_IPI(int cpu)
422{ 414{
423 ops->qirr_info(cpu, IPI_PRIORITY); 415 if (firmware_has_feature(FW_FEATURE_LPAR))
416 lpar_qirr_info(cpu, IPI_PRIORITY);
417 else
418 direct_qirr_info(cpu, IPI_PRIORITY);
424} 419}
420
425#endif /* CONFIG_SMP */ 421#endif /* CONFIG_SMP */
426 422
423static void xics_set_cpu_priority(int cpu, unsigned char cppr)
424{
425 if (firmware_has_feature(FW_FEATURE_LPAR))
426 lpar_cppr_info(cpu, cppr);
427 else
428 direct_cppr_info(cpu, cppr);
429 iosync();
430}
431
432static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
433{
434 unsigned int irq;
435 int status;
436 int xics_status[2];
437 unsigned long newmask;
438 cpumask_t tmp = CPU_MASK_NONE;
439
440 irq = virt_irq_to_real(irq_offset_down(virq));
441 if (irq == XICS_IPI || irq == NO_IRQ)
442 return;
443
444 status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
445
446 if (status) {
447 printk(KERN_ERR "xics_set_affinity: irq=%u ibm,get-xive "
448 "returns %d\n", irq, status);
449 return;
450 }
451
452 /* For the moment only implement delivery to all cpus or one cpu */
453 if (cpus_equal(cpumask, CPU_MASK_ALL)) {
454 newmask = default_distrib_server;
455 } else {
456 cpus_and(tmp, cpu_online_map, cpumask);
457 if (cpus_empty(tmp))
458 return;
459 newmask = get_hard_smp_processor_id(first_cpu(tmp));
460 }
461
462 status = rtas_call(ibm_set_xive, 3, 1, NULL,
463 irq, newmask, xics_status[1]);
464
465 if (status) {
466 printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive "
467 "returns %d\n", irq, status);
468 return;
469 }
470}
471
472static struct irq_chip xics_pic_direct = {
473 .typename = " XICS ",
474 .startup = xics_startup,
475 .mask = xics_mask_irq,
476 .unmask = xics_unmask_irq,
477 .eoi = xics_eoi_direct,
478 .set_affinity = xics_set_affinity
479};
480
481
482static struct irq_chip xics_pic_lpar = {
483 .typename = " XICS ",
484 .startup = xics_startup,
485 .mask = xics_mask_irq,
486 .unmask = xics_unmask_irq,
487 .eoi = xics_eoi_lpar,
488 .set_affinity = xics_set_affinity
489};
490
491
427void xics_setup_cpu(void) 492void xics_setup_cpu(void)
428{ 493{
429 int cpu = smp_processor_id(); 494 int cpu = smp_processor_id();
430 495
431 ops->cppr_info(cpu, 0xff); 496 xics_set_cpu_priority(cpu, 0xff);
432 iosync();
433 497
434 /* 498 /*
435 * Put the calling processor into the GIQ. This is really only 499 * Put the calling processor into the GIQ. This is really only
@@ -453,6 +517,7 @@ void xics_init_IRQ(void)
453 unsigned long addr; 517 unsigned long addr;
454 unsigned long size; 518 unsigned long size;
455 } intnodes[NR_CPUS]; 519 } intnodes[NR_CPUS];
520 struct irq_chip *chip;
456 521
457 ppc64_boot_msg(0x20, "XICS Init"); 522 ppc64_boot_msg(0x20, "XICS Init");
458 523
@@ -519,26 +584,10 @@ nextnode:
519 intr_base = intnodes[0].addr; 584 intr_base = intnodes[0].addr;
520 intr_size = intnodes[0].size; 585 intr_size = intnodes[0].size;
521 586
522 np = of_find_node_by_type(NULL, "interrupt-controller"); 587 if (firmware_has_feature(FW_FEATURE_LPAR)) {
523 if (!np) { 588 ppc_md.get_irq = xics_get_irq_lpar;
524 printk(KERN_DEBUG "xics: no ISA interrupt controller\n"); 589 chip = &xics_pic_lpar;
525 xics_irq_8259_cascade_real = -1; 590 } else {
526 xics_irq_8259_cascade = -1;
527 } else {
528 ireg = (uint *) get_property(np, "interrupts", NULL);
529 if (!ireg)
530 panic("xics_init_IRQ: can't find ISA interrupts property");
531
532 xics_irq_8259_cascade_real = *ireg;
533 xics_irq_8259_cascade
534 = virt_irq_create_mapping(xics_irq_8259_cascade_real);
535 i8259_init(0, 0);
536 of_node_put(np);
537 }
538
539 if (firmware_has_feature(FW_FEATURE_LPAR))
540 ops = &pSeriesLP_ops;
541 else {
542#ifdef CONFIG_SMP 591#ifdef CONFIG_SMP
543 for_each_possible_cpu(i) { 592 for_each_possible_cpu(i) {
544 int hard_id; 593 int hard_id;
@@ -554,32 +603,54 @@ nextnode:
554#else 603#else
555 xics_per_cpu[0] = ioremap(intr_base, intr_size); 604 xics_per_cpu[0] = ioremap(intr_base, intr_size);
556#endif /* CONFIG_SMP */ 605#endif /* CONFIG_SMP */
606 ppc_md.get_irq = xics_get_irq_direct;
607 chip = &xics_pic_direct;
608
557 } 609 }
558 610
559 for (i = irq_offset_value(); i < NR_IRQS; ++i) 611 for (i = irq_offset_value(); i < NR_IRQS; ++i) {
560 get_irq_desc(i)->chip = &xics_pic; 612 /* All IRQs on XICS are level for now. MSI code may want to modify
613 * that for reporting purposes
614 */
615 get_irq_desc(i)->status |= IRQ_LEVEL;
616 set_irq_chip_and_handler(i, chip, handle_fasteoi_irq);
617 }
561 618
562 xics_setup_cpu(); 619 xics_setup_cpu();
563 620
564 ppc64_boot_msg(0x21, "XICS Done"); 621 ppc64_boot_msg(0x21, "XICS Done");
565} 622}
566 623
567/* 624static int xics_setup_8259_cascade(void)
568 * We cant do this in init_IRQ because we need the memory subsystem up for 625{
569 * request_irq() 626 struct device_node *np;
570 */ 627 uint *ireg;
571static int __init xics_setup_i8259(void) 628
572{ 629 np = of_find_node_by_type(NULL, "interrupt-controller");
573 if (ppc64_interrupt_controller == IC_PPC_XIC && 630 if (np == NULL) {
574 xics_irq_8259_cascade != -1) { 631 printk(KERN_WARNING "xics: no ISA interrupt controller\n");
575 if (request_irq(irq_offset_up(xics_irq_8259_cascade), 632 xics_irq_8259_cascade_real = -1;
576 no_action, 0, "8259 cascade", NULL)) 633 xics_irq_8259_cascade = -1;
577 printk(KERN_ERR "xics_setup_i8259: couldn't get 8259 " 634 return 0;
578 "cascade\n");
579 } 635 }
636
637 ireg = (uint *) get_property(np, "interrupts", NULL);
638 if (!ireg)
639 panic("xics_init_IRQ: can't find ISA interrupts property");
640
641 xics_irq_8259_cascade_real = *ireg;
642 xics_irq_8259_cascade = irq_offset_up
643 (virt_irq_create_mapping(xics_irq_8259_cascade_real));
644 i8259_init(0, 0);
645 of_node_put(np);
646
647 xics_set_irq_revmap(xics_irq_8259_cascade);
648 set_irq_chained_handler(xics_irq_8259_cascade, pSeries_8259_cascade);
649
580 return 0; 650 return 0;
581} 651}
582arch_initcall(xics_setup_i8259); 652arch_initcall(xics_setup_8259_cascade);
653
583 654
584#ifdef CONFIG_SMP 655#ifdef CONFIG_SMP
585void xics_request_IPIs(void) 656void xics_request_IPIs(void)
@@ -590,61 +661,22 @@ void xics_request_IPIs(void)
590 * IPIs are marked IRQF_DISABLED as they must run with irqs 661 * IPIs are marked IRQF_DISABLED as they must run with irqs
591 * disabled 662 * disabled
592 */ 663 */
593 request_irq(irq_offset_up(XICS_IPI), xics_ipi_action, 664 set_irq_handler(irq_offset_up(XICS_IPI), handle_percpu_irq);
594 IRQF_DISABLED, "IPI", NULL); 665 if (firmware_has_feature(FW_FEATURE_LPAR))
595 get_irq_desc(irq_offset_up(XICS_IPI))->status |= IRQ_PER_CPU; 666 request_irq(irq_offset_up(XICS_IPI), xics_ipi_action_lpar,
596} 667 SA_INTERRUPT, "IPI", NULL);
597#endif 668 else
598 669 request_irq(irq_offset_up(XICS_IPI), xics_ipi_action_direct,
599static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) 670 SA_INTERRUPT, "IPI", NULL);
600{
601 unsigned int irq;
602 int status;
603 int xics_status[2];
604 unsigned long newmask;
605 cpumask_t tmp = CPU_MASK_NONE;
606
607 irq = virt_irq_to_real(irq_offset_down(virq));
608 if (irq == XICS_IPI || irq == NO_IRQ)
609 return;
610
611 status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
612
613 if (status) {
614 printk(KERN_ERR "xics_set_affinity: irq=%u ibm,get-xive "
615 "returns %d\n", irq, status);
616 return;
617 }
618
619 /* For the moment only implement delivery to all cpus or one cpu */
620 if (cpus_equal(cpumask, CPU_MASK_ALL)) {
621 newmask = default_distrib_server;
622 } else {
623 cpus_and(tmp, cpu_online_map, cpumask);
624 if (cpus_empty(tmp))
625 return;
626 newmask = get_hard_smp_processor_id(first_cpu(tmp));
627 }
628
629 status = rtas_call(ibm_set_xive, 3, 1, NULL,
630 irq, newmask, xics_status[1]);
631
632 if (status) {
633 printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive "
634 "returns %d\n", irq, status);
635 return;
636 }
637} 671}
672#endif /* CONFIG_SMP */
638 673
639void xics_teardown_cpu(int secondary) 674void xics_teardown_cpu(int secondary)
640{ 675{
676 struct irq_desc *desc = get_irq_desc(irq_offset_up(XICS_IPI));
641 int cpu = smp_processor_id(); 677 int cpu = smp_processor_id();
642 678
643 ops->cppr_info(cpu, 0x00); 679 xics_set_cpu_priority(cpu, 0);
644 iosync();
645
646 /* Clear IPI */
647 ops->qirr_info(cpu, 0xff);
648 680
649 /* 681 /*
650 * we need to EOI the IPI if we got here from kexec down IPI 682 * we need to EOI the IPI if we got here from kexec down IPI
@@ -653,7 +685,8 @@ void xics_teardown_cpu(int secondary)
653 * should we be flagging idle loop instead? 685 * should we be flagging idle loop instead?
654 * or creating some task to be scheduled? 686 * or creating some task to be scheduled?
655 */ 687 */
656 ops->xirr_info_set(cpu, XICS_IPI); 688 if (desc->chip && desc->chip->eoi)
689 desc->chip->eoi(XICS_IPI);
657 690
658 /* 691 /*
659 * Some machines need to have at least one cpu in the GIQ, 692 * Some machines need to have at least one cpu in the GIQ,
@@ -674,8 +707,7 @@ void xics_migrate_irqs_away(void)
674 unsigned int irq, virq, cpu = smp_processor_id(); 707 unsigned int irq, virq, cpu = smp_processor_id();
675 708
676 /* Reject any interrupt that was queued to us... */ 709 /* Reject any interrupt that was queued to us... */
677 ops->cppr_info(cpu, 0); 710 xics_set_cpu_priority(cpu, 0);
678 iosync();
679 711
680 /* remove ourselves from the global interrupt queue */ 712 /* remove ourselves from the global interrupt queue */
681 status = rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, 713 status = rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
@@ -683,11 +715,10 @@ void xics_migrate_irqs_away(void)
683 WARN_ON(status < 0); 715 WARN_ON(status < 0);
684 716
685 /* Allow IPIs again... */ 717 /* Allow IPIs again... */
686 ops->cppr_info(cpu, DEFAULT_PRIORITY); 718 xics_set_cpu_priority(cpu, DEFAULT_PRIORITY);
687 iosync();
688 719
689 for_each_irq(virq) { 720 for_each_irq(virq) {
690 irq_desc_t *desc; 721 struct irq_desc *desc;
691 int xics_status[2]; 722 int xics_status[2];
692 unsigned long flags; 723 unsigned long flags;
693 724
diff --git a/arch/powerpc/platforms/pseries/xics.h b/arch/powerpc/platforms/pseries/xics.h
index e14c70868f1d..67dedf3514ec 100644
--- a/arch/powerpc/platforms/pseries/xics.h
+++ b/arch/powerpc/platforms/pseries/xics.h
@@ -14,13 +14,12 @@
14 14
15#include <linux/cache.h> 15#include <linux/cache.h>
16 16
17void xics_init_IRQ(void); 17extern void xics_init_IRQ(void);
18int xics_get_irq(struct pt_regs *); 18extern void xics_setup_cpu(void);
19void xics_setup_cpu(void); 19extern void xics_teardown_cpu(int secondary);
20void xics_teardown_cpu(int secondary); 20extern void xics_cause_IPI(int cpu);
21void xics_cause_IPI(int cpu); 21extern void xics_request_IPIs(void);
22void xics_request_IPIs(void); 22extern void xics_migrate_irqs_away(void);
23void xics_migrate_irqs_away(void);
24 23
25/* first argument is ignored for now*/ 24/* first argument is ignored for now*/
26void pSeriesLP_cppr_info(int n_cpu, u8 value); 25void pSeriesLP_cppr_info(int n_cpu, u8 value);
@@ -31,4 +30,8 @@ struct xics_ipi_struct {
31 30
32extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; 31extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
33 32
33struct irq_desc;
34extern void pSeries_8259_cascade(unsigned int irq, struct irq_desc *desc,
35 struct pt_regs *regs);
36
34#endif /* _POWERPC_KERNEL_XICS_H */ 37#endif /* _POWERPC_KERNEL_XICS_H */
diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c
index 1a3ef1ab9d6e..c2e9465871aa 100644
--- a/arch/powerpc/sysdev/i8259.c
+++ b/arch/powerpc/sysdev/i8259.c
@@ -69,11 +69,6 @@ int i8259_irq(struct pt_regs *regs)
69 return irq + i8259_pic_irq_offset; 69 return irq + i8259_pic_irq_offset;
70} 70}
71 71
72int i8259_irq_cascade(struct pt_regs *regs, void *unused)
73{
74 return i8259_irq(regs);
75}
76
77static void i8259_mask_and_ack_irq(unsigned int irq_nr) 72static void i8259_mask_and_ack_irq(unsigned int irq_nr)
78{ 73{
79 unsigned long flags; 74 unsigned long flags;
@@ -129,19 +124,11 @@ static void i8259_unmask_irq(unsigned int irq_nr)
129 spin_unlock_irqrestore(&i8259_lock, flags); 124 spin_unlock_irqrestore(&i8259_lock, flags);
130} 125}
131 126
132static void i8259_end_irq(unsigned int irq) 127static struct irq_chip i8259_pic = {
133{ 128 .typename = " i8259 ",
134 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) 129 .mask = i8259_mask_irq,
135 && irq_desc[irq].action) 130 .unmask = i8259_unmask_irq,
136 i8259_unmask_irq(irq); 131 .mask_ack = i8259_mask_and_ack_irq,
137}
138
139struct hw_interrupt_type i8259_pic = {
140 .typename = " i8259 ",
141 .enable = i8259_unmask_irq,
142 .disable = i8259_mask_irq,
143 .ack = i8259_mask_and_ack_irq,
144 .end = i8259_end_irq,
145}; 132};
146 133
147static struct resource pic1_iores = { 134static struct resource pic1_iores = {
@@ -207,8 +194,11 @@ void __init i8259_init(unsigned long intack_addr, int offset)
207 194
208 spin_unlock_irqrestore(&i8259_lock, flags); 195 spin_unlock_irqrestore(&i8259_lock, flags);
209 196
210 for (i = 0; i < NUM_ISA_INTERRUPTS; ++i) 197 for (i = 0; i < NUM_ISA_INTERRUPTS; ++i) {
211 irq_desc[offset + i].chip = &i8259_pic; 198 set_irq_chip_and_handler(offset + i, &i8259_pic,
199 handle_level_irq);
200 irq_desc[offset + i].status |= IRQ_LEVEL;
201 }
212 202
213 /* reserve our resources */ 203 /* reserve our resources */
214 setup_irq(offset + 2, &i8259_irqaction); 204 setup_irq(offset + 2, &i8259_irqaction);
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 7e469358895f..9a95f16c19a5 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -100,8 +100,8 @@ static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg)
100 100
101 if (mpic->flags & MPIC_PRIMARY) 101 if (mpic->flags & MPIC_PRIMARY)
102 cpu = hard_smp_processor_id(); 102 cpu = hard_smp_processor_id();
103 103 return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN,
104 return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], reg); 104 mpic->cpuregs[cpu], reg);
105} 105}
106 106
107static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value) 107static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value)
@@ -378,14 +378,14 @@ static inline u32 mpic_physmask(u32 cpumask)
378/* Get the mpic structure from the IPI number */ 378/* Get the mpic structure from the IPI number */
379static inline struct mpic * mpic_from_ipi(unsigned int ipi) 379static inline struct mpic * mpic_from_ipi(unsigned int ipi)
380{ 380{
381 return container_of(irq_desc[ipi].chip, struct mpic, hc_ipi); 381 return irq_desc[ipi].chip_data;
382} 382}
383#endif 383#endif
384 384
385/* Get the mpic structure from the irq number */ 385/* Get the mpic structure from the irq number */
386static inline struct mpic * mpic_from_irq(unsigned int irq) 386static inline struct mpic * mpic_from_irq(unsigned int irq)
387{ 387{
388 return container_of(irq_desc[irq].chip, struct mpic, hc_irq); 388 return irq_desc[irq].chip_data;
389} 389}
390 390
391/* Send an EOI */ 391/* Send an EOI */
@@ -410,7 +410,7 @@ static irqreturn_t mpic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
410 */ 410 */
411 411
412 412
413static void mpic_enable_irq(unsigned int irq) 413static void mpic_unmask_irq(unsigned int irq)
414{ 414{
415 unsigned int loops = 100000; 415 unsigned int loops = 100000;
416 struct mpic *mpic = mpic_from_irq(irq); 416 struct mpic *mpic = mpic_from_irq(irq);
@@ -429,35 +429,9 @@ static void mpic_enable_irq(unsigned int irq)
429 break; 429 break;
430 } 430 }
431 } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK); 431 } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);
432
433#ifdef CONFIG_MPIC_BROKEN_U3
434 if (mpic->flags & MPIC_BROKEN_U3) {
435 unsigned int src = irq - mpic->irq_offset;
436 if (mpic_is_ht_interrupt(mpic, src) &&
437 (irq_desc[irq].status & IRQ_LEVEL))
438 mpic_ht_end_irq(mpic, src);
439 }
440#endif /* CONFIG_MPIC_BROKEN_U3 */
441}
442
443static unsigned int mpic_startup_irq(unsigned int irq)
444{
445#ifdef CONFIG_MPIC_BROKEN_U3
446 struct mpic *mpic = mpic_from_irq(irq);
447 unsigned int src = irq - mpic->irq_offset;
448#endif /* CONFIG_MPIC_BROKEN_U3 */
449
450 mpic_enable_irq(irq);
451
452#ifdef CONFIG_MPIC_BROKEN_U3
453 if (mpic_is_ht_interrupt(mpic, src))
454 mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status);
455#endif /* CONFIG_MPIC_BROKEN_U3 */
456
457 return 0;
458} 432}
459 433
460static void mpic_disable_irq(unsigned int irq) 434static void mpic_mask_irq(unsigned int irq)
461{ 435{
462 unsigned int loops = 100000; 436 unsigned int loops = 100000;
463 struct mpic *mpic = mpic_from_irq(irq); 437 struct mpic *mpic = mpic_from_irq(irq);
@@ -478,23 +452,58 @@ static void mpic_disable_irq(unsigned int irq)
478 } while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK)); 452 } while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));
479} 453}
480 454
481static void mpic_shutdown_irq(unsigned int irq) 455static void mpic_end_irq(unsigned int irq)
482{ 456{
457 struct mpic *mpic = mpic_from_irq(irq);
458
459#ifdef DEBUG_IRQ
460 DBG("%s: end_irq: %d\n", mpic->name, irq);
461#endif
462 /* We always EOI on end_irq() even for edge interrupts since that
463 * should only lower the priority, the MPIC should have properly
464 * latched another edge interrupt coming in anyway
465 */
466
467 mpic_eoi(mpic);
468}
469
483#ifdef CONFIG_MPIC_BROKEN_U3 470#ifdef CONFIG_MPIC_BROKEN_U3
471
472static void mpic_unmask_ht_irq(unsigned int irq)
473{
484 struct mpic *mpic = mpic_from_irq(irq); 474 struct mpic *mpic = mpic_from_irq(irq);
485 unsigned int src = irq - mpic->irq_offset; 475 unsigned int src = irq - mpic->irq_offset;
486 476
487 if (mpic_is_ht_interrupt(mpic, src)) 477 mpic_unmask_irq(irq);
488 mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status);
489 478
490#endif /* CONFIG_MPIC_BROKEN_U3 */ 479 if (irq_desc[irq].status & IRQ_LEVEL)
480 mpic_ht_end_irq(mpic, src);
481}
482
483static unsigned int mpic_startup_ht_irq(unsigned int irq)
484{
485 struct mpic *mpic = mpic_from_irq(irq);
486 unsigned int src = irq - mpic->irq_offset;
491 487
492 mpic_disable_irq(irq); 488 mpic_unmask_irq(irq);
489 mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status);
490
491 return 0;
493} 492}
494 493
495static void mpic_end_irq(unsigned int irq) 494static void mpic_shutdown_ht_irq(unsigned int irq)
495{
496 struct mpic *mpic = mpic_from_irq(irq);
497 unsigned int src = irq - mpic->irq_offset;
498
499 mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status);
500 mpic_mask_irq(irq);
501}
502
503static void mpic_end_ht_irq(unsigned int irq)
496{ 504{
497 struct mpic *mpic = mpic_from_irq(irq); 505 struct mpic *mpic = mpic_from_irq(irq);
506 unsigned int src = irq - mpic->irq_offset;
498 507
499#ifdef DEBUG_IRQ 508#ifdef DEBUG_IRQ
500 DBG("%s: end_irq: %d\n", mpic->name, irq); 509 DBG("%s: end_irq: %d\n", mpic->name, irq);
@@ -504,21 +513,16 @@ static void mpic_end_irq(unsigned int irq)
504 * latched another edge interrupt coming in anyway 513 * latched another edge interrupt coming in anyway
505 */ 514 */
506 515
507#ifdef CONFIG_MPIC_BROKEN_U3 516 if (irq_desc[irq].status & IRQ_LEVEL)
508 if (mpic->flags & MPIC_BROKEN_U3) { 517 mpic_ht_end_irq(mpic, src);
509 unsigned int src = irq - mpic->irq_offset;
510 if (mpic_is_ht_interrupt(mpic, src) &&
511 (irq_desc[irq].status & IRQ_LEVEL))
512 mpic_ht_end_irq(mpic, src);
513 }
514#endif /* CONFIG_MPIC_BROKEN_U3 */
515
516 mpic_eoi(mpic); 518 mpic_eoi(mpic);
517} 519}
518 520
521#endif /* CONFIG_MPIC_BROKEN_U3 */
522
519#ifdef CONFIG_SMP 523#ifdef CONFIG_SMP
520 524
521static void mpic_enable_ipi(unsigned int irq) 525static void mpic_unmask_ipi(unsigned int irq)
522{ 526{
523 struct mpic *mpic = mpic_from_ipi(irq); 527 struct mpic *mpic = mpic_from_ipi(irq);
524 unsigned int src = irq - mpic->ipi_offset; 528 unsigned int src = irq - mpic->ipi_offset;
@@ -527,7 +531,7 @@ static void mpic_enable_ipi(unsigned int irq)
527 mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK); 531 mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK);
528} 532}
529 533
530static void mpic_disable_ipi(unsigned int irq) 534static void mpic_mask_ipi(unsigned int irq)
531{ 535{
532 /* NEVER disable an IPI... that's just plain wrong! */ 536 /* NEVER disable an IPI... that's just plain wrong! */
533} 537}
@@ -560,6 +564,30 @@ static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)
560 mpic_physmask(cpus_addr(tmp)[0])); 564 mpic_physmask(cpus_addr(tmp)[0]));
561} 565}
562 566
567static struct irq_chip mpic_irq_chip = {
568 .mask = mpic_mask_irq,
569 .unmask = mpic_unmask_irq,
570 .eoi = mpic_end_irq,
571};
572
573#ifdef CONFIG_SMP
574static struct irq_chip mpic_ipi_chip = {
575 .mask = mpic_mask_ipi,
576 .unmask = mpic_unmask_ipi,
577 .eoi = mpic_end_ipi,
578};
579#endif /* CONFIG_SMP */
580
581#ifdef CONFIG_MPIC_BROKEN_U3
582static struct irq_chip mpic_irq_ht_chip = {
583 .startup = mpic_startup_ht_irq,
584 .shutdown = mpic_shutdown_ht_irq,
585 .mask = mpic_mask_irq,
586 .unmask = mpic_unmask_ht_irq,
587 .eoi = mpic_end_ht_irq,
588};
589#endif /* CONFIG_MPIC_BROKEN_U3 */
590
563 591
564/* 592/*
565 * Exported functions 593 * Exported functions
@@ -589,19 +617,19 @@ struct mpic * __init mpic_alloc(unsigned long phys_addr,
589 memset(mpic, 0, sizeof(struct mpic)); 617 memset(mpic, 0, sizeof(struct mpic));
590 mpic->name = name; 618 mpic->name = name;
591 619
620 mpic->hc_irq = mpic_irq_chip;
592 mpic->hc_irq.typename = name; 621 mpic->hc_irq.typename = name;
593 mpic->hc_irq.startup = mpic_startup_irq;
594 mpic->hc_irq.shutdown = mpic_shutdown_irq;
595 mpic->hc_irq.enable = mpic_enable_irq;
596 mpic->hc_irq.disable = mpic_disable_irq;
597 mpic->hc_irq.end = mpic_end_irq;
598 if (flags & MPIC_PRIMARY) 622 if (flags & MPIC_PRIMARY)
599 mpic->hc_irq.set_affinity = mpic_set_affinity; 623 mpic->hc_irq.set_affinity = mpic_set_affinity;
624#ifdef CONFIG_MPIC_BROKEN_U3
625 mpic->hc_ht_irq = mpic_irq_ht_chip;
626 mpic->hc_ht_irq.typename = name;
627 if (flags & MPIC_PRIMARY)
628 mpic->hc_ht_irq.set_affinity = mpic_set_affinity;
629#endif /* CONFIG_MPIC_BROKEN_U3 */
600#ifdef CONFIG_SMP 630#ifdef CONFIG_SMP
601 mpic->hc_ipi.typename = name; 631 mpic->hc_ipi.typename = name;
602 mpic->hc_ipi.enable = mpic_enable_ipi; 632 mpic->hc_ipi = mpic_ipi_chip;
603 mpic->hc_ipi.disable = mpic_disable_ipi;
604 mpic->hc_ipi.end = mpic_end_ipi;
605#endif /* CONFIG_SMP */ 633#endif /* CONFIG_SMP */
606 634
607 mpic->flags = flags; 635 mpic->flags = flags;
@@ -697,28 +725,6 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
697 mpic->num_sources = isu_first + mpic->isu_size; 725 mpic->num_sources = isu_first + mpic->isu_size;
698} 726}
699 727
700void __init mpic_setup_cascade(unsigned int irq, mpic_cascade_t handler,
701 void *data)
702{
703 struct mpic *mpic = mpic_find(irq, NULL);
704 unsigned long flags;
705
706 /* Synchronization here is a bit dodgy, so don't try to replace cascade
707 * interrupts on the fly too often ... but normally it's set up at boot.
708 */
709 spin_lock_irqsave(&mpic_lock, flags);
710 if (mpic->cascade)
711 mpic_disable_irq(mpic->cascade_vec + mpic->irq_offset);
712 mpic->cascade = NULL;
713 wmb();
714 mpic->cascade_vec = irq - mpic->irq_offset;
715 mpic->cascade_data = data;
716 wmb();
717 mpic->cascade = handler;
718 mpic_enable_irq(irq);
719 spin_unlock_irqrestore(&mpic_lock, flags);
720}
721
722void __init mpic_init(struct mpic *mpic) 728void __init mpic_init(struct mpic *mpic)
723{ 729{
724 int i; 730 int i;
@@ -750,8 +756,10 @@ void __init mpic_init(struct mpic *mpic)
750#ifdef CONFIG_SMP 756#ifdef CONFIG_SMP
751 if (!(mpic->flags & MPIC_PRIMARY)) 757 if (!(mpic->flags & MPIC_PRIMARY))
752 continue; 758 continue;
753 irq_desc[mpic->ipi_offset+i].status |= IRQ_PER_CPU; 759 set_irq_chip_data(mpic->ipi_offset+i, mpic);
754 irq_desc[mpic->ipi_offset+i].chip = &mpic->hc_ipi; 760 set_irq_chip_and_handler(mpic->ipi_offset+i,
761 &mpic->hc_ipi,
762 handle_percpu_irq);
755#endif /* CONFIG_SMP */ 763#endif /* CONFIG_SMP */
756 } 764 }
757 765
@@ -763,7 +771,7 @@ void __init mpic_init(struct mpic *mpic)
763 /* Do the HT PIC fixups on U3 broken mpic */ 771 /* Do the HT PIC fixups on U3 broken mpic */
764 DBG("MPIC flags: %x\n", mpic->flags); 772 DBG("MPIC flags: %x\n", mpic->flags);
765 if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY)) 773 if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY))
766 mpic_scan_ht_pics(mpic); 774 mpic_scan_ht_pics(mpic);
767#endif /* CONFIG_MPIC_BROKEN_U3 */ 775#endif /* CONFIG_MPIC_BROKEN_U3 */
768 776
769 for (i = 0; i < mpic->num_sources; i++) { 777 for (i = 0; i < mpic->num_sources; i++) {
@@ -811,8 +819,17 @@ void __init mpic_init(struct mpic *mpic)
811 819
812 /* init linux descriptors */ 820 /* init linux descriptors */
813 if (i < mpic->irq_count) { 821 if (i < mpic->irq_count) {
814 irq_desc[mpic->irq_offset+i].status = level ? IRQ_LEVEL : 0; 822 struct irq_chip *chip = &mpic->hc_irq;
815 irq_desc[mpic->irq_offset+i].chip = &mpic->hc_irq; 823
824 irq_desc[mpic->irq_offset+i].status |=
825 level ? IRQ_LEVEL : 0;
826#ifdef CONFIG_MPIC_BROKEN_U3
827 if (mpic_is_ht_interrupt(mpic, i))
828 chip = &mpic->hc_ht_irq;
829#endif /* CONFIG_MPIC_BROKEN_U3 */
830 set_irq_chip_data(mpic->irq_offset+i, mpic);
831 set_irq_chip_and_handler(mpic->irq_offset+i, chip,
832 handle_fasteoi_irq);
816 } 833 }
817 } 834 }
818 835
@@ -986,14 +1003,6 @@ int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs)
986#ifdef DEBUG_LOW 1003#ifdef DEBUG_LOW
987 DBG("%s: get_one_irq(): %d\n", mpic->name, irq); 1004 DBG("%s: get_one_irq(): %d\n", mpic->name, irq);
988#endif 1005#endif
989 if (mpic->cascade && irq == mpic->cascade_vec) {
990#ifdef DEBUG_LOW
991 DBG("%s: cascading ...\n", mpic->name);
992#endif
993 irq = mpic->cascade(regs, mpic->cascade_data);
994 mpic_eoi(mpic);
995 return irq;
996 }
997 if (unlikely(irq == MPIC_VEC_SPURRIOUS)) 1006 if (unlikely(irq == MPIC_VEC_SPURRIOUS))
998 return -1; 1007 return -1;
999 if (irq < MPIC_VEC_IPI_0) { 1008 if (irq < MPIC_VEC_IPI_0) {
diff --git a/include/asm-powerpc/i8259.h b/include/asm-powerpc/i8259.h
index 0392159e16e4..ff31cb90325f 100644
--- a/include/asm-powerpc/i8259.h
+++ b/include/asm-powerpc/i8259.h
@@ -4,11 +4,8 @@
4 4
5#include <linux/irq.h> 5#include <linux/irq.h>
6 6
7extern struct hw_interrupt_type i8259_pic;
8
9extern void i8259_init(unsigned long intack_addr, int offset); 7extern void i8259_init(unsigned long intack_addr, int offset);
10extern int i8259_irq(struct pt_regs *regs); 8extern int i8259_irq(struct pt_regs *regs);
11extern int i8259_irq_cascade(struct pt_regs *regs, void *unused);
12 9
13#endif /* __KERNEL__ */ 10#endif /* __KERNEL__ */
14#endif /* _ASM_POWERPC_I8259_H */ 11#endif /* _ASM_POWERPC_I8259_H */
diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h
index eb5f33e1977a..13fa2ef38dc7 100644
--- a/include/asm-powerpc/irq.h
+++ b/include/asm-powerpc/irq.h
@@ -514,9 +514,12 @@ extern u64 ppc64_interrupt_controller;
514 514
515#endif 515#endif
516 516
517#ifndef CONFIG_PPC_MERGE
517#define NR_MASK_WORDS ((NR_IRQS + 31) / 32) 518#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
518/* pedantic: these are long because they are used with set_bit --RR */ 519/* pedantic: these are long because they are used with set_bit --RR */
519extern unsigned long ppc_cached_irq_mask[NR_MASK_WORDS]; 520extern unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
521#endif
522
520extern atomic_t ppc_n_lost_interrupts; 523extern atomic_t ppc_n_lost_interrupts;
521 524
522#define virt_irq_create_mapping(x) (x) 525#define virt_irq_create_mapping(x) (x)
@@ -579,9 +582,8 @@ extern struct thread_info *softirq_ctx[NR_CPUS];
579 582
580extern void irq_ctx_init(void); 583extern void irq_ctx_init(void);
581extern void call_do_softirq(struct thread_info *tp); 584extern void call_do_softirq(struct thread_info *tp);
582extern int call___do_IRQ(int irq, struct pt_regs *regs, 585extern int call_handle_irq(int irq, void *p1, void *p2,
583 struct thread_info *tp); 586 struct thread_info *tp, void *func);
584
585#else 587#else
586#define irq_ctx_init() 588#define irq_ctx_init()
587 589
diff --git a/include/asm-powerpc/mpic.h b/include/asm-powerpc/mpic.h
index f0d22ac34b96..a2277cb77ddc 100644
--- a/include/asm-powerpc/mpic.h
+++ b/include/asm-powerpc/mpic.h
@@ -114,9 +114,6 @@
114#define MPIC_VEC_TIMER_1 248 114#define MPIC_VEC_TIMER_1 248
115#define MPIC_VEC_TIMER_0 247 115#define MPIC_VEC_TIMER_0 247
116 116
117/* Type definition of the cascade handler */
118typedef int (*mpic_cascade_t)(struct pt_regs *regs, void *data);
119
120#ifdef CONFIG_MPIC_BROKEN_U3 117#ifdef CONFIG_MPIC_BROKEN_U3
121/* Fixup table entry */ 118/* Fixup table entry */
122struct mpic_irq_fixup 119struct mpic_irq_fixup
@@ -133,9 +130,12 @@ struct mpic_irq_fixup
133struct mpic 130struct mpic
134{ 131{
135 /* The "linux" controller struct */ 132 /* The "linux" controller struct */
136 hw_irq_controller hc_irq; 133 struct irq_chip hc_irq;
134#ifdef CONFIG_MPIC_BROKEN_U3
135 struct irq_chip hc_ht_irq;
136#endif
137#ifdef CONFIG_SMP 137#ifdef CONFIG_SMP
138 hw_irq_controller hc_ipi; 138 struct irq_chip hc_ipi;
139#endif 139#endif
140 const char *name; 140 const char *name;
141 /* Flags */ 141 /* Flags */
@@ -153,10 +153,6 @@ struct mpic
153 unsigned int num_sources; 153 unsigned int num_sources;
154 /* Number of CPUs */ 154 /* Number of CPUs */
155 unsigned int num_cpus; 155 unsigned int num_cpus;
156 /* cascade handler */
157 mpic_cascade_t cascade;
158 void *cascade_data;
159 unsigned int cascade_vec;
160 /* senses array */ 156 /* senses array */
161 unsigned char *senses; 157 unsigned char *senses;
162 unsigned int senses_count; 158 unsigned int senses_count;
@@ -237,17 +233,6 @@ extern void mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
237 */ 233 */
238extern void mpic_init(struct mpic *mpic); 234extern void mpic_init(struct mpic *mpic);
239 235
240/* Setup a cascade. Currently, only one cascade is supported this
241 * way, though you can always do a normal request_irq() and add
242 * other cascades this way. You should call this _after_ having
243 * added all the ISUs
244 *
245 * @irq_no: "linux" irq number of the cascade (that is offset'ed vector)
246 * @handler: cascade handler function
247 */
248extern void mpic_setup_cascade(unsigned int irq_no, mpic_cascade_t hanlder,
249 void *data);
250
251/* 236/*
252 * All of the following functions must only be used after the 237 * All of the following functions must only be used after the
253 * ISUs have been assigned and the controller fully initialized 238 * ISUs have been assigned and the controller fully initialized