#include <linux/sysdev.h>
#include <linux/cpu.h>
#include <linux/module.h>
-#include <linux/dmi.h>
#include <asm/atomic.h>
#include <asm/smp.h>
/*
* 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
printk("No ESR for 82489DX.\n");
}
- if (nmi_watchdog == NMI_LOCAL_APIC)
- setup_apic_nmi_watchdog();
+ setup_apic_nmi_watchdog(NULL);
apic_pm_activate();
}
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();
{
unsigned int l, h;
unsigned long flags;
+ int maxlvt;
if (!apic_pm_state.active)
return 0;
+ maxlvt = get_maxlvt();
+
local_irq_save(flags);
/*
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);
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)
return 1;
}
-__setup("apic", apic_set_verbosity);
+__setup("apic=", apic_set_verbosity);
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;
}
/*
* 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
/*
fastcall void smp_apic_timer_interrupt(struct pt_regs *regs)
{
+ struct pt_regs *old_regs = set_irq_regs(regs);
int cpu = smp_processor_id();
/*
* 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();
*/
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;
* 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
}
}
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.
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);
+