diff options
author | Philippe Langlais <philippe.langlais@linaro.org> | 2011-05-09 17:04:37 +0200 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@stericsson.com> | 2011-09-19 15:15:08 +0200 |
commit | 35474a6ad46cfa2747b42e4ab9dad2ce74cc672a (patch) | |
tree | 80a55344fda74f200ab535195b06063e096e728b /arch/arm | |
parent | 9a78ede38b37a5df835832dac5c90538fe4187f7 (diff) |
ARM: ux500: cpuidle_dbg: Code clean-up and minor fixes
Remove the recursivness from ux500_ci_dbg_log and at the
same time simplify the code plus remove a potential deadlock.
ST-Ericsson Linux next: Not tested, ask SSM for ER
ST-Ericsson ID: ER329430
ST-Ericsson FOSS-OUT ID: Trivial
Change-Id: Ife93b19e3e6d646f4d34c306820daec37c5e23f8
Signed-off-by: Jonas Aaberg <jonas.aberg@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/20643
Conflicts:
arch/arm/configs/u8500_defconfig
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-ux500/pm/Kconfig | 3 | ||||
-rw-r--r-- | arch/arm/mach-ux500/pm/cpuidle.c | 22 | ||||
-rw-r--r-- | arch/arm/mach-ux500/pm/cpuidle.h | 4 | ||||
-rw-r--r-- | arch/arm/mach-ux500/pm/cpuidle_dbg.c | 185 | ||||
-rw-r--r-- | arch/arm/mach-ux500/pm/cpuidle_dbg.h | 4 |
5 files changed, 101 insertions, 117 deletions
diff --git a/arch/arm/mach-ux500/pm/Kconfig b/arch/arm/mach-ux500/pm/Kconfig index 84eb194afe0..b0fb08831c7 100644 --- a/arch/arm/mach-ux500/pm/Kconfig +++ b/arch/arm/mach-ux500/pm/Kconfig @@ -16,10 +16,11 @@ config U8500_CPUIDLE config U8500_CPUIDLE_DEEPEST_STATE int "Deepest sleep state" - default 3 + default 4 depends on U8500_CPUIDLE help Set deepest sleep state. See the cstate struct in cpuidle.c. + Default is ApSleep. config U8500_CPUIDLE_DEBUG bool "CPUIdle debug" diff --git a/arch/arm/mach-ux500/pm/cpuidle.c b/arch/arm/mach-ux500/pm/cpuidle.c index 48d16ca86ec..3612bfb286c 100644 --- a/arch/arm/mach-ux500/pm/cpuidle.c +++ b/arch/arm/mach-ux500/pm/cpuidle.c @@ -32,6 +32,20 @@ static struct cstate cstates[] = { .enter_latency = 0, .exit_latency = 0, .threshold = 0, + .power_usage = 1000, + .APE = APE_ON, + .ARM = ARM_ON, + .ARM_PLL = ARM_PLL_ON, + .UL_PLL = UL_PLL_ON, + .ESRAM = ESRAM_RET, + .pwrst = NO_TRANSITION, + .state = CI_RUNNING, + .desc = "Running ", + }, + { + .enter_latency = 0, + .exit_latency = 0, + .threshold = 0, .power_usage = 10, .APE = APE_ON, .ARM = ARM_ON, @@ -348,7 +362,7 @@ static int determine_sleep_state(int idle_cpus, /* If first cpu to sleep, go to most shallow sleep state */ if (idle_cpus < num_online_cpus()) - return 0; + return CI_WFI; /* If other CPU is going to WFI, but not yet there wait. */ while (1) { @@ -359,7 +373,7 @@ static int determine_sleep_state(int idle_cpus, return -1; if (atomic_read(&idle_cpus_counter) < num_online_cpus()) - return 0; + return CI_WFI; } power_state_req = power_state_active_is_enabled() || @@ -405,7 +419,7 @@ static int determine_sleep_state(int idle_cpus, break; } - return max(0, i); + return max(CI_WFI, i); } @@ -453,7 +467,7 @@ static int enter_sleep(struct cpuidle_device *dev, gov_cstate); if (target < 0) { /* "target" will be last_state in the cpuidle framework */ - target = 0; + target = CI_RUNNING; goto exit_fast; } diff --git a/arch/arm/mach-ux500/pm/cpuidle.h b/arch/arm/mach-ux500/pm/cpuidle.h index 0bc69ceeb46..7baaf99d855 100644 --- a/arch/arm/mach-ux500/pm/cpuidle.h +++ b/arch/arm/mach-ux500/pm/cpuidle.h @@ -40,12 +40,12 @@ enum ESRAM { }; enum ci_pwrst { - CI_WFI = 0, + CI_RUNNING = 0, + CI_WFI = 1, CI_IDLE, CI_SLEEP, CI_DEEP_IDLE, CI_DEEP_SLEEP, - CI_RUNNING = 255, }; struct cstate { diff --git a/arch/arm/mach-ux500/pm/cpuidle_dbg.c b/arch/arm/mach-ux500/pm/cpuidle_dbg.c index 4df36fc0ea7..bd3b683975b 100644 --- a/arch/arm/mach-ux500/pm/cpuidle_dbg.c +++ b/arch/arm/mach-ux500/pm/cpuidle_dbg.c @@ -2,7 +2,7 @@ * Copyright (C) ST-Ericsson SA 2010 * * License Terms: GNU General Public License v2 - * Author: Rickard Andersson <rickard.andersson@stericsson.com> for ST-Ericsson + * Author: Rickard Andersson <rickard.andersson@stericsson.com>, * Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson */ @@ -41,7 +41,6 @@ struct state_history { u32 state; u32 *counter; ktime_t *time; - spinlock_t lock; }; static DEFINE_PER_CPU(struct state_history, *state_history); @@ -50,7 +49,7 @@ static u32 dbg_console_enable = 1; static void __iomem *uart_base; static struct clk *uart_clk; - /* Blocks ApSleep and ApDeepSleep */ +/* Blocks ApSleep and ApDeepSleep */ static bool force_APE_on; static bool reset_timer; static int deepest_allowed_state = CONFIG_U8500_CPUIDLE_DEEPEST_STATE; @@ -155,12 +154,10 @@ void ux500_ci_dbg_console_check_uart(void) spin_lock_irqsave(&dbg_lock, flags); status = readw(uart_base + UART011_MIS); - if (status & (UART011_MIS_RTIS | UART011_MIS_RXIS)) { + if (status & (UART011_MIS_RTIS | UART011_MIS_RXIS)) reset_timer = true; - spin_unlock_irqrestore(&dbg_lock, flags); - } else { - spin_unlock_irqrestore(&dbg_lock, flags); - } + + spin_unlock_irqrestore(&dbg_lock, flags); clk_disable(uart_clk); } @@ -192,11 +189,25 @@ static void dbg_cpuidle_work_function(struct work_struct *work) force_APE_on = false; } -void ux500_ci_dbg_log(int state, int this_cpu) +static void state_record_time(struct state_history *sh, enum ci_pwrst pstate, + ktime_t now) +{ + ktime_t dtime; + + dtime = ktime_sub(now, sh->start); + sh->time[sh->state] = ktime_add(sh->time[sh->state], dtime); + + sh->start = now; + + sh->state = pstate; + sh->counter[sh->state]++; +} + +void ux500_ci_dbg_log(enum ci_pwrst pstate, int this_cpu) { int i; ktime_t now; - ktime_t dtime; + unsigned long flags; struct state_history *sh; struct state_history *sh_other; @@ -205,18 +216,16 @@ void ux500_ci_dbg_log(int state, int this_cpu) sh = per_cpu(state_history, this_cpu); - spin_lock_irqsave(&sh->lock, flags); - - dtime = ktime_sub(now, sh->start); - sh->time[sh->state] = ktime_add(sh->time[sh->state], dtime); + spin_lock_irqsave(&dbg_lock, flags); - sh->start = now; + /* + * Check if current state is just a repeat of + * the state we're already in, then just quit. + */ + if (pstate == sh->state) + goto done; - if (state == CI_RUNNING) - sh->state = cstates_len; - else - sh->state = state; - sh->counter[sh->state]++; + state_record_time(sh, pstate, now); /* * Update other cpus, (this_cpu = A, other cpus = B) if: @@ -239,18 +248,18 @@ void ux500_ci_dbg_log(int state, int this_cpu) if (sh_other->state == sh->state) continue; - if (state == CI_RUNNING && sh_other->state != CI_WFI) { - ux500_ci_dbg_log(CI_WFI, i); + if (pstate == CI_RUNNING && sh_other->state != CI_WFI) { + state_record_time(sh_other, CI_WFI, now); continue; } /* * This cpu is something else than running or wfi, both must be * in the same state. */ - ux500_ci_dbg_log(state, i); + state_record_time(sh_other, pstate, now); } done: - spin_unlock_irqrestore(&sh->lock, flags); + spin_unlock_irqrestore(&dbg_lock, flags); } static ssize_t set_deepest_state(struct file *file, @@ -274,6 +283,9 @@ static ssize_t set_deepest_state(struct file *file, if (i > cstates_len - 1) i = cstates_len - 1; + if (i == 0) + i = 1; + deepest_allowed_state = i; pr_debug("cpuidle: changed deepest allowed sleep state to %d.\n", @@ -303,16 +315,15 @@ static ssize_t stats_write(struct file *file, for_each_possible_cpu(cpu) { sh = per_cpu(state_history, cpu); - spin_lock_irqsave(&sh->lock, flags); - for (i = 0; i <= cstates_len; i++) { + spin_lock_irqsave(&dbg_lock, flags); + for (i = 0; i < cstates_len; i++) { sh->counter[i] = 0; sh->time[i] = ktime_set(0, 0); + sh->start = ktime_get(); } - for (i = 0; i <= cstates_len; i++) - sh->start = ktime_get(); - sh->state = cstates_len; /* CI_RUNNING */ - spin_unlock_irqrestore(&sh->lock, flags); + sh->state = CI_RUNNING; + spin_unlock_irqrestore(&dbg_lock, flags); } return count; @@ -331,17 +342,17 @@ static int stats_print(struct seq_file *s, void *p) for_each_possible_cpu(cpu) { sh = per_cpu(state_history, cpu); - spin_lock_irqsave(&sh->lock, flags); + spin_lock_irqsave(&dbg_lock, flags); seq_printf(s, "\nCPU%d\n", cpu); total = ktime_set(0, 0); - for (i = 0; i <= cstates_len; i++) + for (i = 0; i < cstates_len; i++) total = ktime_add(total, sh->time[i]); total_us = ktime_to_us(total); do_div(total_us, 100); - for (i = 0; i <= cstates_len; i++) { + for (i = 0; i < cstates_len; i++) { t_us = ktime_to_us(sh->time[i]); perc = ktime_to_us(sh->time[i]); @@ -349,18 +360,12 @@ static int stats_print(struct seq_file *s, void *p) if (total_us != 0) do_div(perc, total_us); - if (i == cstates_len) - seq_printf(s, " - Running : # " - "%d in %d ms %d%%\n", - sh->counter[cstates_len], - (u32) t_us, (u32)perc); - else - seq_printf(s, "%d - %s: # %u in %d ms %d%%\n", - i, cstates[i].desc, - sh->counter[i], - (u32) t_us, (u32)perc); + seq_printf(s, "%d - %s: # %u in %d ms %d%%\n", + i, cstates[i].desc, + sh->counter[i], + (u32) t_us, (u32)perc); } - spin_unlock_irqrestore(&sh->lock, flags); + spin_unlock_irqrestore(&dbg_lock, flags); } return 0; } @@ -374,7 +379,7 @@ static int ap_family_show(struct seq_file *s, void *iter) struct state_history *sh; sh = per_cpu(state_history, 0); - spin_lock_irqsave(&sh->lock, flags); + spin_lock_irqsave(&dbg_lock, flags); for (i = 0 ; i < cstates_len; i++) { if (cstates[i].state == (enum ci_pwrst)s->private) @@ -382,7 +387,7 @@ static int ap_family_show(struct seq_file *s, void *iter) } seq_printf(s, "%u\n", count); - spin_unlock_irqrestore(&sh->lock, flags); + spin_unlock_irqrestore(&dbg_lock, flags); return 0; } @@ -431,34 +436,6 @@ static const struct file_operations ap_family_fops = { }; static struct dentry *cpuidle_dir; -static struct dentry *deepest_state_file; -static struct dentry *stats_file; -static struct dentry *dbg_console_file; -static struct dentry *apidle_file; -static struct dentry *apsleep_file; -static struct dentry *apdeepidle_file; -static struct dentry *apdeepsleep_file; - -static void remove_debugfs(void) -{ - if (!IS_ERR_OR_NULL(dbg_console_file)) - debugfs_remove(dbg_console_file); - if (!IS_ERR_OR_NULL(stats_file)) - debugfs_remove(stats_file); - if (!IS_ERR_OR_NULL(deepest_state_file)) - debugfs_remove(deepest_state_file); - if (!IS_ERR_OR_NULL(apidle_file)) - debugfs_remove(apidle_file); - if (!IS_ERR_OR_NULL(apsleep_file)) - debugfs_remove(apsleep_file); - if (!IS_ERR_OR_NULL(apdeepidle_file)) - debugfs_remove(apdeepidle_file); - if (!IS_ERR_OR_NULL(apdeepsleep_file)) - debugfs_remove(apdeepsleep_file); - - if (!IS_ERR_OR_NULL(cpuidle_dir)) - debugfs_remove(cpuidle_dir); -} static void setup_debugfs(void) { @@ -466,55 +443,48 @@ static void setup_debugfs(void) if (IS_ERR_OR_NULL(cpuidle_dir)) goto fail; - deepest_state_file = debugfs_create_file("deepest_state", - S_IWUGO | S_IRUGO, cpuidle_dir, - NULL, &deepest_state_fops); - if (IS_ERR_OR_NULL(deepest_state_file)) + if (IS_ERR_OR_NULL(debugfs_create_file("deepest_state", + S_IWUGO | S_IRUGO, cpuidle_dir, + NULL, &deepest_state_fops))) goto fail; - stats_file = debugfs_create_file("stats", - S_IRUGO, cpuidle_dir, NULL, - &stats_fops); - if (IS_ERR_OR_NULL(stats_file)) + if (IS_ERR_OR_NULL(debugfs_create_file("stats", + S_IRUGO, cpuidle_dir, NULL, + &stats_fops))) goto fail; - dbg_console_file = debugfs_create_bool("dbg_console_enable", + if (IS_ERR_OR_NULL(debugfs_create_bool("dbg_console_enable", S_IWUGO | S_IRUGO, cpuidle_dir, - &dbg_console_enable); - if (IS_ERR_OR_NULL(dbg_console_file)) + &dbg_console_enable))) goto fail; - apidle_file = debugfs_create_file("ap_idle", S_IRUGO, - cpuidle_dir, - (void *)CI_IDLE, - &ap_family_fops); - if (IS_ERR_OR_NULL(apidle_file)) + if (IS_ERR_OR_NULL(debugfs_create_file("ap_idle", S_IRUGO, + cpuidle_dir, + (void *)CI_IDLE, + &ap_family_fops))) goto fail; - apsleep_file = debugfs_create_file("ap_sleep", S_IRUGO, - cpuidle_dir, - (void *)CI_SLEEP, - &ap_family_fops); - if (IS_ERR_OR_NULL(apsleep_file)) + if (IS_ERR_OR_NULL(debugfs_create_file("ap_sleep", S_IRUGO, + cpuidle_dir, + (void *)CI_SLEEP, + &ap_family_fops))) goto fail; - apdeepidle_file = debugfs_create_file("ap_deepidle", S_IRUGO, + if (IS_ERR_OR_NULL(debugfs_create_file("ap_deepidle", S_IRUGO, cpuidle_dir, (void *)CI_DEEP_IDLE, - &ap_family_fops); - if (IS_ERR_OR_NULL(apdeepidle_file)) + &ap_family_fops))) goto fail; - apdeepsleep_file = debugfs_create_file("ap_deepsleep", S_IRUGO, + if (IS_ERR_OR_NULL(debugfs_create_file("ap_deepsleep", S_IRUGO, cpuidle_dir, (void *)CI_DEEP_SLEEP, - &ap_family_fops); - if (IS_ERR_OR_NULL(apdeepsleep_file)) + &ap_family_fops))) goto fail; return; fail: - remove_debugfs(); + debugfs_remove_recursive(cpuidle_dir); } void ux500_ci_dbg_init(void) @@ -529,17 +499,16 @@ void ux500_ci_dbg_init(void) per_cpu(state_history, cpu) = kzalloc(sizeof(struct state_history), GFP_KERNEL); sh = per_cpu(state_history, cpu); - sh->counter = kzalloc(sizeof(u32) * (cstates_len + 1), + sh->counter = kzalloc(sizeof(u32) * cstates_len, GFP_KERNEL); - sh->time = kzalloc(sizeof(ktime_t) * (cstates_len + 1), + sh->time = kzalloc(sizeof(ktime_t) * cstates_len, GFP_KERNEL); - spin_lock_init(&sh->lock); /* Only first CPU used during boot */ if (cpu == 0) - sh->state = cstates_len; /* CI_RUNNING */ + sh->state = CI_RUNNING; else - sh->state = CI_WFI; + sh->state = CI_WFI; sh->start = ktime_get(); } @@ -574,7 +543,7 @@ void ux500_ci_dbg_remove(void) int cpu; struct state_history *sh; - remove_debugfs(); + debugfs_remove_recursive(cpuidle_dir); for_each_possible_cpu(cpu) { sh = per_cpu(state_history, cpu); diff --git a/arch/arm/mach-ux500/pm/cpuidle_dbg.h b/arch/arm/mach-ux500/pm/cpuidle_dbg.h index e614910e9bc..9a648c4b432 100644 --- a/arch/arm/mach-ux500/pm/cpuidle_dbg.h +++ b/arch/arm/mach-ux500/pm/cpuidle_dbg.h @@ -13,7 +13,7 @@ void ux500_ci_dbg_init(void); void ux500_ci_dbg_remove(void); -void ux500_ci_dbg_log(int state, int this_cpu); +void ux500_ci_dbg_log(enum ci_pwrst pstate, int this_cpu); bool ux500_ci_dbg_force_ape_on(void); int ux500_ci_dbg_deepest_state(void); @@ -34,7 +34,7 @@ static inline void ux500_ci_dbg_msg(char *dbg_string) { } static inline void ux500_ci_dbg_init(void) { } static inline void ux500_ci_dbg_remove(void) { } -static inline void ux500_ci_dbg_log(int state, int this_cpu) { } +static inline void ux500_ci_dbg_log(enum ci_pwrst pstate, int this_cpu) { } static inline bool ux500_ci_dbg_force_ape_on(void) { |