summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2005-11-17 10:04:37 +0300
committerPaul Mackerras <paulus@samba.org>2006-01-09 06:50:18 +0300
commit1d7a6b97f3c30087e307655116ff2ed492a37ad0 (patch)
tree7a384f6fac7ea5328ea0c2d3f96368e9bc3a4fc9
parenta50b56d24c59db33792b421af4016a9c958a906f (diff)
downloadlinux-1d7a6b97f3c30087e307655116ff2ed492a37ad0.tar.xz
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>
-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 {
} data;
};
+static DEFINE_SPINLOCK(pending_irqs_lock);
+static int num_pending_irqs;
+static int pending_irqs[NR_IRQS];
+
static void int_received(struct pci_event *event, struct pt_regs *regs)
{
int irq;
-#ifdef CONFIG_IRQSTACKS
- struct thread_info *curtp, *irqtp;
-#endif
switch (event->event.xSubtype) {
case pe_slot_interrupt:
irq = event->event.xCorrelationToken;
- /* Dispatch the interrupt handlers for this irq */
-#ifdef CONFIG_IRQSTACKS
- /* Switch to the irq stack to handle this */
- curtp = current_thread_info();
- irqtp = hardirq_ctx[smp_processor_id()];
- if (curtp != irqtp) {
- irqtp->task = curtp->task;
- irqtp->flags = 0;
- call___do_IRQ(irq, regs, irqtp);
- irqtp->task = NULL;
- if (irqtp->flags)
- set_bits(irqtp->flags, &curtp->flags);
- } else
-#endif
- __do_IRQ(irq, regs);
+ if (irq < NR_IRQS) {
+ spin_lock(&pending_irqs_lock);
+ pending_irqs[irq]++;
+ num_pending_irqs++;
+ spin_unlock(&pending_irqs_lock);
+ } else {
+ printk(KERN_WARNING "int_received: bad irq number %d\n",
+ irq);
+ HvCallPci_eoi(event->data.slot.bus_number,
+ event->data.slot.sub_bus_number,
+ event->data.slot.dev_id);
+ }
break;
/* Ignore error recovery events for now */
case pe_bus_created:
@@ -342,6 +340,8 @@ int __init iSeries_allocate_IRQ(HvBusNumber bus,
int iSeries_get_irq(struct pt_regs *regs)
{
struct paca_struct *lpaca;
+ /* -2 means ignore this interrupt */
+ int irq = -2;
lpaca = get_paca();
#ifdef CONFIG_SMP
@@ -353,6 +353,19 @@ int iSeries_get_irq(struct pt_regs *regs)
if (hvlpevent_is_pending())
process_hvlpevents(regs);
- /* -2 means ignore this interrupt */
- return -2;
+ if (num_pending_irqs) {
+ spin_lock(&pending_irqs_lock);
+ for (irq = 0; irq < NR_IRQS; irq++) {
+ if (pending_irqs[irq]) {
+ pending_irqs[irq]--;
+ num_pending_irqs--;
+ break;
+ }
+ }
+ spin_unlock(&pending_irqs_lock);
+ if (irq >= NR_IRQS)
+ irq = -2;
+ }
+
+ return irq;
}