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
prev parent 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.