From patchwork Thu Jul 31 11:39:38 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomeu Vizoso X-Patchwork-Id: 4655311 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 316009F2B8 for ; Thu, 31 Jul 2014 11:43:15 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 2861D201BB for ; Thu, 31 Jul 2014 11:43:14 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4262C2017A for ; Thu, 31 Jul 2014 11:43:13 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1XCojJ-0001rU-0b; Thu, 31 Jul 2014 11:41:05 +0000 Received: from mail-wi0-x22a.google.com ([2a00:1450:400c:c05::22a]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1XCoix-0001bu-0C for linux-arm-kernel@lists.infradead.org; Thu, 31 Jul 2014 11:40:43 +0000 Received: by mail-wi0-f170.google.com with SMTP id f8so1116272wiw.1 for ; Thu, 31 Jul 2014 04:40:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=EzbqGxc7E0xiJlfmUBiBFcngB6GBnrmcyj+w5EaPIT8=; b=T/dkHIjEcnHQVLiwU40/of6olv2o0dZz37BCnb1GzQXbTlUvCvr6M7b6Wj91PpSj+S 4/Q/gxmVAx3xApZ31XEJnZuuJnXnkV6EABUyXyaps1hSGM6schD+BFHMnZZ11lZXGBAE Py1Ena5wWyg3YX/cSYF+zPsErlMrIjENJ9q0rivOYtfFUIfc2pf7cZ/pDNIym0aD9369 elTK6uD8aMDmIa9Htd/FSV1TWw/Em8fYI8eiVyNpzErz1PTEDiBi2XjiPBsYNiyWoQt/ yfCGayouT0j59vmTS8TA3XZBEz9VwoQd9ESwCjSe/T0Tpbg5v5cBdany3y554muV/JI4 8TPw== X-Received: by 10.180.78.100 with SMTP id a4mr16175206wix.36.1406806819595; Thu, 31 Jul 2014 04:40:19 -0700 (PDT) Received: from cizrna.lan (37-48-39-114.tmcz.cz. [37.48.39.114]) by mx.google.com with ESMTPSA id k6sm12815328wjq.5.2014.07.31.04.40.17 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 31 Jul 2014 04:40:18 -0700 (PDT) From: Tomeu Vizoso To: Mike Turquette Subject: [PATCH v4 RESEND 5/6] clk: per-user clock accounting for debug Date: Thu, 31 Jul 2014 13:39:38 +0200 Message-Id: <1406806779-26939-5-git-send-email-tomeu.vizoso@collabora.com> X-Mailer: git-send-email 1.9.3 In-Reply-To: <1406806779-26939-1-git-send-email-tomeu.vizoso@collabora.com> References: <1406806779-26939-1-git-send-email-tomeu.vizoso@collabora.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140731_044043_339896_2B7E6A27 X-CRM114-Status: GOOD ( 17.11 ) X-Spam-Score: -0.7 (/) Cc: Tomeu Vizoso , Stephen Warren , Tomasz Figa , linux-kernel@vger.kernel.org, rabin@rab.in, Thierry Reding , Peter De Schrijver , linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-2.5 required=5.0 tests=BAYES_00,DKIM_SIGNED, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When a clock has multiple users, the WARNING on imbalance of enable/disable may not show the guilty party since although they may have commited the error earlier, the warning is emitted later when some other user, presumably innocent, disables the clock. Provide per-user clock enable/disable accounting and disabler tracking in order to help debug these problems. Based on previous work by Rabin Vincent . Signed-off-by: Tomeu Vizoso --- drivers/clk/clk.c | 38 ++++++++++++++++++++++++++++++++++---- drivers/clk/clk.h | 3 ++- drivers/clk/clkdev.c | 12 ++++++++---- include/linux/clk-private.h | 4 ++++ 4 files changed, 48 insertions(+), 9 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 095edaa..f1cdc01 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -568,7 +568,8 @@ static int clk_disable_unused(void) } late_initcall_sync(clk_disable_unused); -struct clk *__clk_create_clk(struct clk_core *clk_core) +struct clk *__clk_create_clk(struct clk_core *clk_core, const char *dev, + const char *con) { struct clk *clk; @@ -581,6 +582,8 @@ struct clk *__clk_create_clk(struct clk_core *clk_core) return ERR_PTR(-ENOMEM); clk->core = clk_core; + clk->dev_id = dev; + clk->con_id = con; return clk; } @@ -961,10 +964,25 @@ EXPORT_SYMBOL_GPL(clk_provider_disable); */ void clk_disable(struct clk *clk_user) { + struct clk_core *clk; + unsigned long flags; + if (IS_ERR_OR_NULL(clk_user)) return; - clk_provider_disable(clk_to_clk_core(clk_user)); + clk = clk_to_clk_core(clk_user); + + flags = clk_enable_lock(); + if (!WARN(clk_user->enable_count == 0, + "incorrect disable clk dev %s con %s last disabler %pF\n", + clk_user->dev_id, clk_user->con_id, clk_user->last_disable)) { + + clk_user->last_disable = __builtin_return_address(0); + clk_user->enable_count--; + + __clk_disable(clk); + } + clk_enable_unlock(flags); } EXPORT_SYMBOL_GPL(clk_disable); @@ -1025,10 +1043,22 @@ EXPORT_SYMBOL_GPL(clk_provider_enable); */ int clk_enable(struct clk *clk_user) { + struct clk_core *clk; + unsigned long flags; + int ret; + if (!clk_user) return 0; - return clk_provider_enable(clk_to_clk_core(clk_user)); + clk = clk_to_clk_core(clk_user); + + flags = clk_enable_lock(); + ret = __clk_enable(clk); + if (!ret) + clk_user->enable_count++; + clk_enable_unlock(flags); + + return ret; } EXPORT_SYMBOL_GPL(clk_enable); @@ -1726,7 +1756,7 @@ struct clk *clk_get_parent(struct clk *clk_user) clk = clk_to_clk_core(clk_user); parent = clk_provider_get_parent(clk); - return __clk_create_clk(parent); + return __clk_create_clk(parent, clk_user->dev_id, clk_user->con_id); } EXPORT_SYMBOL_GPL(clk_get_parent); diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h index 3b3068b..49eff38 100644 --- a/drivers/clk/clk.h +++ b/drivers/clk/clk.h @@ -19,5 +19,6 @@ void of_clk_unlock(void); #endif #if defined(CONFIG_COMMON_CLK) -struct clk *__clk_create_clk(struct clk_core *clk_core); +struct clk *__clk_create_clk(struct clk_core *clk_core, const char *dev, + const char *con); #endif diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index 912de48..517a25b 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c @@ -76,7 +76,9 @@ struct clk_core *of_clk_provider_get(struct device_node *np, int index) struct clk *of_clk_get(struct device_node *np, int index) { - return __clk_create_clk(of_clk_provider_get(np, index)); + struct clk_core *clk = of_clk_provider_get(np, index); + + return __clk_create_clk(clk, np->full_name, NULL); } EXPORT_SYMBOL(of_clk_get); @@ -128,7 +130,9 @@ struct clk_core *of_clk_provider_get_by_name(struct device_node *np, const char */ struct clk *of_clk_get_by_name(struct device_node *np, const char *name) { - return __clk_create_clk(of_clk_provider_get_by_name(np, name)); + struct clk_core *clk = of_clk_provider_get_by_name(np, name); + + return __clk_create_clk(clk, np->full_name, NULL); } EXPORT_SYMBOL(of_clk_get_by_name); #endif @@ -200,7 +204,7 @@ struct clk *clk_get_sys(const char *dev_id, const char *con_id) #if defined(CONFIG_COMMON_CLK) struct clk_core *clk = clk_provider_get_sys(dev_id, con_id); - return __clk_create_clk(clk); + return __clk_create_clk(clk, dev_id, con_id); #else struct clk_lookup *cl; @@ -242,7 +246,7 @@ struct clk *clk_get(struct device *dev, const char *con_id) #if defined(CONFIG_COMMON_CLK) const char *dev_id = dev ? dev_name(dev) : NULL; - return __clk_create_clk(clk_provider_get(dev, con_id)); + return __clk_create_clk(clk_provider_get(dev, con_id), dev_id, con_id); #else const char *dev_id = dev ? dev_name(dev) : NULL; struct clk *clk; diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h index 2c1ece9..9657fc8 100644 --- a/include/linux/clk-private.h +++ b/include/linux/clk-private.h @@ -57,6 +57,10 @@ struct clk_core { struct clk { struct clk_core *core; + unsigned int enable_count; + const char *dev_id; + const char *con_id; + void *last_disable; }; /*