[SPARC64]: Virtualize IRQ numbers.

Inspired by PowerPC XICS interrupt support code.

All IRQs are virtualized in order to keep NR_IRQS from needing
to be too large.  Interrupts on sparc64 are arbitrary 11-bit
values, but we don't need to define NR_IRQS to 2048 if we
virtualize the IRQs.

As PCI and SBUS controller drivers build device IRQs, we divy
out virtual IRQ numbers incrementally starting at 1.  Zero is
a special virtual IRQ used for the timer interrupt.

So device drivers all see virtual IRQs, and all the normal
interfaces such as request_irq(), enable_irq(), etc. translate
that into a real IRQ number in order to configure the IRQ.

At this point knowledge of the struct ino_bucket is almost
entirely contained within arch/sparc64/kernel/irq.c  There are
a few small bits in the PCI controller drivers that need to
be swept away before we can remove ino_bucket's definition
out of asm-sparc64/irq.h and privately into kernel/irq.c

Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c
index ca49ef0..0c400b5 100644
--- a/arch/sparc64/kernel/pci_schizo.c
+++ b/arch/sparc64/kernel/pci_schizo.c
@@ -270,25 +270,33 @@
 	}
 }
 
+static unsigned long schizo_ino_to_iclr(struct pci_pbm_info *pbm,
+					unsigned int ino)
+{
+	ino &= PCI_IRQ_INO;
+	return pbm->pbm_regs + schizo_iclr_offset(ino) + 4;
+}
+
+static unsigned long schizo_ino_to_imap(struct pci_pbm_info *pbm,
+					unsigned int ino)
+{
+	ino &= PCI_IRQ_INO;
+	return pbm->pbm_regs + schizo_imap_offset(ino) + 4;
+}
+
 static unsigned int schizo_irq_build(struct pci_pbm_info *pbm,
 				     struct pci_dev *pdev,
 				     unsigned int ino)
 {
-	struct ino_bucket *bucket;
 	unsigned long imap, iclr;
-	unsigned long imap_off, iclr_off;
 	int ign_fixup;
+	int virt_irq;
 
 	ino &= PCI_IRQ_INO;
-	imap_off = schizo_imap_offset(ino);
 
 	/* Now build the IRQ bucket. */
-	imap = pbm->pbm_regs + imap_off;
-	imap += 4;
-
-	iclr_off = schizo_iclr_offset(ino);
-	iclr = pbm->pbm_regs + iclr_off;
-	iclr += 4;
+	imap = schizo_ino_to_imap(pbm, ino);
+	iclr = schizo_ino_to_iclr(pbm, ino);
 
 	/* On Schizo, no inofixup occurs.  This is because each
 	 * INO has it's own IMAP register.  On Psycho and Sabre
@@ -305,19 +313,17 @@
 			ign_fixup = (1 << 6);
 	}
 
-	bucket = __bucket(build_irq(ign_fixup, iclr, imap));
-	bucket->flags |= IBF_PCI;
+	virt_irq = build_irq(ign_fixup, iclr, imap, IBF_PCI);
 
 	if (pdev && pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) {
-		struct irq_desc *p = bucket->irq_info;
-
-		p->pre_handler = tomatillo_wsync_handler;
-		p->pre_handler_arg1 = ((pbm->chip_version <= 4) ?
-				       (void *) 1 : (void *) 0);
-		p->pre_handler_arg2 = (void *) pbm->sync_reg;
+		irq_install_pre_handler(virt_irq,
+					tomatillo_wsync_handler,
+					((pbm->chip_version <= 4) ?
+					 (void *) 1 : (void *) 0),
+					(void *) pbm->sync_reg);
 	}
 
-	return __irq(bucket);
+	return virt_irq;
 }
 
 /* SCHIZO error handling support. */
@@ -358,7 +364,6 @@
 static void schizo_clear_other_err_intr(struct pci_controller_info *p, int irq)
 {
 	struct pci_pbm_info *pbm;
-	struct ino_bucket *bucket;
 	unsigned long iclr;
 
 	/* Do not clear the interrupt for the other PCI bus.
@@ -376,11 +381,11 @@
 	else
 		pbm = &p->pbm_A;
 
-	irq = schizo_irq_build(pbm, NULL,
-			       (pbm->portid << 6) | (irq & IMAP_INO));
-	bucket = __bucket(irq);
-	iclr = bucket->iclr;
+	schizo_irq_build(pbm, NULL,
+			 (pbm->portid << 6) | (irq & IMAP_INO));
 
+	iclr = schizo_ino_to_iclr(pbm,
+				  (pbm->portid << 6) | (irq & IMAP_INO));
 	upa_writel(ICLR_IDLE, iclr);
 }
 
@@ -1125,7 +1130,6 @@
 {
 	struct pci_pbm_info *pbm;
 	unsigned int irq;
-	struct ino_bucket *bucket;
 	u64 tmp, err_mask, err_no_mask;
 
 	/* Build IRQs and register handlers. */
@@ -1137,8 +1141,7 @@
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_UE_INO));
 	upa_writel(tmp, (pbm->pbm_regs +
 			 schizo_imap_offset(SCHIZO_UE_INO) + 4));
 
@@ -1150,8 +1153,7 @@
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_CE_INO));
 	upa_writel(tmp, (pbm->pbm_regs +
 			 schizo_imap_offset(SCHIZO_CE_INO) + 4));
 
@@ -1164,8 +1166,8 @@
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) |
+						 SCHIZO_PCIERR_A_INO)));
 	upa_writel(tmp, (pbm->pbm_regs +
 			 schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4));
 
@@ -1178,8 +1180,8 @@
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) |
+						 SCHIZO_PCIERR_B_INO)));
 	upa_writel(tmp, (pbm->pbm_regs +
 			 schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4));
 
@@ -1191,8 +1193,8 @@
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) |
+						 SCHIZO_SERR_INO)));
 	upa_writel(tmp, (pbm->pbm_regs +
 			 schizo_imap_offset(SCHIZO_SERR_INO) + 4));
 
@@ -1263,7 +1265,6 @@
 {
 	struct pci_pbm_info *pbm;
 	unsigned int irq;
-	struct ino_bucket *bucket;
 	u64 tmp, err_mask, err_no_mask;
 
 	/* Build IRQs and register handlers. */
@@ -1275,8 +1276,7 @@
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_UE_INO));
 	upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4));
 
 	pbm = pbm_for_ino(p, SCHIZO_CE_INO);
@@ -1287,8 +1287,7 @@
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_CE_INO));
 	upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_CE_INO) + 4));
 
 	pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO);
@@ -1299,8 +1298,7 @@
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_PCIERR_A_INO));
 	upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4));
 
 	pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO);
@@ -1311,8 +1309,7 @@
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_PCIERR_B_INO));
 	upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4));
 
 	pbm = pbm_for_ino(p, SCHIZO_SERR_INO);
@@ -1323,8 +1320,7 @@
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_SERR_INO));
 	upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_SERR_INO) + 4));
 
 	/* Enable UE and CE interrupts for controller. */