public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: George Anzinger <george@mvista.com>
To: Parag Warudkar <kernel-stuff@comcast.net>
Cc: Dominik Brodowski <linux@dominikbrodowski.net>,
	john stultz <johnstul@us.ibm.com>,
	Nishanth Aravamudan <nacc@us.ibm.com>, Andi Kleen <ak@suse.de>,
	lkml <linux-kernel@vger.kernel.org>,
	Tim Schmielau <tim@physik3.uni-rostock.de>,
	albert@users.sourceforge.net,
	Ulrich Windl <ulrich.windl@rz.uni-regensburg.de>,
	Christoph Lameter <clameter@sgi.com>,
	David Mosberger <davidm@hpl.hp.com>,
	Andrew Morton <akpm@osdl.org>,
	paulus@samba.org, schwidefsky@de.ibm.com,
	keith maanthey <kmannth@us.ibm.com>,
	Chris McDermott <lcm@us.ibm.com>, Max Asbock <masbock@us.ibm.com>,
	mahuja@us.ibm.com, Darren Hart <darren@dvhart.com>,
	"Darrick J. Wong" <djwong@us.ibm.com>,
	Anton Blanchard <anton@samba.org>,
	donf@us.ibm.com, mpm@selenic.com, benh@kernel.crashing.org
Subject: Re: [PATCH 3/4] new timeofday x86-64 arch specific changes (v. B1)
Date: Thu, 09 Jun 2005 17:48:41 -0700	[thread overview]
Message-ID: <42A8E369.8080504@mvista.com> (raw)
In-Reply-To: <200506052304.35298.kernel-stuff@comcast.net>

Parag Warudkar wrote:
> On Sunday 05 June 2005 13:05, Dominik Brodowski wrote:
> 
>>IIRC (from the comment above) several chipsets suffer from this
>>inconsistency, namely the widely used PIIX4(E) and ICH(4 only? or also
>>other ICH-ones?). Therefore, we'd need at least some sort of boot-time
>>check to decide which method to use... and based on the method, we can
>>adjust the priority maybe?
> 
> 
> To begin with, will the simple proof-of-concept patch like below work? (It 
> tests the chipset read in the same do{}while loop - if the loop executes only 
> once, it considers the chipset good - in which case it executes the faster 
> read_pmtmr_fast function.) Or does it need wider testing under different 
> circumstances to conclude that chipset is good?
> 
> I tested the patch under Virtual PC which emulates a PIIX4 chipset. Test 
> passes there, meaning the do {}while  loop executes only once.

As I understand the problem it is that the counter is, sometimes, read while it 
is is rippling the carry up to the higher bits.  This will only happen if the 
read is done just as the hardware is bumping the count and even then only if 
there is a carry.  Exactly where in the carry sequency this happens is likely 
just a guess.

In the HRT patch I take care of this by testing the read against a prior read 
(up to 1/HZ away).  If the number is bigger and to too much bigger, I just do 
one read.  Here is the full routine:

quick_get_cpuctr(void)
{
	static  unsigned long last_read = 0;
	static  int qgc_max = 0;
	int i;

	unsigned long rd_delta, rd_ans, rd = inl(acpi_pm_tmr_address);

	/*
	 * This will be REALLY big if ever we move backward in time...
	 */
	rd_delta = (rd - last_read) & SIZE_MASK;
	last_read = rd;

	rd_ans =  (rd - last_update) & SIZE_MASK;

	if (likely((rd_ans < (arch_cycles_per_jiffy << 1)) &&
		   (rd_delta < (arch_cycles_per_jiffy << 1))))
		return rd_ans;

	for (i = 0; i < 10; i++) {
		rd = inl(acpi_pm_tmr_address);
		rd_delta = (rd - last_read) & SIZE_MASK;
		last_read = rd;
		if (unlikely(i > qgc_max))
			qgc_max = i;
		/*
		 * On my test machine (800MHZ dual PIII) this is always
		 * seven.  Seems long, but we will give it some slack...
		 * We note that rd_delta (and all the vars) unsigned so
		 * a backward movement will show as a really big number.
		 */
		if (likely(rd_delta < 20))
			return (rd - last_update) & SIZE_MASK;
	}
	return (rd - last_update) & SIZE_MASK;
}
George
-- 
> 
> Parag
> 
> 
> ------------------------------------------------------------------------
> 
> --- linux-2.6-orig/arch/i386/kernel/timers/timer_pm.c	2005-03-02 02:37:48.000000000 -0500
> +++ linux-2.6.12-rc5/arch/i386/kernel/timers/timer_pm.c	2005-06-05 23:01:15.000000000 -0400
> @@ -35,6 +35,10 @@
>   * in arch/i386/acpi/boot.c */
>  u32 pmtmr_ioport = 0;
>  
> +struct pmtmr_rd_func {
> +	u32 (*read_pmtmr) (void);
> +}pmtmr_rd_func;
> +
>  
>  /* value of the Power timer at last timer interrupt */
>  static u32 offset_tick;
> @@ -45,6 +49,11 @@
>  
>  #define ACPI_PM_MASK 0xFFFFFF /* limit it to 24 bits */
>  
> +static inline u32 read_pmtmr_fast(void)
> +{
> +	return inl(pmtmr_ioport);
> +}
> +
>  /*helper function to safely read acpi pm timesource*/
>  static inline u32 read_pmtmr(void)
>  {
> @@ -76,14 +85,14 @@
>  	unsigned long count, delta;
>  
>  	mach_prepare_counter();
> -	value1 = read_pmtmr();
> +	value1 = pmtmr_rd_func.read_pmtmr();
>  	mach_countup(&count);
> -	value2 = read_pmtmr();
> +	value2 = pmtmr_rd_func.read_pmtmr();
>  	delta = (value2 - value1) & ACPI_PM_MASK;
>  
>  	/* Check that the PMTMR delta is within 5% of what we expect */
> -	if (delta < (PMTMR_EXPECTED_RATE * 19) / 20 ||
> -	    delta > (PMTMR_EXPECTED_RATE * 21) / 20) {
> +	if (delta < (PMTMR_EXPECTED_RATE * 18) / 20 ||
> +	    delta > (PMTMR_EXPECTED_RATE * 22) / 20) {
>  		printk(KERN_INFO "PM-Timer running at invalid rate: %lu%% of normal - aborting.\n", 100UL * delta / PMTMR_EXPECTED_RATE);
>  		return -1;
>  	}
> @@ -95,9 +104,16 @@
>  static int init_pmtmr(char* override)
>  {
>  	u32 value1, value2;
> -	unsigned int i;
> +	u32 v1=0,v2=0,v3=0;
> +	unsigned int i, loop_cnt=0;
>  
> - 	if (override[0] && strncmp(override,"pmtmr",5))
> +	/* Use slower but probably more correct read function by
> +	 * default. This is overriden with a fast one if it is
> +	 * suitable to do so below.
> +	 */
> +	pmtmr_rd_func.read_pmtmr = read_pmtmr;
> + 	
> +	if (override[0] && strncmp(override,"pmtmr",5))
>  		return -ENODEV;
>  
>  	if (!pmtmr_ioport)
> @@ -106,9 +122,32 @@
>  	/* we use the TSC for delay_pmtmr, so make sure it exists */
>  	if (!cpu_has_tsc)
>  		return -ENODEV;
> +	/* It has been reported that because of various broken
> +	 * chipsets (ICH4, PIIX4 and PIIX4E) where the ACPI PM time
> +	 * source is not latched, so you must read it multiple
> +	 * times to insure a safe value is read.
> +	 */
> +	do {
> +		v1 = inl(pmtmr_ioport);
> +		v2 = inl(pmtmr_ioport);
> +		v3 = inl(pmtmr_ioport);
> +		loop_cnt++;
> +	} while ((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1)
> +			|| (v3 > v1 && v3 < v2));
> +	
> +	if(loop_cnt == 1) { 
> +		/*We have a good chipset*/
> +		printk(KERN_INFO "PM Timer: Chipset passes port read test\n");
> +		pmtmr_rd_func.read_pmtmr = read_pmtmr_fast;
> +	}
> +	
> +	else {
> +		printk(KERN_INFO "PM Timer: Chipset fails port read test:");
> +	 	printk(KERN_INFO "Working around it.");
> +	}
>  
>  	/* "verify" this timing source */
> -	value1 = read_pmtmr();
> +	value1 = pmtmr_rd_func.read_pmtmr();
>  	for (i = 0; i < 10000; i++) {
>  		value2 = read_pmtmr();
>  		if (value2 == value1)
> @@ -156,7 +195,7 @@
>  
>  	write_seqlock(&monotonic_lock);
>  
> -	offset_tick = read_pmtmr();
> +	offset_tick = pmtmr_rd_func.read_pmtmr();
>  
>  	/* calculate tick interval */
>  	delta = (offset_tick - last_offset) & ACPI_PM_MASK;
> @@ -202,7 +241,7 @@
>  	} while (read_seqretry(&monotonic_lock, seq));
>  
>  	/* Read the pmtmr */
> -	this_offset =  read_pmtmr();
> +	this_offset =  pmtmr_rd_func.read_pmtmr();
>  
>  	/* convert to nanoseconds */
>  	ret = (this_offset - last_offset) & ACPI_PM_MASK;
> @@ -232,7 +271,7 @@
>  	u32 now, offset, delta = 0;
>  
>  	offset = offset_tick;
> -	now = read_pmtmr();
> +	now = pmtmr_rd_func.read_pmtmr();
>  	delta = (now - offset)&ACPI_PM_MASK;
>  
>  	return (unsigned long) offset_delay + cyc2us(delta);

-- 
George Anzinger   george@mvista.com
HRT (High-res-timers):  http://sourceforge.net/projects/high-res-timers/

  parent reply	other threads:[~2005-06-10  0:53 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-06-02 18:27 [PATCH 3/4] new timeofday x86-64 arch specific changes (v. B1) Parag Warudkar
2005-06-02 18:39 ` Nishanth Aravamudan
2005-06-02 23:05   ` Parag Warudkar
2005-06-02 23:20     ` john stultz
2005-06-02 23:33       ` Parag Warudkar
2005-06-02 23:50       ` Parag Warudkar
2005-06-03  7:05         ` Ulrich Windl
2005-06-03 15:24         ` john stultz
2005-06-05 17:05           ` Dominik Brodowski
2005-06-06  3:04             ` Parag Warudkar
2005-06-06  3:14               ` Dominik Brodowski
2005-06-10  0:48               ` George Anzinger [this message]
2005-06-06  9:21             ` Andi Kleen
2005-06-06  9:24               ` Dominik Brodowski
2005-06-06  9:30                 ` Andi Kleen
2005-06-06 13:32               ` Vojtech Pavlik
2005-06-06 22:53             ` john stultz
2005-06-03 16:30         ` Andi Kleen
2005-06-03 18:27           ` john stultz
2005-06-03 19:02             ` Christoph Lameter
2005-06-03 19:21               ` john stultz
2005-06-05 11:27             ` Andi Kleen
2005-06-06 22:51               ` john stultz
2005-06-04 18:40           ` Parag Warudkar
2005-06-05 11:28             ` Andi Kleen
2005-06-05 14:15               ` Parag Warudkar
2005-06-05 20:51                 ` Lee Revell
2005-06-05 21:41                   ` Parag Warudkar
2005-06-05 22:13                     ` Lee Revell
2005-06-06  9:29                 ` Andi Kleen
2005-06-06 11:46                   ` Parag Warudkar
2005-06-08 13:51                     ` Andi Kleen
2005-06-09  1:47                       ` Lee Revell
2005-06-09  2:12                         ` john stultz
2005-06-09  2:42                           ` Parag Warudkar
2005-06-09 14:17                           ` Andi Kleen
2005-06-03 13:32       ` Parag Warudkar
2005-06-02 18:40 ` john stultz
  -- strict thread matches above, loose matches on Subject: below --
2005-06-02 18:51 Parag Warudkar
2005-06-01 23:09 [PATCH 1/4] new timeofday core subsystem " john stultz
2005-06-01 23:12 ` [PATCH 2/4] new timeofday i386 arch specific changes " john stultz
2005-06-01 23:13   ` [PATCH 3/4] new timeofday x86-64 " john stultz
2005-06-02  0:37     ` Parag Warudkar
2005-06-02 17:34       ` john stultz

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=42A8E369.8080504@mvista.com \
    --to=george@mvista.com \
    --cc=ak@suse.de \
    --cc=akpm@osdl.org \
    --cc=albert@users.sourceforge.net \
    --cc=anton@samba.org \
    --cc=benh@kernel.crashing.org \
    --cc=clameter@sgi.com \
    --cc=darren@dvhart.com \
    --cc=davidm@hpl.hp.com \
    --cc=djwong@us.ibm.com \
    --cc=donf@us.ibm.com \
    --cc=johnstul@us.ibm.com \
    --cc=kernel-stuff@comcast.net \
    --cc=kmannth@us.ibm.com \
    --cc=lcm@us.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@dominikbrodowski.net \
    --cc=mahuja@us.ibm.com \
    --cc=masbock@us.ibm.com \
    --cc=mpm@selenic.com \
    --cc=nacc@us.ibm.com \
    --cc=paulus@samba.org \
    --cc=schwidefsky@de.ibm.com \
    --cc=tim@physik3.uni-rostock.de \
    --cc=ulrich.windl@rz.uni-regensburg.de \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox