diff options
-rw-r--r-- | arch/x86_64/mm/srat.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c index 33340bd1e328..9f69d28652f8 100644 --- a/arch/x86_64/mm/srat.c +++ b/arch/x86_64/mm/srat.c | |||
@@ -91,9 +91,36 @@ static __init inline int srat_disabled(void) | |||
91 | return numa_off || acpi_numa < 0; | 91 | return numa_off || acpi_numa < 0; |
92 | } | 92 | } |
93 | 93 | ||
94 | /* | ||
95 | * A lot of BIOS fill in 10 (= no distance) everywhere. This messes | ||
96 | * up the NUMA heuristics which wants the local node to have a smaller | ||
97 | * distance than the others. | ||
98 | * Do some quick checks here and only use the SLIT if it passes. | ||
99 | */ | ||
100 | static __init int slit_valid(struct acpi_table_slit *slit) | ||
101 | { | ||
102 | int i, j; | ||
103 | int d = slit->localities; | ||
104 | for (i = 0; i < d; i++) { | ||
105 | for (j = 0; j < d; j++) { | ||
106 | u8 val = slit->entry[d*i + j]; | ||
107 | if (i == j) { | ||
108 | if (val != 10) | ||
109 | return 0; | ||
110 | } else if (val <= 10) | ||
111 | return 0; | ||
112 | } | ||
113 | } | ||
114 | return 1; | ||
115 | } | ||
116 | |||
94 | /* Callback for SLIT parsing */ | 117 | /* Callback for SLIT parsing */ |
95 | void __init acpi_numa_slit_init(struct acpi_table_slit *slit) | 118 | void __init acpi_numa_slit_init(struct acpi_table_slit *slit) |
96 | { | 119 | { |
120 | if (!slit_valid(slit)) { | ||
121 | printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used.\n"); | ||
122 | return; | ||
123 | } | ||
97 | acpi_slit = slit; | 124 | acpi_slit = slit; |
98 | } | 125 | } |
99 | 126 | ||