diff options
author | Alexey Brodkin <alexey.brodkin@synopsys.com> | 2018-11-19 06:29:17 -0500 |
---|---|---|
committer | Daniel Lezcano <daniel.lezcano@linaro.org> | 2018-12-18 16:22:23 -0500 |
commit | bf287607c80f24387fedb431a346dc67f25be12c (patch) | |
tree | c2c0450742868addbf70642c01504c12e559048c /drivers/clocksource/arc_timer.c | |
parent | 2bbaf54216448486def1153486778a975a73041d (diff) |
clocksource/drivers/arc_timer: Utilize generic sched_clock
It turned out we used to use default implementation of sched_clock()
from kernel/sched/clock.c which was as precise as 1/HZ, i.e.
by default we had 10 msec granularity of time measurement.
Now given ARC built-in timers are clocked with the same frequency as
CPU cores we may get much higher precision of time tracking.
Thus we switch to generic sched_clock which really reads ARC hardware
counters.
This is especially helpful for measuring short events.
That's what we used to have:
------------------------------>8------------------------
$ perf stat /bin/sh -c /root/lmbench-master/bin/arc/hello > /dev/null
Performance counter stats for '/bin/sh -c /root/lmbench-master/bin/arc/hello':
10.000000 task-clock (msec) # 2.832 CPUs utilized
1 context-switches # 0.100 K/sec
1 cpu-migrations # 0.100 K/sec
63 page-faults # 0.006 M/sec
3049480 cycles # 0.305 GHz
1091259 instructions # 0.36 insn per cycle
256828 branches # 25.683 M/sec
27026 branch-misses # 10.52% of all branches
0.003530687 seconds time elapsed
0.000000000 seconds user
0.010000000 seconds sys
------------------------------>8------------------------
And now we'll see:
------------------------------>8------------------------
$ perf stat /bin/sh -c /root/lmbench-master/bin/arc/hello > /dev/null
Performance counter stats for '/bin/sh -c /root/lmbench-master/bin/arc/hello':
3.004322 task-clock (msec) # 0.865 CPUs utilized
1 context-switches # 0.333 K/sec
1 cpu-migrations # 0.333 K/sec
63 page-faults # 0.021 M/sec
2986734 cycles # 0.994 GHz
1087466 instructions # 0.36 insn per cycle
255209 branches # 84.947 M/sec
26002 branch-misses # 10.19% of all branches
0.003474829 seconds time elapsed
0.003519000 seconds user
0.000000000 seconds sys
------------------------------>8------------------------
Note how much more meaningful is the second output - time spent for
execution pretty much matches number of cycles spent (we're runnign
@ 1GHz here).
Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Vineet Gupta <vgupta@synopsys.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: stable@vger.kernel.org
Acked-by: Vineet Gupta <vgupta@synopsys.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Diffstat (limited to 'drivers/clocksource/arc_timer.c')
-rw-r--r-- | drivers/clocksource/arc_timer.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/drivers/clocksource/arc_timer.c b/drivers/clocksource/arc_timer.c index 20da9b1d7f7d..b28970ca4a7a 100644 --- a/drivers/clocksource/arc_timer.c +++ b/drivers/clocksource/arc_timer.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/cpu.h> | 23 | #include <linux/cpu.h> |
24 | #include <linux/of.h> | 24 | #include <linux/of.h> |
25 | #include <linux/of_irq.h> | 25 | #include <linux/of_irq.h> |
26 | #include <linux/sched_clock.h> | ||
26 | 27 | ||
27 | #include <soc/arc/timers.h> | 28 | #include <soc/arc/timers.h> |
28 | #include <soc/arc/mcip.h> | 29 | #include <soc/arc/mcip.h> |
@@ -88,6 +89,11 @@ static u64 arc_read_gfrc(struct clocksource *cs) | |||
88 | return (((u64)h) << 32) | l; | 89 | return (((u64)h) << 32) | l; |
89 | } | 90 | } |
90 | 91 | ||
92 | static notrace u64 arc_gfrc_clock_read(void) | ||
93 | { | ||
94 | return arc_read_gfrc(NULL); | ||
95 | } | ||
96 | |||
91 | static struct clocksource arc_counter_gfrc = { | 97 | static struct clocksource arc_counter_gfrc = { |
92 | .name = "ARConnect GFRC", | 98 | .name = "ARConnect GFRC", |
93 | .rating = 400, | 99 | .rating = 400, |
@@ -111,6 +117,8 @@ static int __init arc_cs_setup_gfrc(struct device_node *node) | |||
111 | if (ret) | 117 | if (ret) |
112 | return ret; | 118 | return ret; |
113 | 119 | ||
120 | sched_clock_register(arc_gfrc_clock_read, 64, arc_timer_freq); | ||
121 | |||
114 | return clocksource_register_hz(&arc_counter_gfrc, arc_timer_freq); | 122 | return clocksource_register_hz(&arc_counter_gfrc, arc_timer_freq); |
115 | } | 123 | } |
116 | TIMER_OF_DECLARE(arc_gfrc, "snps,archs-timer-gfrc", arc_cs_setup_gfrc); | 124 | TIMER_OF_DECLARE(arc_gfrc, "snps,archs-timer-gfrc", arc_cs_setup_gfrc); |
@@ -139,6 +147,11 @@ static u64 arc_read_rtc(struct clocksource *cs) | |||
139 | return (((u64)h) << 32) | l; | 147 | return (((u64)h) << 32) | l; |
140 | } | 148 | } |
141 | 149 | ||
150 | static notrace u64 arc_rtc_clock_read(void) | ||
151 | { | ||
152 | return arc_read_rtc(NULL); | ||
153 | } | ||
154 | |||
142 | static struct clocksource arc_counter_rtc = { | 155 | static struct clocksource arc_counter_rtc = { |
143 | .name = "ARCv2 RTC", | 156 | .name = "ARCv2 RTC", |
144 | .rating = 350, | 157 | .rating = 350, |
@@ -170,6 +183,8 @@ static int __init arc_cs_setup_rtc(struct device_node *node) | |||
170 | 183 | ||
171 | write_aux_reg(AUX_RTC_CTRL, 1); | 184 | write_aux_reg(AUX_RTC_CTRL, 1); |
172 | 185 | ||
186 | sched_clock_register(arc_rtc_clock_read, 64, arc_timer_freq); | ||
187 | |||
173 | return clocksource_register_hz(&arc_counter_rtc, arc_timer_freq); | 188 | return clocksource_register_hz(&arc_counter_rtc, arc_timer_freq); |
174 | } | 189 | } |
175 | TIMER_OF_DECLARE(arc_rtc, "snps,archs-timer-rtc", arc_cs_setup_rtc); | 190 | TIMER_OF_DECLARE(arc_rtc, "snps,archs-timer-rtc", arc_cs_setup_rtc); |
@@ -185,6 +200,11 @@ static u64 arc_read_timer1(struct clocksource *cs) | |||
185 | return (u64) read_aux_reg(ARC_REG_TIMER1_CNT); | 200 | return (u64) read_aux_reg(ARC_REG_TIMER1_CNT); |
186 | } | 201 | } |
187 | 202 | ||
203 | static notrace u64 arc_timer1_clock_read(void) | ||
204 | { | ||
205 | return arc_read_timer1(NULL); | ||
206 | } | ||
207 | |||
188 | static struct clocksource arc_counter_timer1 = { | 208 | static struct clocksource arc_counter_timer1 = { |
189 | .name = "ARC Timer1", | 209 | .name = "ARC Timer1", |
190 | .rating = 300, | 210 | .rating = 300, |
@@ -209,6 +229,8 @@ static int __init arc_cs_setup_timer1(struct device_node *node) | |||
209 | write_aux_reg(ARC_REG_TIMER1_CNT, 0); | 229 | write_aux_reg(ARC_REG_TIMER1_CNT, 0); |
210 | write_aux_reg(ARC_REG_TIMER1_CTRL, TIMER_CTRL_NH); | 230 | write_aux_reg(ARC_REG_TIMER1_CTRL, TIMER_CTRL_NH); |
211 | 231 | ||
232 | sched_clock_register(arc_timer1_clock_read, 32, arc_timer_freq); | ||
233 | |||
212 | return clocksource_register_hz(&arc_counter_timer1, arc_timer_freq); | 234 | return clocksource_register_hz(&arc_counter_timer1, arc_timer_freq); |
213 | } | 235 | } |
214 | 236 | ||