forked from mirrors/linux
		
	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:
		
							parent
							
								
									652ed95d5f
								
							
						
					
					
						commit
						b69880f9cc
					
				
					 2 changed files with 77 additions and 0 deletions
				
			
		| 
						 | 
					@ -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();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue