diff options
Diffstat (limited to 'arch/x86/kernel/apic/io_apic.c')
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 620da6fed6b7..913d4bd2913a 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -593,10 +593,56 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin) | |||
593 | entry = ioapic_read_entry(apic, pin); | 593 | entry = ioapic_read_entry(apic, pin); |
594 | if (entry.delivery_mode == dest_SMI) | 594 | if (entry.delivery_mode == dest_SMI) |
595 | return; | 595 | return; |
596 | |||
597 | /* | ||
598 | * Make sure the entry is masked and re-read the contents to check | ||
599 | * if it is a level triggered pin and if the remote-IRR is set. | ||
600 | */ | ||
601 | if (!entry.mask) { | ||
602 | entry.mask = 1; | ||
603 | ioapic_write_entry(apic, pin, entry); | ||
604 | entry = ioapic_read_entry(apic, pin); | ||
605 | } | ||
606 | |||
607 | if (entry.irr) { | ||
608 | /* | ||
609 | * Make sure the trigger mode is set to level. Explicit EOI | ||
610 | * doesn't clear the remote-IRR if the trigger mode is not | ||
611 | * set to level. | ||
612 | */ | ||
613 | if (!entry.trigger) { | ||
614 | entry.trigger = IOAPIC_LEVEL; | ||
615 | ioapic_write_entry(apic, pin, entry); | ||
616 | } | ||
617 | |||
618 | if (mpc_ioapic_ver(apic) >= 0x20) { | ||
619 | unsigned long flags; | ||
620 | |||
621 | raw_spin_lock_irqsave(&ioapic_lock, flags); | ||
622 | io_apic_eoi(apic, entry.vector); | ||
623 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); | ||
624 | } else { | ||
625 | /* | ||
626 | * Mechanism by which we clear remote-IRR in this | ||
627 | * case is by changing the trigger mode to edge and | ||
628 | * back to level. | ||
629 | */ | ||
630 | entry.trigger = IOAPIC_EDGE; | ||
631 | ioapic_write_entry(apic, pin, entry); | ||
632 | entry.trigger = IOAPIC_LEVEL; | ||
633 | ioapic_write_entry(apic, pin, entry); | ||
634 | } | ||
635 | } | ||
636 | |||
596 | /* | 637 | /* |
597 | * Disable it in the IO-APIC irq-routing table: | 638 | * Clear the rest of the bits in the IO-APIC RTE except for the mask |
639 | * bit. | ||
598 | */ | 640 | */ |
599 | ioapic_mask_entry(apic, pin); | 641 | ioapic_mask_entry(apic, pin); |
642 | entry = ioapic_read_entry(apic, pin); | ||
643 | if (entry.irr) | ||
644 | printk(KERN_ERR "Unable to reset IRR for apic: %d, pin :%d\n", | ||
645 | mpc_ioapic_id(apic), pin); | ||
600 | } | 646 | } |
601 | 647 | ||
602 | static void clear_IO_APIC (void) | 648 | static void clear_IO_APIC (void) |