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/x86_64/kernel/apic.c | |
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/x86_64/kernel/apic.c')
-rw-r--r-- | arch/x86_64/kernel/apic.c | 22 |
1 files changed, 18 insertions, 4 deletions
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); |