mirror of
https://github.com/adulau/aha.git
synced 2025-01-04 07:03:38 +00:00
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>
This commit is contained in:
parent
36d872a370
commit
39b8931b5c
3 changed files with 34 additions and 33 deletions
|
@ -465,7 +465,6 @@ void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
|
||||||
printk(KERN_ERR
|
printk(KERN_ERR
|
||||||
"ACPI 2.0 SLIT: size mismatch: %d expected, %d actual\n",
|
"ACPI 2.0 SLIT: size mismatch: %d expected, %d actual\n",
|
||||||
len, slit->header.length);
|
len, slit->header.length);
|
||||||
memset(numa_slit, 10, sizeof(numa_slit));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
slit_table = slit;
|
slit_table = slit;
|
||||||
|
@ -574,8 +573,14 @@ void __init acpi_numa_arch_fixup(void)
|
||||||
printk(KERN_INFO "Number of memory chunks in system = %d\n",
|
printk(KERN_INFO "Number of memory chunks in system = %d\n",
|
||||||
num_node_memblks);
|
num_node_memblks);
|
||||||
|
|
||||||
if (!slit_table)
|
if (!slit_table) {
|
||||||
|
for (i = 0; i < MAX_NUMNODES; i++)
|
||||||
|
for (j = 0; j < MAX_NUMNODES; j++)
|
||||||
|
node_distance(i, j) = i == j ? LOCAL_DISTANCE :
|
||||||
|
REMOTE_DISTANCE;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
memset(numa_slit, -1, sizeof(numa_slit));
|
memset(numa_slit, -1, sizeof(numa_slit));
|
||||||
for (i = 0; i < slit_table->locality_count; i++) {
|
for (i = 0; i < slit_table->locality_count; i++) {
|
||||||
if (!pxm_bit_test(i))
|
if (!pxm_bit_test(i))
|
||||||
|
|
|
@ -97,36 +97,9 @@ static __init inline int srat_disabled(void)
|
||||||
return numa_off || acpi_numa < 0;
|
return numa_off || acpi_numa < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Callback for SLIT parsing */
|
/* Callback for SLIT parsing */
|
||||||
void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
|
void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
|
||||||
{
|
{
|
||||||
if (!slit_valid(slit)) {
|
|
||||||
printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
acpi_slit = slit;
|
acpi_slit = slit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
static int __init acpi_parse_slit(struct acpi_table_header *table)
|
||||||
{
|
{
|
||||||
struct acpi_table_slit *slit;
|
struct acpi_table_slit *slit;
|
||||||
u32 localities;
|
|
||||||
|
|
||||||
if (!table)
|
if (!table)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
slit = (struct acpi_table_slit *)table;
|
slit = (struct acpi_table_slit *)table;
|
||||||
|
|
||||||
/* downcast just for %llu vs %lu for i386/ia64 */
|
if (!slit_valid(slit)) {
|
||||||
localities = (u32) slit->locality_count;
|
printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used.\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
acpi_numa_slit_init(slit);
|
acpi_numa_slit_init(slit);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in a new issue