Attempt to detect if the hardware is UP hardware, and use the optional
UP specific processors functions in struct proc_info_list if available.

Signed-off-by: Tony Lindgren <[email protected]>
---
 arch/arm/include/asm/procinfo.h |    6 +++++
 arch/arm/include/asm/smp_plat.h |    9 ++++++++
 arch/arm/kernel/setup.c         |   45 +++++++++++++++++++++++++++++++++++++++
 arch/arm/mm/mmu.c               |   20 ++++++++++-------
 4 files changed, 71 insertions(+), 9 deletions(-)

diff --git a/arch/arm/include/asm/procinfo.h b/arch/arm/include/asm/procinfo.h
index ca52e58..962d01e 100644
--- a/arch/arm/include/asm/procinfo.h
+++ b/arch/arm/include/asm/procinfo.h
@@ -40,6 +40,12 @@ struct proc_info_list {
        struct cpu_tlb_fns      *tlb;
        struct cpu_user_fns     *user;
        struct cpu_cache_fns    *cache;
+
+#ifdef CONFIG_SMP_ON_UP
+       struct processor        *proc_up;
+       struct cpu_tlb_fns      *tlb_up;
+       struct cpu_cache_fns    *cache_up;
+#endif
 };
 
 #else  /* __KERNEL__ */
diff --git a/arch/arm/include/asm/smp_plat.h b/arch/arm/include/asm/smp_plat.h
index e621530..1c2f587 100644
--- a/arch/arm/include/asm/smp_plat.h
+++ b/arch/arm/include/asm/smp_plat.h
@@ -18,4 +18,13 @@ static inline int cache_ops_need_broadcast(void)
        return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 1;
 }
 
+#ifdef CONFIG_SMP_ON_UP
+extern int smp_on_up(void);
+#else
+static inline int smp_on_up(void)
+{
+       return 0;
+}
+#endif
+
 #endif
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index d5231ae..5f3606c 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -289,6 +289,50 @@ static void __init feat_v6_fixup(void)
                elf_hwcap &= ~HWCAP_TLS;
 }
 
+#ifdef CONFIG_SMP_ON_UP
+
+static int _smp_on_up;
+
+int smp_on_up(void)
+{
+       return _smp_on_up;
+}
+
+static void __init smp_on_up_fixup(struct proc_info_list *list)
+{
+       int id;
+
+       id = read_cpuid_id() & 0xff0f0000;
+       if ((id == 0x41070000) || (id == 0x410f0000)) {
+               int mpidr;
+
+               asm volatile("mrc p15, 0, %0, c0, c0, 5" : "=r" (mpidr));
+               mpidr >>= 30;
+
+               /* SMP hardware? */
+               if (!((mpidr == 0) || (mpidr == 3)))
+                       return;
+       }
+
+       _smp_on_up = 1;
+
+       pr_info("CPU: SMP kernel on UP hardware\n");
+
+       if (list->proc_up)
+               processor = *list->proc_up;
+
+       if (list->tlb_up)
+               cpu_tlb = *list->tlb_up;
+
+       if (list->cache_up)
+               cpu_cache = *list->cache_up;
+}
+#else
+static inline void smp_on_up_fixup(struct proc_info_list *list)
+{
+}
+#endif
+
 static void __init setup_processor(void)
 {
        struct proc_info_list *list;
@@ -331,6 +375,7 @@ static void __init setup_processor(void)
        elf_hwcap &= ~HWCAP_THUMB;
 #endif
 
+       smp_on_up_fixup(list);
        feat_v6_fixup();
 
        cacheid_init();
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 6e1c4f6..f320901 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -430,15 +430,17 @@ static void __init build_mem_type_table(void)
                /*
                 * Mark memory with the "shared" attribute for SMP systems
                 */
-               user_pgprot |= L_PTE_SHARED;
-               kern_pgprot |= L_PTE_SHARED;
-               vecs_pgprot |= L_PTE_SHARED;
-               mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_S;
-               mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED;
-               mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S;
-               mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED;
-               mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
-               mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S;
+               if (!smp_on_up()) {
+                       user_pgprot |= L_PTE_SHARED;
+                       kern_pgprot |= L_PTE_SHARED;
+                       vecs_pgprot |= L_PTE_SHARED;
+                       mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_S;
+                       mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED;
+                       mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S;
+                       mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED;
+                       mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
+                       mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S;
+               }
 #endif
        }
 

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to