aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Boyd <sboyd@codeaurora.org>2015-02-02 17:37:41 -0500
committerStephen Boyd <sboyd@codeaurora.org>2015-03-12 15:18:51 -0400
commitdfc202ead3123988793ac1160849676000b77ee4 (patch)
tree3720e97d6434c3f32480aa7753a7ba39e103b6ba
parent08b9575660cd6d654c05314fc41d2209f2d8bdfb (diff)
clk: Add tracepoints for hardware operations
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> Signed-off-by: Michael Turquette <mturquette@linaro.org>
-rw-r--r--drivers/clk/clk.c56
-rw-r--r--include/trace/events/clk.h198
2 files changed, 244 insertions, 10 deletions
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 0b3f39c03785..42064cec2364 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -77,6 +77,9 @@ struct clk_core {
77 struct kref ref; 77 struct kref ref;
78}; 78};
79 79
80#define CREATE_TRACE_POINTS
81#include <trace/events/clk.h>
82
80struct clk { 83struct clk {
81 struct clk_core *core; 84 struct clk_core *core;
82 const char *dev_id; 85 const char *dev_id;
@@ -492,10 +495,12 @@ static void clk_unprepare_unused_subtree(struct clk_core *clk)
492 return; 495 return;
493 496
494 if (clk_core_is_prepared(clk)) { 497 if (clk_core_is_prepared(clk)) {
498 trace_clk_unprepare(clk);
495 if (clk->ops->unprepare_unused) 499 if (clk->ops->unprepare_unused)
496 clk->ops->unprepare_unused(clk->hw); 500 clk->ops->unprepare_unused(clk->hw);
497 else if (clk->ops->unprepare) 501 else if (clk->ops->unprepare)
498 clk->ops->unprepare(clk->hw); 502 clk->ops->unprepare(clk->hw);
503 trace_clk_unprepare_complete(clk);
499 } 504 }
500} 505}
501 506
@@ -524,10 +529,12 @@ static void clk_disable_unused_subtree(struct clk_core *clk)
524 * back to .disable 529 * back to .disable
525 */ 530 */
526 if (clk_core_is_enabled(clk)) { 531 if (clk_core_is_enabled(clk)) {
532 trace_clk_disable(clk);
527 if (clk->ops->disable_unused) 533 if (clk->ops->disable_unused)
528 clk->ops->disable_unused(clk->hw); 534 clk->ops->disable_unused(clk->hw);
529 else if (clk->ops->disable) 535 else if (clk->ops->disable)
530 clk->ops->disable(clk->hw); 536 clk->ops->disable(clk->hw);
537 trace_clk_disable_complete(clk);
531 } 538 }
532 539
533unlock_out: 540unlock_out:
@@ -907,9 +914,12 @@ static void clk_core_unprepare(struct clk_core *clk)
907 914
908 WARN_ON(clk->enable_count > 0); 915 WARN_ON(clk->enable_count > 0);
909 916
917 trace_clk_unprepare(clk);
918
910 if (clk->ops->unprepare) 919 if (clk->ops->unprepare)
911 clk->ops->unprepare(clk->hw); 920 clk->ops->unprepare(clk->hw);
912 921
922 trace_clk_unprepare_complete(clk);
913 clk_core_unprepare(clk->parent); 923 clk_core_unprepare(clk->parent);
914} 924}
915 925
@@ -947,12 +957,16 @@ static int clk_core_prepare(struct clk_core *clk)
947 if (ret) 957 if (ret)
948 return ret; 958 return ret;
949 959
950 if (clk->ops->prepare) { 960 trace_clk_prepare(clk);
961
962 if (clk->ops->prepare)
951 ret = clk->ops->prepare(clk->hw); 963 ret = clk->ops->prepare(clk->hw);
952 if (ret) { 964
953 clk_core_unprepare(clk->parent); 965 trace_clk_prepare_complete(clk);
954 return ret; 966
955 } 967 if (ret) {
968 clk_core_unprepare(clk->parent);
969 return ret;
956 } 970 }
957 } 971 }
958 972
@@ -999,9 +1013,13 @@ static void clk_core_disable(struct clk_core *clk)
999 if (--clk->enable_count > 0) 1013 if (--clk->enable_count > 0)
1000 return; 1014 return;
1001 1015
1016 trace_clk_disable(clk);
1017
1002 if (clk->ops->disable) 1018 if (clk->ops->disable)
1003 clk->ops->disable(clk->hw); 1019 clk->ops->disable(clk->hw);
1004 1020
1021 trace_clk_disable_complete(clk);
1022
1005 clk_core_disable(clk->parent); 1023 clk_core_disable(clk->parent);
1006} 1024}
1007 1025
@@ -1054,12 +1072,16 @@ static int clk_core_enable(struct clk_core *clk)
1054 if (ret) 1072 if (ret)
1055 return ret; 1073 return ret;
1056 1074
1057 if (clk->ops->enable) { 1075 trace_clk_enable(clk);
1076
1077 if (clk->ops->enable)
1058 ret = clk->ops->enable(clk->hw); 1078 ret = clk->ops->enable(clk->hw);
1059 if (ret) { 1079
1060 clk_core_disable(clk->parent); 1080 trace_clk_enable_complete(clk);
1061 return ret; 1081
1062 } 1082 if (ret) {
1083 clk_core_disable(clk->parent);
1084 return ret;
1063 } 1085 }
1064 } 1086 }
1065 1087
@@ -1490,10 +1512,14 @@ static int __clk_set_parent(struct clk_core *clk, struct clk_core *parent,
1490 1512
1491 old_parent = __clk_set_parent_before(clk, parent); 1513 old_parent = __clk_set_parent_before(clk, parent);
1492 1514
1515 trace_clk_set_parent(clk, parent);
1516
1493 /* change clock input source */ 1517 /* change clock input source */
1494 if (parent && clk->ops->set_parent) 1518 if (parent && clk->ops->set_parent)
1495 ret = clk->ops->set_parent(clk->hw, p_index); 1519 ret = clk->ops->set_parent(clk->hw, p_index);
1496 1520
1521 trace_clk_set_parent_complete(clk, parent);
1522
1497 if (ret) { 1523 if (ret) {
1498 flags = clk_enable_lock(); 1524 flags = clk_enable_lock();
1499 clk_reparent(clk, old_parent); 1525 clk_reparent(clk, old_parent);
@@ -1719,6 +1745,7 @@ static void clk_change_rate(struct clk_core *clk)
1719 1745
1720 if (clk->new_parent && clk->new_parent != clk->parent) { 1746 if (clk->new_parent && clk->new_parent != clk->parent) {
1721 old_parent = __clk_set_parent_before(clk, clk->new_parent); 1747 old_parent = __clk_set_parent_before(clk, clk->new_parent);
1748 trace_clk_set_parent(clk, clk->new_parent);
1722 1749
1723 if (clk->ops->set_rate_and_parent) { 1750 if (clk->ops->set_rate_and_parent) {
1724 skip_set_rate = true; 1751 skip_set_rate = true;
@@ -1729,12 +1756,17 @@ static void clk_change_rate(struct clk_core *clk)
1729 clk->ops->set_parent(clk->hw, clk->new_parent_index); 1756 clk->ops->set_parent(clk->hw, clk->new_parent_index);
1730 } 1757 }
1731 1758
1759 trace_clk_set_parent_complete(clk, clk->new_parent);
1732 __clk_set_parent_after(clk, clk->new_parent, old_parent); 1760 __clk_set_parent_after(clk, clk->new_parent, old_parent);
1733 } 1761 }
1734 1762
1763 trace_clk_set_rate(clk, clk->new_rate);
1764
1735 if (!skip_set_rate && clk->ops->set_rate) 1765 if (!skip_set_rate && clk->ops->set_rate)
1736 clk->ops->set_rate(clk->hw, clk->new_rate, best_parent_rate); 1766 clk->ops->set_rate(clk->hw, clk->new_rate, best_parent_rate);
1737 1767
1768 trace_clk_set_rate_complete(clk, clk->new_rate);
1769
1738 clk->rate = clk_recalc(clk, best_parent_rate); 1770 clk->rate = clk_recalc(clk, best_parent_rate);
1739 1771
1740 if (clk->notifier_count && old_rate != clk->rate) 1772 if (clk->notifier_count && old_rate != clk->rate)
@@ -2135,9 +2167,13 @@ int clk_set_phase(struct clk *clk, int degrees)
2135 2167
2136 clk_prepare_lock(); 2168 clk_prepare_lock();
2137 2169
2170 trace_clk_set_phase(clk->core, degrees);
2171
2138 if (clk->core->ops->set_phase) 2172 if (clk->core->ops->set_phase)
2139 ret = clk->core->ops->set_phase(clk->core->hw, degrees); 2173 ret = clk->core->ops->set_phase(clk->core->hw, degrees);
2140 2174
2175 trace_clk_set_phase_complete(clk->core, degrees);
2176
2141 if (!ret) 2177 if (!ret)
2142 clk->core->phase = degrees; 2178 clk->core->phase = degrees;
2143 2179
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 @@
1/*
2 * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
3 *
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13#undef TRACE_SYSTEM
14#define TRACE_SYSTEM clk
15
16#if !defined(_TRACE_CLK_H) || defined(TRACE_HEADER_MULTI_READ)
17#define _TRACE_CLK_H
18
19#include <linux/tracepoint.h>
20
21struct clk_core;
22
23DECLARE_EVENT_CLASS(clk,
24
25 TP_PROTO(struct clk_core *core),
26
27 TP_ARGS(core),
28
29 TP_STRUCT__entry(
30 __string( name, core->name )
31 ),
32
33 TP_fast_assign(
34 __assign_str(name, core->name);
35 ),
36
37 TP_printk("%s", __get_str(name))
38);
39
40DEFINE_EVENT(clk, clk_enable,
41
42 TP_PROTO(struct clk_core *core),
43
44 TP_ARGS(core)
45);
46
47DEFINE_EVENT(clk, clk_enable_complete,
48
49 TP_PROTO(struct clk_core *core),
50
51 TP_ARGS(core)
52);
53
54DEFINE_EVENT(clk, clk_disable,
55
56 TP_PROTO(struct clk_core *core),
57
58 TP_ARGS(core)
59);
60
61DEFINE_EVENT(clk, clk_disable_complete,
62
63 TP_PROTO(struct clk_core *core),
64
65 TP_ARGS(core)
66);
67
68DEFINE_EVENT(clk, clk_prepare,
69
70 TP_PROTO(struct clk_core *core),
71
72 TP_ARGS(core)
73);
74
75DEFINE_EVENT(clk, clk_prepare_complete,
76
77 TP_PROTO(struct clk_core *core),
78
79 TP_ARGS(core)
80);
81
82DEFINE_EVENT(clk, clk_unprepare,
83
84 TP_PROTO(struct clk_core *core),
85
86 TP_ARGS(core)
87);
88
89DEFINE_EVENT(clk, clk_unprepare_complete,
90
91 TP_PROTO(struct clk_core *core),
92
93 TP_ARGS(core)
94);
95
96DECLARE_EVENT_CLASS(clk_rate,
97
98 TP_PROTO(struct clk_core *core, unsigned long rate),
99
100 TP_ARGS(core, rate),
101
102 TP_STRUCT__entry(
103 __string( name, core->name )
104 __field(unsigned long, rate )
105 ),
106
107 TP_fast_assign(
108 __assign_str(name, core->name);
109 __entry->rate = rate;
110 ),
111
112 TP_printk("%s %lu", __get_str(name), (unsigned long)__entry->rate)
113);
114
115DEFINE_EVENT(clk_rate, clk_set_rate,
116
117 TP_PROTO(struct clk_core *core, unsigned long rate),
118
119 TP_ARGS(core, rate)
120);
121
122DEFINE_EVENT(clk_rate, clk_set_rate_complete,
123
124 TP_PROTO(struct clk_core *core, unsigned long rate),
125
126 TP_ARGS(core, rate)
127);
128
129DECLARE_EVENT_CLASS(clk_parent,
130
131 TP_PROTO(struct clk_core *core, struct clk_core *parent),
132
133 TP_ARGS(core, parent),
134
135 TP_STRUCT__entry(
136 __string( name, core->name )
137 __string( pname, parent->name )
138 ),
139
140 TP_fast_assign(
141 __assign_str(name, core->name);
142 __assign_str(pname, parent->name);
143 ),
144
145 TP_printk("%s %s", __get_str(name), __get_str(pname))
146);
147
148DEFINE_EVENT(clk_parent, clk_set_parent,
149
150 TP_PROTO(struct clk_core *core, struct clk_core *parent),
151
152 TP_ARGS(core, parent)
153);
154
155DEFINE_EVENT(clk_parent, clk_set_parent_complete,
156
157 TP_PROTO(struct clk_core *core, struct clk_core *parent),
158
159 TP_ARGS(core, parent)
160);
161
162DECLARE_EVENT_CLASS(clk_phase,
163
164 TP_PROTO(struct clk_core *core, int phase),
165
166 TP_ARGS(core, phase),
167
168 TP_STRUCT__entry(
169 __string( name, core->name )
170 __field( int, phase )
171 ),
172
173 TP_fast_assign(
174 __assign_str(name, core->name);
175 __entry->phase = phase;
176 ),
177
178 TP_printk("%s %d", __get_str(name), (int)__entry->phase)
179);
180
181DEFINE_EVENT(clk_phase, clk_set_phase,
182
183 TP_PROTO(struct clk_core *core, int phase),
184
185 TP_ARGS(core, phase)
186);
187
188DEFINE_EVENT(clk_phase, clk_set_phase_complete,
189
190 TP_PROTO(struct clk_core *core, int phase),
191
192 TP_ARGS(core, phase)
193);
194
195#endif /* _TRACE_CLK_H */
196
197/* This part must be outside protection */
198#include <trace/define_trace.h>