aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Renninger <trenn@suse.de>2011-01-07 05:29:44 -0500
committerLen Brown <len.brown@intel.com>2011-01-12 18:05:16 -0500
commitf77cfe4ea21760268c0277fa3e4b02dfd2a2c2f4 (patch)
treeffd83ee874d1cbe062cd70cade50c017725ba586
parentf878133bf022717b880d0e0995b8f91436fd605c (diff)
cpuidle/x86/perf: fix power:cpu_idle double end events and throw cpu_idle events from the cpuidle layer
Currently intel_idle and acpi_idle driver show double cpu_idle "exit idle" events -> this patch fixes it and makes cpu_idle events throwing less complex. It also introduces cpu_idle events for all architectures which use the cpuidle subsystem, namely: - arch/arm/mach-at91/cpuidle.c - arch/arm/mach-davinci/cpuidle.c - arch/arm/mach-kirkwood/cpuidle.c - arch/arm/mach-omap2/cpuidle34xx.c - arch/drivers/acpi/processor_idle.c (for all cases, not only mwait) - arch/x86/kernel/process.c (did throw events before, but was a mess) - drivers/idle/intel_idle.c (did throw events before) Convention should be: Fire cpu_idle events inside the current pm_idle function (not somewhere down the the callee tree) to keep things easy. Current possible pm_idle functions in X86: c1e_idle, poll_idle, cpuidle_idle_call, mwait_idle, default_idle -> this is really easy is now. This affects userspace: The type field of the cpu_idle power event can now direclty get mapped to: /sys/devices/system/cpu/cpuX/cpuidle/stateX/{name,desc,usage,time,...} instead of throwing very CPU/mwait specific values. This change is not visible for the intel_idle driver. For the acpi_idle driver it should only be visible if the vendor misses out C-states in his BIOS. Another (perf timechart) patch reads out cpuidle info of cpu_idle events from: /sys/.../cpuidle/stateX/*, then the cpuidle events are mapped to the correct C-/cpuidle state again, even if e.g. vendors miss out C-states in their BIOS and for example only export C1 and C3. -> everything is fine. Signed-off-by: Thomas Renninger <trenn@suse.de> CC: Robert Schoene <robert.schoene@tu-dresden.de> CC: Jean Pihet <j-pihet@ti.com> CC: Arjan van de Ven <arjan@linux.intel.com> CC: Ingo Molnar <mingo@elte.hu> CC: Frederic Weisbecker <fweisbec@gmail.com> CC: linux-pm@lists.linux-foundation.org CC: linux-acpi@vger.kernel.org CC: linux-kernel@vger.kernel.org CC: linux-perf-users@vger.kernel.org CC: linux-omap@vger.kernel.org Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r--arch/x86/kernel/process.c6
-rw-r--r--arch/x86/kernel/process_32.c4
-rw-r--r--arch/x86/kernel/process_64.c6
-rw-r--r--drivers/cpuidle/cpuidle.c10
-rw-r--r--drivers/idle/intel_idle.c2
5 files changed, 12 insertions, 16 deletions
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 09c08a1c706f..67e96e67157b 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -386,6 +386,8 @@ void default_idle(void)
386 else 386 else
387 local_irq_enable(); 387 local_irq_enable();
388 current_thread_info()->status |= TS_POLLING; 388 current_thread_info()->status |= TS_POLLING;
389 trace_power_end(smp_processor_id());
390 trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
389 } else { 391 } else {
390 local_irq_enable(); 392 local_irq_enable();
391 /* loop is done by the caller */ 393 /* loop is done by the caller */
@@ -443,8 +445,6 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait);
443 */ 445 */
444void mwait_idle_with_hints(unsigned long ax, unsigned long cx) 446void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
445{ 447{
446 trace_power_start(POWER_CSTATE, (ax>>4)+1, smp_processor_id());
447 trace_cpu_idle((ax>>4)+1, smp_processor_id());
448 if (!need_resched()) { 448 if (!need_resched()) {
449 if (cpu_has(__this_cpu_ptr(&cpu_info), X86_FEATURE_CLFLUSH_MONITOR)) 449 if (cpu_has(__this_cpu_ptr(&cpu_info), X86_FEATURE_CLFLUSH_MONITOR))
450 clflush((void *)&current_thread_info()->flags); 450 clflush((void *)&current_thread_info()->flags);
@@ -471,6 +471,8 @@ static void mwait_idle(void)
471 __sti_mwait(0, 0); 471 __sti_mwait(0, 0);
472 else 472 else
473 local_irq_enable(); 473 local_irq_enable();
474 trace_power_end(smp_processor_id());
475 trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
474 } else 476 } else
475 local_irq_enable(); 477 local_irq_enable();
476} 478}
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 4b9befa0e347..8d128783af47 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -57,8 +57,6 @@
57#include <asm/syscalls.h> 57#include <asm/syscalls.h>
58#include <asm/debugreg.h> 58#include <asm/debugreg.h>
59 59
60#include <trace/events/power.h>
61
62asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); 60asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
63 61
64/* 62/*
@@ -113,8 +111,6 @@ void cpu_idle(void)
113 stop_critical_timings(); 111 stop_critical_timings();
114 pm_idle(); 112 pm_idle();
115 start_critical_timings(); 113 start_critical_timings();
116 trace_power_end(smp_processor_id());
117 trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
118 } 114 }
119 tick_nohz_restart_sched_tick(); 115 tick_nohz_restart_sched_tick();
120 preempt_enable_no_resched(); 116 preempt_enable_no_resched();
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 4c818a738396..bd387e8f73b4 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -51,8 +51,6 @@
51#include <asm/syscalls.h> 51#include <asm/syscalls.h>
52#include <asm/debugreg.h> 52#include <asm/debugreg.h>
53 53
54#include <trace/events/power.h>
55
56asmlinkage extern void ret_from_fork(void); 54asmlinkage extern void ret_from_fork(void);
57 55
58DEFINE_PER_CPU(unsigned long, old_rsp); 56DEFINE_PER_CPU(unsigned long, old_rsp);
@@ -141,10 +139,6 @@ void cpu_idle(void)
141 pm_idle(); 139 pm_idle();
142 start_critical_timings(); 140 start_critical_timings();
143 141
144 trace_power_end(smp_processor_id());
145 trace_cpu_idle(PWR_EVENT_EXIT,
146 smp_processor_id());
147
148 /* In many cases the interrupt that ended idle 142 /* In many cases the interrupt that ended idle
149 has already called exit_idle. But some idle 143 has already called exit_idle. But some idle
150 loops can be woken up without interrupt. */ 144 loops can be woken up without interrupt. */
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 386888f10df0..e4855c33f897 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -96,7 +96,15 @@ static void cpuidle_idle_call(void)
96 96
97 /* enter the state and update stats */ 97 /* enter the state and update stats */
98 dev->last_state = target_state; 98 dev->last_state = target_state;
99
100 trace_power_start(POWER_CSTATE, next_state, dev->cpu);
101 trace_cpu_idle(next_state, dev->cpu);
102
99 dev->last_residency = target_state->enter(dev, target_state); 103 dev->last_residency = target_state->enter(dev, target_state);
104
105 trace_power_end(dev->cpu);
106 trace_cpu_idle(PWR_EVENT_EXIT, dev->cpu);
107
100 if (dev->last_state) 108 if (dev->last_state)
101 target_state = dev->last_state; 109 target_state = dev->last_state;
102 110
@@ -106,8 +114,6 @@ static void cpuidle_idle_call(void)
106 /* give the governor an opportunity to reflect on the outcome */ 114 /* give the governor an opportunity to reflect on the outcome */
107 if (cpuidle_curr_governor->reflect) 115 if (cpuidle_curr_governor->reflect)
108 cpuidle_curr_governor->reflect(dev); 116 cpuidle_curr_governor->reflect(dev);
109 trace_power_end(smp_processor_id());
110 trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
111} 117}
112 118
113/** 119/**
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 56ac09d6c930..60fa6ecdb41f 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -220,8 +220,6 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state)
220 kt_before = ktime_get_real(); 220 kt_before = ktime_get_real();
221 221
222 stop_critical_timings(); 222 stop_critical_timings();
223 trace_power_start(POWER_CSTATE, (eax >> 4) + 1, cpu);
224 trace_cpu_idle((eax >> 4) + 1, cpu);
225 if (!need_resched()) { 223 if (!need_resched()) {
226 224
227 __monitor((void *)&current_thread_info()->flags, 0, 0); 225 __monitor((void *)&current_thread_info()->flags, 0, 0);