Commit 8c777fd8 authored by John Stultz's avatar John Stultz Committed by Linus Torvalds

[PATCH] linux-2.5.57_delay-cleanup_A1.patch

This cleans up the delay code by moving the timer-specific
implementations into the timer_ops struct.  Thus, rather then doing:

	if(x86_delay_tsc)
		__rdtsc_delay(loops);
	else if(x86_delay_cyclone)
		__cyclone_delay(loops);
	else if(whatever....

we just simply do:

	timer->delay(loops);

Making it much easier to accommodate alternate time sources.
parent cab1826e
...@@ -150,7 +150,6 @@ static int init_cyclone(void) ...@@ -150,7 +150,6 @@ static int init_cyclone(void)
} }
#if 0 /* XXX future work */
static void delay_cyclone(unsigned long loops) static void delay_cyclone(unsigned long loops)
{ {
unsigned long bclock, now; unsigned long bclock, now;
...@@ -162,12 +161,12 @@ static void delay_cyclone(unsigned long loops) ...@@ -162,12 +161,12 @@ static void delay_cyclone(unsigned long loops)
now = cyclone_timer[0]; now = cyclone_timer[0];
} while ((now-bclock) < loops); } while ((now-bclock) < loops);
} }
#endif
/************************************************************/ /************************************************************/
/* cyclone timer_opts struct */ /* cyclone timer_opts struct */
struct timer_opts timer_cyclone = { struct timer_opts timer_cyclone = {
.init = init_cyclone, .init = init_cyclone,
.mark_offset = mark_offset_cyclone, .mark_offset = mark_offset_cyclone,
.get_offset = get_offset_cyclone .get_offset = get_offset_cyclone,
.delay = delay_cyclone,
}; };
...@@ -15,10 +15,23 @@ static unsigned long get_offset_none(void) ...@@ -15,10 +15,23 @@ static unsigned long get_offset_none(void)
return 0; return 0;
} }
static void delay_none(unsigned long loops)
{
int d0;
__asm__ __volatile__(
"\tjmp 1f\n"
".align 16\n"
"1:\tjmp 2f\n"
".align 16\n"
"2:\tdecl %0\n\tjns 2b"
:"=&a" (d0)
:"0" (loops));
}
/* tsc timer_opts struct */ /* tsc timer_opts struct */
struct timer_opts timer_none = { struct timer_opts timer_none = {
.init = init_none, .init = init_none,
.mark_offset = mark_offset_none, .mark_offset = mark_offset_none,
.get_offset = get_offset_none, .get_offset = get_offset_none,
.delay = delay_none,
}; };
...@@ -27,6 +27,19 @@ static void mark_offset_pit(void) ...@@ -27,6 +27,19 @@ static void mark_offset_pit(void)
/* nothing needed */ /* nothing needed */
} }
static void delay_pit(unsigned long loops)
{
int d0;
__asm__ __volatile__(
"\tjmp 1f\n"
".align 16\n"
"1:\tjmp 2f\n"
".align 16\n"
"2:\tdecl %0\n\tjns 2b"
:"=&a" (d0)
:"0" (loops));
}
/* This function must be called with interrupts disabled /* This function must be called with interrupts disabled
* It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs * It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs
...@@ -129,4 +142,5 @@ struct timer_opts timer_pit = { ...@@ -129,4 +142,5 @@ struct timer_opts timer_pit = {
.init = init_pit, .init = init_pit,
.mark_offset = mark_offset_pit, .mark_offset = mark_offset_pit,
.get_offset = get_offset_pit, .get_offset = get_offset_pit,
.delay = delay_pit,
}; };
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
int tsc_disable __initdata = 0; int tsc_disable __initdata = 0;
extern int x86_udelay_tsc;
extern spinlock_t i8253_lock; extern spinlock_t i8253_lock;
static int use_tsc; static int use_tsc;
...@@ -107,6 +106,17 @@ static void mark_offset_tsc(void) ...@@ -107,6 +106,17 @@ static void mark_offset_tsc(void)
delay_at_last_interrupt = (count + LATCH/2) / LATCH; delay_at_last_interrupt = (count + LATCH/2) / LATCH;
} }
static void delay_tsc(unsigned long loops)
{
unsigned long bclock, now;
rdtscl(bclock);
do
{
rep_nop();
rdtscl(now);
} while ((now-bclock) < loops);
}
/* ------ Calibrate the TSC ------- /* ------ Calibrate the TSC -------
* Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset(). * Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset().
...@@ -272,8 +282,6 @@ static int init_tsc(void) ...@@ -272,8 +282,6 @@ static int init_tsc(void)
* We could be more selective here I suspect * We could be more selective here I suspect
* and just enable this for the next intel chips ? * and just enable this for the next intel chips ?
*/ */
x86_udelay_tsc = 1;
/* report CPU clock rate in Hz. /* report CPU clock rate in Hz.
* The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) = * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) =
* clock/second. Our precision is about 100 ppm. * clock/second. Our precision is about 100 ppm.
...@@ -310,4 +318,5 @@ struct timer_opts timer_tsc = { ...@@ -310,4 +318,5 @@ struct timer_opts timer_tsc = {
.init = init_tsc, .init = init_tsc,
.mark_offset = mark_offset_tsc, .mark_offset = mark_offset_tsc,
.get_offset = get_offset_tsc, .get_offset = get_offset_tsc,
.delay = delay_tsc,
}; };
...@@ -15,54 +15,17 @@ ...@@ -15,54 +15,17 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/delay.h> #include <asm/delay.h>
#include <asm/timer.h>
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
#include <asm/smp.h> #include <asm/smp.h>
#endif #endif
int x86_udelay_tsc = 0; /* Delay via TSC */ extern struct timer_opts* timer;
/*
* Do a udelay using the TSC for any CPU that happens
* to have one that we trust.
*/
static void __rdtsc_delay(unsigned long loops)
{
unsigned long bclock, now;
rdtscl(bclock);
do
{
rep_nop();
rdtscl(now);
} while ((now-bclock) < loops);
}
/*
* Non TSC based delay loop for 386, 486, MediaGX
*/
static void __loop_delay(unsigned long loops)
{
int d0;
__asm__ __volatile__(
"\tjmp 1f\n"
".align 16\n"
"1:\tjmp 2f\n"
".align 16\n"
"2:\tdecl %0\n\tjns 2b"
:"=&a" (d0)
:"0" (loops));
}
void __delay(unsigned long loops) void __delay(unsigned long loops)
{ {
if (x86_udelay_tsc) timer->delay(loops);
__rdtsc_delay(loops);
else
__loop_delay(loops);
} }
inline void __const_udelay(unsigned long xloops) inline void __const_udelay(unsigned long xloops)
......
...@@ -14,6 +14,7 @@ struct timer_opts{ ...@@ -14,6 +14,7 @@ struct timer_opts{
int (*init)(void); int (*init)(void);
void (*mark_offset)(void); void (*mark_offset)(void);
unsigned long (*get_offset)(void); unsigned long (*get_offset)(void);
void (*delay)(unsigned long);
}; };
#define TICK_SIZE (tick_nsec / 1000) #define TICK_SIZE (tick_nsec / 1000)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment