diff options
Diffstat (limited to 'kernel/time/clocksource.c')
| -rw-r--r-- | kernel/time/clocksource.c | 44 | 
1 files changed, 21 insertions, 23 deletions
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index e5b260aa0e02..d25ba49e313c 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -20,6 +20,16 @@  #include "tick-internal.h"  #include "timekeeping_internal.h" +static noinline u64 cycles_to_nsec_safe(struct clocksource *cs, u64 start, u64 end) +{ +	u64 delta = clocksource_delta(end, start, cs->mask); + +	if (likely(delta < cs->max_cycles)) +		return clocksource_cyc2ns(delta, cs->mult, cs->shift); + +	return mul_u64_u32_shr(delta, cs->mult, cs->shift); +} +  /**   * clocks_calc_mult_shift - calculate mult/shift factors for scaled math of clocks   * @mult:	pointer to mult variable @@ -222,8 +232,8 @@ enum wd_read_status {  static enum wd_read_status cs_watchdog_read(struct clocksource *cs, u64 *csnow, u64 *wdnow)  {  	unsigned int nretries, max_retries; -	u64 wd_end, wd_end2, wd_delta;  	int64_t wd_delay, wd_seq_delay; +	u64 wd_end, wd_end2;  	max_retries = clocksource_get_max_watchdog_retry();  	for (nretries = 0; nretries <= max_retries; nretries++) { @@ -234,9 +244,7 @@ static enum wd_read_status cs_watchdog_read(struct clocksource *cs, u64 *csnow,  		wd_end2 = watchdog->read(watchdog);  		local_irq_enable(); -		wd_delta = clocksource_delta(wd_end, *wdnow, watchdog->mask); -		wd_delay = clocksource_cyc2ns(wd_delta, watchdog->mult, -					      watchdog->shift); +		wd_delay = cycles_to_nsec_safe(watchdog, *wdnow, wd_end);  		if (wd_delay <= WATCHDOG_MAX_SKEW) {  			if (nretries > 1 || nretries >= max_retries) {  				pr_warn("timekeeping watchdog on CPU%d: %s retried %d times before success\n", @@ -254,8 +262,7 @@ static enum wd_read_status cs_watchdog_read(struct clocksource *cs, u64 *csnow,  		 * report system busy, reinit the watchdog and skip the current  		 * watchdog test.  		 */ -		wd_delta = clocksource_delta(wd_end2, wd_end, watchdog->mask); -		wd_seq_delay = clocksource_cyc2ns(wd_delta, watchdog->mult, watchdog->shift); +		wd_seq_delay = cycles_to_nsec_safe(watchdog, wd_end, wd_end2);  		if (wd_seq_delay > WATCHDOG_MAX_SKEW/2)  			goto skip_test;  	} @@ -366,8 +373,7 @@ void clocksource_verify_percpu(struct clocksource *cs)  		delta = (csnow_end - csnow_mid) & cs->mask;  		if (delta < 0)  			cpumask_set_cpu(cpu, &cpus_ahead); -		delta = clocksource_delta(csnow_end, csnow_begin, cs->mask); -		cs_nsec = clocksource_cyc2ns(delta, cs->mult, cs->shift); +		cs_nsec = cycles_to_nsec_safe(cs, csnow_begin, csnow_end);  		if (cs_nsec > cs_nsec_max)  			cs_nsec_max = cs_nsec;  		if (cs_nsec < cs_nsec_min) @@ -398,8 +404,8 @@ static inline void clocksource_reset_watchdog(void)  static void clocksource_watchdog(struct timer_list *unused)  { -	u64 csnow, wdnow, cslast, wdlast, delta;  	int64_t wd_nsec, cs_nsec, interval; +	u64 csnow, wdnow, cslast, wdlast;  	int next_cpu, reset_pending;  	struct clocksource *cs;  	enum wd_read_status read_ret; @@ -456,12 +462,8 @@ static void clocksource_watchdog(struct timer_list *unused)  			continue;  		} -		delta = clocksource_delta(wdnow, cs->wd_last, watchdog->mask); -		wd_nsec = clocksource_cyc2ns(delta, watchdog->mult, -					     watchdog->shift); - -		delta = clocksource_delta(csnow, cs->cs_last, cs->mask); -		cs_nsec = clocksource_cyc2ns(delta, cs->mult, cs->shift); +		wd_nsec = cycles_to_nsec_safe(watchdog, cs->wd_last, wdnow); +		cs_nsec = cycles_to_nsec_safe(cs, cs->cs_last, csnow);  		wdlast = cs->wd_last; /* save these in case we print them */  		cslast = cs->cs_last;  		cs->cs_last = csnow; @@ -832,7 +834,7 @@ void clocksource_start_suspend_timing(struct clocksource *cs, u64 start_cycles)   */  u64 clocksource_stop_suspend_timing(struct clocksource *cs, u64 cycle_now)  { -	u64 now, delta, nsec = 0; +	u64 now, nsec = 0;  	if (!suspend_clocksource)  		return 0; @@ -847,12 +849,8 @@ u64 clocksource_stop_suspend_timing(struct clocksource *cs, u64 cycle_now)  	else  		now = suspend_clocksource->read(suspend_clocksource); -	if (now > suspend_start) { -		delta = clocksource_delta(now, suspend_start, -					  suspend_clocksource->mask); -		nsec = mul_u64_u32_shr(delta, suspend_clocksource->mult, -				       suspend_clocksource->shift); -	} +	if (now > suspend_start) +		nsec = cycles_to_nsec_safe(suspend_clocksource, suspend_start, now);  	/*  	 * Disable the suspend timer to save power if current clocksource is @@ -1336,7 +1334,7 @@ static ssize_t current_clocksource_show(struct device *dev,  	ssize_t count = 0;  	mutex_lock(&clocksource_mutex); -	count = snprintf(buf, PAGE_SIZE, "%s\n", curr_clocksource->name); +	count = sysfs_emit(buf, "%s\n", curr_clocksource->name);  	mutex_unlock(&clocksource_mutex);  	return count;  |