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: 12800 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 09A9B23E37 for ; Fri, 9 Nov 2012 23:47:45 +0000 (UTC) Received: from mail-ia0-f180.google.com (mail-ia0-f180.google.com [209.85.210.180]) by fiordland.canonical.com (Postfix) with ESMTP id 7DDBCA18395 for ; Fri, 9 Nov 2012 23:47:44 +0000 (UTC) Received: by mail-ia0-f180.google.com with SMTP id f6so3011375iag.11 for ; Fri, 09 Nov 2012 15:47:43 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf:date:from :to:cc:subject:in-reply-to:message-id:references:user-agent :mime-version:content-type:x-gm-message-state; bh=sw4B1NHvDiyDoWQV13j7rP+gjc3TEkTM4CDYdZENHpM=; b=Ofm3PAPRtJKtz9GUg8ycJC4pWpCtnDSlARh2+S640CAyYsfUM0Y58hpxi2Ah5BQTJ+ OmHGO3y/udLwQrSslu3Sh1jOT/TxAWIh5qLJfAy5xNf0cg2G8VGrsByZl7V24HC/RyED tNAo2xzcxZz17esISXwzMVKYdADE0h73oY+SpdiHSYxwkfxxCBoPVsqKXp4vItD+ewz2 rzd0pmHDZH2IUCLKWDGhQ049e6r/O2OomlFYSOnuWtVkkhjPtSMUAYP/Fmby4i4Xuu7S BlUump2u5C15Jbl13r+JWy6vKqiZnCC3CaqUB0xae7x3SDgEXKv6RQ47E7RgHwKUZMx/ O1pg== Received: by 10.43.46.2 with SMTP id um2mr5068343icb.18.1352504863836; Fri, 09 Nov 2012 15:47:43 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.50.67.148 with SMTP id n20csp102219igt; Fri, 9 Nov 2012 15:47:43 -0800 (PST) Received: by 10.43.57.5 with SMTP id we5mr11795180icb.23.1352504862599; Fri, 09 Nov 2012 15:47:42 -0800 (PST) Received: from utopia.booyaka.com (utopia.booyaka.com. [74.50.51.50]) by mx.google.com with ESMTPS id ph2si32742718icb.30.2012.11.09.15.47.42 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 09 Nov 2012 15:47:42 -0800 (PST) Received-SPF: neutral (google.com: 74.50.51.50 is neither permitted nor denied by best guess record for domain of paul@pwsan.com) client-ip=74.50.51.50; Authentication-Results: mx.google.com; spf=neutral (google.com: 74.50.51.50 is neither permitted nor denied by best guess record for domain of paul@pwsan.com) smtp.mail=paul@pwsan.com 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 cc: rnayak@ti.com, linux-omap@vger.kernel.org, linux-arm-kernel@lists.infradead.org, patches@linaro.org 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-Gm-Message-State: ALoCoQlJo3+2epRldakAGGoAx7bOdWlJ4SX3gAHMwTYdXpDXptaq1ZjvT3mMAnJZ0SxxRq0Yztml 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; }