[SPARC64]: Fix uniprocessor IRQ targetting on SUN4V.
authorDavid S. Miller <davem@sunset.davemloft.net>
Fri, 17 Feb 2006 16:38:06 +0000 (08:38 -0800)
committerDavid S. Miller <davem@sunset.davemloft.net>
Mon, 20 Mar 2006 09:13:24 +0000 (01:13 -0800)
We need to use the real hardware processor ID when
targetting interrupts, not the "define to 0" thing
the uniprocessor build gives us.

Also, fill in the Node-ID and Agent-ID fields properly
on sun4u/Safari.

Signed-off-by: David S. Miller <davem@davemloft.net>
arch/sparc64/kernel/entry.S
arch/sparc64/kernel/irq.c
arch/sparc64/kernel/setup.c
include/asm-sparc64/cpudata.h
include/asm-sparc64/irq.h

index f5c8a29..bd332e4 100644 (file)
@@ -1692,10 +1692,12 @@ __flushw_user:
 #ifdef CONFIG_SMP
        .globl          hard_smp_processor_id
 hard_smp_processor_id:
+#endif
+       .globl          real_hard_smp_processor_id
+real_hard_smp_processor_id:
        __GET_CPUID(%o0)
        retl
         nop
-#endif
 
        /* %o0: devhandle
         * %o1: devino
index bb0bb34..712b16c 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);
        }
 
index 9b0c409..77066f1 100644 (file)
@@ -222,7 +222,6 @@ static struct pt_regs fake_swapper_regs = { { 0, }, 0, 0, 0, 0 };
 
 static void __init per_cpu_patch(void)
 {
-#ifdef CONFIG_SMP
        struct cpuid_patch_entry *p;
        unsigned long ver;
        int is_jbus;
@@ -233,8 +232,8 @@ static void __init per_cpu_patch(void)
        is_jbus = 0;
        if (tlb_type != hypervisor) {
                __asm__ ("rdpr %%ver, %0" : "=r" (ver));
-               is_jbus = ((ver >> 32) == __JALAPENO_ID ||
-                          (ver >> 32) == __SERRANO_ID);
+               is_jbus = ((ver >> 32UL) == __JALAPENO_ID ||
+                          (ver >> 32UL) == __SERRANO_ID);
        }
 
        p = &__cpuid_patch;
@@ -279,7 +278,6 @@ static void __init per_cpu_patch(void)
 
                p++;
        }
-#endif
 }
 
 static void __init sun4v_patch(void)
index 771aa94..84656f1 100644 (file)
@@ -80,7 +80,6 @@ extern struct trap_per_cpu trap_block[NR_CPUS];
 extern void init_cur_cpu_trap(struct thread_info *);
 extern void setup_tba(void);
 
-#ifdef CONFIG_SMP
 struct cpuid_patch_entry {
        unsigned int    addr;
        unsigned int    cheetah_safari[4];
@@ -89,7 +88,6 @@ struct cpuid_patch_entry {
        unsigned int    sun4v[4];
 };
 extern struct cpuid_patch_entry __cpuid_patch, __cpuid_patch_end;
-#endif
 
 struct sun4v_1insn_patch_entry {
        unsigned int    addr;
@@ -123,8 +121,6 @@ extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch,
 
 #include <asm/scratchpad.h>
 
-#ifdef CONFIG_SMP
-
 #define __GET_CPUID(REG)                               \
        /* Spitfire implementation (default). */        \
 661:   ldxa            [%g0] ASI_UPA_CONFIG, REG;      \
@@ -156,6 +152,8 @@ extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch,
        nop;                                            \
        .previous;
 
+#ifdef CONFIG_SMP
+
 #define TRAP_LOAD_TRAP_BLOCK(DEST, TMP)                \
        __GET_CPUID(TMP)                        \
        sethi   %hi(trap_block), DEST;          \
index 529a9df..de33d6e 100644 (file)
@@ -72,8 +72,11 @@ struct ino_bucket {
 #define IMAP_VALID             0x80000000      /* IRQ Enabled          */
 #define IMAP_TID_UPA           0x7c000000      /* UPA TargetID         */
 #define IMAP_TID_JBUS          0x7c000000      /* JBUS TargetID        */
+#define IMAP_TID_SHIFT         26
 #define IMAP_AID_SAFARI                0x7c000000      /* Safari AgentID       */
+#define IMAP_AID_SHIFT         26
 #define IMAP_NID_SAFARI                0x03e00000      /* Safari NodeID        */
+#define IMAP_NID_SHIFT         21
 #define IMAP_IGN               0x000007c0      /* IRQ Group Number     */
 #define IMAP_INO               0x0000003f      /* IRQ Number           */
 #define IMAP_INR               0x000007ff      /* Full interrupt number*/