Package: kernel-source-2.4.27 Version: 2.4.27-8 Severity: normal Tags: patch
The 2.6 kernel series has, since 2.6.5, had a fix for an erroneous timer override present in many BIOSes in nforce[23] chipsets. The 2.4 series is missing this, resulting in an XT_PIC timer on systems that have an APIC-enabled kernel. This is believed to cause system instability, including hard lock-ups (with no ssh). At my request, Zwane Mwaikambo has kindly backported the fix for 2.4.30 and Ihave found that this patch works almost unaltered on Debian's kernel-source-2.4.27. Bearing in mind the proximity of Sarge's release and especially d-i rc3, I thought I should send you the patch for review now. Maybe this will have to be a post-Sarge item but there is a lot of cheap nforce2 out there and 2.6.8 may not be suitable for everyone so I hope you can consider this patch for inclusion in Sarge's 2.4.27. -- System Information: Debian Release: 3.1 Architecture: i386 (i686) Kernel: Linux 2.4.27.20050219.0 Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968) Versions of packages kernel-source-2.4.27 depends on: ii binutils 2.15-5 The GNU assembler, linker and bina ii bzip2 1.0.2-1 A high-quality block-sorting file ii coreutils [fileutils] 5.2.1-2 The GNU core utilities -- no debconf information
# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/02/18 07:53:21-07:00 [EMAIL PROTECTED] # ACPI skip_timer_override backport from 2.6 including early PCI bridge detection. # # include/asm-x86_64/acpi.h # 2005/02/18 07:53:18-07:00 [EMAIL PROTECTED] +1 -0 # ACPI skip_timer_override backport from 2.6 including early PCI bridge detection. # # include/asm-i386/pci-direct.h # 2005/02/18 07:53:18-07:00 [EMAIL PROTECTED] +1 -0 # ACPI skip_timer_override backport from 2.6 including early PCI bridge detection. # # include/asm-i386/acpi.h # 2005/02/18 07:53:18-07:00 [EMAIL PROTECTED] +2 -0 # ACPI skip_timer_override backport from 2.6 including early PCI bridge detection. # # arch/x86_64/kernel/io_apic.c # 2005/02/18 07:53:18-07:00 [EMAIL PROTECTED] +7 -3 # ACPI skip_timer_override backport from 2.6 including early PCI bridge detection. # # arch/x86_64/kernel/acpi.c # 2005/02/18 07:53:18-07:00 [EMAIL PROTECTED] +7 -0 # ACPI skip_timer_override backport from 2.6 including early PCI bridge detection. # # arch/i386/kernel/earlyquirk.c # 2005/02/18 07:53:18-07:00 [EMAIL PROTECTED] +53 -0 # ACPI skip_timer_override backport from 2.6 including early PCI bridge detection. # # arch/i386/kernel/acpi.c # 2005/02/18 07:53:18-07:00 [EMAIL PROTECTED] +9 -0 # ACPI skip_timer_override backport from 2.6 including early PCI bridge detection. # # arch/i386/kernel/Makefile # 2005/02/18 07:53:18-07:00 [EMAIL PROTECTED] +1 -1 # ACPI skip_timer_override backport from 2.6 including early PCI bridge detection. # diff -Nru a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile --- a/arch/i386/kernel/Makefile 2005-02-18 07:53:58 -07:00 +++ b/arch/i386/kernel/Makefile 2005-02-18 07:53:58 -07:00 @@ -40,8 +40,8 @@ obj-$(CONFIG_ACPI_SLEEP) += acpi_wakeup.o obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o obj-$(CONFIG_X86_LOCAL_APIC) += mpparse.o apic.o nmi.o -obj-$(CONFIG_X86_IO_APIC) += io_apic.o +obj-$(CONFIG_X86_IO_APIC) += io_apic.o earlyquirk.o obj-$(CONFIG_X86_VISWS_APIC) += visws_apic.o obj-$(CONFIG_CPU_EMU486) += emu.o obj-$(CONFIG_EDD) += edd.o diff -Nru a/arch/i386/kernel/acpi.c b/arch/i386/kernel/acpi.c --- a/arch/i386/kernel/acpi.c 2005-02-18 07:53:58 -07:00 +++ b/arch/i386/kernel/acpi.c 2005-02-18 07:53:58 -07:00 @@ -55,6 +55,7 @@ acpi_interrupt_flags acpi_sci_flags __initdata; int acpi_sci_override_gsi __initdata; +int acpi_skip_timer_override __initdata; /* -------------------------------------------------------------------------- Boot-time Configuration -------------------------------------------------------------------------- */ @@ -320,6 +321,12 @@ return 0; } + if (acpi_skip_timer_override && + intsrc->bus_irq == 0 && intsrc->global_irq == 2) { + printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n"); + return 0; + } + mp_override_legacy_irq ( intsrc->bus_irq, intsrc->flags.polarity, @@ -433,6 +440,8 @@ return result; } + check_acpi_pci(); + result = acpi_blacklisted(); if (result) { printk(KERN_NOTICE PREFIX "BIOS listed in blacklist, disabling ACPI support\n"); diff -Nru a/arch/i386/kernel/earlyquirk.c b/arch/i386/kernel/earlyquirk.c --- a/arch/i386/kernel/earlyquirk.c 2005-02-18 07:53:58 -07:00 +++ b/arch/i386/kernel/earlyquirk.c 2005-02-18 07:53:58 -07:00 @@ -0,0 +1,53 @@ +/* + * Do early PCI probing for bug detection when the main PCI subsystem is + * not up yet. + */ +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/pci.h> +#include <asm/pci-direct.h> +#include <asm/acpi.h> + +#ifdef CONFIG_ACPI +static int __init check_bridge(int vendor, int device) +{ + /* According to Nvidia all timer overrides are bogus. Just ignore + them all. */ + if (vendor == PCI_VENDOR_ID_NVIDIA) { + acpi_skip_timer_override = 1; + } + return 0; +} + +void __init check_acpi_pci(void) +{ + int num,slot,func; + + /* Assume the machine supports type 1. If not it will + always read ffffffff and should not have any side effect. */ + + /* Poor man's PCI discovery */ + for (num = 0; num < 32; num++) { + for (slot = 0; slot < 32; slot++) { + for (func = 0; func < 8; func++) { + u32 class; + u32 vendor; + class = read_pci_config(num,slot,func, + PCI_CLASS_REVISION); + if (class == 0xffffffff) + break; + + if ((class >> 16) != PCI_CLASS_BRIDGE_PCI) + continue; + + vendor = read_pci_config(num, slot, func, + PCI_VENDOR_ID); + + if (check_bridge(vendor&0xffff, vendor >> 16)) + return; + } + + } + } +} +#endif /* CONFIG_ACPI */ diff -Nru a/arch/x86_64/kernel/acpi.c b/arch/x86_64/kernel/acpi.c --- a/arch/x86_64/kernel/acpi.c 2005-02-18 07:53:58 -07:00 +++ b/arch/x86_64/kernel/acpi.c 2005-02-18 07:53:58 -07:00 @@ -53,6 +53,7 @@ acpi_interrupt_flags acpi_sci_flags __initdata; int acpi_sci_override_gsi __initdata; +int acpi_skip_timer_override __initdata; /* -------------------------------------------------------------------------- Boot-time Configuration -------------------------------------------------------------------------- */ @@ -330,6 +331,12 @@ if (intsrc->bus_irq == acpi_fadt.sci_int) { acpi_sci_ioapic_setup(intsrc->global_irq, intsrc->flags.polarity, intsrc->flags.trigger); + return 0; + } + + if (acpi_skip_timer_override && + intsrc->bus_irq == 0 && intsrc->global_irq == 2) { + printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n"); return 0; } diff -Nru a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c --- a/arch/x86_64/kernel/io_apic.c 2005-02-18 07:53:58 -07:00 +++ b/arch/x86_64/kernel/io_apic.c 2005-02-18 07:53:58 -07:00 @@ -259,10 +259,14 @@ case PCI_VENDOR_ID_VIA: return; case PCI_VENDOR_ID_NVIDIA: +#ifdef CONFIG_ACPI + /* All timer overrides on Nvidia + seem to be wrong. Skip them. */ + acpi_skip_timer_override = 1; printk(KERN_INFO - "PCI bridge %02x:%02x from %x found. Setting \"noapic\". Overwrite with \"apic\"\n", - num,slot,vendor); - skip_ioapic_setup = 1; + "Nvidia board detected. Ignoring ACPI timer override.\n"); +#endif + /* RED-PEN skip them on mptables too? */ return; } diff -Nru a/include/asm-i386/acpi.h b/include/asm-i386/acpi.h --- a/include/asm-i386/acpi.h 2005-02-18 07:53:58 -07:00 +++ b/include/asm-i386/acpi.h 2005-02-18 07:53:58 -07:00 @@ -121,6 +121,8 @@ extern int acpi_strict; extern int acpi_disabled; extern int acpi_ht; +extern int acpi_skip_timer_override; +void __init check_acpi_pci(void); static inline void disable_acpi(void) { acpi_disabled = 1; diff -Nru a/include/asm-i386/pci-direct.h b/include/asm-i386/pci-direct.h --- a/include/asm-i386/pci-direct.h 2005-02-18 07:53:58 -07:00 +++ b/include/asm-i386/pci-direct.h 2005-02-18 07:53:58 -07:00 @@ -0,0 +1 @@ +#include "asm-x86_64/pci-direct.h" diff -Nru a/include/asm-x86_64/acpi.h b/include/asm-x86_64/acpi.h --- a/include/asm-x86_64/acpi.h 2005-02-18 07:53:58 -07:00 +++ b/include/asm-x86_64/acpi.h 2005-02-18 07:53:58 -07:00 @@ -118,6 +118,7 @@ extern int acpi_strict; extern int acpi_disabled; extern int acpi_ht; +extern int acpi_skip_timer_override; static inline void disable_acpi(void) { acpi_disabled = 1;