> Hi Vojtech,
> 
> Appended patch:
> 
> (a) merges your patch of November 2001 into 2.2.21rc3
> (b) adds a boot-time option to explicitly disable the via-timer hacks.
> 
> I've been using this patch for a while, but haven't subjected it to more
> thorough testing than that it boots OK and doesn't appear to complicate
> anything (I might be able to trigger the relevant condition by running the
> battery right down on my (old) AcerNote-950, but one of the last times
> this happened I also got some pretty nasty file system corruption - so I'm
> not too keen to try that one again :-| ).
> 
> Anyway, does this patch and my merge of it look correct?
Looks OK.
> 
> Thanks,
> Neale.
> 
> --- linux-2.2.21-rc3-orig/arch/i386/kernel/time.c	Mon Mar 26 02:37:30 2001
> +++ linux-2.2.21-rc3-ntb/arch/i386/kernel/time.c	Fri Apr  5 23:04:13 2002
> @@ -81,6 +81,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 asm("ax");
> @@ -111,6 +113,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
>  
>  #ifndef CONFIG_X86_TSC
> @@ -177,12 +227,8 @@
>  	count |= inb_p(0x40) << 8;
>  
>  	/* VIA686a test code... reset the latch if count > max */
> - 	if (count > LATCH-1) {
> -		outb_p(0x34, 0x43);
> -		outb_p(LATCH & 0xff, 0x40);
> -		outb(LATCH >> 8, 0x40);
> -		count = LATCH - 1;
> -	}	
> +	if (count > LATCH)
> +		via_reset_and_whine(&count);
>  	
>  	/*
>  	 * avoiding timer inconsistencies (they are rare, but they happen)...
> @@ -478,19 +524,8 @@
>  		count |= inb(0x40) << 8;
>  
>  		/* VIA686a test code... reset the latch if count > max */
> -		if (count > LATCH-1) {
> -			static int last_whine;
> -			outb_p(0x34, 0x43);
> -			outb_p(LATCH & 0xff, 0x40);
> -			outb(LATCH >> 8, 0x40);
> -			count = LATCH - 1;
> -			if(time_after(jiffies, last_whine))
> -			{
> -				printk(KERN_WARNING "probable hardware bug: clock timer configuration lost - probably a VIA686a.\n");
> -				printk(KERN_WARNING "probable hardware bug: restoring chip configuration.\n");
> -				last_whine = jiffies + HZ;
> -			}			
> -		}	
> +		if (count > LATCH)
> +			via_reset_and_whine(&count);
>  
>  #if 0
>  		spin_unlock(&i8253_lock);
> @@ -737,3 +772,25 @@
>  	setup_x86_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);
-- Vojtech Pavlik SuSE Labs - 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/