diff options
author | Paul Burton <paul.burton@imgtec.com> | 2014-04-14 10:21:25 -0400 |
---|---|---|
committer | Paul Burton <paul.burton@imgtec.com> | 2014-05-28 11:20:32 -0400 |
commit | 5c399f6eb2c3911d94509f8f39bfd9aed6568f86 (patch) | |
tree | 0aac5de19c39ddcead0b206c12f73e3169651d17 | |
parent | 1d8f1f5a780abe51257f7d2e33142f33d983a9ed (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>
-rw-r--r-- | arch/mips/kernel/smp-cps.c | 30 |
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 | ||
89 | static void __init cps_prepare_cpus(unsigned int max_cpus) | 89 | static 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) { |