Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932761AbcLHUxX (ORCPT ); Thu, 8 Dec 2016 15:53:23 -0500 Received: from Galois.linutronix.de ([146.0.238.70]:47095 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932164AbcLHUwV (ORCPT ); Thu, 8 Dec 2016 15:52:21 -0500 Message-Id: <20161208204228.921674404@linutronix.de> User-Agent: quilt/0.63-1 Date: Thu, 08 Dec 2016 20:49:38 -0000 From: Thomas Gleixner To: LKML Cc: John Stultz , Peter Zijlstra , Ingo Molnar , David Gibson , Liav Rehana , Chris Metcalf , Richard Cochran , Parit Bhargava , Laurent Vivier , "Christopher S. Hall" Subject: [patch 4/6] timekeeping: Use mul_u64_u32_shr() instead of open coding it References: <20161208202623.883855034@linutronix.de> MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-15 Content-Disposition: inline; filename=timekeeping--Use-mul_u64_u32_shr---instead-of-open-coding-it.patch Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 1807 Lines: 54 The resume code must deal with a clocksource delta which is potentially big enough to overflow the 64bit mult. Replace the open coded handling with the proper function. Signed-off-by: Thomas Gleixner --- kernel/time/timekeeping.c | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -1615,7 +1615,7 @@ void timekeeping_resume(void) struct clocksource *clock = tk->tkr_mono.clock; unsigned long flags; struct timespec64 ts_new, ts_delta; - cycle_t cycle_now, cycle_delta; + cycle_t cycle_now; sleeptime_injected = false; read_persistent_clock64(&ts_new); @@ -1641,27 +1641,11 @@ void timekeeping_resume(void) cycle_now = tk->tkr_mono.read(clock); if ((clock->flags & CLOCK_SOURCE_SUSPEND_NONSTOP) && cycle_now > tk->tkr_mono.cycle_last) { - u64 num, max = ULLONG_MAX; - u32 mult = clock->mult; - u32 shift = clock->shift; - s64 nsec = 0; - - cycle_delta = clocksource_delta(cycle_now, tk->tkr_mono.cycle_last, - tk->tkr_mono.mask); - - /* - * "cycle_delta * mutl" may cause 64 bits overflow, if the - * suspended time is too long. In that case we need do the - * 64 bits math carefully - */ - do_div(max, mult); - if (cycle_delta > max) { - num = div64_u64(cycle_delta, max); - nsec = (((u64) max * mult) >> shift) * num; - cycle_delta -= num * max; - } - nsec += ((u64) cycle_delta * mult) >> shift; + u64 nsec, cyc_delta; + cyc_delta = clocksource_delta(cycle_now, tk->tkr_mono.cycle_last, + tk->tkr_mono.mask); + nsec = mul_u64_u32_shr(cyc_delta, clock->mult, clock->shift); ts_delta = ns_to_timespec64(nsec); sleeptime_injected = true; } else if (timespec64_compare(&ts_new, &timekeeping_suspend_time) > 0) {