Commit c35a7261 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] synchronize_tsc() fixes

- Move the tsc synchronisation variables into a struct, mark it __initdata

- local `realdelta' wants to be 64-bit

- Print the skew for negative skews, as well as for positive ones

- remove dead code

Cc: john stultz <johnstul@us.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 851f8a69
...@@ -212,14 +212,20 @@ static void __devinit smp_store_cpu_info(int id) ...@@ -212,14 +212,20 @@ static void __devinit smp_store_cpu_info(int id)
* then we print a warning if not, and always resync. * then we print a warning if not, and always resync.
*/ */
static atomic_t tsc_start_flag = ATOMIC_INIT(0); static struct {
static atomic_t tsc_count_start = ATOMIC_INIT(0); atomic_t start_flag;
static atomic_t tsc_count_stop = ATOMIC_INIT(0); atomic_t count_start;
static unsigned long long tsc_values[NR_CPUS]; atomic_t count_stop;
unsigned long long values[NR_CPUS];
} tsc __initdata = {
.start_flag = ATOMIC_INIT(0),
.count_start = ATOMIC_INIT(0),
.count_stop = ATOMIC_INIT(0),
};
#define NR_LOOPS 5 #define NR_LOOPS 5
static void __init synchronize_tsc_bp (void) static void __init synchronize_tsc_bp(void)
{ {
int i; int i;
unsigned long long t0; unsigned long long t0;
...@@ -233,7 +239,7 @@ static void __init synchronize_tsc_bp (void) ...@@ -233,7 +239,7 @@ static void __init synchronize_tsc_bp (void)
/* convert from kcyc/sec to cyc/usec */ /* convert from kcyc/sec to cyc/usec */
one_usec = cpu_khz / 1000; one_usec = cpu_khz / 1000;
atomic_set(&tsc_start_flag, 1); atomic_set(&tsc.start_flag, 1);
wmb(); wmb();
/* /*
...@@ -250,16 +256,16 @@ static void __init synchronize_tsc_bp (void) ...@@ -250,16 +256,16 @@ static void __init synchronize_tsc_bp (void)
/* /*
* all APs synchronize but they loop on '== num_cpus' * all APs synchronize but they loop on '== num_cpus'
*/ */
while (atomic_read(&tsc_count_start) != num_booting_cpus()-1) while (atomic_read(&tsc.count_start) != num_booting_cpus()-1)
cpu_relax(); cpu_relax();
atomic_set(&tsc_count_stop, 0); atomic_set(&tsc.count_stop, 0);
wmb(); wmb();
/* /*
* this lets the APs save their current TSC: * this lets the APs save their current TSC:
*/ */
atomic_inc(&tsc_count_start); atomic_inc(&tsc.count_start);
rdtscll(tsc_values[smp_processor_id()]); rdtscll(tsc.values[smp_processor_id()]);
/* /*
* We clear the TSC in the last loop: * We clear the TSC in the last loop:
*/ */
...@@ -269,56 +275,54 @@ static void __init synchronize_tsc_bp (void) ...@@ -269,56 +275,54 @@ static void __init synchronize_tsc_bp (void)
/* /*
* Wait for all APs to leave the synchronization point: * Wait for all APs to leave the synchronization point:
*/ */
while (atomic_read(&tsc_count_stop) != num_booting_cpus()-1) while (atomic_read(&tsc.count_stop) != num_booting_cpus()-1)
cpu_relax(); cpu_relax();
atomic_set(&tsc_count_start, 0); atomic_set(&tsc.count_start, 0);
wmb(); wmb();
atomic_inc(&tsc_count_stop); atomic_inc(&tsc.count_stop);
} }
sum = 0; sum = 0;
for (i = 0; i < NR_CPUS; i++) { for (i = 0; i < NR_CPUS; i++) {
if (cpu_isset(i, cpu_callout_map)) { if (cpu_isset(i, cpu_callout_map)) {
t0 = tsc_values[i]; t0 = tsc.values[i];
sum += t0; sum += t0;
} }
} }
avg = sum; avg = sum;
do_div(avg, num_booting_cpus()); do_div(avg, num_booting_cpus());
sum = 0;
for (i = 0; i < NR_CPUS; i++) { for (i = 0; i < NR_CPUS; i++) {
if (!cpu_isset(i, cpu_callout_map)) if (!cpu_isset(i, cpu_callout_map))
continue; continue;
delta = tsc_values[i] - avg; delta = tsc.values[i] - avg;
if (delta < 0) if (delta < 0)
delta = -delta; delta = -delta;
/* /*
* We report bigger than 2 microseconds clock differences. * We report bigger than 2 microseconds clock differences.
*/ */
if (delta > 2*one_usec) { if (delta > 2*one_usec) {
long realdelta; long long realdelta;
if (!buggy) { if (!buggy) {
buggy = 1; buggy = 1;
printk("\n"); printk("\n");
} }
realdelta = delta; realdelta = delta;
do_div(realdelta, one_usec); do_div(realdelta, one_usec);
if (tsc_values[i] < avg) if (tsc.values[i] < avg)
realdelta = -realdelta; realdelta = -realdelta;
if (realdelta > 0) if (realdelta)
printk(KERN_INFO "CPU#%d had %ld usecs TSC " printk(KERN_INFO "CPU#%d had %Ld usecs TSC "
"skew, fixed it up.\n", i, realdelta); "skew, fixed it up.\n", i, realdelta);
} }
sum += delta;
} }
if (!buggy) if (!buggy)
printk("passed.\n"); printk("passed.\n");
} }
static void __init synchronize_tsc_ap (void) static void __init synchronize_tsc_ap(void)
{ {
int i; int i;
...@@ -327,20 +331,20 @@ static void __init synchronize_tsc_ap (void) ...@@ -327,20 +331,20 @@ static void __init synchronize_tsc_ap (void)
* this gets called, so we first wait for the BP to * this gets called, so we first wait for the BP to
* finish SMP initialization: * finish SMP initialization:
*/ */
while (!atomic_read(&tsc_start_flag)) while (!atomic_read(&tsc.start_flag))
cpu_relax(); cpu_relax();
for (i = 0; i < NR_LOOPS; i++) { for (i = 0; i < NR_LOOPS; i++) {
atomic_inc(&tsc_count_start); atomic_inc(&tsc.count_start);
while (atomic_read(&tsc_count_start) != num_booting_cpus()) while (atomic_read(&tsc.count_start) != num_booting_cpus())
cpu_relax(); cpu_relax();
rdtscll(tsc_values[smp_processor_id()]); rdtscll(tsc.values[smp_processor_id()]);
if (i == NR_LOOPS-1) if (i == NR_LOOPS-1)
write_tsc(0, 0); write_tsc(0, 0);
atomic_inc(&tsc_count_stop); atomic_inc(&tsc.count_stop);
while (atomic_read(&tsc_count_stop) != num_booting_cpus()) while (atomic_read(&tsc.count_stop) != num_booting_cpus())
cpu_relax(); cpu_relax();
} }
} }
......
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