Skip to content

Commit

Permalink
[CPUFREQ] x86 cpufreq: Make trace_power_frequency cpufreq driver inde…
Browse files Browse the repository at this point in the history
…pendent

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>
  • Loading branch information
Thomas Renninger authored and Dave Jones committed Aug 3, 2010
1 parent 6b72e39 commit 6f4f272
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 25 deletions.
3 changes: 0 additions & 3 deletions arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
#include <linux/compiler.h>
#include <linux/dmi.h>
#include <linux/slab.h>
#include <trace/events/power.h>

#include <linux/acpi.h>
#include <linux/io.h>
Expand Down Expand Up @@ -324,8 +323,6 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
}
}

trace_power_frequency(POWER_PSTATE, data->freq_table[next_state].frequency);

switch (data->cpu_feature) {
case SYSTEM_INTEL_MSR_CAPABLE:
cmd.type = SYSTEM_INTEL_MSR_CAPABLE;
Expand Down
8 changes: 4 additions & 4 deletions arch/x86/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ static inline int hlt_use_halt(void)
void default_idle(void)
{
if (hlt_use_halt()) {
trace_power_start(POWER_CSTATE, 1);
trace_power_start(POWER_CSTATE, 1, smp_processor_id());
current_thread_info()->status &= ~TS_POLLING;
/*
* TS_POLLING-cleared state must be visible before we
Expand Down Expand Up @@ -441,7 +441,7 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait);
*/
void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
{
trace_power_start(POWER_CSTATE, (ax>>4)+1);
trace_power_start(POWER_CSTATE, (ax>>4)+1, smp_processor_id());
if (!need_resched()) {
if (cpu_has(&current_cpu_data, X86_FEATURE_CLFLUSH_MONITOR))
clflush((void *)&current_thread_info()->flags);
Expand All @@ -457,7 +457,7 @@ void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
static void mwait_idle(void)
{
if (!need_resched()) {
trace_power_start(POWER_CSTATE, 1);
trace_power_start(POWER_CSTATE, 1, smp_processor_id());
if (cpu_has(&current_cpu_data, X86_FEATURE_CLFLUSH_MONITOR))
clflush((void *)&current_thread_info()->flags);

Expand All @@ -478,7 +478,7 @@ static void mwait_idle(void)
*/
static void poll_idle(void)
{
trace_power_start(POWER_CSTATE, 0);
trace_power_start(POWER_CSTATE, 0, smp_processor_id());
local_irq_enable();
while (!need_resched())
cpu_relax();
Expand Down
5 changes: 5 additions & 0 deletions drivers/cpufreq/cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#include <linux/completion.h>
#include <linux/mutex.h>

#include <trace/events/power.h>

#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, \
"cpufreq-core", msg)

Expand Down Expand Up @@ -350,6 +352,9 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)

case CPUFREQ_POSTCHANGE:
adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
dprintk("FREQ: %lu - CPU: %lu", (unsigned long)freqs->new,
(unsigned long)freqs->cpu);
trace_power_frequency(POWER_PSTATE, freqs->new, freqs->cpu);
srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
CPUFREQ_POSTCHANGE, freqs);
if (likely(policy) && likely(policy->cpu == freqs->cpu))
Expand Down
2 changes: 1 addition & 1 deletion drivers/cpuidle/cpuidle.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ static void cpuidle_idle_call(void)
/* give the governor an opportunity to reflect on the outcome */
if (cpuidle_curr_governor->reflect)
cpuidle_curr_governor->reflect(dev);
trace_power_end(0);
trace_power_end(smp_processor_id());
}

/**
Expand Down
27 changes: 15 additions & 12 deletions include/trace/events/power.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,52 +18,55 @@ enum {

DECLARE_EVENT_CLASS(power,

TP_PROTO(unsigned int type, unsigned int state),
TP_PROTO(unsigned int type, unsigned int state, unsigned int cpu_id),

TP_ARGS(type, state),
TP_ARGS(type, state, cpu_id),

TP_STRUCT__entry(
__field( u64, type )
__field( u64, state )
__field( u64, cpu_id )
),

TP_fast_assign(
__entry->type = type;
__entry->state = state;
__entry->cpu_id = cpu_id;
),

TP_printk("type=%lu state=%lu", (unsigned long)__entry->type, (unsigned long)__entry->state)
TP_printk("type=%lu state=%lu cpu_id=%lu", (unsigned long)__entry->type,
(unsigned long)__entry->state, (unsigned long)__entry->cpu_id)
);

DEFINE_EVENT(power, power_start,

TP_PROTO(unsigned int type, unsigned int state),
TP_PROTO(unsigned int type, unsigned int state, unsigned int cpu_id),

TP_ARGS(type, state)
TP_ARGS(type, state, cpu_id)
);

DEFINE_EVENT(power, power_frequency,

TP_PROTO(unsigned int type, unsigned int state),
TP_PROTO(unsigned int type, unsigned int state, unsigned int cpu_id),

TP_ARGS(type, state)
TP_ARGS(type, state, cpu_id)
);

TRACE_EVENT(power_end,

TP_PROTO(int dummy),
TP_PROTO(unsigned int cpu_id),

TP_ARGS(dummy),
TP_ARGS(cpu_id),

TP_STRUCT__entry(
__field( u64, dummy )
__field( u64, cpu_id )
),

TP_fast_assign(
__entry->dummy = 0xffff;
__entry->cpu_id = cpu_id;
),

TP_printk("dummy=%lu", (unsigned long)__entry->dummy)
TP_printk("cpu_id=%lu", (unsigned long)__entry->cpu_id)

);

Expand Down
11 changes: 6 additions & 5 deletions tools/perf/builtin-timechart.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,8 +300,9 @@ struct trace_entry {

struct power_entry {
struct trace_entry te;
s64 type;
s64 value;
u64 type;
u64 value;
u64 cpu_id;
};

#define TASK_COMM_LEN 16
Expand Down Expand Up @@ -498,13 +499,13 @@ static int process_sample_event(event_t *event, struct perf_session *session)
return 0;

if (strcmp(event_str, "power:power_start") == 0)
c_state_start(data.cpu, data.time, pe->value);
c_state_start(pe->cpu_id, data.time, pe->value);

if (strcmp(event_str, "power:power_end") == 0)
c_state_end(data.cpu, data.time);
c_state_end(pe->cpu_id, data.time);

if (strcmp(event_str, "power:power_frequency") == 0)
p_state_change(data.cpu, data.time, pe->value);
p_state_change(pe->cpu_id, data.time, pe->value);

if (strcmp(event_str, "sched:sched_wakeup") == 0)
sched_wakeup(data.cpu, data.time, data.pid, te);
Expand Down

0 comments on commit 6f4f272

Please sign in to comment.