diff options
| -rw-r--r-- | Documentation/kernel-parameters.txt | 9 | ||||
| -rw-r--r-- | arch/i386/kernel/acpi/earlyquirk.c | 7 | ||||
| -rw-r--r-- | arch/i386/kernel/io_apic.c | 4 | ||||
| -rw-r--r-- | arch/i386/kernel/setup.c | 5 | ||||
| -rw-r--r-- | arch/x86_64/kernel/io_apic.c | 13 | ||||
| -rw-r--r-- | arch/x86_64/kernel/setup.c | 5 | ||||
| -rw-r--r-- | include/asm-i386/apic.h | 2 | ||||
| -rw-r--r-- | include/asm-x86_64/apic.h | 2 |
8 files changed, 47 insertions, 0 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index db2603ceabba..7086f0a90d14 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
| @@ -164,6 +164,15 @@ running once the system is up. | |||
| 164 | over-ride platform specific driver. | 164 | over-ride platform specific driver. |
| 165 | See also Documentation/acpi-hotkey.txt. | 165 | See also Documentation/acpi-hotkey.txt. |
| 166 | 166 | ||
| 167 | enable_timer_pin_1 [i386,x86-64] | ||
| 168 | Enable PIN 1 of APIC timer | ||
| 169 | Can be useful to work around chipset bugs (in particular on some ATI chipsets) | ||
| 170 | The kernel tries to set a reasonable default. | ||
| 171 | |||
| 172 | disable_timer_pin_1 [i386,x86-64] | ||
| 173 | Disable PIN 1 of APIC timer | ||
| 174 | Can be useful to work around chipset bugs. | ||
| 175 | |||
| 167 | ad1816= [HW,OSS] | 176 | ad1816= [HW,OSS] |
| 168 | Format: <io>,<irq>,<dma>,<dma2> | 177 | Format: <io>,<irq>,<dma>,<dma2> |
| 169 | See also Documentation/sound/oss/AD1816. | 178 | See also Documentation/sound/oss/AD1816. |
diff --git a/arch/i386/kernel/acpi/earlyquirk.c b/arch/i386/kernel/acpi/earlyquirk.c index f1b9d2a46dab..087ecc67e9b3 100644 --- a/arch/i386/kernel/acpi/earlyquirk.c +++ b/arch/i386/kernel/acpi/earlyquirk.c | |||
| @@ -15,6 +15,13 @@ static int __init check_bridge(int vendor, int device) | |||
| 15 | if (vendor == PCI_VENDOR_ID_NVIDIA) { | 15 | if (vendor == PCI_VENDOR_ID_NVIDIA) { |
| 16 | acpi_skip_timer_override = 1; | 16 | acpi_skip_timer_override = 1; |
| 17 | } | 17 | } |
| 18 | /* | ||
| 19 | * ATI IXP chipsets get double timer interrupts. | ||
| 20 | * For now just do this for all ATI chipsets. | ||
| 21 | * FIXME: this needs to be checked for the non ACPI case too. | ||
| 22 | */ | ||
| 23 | if (vendor == PCI_VENDOR_ID_ATI) | ||
| 24 | disable_timer_pin_1 = 1; | ||
| 18 | return 0; | 25 | return 0; |
| 19 | } | 26 | } |
| 20 | 27 | ||
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 35d3ce26a544..378313b0cce9 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c | |||
| @@ -60,6 +60,8 @@ int sis_apic_bug = -1; | |||
| 60 | */ | 60 | */ |
| 61 | int nr_ioapic_registers[MAX_IO_APICS]; | 61 | int nr_ioapic_registers[MAX_IO_APICS]; |
| 62 | 62 | ||
| 63 | int disable_timer_pin_1 __initdata; | ||
| 64 | |||
| 63 | /* | 65 | /* |
| 64 | * Rough estimation of how many shared IRQs there are, can | 66 | * Rough estimation of how many shared IRQs there are, can |
| 65 | * be changed anytime. | 67 | * be changed anytime. |
| @@ -2211,6 +2213,8 @@ static inline void check_timer(void) | |||
| 2211 | setup_nmi(); | 2213 | setup_nmi(); |
| 2212 | enable_8259A_irq(0); | 2214 | enable_8259A_irq(0); |
| 2213 | } | 2215 | } |
| 2216 | if (disable_timer_pin_1 > 0) | ||
| 2217 | clear_IO_APIC_pin(0, pin1); | ||
| 2214 | return; | 2218 | return; |
| 2215 | } | 2219 | } |
| 2216 | clear_IO_APIC_pin(0, pin1); | 2220 | clear_IO_APIC_pin(0, pin1); |
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index f3d808451d25..dc39ca6a7eca 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c | |||
| @@ -851,6 +851,11 @@ static void __init parse_cmdline_early (char ** cmdline_p) | |||
| 851 | #endif | 851 | #endif |
| 852 | 852 | ||
| 853 | #ifdef CONFIG_X86_LOCAL_APIC | 853 | #ifdef CONFIG_X86_LOCAL_APIC |
| 854 | if (!memcmp(from, "disable_timer_pin_1", 19)) | ||
| 855 | disable_timer_pin_1 = 1; | ||
| 856 | if (!memcmp(from, "enable_timer_pin_1", 18)) | ||
| 857 | disable_timer_pin_1 = -1; | ||
| 858 | |||
| 854 | /* disable IO-APIC */ | 859 | /* disable IO-APIC */ |
| 855 | else if (!memcmp(from, "noapic", 6)) | 860 | else if (!memcmp(from, "noapic", 6)) |
| 856 | disable_ioapic_setup(); | 861 | disable_ioapic_setup(); |
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index 961b519bda56..522944a000ad 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c | |||
| @@ -44,6 +44,8 @@ int sis_apic_bug; /* not actually supported, dummy for compile */ | |||
| 44 | 44 | ||
| 45 | static int no_timer_check; | 45 | static int no_timer_check; |
| 46 | 46 | ||
| 47 | int disable_timer_pin_1 __initdata; | ||
| 48 | |||
| 47 | static DEFINE_SPINLOCK(ioapic_lock); | 49 | static DEFINE_SPINLOCK(ioapic_lock); |
| 48 | 50 | ||
| 49 | /* | 51 | /* |
| @@ -297,6 +299,15 @@ void __init check_ioapic(void) | |||
| 297 | #endif | 299 | #endif |
| 298 | /* RED-PEN skip them on mptables too? */ | 300 | /* RED-PEN skip them on mptables too? */ |
| 299 | return; | 301 | return; |
| 302 | case PCI_VENDOR_ID_ATI: | ||
| 303 | /* All timer interrupts on atiixp | ||
| 304 | are doubled. Disable one. */ | ||
| 305 | if (disable_timer_pin_1 == 0) { | ||
| 306 | disable_timer_pin_1 = 1; | ||
| 307 | printk(KERN_INFO | ||
| 308 | "ATI board detected. Disabling timer pin 1.\n"); | ||
| 309 | } | ||
| 310 | return; | ||
| 300 | } | 311 | } |
| 301 | 312 | ||
| 302 | /* No multi-function device? */ | 313 | /* No multi-function device? */ |
| @@ -1658,6 +1669,8 @@ static inline void check_timer(void) | |||
| 1658 | setup_nmi(); | 1669 | setup_nmi(); |
| 1659 | enable_8259A_irq(0); | 1670 | enable_8259A_irq(0); |
| 1660 | } | 1671 | } |
| 1672 | if (disable_timer_pin_1 > 0) | ||
| 1673 | clear_IO_APIC_pin(0, pin1); | ||
| 1661 | return; | 1674 | return; |
| 1662 | } | 1675 | } |
| 1663 | clear_IO_APIC_pin(0, pin1); | 1676 | clear_IO_APIC_pin(0, pin1); |
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 869770da2933..351d8d64c2fb 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c | |||
| @@ -336,6 +336,11 @@ static __init void parse_cmdline_early (char ** cmdline_p) | |||
| 336 | #endif | 336 | #endif |
| 337 | #endif | 337 | #endif |
| 338 | 338 | ||
| 339 | if (!memcmp(from, "disable_timer_pin_1", 19)) | ||
| 340 | disable_timer_pin_1 = 1; | ||
| 341 | if (!memcmp(from, "enable_timer_pin_1", 18)) | ||
| 342 | disable_timer_pin_1 = -1; | ||
| 343 | |||
| 339 | if (!memcmp(from, "nolapic", 7) || | 344 | if (!memcmp(from, "nolapic", 7) || |
| 340 | !memcmp(from, "disableapic", 11)) | 345 | !memcmp(from, "disableapic", 11)) |
| 341 | disable_apic = 1; | 346 | disable_apic = 1; |
diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h index 6a1b1882285c..8c454aa58ac6 100644 --- a/include/asm-i386/apic.h +++ b/include/asm-i386/apic.h | |||
| @@ -130,6 +130,8 @@ extern unsigned int nmi_watchdog; | |||
| 130 | #define NMI_LOCAL_APIC 2 | 130 | #define NMI_LOCAL_APIC 2 |
| 131 | #define NMI_INVALID 3 | 131 | #define NMI_INVALID 3 |
| 132 | 132 | ||
| 133 | extern int disable_timer_pin_1; | ||
| 134 | |||
| 133 | #else /* !CONFIG_X86_LOCAL_APIC */ | 135 | #else /* !CONFIG_X86_LOCAL_APIC */ |
| 134 | static inline void lapic_shutdown(void) { } | 136 | static inline void lapic_shutdown(void) { } |
| 135 | 137 | ||
diff --git a/include/asm-x86_64/apic.h b/include/asm-x86_64/apic.h index 1559d78894ac..6c5d5ca8383a 100644 --- a/include/asm-x86_64/apic.h +++ b/include/asm-x86_64/apic.h | |||
| @@ -109,6 +109,8 @@ extern unsigned int nmi_watchdog; | |||
| 109 | #define NMI_LOCAL_APIC 2 | 109 | #define NMI_LOCAL_APIC 2 |
| 110 | #define NMI_INVALID 3 | 110 | #define NMI_INVALID 3 |
| 111 | 111 | ||
| 112 | extern int disable_timer_pin_1; | ||
| 113 | |||
| 112 | #endif /* CONFIG_X86_LOCAL_APIC */ | 114 | #endif /* CONFIG_X86_LOCAL_APIC */ |
| 113 | 115 | ||
| 114 | extern unsigned boot_cpu_id; | 116 | extern unsigned boot_cpu_id; |
