From: white phoenix <white.phoenix@gmail.com>
To: linux-kernel@vger.kernel.org
Subject: nforce2 bugs?
Date: Wed, 29 Sep 2004 18:42:23 -0400 [thread overview]
Message-ID: <e2ae0e3b04092915427fcff604@mail.gmail.com> (raw)
I'm wondering if any of the older nforce2 chipset bugs have been fixed
in recent kernels. i've seen a number of nforce2 kernel patches
floating around. can someone tell me what some of these do? lol.
---------------------------nforce2-disconnect-quirk.patch:------------------------------------------------------------
[x86] fix lockups with APIC support on nForce2
Add PCI quirk to disable Halt Disconnect and Stop Grant Disconnect
(based on athcool program by Osamu Kayasono).
Spotted by Prakash K. Cheemplavam <prakashpublic@gmx.de>
and Mathieu <cheuche+lkml@free.fr>.
arch/i386/pci/fixup.c | 17 +++++++++++++++++
1 files changed, 17 insertions(+)
diff -puN arch/i386/pci/fixup.c~nforce2-disconnect-quirk arch/i386/pci/fixup.c
--- linux-2.6.0-test11/arch/i386/pci/fixup.c~nforce2-disconnect-quirk 2003-12-08
00:09:56.480294672 +0100
+++ linux-2.6.0-test11-root/arch/i386/pci/fixup.c 2003-12-08
00:09:56.484294064 +0100
@@ -187,6 +187,22 @@ static void __devinit pci_fixup_transpar
dev->transparent = 1;
}
+/*
+ * Halt Disconnect and Stop Grant Disconnect (bit 4 at offset 0x6F)
+ * must be disabled when APIC is used (or lockups will happen).
+ */
+static void __devinit pci_fixup_nforce2_disconnect(struct pci_dev *d)
+{
+ u8 t;
+
+ pci_read_config_byte(d, 0x6F, &t);
+ if (t & 0x10) {
+ printk(KERN_INFO "PCI: disabling nForce2 Halt Disconnect"
+ " and Stop Grant Disconnect\n");
+ pci_write_config_byte(d, 0x6F, (t & 0xef));
+ }
+}
+
struct pci_fixup pcibios_fixups[] = {
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx
},
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx
},
@@ -205,5 +221,6 @@ struct pci_fixup pcibios_fixups[] = {
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_via_northbridge_bug
},
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, pci_fixup_ncr53c810
},
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_fixup_transparent_bridge
},
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci_fixup_nforce2_disconnect
},
{ 0 }
};
_
----------------------------------nforce2-idleC1halt-rd-2.6.5.patch---------------------------------------------------
--- linux-2.6.5/arch/i386/kernel/process.c.orig 2004-04-04
13:36:10.000000000 +1000
+++ linux-2.6.5/arch/i386/kernel/process.c 2004-04-15 20:41:13.000000000 +1000
@@ -47,10 +47,13 @@
#include <asm/irq.h>
#include <asm/desc.h>
#ifdef CONFIG_MATH_EMULATION
#include <asm/math_emu.h>
#endif
+#if defined(CONFIG_X86_UP_APIC)
+#include <asm/apic.h>
+#endif
#include <linux/irq.h>
#include <linux/err.h>
asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
@@ -98,10 +101,34 @@ void default_idle(void)
local_irq_enable();
}
}
/*
+ * We use this to avoid nforce2 lockups
+ * Reduces frequency of C1 disconnects
+ */
+static void c1halt_idle(void)
+{
+ if (!hlt_counter && current_cpu_data.hlt_works_ok) {
+ local_irq_disable();
+#if defined(CONFIG_X86_UP_APIC)
+ /* only hlt disconnect if more than 1.6% of apic interval remains */
+ extern int enable_local_apic;
+ if(!need_resched() && (enable_local_apic < 0 ||
+ (apic_read(APIC_TMCCT) > (apic_read(APIC_TMICT)>>6)))) {
+#else
+ /* just adds a little delay to assist in back to back disconnects */
+ if(!need_resched()) {
+#endif
+ ndelay(600); /* helps nforce2 but adds 0.6us hard int latency */
+ safe_halt(); /* nothing better to do until we wake up */
+ } else {
+ local_irq_enable();
+ }
+ }
+}
+/*
* On SMP it's slightly faster (but much more power-consuming!)
* to poll the ->work.need_resched flag instead of waiting for the
* cross-CPU IPI to arrive. Use this option with caution.
*/
static void poll_idle (void)
@@ -135,20 +162,18 @@ static void poll_idle (void)
* The idle thread. There's no useful work to be
* done, so just try to conserve power and have a
* low exit latency (ie sit in a loop waiting for
* somebody to say that they'd like to reschedule)
*/
+static void (*idle)(void);
void cpu_idle (void)
{
/* endless idle loop with no priority at all */
while (1) {
while (!need_resched()) {
- void (*idle)(void) = pm_idle;
-
if (!idle)
- idle = default_idle;
-
+ idle = pm_idle ? pm_idle : default_idle;
irq_stat[smp_processor_id()].idle_timestamp = jiffies;
idle();
}
schedule();
}
@@ -199,16 +224,18 @@ void __init select_idle_routine(const st
static int __init idle_setup (char *str)
{
if (!strncmp(str, "poll", 4)) {
printk("using polling idle threads.\n");
- pm_idle = poll_idle;
+ idle = poll_idle;
} else if (!strncmp(str, "halt", 4)) {
printk("using halt in idle threads.\n");
- pm_idle = default_idle;
+ idle = default_idle;
+ } else if (!strncmp(str, "C1halt", 6)) {
+ printk("using C1 halt disconnect friendly idle threads.\n");
+ idle = c1halt_idle;
}
-
return 1;
}
__setup("idle=", idle_setup);
--------------------------------------------nforce2-ioapic-rd-2.6.5.patch-----------------------------------------------
--- linux-2.6.5/arch/i386/kernel/io_apic.c.orig 2004-04-16
00:20:54.000000000 +1000
+++ linux-2.6.5/arch/i386/kernel/io_apic.c 2004-04-15 20:24:18.000000000 +1000
@@ -2179,10 +2179,13 @@ static inline void check_timer(void)
if (pin1 != -1) {
/*
* Ok, does IRQ0 through the IOAPIC work?
*/
+ extern int acpi_skip_timer_override;
+ if(acpi_skip_timer_override)
+ timer_ack=0;
unmask_IO_APIC_irq(0);
if (timer_irq_works()) {
if (nmi_watchdog == NMI_IO_APIC) {
disable_8259A_irq(0);
setup_nmi();
--------------------------------------------nforce-apic-tack.patch--------------------------------------------------------
--- linux-2.6.0/arch/i386/kernel/apic.c 2003-12-18 12:59:58.000000000 +1000
+++ linux-2.6.0-rd/arch/i386/kernel/apic.c 2003-12-21 12:39:28.000000000 +1000
@@ -1070,10 +1070,17 @@ inline void smp_local_timer_interrupt(st
* we can take more than 100K local irqs per second on a 100 MHz P5.
*/
}
/*
+ * Athlon nforce2 R.D.
+ * preset timer ack mode if desired
+ * e.g. static int apic_timerack = 2;
+*/
+static int apic_timerack;
+
+/*
* Local APIC timer interrupt. This is the most natural way for doing
* local interrupts, but local timer interrupts can be emulated by
* broadcast interrupts too. [in case the hw doesn't support APIC timers]
*
* [ if a single-CPU system runs an SMP kernel then we call the local
@@ -1088,10 +1095,54 @@ void smp_apic_timer_interrupt(struct pt_
* the NMI deadlock-detector uses this.
*/
irq_stat[cpu].apic_timer_irqs++;
/*
+ * Athlon nforce2 timer ack delay. Ross Dickson.
+ * works around issue of hard lockups in code location
+ * where linux exposes underlying system timing fault?
+ * hopefully manufacturers will fix it soon.
+ * We leave C1 disconnect bit alone as bios/SMM wants?
+ */
+ if(apic_timerack) {
+ if(apic_timerack==1) {
+ /* v1 timer ack delay, inline delay version
+ * on AMDXP & nforce2 chipset we use at least 500ns
+ * try to scale delay time with cpu speed.
+ * safe all cpu cores?
+ */
+ ndelay((cpu_khz >> 12)+200); /* don't ack too soon or hard lockup */
+ } else {
+ static unsigned int passno, safecnt;
+ /* v2 timer ack delay, timeout version, more efficient
+ * on AMDXP & nforce2 chipset we need 800ns?
+ * from timer irq start to apic irq ack, read apic timer,
+ * may be unsafe for thoroughbred cores?
+ */
+ if(!passno) { /* calculate timing */
+ safecnt = apic_read(APIC_TMICT) -
+ ( (800UL * apic_read(APIC_TMICT) ) /
+ (1000000000UL/HZ) );
+ printk("..APIC TIMER ack delay, reload:%lu, safe:%u\n",
+ apic_read(APIC_TMICT), safecnt);
+ passno++;
+ }
+#if APIC_DEBUG
+ if(passno<12) {
+ unsigned int at1 = apic_read(APIC_TMCCT);
+ if( passno > 1 )
+ Dprintk("..APIC TIMER ack delay, predelay count:%u \n", at1 );
+ passno++;
+ }
+# endif
+ /* delay only if required */
+ while( apic_read(APIC_TMCCT) > safecnt )
+ ndelay(100);
+ }
+ }
+
+ /*
* NOTE! We'd better ACK the irq immediately,
* because timer handling can be slow.
*/
ack_APIC_irq();
/*
@@ -1157,10 +1208,28 @@ asmlinkage void smp_error_interrupt(void
smp_processor_id(), v , v1);
irq_exit();
}
/*
+* Athlon nforce2 timer ack delay. R.D.
+* kernel arg apic_tack=[012]
+* 0 off, 1 always delay, 2 timeout
+*/
+static int __init setup_apic_timerack(char *str)
+{
+ int tack;
+
+ get_option(&str, &tack);
+
+ if ( tack < 0 || tack > 2 )
+ return 0;
+ apic_timerack = tack;
+ return 1;
+}
+__setup("apic_tack=", setup_apic_timerack);
+
+/*
* This initializes the IO-APIC and APIC hardware if this is
* a UP kernel.
*/
int __init APIC_init_uniprocessor (void)
{
--- CUT HERE ---
io-apic edge:
--- CUT HERE ---
--- linux-2.6.0/arch/i386/kernel/io_apic.c 2003-12-18 12:58:39.000000000 +1000
+++ linux-2.6.0-rd/arch/i386/kernel/io_apic.c 2003-12-20
21:41:52.000000000 +1000
@@ -2123,12 +2123,56 @@ static inline void check_timer(void)
check_nmi_watchdog();
}
return;
}
clear_IO_APIC_pin(0, pin1);
- printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to IO-APIC\n");
+ printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to IO-APIC
INTIN%d\n",pin1);
+ }
+
+#if defined(CONFIG_ACPI_BOOT) && defined(CONFIG_X86_UP_IOAPIC)
+ /* for nforce2 try vector 0 on pin0
+ * Note 8259a is already masked, also by default
+ * the io_apic_set_pci_routing call disables the 8259 irq 0
+ * so we must be connected directly to the 8254 timer if this works
+ * Note2: this violates the above comment re Subtle but works!
+ */
+ printk(KERN_INFO "..TIMER: Is timer irq0 connected to IO-APIC INTIN0? ...\n");
+ if (pin1 != -1) {
+ extern spinlock_t i8259A_lock;
+ unsigned long flags;
+ int tok, saved_timer_ack = timer_ack;
+ /*
+ * Ok, does IRQ0 through the IOAPIC work?
+ */
+ io_apic_set_pci_routing ( 0, 0, 0, 0, 0); /* connect pin */
+ unmask_IO_APIC_irq(0);
+ timer_ack = 0;
+
+ /*
+ * Ok, does IRQ0 through the IOAPIC work?
+ */
+ spin_lock_irqsave(&i8259A_lock, flags);
+ Dprintk("..TIMER 8259A ints disabled?, imr1:%02x, imr2:%02x\n",
inb(0x21), inb(0xA1));
+ tok = timer_irq_works();
+ spin_unlock_irqrestore(&i8259A_lock, flags);
+ if (tok) {
+ if (nmi_watchdog == NMI_IO_APIC) {
+ disable_8259A_irq(0);
+ setup_nmi();
+ enable_8259A_irq(0);
+ check_nmi_watchdog();
+ }
+ printk(KERN_INFO "..TIMER: works OK on IO-APIC INTIN0 irq0\n" );
+ return;
+ }
+ /* failed */
+ timer_ack = saved_timer_ack;
+ clear_IO_APIC_pin(0, 0);
+ io_apic_set_pci_routing ( 0, pin1, 0, 0, 0);
+ printk(KERN_ERR "..MP-BIOS: 8254 timer not connected to IO-APIC INTIN0\n");
}
+#endif
printk(KERN_INFO "...trying to set up timer (IRQ0) through the 8259A ... ");
if (pin2 != -1) {
printk("\n..... (found pin %d) ...", pin2);
/*
-----------------------------------more-nforce-fixes.patch----------------------------------------------------------------
===== Documentation/kernel-parameters.txt 1.44 vs edited =====
--- 1.44/Documentation/kernel-parameters.txt Mon Mar 22 16:03:22 2004
+++ edited/Documentation/kernel-parameters.txt Wed Apr 21 15:28:12 2004
@@ -122,6 +122,10 @@
acpi_serialize [HW,ACPI] force serialization of AML methods
+ acpi_skip_timer_override [HW,ACPI]
+ Recognize and ignore IRQ0/pin2 Interrupt Override.
+ For broken nForce2 BIOS resulting in XT-PIC timer.
+
ad1816= [HW,OSS]
Format: <io>,<irq>,<dma>,<dma2>
See also Documentation/sound/oss/AD1816.
===== arch/i386/kernel/dmi_scan.c 1.57 vs edited =====
--- 1.57/arch/i386/kernel/dmi_scan.c Fri Apr 16 22:03:06 2004
+++ edited/arch/i386/kernel/dmi_scan.c Wed Apr 21 18:29:35 2004
@@ -540,6 +540,19 @@
#endif
/*
+ * early nForce2 reference BIOS shipped with a
+ * bogus ACPI IRQ0 -> pin2 interrupt override -- ignore it
+ */
+static __init int ignore_timer_override(struct dmi_blacklist *d)
+{
+ extern int acpi_skip_timer_override;
+ printk(KERN_NOTICE "%s detected: BIOS IRQ0 pin2 override"
+ " will be ignored\n", d->ident);
+
+ acpi_skip_timer_override = 1;
+ return 0;
+}
+/*
* Process the DMI blacklists
*/
@@ -944,6 +957,37 @@
MATCH(DMI_BOARD_VENDOR, "IBM"),
MATCH(DMI_PRODUCT_NAME, "eserver xSeries 440"),
NO_MATCH, NO_MATCH }},
+
+/*
+ * Systems with nForce2 BIOS timer override bug
+ * add Albatron KM18G Pro
+ * add DFI NFII 400-AL
+ * add Epox 8RGA+
+ * add Shuttle AN35N
+ */
+ { ignore_timer_override, "Abit NF7-S v2", {
+ MATCH(DMI_BOARD_VENDOR, "http://www.abit.com.tw/"),
+ MATCH(DMI_BOARD_NAME, "NF7-S/NF7,NF7-V (nVidia-nForce2)"),
+ MATCH(DMI_BIOS_VERSION, "6.00 PG"),
+ MATCH(DMI_BIOS_DATE, "03/24/2004") }},
+
+ { ignore_timer_override, "Asus A7N8X v2", {
+ MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ MATCH(DMI_BOARD_NAME, "A7N8X2.0"),
+ MATCH(DMI_BIOS_VERSION, "ASUS A7N8X2.0 Deluxe ACPI BIOS Rev 1007"),
+ MATCH(DMI_BIOS_DATE, "10/06/2003") }},
+
+ { ignore_timer_override, "Asus A7N8X-X", {
+ MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ MATCH(DMI_BOARD_NAME, "A7N8X-X"),
+ MATCH(DMI_BIOS_VERSION, "ASUS A7N8X-X ACPI BIOS Rev 1007"),
+ MATCH(DMI_BIOS_DATE, "10/07/2003") }},
+
+ { ignore_timer_override, "Shuttle SN41G2", {
+ MATCH(DMI_BOARD_VENDOR, "Shuttle Inc"),
+ MATCH(DMI_BOARD_NAME, "FN41"),
+ MATCH(DMI_BIOS_VERSION, "6.00 PG"),
+ MATCH(DMI_BIOS_DATE, "01/14/2004") }},
#endif // CONFIG_ACPI_BOOT
#ifdef CONFIG_ACPI_PCI
===== arch/i386/kernel/setup.c 1.115 vs edited =====
--- 1.115/arch/i386/kernel/setup.c Fri Apr 2 07:21:43 2004
+++ edited/arch/i386/kernel/setup.c Wed Apr 21 15:28:12 2004
@@ -614,6 +614,9 @@
else if (!memcmp(from, "acpi_sci=low", 12))
acpi_sci_flags.polarity = 3;
+ else if (!memcmp(from, "acpi_skip_timer_override", 24))
+ acpi_skip_timer_override = 1;
+
#ifdef CONFIG_X86_LOCAL_APIC
/* disable IO-APIC */
else if (!memcmp(from, "noapic", 6))
===== arch/i386/kernel/acpi/boot.c 1.58 vs edited =====
--- 1.58/arch/i386/kernel/acpi/boot.c Tue Apr 20 20:54:03 2004
+++ edited/arch/i386/kernel/acpi/boot.c Wed Apr 21 15:28:13 2004
@@ -62,6 +62,7 @@
acpi_interrupt_flags acpi_sci_flags __initdata;
int acpi_sci_override_gsi __initdata;
+int acpi_skip_timer_override __initdata;
#ifdef CONFIG_X86_LOCAL_APIC
static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
@@ -327,6 +328,12 @@
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;
}
mp_override_legacy_irq (
===== include/asm-i386/acpi.h 1.18 vs edited =====
--- 1.18/include/asm-i386/acpi.h Tue Mar 30 17:05:19 2004
+++ edited/include/asm-i386/acpi.h Wed Apr 21 15:28:14 2004
@@ -118,6 +118,7 @@
#ifdef CONFIG_X86_IO_APIC
extern int skip_ioapic_setup;
extern int acpi_irq_to_vector(u32 irq); /* deprecated in favor of
acpi_gsi_to_irq */
+extern int acpi_skip_timer_override;
static inline void disable_ioapic_setup(void)
{
next reply other threads:[~2004-09-29 22:46 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-09-29 22:42 white phoenix [this message]
2004-09-29 22:17 ` nforce2 bugs? Alan Cox
2004-09-30 0:32 ` white phoenix
2004-09-30 9:25 ` Prakash K. Cheemplavam
2004-09-30 14:24 ` Maciej W. Rozycki
-- strict thread matches above, loose matches on Subject: below --
2004-09-30 15:43 Andy Currid
2004-09-30 16:59 ` Maciej W. Rozycki
2004-10-01 3:41 ` Ross Dickson
2004-10-01 11:16 ` Jesse Stockall
2004-10-02 2:13 Jesse Allen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=e2ae0e3b04092915427fcff604@mail.gmail.com \
--to=white.phoenix@gmail.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.