X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fia64%2Fsn%2Fkernel%2Fsn2%2Ftimer.c;h=56a88b6df4b41fbca0df635ab5fc23988b0298b4;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=85f7d215a35800de1447186fa75882493fbc4956;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/arch/ia64/sn/kernel/sn2/timer.c b/arch/ia64/sn/kernel/sn2/timer.c index 85f7d215a..56a88b6df 100644 --- a/arch/ia64/sn/kernel/sn2/timer.c +++ b/arch/ia64/sn/kernel/sn2/timer.c @@ -14,22 +14,42 @@ #include #include +#include #include +#include #include - extern unsigned long sn_rtc_cycles_per_second; -static struct time_interpolator sn2_interpolator; +static struct time_interpolator sn2_interpolator = { + .drift = -1, + .shift = 10, + .mask = (1LL << 55) - 1, + .source = TIME_SOURCE_MMIO64 +}; + +/* + * sn udelay uses the RTC instead of the ITC because the ITC is not + * synchronized across all CPUs, and the thread may migrate to another CPU + * if preemption is enabled. + */ +static void +ia64_sn_udelay (unsigned long usecs) +{ + unsigned long start = rtc_time(); + unsigned long end = start + + usecs * sn_rtc_cycles_per_second / 1000000; + + while (time_before((unsigned long)rtc_time(), end)) + cpu_relax(); +} -void __init -sn_timer_init(void) +void __init sn_timer_init(void) { sn2_interpolator.frequency = sn_rtc_cycles_per_second; - sn2_interpolator.drift = -1; /* unknown */ - sn2_interpolator.shift = 10; /* RTC is 54 bits maximum shift is 10 */ sn2_interpolator.addr = RTC_COUNTER_ADDR; - sn2_interpolator.source = TIME_SOURCE_MMIO64; register_time_interpolator(&sn2_interpolator); + + ia64_udelay = &ia64_sn_udelay; }