summaryrefslogtreecommitdiff
path: root/arch/mips
diff options
context:
space:
mode:
authorPaul Burton <paul.burton@imgtec.com>2014-04-14 15:21:25 +0100
committerPaul Burton <paul.burton@imgtec.com>2014-05-28 16:20:32 +0100
commit5c399f6eb2c3911d94509f8f39bfd9aed6568f86 (patch)
tree0aac5de19c39ddcead0b206c12f73e3169651d17 /arch/mips
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')
-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)
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) {