Commit 25e41933 authored by Thomas Renninger's avatar Thomas Renninger Committed by Ingo Molnar

perf: Clean up power events by introducing new, more generic ones

Add these new power trace events:

 power:cpu_idle
 power:cpu_frequency
 power:machine_suspend

The old C-state/idle accounting events:
  power:power_start
  power:power_end

Have now a replacement (but we are still keeping the old
tracepoints for compatibility):

  power:cpu_idle

and
  power:power_frequency

is replaced with:
  power:cpu_frequency

power:machine_suspend is newly introduced.

Jean Pihet has a patch integrated into the generic layer
(kernel/power/suspend.c) which will make use of it.

the type= field got removed from both, it was never
used and the type is differed by the event type itself.

perf timechart userspace tool gets adjusted in a separate patch.
Signed-off-by: default avatarThomas Renninger <trenn@suse.de>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Acked-by: default avatarArjan van de Ven <arjan@linux.intel.com>
Acked-by: default avatarJean Pihet <jean.pihet@newoldbits.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: rjw@sisk.pl
LKML-Reference: <1294073445-14812-3-git-send-email-trenn@suse.de>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
LKML-Reference: <1290072314-31155-2-git-send-email-trenn@suse.de>
parent 61a0d49c
...@@ -373,6 +373,7 @@ void default_idle(void) ...@@ -373,6 +373,7 @@ void default_idle(void)
{ {
if (hlt_use_halt()) { if (hlt_use_halt()) {
trace_power_start(POWER_CSTATE, 1, smp_processor_id()); trace_power_start(POWER_CSTATE, 1, smp_processor_id());
trace_cpu_idle(1, smp_processor_id());
current_thread_info()->status &= ~TS_POLLING; current_thread_info()->status &= ~TS_POLLING;
/* /*
* TS_POLLING-cleared state must be visible before we * TS_POLLING-cleared state must be visible before we
...@@ -443,6 +444,7 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait); ...@@ -443,6 +444,7 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait);
void mwait_idle_with_hints(unsigned long ax, unsigned long cx) void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
{ {
trace_power_start(POWER_CSTATE, (ax>>4)+1, smp_processor_id()); trace_power_start(POWER_CSTATE, (ax>>4)+1, smp_processor_id());
trace_cpu_idle((ax>>4)+1, smp_processor_id());
if (!need_resched()) { if (!need_resched()) {
if (cpu_has(&current_cpu_data, X86_FEATURE_CLFLUSH_MONITOR)) if (cpu_has(&current_cpu_data, X86_FEATURE_CLFLUSH_MONITOR))
clflush((void *)&current_thread_info()->flags); clflush((void *)&current_thread_info()->flags);
...@@ -459,6 +461,7 @@ static void mwait_idle(void) ...@@ -459,6 +461,7 @@ static void mwait_idle(void)
{ {
if (!need_resched()) { if (!need_resched()) {
trace_power_start(POWER_CSTATE, 1, smp_processor_id()); trace_power_start(POWER_CSTATE, 1, smp_processor_id());
trace_cpu_idle(1, smp_processor_id());
if (cpu_has(&current_cpu_data, X86_FEATURE_CLFLUSH_MONITOR)) if (cpu_has(&current_cpu_data, X86_FEATURE_CLFLUSH_MONITOR))
clflush((void *)&current_thread_info()->flags); clflush((void *)&current_thread_info()->flags);
...@@ -480,10 +483,12 @@ static void mwait_idle(void) ...@@ -480,10 +483,12 @@ static void mwait_idle(void)
static void poll_idle(void) static void poll_idle(void)
{ {
trace_power_start(POWER_CSTATE, 0, smp_processor_id()); trace_power_start(POWER_CSTATE, 0, smp_processor_id());
trace_cpu_idle(0, smp_processor_id());
local_irq_enable(); local_irq_enable();
while (!need_resched()) while (!need_resched())
cpu_relax(); cpu_relax();
trace_power_end(0); trace_power_end(smp_processor_id());
trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
} }
/* /*
......
...@@ -113,8 +113,8 @@ void cpu_idle(void) ...@@ -113,8 +113,8 @@ void cpu_idle(void)
stop_critical_timings(); stop_critical_timings();
pm_idle(); pm_idle();
start_critical_timings(); start_critical_timings();
trace_power_end(smp_processor_id()); trace_power_end(smp_processor_id());
trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
} }
tick_nohz_restart_sched_tick(); tick_nohz_restart_sched_tick();
preempt_enable_no_resched(); preempt_enable_no_resched();
......
...@@ -142,6 +142,8 @@ void cpu_idle(void) ...@@ -142,6 +142,8 @@ void cpu_idle(void)
start_critical_timings(); start_critical_timings();
trace_power_end(smp_processor_id()); trace_power_end(smp_processor_id());
trace_cpu_idle(PWR_EVENT_EXIT,
smp_processor_id());
/* In many cases the interrupt that ended idle /* In many cases the interrupt that ended idle
has already called exit_idle. But some idle has already called exit_idle. But some idle
......
...@@ -355,6 +355,7 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) ...@@ -355,6 +355,7 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
dprintk("FREQ: %lu - CPU: %lu", (unsigned long)freqs->new, dprintk("FREQ: %lu - CPU: %lu", (unsigned long)freqs->new,
(unsigned long)freqs->cpu); (unsigned long)freqs->cpu);
trace_power_frequency(POWER_PSTATE, freqs->new, freqs->cpu); trace_power_frequency(POWER_PSTATE, freqs->new, freqs->cpu);
trace_cpu_frequency(freqs->new, freqs->cpu);
srcu_notifier_call_chain(&cpufreq_transition_notifier_list, srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
CPUFREQ_POSTCHANGE, freqs); CPUFREQ_POSTCHANGE, freqs);
if (likely(policy) && likely(policy->cpu == freqs->cpu)) if (likely(policy) && likely(policy->cpu == freqs->cpu))
......
...@@ -107,6 +107,7 @@ static void cpuidle_idle_call(void) ...@@ -107,6 +107,7 @@ static void cpuidle_idle_call(void)
if (cpuidle_curr_governor->reflect) if (cpuidle_curr_governor->reflect)
cpuidle_curr_governor->reflect(dev); cpuidle_curr_governor->reflect(dev);
trace_power_end(smp_processor_id()); trace_power_end(smp_processor_id());
trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
} }
/** /**
......
...@@ -221,6 +221,7 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state) ...@@ -221,6 +221,7 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state)
stop_critical_timings(); stop_critical_timings();
trace_power_start(POWER_CSTATE, (eax >> 4) + 1, cpu); trace_power_start(POWER_CSTATE, (eax >> 4) + 1, cpu);
trace_cpu_idle((eax >> 4) + 1, cpu);
if (!need_resched()) { if (!need_resched()) {
__monitor((void *)&current_thread_info()->flags, 0, 0); __monitor((void *)&current_thread_info()->flags, 0, 0);
......
...@@ -7,16 +7,67 @@ ...@@ -7,16 +7,67 @@
#include <linux/ktime.h> #include <linux/ktime.h>
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#ifndef _TRACE_POWER_ENUM_ DECLARE_EVENT_CLASS(cpu,
#define _TRACE_POWER_ENUM_
enum { TP_PROTO(unsigned int state, unsigned int cpu_id),
POWER_NONE = 0,
POWER_CSTATE = 1, /* C-State */ TP_ARGS(state, cpu_id),
POWER_PSTATE = 2, /* Fequency change or DVFS */
POWER_SSTATE = 3, /* Suspend */ TP_STRUCT__entry(
}; __field( u32, state )
__field( u32, cpu_id )
),
TP_fast_assign(
__entry->state = state;
__entry->cpu_id = cpu_id;
),
TP_printk("state=%lu cpu_id=%lu", (unsigned long)__entry->state,
(unsigned long)__entry->cpu_id)
);
DEFINE_EVENT(cpu, cpu_idle,
TP_PROTO(unsigned int state, unsigned int cpu_id),
TP_ARGS(state, cpu_id)
);
/* This file can get included multiple times, TRACE_HEADER_MULTI_READ at top */
#ifndef _PWR_EVENT_AVOID_DOUBLE_DEFINING
#define _PWR_EVENT_AVOID_DOUBLE_DEFINING
#define PWR_EVENT_EXIT -1
#endif #endif
DEFINE_EVENT(cpu, cpu_frequency,
TP_PROTO(unsigned int frequency, unsigned int cpu_id),
TP_ARGS(frequency, cpu_id)
);
TRACE_EVENT(machine_suspend,
TP_PROTO(unsigned int state),
TP_ARGS(state),
TP_STRUCT__entry(
__field( u32, state )
),
TP_fast_assign(
__entry->state = state;
),
TP_printk("state=%lu", (unsigned long)__entry->state)
);
/* This code will be removed after deprecation time exceeded (2.6.41) */
#ifdef CONFIG_EVENT_POWER_TRACING_DEPRECATED
/* /*
* The power events are used for cpuidle & suspend (power_start, power_end) * The power events are used for cpuidle & suspend (power_start, power_end)
* and for cpufreq (power_frequency) * and for cpufreq (power_frequency)
...@@ -75,6 +126,36 @@ TRACE_EVENT(power_end, ...@@ -75,6 +126,36 @@ TRACE_EVENT(power_end,
); );
/* Deprecated dummy functions must be protected against multi-declartion */
#ifndef _PWR_EVENT_AVOID_DOUBLE_DEFINING_DEPRECATED
#define _PWR_EVENT_AVOID_DOUBLE_DEFINING_DEPRECATED
enum {
POWER_NONE = 0,
POWER_CSTATE = 1,
POWER_PSTATE = 2,
};
#endif /* _PWR_EVENT_AVOID_DOUBLE_DEFINING_DEPRECATED */
#else /* CONFIG_EVENT_POWER_TRACING_DEPRECATED */
#ifndef _PWR_EVENT_AVOID_DOUBLE_DEFINING_DEPRECATED
#define _PWR_EVENT_AVOID_DOUBLE_DEFINING_DEPRECATED
enum {
POWER_NONE = 0,
POWER_CSTATE = 1,
POWER_PSTATE = 2,
};
/* These dummy declaration have to be ripped out when the deprecated
events get removed */
static inline void trace_power_start(u64 type, u64 state, u64 cpuid) {};
static inline void trace_power_end(u64 cpuid) {};
static inline void trace_power_frequency(u64 type, u64 state, u64 cpuid) {};
#endif /* _PWR_EVENT_AVOID_DOUBLE_DEFINING_DEPRECATED */
#endif /* CONFIG_EVENT_POWER_TRACING_DEPRECATED */
/* /*
* The clock events are used for clock enable/disable and for * The clock events are used for clock enable/disable and for
* clock rate change * clock rate change
...@@ -153,7 +234,6 @@ DEFINE_EVENT(power_domain, power_domain_target, ...@@ -153,7 +234,6 @@ DEFINE_EVENT(power_domain, power_domain_target,
TP_ARGS(name, state, cpu_id) TP_ARGS(name, state, cpu_id)
); );
#endif /* _TRACE_POWER_H */ #endif /* _TRACE_POWER_H */
/* This part must be outside protection */ /* This part must be outside protection */
......
...@@ -69,6 +69,21 @@ config EVENT_TRACING ...@@ -69,6 +69,21 @@ config EVENT_TRACING
select CONTEXT_SWITCH_TRACER select CONTEXT_SWITCH_TRACER
bool bool
config EVENT_POWER_TRACING_DEPRECATED
depends on EVENT_TRACING
bool "Deprecated power event trace API, to be removed"
default y
help
Provides old power event types:
C-state/idle accounting events:
power:power_start
power:power_end
and old cpufreq accounting event:
power:power_frequency
This is for userspace compatibility
and will vanish after 5 kernel iterations,
namely 2.6.41.
config CONTEXT_SWITCH_TRACER config CONTEXT_SWITCH_TRACER
bool bool
......
...@@ -13,5 +13,8 @@ ...@@ -13,5 +13,8 @@
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
#include <trace/events/power.h> #include <trace/events/power.h>
#ifdef EVENT_POWER_TRACING_DEPRECATED
EXPORT_TRACEPOINT_SYMBOL_GPL(power_start); EXPORT_TRACEPOINT_SYMBOL_GPL(power_start);
#endif
EXPORT_TRACEPOINT_SYMBOL_GPL(cpu_idle);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment