Messages in this thread Patch in this message | | | Date | Sun, 23 Jul 2000 18:08:46 -0700 | From | Philipp Rumpf <> | Subject | Re: BogoMIPS and changed CPU speed |
| |
On Sun, Jul 23, 2000 at 09:41:45PM +0200, Pavel Machek wrote: > Hi! > > > As I understand the BogoMIPS value is used for some fine grained > > delays. How does then the system survive a big change in the processor > > speed when : > > > > - user changes FSB on the fly ( possible with newer mainboards, > > I never tried it though ) > > - CPU goes to lower clock due to power management > > - user (de)activates TURBO on older x86 computers > > - CPU goes to HIGHER clock due to power managment. This happens on my > toshiba. > > We've got a problem. There's no good solution, but we can at least
Yes, there is. We can just use the PIT for udelay - it might not be optimal on SMP but it seems to work here.
Pavel, does it work for you ? It should report 2.38 BogoMIPS (PIT clock is 1.193 MHz) regardless of the power management mode you're in.
If it works, changing it to use __setup to determine which method to use should be trivial.
--- linux/arch/i386/lib/delay.c Mon Apr 24 13:39:34 2000 +++ linux-prumpf/arch/i386/lib/delay.c Sun Jul 23 18:02:17 2000 @@ -13,7 +13,9 @@ #include <linux/config.h> #include <linux/sched.h> #include <linux/delay.h> +#include <linux/spinlock.h> #include <asm/delay.h> +#include <asm/io.h> #ifdef CONFIG_SMP #include <asm/smp.h> @@ -41,6 +43,48 @@ } /* + * PIT based delay loop for laptops with weird power-saving modes + */ + +static void __pit_delay(unsigned long loops) +{ + unsigned long flags; + unsigned long count, count_p; + unsigned long diff; + extern spinlock_t i8253_lock; /* yuck */ + + spin_lock_irqsave(&i8253_lock, flags); + + outb_p(0x00, 0x43); + count_p = inb_p(0x40); + count_p |= inb_p(0x40) << 8; + + spin_unlock_irqrestore(&i8253_lock, flags); + + while(loops) { + spin_lock_irqsave(&i8253_lock, flags); + + outb_p(0x00, 0x43); + count = inb_p(0x40); + count |= inb_p(0x40) << 8; + + spin_unlock_irqrestore(&i8253_lock, flags); + + /* count > count_p can happen when the timer wraps around + * or because of chipset bugs. We won't lose much precision + * by ignoring it.*/ + + if(count < count_p) { + diff = count_p - count; + diff = diff < loops ? diff : loops; + loops -= diff; + } + + count_p = count; + } +} + +/* * Non TSC based delay loop for 386, 486, MediaGX */ @@ -59,7 +103,9 @@ void __delay(unsigned long loops) { - if(x86_udelay_tsc) + if(1) + __pit_delay(loops); + else if(x86_udelay_tsc) __rdtsc_delay(loops); else __loop_delay(loops);
Philipp Rumpf
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |