aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/io_apic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/io_apic.c')
-rw-r--r--arch/x86/kernel/io_apic.c103
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) \ 646static 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; \ 667static 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 */
677DO_ACTION(__unmask, 0, |= 0, &= ~IO_APIC_REDIR_MASKED, )
678 671
679#ifdef CONFIG_X86_64 672#ifdef CONFIG_X86_64
680/* 673void 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 */
684static 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 */ 684static void __mask_IO_APIC_irq(unsigned int irq)
691DO_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 */ 689static void __mask_IO_APIC_irq(unsigned int irq)
696DO_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}
699DO_ACTION(__mask_and_edge, 0, |= IO_APIC_REDIR_MASKED, &= ~IO_APIC_REDIR_LEVEL_TRIGGER, )
700 693
701/* mask = 0, trigger = 1 */ 694static void __mask_and_edge_IO_APIC_irq(unsigned int irq)
702DO_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 700static 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
706static void mask_IO_APIC_irq (unsigned int irq) 707static void mask_IO_APIC_irq (unsigned int irq)
707{ 708{