Преглед на файлове

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>
Paul Burton преди 11 години
родител
ревизия
5c399f6eb2
променени са 1 файла, в които са добавени 28 реда и са изтрити 2 реда
  1. 28 2
      arch/mips/kernel/smp-cps.c

+ 28 - 2
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) {