aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorFenghua Yu <fenghua.yu@intel.com>2008-06-09 19:48:18 -0400
committerLen Brown <len.brown@intel.com>2008-06-11 19:13:46 -0400
commit39b8931b5cad9a7cbcd2394a40a088311e783a82 (patch)
tree4db8369a3d5cc54a61942f38de9eb392e7e5bc60 /drivers/acpi
parent36d872a370d3d10e5a7faa9dcacce744260fb13b (diff)
ACPI: handle invalid ACPI SLIT table
This is a SLIT sanity checking patch. It moves slit_valid() function to generic ACPI code and does sanity checking for both x86 and ia64. It sets up node_distance with LOCAL_DISTANCE and REMOTE_DISTANCE when hitting invalid SLIT table on ia64. It also cleans up unused variable localities in acpi_parse_slit() on x86. Signed-off-by: Fenghua Yu <fenghua.yu@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/numa.c31
1 files changed, 27 insertions, 4 deletions
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 5d59cb33b1a5..658e5f3abae0 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -140,19 +140,42 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header)
140 } 140 }
141} 141}
142 142
143/*
144 * A lot of BIOS fill in 10 (= no distance) everywhere. This messes
145 * up the NUMA heuristics which wants the local node to have a smaller
146 * distance than the others.
147 * Do some quick checks here and only use the SLIT if it passes.
148 */
149static __init int slit_valid(struct acpi_table_slit *slit)
150{
151 int i, j;
152 int d = slit->locality_count;
153 for (i = 0; i < d; i++) {
154 for (j = 0; j < d; j++) {
155 u8 val = slit->entry[d*i + j];
156 if (i == j) {
157 if (val != LOCAL_DISTANCE)
158 return 0;
159 } else if (val <= LOCAL_DISTANCE)
160 return 0;
161 }
162 }
163 return 1;
164}
165
143static int __init acpi_parse_slit(struct acpi_table_header *table) 166static int __init acpi_parse_slit(struct acpi_table_header *table)
144{ 167{
145 struct acpi_table_slit *slit; 168 struct acpi_table_slit *slit;
146 u32 localities;
147 169
148 if (!table) 170 if (!table)
149 return -EINVAL; 171 return -EINVAL;
150 172
151 slit = (struct acpi_table_slit *)table; 173 slit = (struct acpi_table_slit *)table;
152 174
153 /* downcast just for %llu vs %lu for i386/ia64 */ 175 if (!slit_valid(slit)) {
154 localities = (u32) slit->locality_count; 176 printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used.\n");
155 177 return -EINVAL;
178 }
156 acpi_numa_slit_init(slit); 179 acpi_numa_slit_init(slit);
157 180
158 return 0; 181 return 0;