[SPARC64]: Fix virq decomposition.

The dev_handle and dev_ino fields don't match up exactly to
the traditional IMAP_IGN and IMAP_INO masks.

So store them away in a table and look them up directly.

Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index edd530f..db31bf6 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -87,7 +87,11 @@
  */
 #define irq_work(__cpu)	&(trap_block[(__cpu)].irq_worklist)
 
-static unsigned int virt_to_real_irq_table[NR_IRQS];
+static struct {
+	unsigned int irq;
+	unsigned int dev_handle;
+	unsigned int dev_ino;
+} virt_to_real_irq_table[NR_IRQS];
 
 static unsigned char virt_irq_alloc(unsigned int real_irq)
 {
@@ -96,7 +100,7 @@
 	BUILD_BUG_ON(NR_IRQS >= 256);
 
 	for (ent = 1; ent < NR_IRQS; ent++) {
-		if (!virt_to_real_irq_table[ent])
+		if (!virt_to_real_irq_table[ent].irq)
 			break;
 	}
 	if (ent >= NR_IRQS) {
@@ -104,7 +108,7 @@
 		return 0;
 	}
 
-	virt_to_real_irq_table[ent] = real_irq;
+	virt_to_real_irq_table[ent].irq = real_irq;
 
 	return ent;
 }
@@ -117,8 +121,8 @@
 	if (virt_irq >= NR_IRQS)
 		return;
 
-	real_irq = virt_to_real_irq_table[virt_irq];
-	virt_to_real_irq_table[virt_irq] = 0;
+	real_irq = virt_to_real_irq_table[virt_irq].irq;
+	virt_to_real_irq_table[virt_irq].irq = 0;
 
 	__bucket(real_irq)->virt_irq = 0;
 }
@@ -126,7 +130,7 @@
 
 static unsigned int virt_to_real_irq(unsigned char virt_irq)
 {
-	return virt_to_real_irq_table[virt_irq];
+	return virt_to_real_irq_table[virt_irq].irq;
 }
 
 /*
@@ -418,7 +422,6 @@
 static void sun4v_virq_enable(unsigned int virt_irq)
 {
 	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
-	unsigned int ino = bucket - &ivector_table[0];
 
 	if (likely(bucket)) {
 		unsigned long cpuid, dev_handle, dev_ino;
@@ -426,8 +429,8 @@
 
 		cpuid = irq_choose_cpu(virt_irq);
 
-		dev_handle = ino & IMAP_IGN;
-		dev_ino = ino & IMAP_INO;
+		dev_handle = virt_to_real_irq_table[virt_irq].dev_handle;
+		dev_ino = virt_to_real_irq_table[virt_irq].dev_ino;
 
 		err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid);
 		if (err != HV_EOK)
@@ -452,7 +455,6 @@
 static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask)
 {
 	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
-	unsigned int ino = bucket - &ivector_table[0];
 
 	if (likely(bucket)) {
 		unsigned long cpuid, dev_handle, dev_ino;
@@ -460,8 +462,8 @@
 
 		cpuid = irq_choose_cpu(virt_irq);
 
-		dev_handle = ino & IMAP_IGN;
-		dev_ino = ino & IMAP_INO;
+		dev_handle = virt_to_real_irq_table[virt_irq].dev_handle;
+		dev_ino = virt_to_real_irq_table[virt_irq].dev_ino;
 
 		err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid);
 		if (err != HV_EOK)
@@ -474,14 +476,13 @@
 static void sun4v_virq_disable(unsigned int virt_irq)
 {
 	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
-	unsigned int ino = bucket - &ivector_table[0];
 
 	if (likely(bucket)) {
 		unsigned long dev_handle, dev_ino;
 		int err;
 
-		dev_handle = ino & IMAP_IGN;
-		dev_ino = ino & IMAP_INO;
+		dev_handle = virt_to_real_irq_table[virt_irq].dev_handle;
+		dev_ino = virt_to_real_irq_table[virt_irq].dev_ino;
 
 		err = sun4v_vintr_set_valid(dev_handle, dev_ino,
 					    HV_INTR_DISABLED);
@@ -495,7 +496,6 @@
 static void sun4v_virq_end(unsigned int virt_irq)
 {
 	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
-	unsigned int ino = bucket - &ivector_table[0];
 	struct irq_desc *desc = irq_desc + virt_irq;
 
 	if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
@@ -505,8 +505,8 @@
 		unsigned long dev_handle, dev_ino;
 		int err;
 
-		dev_handle = ino & IMAP_IGN;
-		dev_ino = ino & IMAP_INO;
+		dev_handle = virt_to_real_irq_table[virt_irq].dev_handle;
+		dev_ino = virt_to_real_irq_table[virt_irq].dev_ino;
 
 		err = sun4v_vintr_set_state(dev_handle, dev_ino,
 					    HV_INTR_STATE_IDLE);
@@ -700,6 +700,7 @@
 unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
 {
 	unsigned long sysino, hv_err;
+	unsigned int virq;
 
 	BUG_ON(devhandle & devino);
 
@@ -713,7 +714,12 @@
 		prom_halt();
 	}
 
-	return sun4v_build_common(sysino, &sun4v_virq);
+	virq = sun4v_build_common(sysino, &sun4v_virq);
+
+	virt_to_real_irq_table[virq].dev_handle = devhandle;
+	virt_to_real_irq_table[virq].dev_ino = devino;
+
+	return virq;
 }
 
 #ifdef CONFIG_PCI_MSI