diff options
author | Jonas Aaberg <jonas.aberg@stericsson.com> | 2011-05-27 11:59:04 +0200 |
---|---|---|
committer | said m bagheri <ebgheri@steludxu2848.(none)> | 2011-06-17 13:42:06 +0200 |
commit | 0de977bef81a23499353814d205a636459969abe (patch) | |
tree | d15f4e00560a7f2e36f2c43e68d7fa03bae380ff /arch | |
parent | e0f58c0c1b17dbb4d6b483fc40f5868410b46130 (diff) |
ARM: ux500: cpuidle_dbg: Show reason why ApIdle
Add debug code to show the reason why we're in ApIdle
and not in ApSleep.
ST-Ericsson Linux next: ER338824
ST-Ericsson ID: -
ST-Ericsson FOSS-OUT ID: Trivial
Change-Id: I652a5708f08c279b4a2a322bab45ea8eac693e56
Signed-off-by: Jonas Aaberg <jonas.aberg@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/24043
Reviewed-by: QATEST
Reviewed-by: Rickard ANDERSSON <rickard.andersson@stericsson.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-ux500/pm/cpuidle.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-ux500/pm/cpuidle_dbg.c | 46 | ||||
-rw-r--r-- | arch/arm/mach-ux500/pm/cpuidle_dbg.h | 10 |
3 files changed, 57 insertions, 3 deletions
diff --git a/arch/arm/mach-ux500/pm/cpuidle.c b/arch/arm/mach-ux500/pm/cpuidle.c index fe04634a5b2..bba32577259 100644 --- a/arch/arm/mach-ux500/pm/cpuidle.c +++ b/arch/arm/mach-ux500/pm/cpuidle.c @@ -352,6 +352,10 @@ static int determine_sleep_state(u32 *sleep_time) break; } + ux500_ci_dbg_register_reason(i, power_state_req, + (*sleep_time), + max_depth); + return max(CI_WFI, i); } diff --git a/arch/arm/mach-ux500/pm/cpuidle_dbg.c b/arch/arm/mach-ux500/pm/cpuidle_dbg.c index 5d3315dbf70..d74743c53c1 100644 --- a/arch/arm/mach-ux500/pm/cpuidle_dbg.c +++ b/arch/arm/mach-ux500/pm/cpuidle_dbg.c @@ -62,6 +62,10 @@ struct state_history { u32 exit_counter; u32 timed_out; ktime_t measure_begin; + int ape_blocked; + int time_blocked; + int both_blocked; + int gov_blocked; struct state_history_state *states; }; static DEFINE_PER_CPU(struct state_history, *state_history); @@ -78,6 +82,11 @@ static int deepest_allowed_state = CONFIG_U8500_CPUIDLE_DEEPEST_STATE; static u32 measure_latency; static bool wake_latency; +static bool apidle_both_blocked; +static bool apidle_ape_blocked; +static bool apidle_time_blocked; +static bool apidle_gov_blocked; + static struct cstate *cstates; static int cstates_len; static DEFINE_SPINLOCK(dbg_lock); @@ -324,11 +333,23 @@ static void state_record_time(struct state_history *sh, int ctarget, sh->states[sh->state].counter++; } +void ux500_ci_dbg_register_reason(int idx, bool power_state_req, + u32 time, u32 max_depth) +{ + + + if (cstates[idx].state == CI_IDLE) { + apidle_ape_blocked = power_state_req; + apidle_time_blocked = time < cstates[idx + 1].threshold; + apidle_both_blocked = power_state_req && apidle_time_blocked; + apidle_gov_blocked = cstates[max_depth].state == CI_IDLE; + } +} + void ux500_ci_dbg_log(int ctarget, ktime_t enter_time) { int i; ktime_t now; - unsigned long flags; struct state_history *sh; struct state_history *sh_other; @@ -342,6 +363,17 @@ void ux500_ci_dbg_log(int ctarget, ktime_t enter_time) spin_lock_irqsave(&dbg_lock, flags); + if (cstates[ctarget].state == CI_IDLE) { + if (apidle_both_blocked) + sh->both_blocked++; + if (apidle_ape_blocked) + sh->ape_blocked++; + if (apidle_time_blocked) + sh->time_blocked++; + if (apidle_gov_blocked) + sh->gov_blocked++; + } + /* * Check if current state is just a repeat of * the state we're already in, then just quit. @@ -419,9 +451,14 @@ static void state_history_reset(void) sh->start = ktime_get(); sh->measure_begin = sh->start; - sh->state = cstates_len; /* CI_RUNNING */ + /* Don't touch sh->state, since that is where we are now */ + sh->exit_counter = 0; sh->timed_out = 0; + sh->ape_blocked = 0; + sh->time_blocked = 0; + sh->both_blocked = 0; + sh->gov_blocked = 0; } spin_unlock_irqrestore(&dbg_lock, flags); } @@ -533,6 +570,11 @@ static void stats_disp_one(struct seq_file *s, struct state_history *sh, seq_printf(s, " in %d ms %d%%", (u32) t_us, (u32)perc); + if (cstates[i].state == CI_IDLE) + seq_printf(s, ", reg:%d time:%d both:%d gov:%d", + sh->ape_blocked, sh->time_blocked, + sh->both_blocked, sh->gov_blocked); + if (sh->states[i].counter) seq_printf(s, ", hit rate: %u%% ", 100 * sh->states[i].hit_rate / diff --git a/arch/arm/mach-ux500/pm/cpuidle_dbg.h b/arch/arm/mach-ux500/pm/cpuidle_dbg.h index 143b8cf48d8..406106038ad 100644 --- a/arch/arm/mach-ux500/pm/cpuidle_dbg.h +++ b/arch/arm/mach-ux500/pm/cpuidle_dbg.h @@ -9,6 +9,8 @@ #ifndef CPUIDLE_DBG_H #define CPUIDLE_DBG_H +#include "cpuidle.h" + #ifdef CONFIG_U8500_CPUIDLE_DEBUG void ux500_ci_dbg_init(void); void ux500_ci_dbg_remove(void); @@ -17,7 +19,9 @@ void ux500_ci_dbg_log(int ctarget, ktime_t enter_time); void ux500_ci_dbg_wake_latency(int ctarget, int sleep_time); void ux500_ci_dbg_exit_latency(int ctarget, ktime_t now, ktime_t exit, ktime_t enter, bool timed_out); -void ux500_ci_dbg_wake_timer(bool timed); + +void ux500_ci_dbg_register_reason(int idx, bool power_state_req, + u32 sleep_time, u32 max_depth); bool ux500_ci_dbg_force_ape_on(void); int ux500_ci_dbg_deepest_state(void); @@ -40,6 +44,10 @@ static inline void ux500_ci_dbg_exit_latency(int ctarget, ktime_t enter, bool timed_out) { } static inline void ux500_ci_dbg_wake_latency(int ctarget, int sleep_time) { } + +static inline void ux500_ci_dbg_register_reason(int idx, bool power_state_req, + u32 sleep_time, u32 max_depth) { } + static inline bool ux500_ci_dbg_force_ape_on(void) { return false; |