From patchwork Thu May 19 17:32:22 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 798232 Received: from bombadil.infradead.org (bombadil.infradead.org [18.85.46.34]) by demeter2.kernel.org (8.14.4/8.14.3) with ESMTP id p4JHYF4l022105 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Thu, 19 May 2011 17:34:36 GMT Received: from canuck.infradead.org ([2001:4978:20e::1]) by bombadil.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1QN75J-0008LH-Re; Thu, 19 May 2011 17:32:30 +0000 Received: from localhost ([127.0.0.1] helo=canuck.infradead.org) by canuck.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1QN75I-000797-5w; Thu, 19 May 2011 17:32:28 +0000 Received: from mail-iy0-f177.google.com ([209.85.210.177]) by canuck.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1QN75E-00078P-H4 for linux-arm-kernel@lists.infradead.org; Thu, 19 May 2011 17:32:25 +0000 Received: by iyb39 with SMTP id 39so2811042iyb.36 for ; Thu, 19 May 2011 10:32:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:sender:in-reply-to:references:date :x-google-sender-auth:message-id:subject:from:to:cc:content-type :content-transfer-encoding; bh=aLyjvzkQBi+pzZji+d13TGPV78GqNbTYEnpgKZPAySE=; b=KtCXXn97QxhGymALzqeh0TQ78Hpy32LhzEaOu3Vlj2OA7leLFh5OswVFAzxiXZb+ih Fx0Pb+RmD1dh9SbFg1FWgEukCdlWDjsc6qJSC5UgNWsAdofxB0bLJdtJ9CjC2/jLu1wa +1iwfrI3/4bpeBbTLw9os+XiDuto4vLtc6BKM= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:sender:in-reply-to:references:date :x-google-sender-auth:message-id:subject:from:to:cc:content-type :content-transfer-encoding; b=j0OAh50dRp6MzC//xmtptMFdIeAkARq7Oq2R3NUtK0nET0rVb24r+r811qB7G5pIod c/+0mFwZtAr0PWigtKkVJYdl7MuBuKWdP58Vi8LcEptsPVf1G3n1uj6LEZ18YNY9fP66 T4Kgng7uD8fppK5IQxCuhpS7Wi8yjXoye2H1o= MIME-Version: 1.0 Received: by 10.231.78.144 with SMTP id l16mr2536189ibk.26.1305826342840; Thu, 19 May 2011 10:32:22 -0700 (PDT) Received: by 10.231.20.3 with HTTP; Thu, 19 May 2011 10:32:22 -0700 (PDT) In-Reply-To: <1305588114-23728-1-git-send-email-ccross@android.com> References: <1305588114-23728-1-git-send-email-ccross@android.com> Date: Thu, 19 May 2011 19:32:22 +0200 X-Google-Sender-Auth: NxR45ba9c8uQNAz08zmB5VYktTs Message-ID: Subject: Re: [PATCH] ARM: smp_twd: Reconfigure clockevents after cpufreq change From: Linus Walleij To: Colin Cross , Thomas Gleixner X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.6 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20110519_133224_682674_CE9713F1 X-CRM114-Status: GOOD ( 26.42 ) X-Spam-Score: -0.7 (/) X-Spam-Report: SpamAssassin version 3.3.1 on canuck.infradead.org summary: Content analysis details: (-0.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [209.85.210.177 listed in list.dnswl.org] 0.0 FREEMAIL_FROM Sender email is freemail (linus.ml.walleij[at]gmail.com) 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.0 RFC_ABUSE_POST Both abuse and postmaster missing on sender domain Cc: Russell King , linux-arm-kernel@lists-infradead.org, linux-kernel@vger.kernel.org, Santosh Shilimkar , Martin Persson , linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter2.kernel.org [140.211.167.43]); Thu, 19 May 2011 17:34:36 +0000 (UTC) X-MIME-Autoconverted: from quoted-printable to 8bit by demeter2.kernel.org id p4JHYF4l022105 2011/5/17 Colin Cross : > This patch depends on Thomas Gleixner's patch to add clockevents_reconfigure > See: https://lkml.org/lkml/2011/5/13/122 Patch set has evolved, see below. Also note that you more or less reimplement Rob Herrings patch: http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=6802/1 (no big deal I guess, give him a nod) To work with Thomas full changeset just create a fresh branch and: git pull git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-tip.git timers/clockevents Pls change subject from ARM: to clockevents: and merge through Thomas tree (IMHO). > diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c > index 60636f4..dbf58d4 100644 > --- a/arch/arm/kernel/smp_twd.c > +++ b/arch/arm/kernel/smp_twd.c > @@ -10,21 +10,29 @@ >  */ >  #include >  #include > +#include > +#include >  #include >  #include > +#include >  #include >  #include >  #include >  #include >  #include > +#include > >  #include >  #include > > +#define TWD_MIN_RANGE 4 > + Loose this. Let the framework decide using the function below. >  /* set up by the platform code */ >  void __iomem *twd_base; > > +static struct clk *twd_clk; >  static unsigned long twd_timer_rate; > +static DEFINE_PER_CPU(struct clock_event_device *, twd_ce); > >  static void twd_set_mode(enum clock_event_mode mode, >                        struct clock_event_device *clk) > @@ -80,6 +88,49 @@ int twd_timer_ack(void) >        return 0; >  } > > +/* > + * Updates clockevent frequency when the cpu frequency changes. > + * Called on the cpu that is changing frequency with interrupts disabled. > + */ > +static void twd_update_frequency(void *data) > +{ > +       twd_timer_rate = clk_get_rate(twd_clk); > + > +       clockevents_reconfigure(__get_cpu_var(twd_ce), twd_timer_rate, > +                       TWD_MIN_RANGE); Changed name to clockevents_update_freq(), dropped range argument. > +} > + > +static int twd_cpufreq_transition(struct notifier_block *nb, > +       unsigned long state, void *data) > +{ > +       struct cpufreq_freqs *freqs = data; > + > +       /* > +        * The twd clock events must be reprogrammed to account for the new > +        * frequency.  The timer is local to a cpu, so cross-call to the > +        * changing cpu. > +        */ > +       if (state == CPUFREQ_POSTCHANGE || state == CPUFREQ_RESUMECHANGE) > +               smp_call_function_single(freqs->cpu, twd_update_frequency, > +                       NULL, 1); > + > +       return NOTIFY_OK; > +} > + > +static struct notifier_block twd_cpufreq_nb = { > +       .notifier_call = twd_cpufreq_transition, > +}; > + > +static int twd_cpufreq_init(void) > +{ > +       if (!IS_ERR_OR_NULL(twd_clk)) > +               return cpufreq_register_notifier(&twd_cpufreq_nb, > +                       CPUFREQ_TRANSITION_NOTIFIER); > + > +       return 0; > +} > +core_initcall(twd_cpufreq_init); > + >  static void __cpuinit twd_calibrate_rate(void) >  { >        unsigned long count; > @@ -124,7 +175,16 @@ static void __cpuinit twd_calibrate_rate(void) >  */ >  void __cpuinit twd_timer_setup(struct clock_event_device *clk) >  { > -       twd_calibrate_rate(); > +       if (twd_clk == NULL) { > +               twd_clk = clk_get_sys("smp_twd", NULL); > +               if (IS_ERR_OR_NULL(twd_clk)) > +                       pr_warn("%s: no clock found\n", __func__); > +       } > + > +       if (!IS_ERR_OR_NULL(twd_clk)) > +               twd_timer_rate = clk_get_rate(twd_clk); > +       else > +               twd_calibrate_rate(); > >        clk->name = "local_timer"; >        clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | > @@ -132,13 +192,16 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) >        clk->rating = 350; >        clk->set_mode = twd_set_mode; >        clk->set_next_event = twd_set_next_event; > -       clk->shift = 20; > -       clk->mult = div_sc(twd_timer_rate, NSEC_PER_SEC, clk->shift); > + > +       clockevents_calc_mult_shift(clk, twd_timer_rate, TWD_MIN_RANGE); > + >        clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk); >        clk->min_delta_ns = clockevent_delta2ns(0xf, clk); Get rid of everything between clk->shift ... and here and replace it with: clockevents_config_and_register(clk, twd_timer_rate, 0xf, 0xffffffff); >        /* Make sure our local interrupt controller has this enabled */ >        gic_enable_ppi(clk->irq); > > +       __get_cpu_var(twd_ce) = clk; > + >        clockevents_register_device(clk); >  } Or just smack in this patch on top: From fd546090b8f0cb5df06103c014466c86cf58b73a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 19 May 2011 18:55:22 +0200 Subject: [PATCH] Fix smallish cleanup --- arch/arm/kernel/smp_twd.c | 13 +++---------- 1 files changed, 3 insertions(+), 10 deletions(-) } diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index dbf58d4..968f298 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -25,8 +25,6 @@ #include #include -#define TWD_MIN_RANGE 4 - /* set up by the platform code */ void __iomem *twd_base; @@ -96,8 +94,7 @@ static void twd_update_frequency(void *data) { twd_timer_rate = clk_get_rate(twd_clk); - clockevents_reconfigure(__get_cpu_var(twd_ce), twd_timer_rate, - TWD_MIN_RANGE); + clockevents_update_freq(__get_cpu_var(twd_ce), twd_timer_rate); } static int twd_cpufreq_transition(struct notifier_block *nb, @@ -193,15 +190,11 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) clk->set_mode = twd_set_mode; clk->set_next_event = twd_set_next_event; - clockevents_calc_mult_shift(clk, twd_timer_rate, TWD_MIN_RANGE); - - clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk); - clk->min_delta_ns = clockevent_delta2ns(0xf, clk); - /* Make sure our local interrupt controller has this enabled */ gic_enable_ppi(clk->irq); __get_cpu_var(twd_ce) = clk; - clockevents_register_device(clk); + clockevents_config_and_register(clk, twd_timer_rate, + 0xf, 0xffffffff);