From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752158AbcGMNBB (ORCPT ); Wed, 13 Jul 2016 09:01:01 -0400 Received: from mail-wm0-f66.google.com ([74.125.82.66]:34646 "EHLO mail-wm0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750890AbcGMNAx (ORCPT ); Wed, 13 Jul 2016 09:00:53 -0400 From: Nicolai Stange To: Thomas Gleixner Cc: John Stultz , linux-kernel@vger.kernel.org, Nicolai Stange Subject: [RFC v3 3/3] kernel/time/timekeeping: inform clockevents about freq adjustments Date: Wed, 13 Jul 2016 15:00:17 +0200 Message-Id: <20160713130017.8202-4-nicstange@gmail.com> X-Mailer: git-send-email 2.9.0 In-Reply-To: <20160713130017.8202-1-nicstange@gmail.com> References: <20160713130017.8202-1-nicstange@gmail.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Upon adjustments of the monotonic clock's frequencies from the timekeeping core, the clockevents devices' ->mult_mono should be changed accordingly, too. Introduce clockevents_adjust_all_freqs() which traverses all registered clockevent devices and recalculates their ->mult_mono based on the monotonic clock's current frequency. Call clockevents_adjust_all_freqs() from timekeeping_apply_adjustment(). Signed-off-by: Nicolai Stange --- kernel/time/clockevents.c | 25 +++++++++++++++++++++++++ kernel/time/tick-internal.h | 1 + kernel/time/timekeeping.c | 3 +++ 3 files changed, 29 insertions(+) diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index ec01375..f3fb1e5 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -558,6 +558,31 @@ void __clockevents_adjust_freq(struct clock_event_device *dev) mult_cs_raw); } +void clockevents_adjust_all_freqs(u32 mult_cs_mono, u32 mult_cs_raw) +{ + u32 last_mult_raw = 0, last_mult_mono = 0; + u32 mult_raw; + unsigned long flags; + struct clock_event_device *dev; + + raw_spin_lock_irqsave(&clockevents_lock, flags); + list_for_each_entry(dev, &clockevent_devices, list) { + if (!(dev->features & CLOCK_EVT_FEAT_ONESHOT)) + continue; + + mult_raw = dev->mult; + if (mult_raw != last_mult_raw) { + last_mult_raw = mult_raw; + last_mult_mono = + __clockevents_calc_adjust_freq(mult_raw, + mult_cs_mono, + mult_cs_raw); + } + dev->mult_mono = last_mult_mono; + } + raw_spin_unlock_irqrestore(&clockevents_lock, flags); +} + int __clockevents_update_freq(struct clock_event_device *dev, u32 freq) { clockevents_config(dev, freq); diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h index 0b29d23..9162671 100644 --- a/kernel/time/tick-internal.h +++ b/kernel/time/tick-internal.h @@ -56,6 +56,7 @@ extern int clockevents_program_event(struct clock_event_device *dev, ktime_t expires, bool force); extern void clockevents_handle_noop(struct clock_event_device *dev); extern int __clockevents_update_freq(struct clock_event_device *dev, u32 freq); +extern void clockevents_adjust_all_freqs(u32 mult_cs_mono, u32 mult_cs_raw); extern void timekeeping_get_mono_mult(u32 *mult_cs_mono, u32 *mult_cs_raw); extern ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt); diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index a011ae1..e98f67c 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -1852,6 +1852,9 @@ static __always_inline void timekeeping_apply_adjustment(struct timekeeper *tk, tk->xtime_interval += interval; tk->tkr_mono.xtime_nsec -= offset; tk->ntp_error -= (interval - offset) << tk->ntp_error_shift; + + clockevents_adjust_all_freqs(tk->tkr_mono.mult, + tk->tkr_mono.clock->mult); } /* -- 2.9.0