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>
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index 5e92149..42e978e 100644
--- a/arch/powerpc/platforms/iseries/irq.c
+++ b/arch/powerpc/platforms/iseries/irq.c
@@ -82,31 +82,29 @@
 	} 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 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 @@
 	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;
 }