intel_pstate: Add trace point to report internal state.

Add perf trace event "power:pstate_sample" to report driver state to
aid in diagnosing issues reported against intel_pstate.

Signed-off-by: Dirk Brandewie <dirk.j.brandewie@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
Dirk Brandewie 2014-01-16 10:32:25 -08:00 committed by Rafael J. Wysocki
parent 652ed95d5f
commit b69880f9cc
2 changed files with 77 additions and 0 deletions

View file

@ -51,6 +51,8 @@ static inline int32_t div_fp(int32_t x, int32_t y)
return div_s64((int64_t)x << FRAC_BITS, (int64_t)y); return div_s64((int64_t)x << FRAC_BITS, (int64_t)y);
} }
static u64 energy_divisor;
struct sample { struct sample {
int32_t core_pct_busy; int32_t core_pct_busy;
u64 aperf; u64 aperf;
@ -559,6 +561,7 @@ static inline void intel_pstate_sample(struct cpudata *cpu)
rdmsrl(MSR_IA32_APERF, aperf); rdmsrl(MSR_IA32_APERF, aperf);
rdmsrl(MSR_IA32_MPERF, mperf); rdmsrl(MSR_IA32_MPERF, mperf);
cpu->sample_ptr = (cpu->sample_ptr + 1) % SAMPLE_COUNT; cpu->sample_ptr = (cpu->sample_ptr + 1) % SAMPLE_COUNT;
cpu->samples[cpu->sample_ptr].aperf = aperf; cpu->samples[cpu->sample_ptr].aperf = aperf;
cpu->samples[cpu->sample_ptr].mperf = mperf; cpu->samples[cpu->sample_ptr].mperf = mperf;
@ -603,6 +606,7 @@ static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu)
ctl = pid_calc(pid, busy_scaled); ctl = pid_calc(pid, busy_scaled);
steps = abs(ctl); steps = abs(ctl);
if (ctl < 0) if (ctl < 0)
intel_pstate_pstate_increase(cpu, steps); intel_pstate_pstate_increase(cpu, steps);
else else
@ -612,9 +616,24 @@ static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu)
static void intel_pstate_timer_func(unsigned long __data) static void intel_pstate_timer_func(unsigned long __data)
{ {
struct cpudata *cpu = (struct cpudata *) __data; struct cpudata *cpu = (struct cpudata *) __data;
struct sample *sample;
u64 energy;
intel_pstate_sample(cpu); intel_pstate_sample(cpu);
sample = &cpu->samples[cpu->sample_ptr];
rdmsrl(MSR_PKG_ENERGY_STATUS, energy);
intel_pstate_adjust_busy_pstate(cpu); intel_pstate_adjust_busy_pstate(cpu);
trace_pstate_sample(fp_toint(sample->core_pct_busy),
fp_toint(intel_pstate_get_scaled_busy(cpu)),
cpu->pstate.current_pstate,
sample->mperf,
sample->aperf,
div64_u64(energy, energy_divisor),
sample->freq);
intel_pstate_set_sample_time(cpu); intel_pstate_set_sample_time(cpu);
} }
@ -894,6 +913,7 @@ static int __init intel_pstate_init(void)
int cpu, rc = 0; int cpu, rc = 0;
const struct x86_cpu_id *id; const struct x86_cpu_id *id;
struct cpu_defaults *cpu_info; struct cpu_defaults *cpu_info;
u64 units;
if (no_load) if (no_load)
return -ENODEV; return -ENODEV;
@ -927,8 +947,12 @@ static int __init intel_pstate_init(void)
if (rc) if (rc)
goto out; goto out;
rdmsrl(MSR_RAPL_POWER_UNIT, units);
energy_divisor = 1 << ((units >> 8) & 0x1f); /* bits{12:8} */
intel_pstate_debug_expose_params(); intel_pstate_debug_expose_params();
intel_pstate_sysfs_expose_params(); intel_pstate_sysfs_expose_params();
return rc; return rc;
out: out:
get_online_cpus(); get_online_cpus();

View file

@ -35,6 +35,59 @@ DEFINE_EVENT(cpu, cpu_idle,
TP_ARGS(state, cpu_id) TP_ARGS(state, cpu_id)
); );
TRACE_EVENT(pstate_sample,
TP_PROTO(u32 core_busy,
u32 scaled_busy,
u32 state,
u64 mperf,
u64 aperf,
u32 energy,
u32 freq
),
TP_ARGS(core_busy,
scaled_busy,
state,
mperf,
aperf,
energy,
freq
),
TP_STRUCT__entry(
__field(u32, core_busy)
__field(u32, scaled_busy)
__field(u32, state)
__field(u64, mperf)
__field(u64, aperf)
__field(u32, energy)
__field(u32, freq)
),
TP_fast_assign(
__entry->core_busy = core_busy;
__entry->scaled_busy = scaled_busy;
__entry->state = state;
__entry->mperf = mperf;
__entry->aperf = aperf;
__entry->energy = energy;
__entry->freq = freq;
),
TP_printk("core_busy=%lu scaled=%lu state=%lu mperf=%llu aperf=%llu energy=%lu freq=%lu ",
(unsigned long)__entry->core_busy,
(unsigned long)__entry->scaled_busy,
(unsigned long)__entry->state,
(unsigned long long)__entry->mperf,
(unsigned long long)__entry->aperf,
(unsigned long)__entry->energy,
(unsigned long)__entry->freq
)
);
/* This file can get included multiple times, TRACE_HEADER_MULTI_READ at top */ /* This file can get included multiple times, TRACE_HEADER_MULTI_READ at top */
#ifndef _PWR_EVENT_AVOID_DOUBLE_DEFINING #ifndef _PWR_EVENT_AVOID_DOUBLE_DEFINING
#define _PWR_EVENT_AVOID_DOUBLE_DEFINING #define _PWR_EVENT_AVOID_DOUBLE_DEFINING