powerpc: more iseries irq work
authorStephen Rothwell <sfr@canb.auug.org.au>
Thu, 17 Nov 2005 07:04:37 +0000 (18:04 +1100)
committerPaul Mackerras <paulus@samba.org>
Mon, 9 Jan 2006 03:50:18 +0000 (14:50 +1100)
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>
arch/powerpc/platforms/iseries/irq.c

index 5e92149b9b9610bb41dab05df3c166a92fece75b..42e978e4897a9d24860ed741abca38ecb2b65133 100644 (file)
@@ -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;
 }