fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / arch / i386 / kernel / apic.c
index 5bec4fb..776d9be 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/sysdev.h>
 #include <linux/cpu.h>
 #include <linux/module.h>
-#include <linux/dmi.h>
 
 #include <asm/atomic.h>
 #include <asm/smp.h>
@@ -53,10 +52,18 @@ static cpumask_t timer_bcast_ipi;
 /*
  * Knob to control our willingness to enable the local APIC.
  */
-int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
-int prefer_apic __initdata = 0;        /* when enable_local_apic == 0 prefer APIC but don't force against
-                                  BIOS wishes */
-int apic_disabled_by_dmi __initdata;
+static int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
+
+static inline void lapic_disable(void)
+{
+       enable_local_apic = -1;
+       clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
+}
+
+static inline void lapic_enable(void)
+{
+       enable_local_apic = 1;
+}
 
 /*
  * Debug level
@@ -590,8 +597,7 @@ void __devinit setup_local_APIC(void)
                        printk("No ESR for 82489DX.\n");
        }
 
-       if (nmi_watchdog == NMI_LOCAL_APIC)
-               setup_apic_nmi_watchdog();
+       setup_apic_nmi_watchdog(NULL);
        apic_pm_activate();
 }
 
@@ -641,23 +647,30 @@ static struct {
 static int lapic_suspend(struct sys_device *dev, pm_message_t state)
 {
        unsigned long flags;
+       int maxlvt;
 
        if (!apic_pm_state.active)
                return 0;
 
+       maxlvt = get_maxlvt();
+
        apic_pm_state.apic_id = apic_read(APIC_ID);
        apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI);
        apic_pm_state.apic_ldr = apic_read(APIC_LDR);
        apic_pm_state.apic_dfr = apic_read(APIC_DFR);
        apic_pm_state.apic_spiv = apic_read(APIC_SPIV);
        apic_pm_state.apic_lvtt = apic_read(APIC_LVTT);
-       apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC);
+       if (maxlvt >= 4)
+               apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC);
        apic_pm_state.apic_lvt0 = apic_read(APIC_LVT0);
        apic_pm_state.apic_lvt1 = apic_read(APIC_LVT1);
        apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR);
        apic_pm_state.apic_tmict = apic_read(APIC_TMICT);
        apic_pm_state.apic_tdcr = apic_read(APIC_TDCR);
-       apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);
+#ifdef CONFIG_X86_MCE_P4THERMAL
+       if (maxlvt >= 5)
+               apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);
+#endif
        
        local_irq_save(flags);
        disable_local_APIC();
@@ -669,10 +682,13 @@ static int lapic_resume(struct sys_device *dev)
 {
        unsigned int l, h;
        unsigned long flags;
+       int maxlvt;
 
        if (!apic_pm_state.active)
                return 0;
 
+       maxlvt = get_maxlvt();
+
        local_irq_save(flags);
 
        /*
@@ -694,8 +710,12 @@ static int lapic_resume(struct sys_device *dev)
        apic_write(APIC_SPIV, apic_pm_state.apic_spiv);
        apic_write(APIC_LVT0, apic_pm_state.apic_lvt0);
        apic_write(APIC_LVT1, apic_pm_state.apic_lvt1);
-       apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr);
-       apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc);
+#ifdef CONFIG_X86_MCE_P4THERMAL
+       if (maxlvt >= 5)
+               apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr);
+#endif
+       if (maxlvt >= 4)
+               apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc);
        apic_write(APIC_LVTT, apic_pm_state.apic_lvtt);
        apic_write(APIC_TDCR, apic_pm_state.apic_tdcr);
        apic_write(APIC_TMICT, apic_pm_state.apic_tmict);
@@ -757,10 +777,6 @@ static void apic_pm_activate(void) { }
 
 static int __init apic_set_verbosity(char *str)
 {
-       if (*str == '=')
-               ++str;
-       if (*str == 0)
-               prefer_apic = 1;
        if (strcmp("debug", str) == 0)
                apic_verbosity = APIC_DEBUG;
        else if (strcmp("verbose", str) == 0)
@@ -768,7 +784,7 @@ static int __init apic_set_verbosity(char *str)
        return 1;
 }
 
-__setup("apic", apic_set_verbosity);
+__setup("apic=", apic_set_verbosity);
 
 static int __init detect_init_APIC (void)
 {
@@ -799,9 +815,8 @@ static int __init detect_init_APIC (void)
                 * APIC only if "lapic" specified.
                 */
                if (enable_local_apic <= 0) {
-                       if (!apic_disabled_by_dmi)
-                               printk("Local APIC disabled by BIOS -- "
-                                      "you can enable it with \"lapic\"\n");
+                       printk("Local APIC disabled by BIOS -- "
+                              "you can enable it with \"lapic\"\n");
                        return -1;
                }
                /*
@@ -1192,11 +1207,11 @@ EXPORT_SYMBOL(switch_ipi_to_APIC_timer);
  * value into /proc/profile.
  */
 
-inline void smp_local_timer_interrupt(struct pt_regs * regs)
+inline void smp_local_timer_interrupt(void)
 {
-       profile_tick(CPU_PROFILING, regs);
+       profile_tick(CPU_PROFILING);
 #ifdef CONFIG_SMP
-       update_process_times(user_mode_vm(regs));
+       update_process_times(user_mode_vm(get_irq_regs()));
 #endif
 
        /*
@@ -1222,6 +1237,7 @@ inline void smp_local_timer_interrupt(struct pt_regs * regs)
 
 fastcall void smp_apic_timer_interrupt(struct pt_regs *regs)
 {
+       struct pt_regs *old_regs = set_irq_regs(regs);
        int cpu = smp_processor_id();
 
        /*
@@ -1240,12 +1256,13 @@ fastcall void smp_apic_timer_interrupt(struct pt_regs *regs)
         * interrupt lock, which is the WrongThing (tm) to do.
         */
        irq_enter();
-       smp_local_timer_interrupt(regs);
+       smp_local_timer_interrupt();
        irq_exit();
+       set_irq_regs(old_regs);
 }
 
 #ifndef CONFIG_SMP
-static void up_apic_timer_interrupt_call(struct pt_regs *regs)
+static void up_apic_timer_interrupt_call(void)
 {
        int cpu = smp_processor_id();
 
@@ -1254,11 +1271,11 @@ static void up_apic_timer_interrupt_call(struct pt_regs *regs)
         */
        per_cpu(irq_stat, cpu).apic_timer_irqs++;
 
-       smp_local_timer_interrupt(regs);
+       smp_local_timer_interrupt();
 }
 #endif
 
-void smp_send_timer_broadcast_ipi(struct pt_regs *regs)
+void smp_send_timer_broadcast_ipi(void)
 {
        cpumask_t mask;
 
@@ -1271,7 +1288,7 @@ void smp_send_timer_broadcast_ipi(struct pt_regs *regs)
                 * We can directly call the apic timer interrupt handler
                 * in UP case. Minus all irq related functions
                 */
-               up_apic_timer_interrupt_call(regs);
+               up_apic_timer_interrupt_call();
 #endif
        }
 }
@@ -1335,64 +1352,6 @@ fastcall void smp_error_interrupt(struct pt_regs *regs)
        irq_exit();
 }
 
-#ifdef CONFIG_X86_APIC_AUTO
-
-/* Some heuristics to decide when to enable the APICs */
-
-static __init int dmi_enable_apic(void)
-{
-       int year;
-       int apic;
-       char *vendor;
-
-       /* If the machine has more than one CPU try to use APIC because it'll
-          be running the SMP kernel with APIC soon anyways.
-          This won't cover dual core, but they are handled by the date check
-          below. */
-       if (dmi_cpus > 1)
-               return 1;
-
-       year = dmi_get_year(DMI_BIOS_DATE);
-       vendor = dmi_get_system_info(DMI_BIOS_VENDOR);
-       apic = 0;
-
-       /* All Intel BIOS since 1998 assumed APIC on. Don't include 1998 itself
-          because we're not sure for that. */
-       if (vendor && !strncmp(vendor, "Intel", 5))
-               apic = 1;
-       /* Use APIC for anything since 2001 */
-       else if (year >= 2001)
-               apic = 1;
-
-#ifdef CONFIG_ACPI
-       /* When ACPI is disabled also default to APIC off on very new systems (>= 2004)
-          which typically don't have working mptables anymore */
-       if (acpi_noirq && year >= 2004)
-               apic = 0;
-#endif
-
-       if (!apic)
-               apic_disabled_by_dmi = 1;
-
-       return apic;
-}
-
-void __init dmi_check_apic(void)
-{
-       if (enable_local_apic != 0 || prefer_apic)
-               return;
-       if (!dmi_enable_apic()) {
-               clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
-               nr_ioapics = 0;
-               enable_local_apic = -1;
-               printk(KERN_INFO "IO/L-APIC disabled because your old system seems to be old\n");
-               printk(KERN_INFO "overwrite with \"apic\"\n");
-               return;
-       }
-       printk(KERN_INFO "IO/L-APIC allowed because system is MP or new enough\n");
-}
-#endif
-
 /*
  * This initializes the IO-APIC and APIC hardware if this is
  * a UP kernel.
@@ -1440,3 +1399,18 @@ int __init APIC_init_uniprocessor (void)
 
        return 0;
 }
+
+static int __init parse_lapic(char *arg)
+{
+       lapic_enable();
+       return 0;
+}
+early_param("lapic", parse_lapic);
+
+static int __init parse_nolapic(char *arg)
+{
+       lapic_disable();
+       return 0;
+}
+early_param("nolapic", parse_nolapic);
+