x86: fix ioapic bug again
authorIngo Molnar <mingo@elte.hu>
Fri, 21 Mar 2008 13:32:36 +0000 (14:32 +0100)
committerIngo Molnar <mingo@elte.hu>
Thu, 17 Apr 2008 15:41:21 +0000 (17:41 +0200)
un-revert:

 commit 4960c9df1407c2723459c60ff13e6efe0c209c62
 Author: Thomas Gleixner <tglx@linutronix.de>
 Date:   Tue Jan 22 10:23:01 2008 +0100

     Revert "x86: fix NMI watchdog & 'stopped time' problem"

         This reverts commit d4d25deca49ec2527a634557bf5a6cf449f85deb.

needs a proper fix though ...

Signed-off-by: Ingo Molnar <mingo@elte.hu>
arch/x86/kernel/io_apic_32.c
arch/x86/kernel/nmi_32.c

index 742fab45e1c6ab66cd1e1635bdd44cf7355a1a61..8ed6eb9676521b12ad36a041e03a85a1b5c8d5be 100644 (file)
@@ -2124,10 +2124,14 @@ static inline void __init check_timer(void)
 {
        int apic1, pin1, apic2, pin2;
        int vector;
+       unsigned int ver;
        unsigned long flags;
 
        local_irq_save(flags);
 
+       ver = apic_read(APIC_LVR);
+       ver = GET_APIC_VERSION(ver);
+
        /*
         * get/set the timer IRQ vector:
         */
@@ -2140,11 +2144,15 @@ static inline void __init check_timer(void)
         * mode for the 8259A whenever interrupts are routed
         * through I/O APICs.  Also IRQ0 has to be enabled in
         * the 8259A which implies the virtual wire has to be
-        * disabled in the local APIC.
+        * disabled in the local APIC.  Finally timer interrupts
+        * need to be acknowledged manually in the 8259A for
+        * timer_interrupt() and for the i82489DX when using
+        * the NMI watchdog.
         */
        apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
        init_8259A(1);
-       timer_ack = 1;
+       timer_ack = !cpu_has_tsc;
+       timer_ack |= (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver));
        if (timer_over_8254 > 0)
                enable_8259A_irq(0);
 
index 662e63e1cd57a51a1393d3e7bbc811eaf6b43077..8421d0ac6f2200fbf91dcae68aceba921ea49cbd 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <asm/smp.h>
 #include <asm/nmi.h>
+#include <asm/timer.h>
 
 #include "mach_traps.h"
 
@@ -81,7 +82,7 @@ int __init check_nmi_watchdog(void)
 
        prev_nmi_count = kmalloc(NR_CPUS * sizeof(int), GFP_KERNEL);
        if (!prev_nmi_count)
-               return -1;
+               goto error;
 
        printk(KERN_INFO "Testing NMI watchdog ... ");
 
@@ -118,7 +119,7 @@ int __init check_nmi_watchdog(void)
        if (!atomic_read(&nmi_active)) {
                kfree(prev_nmi_count);
                atomic_set(&nmi_active, -1);
-               return -1;
+               goto error;
        }
        printk("OK.\n");
 
@@ -129,6 +130,10 @@ int __init check_nmi_watchdog(void)
 
        kfree(prev_nmi_count);
        return 0;
+error:
+       timer_ack = !cpu_has_tsc;
+
+       return -1;
 }
 
 static int __init setup_nmi_watchdog(char *str)