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 | |
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')
-rw-r--r-- | arch/i386/kernel/apic.c | 22 | ||||
-rw-r--r-- | arch/x86_64/kernel/apic.c | 22 |
2 files changed, 36 insertions, 8 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); |
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c index 5c468971e645..f0b00d8731cb 100644 --- a/arch/x86_64/kernel/apic.c +++ b/arch/x86_64/kernel/apic.c | |||
@@ -459,23 +459,30 @@ static struct { | |||
459 | static int lapic_suspend(struct sys_device *dev, pm_message_t state) | 459 | static int lapic_suspend(struct sys_device *dev, pm_message_t state) |
460 | { | 460 | { |
461 | unsigned long flags; | 461 | unsigned long flags; |
462 | int maxlvt; | ||
462 | 463 | ||
463 | if (!apic_pm_state.active) | 464 | if (!apic_pm_state.active) |
464 | return 0; | 465 | return 0; |
465 | 466 | ||
467 | maxlvt = get_maxlvt(); | ||
468 | |||
466 | apic_pm_state.apic_id = apic_read(APIC_ID); | 469 | apic_pm_state.apic_id = apic_read(APIC_ID); |
467 | apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI); | 470 | apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI); |
468 | apic_pm_state.apic_ldr = apic_read(APIC_LDR); | 471 | apic_pm_state.apic_ldr = apic_read(APIC_LDR); |
469 | apic_pm_state.apic_dfr = apic_read(APIC_DFR); | 472 | apic_pm_state.apic_dfr = apic_read(APIC_DFR); |
470 | apic_pm_state.apic_spiv = apic_read(APIC_SPIV); | 473 | apic_pm_state.apic_spiv = apic_read(APIC_SPIV); |
471 | apic_pm_state.apic_lvtt = apic_read(APIC_LVTT); | 474 | apic_pm_state.apic_lvtt = apic_read(APIC_LVTT); |
472 | apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC); | 475 | if (maxlvt >= 4) |
476 | apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC); | ||
473 | apic_pm_state.apic_lvt0 = apic_read(APIC_LVT0); | 477 | apic_pm_state.apic_lvt0 = apic_read(APIC_LVT0); |
474 | apic_pm_state.apic_lvt1 = apic_read(APIC_LVT1); | 478 | apic_pm_state.apic_lvt1 = apic_read(APIC_LVT1); |
475 | apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR); | 479 | apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR); |
476 | apic_pm_state.apic_tmict = apic_read(APIC_TMICT); | 480 | apic_pm_state.apic_tmict = apic_read(APIC_TMICT); |
477 | apic_pm_state.apic_tdcr = apic_read(APIC_TDCR); | 481 | apic_pm_state.apic_tdcr = apic_read(APIC_TDCR); |
478 | apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); | 482 | #ifdef CONFIG_X86_MCE_INTEL |
483 | if (maxlvt >= 5) | ||
484 | apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); | ||
485 | #endif | ||
479 | local_irq_save(flags); | 486 | local_irq_save(flags); |
480 | disable_local_APIC(); | 487 | disable_local_APIC(); |
481 | local_irq_restore(flags); | 488 | local_irq_restore(flags); |
@@ -486,10 +493,13 @@ static int lapic_resume(struct sys_device *dev) | |||
486 | { | 493 | { |
487 | unsigned int l, h; | 494 | unsigned int l, h; |
488 | unsigned long flags; | 495 | unsigned long flags; |
496 | int maxlvt; | ||
489 | 497 | ||
490 | if (!apic_pm_state.active) | 498 | if (!apic_pm_state.active) |
491 | return 0; | 499 | return 0; |
492 | 500 | ||
501 | maxlvt = get_maxlvt(); | ||
502 | |||
493 | local_irq_save(flags); | 503 | local_irq_save(flags); |
494 | rdmsr(MSR_IA32_APICBASE, l, h); | 504 | rdmsr(MSR_IA32_APICBASE, l, h); |
495 | l &= ~MSR_IA32_APICBASE_BASE; | 505 | l &= ~MSR_IA32_APICBASE_BASE; |
@@ -503,8 +513,12 @@ static int lapic_resume(struct sys_device *dev) | |||
503 | apic_write(APIC_SPIV, apic_pm_state.apic_spiv); | 513 | apic_write(APIC_SPIV, apic_pm_state.apic_spiv); |
504 | apic_write(APIC_LVT0, apic_pm_state.apic_lvt0); | 514 | apic_write(APIC_LVT0, apic_pm_state.apic_lvt0); |
505 | apic_write(APIC_LVT1, apic_pm_state.apic_lvt1); | 515 | apic_write(APIC_LVT1, apic_pm_state.apic_lvt1); |
506 | apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr); | 516 | #ifdef CONFIG_X86_MCE_INTEL |
507 | apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc); | 517 | if (maxlvt >= 5) |
518 | apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr); | ||
519 | #endif | ||
520 | if (maxlvt >= 4) | ||
521 | apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc); | ||
508 | apic_write(APIC_LVTT, apic_pm_state.apic_lvtt); | 522 | apic_write(APIC_LVTT, apic_pm_state.apic_lvtt); |
509 | apic_write(APIC_TDCR, apic_pm_state.apic_tdcr); | 523 | apic_write(APIC_TDCR, apic_pm_state.apic_tdcr); |
510 | apic_write(APIC_TMICT, apic_pm_state.apic_tmict); | 524 | apic_write(APIC_TMICT, apic_pm_state.apic_tmict); |