From patchwork Thu Jul 10 13:32:25 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomeu Vizoso X-Patchwork-Id: 4524031 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 D41E49F26C for ; Thu, 10 Jul 2014 13:36:43 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id DA58F2012F for ; Thu, 10 Jul 2014 13:36:42 +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 D4F0520034 for ; Thu, 10 Jul 2014 13:36:41 +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 1X5EV4-0005E0-G9; Thu, 10 Jul 2014 13:35:02 +0000 Received: from mail-wg0-x22a.google.com ([2a00:1450:400c:c00::22a]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1X5EUz-0004rg-P7 for linux-arm-kernel@lists.infradead.org; Thu, 10 Jul 2014 13:34:58 +0000 Received: by mail-wg0-f42.google.com with SMTP id l18so2084392wgh.1 for ; Thu, 10 Jul 2014 06:34:34 -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=EnbXlbq0/y1RZS1w7+uNKCQKdM8CtWJrqHTJauHI2qE=; b=akKXkrpLtZjaU3OL4cn1HRXE6RPG8KTkZq3bWv1SXLI4IyqGUuYW+eI8OqV62vNHTH 5KCzQoVy2piGuH4RvCNFnkNYEpq6WgtAIlRrAmTxOgPv9FOzXQllNrJN83G4pmQCcb72 q9RaVR4JW9kLda4YndEJSdd1cqKipJDIXZ3XWKu5tF6a+PWg+kprv6w9iWP4GXL//EYx 4Bapl2nHsoyxunOVo0rdFfOVuECy6BtLSg7zGFnqivFvnAr3JjTvkjKQvmuzn/r/u1BD Kjw37loBE866ICBTX3l0iVtSaRAnT5txDOvz+P6x3Uy+pZ6dP5dszW9Vmyl+BWFzHEqc +CcQ== X-Received: by 10.180.76.20 with SMTP id g20mr19381510wiw.7.1404999274104; Thu, 10 Jul 2014 06:34:34 -0700 (PDT) Received: from localhost.localdomain (37-48-51-141.tmcz.cz. [37.48.51.141]) by mx.google.com with ESMTPSA id wi9sm110431804wjc.23.2014.07.10.06.34.32 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 10 Jul 2014 06:34:33 -0700 (PDT) From: Tomeu Vizoso To: Stephen Warren , Thierry Reding , Mike Turquette , rabin@rab.in, linux-tegra@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, tomasz.figa@gmail.com Subject: [RFC v3 4/5] clk: per-user clock accounting for debug Date: Thu, 10 Jul 2014 15:32:25 +0200 Message-Id: <1404999146-32691-5-git-send-email-tomeu.vizoso@collabora.com> X-Mailer: git-send-email 1.9.3 In-Reply-To: <1404999146-32691-1-git-send-email-tomeu.vizoso@collabora.com> References: <1404999146-32691-1-git-send-email-tomeu.vizoso@collabora.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140710_063458_340082_E0BCEDBB X-CRM114-Status: GOOD ( 16.56 ) X-Spam-Score: -0.7 (/) Cc: Javier Martinez Canillas , Tomeu Vizoso 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.4 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 | 35 +++++++++++++++++++++++++++++++---- drivers/clk/clk.h | 3 ++- drivers/clk/clkdev.c | 16 ++++++++++++---- include/linux/clk-private.h | 4 ++++ 4 files changed, 49 insertions(+), 9 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index cc1d09b..9d51900 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; } @@ -955,7 +958,20 @@ EXPORT_SYMBOL_GPL(clk_provider_disable); */ void clk_disable(struct clk *clk_user) { - clk_provider_disable(clk_to_clk_core(clk_user)); + struct clk_core *clk = clk_to_clk_core(clk_user); + unsigned long flags; + + 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); @@ -1016,7 +1032,17 @@ EXPORT_SYMBOL_GPL(clk_provider_enable); */ int clk_enable(struct clk *clk_user) { - return clk_provider_enable(clk_to_clk_core(clk_user)); + struct clk_core *clk = clk_to_clk_core(clk_user); + unsigned long flags; + int ret; + + 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); @@ -1692,8 +1718,9 @@ EXPORT_SYMBOL_GPL(clk_provider_get_parent); struct clk *clk_get_parent(struct clk *clk_user) { struct clk_core *clk = clk_to_clk_core(clk_user); + struct clk_core *parent = clk_provider_get_parent(clk); - return __clk_create_clk(clk_provider_get_parent(clk)); + 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 4d7398f..3987594 100644 --- a/drivers/clk/clk.h +++ b/drivers/clk/clk.h @@ -23,5 +23,6 @@ static inline struct clk_core *clk_to_clk_core(struct clk *clk) { return clk->core; } -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 10020b2..6ea91bf 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 @@ -195,7 +199,9 @@ EXPORT_SYMBOL_GPL(clk_provider_get_sys); struct clk *clk_get_sys(const char *dev_id, const char *con_id) { - return __clk_create_clk(clk_provider_get_sys(dev_id, con_id)); + struct clk_core *clk = clk_provider_get_sys(dev_id, con_id); + + return __clk_create_clk(clk, dev_id, con_id); } EXPORT_SYMBOL(clk_get_sys); @@ -218,7 +224,9 @@ EXPORT_SYMBOL(clk_provider_get); struct clk *clk_get(struct device *dev, const char *con_id) { - return __clk_create_clk(clk_provider_get(dev, con_id)); + const char *dev_id = dev ? dev_name(dev) : NULL; + + return __clk_create_clk(clk_provider_get(dev, con_id), dev_id, con_id); } EXPORT_SYMBOL(clk_get); 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; }; /*