aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2005-11-17 02:04:37 -0500
committerPaul Mackerras <paulus@samba.org>2006-01-08 22:50:18 -0500
commit1d7a6b97f3c30087e307655116ff2ed492a37ad0 (patch)
tree7a384f6fac7ea5328ea0c2d3f96368e9bc3a4fc9 /arch/powerpc
parenta50b56d24c59db33792b421af4016a9c958a906f (diff)
powerpc: more iseries irq work
Make get_IRQ return a pending irq number so it can be handled in the powerpc geeneric code. Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/platforms/iseries/irq.c53
1 files changed, 33 insertions, 20 deletions
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index 5e92149b9b96..42e978e4897a 100644
--- a/arch/powerpc/platforms/iseries/irq.c
+++ b/arch/powerpc/platforms/iseries/irq.c
@@ -82,31 +82,29 @@ struct pci_event {
82 } data; 82 } data;
83}; 83};
84 84
85static DEFINE_SPINLOCK(pending_irqs_lock);
86static int num_pending_irqs;
87static int pending_irqs[NR_IRQS];
88
85static void int_received(struct pci_event *event, struct pt_regs *regs) 89static void int_received(struct pci_event *event, struct pt_regs *regs)
86{ 90{
87 int irq; 91 int irq;
88#ifdef CONFIG_IRQSTACKS
89 struct thread_info *curtp, *irqtp;
90#endif
91 92
92 switch (event->event.xSubtype) { 93 switch (event->event.xSubtype) {
93 case pe_slot_interrupt: 94 case pe_slot_interrupt:
94 irq = event->event.xCorrelationToken; 95 irq = event->event.xCorrelationToken;
95 /* Dispatch the interrupt handlers for this irq */ 96 if (irq < NR_IRQS) {
96#ifdef CONFIG_IRQSTACKS 97 spin_lock(&pending_irqs_lock);
97 /* Switch to the irq stack to handle this */ 98 pending_irqs[irq]++;
98 curtp = current_thread_info(); 99 num_pending_irqs++;
99 irqtp = hardirq_ctx[smp_processor_id()]; 100 spin_unlock(&pending_irqs_lock);
100 if (curtp != irqtp) { 101 } else {
101 irqtp->task = curtp->task; 102 printk(KERN_WARNING "int_received: bad irq number %d\n",
102 irqtp->flags = 0; 103 irq);
103 call___do_IRQ(irq, regs, irqtp); 104 HvCallPci_eoi(event->data.slot.bus_number,
104 irqtp->task = NULL; 105 event->data.slot.sub_bus_number,
105 if (irqtp->flags) 106 event->data.slot.dev_id);
106 set_bits(irqtp->flags, &curtp->flags); 107 }
107 } else
108#endif
109 __do_IRQ(irq, regs);
110 break; 108 break;
111 /* Ignore error recovery events for now */ 109 /* Ignore error recovery events for now */
112 case pe_bus_created: 110 case pe_bus_created:
@@ -342,6 +340,8 @@ int __init iSeries_allocate_IRQ(HvBusNumber bus,
342int iSeries_get_irq(struct pt_regs *regs) 340int iSeries_get_irq(struct pt_regs *regs)
343{ 341{
344 struct paca_struct *lpaca; 342 struct paca_struct *lpaca;
343 /* -2 means ignore this interrupt */
344 int irq = -2;
345 345
346 lpaca = get_paca(); 346 lpaca = get_paca();
347#ifdef CONFIG_SMP 347#ifdef CONFIG_SMP
@@ -353,6 +353,19 @@ int iSeries_get_irq(struct pt_regs *regs)
353 if (hvlpevent_is_pending()) 353 if (hvlpevent_is_pending())
354 process_hvlpevents(regs); 354 process_hvlpevents(regs);
355 355
356 /* -2 means ignore this interrupt */ 356 if (num_pending_irqs) {
357 return -2; 357 spin_lock(&pending_irqs_lock);
358 for (irq = 0; irq < NR_IRQS; irq++) {
359 if (pending_irqs[irq]) {
360 pending_irqs[irq]--;
361 num_pending_irqs--;
362 break;
363 }
364 }
365 spin_unlock(&pending_irqs_lock);
366 if (irq >= NR_IRQS)
367 irq = -2;
368 }
369
370 return irq;
358} 371}