aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel
diff options
context:
space:
mode:
authorPaul Burton <paul.burton@imgtec.com>2014-04-14 10:21:25 -0400
committerPaul Burton <paul.burton@imgtec.com>2014-05-28 11:20:32 -0400
commit5c399f6eb2c3911d94509f8f39bfd9aed6568f86 (patch)
tree0aac5de19c39ddcead0b206c12f73e3169651d17 /arch/mips/kernel
parent1d8f1f5a780abe51257f7d2e33142f33d983a9ed (diff)
MIPS: smp-cps: prevent multi-core SMP with unsuitable CCA
If the user or bootloader sets the CCA to a value which is not suited for multi-core SMP (ie. anything non-coherent) then limit the system to using only a single core and warn the user. Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r--arch/mips/kernel/smp-cps.c30
1 files changed, 28 insertions, 2 deletions
diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c
index 3c30891fc789..e2f78b34ff93 100644
--- a/arch/mips/kernel/smp-cps.c
+++ b/arch/mips/kernel/smp-cps.c
@@ -88,11 +88,38 @@ static void __init cps_smp_setup(void)
88 88
89static void __init cps_prepare_cpus(unsigned int max_cpus) 89static void __init cps_prepare_cpus(unsigned int max_cpus)
90{ 90{
91 unsigned ncores, core_vpes, c; 91 unsigned ncores, core_vpes, c, cca;
92 bool cca_unsuitable;
92 u32 *entry_code; 93 u32 *entry_code;
93 94
94 mips_mt_set_cpuoptions(); 95 mips_mt_set_cpuoptions();
95 96
97 /* Detect whether the CCA is unsuited to multi-core SMP */
98 cca = read_c0_config() & CONF_CM_CMASK;
99 switch (cca) {
100 case 0x4: /* CWBE */
101 case 0x5: /* CWB */
102 /* The CCA is coherent, multi-core is fine */
103 cca_unsuitable = false;
104 break;
105
106 default:
107 /* CCA is not coherent, multi-core is not usable */
108 cca_unsuitable = true;
109 }
110
111 /* Warn the user if the CCA prevents multi-core */
112 ncores = mips_cm_numcores();
113 if (cca_unsuitable && ncores > 1) {
114 pr_warn("Using only one core due to unsuitable CCA 0x%x\n",
115 cca);
116
117 for_each_present_cpu(c) {
118 if (cpu_data[c].core)
119 set_cpu_present(c, false);
120 }
121 }
122
96 /* Patch the start of mips_cps_core_entry to provide the CM base */ 123 /* Patch the start of mips_cps_core_entry to provide the CM base */
97 entry_code = (u32 *)&mips_cps_core_entry; 124 entry_code = (u32 *)&mips_cps_core_entry;
98 UASM_i_LA(&entry_code, 3, (long)mips_cm_base); 125 UASM_i_LA(&entry_code, 3, (long)mips_cm_base);
@@ -100,7 +127,6 @@ static void __init cps_prepare_cpus(unsigned int max_cpus)
100 (void *)entry_code - (void *)&mips_cps_core_entry); 127 (void *)entry_code - (void *)&mips_cps_core_entry);
101 128
102 /* Allocate core boot configuration structs */ 129 /* Allocate core boot configuration structs */
103 ncores = mips_cm_numcores();
104 mips_cps_core_bootcfg = kcalloc(ncores, sizeof(*mips_cps_core_bootcfg), 130 mips_cps_core_bootcfg = kcalloc(ncores, sizeof(*mips_cps_core_bootcfg),
105 GFP_KERNEL); 131 GFP_KERNEL);
106 if (!mips_cps_core_bootcfg) { 132 if (!mips_cps_core_bootcfg) {