diff options
| author | Len Brown <len.brown@intel.com> | 2004-12-01 03:59:57 -0500 |
|---|---|---|
| committer | Len Brown <lenb@dhcppc3.> | 2004-12-01 03:59:57 -0500 |
| commit | 0e3448746fcaaaeb8ea5061efa89d750d7403fbb (patch) | |
| tree | a66134abc39924c36e25b35c754a1f7e36d421d3 | |
| parent | 7b28bc9322892dba038d3485de0a0ca3227533fa (diff) | |
[ACPI] disable LAPIC at reboot and poweroff if Linux forced it on
http://bugzilla.kernel.org/show_bug.cgi?id=3643
Signed-off-by: Alexey Y Starikovskiy <alexey.y.starikovskiy@intel.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Len Brown <len.brown@intel.com>
| -rw-r--r-- | arch/i386/kernel/apic.c | 23 | ||||
| -rw-r--r-- | arch/i386/kernel/reboot.c | 13 | ||||
| -rw-r--r-- | include/asm-i386/apic.h | 6 |
3 files changed, 31 insertions, 11 deletions
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index 64c175ff4a92..110cc1d46bc2 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -491,12 +491,25 @@ void __init setup_local_APIC (void) apic_pm_activate(); } +/* + * If Linux enabled the LAPIC against the BIOS default + * disable it down before re-entering the BIOS on shutdown. + * Otherwise the BIOS may get confused and not power-off. + */ +void +lapic_shutdown() +{ + if (!cpu_has_apic || !enabled_via_apicbase) + return; + + local_irq_disable(); + disable_local_APIC(); + local_irq_enable(); +} + #ifdef CONFIG_PM static struct { - /* 'active' is true if the local APIC was enabled by us and - not the BIOS; this signifies that we are also responsible - for disabling it before entering apm/acpi suspend */ int active; /* r/w apic fields */ unsigned int apic_id; @@ -584,6 +597,10 @@ static int lapic_resume(struct sys_device *dev) return 0; } +/* + * This device has no shutdown method - fully functioning local APICs + * are needed on every CPU up until machine_halt/restart/poweroff. + */ static struct sysdev_class lapic_sysclass = { set_kset_name("lapic"), diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c index 06974254cd92..fc53f8b1719d 100644 --- a/arch/i386/kernel/reboot.c +++ b/arch/i386/kernel/reboot.c @@ -331,13 +331,10 @@ void machine_restart(char * __unused) * other OSs see a clean IRQ state. */ smp_send_stop(); -#elif defined(CONFIG_X86_LOCAL_APIC) - if (cpu_has_apic) { - local_irq_disable(); - disable_local_APIC(); - local_irq_enable(); - } -#endif +#endif /* CONFIG_SMP */ + + lapic_shutdown(); + #ifdef CONFIG_X86_IO_APIC disable_IO_APIC(); #endif @@ -373,6 +370,8 @@ EXPORT_SYMBOL(machine_halt); void machine_power_off(void) { + lapic_shutdown(); + if (efi_enabled) efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL); if (pm_power_off) diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h index 8135c7c290f2..55ed2de23a62 100644 --- a/include/asm-i386/apic.h +++ b/include/asm-i386/apic.h @@ -88,6 +88,7 @@ extern void clear_local_APIC(void); extern void connect_bsp_APIC (void); extern void disconnect_bsp_APIC (void); extern void disable_local_APIC (void); +extern void lapic_shutdown (void); extern int verify_local_APIC (void); extern void cache_APIC_registers (void); extern void sync_Arb_IDs (void); @@ -116,6 +117,9 @@ extern unsigned int nmi_watchdog; #define NMI_LOCAL_APIC 2 #define NMI_INVALID 3 -#endif /* CONFIG_X86_LOCAL_APIC */ +#else /* !CONFIG_X86_LOCAL_APIC */ +static inline void lapic_shutdown(void) { } + +#endif /* !CONFIG_X86_LOCAL_APIC */ #endif /* __ASM_APIC_H */ |
