|
@@ -140,19 +140,42 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * A lot of BIOS fill in 10 (= no distance) everywhere. This messes
|
|
|
+ * up the NUMA heuristics which wants the local node to have a smaller
|
|
|
+ * distance than the others.
|
|
|
+ * Do some quick checks here and only use the SLIT if it passes.
|
|
|
+ */
|
|
|
+static __init int slit_valid(struct acpi_table_slit *slit)
|
|
|
+{
|
|
|
+ int i, j;
|
|
|
+ int d = slit->locality_count;
|
|
|
+ for (i = 0; i < d; i++) {
|
|
|
+ for (j = 0; j < d; j++) {
|
|
|
+ u8 val = slit->entry[d*i + j];
|
|
|
+ if (i == j) {
|
|
|
+ if (val != LOCAL_DISTANCE)
|
|
|
+ return 0;
|
|
|
+ } else if (val <= LOCAL_DISTANCE)
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
static int __init acpi_parse_slit(struct acpi_table_header *table)
|
|
|
{
|
|
|
struct acpi_table_slit *slit;
|
|
|
- u32 localities;
|
|
|
|
|
|
if (!table)
|
|
|
return -EINVAL;
|
|
|
|
|
|
slit = (struct acpi_table_slit *)table;
|
|
|
|
|
|
- /* downcast just for %llu vs %lu for i386/ia64 */
|
|
|
- localities = (u32) slit->locality_count;
|
|
|
-
|
|
|
+ if (!slit_valid(slit)) {
|
|
|
+ printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used.\n");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
acpi_numa_slit_init(slit);
|
|
|
|
|
|
return 0;
|