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@xxxxxxxxxx> --- arch/mips/kernel/smp-cps.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 4125858..4e2346d 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) (unsigned long)entry_code); /* 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) { -- 1.8.5.3