diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index f5c8a293979f..bd332e41532f 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -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 diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index bb0bb34555da..712b16cdd5fb 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -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); } diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index 9b0c409d5b6a..77066f1bbe2f 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -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) diff --git a/include/asm-sparc64/cpudata.h b/include/asm-sparc64/cpudata.h index 771aa94dfd95..84656f1895cd 100644 --- a/include/asm-sparc64/cpudata.h +++ b/include/asm-sparc64/cpudata.h @@ -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 -#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; \ diff --git a/include/asm-sparc64/irq.h b/include/asm-sparc64/irq.h index 529a9df1ad43..de33d6e1afb5 100644 --- a/include/asm-sparc64/irq.h +++ b/include/asm-sparc64/irq.h @@ -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*/