From patchwork Fri Nov 9 23:47:41 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Walmsley X-Patchwork-Id: 1722551 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id DEF2B3FC8F for ; Fri, 9 Nov 2012 23:49:33 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TWyId-0003Rk-Q1; Fri, 09 Nov 2012 23:47:47 +0000 Received: from utopia.booyaka.com ([74.50.51.50]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1TWyIZ-0003RC-LQ for linux-arm-kernel@lists.infradead.org; Fri, 09 Nov 2012 23:47:44 +0000 Received: (qmail 3876 invoked by uid 1019); 9 Nov 2012 23:47:41 -0000 Date: Fri, 9 Nov 2012 23:47:41 +0000 (UTC) From: Paul Walmsley To: Mike Turquette Subject: Re: [PATCH v2 00/26] Move OMAP2+ over to common clk framework In-Reply-To: <20121109221813.17381.31431@nucleus> Message-ID: References: <1352337181-29427-1-git-send-email-mturquette@ti.com> <20121109221813.17381.31431@nucleus> User-Agent: Alpine 2.00 (DEB 1167 2008-08-23) MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20121109_184743_818187_664E48BE X-CRM114-Status: GOOD ( 24.04 ) X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-1.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: linux-omap@vger.kernel.org, rnayak@ti.com, linux-arm-kernel@lists.infradead.org, patches@linaro.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 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 On Fri, 9 Nov 2012, Mike Turquette wrote: > I just did some more testing on your branch and everything looks great. > The only thing that caught my eye was using the clk-private.h header in > the top-most patch. The following patch will help me sleep better at > night: > > diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c > index ba4d14c..3848735 100644 > --- a/arch/arm/mach-omap2/clockdomain.c > +++ b/arch/arm/mach-omap2/clockdomain.c > @@ -22,7 +22,7 @@ > #include > #include > #include > -#include > +#include > > #include Just folded this one in, the updated patch follows. > Tested on 3530 ES3.0 Beagleboard, boot + suspend/resume. Great! - Paul From: Mike Turquette Date: Fri, 9 Nov 2012 11:28:42 -0700 Subject: [PATCH] ARM: OMAP2+: clockdomain: bypass clockdomain handling when disabling unused clks The OMAP port to the common clk framework[1] resulted in spurious WARNs while disable unused clocks. This is due to _clkdm_clk_hwmod_disable catching clkdm->usecount's with a value of zero. Even less desirable it would not allow the clkdm_clk_disable function pointer to get called due to an early return of -ERANGE. This patch adds a check for such a corner case by skipping the WARN and early return in the event that clkdm->usecount and clk->enable_usecount are both zero. Presumably this could only happen during the check for unused clocks at boot-time. [1] http://article.gmane.org/gmane.linux.ports.arm.omap/88824 Signed-off-by: Mike Turquette [paul@pwsan.com: split the hwmod and clock disable cases; modified the code to skip the clockdomain handling during the disable-unused-clocks phase; added COMMON_CLK ifdef; removed include of clk-private.h at Mike's request] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clockdomain.c | 91 ++++++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 37 deletions(-) diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 64e5046..4424f3d 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -947,35 +948,6 @@ static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm) return 0; } -static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm) -{ - unsigned long flags; - - if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_disable) - return -EINVAL; - - spin_lock_irqsave(&clkdm->lock, flags); - - if (atomic_read(&clkdm->usecount) == 0) { - spin_unlock_irqrestore(&clkdm->lock, flags); - WARN_ON(1); /* underflow */ - return -ERANGE; - } - - if (atomic_dec_return(&clkdm->usecount) > 0) { - spin_unlock_irqrestore(&clkdm->lock, flags); - return 0; - } - - arch_clkdm->clkdm_clk_disable(clkdm); - pwrdm_state_switch(clkdm->pwrdm.ptr); - spin_unlock_irqrestore(&clkdm->lock, flags); - - pr_debug("clockdomain: %s: disabled\n", clkdm->name); - - return 0; -} - /** * clkdm_clk_enable - add an enabled downstream clock to this clkdm * @clkdm: struct clockdomain * @@ -1018,15 +990,39 @@ int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) */ int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk) { - /* - * XXX Rewrite this code to maintain a list of enabled - * downstream clocks for debugging purposes? - */ + unsigned long flags; - if (!clk) + if (!clkdm || !clk || !arch_clkdm || !arch_clkdm->clkdm_clk_disable) return -EINVAL; - return _clkdm_clk_hwmod_disable(clkdm); + spin_lock_irqsave(&clkdm->lock, flags); + +#ifdef CONFIG_COMMON_CLK + /* corner case: disabling unused clocks */ + if (__clk_get_enable_count(clk) == 0) + goto ccd_exit; +#endif + + if (atomic_read(&clkdm->usecount) == 0) { + spin_unlock_irqrestore(&clkdm->lock, flags); + WARN_ON(1); /* underflow */ + return -ERANGE; + } + + if (atomic_dec_return(&clkdm->usecount) > 0) { + spin_unlock_irqrestore(&clkdm->lock, flags); + return 0; + } + + arch_clkdm->clkdm_clk_disable(clkdm); + pwrdm_state_switch(clkdm->pwrdm.ptr); + + pr_debug("clockdomain: %s: disabled\n", clkdm->name); + +ccd_exit: + spin_unlock_irqrestore(&clkdm->lock, flags); + + return 0; } /** @@ -1077,6 +1073,8 @@ int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh) */ int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh) { + unsigned long flags; + /* The clkdm attribute does not exist yet prior OMAP4 */ if (cpu_is_omap24xx() || cpu_is_omap34xx()) return 0; @@ -1086,9 +1084,28 @@ int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh) * downstream hwmods for debugging purposes? */ - if (!oh) + if (!clkdm || !oh || !arch_clkdm || !arch_clkdm->clkdm_clk_disable) return -EINVAL; - return _clkdm_clk_hwmod_disable(clkdm); + spin_lock_irqsave(&clkdm->lock, flags); + + if (atomic_read(&clkdm->usecount) == 0) { + spin_unlock_irqrestore(&clkdm->lock, flags); + WARN_ON(1); /* underflow */ + return -ERANGE; + } + + if (atomic_dec_return(&clkdm->usecount) > 0) { + spin_unlock_irqrestore(&clkdm->lock, flags); + return 0; + } + + arch_clkdm->clkdm_clk_disable(clkdm); + pwrdm_state_switch(clkdm->pwrdm.ptr); + spin_unlock_irqrestore(&clkdm->lock, flags); + + pr_debug("clockdomain: %s: disabled\n", clkdm->name); + + return 0; }