patch-2.4.10 linux/arch/i386/kernel/io_apic.c

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

diff -u --recursive --new-file v2.4.9/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c
@@ -33,25 +33,17 @@
 #include <asm/smp.h>
 #include <asm/desc.h>
 
+#undef APIC_LOCKUP_DEBUG
+
 #define APIC_LOCKUP_DEBUG
 
 static spinlock_t ioapic_lock = SPIN_LOCK_UNLOCKED;
 
 /*
- * # of IO-APICs and # of IRQ routing registers
+ * # of IRQ routing registers
  */
-int nr_ioapics;
 int nr_ioapic_registers[MAX_IO_APICS];
 
-/* I/O APIC entries */
-struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
-
-/* # of MP IRQ source entries */
-struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
-
-/* MP IRQ source entries */
-int mp_irq_entries;
-
 #if CONFIG_SMP
 # define TARGET_CPUS cpu_online_map
 #else
@@ -154,14 +146,17 @@
 void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
 {
 	struct IO_APIC_route_entry entry;
+	unsigned long flags;
 
 	/*
 	 * Disable it in the IO-APIC irq-routing table:
 	 */
 	memset(&entry, 0, sizeof(entry));
 	entry.mask = 1;
+	spin_lock_irqsave(&ioapic_lock, flags);
 	io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry) + 0));
 	io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry) + 1));
+	spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
 static void clear_IO_APIC (void)
@@ -595,6 +590,7 @@
 {
 	struct IO_APIC_route_entry entry;
 	int apic, pin, idx, irq, first_notcon = 1, vector;
+	unsigned long flags;
 
 	printk(KERN_DEBUG "init IO_APIC IRQs\n");
 
@@ -650,8 +646,10 @@
 			if (!apic && (irq < 16))
 				disable_8259A_irq(irq);
 		}
+		spin_lock_irqsave(&ioapic_lock, flags);
 		io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
 		io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
+		spin_unlock_irqrestore(&ioapic_lock, flags);
 	}
 	}
 
@@ -666,6 +664,7 @@
 void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
 {
 	struct IO_APIC_route_entry entry;
+	unsigned long flags;
 
 	memset(&entry,0,sizeof(entry));
 
@@ -695,8 +694,10 @@
 	/*
 	 * Add it to the IO-APIC irq-routing table:
 	 */
+	spin_lock_irqsave(&ioapic_lock, flags);
 	io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1));
 	io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0));
+	spin_unlock_irqrestore(&ioapic_lock, flags);
 
 	enable_8259A_irq(0);
 }
@@ -713,6 +714,7 @@
 	struct IO_APIC_reg_00 reg_00;
 	struct IO_APIC_reg_01 reg_01;
 	struct IO_APIC_reg_02 reg_02;
+	unsigned long flags;
 
  	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
 	for (i = 0; i < nr_ioapics; i++)
@@ -727,10 +729,12 @@
 
 	for (apic = 0; apic < nr_ioapics; apic++) {
 
+	spin_lock_irqsave(&ioapic_lock, flags);
 	*(int *)&reg_00 = io_apic_read(apic, 0);
 	*(int *)&reg_01 = io_apic_read(apic, 1);
 	if (reg_01.version >= 0x10)
 		*(int *)&reg_02 = io_apic_read(apic, 2);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
 
 	printk("\n");
 	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid);
@@ -742,11 +746,9 @@
 	printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)&reg_01);
 	printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.entries);
 	if (	(reg_01.entries != 0x0f) && /* older (Neptune) boards */
-		(reg_01.entries != 0x11) &&
 		(reg_01.entries != 0x17) && /* typical ISA+PCI boards */
 		(reg_01.entries != 0x1b) && /* Compaq Proliant boards */
 		(reg_01.entries != 0x1f) && /* dual Xeon boards */
-		(reg_01.entries != 0x20) &&
 		(reg_01.entries != 0x22) && /* bigger Xeon boards */
 		(reg_01.entries != 0x2E) &&
 		(reg_01.entries != 0x3F)
@@ -757,7 +759,8 @@
 	if (	(reg_01.version != 0x01) && /* 82489DX IO-APICs */
 		(reg_01.version != 0x10) && /* oldest IO-APICs */
 		(reg_01.version != 0x11) && /* Pentium/Pro IO-APICs */
-		(reg_01.version != 0x13)    /* Xeon IO-APICs */
+		(reg_01.version != 0x13) && /* Xeon IO-APICs */
+		(reg_01.entries != 0x20)    /* Intel P64H (82806 AA) */
 	)
 		UNEXPECTED_IO_APIC();
 	if (reg_01.__reserved_1 || reg_01.__reserved_2)
@@ -778,8 +781,10 @@
 	for (i = 0; i <= reg_01.entries; i++) {
 		struct IO_APIC_route_entry entry;
 
+		spin_lock_irqsave(&ioapic_lock, flags);
 		*(((int *)&entry)+0) = io_apic_read(apic, 0x10+i*2);
 		*(((int *)&entry)+1) = io_apic_read(apic, 0x11+i*2);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
 
 		printk(KERN_DEBUG " %02x %03X %02X  ",
 			i,
@@ -806,7 +811,7 @@
 			continue;
 		printk(KERN_DEBUG "IRQ%d ", i);
 		for (;;) {
-			printk("-> %d", entry->pin);
+			printk("-> %d:%d", entry->apic, entry->pin);
 			if (!entry->next)
 				break;
 			entry = irq_2_pin + entry->next;
@@ -956,6 +961,7 @@
 {
 	struct IO_APIC_reg_01 reg_01;
 	int i;
+	unsigned long flags;
 
 	for (i = 0; i < PIN_MAP_SIZE; i++) {
 		irq_2_pin[i].pin = -1;
@@ -969,7 +975,9 @@
 	 * The number of IO-APIC IRQ registers (== #pins):
 	 */
 	for (i = 0; i < nr_ioapics; i++) {
+		spin_lock_irqsave(&ioapic_lock, flags);
 		*(int *)&reg_01 = io_apic_read(i, 1);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
 		nr_ioapic_registers[i] = reg_01.entries+1;
 	}
 
@@ -1006,6 +1014,7 @@
 	int apic;
 	int i;
 	unsigned char old_id;
+	unsigned long flags;
 
 	/*
 	 * Set the IOAPIC ID to the value stored in the MPC table.
@@ -1013,7 +1022,9 @@
 	for (apic = 0; apic < nr_ioapics; apic++) {
 
 		/* Read the register 0 value */
+		spin_lock_irqsave(&ioapic_lock, flags);
 		*(int *)&reg_00 = io_apic_read(apic, 0);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
 		
 		old_id = mp_ioapics[apic].mpc_apicid;
 
@@ -1062,12 +1073,16 @@
 					mp_ioapics[apic].mpc_apicid);
 
 		reg_00.ID = mp_ioapics[apic].mpc_apicid;
+		spin_lock_irqsave(&ioapic_lock, flags);
 		io_apic_write(apic, 0, *(int *)&reg_00);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
 
 		/*
 		 * Sanity check
 		 */
+		spin_lock_irqsave(&ioapic_lock, flags);
 		*(int *)&reg_00 = io_apic_read(apic, 0);
+		spin_unlock_irqrestore(&ioapic_lock, flags);
 		if (reg_00.ID != mp_ioapics[apic].mpc_apicid)
 			panic("could not set ID!\n");
 		else
@@ -1104,25 +1119,6 @@
 	return 0;
 }
 
-static int __init nmi_irq_works(void)
-{
-	irq_cpustat_t tmp[NR_CPUS];
-	int j, cpu;
-
-	memcpy(tmp, irq_stat, sizeof(tmp));
-	sti();
-	mdelay(50);
-
-	for (j = 0; j < smp_num_cpus; j++) {
-		cpu = cpu_logical_map(j);
-		if (nmi_count(cpu) - tmp[cpu].__nmi_count <= 3) {
-			printk(KERN_WARNING "CPU#%d NMI appears to be stuck.\n", cpu);
-			return 0;
-		}
-	}
-	return 1;
-}
-
 /*
  * In the SMP+IOAPIC case it might happen that there are an unspecified
  * number of pending IRQ events unhandled. These cases are very rare,
@@ -1212,6 +1208,7 @@
 static void end_level_ioapic_irq (unsigned int irq)
 {
 	unsigned long v;
+	int i;
 
 /*
  * It appears there is an erratum which affects at least version 0x11
@@ -1232,11 +1229,12 @@
  * operation to prevent an edge-triggered interrupt escaping meanwhile.
  * The idea is from Manfred Spraul.  --macro
  */
-	v = apic_read(APIC_TMR + ((IO_APIC_VECTOR(irq) & ~0x1f) >> 1));
+	i = IO_APIC_VECTOR(irq);
+	v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
 
 	ack_APIC_irq();
 
-	if (!(v & (1 << (IO_APIC_VECTOR(irq) & 0x1f)))) {
+	if (!(v & (1 << (i & 0x1f)))) {
 #ifdef APIC_MISMATCH_DEBUG
 		atomic_inc(&irq_mis_count);
 #endif
@@ -1416,13 +1414,16 @@
 	int pin, i;
 	struct IO_APIC_route_entry entry0, entry1;
 	unsigned char save_control, save_freq_select;
+	unsigned long flags;
 
 	pin = find_isa_irq_pin(8, mp_INT);
 	if (pin == -1)
 		return;
 
+	spin_lock_irqsave(&ioapic_lock, flags);
 	*(((int *)&entry0) + 1) = io_apic_read(0, 0x11 + 2 * pin);
 	*(((int *)&entry0) + 0) = io_apic_read(0, 0x10 + 2 * pin);
+	spin_unlock_irqrestore(&ioapic_lock, flags);
 	clear_IO_APIC_pin(0, pin);
 
 	memset(&entry1, 0, sizeof(entry1));
@@ -1435,8 +1436,10 @@
 	entry1.trigger = 0;
 	entry1.vector = 0;
 
+	spin_lock_irqsave(&ioapic_lock, flags);
 	io_apic_write(0, 0x11 + 2 * pin, *(((int *)&entry1) + 1));
 	io_apic_write(0, 0x10 + 2 * pin, *(((int *)&entry1) + 0));
+	spin_unlock_irqrestore(&ioapic_lock, flags);
 
 	save_control = CMOS_READ(RTC_CONTROL);
 	save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
@@ -1455,8 +1458,10 @@
 	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
 	clear_IO_APIC_pin(0, pin);
 
+	spin_lock_irqsave(&ioapic_lock, flags);
 	io_apic_write(0, 0x11 + 2 * pin, *(((int *)&entry0) + 1));
 	io_apic_write(0, 0x10 + 2 * pin, *(((int *)&entry0) + 0));
+	spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
 /*
@@ -1493,7 +1498,7 @@
 	pin1 = find_isa_irq_pin(0, mp_INT);
 	pin2 = find_isa_irq_pin(0, mp_ExtINT);
 
-	printk(KERN_INFO "..TIMER: vector=%02X pin1=%d pin2=%d\n", vector, pin1, pin2);
+	printk(KERN_INFO "..TIMER: vector=0x%02X pin1=%d pin2=%d\n", vector, pin1, pin2);
 
 	if (pin1 != -1) {
 		/*
@@ -1501,11 +1506,11 @@
 		 */
 		unmask_IO_APIC_irq(0);
 		if (timer_irq_works()) {
-			if (nmi_watchdog) {
+			if (nmi_watchdog == NMI_IO_APIC) {
 				disable_8259A_irq(0);
 				setup_nmi();
 				enable_8259A_irq(0);
-				nmi_irq_works();
+				check_nmi_watchdog();
 			}
 			return;
 		}
@@ -1522,9 +1527,9 @@
 		setup_ExtINT_IRQ0_pin(pin2, vector);
 		if (timer_irq_works()) {
 			printk("works.\n");
-			if (nmi_watchdog) {
+			if (nmi_watchdog == NMI_IO_APIC) {
 				setup_nmi();
-				nmi_irq_works();
+				check_nmi_watchdog();
 			}
 			return;
 		}
@@ -1605,19 +1610,3 @@
 	check_timer();
 	print_IO_APIC();
 }
-
-#ifndef CONFIG_SMP
-/*
- * This initializes the IO-APIC and APIC hardware if this is
- * a UP kernel.
- */
-void IO_APIC_init_uniprocessor (void)
-{
-	if (!smp_found_config)
-		return;
-	connect_bsp_APIC();
-	setup_local_APIC();
-	setup_IO_APIC();
-	setup_APIC_clocks();
-}
-#endif

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