]> git.neil.brown.name Git - history.git/commitdiff
[ACPI] disable LAPIC at reboot and poweroff if Linux forced it on
authorLen Brown <len.brown@intel.com>
Wed, 1 Dec 2004 08:59:57 +0000 (03:59 -0500)
committerLen Brown <lenb@dhcppc3.>
Wed, 1 Dec 2004 08:59:57 +0000 (03:59 -0500)
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>
arch/i386/kernel/apic.c
arch/i386/kernel/reboot.c
include/asm-i386/apic.h

index 64c175ff4a9228c1cd68564ad335eaf55e0f61ec..110cc1d46bc2292cbc4e936d0789e4e3945d55c3 100644 (file)
@@ -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"),
index 06974254cd92d6160cb643a511b7aa32bd36b80b..fc53f8b1719db89cbc920f2713f912334b08797f 100644 (file)
@@ -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)
index 8135c7c290f23a054eb4e9c1f9326603564ee5e7..55ed2de23a623ad26ebd5eb0faf2032f6ce56d5c 100644 (file)
@@ -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 */