From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933351AbcHVXei (ORCPT ); Mon, 22 Aug 2016 19:34:38 -0400 Received: from mail-wm0-f65.google.com ([74.125.82.65]:34464 "EHLO mail-wm0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932719AbcHVXee (ORCPT ); Mon, 22 Aug 2016 19:34:34 -0400 From: Nicolai Stange To: Thomas Gleixner Cc: John Stultz , linux-kernel@vger.kernel.org, Nicolai Stange Subject: [RFC v4 22/22] timekeeping: inform clockevents about freq adjustments Date: Tue, 23 Aug 2016 01:33:20 +0200 Message-Id: <20160822233320.4548-23-nicstange@gmail.com> X-Mailer: git-send-email 2.9.2 In-Reply-To: <20160822233320.4548-1-nicstange@gmail.com> References: <20160822233320.4548-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_adjusted should be changed accordingly, too. Introduce clockevents_adjust_all_freqs() which traverses all registered clockevent devices and recalculates their ->mult_adjusted 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 ee7cd40..8f58565 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -561,6 +561,31 @@ void __clockevents_adjust_freq(struct clock_event_device *dev) dev->shift)); } +void clockevents_adjust_all_freqs(u32 mult_cs_mono, u32 mult_cs_raw) +{ + u32 last_mult_raw = 0, last_mult_adjusted = 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_adjusted = + __clockevents_calc_adjust_freq(mult_raw, + mult_cs_mono, + mult_cs_raw); + } + dev->mult_adjusted = last_mult_adjusted; + } + 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 6eac5b5..8d378b9 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -1845,6 +1845,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.2