@ -41,6 +41,8 @@ struct timekeeper {
/* Shift conversion between clock shifted nano seconds and
* ntp shifted nano seconds . */
int ntp_error_shift ;
/* NTP adjusted clock multiplier */
u32 mult ;
} ;
struct timekeeper timekeeper ;
@ -66,8 +68,8 @@ static void timekeeper_setup_internals(struct clocksource *clock)
/* Do the ns -> cycle conversion first, using original mult */
tmp = NTP_INTERVAL_LENGTH ;
tmp < < = clock - > shift ;
tmp + = clock - > mult_orig / 2 ;
do_div ( tmp , clock - > mult_orig ) ;
tmp + = clock - > mult / 2 ;
do_div ( tmp , clock - > mult ) ;
if ( tmp = = 0 )
tmp = 1 ;
@ -77,13 +79,20 @@ static void timekeeper_setup_internals(struct clocksource *clock)
/* Go back from cycles -> shifted ns */
timekeeper . xtime_interval = ( u64 ) interval * clock - > mult ;
timekeeper . raw_interval =
( ( u64 ) interval * clock - > mult_orig ) > > clock - > shift ;
( ( u64 ) interval * clock - > mult ) > > clock - > shift ;
timekeeper . xtime_nsec = 0 ;
timekeeper . shift = clock - > shift ;
timekeeper . ntp_error = 0 ;
timekeeper . ntp_error_shift = NTP_SCALE_SHIFT - clock - > shift ;
/*
* The timekeeper keeps its own mult values for the currently
* active clocksource . These value will be adjusted via NTP
* to counteract clock drifting .
*/
timekeeper . mult = clock - > mult ;
}
/*
@ -154,14 +163,15 @@ static void timekeeping_forward_now(void)
cycle_delta = ( cycle_now - clock - > cycle_last ) & clock - > mask ;
clock - > cycle_last = cycle_now ;
nsec = clocksource_cyc2ns ( cycle_delta , clock - > mult , clock - > shift ) ;
nsec = clocksource_cyc2ns ( cycle_delta , timekeeper . mult ,
timekeeper . shift ) ;
/* If arch requires, add in gettimeoffset() */
nsec + = arch_gettimeoffset ( ) ;
timespec_add_ns ( & xtime , nsec ) ;
nsec = clocksource_cyc2ns ( cycle_delta , clock - > mult_orig , clock - > shift ) ;
nsec = clocksource_cyc2ns ( cycle_delta , clock - > mult , clock - > shift ) ;
timespec_add_ns ( & raw_time , nsec ) ;
}
@ -193,8 +203,8 @@ void getnstimeofday(struct timespec *ts)
cycle_delta = ( cycle_now - clock - > cycle_last ) & clock - > mask ;
/* convert to nanoseconds: */
nsecs = clocksource_cyc2ns ( cycle_delta , clock - > mult ,
clock - > shift ) ;
nsecs = clocksource_cyc2ns ( cycle_delta , timekeeper . mult ,
timekeeper . shift ) ;
/* If arch requires, add in gettimeoffset() */
nsecs + = arch_gettimeoffset ( ) ;
@ -228,8 +238,8 @@ ktime_t ktime_get(void)
cycle_delta = ( cycle_now - clock - > cycle_last ) & clock - > mask ;
/* convert to nanoseconds: */
nsecs + = clocksource_cyc2ns ( cycle_delta , clock - > mult ,
clock - > shift ) ;
nsecs + = clocksource_cyc2ns ( cycle_delta , timekeeper . mult ,
timekeeper . shift ) ;
} while ( read_seqretry ( & xtime_lock , seq ) ) ;
/*
@ -271,8 +281,8 @@ void ktime_get_ts(struct timespec *ts)
cycle_delta = ( cycle_now - clock - > cycle_last ) & clock - > mask ;
/* convert to nanoseconds: */
nsecs = clocksource_cyc2ns ( cycle_delta , clock - > mult ,
clock - > shift ) ;
nsecs = clocksource_cyc2ns ( cycle_delta , timekeeper . mult ,
timekeeper . shift ) ;
} while ( read_seqretry ( & xtime_lock , seq ) ) ;
@ -356,22 +366,10 @@ static void change_clocksource(void)
if ( new - > enable & & ! new - > enable ( new ) )
return ;
/*
* The frequency may have changed while the clocksource
* was disabled . If so the code in - > enable ( ) must update
* the mult value to reflect the new frequency . Make sure
* mult_orig follows this change .
*/
new - > mult_orig = new - > mult ;
old = timekeeper . clock ;
timekeeper_setup_internals ( new ) ;
/*
* Save mult_orig in mult so that the value can be restored
* regardless if - > enable ( ) updates the value of mult or not .
*/
old - > mult = old - > mult_orig ;
if ( old - > disable )
old - > disable ( old ) ;
@ -461,7 +459,7 @@ void getrawmonotonic(struct timespec *ts)
cycle_delta = ( cycle_now - clock - > cycle_last ) & clock - > mask ;
/* convert to nanoseconds: */
nsecs = clocksource_cyc2ns ( cycle_delta , clock - > mult_orig ,
nsecs = clocksource_cyc2ns ( cycle_delta , clock - > mult ,
clock - > shift ) ;
* ts = raw_time ;
@ -521,9 +519,6 @@ void __init timekeeping_init(void)
clock = clocksource_default_clock ( ) ;
if ( clock - > enable )
clock - > enable ( clock ) ;
/* set mult_orig on enable */
clock - > mult_orig = clock - > mult ;
timekeeper_setup_internals ( clock ) ;
xtime . tv_sec = sec ;
@ -697,7 +692,7 @@ static void timekeeping_adjust(s64 offset)
} else
return ;
timekeeper . clock - > mult + = adj ;
timekeeper . mult + = adj ;
timekeeper . xtime_interval + = interval ;
timekeeper . xtime_nsec - = offset ;
timekeeper . ntp_error - = ( interval - offset ) < <
@ -789,7 +784,7 @@ void update_wall_time(void)
timekeeper . ntp_error + = timekeeper . xtime_nsec < <
timekeeper . ntp_error_shift ;
nsecs = clocksource_cyc2ns ( offset , clock - > mult , clock - > shift ) ;
nsecs = clocksource_cyc2ns ( offset , timekeeper . mult , timekeeper . shift ) ;
update_xtime_cache ( nsecs ) ;
/* check to see if there is a new clocksource to use */