aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Renninger <trenn@suse.de>2010-04-20 07:17:36 -0400
committerDave Jones <davej@redhat.com>2010-08-03 13:47:05 -0400
commit6f4f2723d08534fd4e407e1ef8500b0f4d12c30c (patch)
tree3422ba34e7c6bde7e8d4ca1f1f1ed772efc5cc4c
parent6b72e3934b42930fd40fc42fe762d21be413301c (diff)
[CPUFREQ] x86 cpufreq: Make trace_power_frequency cpufreq driver independent
and fix the broken case if a core's frequency depends on others. trace_power_frequency was only implemented in a rather ungeneric way in acpi-cpufreq driver's target() function only. -> Move the call to trace_power_frequency to cpufreq.c:cpufreq_notify_transition() where CPUFREQ_POSTCHANGE notifier is triggered. This will support power frequency tracing by all cpufreq drivers trace_power_frequency did not trace frequency changes correctly when the userspace governor was used or when CPU cores' frequency depend on each other. -> Moving this into the CPUFREQ_POSTCHANGE notifier and pass the cpu which gets switched automatically fixes this. Robert Schoene provided some important fixes on top of my initial quick shot version which are integrated in this patch: - Forgot some changes in power_end trace (TP_printk/variable names) - Variable dummy in power_end must now be cpu_id - Use static 64 bit variable instead of unsigned int for cpu_id Signed-off-by: Thomas Renninger <trenn@suse.de> CC: davej@redhat.com CC: arjan@infradead.org CC: linux-kernel@vger.kernel.org CC: robert.schoene@tu-dresden.de Tested-by: robert.schoene@tu-dresden.de Signed-off-by: Dave Jones <davej@redhat.com>
-rw-r--r--arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c3
-rw-r--r--arch/x86/kernel/process.c8
-rw-r--r--drivers/cpufreq/cpufreq.c5
-rw-r--r--drivers/cpuidle/cpuidle.c2
-rw-r--r--include/trace/events/power.h27
-rw-r--r--tools/perf/builtin-timechart.c11
6 files changed, 31 insertions, 25 deletions
diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
index cee7aa949c35..246cd3afbb5f 100644
--- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -34,7 +34,6 @@
34#include <linux/compiler.h> 34#include <linux/compiler.h>
35#include <linux/dmi.h> 35#include <linux/dmi.h>
36#include <linux/slab.h> 36#include <linux/slab.h>
37#include <trace/events/power.h>
38 37
39#include <linux/acpi.h> 38#include <linux/acpi.h>
40#include <linux/io.h> 39#include <linux/io.h>
@@ -324,8 +323,6 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
324 } 323 }
325 } 324 }
326 325
327 trace_power_frequency(POWER_PSTATE, data->freq_table[next_state].frequency);
328
329 switch (data->cpu_feature) { 326 switch (data->cpu_feature) {
330 case SYSTEM_INTEL_MSR_CAPABLE: 327 case SYSTEM_INTEL_MSR_CAPABLE:
331 cmd.type = SYSTEM_INTEL_MSR_CAPABLE; 328 cmd.type = SYSTEM_INTEL_MSR_CAPABLE;
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index e7e35219b32f..787572d43d9c 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -371,7 +371,7 @@ static inline int hlt_use_halt(void)
371void default_idle(void) 371void default_idle(void)
372{ 372{
373 if (hlt_use_halt()) { 373 if (hlt_use_halt()) {
374 trace_power_start(POWER_CSTATE, 1); 374 trace_power_start(POWER_CSTATE, 1, smp_processor_id());
375 current_thread_info()->status &= ~TS_POLLING; 375 current_thread_info()->status &= ~TS_POLLING;
376 /* 376 /*
377 * TS_POLLING-cleared state must be visible before we 377 * TS_POLLING-cleared state must be visible before we
@@ -441,7 +441,7 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait);
441 */ 441 */
442void mwait_idle_with_hints(unsigned long ax, unsigned long cx) 442void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
443{ 443{
444 trace_power_start(POWER_CSTATE, (ax>>4)+1); 444 trace_power_start(POWER_CSTATE, (ax>>4)+1, smp_processor_id());
445 if (!need_resched()) { 445 if (!need_resched()) {
446 if (cpu_has(&current_cpu_data, X86_FEATURE_CLFLUSH_MONITOR)) 446 if (cpu_has(&current_cpu_data, X86_FEATURE_CLFLUSH_MONITOR))
447 clflush((void *)&current_thread_info()->flags); 447 clflush((void *)&current_thread_info()->flags);
@@ -457,7 +457,7 @@ void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
457static void mwait_idle(void) 457static void mwait_idle(void)
458{ 458{
459 if (!need_resched()) { 459 if (!need_resched()) {
460 trace_power_start(POWER_CSTATE, 1); 460 trace_power_start(POWER_CSTATE, 1, smp_processor_id());
461 if (cpu_has(&current_cpu_data, X86_FEATURE_CLFLUSH_MONITOR)) 461 if (cpu_has(&current_cpu_data, X86_FEATURE_CLFLUSH_MONITOR))
462 clflush((void *)&current_thread_info()->flags); 462 clflush((void *)&current_thread_info()->flags);
463 463
@@ -478,7 +478,7 @@ static void mwait_idle(void)
478 */ 478 */
479static void poll_idle(void) 479static void poll_idle(void)
480{ 480{
481 trace_power_start(POWER_CSTATE, 0); 481 trace_power_start(POWER_CSTATE, 0, smp_processor_id());
482 local_irq_enable(); 482 local_irq_enable();
483 while (!need_resched()) 483 while (!need_resched())
484 cpu_relax(); 484 cpu_relax();
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 40877d219081..6ce1bb735635 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -29,6 +29,8 @@
29#include <linux/completion.h> 29#include <linux/completion.h>
30#include <linux/mutex.h> 30#include <linux/mutex.h>
31 31
32#include <trace/events/power.h>
33
32#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, \ 34#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, \
33 "cpufreq-core", msg) 35 "cpufreq-core", msg)
34 36
@@ -350,6 +352,9 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
350 352
351 case CPUFREQ_POSTCHANGE: 353 case CPUFREQ_POSTCHANGE:
352 adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); 354 adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
355 dprintk("FREQ: %lu - CPU: %lu", (unsigned long)freqs->new,
356 (unsigned long)freqs->cpu);
357 trace_power_frequency(POWER_PSTATE, freqs->new, freqs->cpu);
353 srcu_notifier_call_chain(&cpufreq_transition_notifier_list, 358 srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
354 CPUFREQ_POSTCHANGE, freqs); 359 CPUFREQ_POSTCHANGE, freqs);
355 if (likely(policy) && likely(policy->cpu == freqs->cpu)) 360 if (likely(policy) && likely(policy->cpu == freqs->cpu))
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 199488576a05..dbefe15bd582 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -95,7 +95,7 @@ static void cpuidle_idle_call(void)
95 /* give the governor an opportunity to reflect on the outcome */ 95 /* give the governor an opportunity to reflect on the outcome */
96 if (cpuidle_curr_governor->reflect) 96 if (cpuidle_curr_governor->reflect)
97 cpuidle_curr_governor->reflect(dev); 97 cpuidle_curr_governor->reflect(dev);
98 trace_power_end(0); 98 trace_power_end(smp_processor_id());
99} 99}
100 100
101/** 101/**
diff --git a/include/trace/events/power.h b/include/trace/events/power.h
index c4efe9b8280d..35a2a6e7bf1e 100644
--- a/include/trace/events/power.h
+++ b/include/trace/events/power.h
@@ -18,52 +18,55 @@ enum {
18 18
19DECLARE_EVENT_CLASS(power, 19DECLARE_EVENT_CLASS(power,
20 20
21 TP_PROTO(unsigned int type, unsigned int state), 21 TP_PROTO(unsigned int type, unsigned int state, unsigned int cpu_id),
22 22
23 TP_ARGS(type, state), 23 TP_ARGS(type, state, cpu_id),
24 24
25 TP_STRUCT__entry( 25 TP_STRUCT__entry(
26 __field( u64, type ) 26 __field( u64, type )
27 __field( u64, state ) 27 __field( u64, state )
28 __field( u64, cpu_id )
28 ), 29 ),
29 30
30 TP_fast_assign( 31 TP_fast_assign(
31 __entry->type = type; 32 __entry->type = type;
32 __entry->state = state; 33 __entry->state = state;
34 __entry->cpu_id = cpu_id;
33 ), 35 ),
34 36
35 TP_printk("type=%lu state=%lu", (unsigned long)__entry->type, (unsigned long)__entry->state) 37 TP_printk("type=%lu state=%lu cpu_id=%lu", (unsigned long)__entry->type,
38 (unsigned long)__entry->state, (unsigned long)__entry->cpu_id)
36); 39);
37 40
38DEFINE_EVENT(power, power_start, 41DEFINE_EVENT(power, power_start,
39 42
40 TP_PROTO(unsigned int type, unsigned int state), 43 TP_PROTO(unsigned int type, unsigned int state, unsigned int cpu_id),
41 44
42 TP_ARGS(type, state) 45 TP_ARGS(type, state, cpu_id)
43); 46);
44 47
45DEFINE_EVENT(power, power_frequency, 48DEFINE_EVENT(power, power_frequency,
46 49
47 TP_PROTO(unsigned int type, unsigned int state), 50 TP_PROTO(unsigned int type, unsigned int state, unsigned int cpu_id),
48 51
49 TP_ARGS(type, state) 52 TP_ARGS(type, state, cpu_id)
50); 53);
51 54
52TRACE_EVENT(power_end, 55TRACE_EVENT(power_end,
53 56
54 TP_PROTO(int dummy), 57 TP_PROTO(unsigned int cpu_id),
55 58
56 TP_ARGS(dummy), 59 TP_ARGS(cpu_id),
57 60
58 TP_STRUCT__entry( 61 TP_STRUCT__entry(
59 __field( u64, dummy ) 62 __field( u64, cpu_id )
60 ), 63 ),
61 64
62 TP_fast_assign( 65 TP_fast_assign(
63 __entry->dummy = 0xffff; 66 __entry->cpu_id = cpu_id;
64 ), 67 ),
65 68
66 TP_printk("dummy=%lu", (unsigned long)__entry->dummy) 69 TP_printk("cpu_id=%lu", (unsigned long)__entry->cpu_id)
67 70
68); 71);
69 72
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 5a52ed9fc10b..5161619d4714 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -300,8 +300,9 @@ struct trace_entry {
300 300
301struct power_entry { 301struct power_entry {
302 struct trace_entry te; 302 struct trace_entry te;
303 s64 type; 303 u64 type;
304 s64 value; 304 u64 value;
305 u64 cpu_id;
305}; 306};
306 307
307#define TASK_COMM_LEN 16 308#define TASK_COMM_LEN 16
@@ -498,13 +499,13 @@ static int process_sample_event(event_t *event, struct perf_session *session)
498 return 0; 499 return 0;
499 500
500 if (strcmp(event_str, "power:power_start") == 0) 501 if (strcmp(event_str, "power:power_start") == 0)
501 c_state_start(data.cpu, data.time, pe->value); 502 c_state_start(pe->cpu_id, data.time, pe->value);
502 503
503 if (strcmp(event_str, "power:power_end") == 0) 504 if (strcmp(event_str, "power:power_end") == 0)
504 c_state_end(data.cpu, data.time); 505 c_state_end(pe->cpu_id, data.time);
505 506
506 if (strcmp(event_str, "power:power_frequency") == 0) 507 if (strcmp(event_str, "power:power_frequency") == 0)
507 p_state_change(data.cpu, data.time, pe->value); 508 p_state_change(pe->cpu_id, data.time, pe->value);
508 509
509 if (strcmp(event_str, "sched:sched_wakeup") == 0) 510 if (strcmp(event_str, "sched:sched_wakeup") == 0)
510 sched_wakeup(data.cpu, data.time, data.pid, te); 511 sched_wakeup(data.cpu, data.time, data.pid, te);