diff options
author | Karsten Wiese <fzu@wemgehoertderstaat.de> | 2006-12-06 20:14:11 -0500 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2006-12-06 20:14:11 -0500 |
commit | f990fff427d68af3e4e1d16fe799c106abc0bf53 (patch) | |
tree | 74681deb5738ddbc10fc34f71837902238378f15 /arch/i386 | |
parent | 9a8cb626a08f2c8251291f3c0a049b29665895d2 (diff) |
[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>
Diffstat (limited to 'arch/i386')
-rw-r--r-- | arch/i386/kernel/apic.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index 2fd4b7d927c2..776d9be26af9 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c | |||
@@ -647,23 +647,30 @@ static struct { | |||
647 | static int lapic_suspend(struct sys_device *dev, pm_message_t state) | 647 | static int lapic_suspend(struct sys_device *dev, pm_message_t state) |
648 | { | 648 | { |
649 | unsigned long flags; | 649 | unsigned long flags; |
650 | int maxlvt; | ||
650 | 651 | ||
651 | if (!apic_pm_state.active) | 652 | if (!apic_pm_state.active) |
652 | return 0; | 653 | return 0; |
653 | 654 | ||
655 | maxlvt = get_maxlvt(); | ||
656 | |||
654 | apic_pm_state.apic_id = apic_read(APIC_ID); | 657 | apic_pm_state.apic_id = apic_read(APIC_ID); |
655 | apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI); | 658 | apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI); |
656 | apic_pm_state.apic_ldr = apic_read(APIC_LDR); | 659 | apic_pm_state.apic_ldr = apic_read(APIC_LDR); |
657 | apic_pm_state.apic_dfr = apic_read(APIC_DFR); | 660 | apic_pm_state.apic_dfr = apic_read(APIC_DFR); |
658 | apic_pm_state.apic_spiv = apic_read(APIC_SPIV); | 661 | apic_pm_state.apic_spiv = apic_read(APIC_SPIV); |
659 | apic_pm_state.apic_lvtt = apic_read(APIC_LVTT); | 662 | apic_pm_state.apic_lvtt = apic_read(APIC_LVTT); |
660 | apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC); | 663 | if (maxlvt >= 4) |
664 | apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC); | ||
661 | apic_pm_state.apic_lvt0 = apic_read(APIC_LVT0); | 665 | apic_pm_state.apic_lvt0 = apic_read(APIC_LVT0); |
662 | apic_pm_state.apic_lvt1 = apic_read(APIC_LVT1); | 666 | apic_pm_state.apic_lvt1 = apic_read(APIC_LVT1); |
663 | apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR); | 667 | apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR); |
664 | apic_pm_state.apic_tmict = apic_read(APIC_TMICT); | 668 | apic_pm_state.apic_tmict = apic_read(APIC_TMICT); |
665 | apic_pm_state.apic_tdcr = apic_read(APIC_TDCR); | 669 | apic_pm_state.apic_tdcr = apic_read(APIC_TDCR); |
666 | apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); | 670 | #ifdef CONFIG_X86_MCE_P4THERMAL |
671 | if (maxlvt >= 5) | ||
672 | apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); | ||
673 | #endif | ||
667 | 674 | ||
668 | local_irq_save(flags); | 675 | local_irq_save(flags); |
669 | disable_local_APIC(); | 676 | disable_local_APIC(); |
@@ -675,10 +682,13 @@ static int lapic_resume(struct sys_device *dev) | |||
675 | { | 682 | { |
676 | unsigned int l, h; | 683 | unsigned int l, h; |
677 | unsigned long flags; | 684 | unsigned long flags; |
685 | int maxlvt; | ||
678 | 686 | ||
679 | if (!apic_pm_state.active) | 687 | if (!apic_pm_state.active) |
680 | return 0; | 688 | return 0; |
681 | 689 | ||
690 | maxlvt = get_maxlvt(); | ||
691 | |||
682 | local_irq_save(flags); | 692 | local_irq_save(flags); |
683 | 693 | ||
684 | /* | 694 | /* |
@@ -700,8 +710,12 @@ static int lapic_resume(struct sys_device *dev) | |||
700 | apic_write(APIC_SPIV, apic_pm_state.apic_spiv); | 710 | apic_write(APIC_SPIV, apic_pm_state.apic_spiv); |
701 | apic_write(APIC_LVT0, apic_pm_state.apic_lvt0); | 711 | apic_write(APIC_LVT0, apic_pm_state.apic_lvt0); |
702 | apic_write(APIC_LVT1, apic_pm_state.apic_lvt1); | 712 | apic_write(APIC_LVT1, apic_pm_state.apic_lvt1); |
703 | apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr); | 713 | #ifdef CONFIG_X86_MCE_P4THERMAL |
704 | apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc); | 714 | if (maxlvt >= 5) |
715 | apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr); | ||
716 | #endif | ||
717 | if (maxlvt >= 4) | ||
718 | apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc); | ||
705 | apic_write(APIC_LVTT, apic_pm_state.apic_lvtt); | 719 | apic_write(APIC_LVTT, apic_pm_state.apic_lvtt); |
706 | apic_write(APIC_TDCR, apic_pm_state.apic_tdcr); | 720 | apic_write(APIC_TDCR, apic_pm_state.apic_tdcr); |
707 | apic_write(APIC_TMICT, apic_pm_state.apic_tmict); | 721 | apic_write(APIC_TMICT, apic_pm_state.apic_tmict); |