Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 1209

kernel-2.6.18-194.11.1.el5.src.rpm

From: Luming Yu <luyu@redhat.com>
Date: Fri, 20 Jun 2008 15:48:15 +0800
Subject: [ia64] handle invalid ACPI SLIT table
Message-id: 485B60BF.9030100@redhat.com
O-Subject: [RHEL 5.3 PATCH] bz 451591: Handle invalid ACPI SLIT table
Bugzilla: 451591
RH-Acked-by: Prarit Bhargava <prarit@redhat.com>
RH-Acked-by: Pete Zaitcev <zaitcev@redhat.com>

bz 451591

Description of problem:

    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.

Upstream status:
39b8931b5cad9a7cbcd2394a40a088311e783a82

Testing status:

Boot fine on tiger4 and Cold fusion, and nothing unusual found.
I don't see "ACPI: SLIT table looks invalid. Not used" in dmesgs from my testing.
It seems to indicate that I don't have box with broken SLIT, or even just NO SLIT.

Please review, and ACK.

Thanks,
Luming

diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 97c2fbd..cdf5be9 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -456,7 +456,6 @@ void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
 		printk(KERN_ERR
 		       "ACPI 2.0 SLIT: size mismatch: %d expected, %d actual\n",
 		       len, slit->header.length);
-		memset(numa_slit, 10, sizeof(numa_slit));
 		return;
 	}
 	slit_table = slit;
@@ -566,8 +565,14 @@ void __init acpi_numa_arch_fixup(void)
 	printk(KERN_INFO "Number of memory chunks in system = %d\n",
 	       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;
+	}
+
 	memset(numa_slit, -1, sizeof(numa_slit));
 	for (i = 0; i < slit_table->localities; i++) {
 		if (!pxm_bit_test(i))
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c
index 54c471c..371241a 100644
--- a/arch/x86_64/mm/srat.c
+++ b/arch/x86_64/mm/srat.c
@@ -89,36 +89,9 @@ static __init inline int srat_disabled(void)
 	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->localities;
-	for (i = 0; i < d; i++) {
-		for (j = 0; j < d; j++)  {
-			u8 val = slit->entry[d*i + j];
-			if (i == j) {
-				if (val != 10)
-					return 0;
-			} else if (val <= 10)
-				return 0;
-		}
-	}
-	return 1;
-}
-
 /* Callback for SLIT parsing */
 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;
 }
 
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index e5e448e..56b1dbe 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -141,19 +141,42 @@ void __init acpi_table_print_srat_entry(acpi_table_entry_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->localities;
+	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(unsigned long phys_addr, unsigned long size)
 {
 	struct acpi_table_slit *slit;
-	u32 localities;
 
 	if (!phys_addr || !size)
 		return -EINVAL;
 
 	slit = (struct acpi_table_slit *)__va(phys_addr);
 
-	/* downcast just for %llu vs %lu for i386/ia64  */
-	localities = (u32) slit->localities;
-
+	if (!slit_valid(slit)) {
+		printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used.\n");
+		return -EINVAL;
+	}
 	acpi_numa_slit_init(slit);
 
 	return 0;
diff --git a/include/linux/topology.h b/include/linux/topology.h
index b47ae36..5ccdb15 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -52,10 +52,11 @@
 
 void arch_update_cpu_topology(void);
 
-#ifndef node_distance
 /* Conform to ACPI 2.0 SLIT distance definitions */
 #define LOCAL_DISTANCE		10
 #define REMOTE_DISTANCE		20
+
+#ifndef node_distance
 #define node_distance(from,to)	((from) == (to) ? LOCAL_DISTANCE : REMOTE_DISTANCE)
 #endif
 #ifndef RECLAIM_DISTANCE