aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/apic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/apic.c')
-rw-r--r--arch/i386/kernel/apic.c29
1 files changed, 26 insertions, 3 deletions
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index f39e09ef64ec..6273bf74c203 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -38,6 +38,7 @@
38#include <asm/i8253.h> 38#include <asm/i8253.h>
39 39
40#include <mach_apic.h> 40#include <mach_apic.h>
41#include <mach_apicdef.h>
41#include <mach_ipi.h> 42#include <mach_ipi.h>
42 43
43#include "io_ports.h" 44#include "io_ports.h"
@@ -414,6 +415,7 @@ void __init init_bsp_APIC(void)
414void __devinit setup_local_APIC(void) 415void __devinit setup_local_APIC(void)
415{ 416{
416 unsigned long oldvalue, value, ver, maxlvt; 417 unsigned long oldvalue, value, ver, maxlvt;
418 int i, j;
417 419
418 /* Pound the ESR really hard over the head with a big hammer - mbligh */ 420 /* Pound the ESR really hard over the head with a big hammer - mbligh */
419 if (esr_disable) { 421 if (esr_disable) {
@@ -451,6 +453,25 @@ void __devinit setup_local_APIC(void)
451 apic_write_around(APIC_TASKPRI, value); 453 apic_write_around(APIC_TASKPRI, value);
452 454
453 /* 455 /*
456 * After a crash, we no longer service the interrupts and a pending
457 * interrupt from previous kernel might still have ISR bit set.
458 *
459 * Most probably by now CPU has serviced that pending interrupt and
460 * it might not have done the ack_APIC_irq() because it thought,
461 * interrupt came from i8259 as ExtInt. LAPIC did not get EOI so it
462 * does not clear the ISR bit and cpu thinks it has already serivced
463 * the interrupt. Hence a vector might get locked. It was noticed
464 * for timer irq (vector 0x31). Issue an extra EOI to clear ISR.
465 */
466 for (i = APIC_ISR_NR - 1; i >= 0; i--) {
467 value = apic_read(APIC_ISR + i*0x10);
468 for (j = 31; j >= 0; j--) {
469 if (value & (1<<j))
470 ack_APIC_irq();
471 }
472 }
473
474 /*
454 * Now that we are all set up, enable the APIC 475 * Now that we are all set up, enable the APIC
455 */ 476 */
456 value = apic_read(APIC_SPIV); 477 value = apic_read(APIC_SPIV);
@@ -570,16 +591,18 @@ void __devinit setup_local_APIC(void)
570 */ 591 */
571void lapic_shutdown(void) 592void lapic_shutdown(void)
572{ 593{
594 unsigned long flags;
595
573 if (!cpu_has_apic) 596 if (!cpu_has_apic)
574 return; 597 return;
575 598
576 local_irq_disable(); 599 local_irq_save(flags);
577 clear_local_APIC(); 600 clear_local_APIC();
578 601
579 if (enabled_via_apicbase) 602 if (enabled_via_apicbase)
580 disable_local_APIC(); 603 disable_local_APIC();
581 604
582 local_irq_enable(); 605 local_irq_restore(flags);
583} 606}
584 607
585#ifdef CONFIG_PM 608#ifdef CONFIG_PM
@@ -729,7 +752,7 @@ static int __init apic_set_verbosity(char *str)
729 printk(KERN_WARNING "APIC Verbosity level %s not recognised" 752 printk(KERN_WARNING "APIC Verbosity level %s not recognised"
730 " use apic=verbose or apic=debug\n", str); 753 " use apic=verbose or apic=debug\n", str);
731 754
732 return 0; 755 return 1;
733} 756}
734 757
735__setup("apic=", apic_set_verbosity); 758__setup("apic=", apic_set_verbosity);