diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2005-11-17 02:04:37 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-01-08 22:50:18 -0500 |
commit | 1d7a6b97f3c30087e307655116ff2ed492a37ad0 (patch) | |
tree | 7a384f6fac7ea5328ea0c2d3f96368e9bc3a4fc9 /arch | |
parent | a50b56d24c59db33792b421af4016a9c958a906f (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')
-rw-r--r-- | arch/powerpc/platforms/iseries/irq.c | 53 |
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 | ||
85 | static DEFINE_SPINLOCK(pending_irqs_lock); | ||
86 | static int num_pending_irqs; | ||
87 | static int pending_irqs[NR_IRQS]; | ||
88 | |||
85 | static void int_received(struct pci_event *event, struct pt_regs *regs) | 89 | static 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, | |||
342 | int iSeries_get_irq(struct pt_regs *regs) | 340 | int 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 | } |