[PATCH] i386: Consolidate modern APIC handling

AMD systems have a modern APIC that supports 8 bit IDs, but
don't have a XAPIC version number.  Add a new "modern_apic"
subfunction that handles this correctly and use it (nearly)
everywhere where XAPIC is tested for.

I removed one wart: the code specified that external APICs
would use an 8bit APIC ID. But I checked a real 82093 data sheet
and it says clearly that they only use 4bit. So I removed
this special case since it would a bit awkward to implement now.

I removed the valid APIC tests in mptable parsing completely. On any modern
system they only check against the full field width (8bit) anyways
and are no-ops. This also fixes them doing the wrong thing
on >8 core Opterons.

This makes i386 boot again on 16 core Opterons.

Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index 6273bf7..254cee9 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -62,6 +62,18 @@
 
 static void apic_pm_activate(void);
 
+int modern_apic(void)
+{
+	unsigned int lvr, version;
+	/* AMD systems use old APIC versions, so check the CPU */
+	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+		boot_cpu_data.x86 >= 0xf)
+		return 1;
+	lvr = apic_read(APIC_LVR);
+	version = GET_APIC_VERSION(lvr);
+	return version >= 0x14;
+}
+
 /*
  * 'what should we do if we get a hw irq event on an illegal vector'.
  * each architecture has to answer this themselves.
@@ -119,10 +131,7 @@
 
 int get_physical_broadcast(void)
 {
-	unsigned int lvr, version;
-	lvr = apic_read(APIC_LVR);
-	version = GET_APIC_VERSION(lvr);
-	if (!APIC_INTEGRATED(version) || version >= 0x14)
+	if (modern_apic())
 		return 0xff;
 	else
 		return 0xf;
@@ -349,9 +358,9 @@
 
 void __init sync_Arb_IDs(void)
 {
-	/* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 */
-	unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR));
-	if (ver >= 0x14)	/* P4 or higher */
+	/* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1
+	   And not needed on AMD */
+	if (modern_apic())
 		return;
 	/*
 	 * Wait for idle.
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
index 8d8aa9d..db12017 100644
--- a/arch/i386/kernel/mpparse.c
+++ b/arch/i386/kernel/mpparse.c
@@ -110,21 +110,6 @@
 static int mpc_record; 
 static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __initdata;
 
-#ifdef CONFIG_X86_NUMAQ
-static int MP_valid_apicid(int apicid, int version)
-{
-	return hweight_long(apicid & 0xf) == 1 && (apicid >> 4) != 0xf;
-}
-#else
-static int MP_valid_apicid(int apicid, int version)
-{
-	if (version >= 0x14)
-		return apicid < 0xff;
-	else
-		return apicid < 0xf;
-}
-#endif
-
 static void __devinit MP_processor_info (struct mpc_config_processor *m)
 {
  	int ver, apicid;
@@ -190,12 +175,6 @@
 
 	ver = m->mpc_apicver;
 
-	if (!MP_valid_apicid(apicid, ver)) {
-		printk(KERN_WARNING "Processor #%d INVALID. (Max ID: %d).\n",
-			m->mpc_apicid, MAX_APICS);
-		return;
-	}
-
 	/*
 	 * Validate version
 	 */
diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h
index ff9ac8d..288233f 100644
--- a/include/asm-i386/apic.h
+++ b/include/asm-i386/apic.h
@@ -139,6 +139,8 @@
 
 extern int timer_over_8254;
 
+extern int modern_apic(void);
+
 #else /* !CONFIG_X86_LOCAL_APIC */
 static inline void lapic_shutdown(void) { }