Commit 0e344874 authored by Len Brown's avatar Len Brown Committed by Len Brown

[ACPI] disable LAPIC at reboot and poweroff if Linux forced it on

http://bugzilla.kernel.org/show_bug.cgi?id=3643Signed-off-by: default avatarAlexey Y Starikovskiy <alexey.y.starikovskiy@intel.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 7b28bc93
......@@ -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"),
......
......@@ -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)
......
......@@ -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 */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment