public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Stephen Boyd <sboyd@codeaurora.org>
To: Mike Turquette <mturquette@linaro.org>,
	Stephen Boyd <sboyd@codeaurora.org>
Cc: linux-kernel@vger.kernel.org, Steven Rostedt <rostedt@goodmis.org>
Subject: [PATCH] clk: Add tracepoints for hardware operations
Date: Fri, 30 Jan 2015 16:16:11 -0800	[thread overview]
Message-ID: <1422663371-31056-1-git-send-email-sboyd@codeaurora.org> (raw)

It's useful to have tracepoints around operations that change the
hardware state so that we can debug clock hardware performance
and operations. Four basic types of events are supported: on/off
events for enable, disable, prepare, unprepare that only record
an event and a clock name, rate changing events for
clk_set_{min_,max_}rate{_range}(), phase changing events for
clk_set_phase() and parent changing events for clk_set_parent().

Cc: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk.c          |  32 ++++++++
 include/trace/events/clk.h | 198 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 230 insertions(+)
 create mode 100644 include/trace/events/clk.h

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index a29daf9edea4..271c3fe71277 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -22,6 +22,9 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/clk.h>
+
 #include "clk.h"
 
 static DEFINE_SPINLOCK(enable_lock);
@@ -448,10 +451,12 @@ static void clk_unprepare_unused_subtree(struct clk_core *clk)
 		return;
 
 	if (clk_core_is_prepared(clk)) {
+		trace_clk_unprepare(clk);
 		if (clk->ops->unprepare_unused)
 			clk->ops->unprepare_unused(clk->hw);
 		else if (clk->ops->unprepare)
 			clk->ops->unprepare(clk->hw);
+		trace_clk_unprepare_complete(clk);
 	}
 }
 
@@ -478,10 +483,12 @@ static void clk_disable_unused_subtree(struct clk_core *clk)
 	 * back to .disable
 	 */
 	if (clk_core_is_enabled(clk)) {
+		trace_clk_disable(clk);
 		if (clk->ops->disable_unused)
 			clk->ops->disable_unused(clk->hw);
 		else if (clk->ops->disable)
 			clk->ops->disable(clk->hw);
+		trace_clk_disable_complete(clk);
 	}
 
 unlock_out:
@@ -861,9 +868,12 @@ static void clk_core_unprepare(struct clk_core *clk)
 
 	WARN_ON(clk->enable_count > 0);
 
+	trace_clk_unprepare(clk);
+
 	if (clk->ops->unprepare)
 		clk->ops->unprepare(clk->hw);
 
+	trace_clk_unprepare_complete(clk);
 	clk_core_unprepare(clk->parent);
 }
 
@@ -901,6 +911,8 @@ static int clk_core_prepare(struct clk_core *clk)
 		if (ret)
 			return ret;
 
+		trace_clk_prepare(clk);
+
 		if (clk->ops->prepare) {
 			ret = clk->ops->prepare(clk->hw);
 			if (ret) {
@@ -908,6 +920,8 @@ static int clk_core_prepare(struct clk_core *clk)
 				return ret;
 			}
 		}
+
+		trace_clk_prepare_complete(clk);
 	}
 
 	clk->prepare_count++;
@@ -953,9 +967,13 @@ static void clk_core_disable(struct clk_core *clk)
 	if (--clk->enable_count > 0)
 		return;
 
+	trace_clk_disable(clk);
+
 	if (clk->ops->disable)
 		clk->ops->disable(clk->hw);
 
+	trace_clk_disable_complete(clk);
+
 	clk_core_disable(clk->parent);
 }
 
@@ -1008,6 +1026,7 @@ static int clk_core_enable(struct clk_core *clk)
 		if (ret)
 			return ret;
 
+		trace_clk_enable(clk);
 		if (clk->ops->enable) {
 			ret = clk->ops->enable(clk->hw);
 			if (ret) {
@@ -1015,6 +1034,7 @@ static int clk_core_enable(struct clk_core *clk)
 				return ret;
 			}
 		}
+		trace_clk_enable_complete(clk);
 	}
 
 	clk->enable_count++;
@@ -1383,6 +1403,8 @@ static struct clk_core *__clk_set_parent_before(struct clk_core *clk,
 	unsigned long flags;
 	struct clk_core *old_parent = clk->parent;
 
+	trace_clk_set_parent(clk, parent);
+
 	/*
 	 * Migrate prepare state between parents and prevent race with
 	 * clk_enable().
@@ -1427,6 +1449,8 @@ static void __clk_set_parent_after(struct clk_core *core,
 		clk_core_disable(old_parent);
 		clk_core_unprepare(old_parent);
 	}
+
+	trace_clk_set_parent_complete(core, parent);
 }
 
 static int __clk_set_parent(struct clk_core *clk, struct clk_core *parent,
@@ -1663,6 +1687,8 @@ static void clk_change_rate(struct clk_core *clk)
 	else if (clk->parent)
 		best_parent_rate = clk->parent->rate;
 
+	trace_clk_set_rate(clk, clk->new_rate);
+
 	if (clk->new_parent && clk->new_parent != clk->parent) {
 		old_parent = __clk_set_parent_before(clk, clk->new_parent);
 
@@ -1681,6 +1707,8 @@ static void clk_change_rate(struct clk_core *clk)
 	if (!skip_set_rate && clk->ops->set_rate)
 		clk->ops->set_rate(clk->hw, clk->new_rate, best_parent_rate);
 
+	trace_clk_set_rate_complete(clk, clk->new_rate);
+
 	clk->rate = clk_recalc(clk, best_parent_rate);
 
 	if (clk->notifier_count && old_rate != clk->rate)
@@ -2081,6 +2109,8 @@ int clk_set_phase(struct clk *clk, int degrees)
 
 	clk_prepare_lock();
 
+	trace_clk_set_phase(clk->core, degrees);
+
 	if (!clk->core->ops->set_phase)
 		goto out_unlock;
 
@@ -2090,6 +2120,8 @@ int clk_set_phase(struct clk *clk, int degrees)
 		clk->core->phase = degrees;
 
 out_unlock:
+	trace_clk_set_phase_complete(clk->core, degrees);
+
 	clk_prepare_unlock();
 
 out:
diff --git a/include/trace/events/clk.h b/include/trace/events/clk.h
new file mode 100644
index 000000000000..758607226bfd
--- /dev/null
+++ b/include/trace/events/clk.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM clk
+
+#if !defined(_TRACE_CLK_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_CLK_H
+
+#include <linux/tracepoint.h>
+
+struct clk_core;
+
+DECLARE_EVENT_CLASS(clk,
+
+	TP_PROTO(struct clk_core *core),
+
+	TP_ARGS(core),
+
+	TP_STRUCT__entry(
+		__string(        name,           core->name       )
+	),
+
+	TP_fast_assign(
+		__assign_str(name, core->name);
+	),
+
+	TP_printk("%s", __get_str(name))
+);
+
+DEFINE_EVENT(clk, clk_enable,
+
+	TP_PROTO(struct clk_core *core),
+
+	TP_ARGS(core)
+);
+
+DEFINE_EVENT(clk, clk_enable_complete,
+
+	TP_PROTO(struct clk_core *core),
+
+	TP_ARGS(core)
+);
+
+DEFINE_EVENT(clk, clk_disable,
+
+	TP_PROTO(struct clk_core *core),
+
+	TP_ARGS(core)
+);
+
+DEFINE_EVENT(clk, clk_disable_complete,
+
+	TP_PROTO(struct clk_core *core),
+
+	TP_ARGS(core)
+);
+
+DEFINE_EVENT(clk, clk_prepare,
+
+	TP_PROTO(struct clk_core *core),
+
+	TP_ARGS(core)
+);
+
+DEFINE_EVENT(clk, clk_prepare_complete,
+
+	TP_PROTO(struct clk_core *core),
+
+	TP_ARGS(core)
+);
+
+DEFINE_EVENT(clk, clk_unprepare,
+
+	TP_PROTO(struct clk_core *core),
+
+	TP_ARGS(core)
+);
+
+DEFINE_EVENT(clk, clk_unprepare_complete,
+
+	TP_PROTO(struct clk_core *core),
+
+	TP_ARGS(core)
+);
+
+DECLARE_EVENT_CLASS(clk_rate,
+
+	TP_PROTO(struct clk_core *core, unsigned long rate),
+
+	TP_ARGS(core, rate),
+
+	TP_STRUCT__entry(
+		__string(        name,           core->name                )
+		__field(unsigned long,           rate                      )
+	),
+
+	TP_fast_assign(
+		__assign_str(name, core->name);
+		__entry->rate = rate;
+	),
+
+	TP_printk("%s %lu", __get_str(name), (unsigned long)__entry->rate)
+);
+
+DEFINE_EVENT(clk_rate, clk_set_rate,
+
+	TP_PROTO(struct clk_core *core, unsigned long rate),
+
+	TP_ARGS(core, rate)
+);
+
+DEFINE_EVENT(clk_rate, clk_set_rate_complete,
+
+	TP_PROTO(struct clk_core *core, unsigned long rate),
+
+	TP_ARGS(core, rate)
+);
+
+DECLARE_EVENT_CLASS(clk_parent,
+
+	TP_PROTO(struct clk_core *core, struct clk_core *parent),
+
+	TP_ARGS(core, parent),
+
+	TP_STRUCT__entry(
+		__string(        name,           core->name                )
+		__string(        pname,          parent->name              )
+	),
+
+	TP_fast_assign(
+		__assign_str(name, core->name);
+		__assign_str(pname, parent->name);
+	),
+
+	TP_printk("%s %s", __get_str(name), __get_str(pname))
+);
+
+DEFINE_EVENT(clk_parent, clk_set_parent,
+
+	TP_PROTO(struct clk_core *core, struct clk_core *parent),
+
+	TP_ARGS(core, parent)
+);
+
+DEFINE_EVENT(clk_parent, clk_set_parent_complete,
+
+	TP_PROTO(struct clk_core *core, struct clk_core *parent),
+
+	TP_ARGS(core, parent)
+);
+
+DECLARE_EVENT_CLASS(clk_phase,
+
+	TP_PROTO(struct clk_core *core, int phase),
+
+	TP_ARGS(core, phase),
+
+	TP_STRUCT__entry(
+		__string(        name,           core->name                )
+		__field(	  int,           phase                     )
+	),
+
+	TP_fast_assign(
+		__assign_str(name, core->name);
+		__entry->phase = phase;
+	),
+
+	TP_printk("%s %d", __get_str(name), (int)__entry->phase)
+);
+
+DEFINE_EVENT(clk_phase, clk_set_phase,
+
+	TP_PROTO(struct clk_core *core, int phase),
+
+	TP_ARGS(core, phase)
+);
+
+DEFINE_EVENT(clk_phase, clk_set_phase_complete,
+
+	TP_PROTO(struct clk_core *core, int phase),
+
+	TP_ARGS(core, phase)
+);
+
+#endif /* _TRACE_CLK_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


             reply	other threads:[~2015-01-31  0:16 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-01-31  0:16 Stephen Boyd [this message]
2015-02-02 16:00 ` [PATCH] clk: Add tracepoints for hardware operations Steven Rostedt
2015-02-02 19:05   ` Mike Turquette
2015-02-02 19:41   ` Stephen Boyd
2015-02-02 20:00     ` Steven Rostedt
  -- strict thread matches above, loose matches on Subject: below --
2014-06-30 23:56 Stephen Boyd
2014-07-01  0:52 ` Steven Rostedt
2014-07-01  1:07   ` Stephen Boyd
2014-07-01  1:11     ` Steven Rostedt
2014-07-02  3:44     ` Mike Turquette

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1422663371-31056-1-git-send-email-sboyd@codeaurora.org \
    --to=sboyd@codeaurora.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mturquette@linaro.org \
    --cc=rostedt@goodmis.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox