diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/Kconfig | 24 | ||||
-rw-r--r-- | arch/x86/include/asm/io_apic.h | 10 | ||||
-rw-r--r-- | arch/x86/include/asm/pci.h | 2 | ||||
-rw-r--r-- | arch/x86/pci/common.c | 17 |
4 files changed, 53 insertions, 0 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 350bee1d54dc..f4ed47db79ee 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -653,6 +653,30 @@ config X86_VISWS_APIC | |||
653 | def_bool y | 653 | def_bool y |
654 | depends on X86_32 && X86_VISWS | 654 | depends on X86_32 && X86_VISWS |
655 | 655 | ||
656 | config X86_REROUTE_FOR_BROKEN_BOOT_IRQS | ||
657 | bool "Reroute for broken boot IRQs" | ||
658 | default n | ||
659 | depends on X86_IO_APIC | ||
660 | help | ||
661 | This option enables a workaround that fixes a source of | ||
662 | spurious interrupts. This is recommended when threaded | ||
663 | interrupt handling is used on systems where the generation of | ||
664 | superfluous "boot interrupts" cannot be disabled. | ||
665 | |||
666 | Some chipsets generate a legacy INTx "boot IRQ" when the IRQ | ||
667 | entry in the chipset's IO-APIC is masked (as, e.g. the RT | ||
668 | kernel does during interrupt handling). On chipsets where this | ||
669 | boot IRQ generation cannot be disabled, this workaround keeps | ||
670 | the original IRQ line masked so that only the equivalent "boot | ||
671 | IRQ" is delivered to the CPUs. The workaround also tells the | ||
672 | kernel to set up the IRQ handler on the boot IRQ line. In this | ||
673 | way only one interrupt is delivered to the kernel. Otherwise | ||
674 | the spurious second interrupt may cause the kernel to bring | ||
675 | down (vital) interrupt lines. | ||
676 | |||
677 | Only affects "broken" chipsets. Interrupt sharing may be | ||
678 | increased on these systems. | ||
679 | |||
656 | config X86_MCE | 680 | config X86_MCE |
657 | bool "Machine Check Exception" | 681 | bool "Machine Check Exception" |
658 | depends on !X86_VOYAGER | 682 | depends on !X86_VOYAGER |
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index 6afd9933a7dd..e475e009ae5d 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h | |||
@@ -156,11 +156,21 @@ extern int sis_apic_bug; | |||
156 | /* 1 if "noapic" boot option passed */ | 156 | /* 1 if "noapic" boot option passed */ |
157 | extern int skip_ioapic_setup; | 157 | extern int skip_ioapic_setup; |
158 | 158 | ||
159 | /* 1 if "noapic" boot option passed */ | ||
160 | extern int noioapicquirk; | ||
161 | |||
162 | /* -1 if "noapic" boot option passed */ | ||
163 | extern int noioapicreroute; | ||
164 | |||
159 | /* 1 if the timer IRQ uses the '8259A Virtual Wire' mode */ | 165 | /* 1 if the timer IRQ uses the '8259A Virtual Wire' mode */ |
160 | extern int timer_through_8259; | 166 | extern int timer_through_8259; |
161 | 167 | ||
162 | static inline void disable_ioapic_setup(void) | 168 | static inline void disable_ioapic_setup(void) |
163 | { | 169 | { |
170 | #ifdef CONFIG_PCI | ||
171 | noioapicquirk = 1; | ||
172 | noioapicreroute = -1; | ||
173 | #endif | ||
164 | skip_ioapic_setup = 1; | 174 | skip_ioapic_setup = 1; |
165 | } | 175 | } |
166 | 176 | ||
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index 875b38edf193..647781298e7e 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h | |||
@@ -19,6 +19,8 @@ struct pci_sysdata { | |||
19 | }; | 19 | }; |
20 | 20 | ||
21 | extern int pci_routeirq; | 21 | extern int pci_routeirq; |
22 | extern int noioapicquirk; | ||
23 | extern int noioapicreroute; | ||
22 | 24 | ||
23 | /* scan a bus after allocating a pci_sysdata for it */ | 25 | /* scan a bus after allocating a pci_sysdata for it */ |
24 | extern struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops, | 26 | extern struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops, |
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index b67732bbb85a..bb1a01f089e2 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c | |||
@@ -23,6 +23,12 @@ unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | | |||
23 | unsigned int pci_early_dump_regs; | 23 | unsigned int pci_early_dump_regs; |
24 | static int pci_bf_sort; | 24 | static int pci_bf_sort; |
25 | int pci_routeirq; | 25 | int pci_routeirq; |
26 | int noioapicquirk; | ||
27 | #ifdef CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS | ||
28 | int noioapicreroute = 0; | ||
29 | #else | ||
30 | int noioapicreroute = 1; | ||
31 | #endif | ||
26 | int pcibios_last_bus = -1; | 32 | int pcibios_last_bus = -1; |
27 | unsigned long pirq_table_addr; | 33 | unsigned long pirq_table_addr; |
28 | struct pci_bus *pci_root_bus; | 34 | struct pci_bus *pci_root_bus; |
@@ -519,6 +525,17 @@ char * __devinit pcibios_setup(char *str) | |||
519 | } else if (!strcmp(str, "skip_isa_align")) { | 525 | } else if (!strcmp(str, "skip_isa_align")) { |
520 | pci_probe |= PCI_CAN_SKIP_ISA_ALIGN; | 526 | pci_probe |= PCI_CAN_SKIP_ISA_ALIGN; |
521 | return NULL; | 527 | return NULL; |
528 | } else if (!strcmp(str, "noioapicquirk")) { | ||
529 | noioapicquirk = 1; | ||
530 | return NULL; | ||
531 | } else if (!strcmp(str, "ioapicreroute")) { | ||
532 | if (noioapicreroute != -1) | ||
533 | noioapicreroute = 0; | ||
534 | return NULL; | ||
535 | } else if (!strcmp(str, "noioapicreroute")) { | ||
536 | if (noioapicreroute != -1) | ||
537 | noioapicreroute = 1; | ||
538 | return NULL; | ||
522 | } | 539 | } |
523 | return str; | 540 | return str; |
524 | } | 541 | } |