Commit f6003b0e authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Linus Torvalds

[PATCH] ftape support for x86_64

We have this patch that adds ftape support for x86_64 and cleans up the
alpha support a little.  The comments look like Vojtech did the x86_64 part
and I guess the alpha bits are from Herbert Xu.
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 78474889
...@@ -31,7 +31,10 @@ ...@@ -31,7 +31,10 @@
#include <asm/io.h> #include <asm/io.h>
#if defined(__alpha__) #if defined(__alpha__)
# include <asm/hwrpb.h> # include <asm/hwrpb.h>
#elif defined(__i386__) || defined(__x86_64__) #elif defined(__x86_64__)
# include <asm/msr.h>
# include <asm/timex.h>
#elif defined(__i386__)
# include <linux/timex.h> # include <linux/timex.h>
#endif #endif
#include <linux/ftape.h> #include <linux/ftape.h>
...@@ -45,7 +48,7 @@ ...@@ -45,7 +48,7 @@
# error Ftape is not implemented for this architecture! # error Ftape is not implemented for this architecture!
#endif #endif
#if defined(__alpha__) #if defined(__alpha__) || defined(__x86_64__)
static unsigned long ps_per_cycle = 0; static unsigned long ps_per_cycle = 0;
#endif #endif
...@@ -72,7 +75,18 @@ unsigned int ftape_timestamp(void) ...@@ -72,7 +75,18 @@ unsigned int ftape_timestamp(void)
asm volatile ("rpcc %0" : "=r" (r)); asm volatile ("rpcc %0" : "=r" (r));
return r; return r;
#elif defined(__i386__) || defined(__x86_64__) #elif defined(__x86_64__)
unsigned long r;
rdtscl(r);
return r;
#elif defined(__i386__)
/*
* Note that there is some time between counter underflowing and jiffies
* increasing, so the code below won't always give correct output.
* -Vojtech
*/
unsigned long flags; unsigned long flags;
__u16 lo; __u16 lo;
__u16 hi; __u16 hi;
...@@ -89,9 +103,9 @@ unsigned int ftape_timestamp(void) ...@@ -89,9 +103,9 @@ unsigned int ftape_timestamp(void)
static unsigned int short_ftape_timestamp(void) static unsigned int short_ftape_timestamp(void)
{ {
#if defined(__alpha__) #if defined(__alpha__) || defined(__x86_64__)
return ftape_timestamp(); return ftape_timestamp();
#elif defined(__i386__) || defined(__x86_64__) #elif defined(__i386__)
unsigned int count; unsigned int count;
unsigned long flags; unsigned long flags;
...@@ -106,9 +120,9 @@ static unsigned int short_ftape_timestamp(void) ...@@ -106,9 +120,9 @@ static unsigned int short_ftape_timestamp(void)
static unsigned int diff(unsigned int t0, unsigned int t1) static unsigned int diff(unsigned int t0, unsigned int t1)
{ {
#if defined(__alpha__) #if defined(__alpha__) || defined(__x86_64__)
return (t1 <= t0) ? t1 + (1UL << 32) - t0 : t1 - t0; return (t1 - t0);
#elif defined(__i386__) || defined(__x86_64__) #elif defined(__i386__)
/* /*
* This is tricky: to work for both short and full ftape_timestamps * This is tricky: to work for both short and full ftape_timestamps
* we'll have to discriminate between these. * we'll have to discriminate between these.
...@@ -122,9 +136,9 @@ static unsigned int diff(unsigned int t0, unsigned int t1) ...@@ -122,9 +136,9 @@ static unsigned int diff(unsigned int t0, unsigned int t1)
static unsigned int usecs(unsigned int count) static unsigned int usecs(unsigned int count)
{ {
#if defined(__alpha__) #if defined(__alpha__) || defined(__x86_64__)
return (ps_per_cycle * count) / 1000000UL; return (ps_per_cycle * count) / 1000000UL;
#elif defined(__i386__) || defined(__x86_64__) #elif defined(__i386__)
return (10000 * count) / ((CLOCK_TICK_RATE + 50) / 100); return (10000 * count) / ((CLOCK_TICK_RATE + 50) / 100);
#endif #endif
} }
...@@ -163,38 +177,13 @@ static void time_inb(void) ...@@ -163,38 +177,13 @@ static void time_inb(void)
static void init_clock(void) static void init_clock(void)
{ {
#if defined(__i386__) || defined(__x86_64__)
unsigned int t;
int i;
TRACE_FUN(ft_t_any); TRACE_FUN(ft_t_any);
/* Haven't studied on why, but there sometimes is a problem #if defined(__x86_64__)
* with the tick timer readout. The two bytes get swapped. ps_per_cycle = 1000000000UL / cpu_khz;
* This hack solves that problem by doing one extra input.
*/
for (i = 0; i < 1000; ++i) {
t = short_ftape_timestamp();
if (t > LATCH) {
inb_p(0x40); /* get in sync again */
TRACE(ft_t_warn, "clock counter fixed");
break;
}
}
#elif defined(__alpha__) #elif defined(__alpha__)
#if CONFIG_FT_ALPHA_CLOCK == 0
#error You must define and set CONFIG_FT_ALPHA_CLOCK in 'make config' !
#endif
extern struct hwrpb_struct *hwrpb; extern struct hwrpb_struct *hwrpb;
TRACE_FUN(ft_t_any); ps_per_cycle = (1000*1000*1000*1000UL) / hwrpb->cycle_freq;
if (hwrpb->cycle_freq != 0) {
ps_per_cycle = (1000*1000*1000*1000UL) / hwrpb->cycle_freq;
} else {
/*
* HELP: Linux 2.0.x doesn't set cycle_freq on my noname !
*/
ps_per_cycle = (1000*1000*1000*1000UL) / CONFIG_FT_ALPHA_CLOCK;
}
#endif #endif
TRACE_EXIT; TRACE_EXIT;
} }
...@@ -213,7 +202,7 @@ void ftape_calibrate(char *name, ...@@ -213,7 +202,7 @@ void ftape_calibrate(char *name,
unsigned int tc = 0; unsigned int tc = 0;
unsigned int count; unsigned int count;
unsigned int time; unsigned int time;
#if defined(__i386__) || defined(__x86_64__) #if defined(__i386__)
unsigned int old_tc = 0; unsigned int old_tc = 0;
unsigned int old_count = 1; unsigned int old_count = 1;
unsigned int old_time = 1; unsigned int old_time = 1;
...@@ -255,7 +244,7 @@ void ftape_calibrate(char *name, ...@@ -255,7 +244,7 @@ void ftape_calibrate(char *name,
tc = (1000 * time) / (count - 1); tc = (1000 * time) / (count - 1);
TRACE(ft_t_any, "once:%3d us,%6d times:%6d us, TC:%5d ns", TRACE(ft_t_any, "once:%3d us,%6d times:%6d us, TC:%5d ns",
usecs(once), count - 1, usecs(multiple), tc); usecs(once), count - 1, usecs(multiple), tc);
#if defined(__alpha__) #if defined(__alpha__) || defined(__x86_64__)
/* /*
* Increase the calibration count exponentially until the * Increase the calibration count exponentially until the
* calibration time exceeds 100 ms. * calibration time exceeds 100 ms.
...@@ -263,7 +252,7 @@ void ftape_calibrate(char *name, ...@@ -263,7 +252,7 @@ void ftape_calibrate(char *name,
if (time >= 100*1000) { if (time >= 100*1000) {
break; break;
} }
#elif defined(__i386__) || defined(__x86_64__) #elif defined(__i386__)
/* /*
* increase the count until the resulting time nears 2/HZ, * increase the count until the resulting time nears 2/HZ,
* then the tc will drop sharply because we lose LATCH counts. * then the tc will drop sharply because we lose LATCH counts.
......
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