Commit 591e47a6 authored by Len Brown's avatar Len Brown

Merge intel.com:/home/lenb/src/26-stable-dev

into intel.com:/home/lenb/src/26-latest-dev
parents f2751c96 0e344874
...@@ -513,12 +513,25 @@ void __init setup_local_APIC (void) ...@@ -513,12 +513,25 @@ void __init setup_local_APIC (void)
apic_pm_activate(); 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 #ifdef CONFIG_PM
static struct { 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; int active;
/* r/w apic fields */ /* r/w apic fields */
unsigned int apic_id; unsigned int apic_id;
...@@ -536,23 +549,9 @@ static struct { ...@@ -536,23 +549,9 @@ static struct {
unsigned int apic_thmr; unsigned int apic_thmr;
} apic_pm_state; } apic_pm_state;
static int lapic_shutdown(struct sys_device *dev)
{
unsigned long flags;
if (!apic_pm_state.active)
return 0;
local_irq_save(flags);
disable_local_APIC();
local_irq_restore(flags);
return 0;
}
static int lapic_suspend(struct sys_device *dev, u32 state) static int lapic_suspend(struct sys_device *dev, u32 state)
{ {
unsigned long flags;
if (!apic_pm_state.active) if (!apic_pm_state.active)
return 0; return 0;
...@@ -571,7 +570,10 @@ static int lapic_suspend(struct sys_device *dev, u32 state) ...@@ -571,7 +570,10 @@ static int lapic_suspend(struct sys_device *dev, u32 state)
apic_pm_state.apic_tdcr = apic_read(APIC_TDCR); apic_pm_state.apic_tdcr = apic_read(APIC_TDCR);
apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);
return lapic_shutdown(dev); local_irq_save(flags);
disable_local_APIC();
local_irq_restore(flags);
return 0;
} }
static int lapic_resume(struct sys_device *dev) static int lapic_resume(struct sys_device *dev)
...@@ -617,10 +619,13 @@ static int lapic_resume(struct sys_device *dev) ...@@ -617,10 +619,13 @@ static int lapic_resume(struct sys_device *dev)
return 0; 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 = { static struct sysdev_class lapic_sysclass = {
set_kset_name("lapic"), set_kset_name("lapic"),
.shutdown = lapic_shutdown,
.resume = lapic_resume, .resume = lapic_resume,
.suspend = lapic_suspend, .suspend = lapic_suspend,
}; };
......
...@@ -331,13 +331,10 @@ void machine_restart(char * __unused) ...@@ -331,13 +331,10 @@ void machine_restart(char * __unused)
* other OSs see a clean IRQ state. * other OSs see a clean IRQ state.
*/ */
smp_send_stop(); smp_send_stop();
#elif defined(CONFIG_X86_LOCAL_APIC) #endif /* CONFIG_SMP */
if (cpu_has_apic) {
local_irq_disable(); lapic_shutdown();
disable_local_APIC();
local_irq_enable();
}
#endif
#ifdef CONFIG_X86_IO_APIC #ifdef CONFIG_X86_IO_APIC
disable_IO_APIC(); disable_IO_APIC();
#endif #endif
...@@ -373,6 +370,8 @@ EXPORT_SYMBOL(machine_halt); ...@@ -373,6 +370,8 @@ EXPORT_SYMBOL(machine_halt);
void machine_power_off(void) void machine_power_off(void)
{ {
lapic_shutdown();
if (efi_enabled) if (efi_enabled)
efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL); efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL);
if (pm_power_off) if (pm_power_off)
......
...@@ -89,6 +89,7 @@ extern void clear_local_APIC(void); ...@@ -89,6 +89,7 @@ extern void clear_local_APIC(void);
extern void connect_bsp_APIC (void); extern void connect_bsp_APIC (void);
extern void disconnect_bsp_APIC (void); extern void disconnect_bsp_APIC (void);
extern void disable_local_APIC (void); extern void disable_local_APIC (void);
extern void lapic_shutdown (void);
extern int verify_local_APIC (void); extern int verify_local_APIC (void);
extern void cache_APIC_registers (void); extern void cache_APIC_registers (void);
extern void sync_Arb_IDs (void); extern void sync_Arb_IDs (void);
...@@ -117,6 +118,9 @@ extern unsigned int nmi_watchdog; ...@@ -117,6 +118,9 @@ extern unsigned int nmi_watchdog;
#define NMI_LOCAL_APIC 2 #define NMI_LOCAL_APIC 2
#define NMI_INVALID 3 #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 */ #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