[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#296639: kernel-source-2.4.27: nforce[23] backport of acpi_skip_timer_override



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 zwane@montezuma.fsmlabs.com 
#   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 zwane@montezuma.fsmlabs.com +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 zwane@montezuma.fsmlabs.com +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 zwane@montezuma.fsmlabs.com +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 zwane@montezuma.fsmlabs.com +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 zwane@montezuma.fsmlabs.com +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 zwane@montezuma.fsmlabs.com +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 zwane@montezuma.fsmlabs.com +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 zwane@montezuma.fsmlabs.com +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;

Reply to: