diff options
author | Paul Burton <paul.burton@imgtec.com> | 2014-04-14 15:21:25 +0100 |
---|---|---|
committer | Paul Burton <paul.burton@imgtec.com> | 2014-05-28 16:20:32 +0100 |
commit | 5c399f6eb2c3911d94509f8f39bfd9aed6568f86 (patch) | |
tree | 0aac5de19c39ddcead0b206c12f73e3169651d17 /arch/mips/kernel | |
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>
Diffstat (limited to 'arch/mips/kernel')
-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 3c30891fc78..e2f78b34ff9 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) static void __init cps_prepare_cpus(unsigned int max_cpus) { - unsigned ncores, core_vpes, c; + unsigned ncores, core_vpes, c, cca; + bool cca_unsuitable; u32 *entry_code; mips_mt_set_cpuoptions(); + /* Detect whether the CCA is unsuited to multi-core SMP */ + cca = read_c0_config() & CONF_CM_CMASK; + switch (cca) { + case 0x4: /* CWBE */ + case 0x5: /* CWB */ + /* The CCA is coherent, multi-core is fine */ + cca_unsuitable = false; + break; + + default: + /* CCA is not coherent, multi-core is not usable */ + cca_unsuitable = true; + } + + /* Warn the user if the CCA prevents multi-core */ + ncores = mips_cm_numcores(); + if (cca_unsuitable && ncores > 1) { + pr_warn("Using only one core due to unsuitable CCA 0x%x\n", + cca); + + for_each_present_cpu(c) { + if (cpu_data[c].core) + set_cpu_present(c, false); + } + } + /* Patch the start of mips_cps_core_entry to provide the CM base */ entry_code = (u32 *)&mips_cps_core_entry; UASM_i_LA(&entry_code, 3, (long)mips_cm_base); @@ -100,7 +127,6 @@ static void __init cps_prepare_cpus(unsigned int max_cpus) (void *)entry_code - (void *)&mips_cps_core_entry); /* Allocate core boot configuration structs */ - ncores = mips_cm_numcores(); mips_cps_core_bootcfg = kcalloc(ncores, sizeof(*mips_cps_core_bootcfg), GFP_KERNEL); if (!mips_cps_core_bootcfg) { |