Loading drivers/cpuidle/lpm-levels.c +32 −15 Original line number Diff line number Diff line Loading @@ -92,9 +92,11 @@ static int lpm_cpu_callback(struct notifier_block *cpu_nb, unsigned long action, void *hcpu); static void cluster_unprepare(struct lpm_cluster *cluster, const struct cpumask *cpu, int child_idx, bool from_idle); const struct cpumask *cpu, int child_idx, bool from_idle, int64_t time); static void cluster_prepare(struct lpm_cluster *cluster, const struct cpumask *cpu, int child_idx, bool from_idle); const struct cpumask *cpu, int child_idx, bool from_idle, int64_t time); static struct notifier_block __refdata lpm_cpu_nblk = { .notifier_call = lpm_cpu_callback, Loading Loading @@ -184,11 +186,11 @@ static int lpm_cpu_callback(struct notifier_block *cpu_nb, switch (action & ~CPU_TASKS_FROZEN) { case CPU_DYING: cluster_prepare(cluster, get_cpu_mask((unsigned int) cpu), NR_LPM_LEVELS, false); NR_LPM_LEVELS, false, 0); break; case CPU_STARTING: cluster_unprepare(cluster, get_cpu_mask((unsigned int) cpu), NR_LPM_LEVELS, false); NR_LPM_LEVELS, false, 0); break; case CPU_ONLINE: smp_call_function_single(cpu, setup_broadcast_timer, Loading Loading @@ -575,7 +577,8 @@ failed_set_mode: } static void cluster_prepare(struct lpm_cluster *cluster, const struct cpumask *cpu, int child_idx, bool from_idle) const struct cpumask *cpu, int child_idx, bool from_idle, int64_t start_time) { int i; Loading Loading @@ -616,15 +619,21 @@ static void cluster_prepare(struct lpm_cluster *cluster, if (cluster_configure(cluster, i, from_idle)) goto failed; cluster->stats->sleep_time = start_time; cluster_prepare(cluster->parent, &cluster->num_children_in_sync, i, from_idle); from_idle, start_time); spin_unlock(&cluster->sync_lock); return; failed: spin_unlock(&cluster->sync_lock); cluster->stats->sleep_time = 0; return; } static void cluster_unprepare(struct lpm_cluster *cluster, const struct cpumask *cpu, int child_idx, bool from_idle) const struct cpumask *cpu, int child_idx, bool from_idle, int64_t end_time) { struct lpm_cluster_level *level; bool first_cpu; Loading Loading @@ -654,6 +663,9 @@ static void cluster_unprepare(struct lpm_cluster *cluster, if (!first_cpu || cluster->last_level == cluster->default_level) goto unlock_return; if (cluster->stats->sleep_time) cluster->stats->sleep_time = end_time - cluster->stats->sleep_time; lpm_stats_cluster_exit(cluster->stats, cluster->last_level, true); level = &cluster->levels[cluster->last_level]; Loading Loading @@ -690,7 +702,7 @@ static void cluster_unprepare(struct lpm_cluster *cluster, cluster_notify(cluster, &cluster->levels[last_level], false); cluster_unprepare(cluster->parent, &cluster->child_cpus, last_level, from_idle); last_level, from_idle, end_time); unlock_return: spin_unlock(&cluster->sync_lock); } Loading Loading @@ -875,13 +887,13 @@ static int lpm_cpuidle_enter(struct cpuidle_device *dev, pwr_params->energy_overhead, pwr_params->latency_us); cpu_prepare(cluster, idx, true); cluster_prepare(cluster, cpumask, idx, true); cluster_prepare(cluster, cpumask, idx, true, ktime_to_ns(ktime_get())); if (need_resched() || (idx < 0)) goto exit; trace_cpu_idle_enter(idx); lpm_stats_cpu_enter(idx); lpm_stats_cpu_enter(idx, start_time); if (!use_psci) { if (idx > 0) Loading @@ -898,8 +910,10 @@ static int lpm_cpuidle_enter(struct cpuidle_device *dev, } exit: lpm_stats_cpu_exit(idx, success); cluster_unprepare(cluster, cpumask, idx, true); end_time = ktime_to_ns(ktime_get()); lpm_stats_cpu_exit(idx, end_time, success); cluster_unprepare(cluster, cpumask, idx, true, end_time); cpu_unprepare(cluster, idx, true); sched_set_cpu_cstate(smp_processor_id(), 0, 0, 0); Loading Loading @@ -1111,6 +1125,7 @@ static int lpm_suspend_enter(suspend_state_t state) struct lpm_cpu *lpm_cpu = cluster->cpu; const struct cpumask *cpumask = get_cpu_mask(cpu); int idx; int64_t time = ktime_to_ns(ktime_get()); for (idx = lpm_cpu->nlevels - 1; idx >= 0; idx--) { Loading @@ -1122,7 +1137,7 @@ static int lpm_suspend_enter(suspend_state_t state) return 0; } cpu_prepare(cluster, idx, false); cluster_prepare(cluster, cpumask, idx, false); cluster_prepare(cluster, cpumask, idx, false, time); if (idx > 0) update_debug_pc_event(CPU_ENTER, idx, 0xdeaffeed, 0xdeaffeed, false); Loading @@ -1143,7 +1158,9 @@ static int lpm_suspend_enter(suspend_state_t state) if (idx > 0) update_debug_pc_event(CPU_EXIT, idx, true, 0xdeaffeed, false); cluster_unprepare(cluster, cpumask, idx, false); time = ktime_to_ns(ktime_get()); cluster_unprepare(cluster, cpumask, idx, false, time); cpu_unprepare(cluster, idx, false); return 0; } Loading Loading @@ -1354,7 +1371,7 @@ void lpm_cpu_hotplug_enter(unsigned int cpu) return; BUG_ON(idx < 0); cluster_prepare(cluster, get_cpu_mask(cpu), idx, false); cluster_prepare(cluster, get_cpu_mask(cpu), idx, false, 0); } msm_cpu_pm_enter_sleep(mode, false); Loading drivers/power/qcom/lpm-stats.c +10 −30 Original line number Diff line number Diff line /* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -24,6 +24,7 @@ #include <linux/suspend.h> #include <soc/qcom/spm.h> #include <soc/qcom/pm.h> #include <soc/qcom/lpm-stats.h> #define MAX_STR_LEN 256 const char *lpm_stats_reset = "reset"; Loading @@ -42,24 +43,6 @@ struct level_stats { uint64_t enter_time; }; struct lifo_stats { uint32_t last_in; uint32_t first_out; }; struct lpm_stats { char name[MAX_STR_LEN]; struct level_stats *time_stats; uint32_t num_levels; struct lifo_stats lifo; struct lpm_stats *parent; struct list_head sibling; struct list_head child; struct cpumask mask; struct dentry *directory; bool is_cpu; }; static struct level_stats suspend_time_stats; static DEFINE_PER_CPU_SHARED_ALIGNED(struct lpm_stats, cpu_stats); Loading Loading @@ -425,13 +408,9 @@ static inline void update_exit_stats(struct lpm_stats *stats, uint32_t index, uint64_t exit_time = 0; /* Update time stats only when exit is preceded by enter */ if (stats->time_stats[index].enter_time) { exit_time = sched_clock() - stats->time_stats[index].enter_time; exit_time = stats->sleep_time; update_level_stats(&stats->time_stats[index], exit_time, success); stats->time_stats[index].enter_time = 0; } } static int config_level(const char *name, const char **levels, Loading Loading @@ -679,8 +658,6 @@ void lpm_stats_cluster_enter(struct lpm_stats *stats, uint32_t index) if (IS_ERR_OR_NULL(stats)) return; stats->time_stats[index].enter_time = sched_clock(); update_last_in_stats(stats); } EXPORT_SYMBOL(lpm_stats_cluster_enter); Loading Loading @@ -717,14 +694,15 @@ EXPORT_SYMBOL(lpm_stats_cluster_exit); * Function to communicate the low power mode level that the cpu is * prepared to enter. */ void lpm_stats_cpu_enter(uint32_t index) void lpm_stats_cpu_enter(uint32_t index, uint64_t time) { struct lpm_stats *stats = &__get_cpu_var(cpu_stats); stats->sleep_time = time; if (!stats->time_stats) return; stats->time_stats[index].enter_time = sched_clock(); } EXPORT_SYMBOL(lpm_stats_cpu_enter); Loading @@ -736,13 +714,15 @@ EXPORT_SYMBOL(lpm_stats_cpu_enter); * * Function to communicate the low power mode level that the cpu exited. */ void lpm_stats_cpu_exit(uint32_t index, bool success) void lpm_stats_cpu_exit(uint32_t index, uint64_t time, bool success) { struct lpm_stats *stats = &__get_cpu_var(cpu_stats); if (!stats->time_stats) return; stats->sleep_time = time - stats->sleep_time; update_exit_stats(stats, index, success); } EXPORT_SYMBOL(lpm_stats_cpu_exit); Loading include/soc/qcom/lpm-stats.h +29 −5 Original line number Diff line number Diff line /* * Copyright (c) 2014, The Linux Foundation. All rights reserved. * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -17,6 +17,29 @@ struct lpm_stats; #define MAX_STR_LEN 256 struct lifo_stats { uint32_t last_in; uint32_t first_out; }; struct lpm_stats { char name[MAX_STR_LEN]; struct level_stats *time_stats; uint32_t num_levels; struct lifo_stats lifo; struct lpm_stats *parent; struct list_head sibling; struct list_head child; struct cpumask mask; struct dentry *directory; int64_t sleep_time; bool is_cpu; }; #ifdef CONFIG_MSM_IDLE_STATS struct lpm_stats *lpm_stats_config_level(const char *name, const char **levels, int num_levels, struct lpm_stats *parent, Loading @@ -24,8 +47,8 @@ struct lpm_stats *lpm_stats_config_level(const char *name, void lpm_stats_cluster_enter(struct lpm_stats *stats, uint32_t index); void lpm_stats_cluster_exit(struct lpm_stats *stats, uint32_t index, bool success); void lpm_stats_cpu_enter(uint32_t index); void lpm_stats_cpu_exit(uint32_t index, bool success); void lpm_stats_cpu_enter(uint32_t index, uint64_t time); void lpm_stats_cpu_exit(uint32_t index, uint64_t time, bool success); void lpm_stats_suspend_enter(void); void lpm_stats_suspend_exit(void); #else Loading @@ -48,12 +71,13 @@ static inline void lpm_stats_cluster_exit(struct lpm_stats *stats, return; } static inline void lpm_stats_cpu_enter(uint32_t index) static inline void lpm_stats_cpu_enter(uint32_t index, uint64_t time) { return; } static inline void lpm_stats_cpu_exit(uint32_t index, bool success) static inline void lpm_stats_cpu_exit(uint32_t index, bool success, uint64_t time) { return; } Loading Loading
drivers/cpuidle/lpm-levels.c +32 −15 Original line number Diff line number Diff line Loading @@ -92,9 +92,11 @@ static int lpm_cpu_callback(struct notifier_block *cpu_nb, unsigned long action, void *hcpu); static void cluster_unprepare(struct lpm_cluster *cluster, const struct cpumask *cpu, int child_idx, bool from_idle); const struct cpumask *cpu, int child_idx, bool from_idle, int64_t time); static void cluster_prepare(struct lpm_cluster *cluster, const struct cpumask *cpu, int child_idx, bool from_idle); const struct cpumask *cpu, int child_idx, bool from_idle, int64_t time); static struct notifier_block __refdata lpm_cpu_nblk = { .notifier_call = lpm_cpu_callback, Loading Loading @@ -184,11 +186,11 @@ static int lpm_cpu_callback(struct notifier_block *cpu_nb, switch (action & ~CPU_TASKS_FROZEN) { case CPU_DYING: cluster_prepare(cluster, get_cpu_mask((unsigned int) cpu), NR_LPM_LEVELS, false); NR_LPM_LEVELS, false, 0); break; case CPU_STARTING: cluster_unprepare(cluster, get_cpu_mask((unsigned int) cpu), NR_LPM_LEVELS, false); NR_LPM_LEVELS, false, 0); break; case CPU_ONLINE: smp_call_function_single(cpu, setup_broadcast_timer, Loading Loading @@ -575,7 +577,8 @@ failed_set_mode: } static void cluster_prepare(struct lpm_cluster *cluster, const struct cpumask *cpu, int child_idx, bool from_idle) const struct cpumask *cpu, int child_idx, bool from_idle, int64_t start_time) { int i; Loading Loading @@ -616,15 +619,21 @@ static void cluster_prepare(struct lpm_cluster *cluster, if (cluster_configure(cluster, i, from_idle)) goto failed; cluster->stats->sleep_time = start_time; cluster_prepare(cluster->parent, &cluster->num_children_in_sync, i, from_idle); from_idle, start_time); spin_unlock(&cluster->sync_lock); return; failed: spin_unlock(&cluster->sync_lock); cluster->stats->sleep_time = 0; return; } static void cluster_unprepare(struct lpm_cluster *cluster, const struct cpumask *cpu, int child_idx, bool from_idle) const struct cpumask *cpu, int child_idx, bool from_idle, int64_t end_time) { struct lpm_cluster_level *level; bool first_cpu; Loading Loading @@ -654,6 +663,9 @@ static void cluster_unprepare(struct lpm_cluster *cluster, if (!first_cpu || cluster->last_level == cluster->default_level) goto unlock_return; if (cluster->stats->sleep_time) cluster->stats->sleep_time = end_time - cluster->stats->sleep_time; lpm_stats_cluster_exit(cluster->stats, cluster->last_level, true); level = &cluster->levels[cluster->last_level]; Loading Loading @@ -690,7 +702,7 @@ static void cluster_unprepare(struct lpm_cluster *cluster, cluster_notify(cluster, &cluster->levels[last_level], false); cluster_unprepare(cluster->parent, &cluster->child_cpus, last_level, from_idle); last_level, from_idle, end_time); unlock_return: spin_unlock(&cluster->sync_lock); } Loading Loading @@ -875,13 +887,13 @@ static int lpm_cpuidle_enter(struct cpuidle_device *dev, pwr_params->energy_overhead, pwr_params->latency_us); cpu_prepare(cluster, idx, true); cluster_prepare(cluster, cpumask, idx, true); cluster_prepare(cluster, cpumask, idx, true, ktime_to_ns(ktime_get())); if (need_resched() || (idx < 0)) goto exit; trace_cpu_idle_enter(idx); lpm_stats_cpu_enter(idx); lpm_stats_cpu_enter(idx, start_time); if (!use_psci) { if (idx > 0) Loading @@ -898,8 +910,10 @@ static int lpm_cpuidle_enter(struct cpuidle_device *dev, } exit: lpm_stats_cpu_exit(idx, success); cluster_unprepare(cluster, cpumask, idx, true); end_time = ktime_to_ns(ktime_get()); lpm_stats_cpu_exit(idx, end_time, success); cluster_unprepare(cluster, cpumask, idx, true, end_time); cpu_unprepare(cluster, idx, true); sched_set_cpu_cstate(smp_processor_id(), 0, 0, 0); Loading Loading @@ -1111,6 +1125,7 @@ static int lpm_suspend_enter(suspend_state_t state) struct lpm_cpu *lpm_cpu = cluster->cpu; const struct cpumask *cpumask = get_cpu_mask(cpu); int idx; int64_t time = ktime_to_ns(ktime_get()); for (idx = lpm_cpu->nlevels - 1; idx >= 0; idx--) { Loading @@ -1122,7 +1137,7 @@ static int lpm_suspend_enter(suspend_state_t state) return 0; } cpu_prepare(cluster, idx, false); cluster_prepare(cluster, cpumask, idx, false); cluster_prepare(cluster, cpumask, idx, false, time); if (idx > 0) update_debug_pc_event(CPU_ENTER, idx, 0xdeaffeed, 0xdeaffeed, false); Loading @@ -1143,7 +1158,9 @@ static int lpm_suspend_enter(suspend_state_t state) if (idx > 0) update_debug_pc_event(CPU_EXIT, idx, true, 0xdeaffeed, false); cluster_unprepare(cluster, cpumask, idx, false); time = ktime_to_ns(ktime_get()); cluster_unprepare(cluster, cpumask, idx, false, time); cpu_unprepare(cluster, idx, false); return 0; } Loading Loading @@ -1354,7 +1371,7 @@ void lpm_cpu_hotplug_enter(unsigned int cpu) return; BUG_ON(idx < 0); cluster_prepare(cluster, get_cpu_mask(cpu), idx, false); cluster_prepare(cluster, get_cpu_mask(cpu), idx, false, 0); } msm_cpu_pm_enter_sleep(mode, false); Loading
drivers/power/qcom/lpm-stats.c +10 −30 Original line number Diff line number Diff line /* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -24,6 +24,7 @@ #include <linux/suspend.h> #include <soc/qcom/spm.h> #include <soc/qcom/pm.h> #include <soc/qcom/lpm-stats.h> #define MAX_STR_LEN 256 const char *lpm_stats_reset = "reset"; Loading @@ -42,24 +43,6 @@ struct level_stats { uint64_t enter_time; }; struct lifo_stats { uint32_t last_in; uint32_t first_out; }; struct lpm_stats { char name[MAX_STR_LEN]; struct level_stats *time_stats; uint32_t num_levels; struct lifo_stats lifo; struct lpm_stats *parent; struct list_head sibling; struct list_head child; struct cpumask mask; struct dentry *directory; bool is_cpu; }; static struct level_stats suspend_time_stats; static DEFINE_PER_CPU_SHARED_ALIGNED(struct lpm_stats, cpu_stats); Loading Loading @@ -425,13 +408,9 @@ static inline void update_exit_stats(struct lpm_stats *stats, uint32_t index, uint64_t exit_time = 0; /* Update time stats only when exit is preceded by enter */ if (stats->time_stats[index].enter_time) { exit_time = sched_clock() - stats->time_stats[index].enter_time; exit_time = stats->sleep_time; update_level_stats(&stats->time_stats[index], exit_time, success); stats->time_stats[index].enter_time = 0; } } static int config_level(const char *name, const char **levels, Loading Loading @@ -679,8 +658,6 @@ void lpm_stats_cluster_enter(struct lpm_stats *stats, uint32_t index) if (IS_ERR_OR_NULL(stats)) return; stats->time_stats[index].enter_time = sched_clock(); update_last_in_stats(stats); } EXPORT_SYMBOL(lpm_stats_cluster_enter); Loading Loading @@ -717,14 +694,15 @@ EXPORT_SYMBOL(lpm_stats_cluster_exit); * Function to communicate the low power mode level that the cpu is * prepared to enter. */ void lpm_stats_cpu_enter(uint32_t index) void lpm_stats_cpu_enter(uint32_t index, uint64_t time) { struct lpm_stats *stats = &__get_cpu_var(cpu_stats); stats->sleep_time = time; if (!stats->time_stats) return; stats->time_stats[index].enter_time = sched_clock(); } EXPORT_SYMBOL(lpm_stats_cpu_enter); Loading @@ -736,13 +714,15 @@ EXPORT_SYMBOL(lpm_stats_cpu_enter); * * Function to communicate the low power mode level that the cpu exited. */ void lpm_stats_cpu_exit(uint32_t index, bool success) void lpm_stats_cpu_exit(uint32_t index, uint64_t time, bool success) { struct lpm_stats *stats = &__get_cpu_var(cpu_stats); if (!stats->time_stats) return; stats->sleep_time = time - stats->sleep_time; update_exit_stats(stats, index, success); } EXPORT_SYMBOL(lpm_stats_cpu_exit); Loading
include/soc/qcom/lpm-stats.h +29 −5 Original line number Diff line number Diff line /* * Copyright (c) 2014, The Linux Foundation. All rights reserved. * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -17,6 +17,29 @@ struct lpm_stats; #define MAX_STR_LEN 256 struct lifo_stats { uint32_t last_in; uint32_t first_out; }; struct lpm_stats { char name[MAX_STR_LEN]; struct level_stats *time_stats; uint32_t num_levels; struct lifo_stats lifo; struct lpm_stats *parent; struct list_head sibling; struct list_head child; struct cpumask mask; struct dentry *directory; int64_t sleep_time; bool is_cpu; }; #ifdef CONFIG_MSM_IDLE_STATS struct lpm_stats *lpm_stats_config_level(const char *name, const char **levels, int num_levels, struct lpm_stats *parent, Loading @@ -24,8 +47,8 @@ struct lpm_stats *lpm_stats_config_level(const char *name, void lpm_stats_cluster_enter(struct lpm_stats *stats, uint32_t index); void lpm_stats_cluster_exit(struct lpm_stats *stats, uint32_t index, bool success); void lpm_stats_cpu_enter(uint32_t index); void lpm_stats_cpu_exit(uint32_t index, bool success); void lpm_stats_cpu_enter(uint32_t index, uint64_t time); void lpm_stats_cpu_exit(uint32_t index, uint64_t time, bool success); void lpm_stats_suspend_enter(void); void lpm_stats_suspend_exit(void); #else Loading @@ -48,12 +71,13 @@ static inline void lpm_stats_cluster_exit(struct lpm_stats *stats, return; } static inline void lpm_stats_cpu_enter(uint32_t index) static inline void lpm_stats_cpu_enter(uint32_t index, uint64_t time) { return; } static inline void lpm_stats_cpu_exit(uint32_t index, bool success) static inline void lpm_stats_cpu_exit(uint32_t index, bool success, uint64_t time) { return; } Loading