[PATCH] x86-64: Disable local APIC timer use on AMD systems with C1E
[powerpc.git] / arch / i386 / kernel / apic.c
index 5cff797..93aa911 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/clockchips.h>
 #include <linux/acpi_pmtmr.h>
 #include <linux/module.h>
+#include <linux/dmi.h>
 
 #include <asm/atomic.h>
 #include <asm/smp.h>
@@ -61,6 +62,11 @@ static int enable_local_apic __initdata = 0;
 
 /* Local APIC timer verification ok */
 static int local_apic_timer_verify_ok;
+/* Disable local APIC timer from the kernel commandline or via dmi quirk */
+static int local_apic_timer_disabled;
+/* Local APIC timer works in C2 */
+int local_apic_timer_c2_ok;
+EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok);
 
 /*
  * Debug level, exported for io_apic.c
@@ -340,6 +346,22 @@ void __init setup_boot_APIC_clock(void)
        long delta, deltapm;
        int pm_referenced = 0;
 
+       if (boot_cpu_has(X86_FEATURE_LAPIC_TIMER_BROKEN))
+               local_apic_timer_disabled = 1;
+
+       /*
+        * The local apic timer can be disabled via the kernel
+        * commandline or from the test above. Register the lapic
+        * timer as a dummy clock event source on SMP systems, so the
+        * broadcast mechanism is used. On UP systems simply ignore it.
+        */
+       if (local_apic_timer_disabled) {
+               /* No broadcast on UP ! */
+               if (num_possible_cpus() > 1)
+                       setup_APIC_timer();
+               return;
+       }
+
        apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"
                    "calibrating APIC timer ...\n");
 
@@ -461,7 +483,8 @@ void __init setup_boot_APIC_clock(void)
                        apic_printk(APIC_VERBOSE, "... jiffies result ok\n");
                else
                        local_apic_timer_verify_ok = 0;
-       }
+       } else
+               local_irq_enable();
 
        if (!local_apic_timer_verify_ok) {
                printk(KERN_WARNING
@@ -1179,6 +1202,20 @@ static int __init parse_nolapic(char *arg)
 }
 early_param("nolapic", parse_nolapic);
 
+static int __init parse_disable_lapic_timer(char *arg)
+{
+       local_apic_timer_disabled = 1;
+       return 0;
+}
+early_param("nolapic_timer", parse_disable_lapic_timer);
+
+static int __init parse_lapic_timer_c2_ok(char *arg)
+{
+       local_apic_timer_c2_ok = 1;
+       return 0;
+}
+early_param("lapic_timer_c2_ok", parse_lapic_timer_c2_ok);
+
 static int __init apic_set_verbosity(char *str)
 {
        if (strcmp("debug", str) == 0)