Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id ; Thu, 16 Jan 2003 13:48:08 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id ; Thu, 16 Jan 2003 13:48:08 -0500 Received: from c185062.adsl.hansenet.de ([213.39.185.62]:34693 "EHLO router.local.rw-it.net") by vger.kernel.org with ESMTP id ; Thu, 16 Jan 2003 13:47:59 -0500 Date: Thu, 16 Jan 2003 19:56:53 +0100 From: Robert Wruck To: linux-kernel@vger.kernel.org Subject: [PATCH] Timer bug fix ported to 2.4.20 Message-ID: <20030116185653.GB5780@router.local.rw-it.net> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4i Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org I recently upgraded from 2.2.19 to 2.4.20 and noted that the via timer bugfix has disappeared. I'm not sure if this is a VIA problem, because it happens on my PIII i440BX-based board, Gigabyte GA-6BXE, which does not seem to have any chips made by VIA. (82443BX, 32371EB PIIX4, ITE 8671 SuperIO) However, whenever i start X, the system clock slows down significantly (it takes about 10 real seconds for 1 system second to elapse). The only patch I could find for this was the one by Neale Banks: http://www.uwsg.iu.edu/hypermail/linux/kernel/0204.1/0005.html I ported this to 2.4.20 and it works (at least for me..) It can still be disabled with "timer=no-via686a" (from the original patch) Any comments? (I'm not subscribed to linux-kernel) Here is some dmesg output generated by the patch: timer.c: VIA bug check triggered. Value read 62758 [0xf526], re-read 62758 [0xf526] timer.c VIA bug really present. <4>Resetting PIT timer. Resetting PIT timer. Resetting PIT timer. timer.c: VIA bug check triggered. Value read 62762 [0xf52a], re-read 62762 [0xf52a] timer.c VIA bug really present. <4>Resetting PIT timer. Resetting PIT timer. Resetting PIT timer. timer.c: VIA bug check triggered. Value read 62756 [0xf524], re-read 62756 [0xf524] timer.c VIA bug really present. <4>Resetting PIT timer. Resetting PIT timer. Resetting PIT timer. Resetting PIT timer. timer.c: VIA bug check triggered. Value read 62760 [0xf528], re-read 62760 [0xf528] timer.c VIA bug really present. <4>Resetting PIT timer. Resetting PIT timer. Resetting PIT timer. Cheers, Robert --- linux-2.4.20/arch/i386/kernel/time.c.orig 2003-01-15 11:33:04.000000000 +0100 +++ linux-2.4.20/arch/i386/kernel/time.c 2003-01-16 16:48:32.000000000 +0100 @@ -84,6 +84,8 @@ spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; +static int via686a_hacks = 1; /* default to enabled */ + static inline unsigned long do_fast_gettimeoffset(void) { register unsigned long eax, edx; @@ -113,6 +115,54 @@ return delay_at_last_interrupt + edx; } +/* + * VIA hardware bug workaround with check if it is really needed and + * a printk that could tell us what's exactly happening on machines which + * trigger the check, but are not VIA-based. + * + * Must be called with the i8253_spinlock held. + */ + +static void via_reset_and_whine(int *count) +{ + static unsigned long last_whine = 0; + unsigned long new_whine; + int count2; + + new_whine = last_whine; + + outb_p(0x00, 0x43); /* Re-read the timer */ + count2 = inb_p(0x40); + count2 |= inb(0x40) << 8; + + if (time_after(jiffies, last_whine)) { + printk(KERN_WARNING "timer.c: VIA bug check triggered. " + "Value read %d [%#x], re-read %d [%#x]\n", + *count, *count, count2, count2); + new_whine = jiffies + HZ; + } + + *count = count2; + + if (count2 > LATCH) { /* Still bad */ + if (time_after(jiffies, last_whine)) { + printk(KERN_WARNING "timer.c VIA bug really present. "); + new_whine = jiffies + HZ; + } + if (via686a_hacks) { + printk(KERN_WARNING "Resetting PIT timer.\n"); + outb_p(0x34, 0x43); + outb_p(LATCH & 0xff, 0x40); + outb(LATCH >> 8, 0x40); + } else { + printk(KERN_WARNING "But VIA hacks disabled.\n"); + } + *count = LATCH - 1; + } + + last_whine = new_whine; +} + #define TICK_SIZE tick spinlock_t i8253_lock = SPIN_LOCK_UNLOCKED; @@ -184,10 +234,7 @@ /* VIA686a test code... reset the latch if count > max + 1 */ if (count > LATCH) { - outb_p(0x34, 0x43); - outb_p(LATCH & 0xff, 0x40); - outb(LATCH >> 8, 0x40); - count = LATCH - 1; + via_reset_and_whine(&count); } spin_unlock(&i8253_lock); @@ -504,6 +551,8 @@ count = inb_p(0x40); /* read the latched count */ count |= inb(0x40) << 8; + if (count > LATCH) + via_reset_and_whine(&count); spin_unlock(&i8253_lock); count = ((LATCH-1) - count) * TICK_SIZE; @@ -717,3 +766,25 @@ setup_irq(0, &irq0); #endif } + +static int __init timer_setup(char *str) +{ + int invert; + + while ((str != NULL) && (*str != '\0')) { + invert = (strncmp(str, "no-", 3) == 0); + if (invert) + str += 3; + if (strncmp(str, "via686a", 7) == 0) { + via686a_hacks = !invert; + if (invert) + printk(KERN_INFO "timer: VIA686a workaround disabled.\n"); + } + str = strchr(str, ','); + if (str != NULL) + str += strspn(str, ", \t"); + } + return 1; +} + +__setup("timer=", timer_setup); - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/