diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kernel/io_apic.c | 103 |
1 files changed, 52 insertions, 51 deletions
diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index 12e59df026db..ac47384724e3 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c | |||
@@ -643,65 +643,66 @@ static void __init replace_pin_at_irq(unsigned int irq, | |||
643 | add_pin_to_irq(irq, newapic, newpin); | 643 | add_pin_to_irq(irq, newapic, newpin); |
644 | } | 644 | } |
645 | 645 | ||
646 | #define __DO_ACTION(R, ACTION_ENABLE, ACTION_DISABLE, FINAL) \ | 646 | static inline void io_apic_modify_irq(unsigned int irq, |
647 | \ | 647 | int mask_and, int mask_or, |
648 | { \ | 648 | void (*final)(struct irq_pin_list *entry)) |
649 | int pin; \ | 649 | { |
650 | struct irq_cfg *cfg; \ | 650 | int pin; |
651 | struct irq_pin_list *entry; \ | 651 | struct irq_cfg *cfg; |
652 | \ | 652 | struct irq_pin_list *entry; |
653 | cfg = irq_cfg(irq); \ | 653 | |
654 | entry = cfg->irq_2_pin; \ | 654 | cfg = irq_cfg(irq); |
655 | for (;;) { \ | 655 | for (entry = cfg->irq_2_pin; entry != NULL; entry = entry->next) { |
656 | unsigned int reg; \ | 656 | unsigned int reg; |
657 | if (!entry) \ | 657 | pin = entry->pin; |
658 | break; \ | 658 | reg = io_apic_read(entry->apic, 0x10 + pin * 2); |
659 | pin = entry->pin; \ | 659 | reg &= mask_and; |
660 | reg = io_apic_read(entry->apic, 0x10 + R + pin*2); \ | 660 | reg |= mask_or; |
661 | reg ACTION_DISABLE; \ | 661 | io_apic_modify(entry->apic, 0x10 + pin * 2, reg); |
662 | reg ACTION_ENABLE; \ | 662 | if (final) |
663 | io_apic_modify(entry->apic, 0x10 + R + pin*2, reg); \ | 663 | final(entry); |
664 | FINAL; \ | 664 | } |
665 | if (!entry->next) \ | 665 | } |
666 | break; \ | 666 | |
667 | entry = entry->next; \ | 667 | static void __unmask_IO_APIC_irq(unsigned int irq) |
668 | } \ | 668 | { |
669 | } | 669 | io_apic_modify_irq(irq, ~IO_APIC_REDIR_MASKED, 0, NULL); |
670 | 670 | } | |
671 | #define DO_ACTION(name,R, ACTION_ENABLE, ACTION_DISABLE, FINAL) \ | ||
672 | \ | ||
673 | static void name##_IO_APIC_irq (unsigned int irq) \ | ||
674 | __DO_ACTION(R, ACTION_ENABLE, ACTION_DISABLE, FINAL) | ||
675 | |||
676 | /* mask = 0 */ | ||
677 | DO_ACTION(__unmask, 0, |= 0, &= ~IO_APIC_REDIR_MASKED, ) | ||
678 | 671 | ||
679 | #ifdef CONFIG_X86_64 | 672 | #ifdef CONFIG_X86_64 |
680 | /* | 673 | void io_apic_sync(struct irq_pin_list *entry) |
681 | * Synchronize the IO-APIC and the CPU by doing | ||
682 | * a dummy read from the IO-APIC | ||
683 | */ | ||
684 | static inline void io_apic_sync(unsigned int apic) | ||
685 | { | 674 | { |
686 | struct io_apic __iomem *io_apic = io_apic_base(apic); | 675 | /* |
676 | * Synchronize the IO-APIC and the CPU by doing | ||
677 | * a dummy read from the IO-APIC | ||
678 | */ | ||
679 | struct io_apic __iomem *io_apic; | ||
680 | io_apic = io_apic_base(entry->apic); | ||
687 | readl(&io_apic->data); | 681 | readl(&io_apic->data); |
688 | } | 682 | } |
689 | 683 | ||
690 | /* mask = 1 */ | 684 | static void __mask_IO_APIC_irq(unsigned int irq) |
691 | DO_ACTION(__mask, 0, |= IO_APIC_REDIR_MASKED, &= ~0, io_apic_sync(entry->apic)) | 685 | { |
692 | 686 | io_apic_modify_irq(irq, ~0, IO_APIC_REDIR_MASKED, &io_apic_sync); | |
693 | #else | 687 | } |
694 | 688 | #else /* CONFIG_X86_32 */ | |
695 | /* mask = 1 */ | 689 | static void __mask_IO_APIC_irq(unsigned int irq) |
696 | DO_ACTION(__mask, 0, |= IO_APIC_REDIR_MASKED, &= ~0, ) | 690 | { |
697 | 691 | io_apic_modify_irq(irq, ~0, IO_APIC_REDIR_MASKED, NULL); | |
698 | /* mask = 1, trigger = 0 */ | 692 | } |
699 | DO_ACTION(__mask_and_edge, 0, |= IO_APIC_REDIR_MASKED, &= ~IO_APIC_REDIR_LEVEL_TRIGGER, ) | ||
700 | 693 | ||
701 | /* mask = 0, trigger = 1 */ | 694 | static void __mask_and_edge_IO_APIC_irq(unsigned int irq) |
702 | DO_ACTION(__unmask_and_level, 0, |= IO_APIC_REDIR_LEVEL_TRIGGER, &= ~IO_APIC_REDIR_MASKED, ) | 695 | { |
696 | io_apic_modify_irq(irq, ~IO_APIC_REDIR_LEVEL_TRIGGER, | ||
697 | IO_APIC_REDIR_MASKED, NULL); | ||
698 | } | ||
703 | 699 | ||
704 | #endif | 700 | static void __unmask_and_level_IO_APIC_irq(unsigned int irq) |
701 | { | ||
702 | io_apic_modify_irq(irq, ~IO_APIC_REDIR_MASKED, | ||
703 | IO_APIC_REDIR_LEVEL_TRIGGER, NULL); | ||
704 | } | ||
705 | #endif /* CONFIG_X86_32 */ | ||
705 | 706 | ||
706 | static void mask_IO_APIC_irq (unsigned int irq) | 707 | static void mask_IO_APIC_irq (unsigned int irq) |
707 | { | 708 | { |