[SPARC64]: Fix uniprocessor IRQ targetting on SUN4V.
[deliverable/linux.git] / arch / sparc64 / kernel / irq.c
index bb0bb34555da4bbbc7a8eb258dc9a198d0cde107..712b16cdd5fbb30ffe5d7a30f43e85f924489bf1 100644 (file)
@@ -138,11 +138,48 @@ out_unlock:
        return 0;
 }
 
+extern unsigned long real_hard_smp_processor_id(void);
+
+static unsigned int sun4u_compute_tid(unsigned long imap, unsigned long cpuid)
+{
+       unsigned int tid;
+
+       if (this_is_starfire) {
+               tid = starfire_translate(imap, cpuid);
+               tid <<= IMAP_TID_SHIFT;
+               tid &= IMAP_TID_UPA;
+       } else {
+               if (tlb_type == cheetah || tlb_type == cheetah_plus) {
+                       unsigned long ver;
+
+                       __asm__ ("rdpr %%ver, %0" : "=r" (ver));
+                       if ((ver >> 32UL) == __JALAPENO_ID ||
+                           (ver >> 32UL) == __SERRANO_ID) {
+                               tid = cpuid << IMAP_TID_SHIFT;
+                               tid &= IMAP_TID_JBUS;
+                       } else {
+                               unsigned int a = cpuid & 0x1f;
+                               unsigned int n = (cpuid >> 5) & 0x1f;
+
+                               tid = ((a << IMAP_AID_SHIFT) |
+                                      (n << IMAP_NID_SHIFT));
+                               tid &= (IMAP_AID_SAFARI |
+                                       IMAP_NID_SAFARI);;
+                       }
+               } else {
+                       tid = cpuid << IMAP_TID_SHIFT;
+                       tid &= IMAP_TID_UPA;
+               }
+       }
+
+       return tid;
+}
+
 /* Now these are always passed a true fully specified sun4u INO. */
 void enable_irq(unsigned int irq)
 {
        struct ino_bucket *bucket = __bucket(irq);
-       unsigned long imap;
+       unsigned long imap, cpuid;
 
        imap = bucket->imap;
        if (imap == 0UL)
@@ -150,54 +187,25 @@ void enable_irq(unsigned int irq)
 
        preempt_disable();
 
+       /* This gets the physical processor ID, even on uniprocessor,
+        * so we can always program the interrupt target correctly.
+        */
+       cpuid = real_hard_smp_processor_id();
+
        if (tlb_type == hypervisor) {
                unsigned int ino = __irq_ino(irq);
-               int cpu = hard_smp_processor_id();
                int err;
 
-               err = sun4v_intr_settarget(ino, cpu);
+               err = sun4v_intr_settarget(ino, cpuid);
                if (err != HV_EOK)
-                       printk("sun4v_intr_settarget(%x,%d): err(%d)\n",
-                              ino, cpu, err);
+                       printk("sun4v_intr_settarget(%x,%lu): err(%d)\n",
+                              ino, cpuid, err);
                err = sun4v_intr_setenabled(ino, HV_INTR_ENABLED);
                if (err != HV_EOK)
                        printk("sun4v_intr_setenabled(%x): err(%d)\n",
                               ino, err);
        } else {
-               unsigned long tid;
-
-               if (tlb_type == cheetah || tlb_type == cheetah_plus) {
-                       unsigned long ver;
-
-                       __asm__ ("rdpr %%ver, %0" : "=r" (ver));
-                       if ((ver >> 32) == __JALAPENO_ID ||
-                           (ver >> 32) == __SERRANO_ID) {
-                               /* We set it to our JBUS ID. */
-                               __asm__ __volatile__("ldxa [%%g0] %1, %0"
-                                                    : "=r" (tid)
-                                                    : "i" (ASI_JBUS_CONFIG));
-                               tid = ((tid & (0x1fUL<<17)) << 9);
-                               tid &= IMAP_TID_JBUS;
-                       } else {
-                               /* We set it to our Safari AID. */
-                               __asm__ __volatile__("ldxa [%%g0] %1, %0"
-                                                    : "=r" (tid)
-                                                    : "i"(ASI_SAFARI_CONFIG));
-                               tid = ((tid & (0x3ffUL<<17)) << 9);
-                               tid &= IMAP_AID_SAFARI;
-                       }
-               } else if (this_is_starfire == 0) {
-                       /* We set it to our UPA MID. */
-                       __asm__ __volatile__("ldxa [%%g0] %1, %0"
-                                            : "=r" (tid)
-                                            : "i" (ASI_UPA_CONFIG));
-                       tid = ((tid & UPA_CONFIG_MID) << 9);
-                       tid &= IMAP_TID_UPA;
-               } else {
-                       tid = (starfire_translate(imap,
-                                                 smp_processor_id()) << 26);
-                       tid &= IMAP_TID_UPA;
-               }
+               unsigned int tid = sun4u_compute_tid(imap, cpuid);
 
                /* NOTE NOTE NOTE, IGN and INO are read-only, IGN is a product
                 * of this SYSIO's preconfigured IGN in the SYSIO Control
@@ -817,18 +825,8 @@ static int retarget_one_irq(struct irqaction *p, int goal_cpu)
                sun4v_intr_setenabled(ino, HV_INTR_ENABLED);
        } else {
                unsigned long imap = bucket->imap;
-               unsigned int tid;
+               unsigned int tid = sun4u_compute_tid(imap, goal_cpu);
 
-               if (tlb_type == cheetah || tlb_type == cheetah_plus) {
-                       tid = goal_cpu << 26;
-                       tid &= IMAP_AID_SAFARI;
-               } else if (this_is_starfire == 0) {
-                       tid = goal_cpu << 26;
-                       tid &= IMAP_TID_UPA;
-               } else {
-                       tid = (starfire_translate(imap, goal_cpu) << 26);
-                       tid &= IMAP_TID_UPA;
-               }
                upa_writel(tid | IMAP_VALID, imap);
        }
 
This page took 0.032624 seconds and 5 git commands to generate.