[PATCH] x86: Regard MSRs in lapic_suspend()/lapic_resume()
Read/Write APIC_LVTPC and APIC_LVTTHMR only, if get_maxlvt() returns certain values. This is done like everywhere else in i386/kernel/apic.c, so I guess its correct. Suspends/Resumes to disk fine and eleminates an smp_error_interrupt() here on a K8. AK: ported to x86-64 too Signed-off-by: Karsten Wiese <fzu@wemgehoertderstaat.de> Signed-off-by: Andi Kleen <ak@suse.de>
This commit is contained in:
parent
9a8cb626a0
commit
f990fff427
|
@ -647,23 +647,30 @@ static struct {
|
|||
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();
|
||||
|
@ -675,10 +682,13 @@ static int lapic_resume(struct sys_device *dev)
|
|||
{
|
||||
unsigned int l, h;
|
||||
unsigned long flags;
|
||||
int maxlvt;
|
||||
|
||||
if (!apic_pm_state.active)
|
||||
return 0;
|
||||
|
||||
maxlvt = get_maxlvt();
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
/*
|
||||
|
@ -700,8 +710,12 @@ static int lapic_resume(struct sys_device *dev)
|
|||
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);
|
||||
|
|
|
@ -459,23 +459,30 @@ static struct {
|
|||
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_INTEL
|
||||
if (maxlvt >= 5)
|
||||
apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);
|
||||
#endif
|
||||
local_irq_save(flags);
|
||||
disable_local_APIC();
|
||||
local_irq_restore(flags);
|
||||
|
@ -486,10 +493,13 @@ static int lapic_resume(struct sys_device *dev)
|
|||
{
|
||||
unsigned int l, h;
|
||||
unsigned long flags;
|
||||
int maxlvt;
|
||||
|
||||
if (!apic_pm_state.active)
|
||||
return 0;
|
||||
|
||||
maxlvt = get_maxlvt();
|
||||
|
||||
local_irq_save(flags);
|
||||
rdmsr(MSR_IA32_APICBASE, l, h);
|
||||
l &= ~MSR_IA32_APICBASE_BASE;
|
||||
|
@ -503,8 +513,12 @@ static int lapic_resume(struct sys_device *dev)
|
|||
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_INTEL
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue