patch-2.4.0-test8 linux/arch/i386/kernel/io_apic.c

Next file: linux/arch/i386/kernel/mca.c
Previous file: linux/arch/i386/kernel/apic.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test7/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c
@@ -982,7 +982,10 @@
 static void __init setup_ioapic_ids_from_mpc (void)
 {
 	struct IO_APIC_reg_00 reg_00;
+	unsigned long phys_id_present_map = phys_cpu_present_map;
 	int apic;
+	int i;
+	unsigned char old_id;
 
 	/*
 	 * Set the IOAPIC ID to the value stored in the MPC table.
@@ -992,6 +995,8 @@
 		/* Read the register 0 value */
 		*(int *)&reg_00 = io_apic_read(apic, 0);
 		
+		old_id = mp_ioapics[apic].mpc_apicid;
+
 		if (mp_ioapics[apic].mpc_apicid >= 0xf) {
 			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
 				apic, mp_ioapics[apic].mpc_apicid);
@@ -1001,20 +1006,40 @@
 		}
 
 		/*
+		 * Sanity check, is the ID really free? Every APIC in a
+		 * system must have a unique ID or we get lots of nice
+		 * 'stuck on smp_invalidate_needed IPI wait' messages.
+		 */
+		if (phys_id_present_map & (1 << mp_ioapics[apic].mpc_apicid)) {
+			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",
+				apic, mp_ioapics[apic].mpc_apicid);
+			for (i = 0; i < 0xf; i++)
+				if (!(phys_id_present_map & (1 << i)))
+					break;
+			if (i >= 0xf)
+				panic("Max APIC ID exceeded!\n");
+			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
+				i);
+			phys_id_present_map |= 1 << i;
+			mp_ioapics[apic].mpc_apicid = i;
+		}
+
+		/*
+		 * We need to adjust the IRQ routing table
+		 * if the ID changed.
+		 */
+		if (old_id != mp_ioapics[apic].mpc_apicid)
+			for (i = 0; i < mp_irq_entries; i++)
+				if (mp_irqs[i].mpc_dstapic == old_id)
+					mp_irqs[i].mpc_dstapic
+						= mp_ioapics[apic].mpc_apicid;
+
+		/*
 		 * Read the right value from the MPC table and
 		 * write it into the ID register.
 	 	 */
 		printk(KERN_INFO "...changing IO-APIC physical APIC ID to %d ...",
 					mp_ioapics[apic].mpc_apicid);
-
-		/*
-		 * Sanity check, is the ID really free? Every APIC in the
-		 * system must have a unique ID or we get lots of nice
-		 * 'stuck on smp_invalidate_needed IPI wait' messages.
-		 */
-		if (phys_cpu_present_map & (1<<mp_ioapics[apic].mpc_apicid))
-			panic("APIC ID %d already used",
-				mp_ioapics[apic].mpc_apicid);
 
 		reg_00.ID = mp_ioapics[apic].mpc_apicid;
 		io_apic_write(apic, 0, *(int *)&reg_00);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)