All of lore.kernel.org
 help / color / mirror / Atom feed
From: john stultz <johnstul@us.ibm.com>
To: Dominik Brodowski <linux@brodo.de>
Cc: Andrew Morton <akpm@osdl.org>,
	lkml <linux-kernel@vger.kernel.org>,
	Alan Cox <alan@lxorguk.ukuu.org.uk>,
	albert@users.sourceforge.net
Subject: Re: ACPI PM-Timer rev.2 [Was: Re: ACPI PM-Timer [Was: Re: [RFC][PATCH] must fix lists]]
Date: 04 Nov 2003 14:03:20 -0800	[thread overview]
Message-ID: <1067983399.11432.102.camel@cog.beaverton.ibm.com> (raw)
In-Reply-To: <20031027230113.GA701@brodo.de>

On Mon, 2003-10-27 at 15:01, Dominik Brodowski wrote:
> On Mon, Oct 27, 2003 at 11:07:19AM -0800, john stultz wrote:
> > Ah, OK. Well, I'd prefer the manual ACPI parsing personally, but having
> > tried and failed to implement it once myself, I'd more prefer not to do
> > it myself. ;)
> 
> Here it is, and it is soooo much nicer than my previous implementation. It
> lacks the "lost-ticks compensation" and math cleanup John is working on, but
> otherwise:

Finally, here are my fixes to Dominik's patch (meant to send these out
last week, but got swamped). Basically it cleans up some of the math,
adds lost-tick compensation and monotonic_clock, fixes up a bit of the
ACPI table mapping, and moves the config option under the ACPI menu. Oh
yea, and it compiles, too ;)

Works well for me, but needs more testing. 

Applies on top of Dominik's ACPI PM-timer rev.2 patch.
http://www.ussg.iu.edu/hypermail/linux/kernel/0310.3/0669.html

Many thanks to Dominik for the great work and getting this started. 
-john


diff -Nru a/Documentation/kernel-parameters.txt
b/Documentation/kernel-parameters.txt
--- a/Documentation/kernel-parameters.txt	Tue Nov  4 13:30:42 2003
+++ b/Documentation/kernel-parameters.txt	Tue Nov  4 13:30:42 2003
@@ -214,7 +214,7 @@
 			Forces specified timesource (if avaliable) to be used
 			when calculating gettimeofday(). If specicified timesource
 			is not avalible, it defaults to PIT. 
-			Format: { pit | tsc | cyclone | ... }
+			Format: { pit | tsc | cyclone | pmtmr }
 
 	hpet=		[IA-32,HPET] option to disable HPET and use PIT.
 			Format: disable
diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig
--- a/arch/i386/Kconfig	Tue Nov  4 13:30:42 2003
+++ b/arch/i386/Kconfig	Tue Nov  4 13:30:42 2003
@@ -411,24 +411,6 @@
 config HPET_EMULATE_RTC
 	def_bool HPET_TIMER && RTC=y
 
-config X86_PM_TIMER
-	bool "Power Management Timer Support"
-	depends on (!X86_VISWS && !X86_VISWS) && EXPERIMENTAL
-	default n
-	help
-	  The Power Management Timer is available on all ACPI-capable,
-	  in most cases even if ACPI is unusable or blacklisted.
-
-	  This timing source is not affected by powermanagement features
-	  like aggressive processor idling, throttling, frequency and/or
-	  voltage scaling, unlike the commonly used Time Stamp Counter 
-	  (TSC) timing source.
-
-	  So, if you see messages like 'Losing too many ticks!' in the 
-	  kernel logs, and/or you are using a this on a notebook which
-	  does not yet have an HPET (see above), you should say "Y" 
-	  here. Otherwise, say "N".
-
 config SMP
 	bool "Symmetric multi-processing support"
 	---help---
diff -Nru a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
--- a/arch/i386/kernel/acpi/boot.c	Tue Nov  4 13:30:42 2003
+++ b/arch/i386/kernel/acpi/boot.c	Tue Nov  4 13:30:42 2003
@@ -319,15 +319,19 @@
 }
 #endif
 
-/* detect the location of the ACPI PM Timer
+/* detect the location of the ACPI PM Timer */
 #ifdef CONFIG_X86_PM_TIMER
 extern u32 pmtmr_ioport;
 
 static int __init acpi_parse_fadt(unsigned long phys, unsigned long
size)
 {
-	struct fadt_descriptor_rev2 *fadt;
+	struct fadt_descriptor_rev2 *fadt =0;
 
-	fadt = __va(phys);
+	fadt = (struct fadt_descriptor_rev2*) __acpi_map_table(phys,size);
+	if(!fadt) {
+		printk(KERN_WARNING PREFIX "Unable to map FADT\n");
+		return 0;
+	}
 
 	if (fadt->revision >= FADT2_REVISION_ID) {
 		/* FADT rev. 2 */
diff -Nru a/arch/i386/kernel/timers/timer_pm.c
b/arch/i386/kernel/timers/timer_pm.c
--- a/arch/i386/kernel/timers/timer_pm.c	Tue Nov  4 13:30:42 2003
+++ b/arch/i386/kernel/timers/timer_pm.c	Tue Nov  4 13:30:42 2003
@@ -30,7 +30,12 @@
 
 /* value of the Power timer at last timer interrupt */
 static u32 offset_tick;
+static u32 offset_delay;
 
+static unsigned long long monotonic_base;
+static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED;
+
+#define ACPI_PM_MASK 0xFFFFFF /* limit it to 24 bits */
 
 static int init_pmtmr(char* override)
 {
@@ -62,23 +67,88 @@
 	return -ENODEV;
 }
 
+static inline u32 cyc2us(u32 cycles)
+{
+	/* The Power Management Timer ticks at 3.579545 ticks per microsecond.
+	 * 1 / PM_TIMER_FREQUENCY == 0.27936511 =~ 286/1024 [error: 0.024%]
+	 *
+	 * Even with HZ = 100, delta is at maximum 35796 ticks, so it can 
+	 * easily be multiplied with 286 (=0x11E) without having to fear
+	 * u32 overflows.
+	 */
+	cycles *= 286;
+	return (cycles >> 10);
+}
 
 /*
  * this gets called during each timer interrupt
  */
 static void mark_offset_pmtmr(void)
 {
+	u32 lost, delta, last_offset;
+	static int first_run = 1;
+	last_offset = offset_tick;
+
+	write_seqlock(&monotonic_lock);
+
 	offset_tick = inl(pmtmr_ioport);
-	offset_tick &= 0xFFFFFF; /* limit it to 24 bits */
+	offset_tick &= ACPI_PM_MASK; /* limit it to 24 bits */
+
+	/* calculate tick interval */
+	delta = (offset_tick - last_offset) & ACPI_PM_MASK;
+
+	/* convert to usecs */
+	delta = offset_delay + cyc2us(delta);
+
+	/* convert to ticks */
+	lost = delta/(USEC_PER_SEC/HZ);
+	offset_delay = delta%(USEC_PER_SEC/HZ);
+
+	/* update the monotonic base value */
+	monotonic_base += delta; 
+	write_sequnlock(&monotonic_lock);
+
+
+	/* compensate for lost ticks */
+	if (lost >= 2)
+		jiffies += lost - 1;
+
+	/* don't calculate delay for first run, 
+	   or if we've got less then a tick */
+	if (first_run || (lost < 1)) {
+		first_run = 0;
+		offset_delay = 0;
+	}
+
 	return;
 }
 
 
 static unsigned long long monotonic_clock_pmtmr(void)
 {
-	return 0;
-}
+	u32 last_offset, this_offset;
+	unsigned long long base, ret;
+	unsigned seq;
+
 
+	/* atomically read monotonic base & last_offset */
+	do {
+		seq = read_seqbegin(&monotonic_lock);
+		last_offset = offset_tick;
+		base = monotonic_base;
+	} while (read_seqretry(&monotonic_lock, seq));
+
+
+	/* Read the cyclone counter */
+
+	this_offset =  inl(pmtmr_ioport) & ACPI_PM_MASK;
+	
+
+	/* convert to nanoseconds */
+	ret = base + ((this_offset - last_offset) & ACPI_PM_MASK);
+	ret = cyc2us(ret)*1000;
+	return ret;
+}
 
 /*
  * copied from delay_pit
@@ -106,21 +176,10 @@
 
 	offset = offset_tick;
 	now = inl(pmtmr_ioport);
-	now &= 0xFFFFFF;
-	if (likely(offset < now))
-		delta = now - offset;
-	else if (offset > now)
-		delta = (0xFFFFFF - offset) + now;
+	now &= ACPI_PM_MASK;
+	delta = (now - offset)&ACPI_PM_MASK;
 
-	/* The Power Management Timer ticks at 3.579545 ticks per microsecond.
-	 * 1 / PM_TIMER_FREQUENCY == 0.27936511 =~ 286/1024 [error: 0.024%]
-	 *
-	 * Even with HZ = 100, delta is at maximum 35796 ticks, so it can 
-	 * easily be multiplied with 286 (=0x11E) without having to fear
-	 * u32 overflows.
-	 */
-	delta *= 286;
-	return (unsigned long) (delta >> 10);
+	return (unsigned long) offset_delay + cyc2us(delta);
 }
 
 
diff -Nru a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
--- a/drivers/acpi/Kconfig	Tue Nov  4 13:30:42 2003
+++ b/drivers/acpi/Kconfig	Tue Nov  4 13:30:42 2003
@@ -269,5 +269,24 @@
 	  particular, many Toshiba laptops require this for correct operation
 	  of the AC module.
 
+config X86_PM_TIMER
+	bool "Power Management Timer Support"
+	depends on X86 && ACPI
+	depends on ACPI_BOOT && EXPERIMENTAL
+	default n
+	help
+	  The Power Management Timer is available on all ACPI-capable,
+	  in most cases even if ACPI is unusable or blacklisted.
+
+	  This timing source is not affected by powermanagement features
+	  like aggressive processor idling, throttling, frequency and/or
+	  voltage scaling, unlike the commonly used Time Stamp Counter 
+	  (TSC) timing source.
+
+	  So, if you see messages like 'Losing too many ticks!' in the 
+	  kernel logs, and/or you are using a this on a notebook which
+	  does not yet have an HPET (see above), you should say "Y" 
+	  here.
+
 endmenu
 




      reply	other threads:[~2003-11-04 22:05 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-10-21  5:46 [RFC] must fix lists Nick Piggin
2003-10-21  9:36 ` Lars Marowsky-Bree
2003-10-22  0:40   ` Nick Piggin
2003-10-21 16:18 ` Randy.Dunlap
2003-10-22  2:50 ` Albert Cahalan
2003-10-23 21:11   ` Alan Cox
2003-10-23 21:09 ` Alan Cox
2003-10-23 23:46   ` Nick Piggin
2003-10-24  1:06     ` Albert Cahalan
2003-10-24  1:55     ` viro
2003-10-24  0:23   ` Chris Wright
2003-10-25 20:18     ` Alan Cox
2003-10-27 12:53       ` [RFC][PATCH] " Nick Piggin
2003-10-27 18:24         ` ACPI PM-Timer [Was: Re: [RFC][PATCH] must fix lists] Dominik Brodowski
2003-10-27 18:42           ` john stultz
2003-10-27 18:49             ` Dominik Brodowski
2003-10-27 19:07               ` john stultz
2003-10-27 23:01                 ` ACPI PM-Timer rev.2 [Was: Re: ACPI PM-Timer [Was: Re: [RFC][PATCH] must fix lists]] Dominik Brodowski
2003-11-04 22:03                   ` john stultz [this message]

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=1067983399.11432.102.camel@cog.beaverton.ibm.com \
    --to=johnstul@us.ibm.com \
    --cc=akpm@osdl.org \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=albert@users.sourceforge.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@brodo.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 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.