Loading arch/arm/mach-msm/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -584,6 +584,7 @@ config MSM7X00A_IDLE_SPIN_TIME menuconfig MSM_IDLE_STATS bool "Collect idle statistics" depends on MSM_PM8X60 default y help Collect idle statistics and export them in proc/msm_pm_stats. Loading arch/arm/mach-msm/pm-8x60.c +12 −1 Original line number Diff line number Diff line Loading @@ -1002,6 +1002,7 @@ enum msm_pm_sleep_mode msm_pm_idle_enter(struct cpuidle_device *dev, int ret = -ENODEV; int notify_rpm = false; bool timer_halted = false; uint32_t l2_stat_id = MSM_SPM_L2_MODE_LAST; sleep_mode = msm_pm_idle_prepare(dev, drv, index, &msm_pm_idle_rs_limits, states); Loading Loading @@ -1033,6 +1034,8 @@ enum msm_pm_sleep_mode msm_pm_idle_enter(struct cpuidle_device *dev, if (ret) goto cpuidle_enter_bail; l2_stat_id = *(uint32_t *)msm_pm_idle_rs_limits; switch (sleep_mode) { case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT: msm_pm_swfi(); Loading Loading @@ -1083,6 +1086,9 @@ enum msm_pm_sleep_mode msm_pm_idle_enter(struct cpuidle_device *dev, notify_rpm, collapsed); time = ktime_to_ns(ktime_get()) - time; msm_pm_l2_add_stat(l2_stat_id, time); msm_pm_ftrace_lpm_exit(smp_processor_id(), sleep_mode, collapsed); if (exit_stat >= 0) msm_pm_add_stat(exit_stat, time); Loading Loading @@ -1188,6 +1194,7 @@ EXPORT_SYMBOL(msm_pm_enable_retention); static int64_t suspend_time, suspend_period; static int collapsed; static int suspend_power_collapsed; static uint32_t l2_stat_id = MSM_SPM_L2_MODE_LAST; static int msm_pm_enter(suspend_state_t state) { Loading Loading @@ -1237,6 +1244,8 @@ static int msm_pm_enter(suspend_state_t state) rs_limits = pm_sleep_ops.lowest_limits(false, MSM_PM_SLEEP_MODE_POWER_COLLAPSE, &time_param, &power); l2_stat_id = *(uint32_t *)rs_limits; if (rs_limits) { if (pm_sleep_ops.enter_sleep) ret = pm_sleep_ops.enter_sleep( Loading Loading @@ -1295,8 +1304,10 @@ static void msm_suspend_wake(void) if (suspend_power_collapsed) { suspend_time = msm_pm_timer_exit_suspend(suspend_time, suspend_period); if (collapsed) if (collapsed) { msm_pm_add_stat(MSM_PM_STAT_SUSPEND, suspend_time); msm_pm_l2_add_stat(l2_stat_id, suspend_time); } else msm_pm_add_stat(MSM_PM_STAT_FAILED_SUSPEND, suspend_time); Loading arch/arm/mach-msm/pm-data.c +28 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,13 @@ #include "pm.h" struct msm_pm_platform_data msm_pm_sleep_modes[] = { [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND)] = { .idle_supported = 0, .suspend_supported = 1, .idle_enabled = 0, .suspend_enabled = 1, }, [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = { .idle_supported = 1, .suspend_supported = 1, Loading Loading @@ -49,6 +56,13 @@ struct msm_pm_platform_data msm_pm_sleep_modes[] = { .suspend_enabled = 1, }, [MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND)] = { .idle_supported = 0, .suspend_supported = 0, .idle_enabled = 0, .suspend_enabled = 0, }, [MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = { .idle_supported = 1, .suspend_supported = 1, Loading @@ -70,6 +84,13 @@ struct msm_pm_platform_data msm_pm_sleep_modes[] = { .suspend_enabled = 0, }, [MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND)] = { .idle_supported = 0, .suspend_supported = 0, .idle_enabled = 0, .suspend_enabled = 0, }, [MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = { .idle_supported = 0, .suspend_supported = 1, Loading Loading @@ -98,6 +119,13 @@ struct msm_pm_platform_data msm_pm_sleep_modes[] = { .suspend_enabled = 0, }, [MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND)] = { .idle_supported = 0, .suspend_supported = 0, .idle_enabled = 0, .suspend_enabled = 0, }, [MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = { .idle_supported = 0, .suspend_supported = 1, Loading arch/arm/mach-msm/pm-stats.c +480 −1 Original line number Diff line number Diff line Loading @@ -18,8 +18,27 @@ #include <linux/uaccess.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/debugfs.h> #include "pm.h" #include "spm.h" static struct dentry *msm_pm_dbg_root; static struct dentry *msm_pm_dentry[NR_CPUS]; struct pm_debugfs_private_data { char *buf; struct msm_pm_time_stats *stats; unsigned int cpu; unsigned int stats_id; }; static DEFINE_PER_CPU_SHARED_ALIGNED( struct pm_debugfs_private_data, msm_pm_debugfs_private_data); static DEFINE_PER_CPU( struct pm_debugfs_private_data, msm_pm_cpu_states[MSM_PM_STAT_COUNT]); static struct pm_debugfs_private_data all_stats_private_data; struct msm_pm_time_stats { const char *name; Loading @@ -30,15 +49,35 @@ struct msm_pm_time_stats { int count; int64_t total_time; bool enabled; int sleep_mode; }; struct msm_pm_cpu_time_stats { struct msm_pm_time_stats stats[MSM_PM_STAT_COUNT]; }; struct pm_l2_debugfs_private_data { char *buf; unsigned int stats_id; }; struct _msm_pm_l2_time_stats { struct msm_pm_time_stats stats[MSM_SPM_L2_MODE_LAST]; }; static DEFINE_MUTEX(msm_pm_stats_mutex); static DEFINE_SPINLOCK(msm_pm_stats_lock); static DEFINE_PER_CPU_SHARED_ALIGNED( struct msm_pm_cpu_time_stats, msm_pm_stats); static DEFINE_SPINLOCK(msm_pm_l2_stats_lock); static struct _msm_pm_l2_time_stats msm_pm_l2_time_stats; static struct pm_l2_debugfs_private_data l2_stats_private_data[] = { {NULL, MSM_SPM_L2_MODE_DISABLED}, {NULL, MSM_SPM_L2_MODE_RETENTION}, {NULL, MSM_SPM_L2_MODE_GDHS}, {NULL, MSM_SPM_L2_MODE_PC_NO_RPM}, {NULL, MSM_SPM_L2_MODE_POWER_COLLAPSE}, {NULL, MSM_SPM_L2_MODE_LAST}, }; /* * Add the given time data to the statistics collection. Loading Loading @@ -83,6 +122,45 @@ add_bail: spin_unlock_irqrestore(&msm_pm_stats_lock, flags); } void msm_pm_l2_add_stat(uint32_t id, int64_t t) { unsigned long flags; struct msm_pm_time_stats *stats; int64_t bt; int i; if (id == MSM_SPM_L2_MODE_DISABLED || id >= MSM_SPM_L2_MODE_LAST) return; spin_lock_irqsave(&msm_pm_l2_stats_lock, flags); stats = msm_pm_l2_time_stats.stats; stats[id].total_time += t; stats[id].count++; bt = t; do_div(bt, stats[id].first_bucket_time); if (bt < 1ULL << (CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT * (CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1))) i = DIV_ROUND_UP(fls((uint32_t)bt), CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT); else i = CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1; if (i >= CONFIG_MSM_IDLE_STATS_BUCKET_COUNT) i = CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1; stats[id].bucket[i]++; if (t < stats[id].min_time[i] || !stats[id].max_time[i]) stats[id].min_time[i] = t; if (t > stats[id].max_time[i]) stats[id].max_time[i] = t; spin_unlock_irqrestore(&msm_pm_l2_stats_lock, flags); } /* * Write out the power management statistics. */ Loading Loading @@ -197,7 +275,344 @@ write_proc_failed: return ret; } #undef MSM_PM_STATS_RESET static size_t read_cpu_state_stats(struct seq_file *m, struct pm_debugfs_private_data *private_data) { struct msm_pm_time_stats *stats = NULL; int i; int64_t bucket_time; int64_t s; uint32_t ns; unsigned int id; unsigned int cpu = 0; int bucket_count = CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1; int bucket_shift = CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT; unsigned long flags; if (private_data == NULL) return 0; stats = private_data->stats; cpu = private_data->cpu; id = private_data->stats_id; spin_lock_irqsave(&msm_pm_stats_lock, flags); s = stats[id].total_time; ns = do_div(s, NSEC_PER_SEC); seq_printf(m, "[cpu %u] %s:\n" " count: %7d\n" " total_time: %lld.%09u\n", cpu, stats[id].name, stats[id].count, s, ns); bucket_time = stats[id].first_bucket_time; for (i = 0; i < bucket_count; i++) { s = bucket_time; ns = do_div(s, NSEC_PER_SEC); seq_printf(m, " <%6lld.%09u: %7d (%lld-%lld)\n", s, ns, stats[id].bucket[i], stats[id].min_time[i], stats[id].max_time[i]); bucket_time <<= bucket_shift; } seq_printf(m, " >=%6lld.%09u: %7d (%lld-%lld)\n", s, ns, stats[id].bucket[i], stats[id].min_time[i], stats[id].max_time[i]); spin_unlock_irqrestore(&msm_pm_stats_lock, flags); return 0; } static size_t read_cpu_stats(struct seq_file *m, struct pm_debugfs_private_data *private_data, unsigned int cpu) { struct msm_pm_time_stats *stats = NULL; int i; int64_t bucket_time; int64_t s; uint32_t ns; unsigned int id; int bucket_count = CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1; int bucket_shift = CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT; unsigned long flags; if (private_data == NULL) return 0; stats = private_data->stats; spin_lock_irqsave(&msm_pm_stats_lock, flags); for (id = 0; id < MSM_PM_STAT_COUNT; id++) { int mode, idx; if (!stats[id].enabled) continue; mode = stats[id].sleep_mode; idx = MSM_PM_MODE(cpu, mode); if ((!msm_pm_sleep_modes[idx].idle_supported) && (!msm_pm_sleep_modes[idx].suspend_supported)) continue; s = stats[id].total_time; ns = do_div(s, NSEC_PER_SEC); seq_printf(m, "[cpu %u] %s:\n" " count: %7d\n" " total_time: %lld.%09u\n", cpu, stats[id].name, stats[id].count, s, ns); bucket_time = stats[id].first_bucket_time; for (i = 0; i < bucket_count; i++) { s = bucket_time; ns = do_div(s, NSEC_PER_SEC); seq_printf(m, " <%6lld.%09u: %7d (%lld-%lld)\n", s, ns, stats[id].bucket[i], stats[id].min_time[i], stats[id].max_time[i]); bucket_time <<= bucket_shift; } seq_printf(m, " >=%6lld.%09u: %7d (%lld-%lld)\n", s, ns, stats[id].bucket[i], stats[id].min_time[i], stats[id].max_time[i]); } spin_unlock_irqrestore(&msm_pm_stats_lock, flags); return 0; } static int msm_pm_stat_file_show(struct seq_file *m, void *v) { unsigned int cpu; static struct pm_debugfs_private_data *private_data; enum msm_pm_time_stats_id stats_id = MSM_PM_STAT_COUNT; if (!m->private) return 0; private_data = m->private; if (num_possible_cpus() == private_data->cpu) { /* statistics of all the cpus to be printed */ unsigned int i; for (i = 0; i < num_possible_cpus(); i++) { private_data = &per_cpu(msm_pm_debugfs_private_data, i); read_cpu_stats(m, private_data, i); } } else { /* only current cpu statistics has to be printed */ cpu = private_data->cpu; stats_id = private_data->stats_id; if (private_data->stats_id == MSM_PM_STAT_COUNT) { /* Read all the status for the CPU */ read_cpu_stats(m, private_data, cpu); } else { if (private_data == NULL) return 0; read_cpu_state_stats(m, private_data); } } return 0; } static int msm_pm_stat_file_open(struct inode *inode, struct file *file) { return single_open(file, msm_pm_stat_file_show, inode->i_private); } static const struct file_operations msm_pm_stat_fops = { .owner = THIS_MODULE, .open = msm_pm_stat_file_open, .read = seq_read, .release = single_release, .llseek = no_llseek, }; static int msm_pm_l2_stat_file_show(struct seq_file *m, void *v) { struct msm_pm_time_stats *stats = NULL; int i; int64_t bucket_time; int64_t s; uint32_t ns; unsigned int id; static struct pm_l2_debugfs_private_data *private_data; if (!m->private) return 0; private_data = m->private; stats = msm_pm_l2_time_stats.stats; if (private_data->stats_id == MSM_SPM_L2_MODE_LAST) { /* All stats print */ for (id = 1; id < MSM_SPM_L2_MODE_LAST; id++) { s = stats[id].total_time; ns = do_div(s, NSEC_PER_SEC); seq_printf(m, "[L2] %s:\n" " count: %7d\n" " total_time: %lld.%09u\n", stats[id].name, stats[id].count, s, ns); bucket_time = stats[id].first_bucket_time; for (i = 0; i < CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1; i++) { s = bucket_time; ns = do_div(s, NSEC_PER_SEC); seq_printf(m, " <%6lld.%09u: %7d (%lld-%lld)\n", s, ns, stats[id].bucket[i], stats[id].min_time[i], stats[id].max_time[i]); bucket_time <<= CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT; } seq_printf(m, ">=%6lld.%09u:%7d (%llid-%lld)\n", s, ns, stats[id].bucket[i], stats[id].min_time[i], stats[id].max_time[i]); } } else { /* individual status print */ id = private_data->stats_id; s = stats[id].total_time; ns = do_div(s, NSEC_PER_SEC); seq_printf(m, "[L2] %s:\n" " count: %7d\n" " total_time: %lld.%09u\n", stats[id].name, stats[id].count, s, ns); bucket_time = stats[id].first_bucket_time; for (i = 0; i < CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1; i++) { s = bucket_time; ns = do_div(s, NSEC_PER_SEC); seq_printf(m, " <%6lld.%09u: %7d (%lld-%lld)\n", s, ns, stats[id].bucket[i], stats[id].min_time[i], stats[id].max_time[i]); bucket_time <<= CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT; } seq_printf(m, ">=%6lld.%09u:%7d (%llid-%lld)\n", s, ns, stats[id].bucket[i], stats[id].min_time[i], stats[id].max_time[i]); } return 0; } static int msm_pm_l2_stat_file_open(struct inode *inode, struct file *file) { return single_open(file, msm_pm_l2_stat_file_show, inode->i_private); } static const struct file_operations msm_pm_l2_stat_fops = { .owner = THIS_MODULE, .open = msm_pm_l2_stat_file_open, .read = seq_read, .release = single_release, .llseek = no_llseek, }; static bool msm_pm_debugfs_create_l2(void) { struct msm_pm_time_stats *stats = msm_pm_l2_time_stats.stats; struct dentry *msm_pm_l2_root; uint32_t stat_id; msm_pm_l2_root = debugfs_create_dir("l2", msm_pm_dbg_root); if (!msm_pm_l2_root) return false; stats[MSM_SPM_L2_MODE_GDHS].name = "GDHS"; stats[MSM_SPM_L2_MODE_GDHS].first_bucket_time = CONFIG_MSM_IDLE_STATS_FIRST_BUCKET; stats[MSM_SPM_L2_MODE_RETENTION].name = "Retention"; stats[MSM_SPM_L2_MODE_RETENTION].first_bucket_time = CONFIG_MSM_IDLE_STATS_FIRST_BUCKET; stats[MSM_SPM_L2_MODE_PC_NO_RPM].name = "No RPM"; stats[MSM_SPM_L2_MODE_PC_NO_RPM].first_bucket_time = CONFIG_MSM_IDLE_STATS_FIRST_BUCKET; stats[MSM_SPM_L2_MODE_POWER_COLLAPSE].name = "PC"; stats[MSM_SPM_L2_MODE_POWER_COLLAPSE].first_bucket_time = CONFIG_MSM_SUSPEND_STATS_FIRST_BUCKET; for (stat_id = 1; stat_id < MSM_SPM_L2_MODE_LAST; stat_id++) { if (!debugfs_create_file( stats[stat_id].name, S_IRUGO, msm_pm_l2_root, (void *)&l2_stats_private_data[stat_id], &msm_pm_l2_stat_fops)) { goto l2_err; } } stat_id = MSM_SPM_L2_MODE_LAST; if (!debugfs_create_file("stats", S_IRUGO, msm_pm_l2_root, (void *)&l2_stats_private_data[stat_id], &msm_pm_l2_stat_fops)) { goto l2_err; } return true; l2_err: debugfs_remove(msm_pm_l2_root); return false; } static bool msm_pm_debugfs_create_root(void) { bool ret = false; msm_pm_dbg_root = debugfs_create_dir("msm_pm_stats", NULL); if (!msm_pm_dbg_root) goto root_error; /* create over all stats file */ all_stats_private_data.cpu = num_possible_cpus(); all_stats_private_data.stats_id = MSM_PM_STAT_COUNT; if (!debugfs_create_file("stats", S_IRUGO, msm_pm_dbg_root, &all_stats_private_data, &msm_pm_stat_fops)) { debugfs_remove(msm_pm_dbg_root); goto root_error; } ret = true; root_error: return ret; } static int msm_pm_stats_open(struct inode *inode, struct file *file) { return single_open(file, msm_pm_stats_show, NULL); Loading @@ -216,11 +631,23 @@ void msm_pm_add_stats(enum msm_pm_time_stats_id *enable_stats, int size) unsigned int cpu; struct proc_dir_entry *d_entry; int i = 0; char cpu_name[8]; bool root_avl = false; root_avl = msm_pm_debugfs_create_root(); if (root_avl) { if (!msm_pm_debugfs_create_l2()) pr_err(" L2 debugfs create error\n"); } for_each_possible_cpu(cpu) { struct msm_pm_time_stats *stats = per_cpu(msm_pm_stats, cpu).stats; struct pm_debugfs_private_data *private_data = &per_cpu(msm_pm_debugfs_private_data, cpu); private_data->stats = stats; stats[MSM_PM_STAT_REQUESTED_IDLE].name = "idle-request"; stats[MSM_PM_STAT_REQUESTED_IDLE].first_bucket_time = CONFIG_MSM_IDLE_STATS_FIRST_BUCKET; Loading @@ -233,14 +660,21 @@ void msm_pm_add_stats(enum msm_pm_time_stats_id *enable_stats, int size) stats[MSM_PM_STAT_IDLE_WFI].first_bucket_time = CONFIG_MSM_IDLE_STATS_FIRST_BUCKET; stats[MSM_PM_STAT_IDLE_WFI].sleep_mode = MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT; stats[MSM_PM_STAT_RETENTION].name = "retention"; stats[MSM_PM_STAT_RETENTION].first_bucket_time = CONFIG_MSM_IDLE_STATS_FIRST_BUCKET; stats[MSM_PM_STAT_RETENTION].sleep_mode = MSM_PM_SLEEP_MODE_RETENTION; stats[MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE].name = "idle-standalone-power-collapse"; stats[MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE]. first_bucket_time = CONFIG_MSM_IDLE_STATS_FIRST_BUCKET; stats[MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE].sleep_mode = MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE; stats[MSM_PM_STAT_IDLE_FAILED_STANDALONE_POWER_COLLAPSE].name = "idle-failed-standalone-power-collapse"; Loading @@ -252,6 +686,8 @@ void msm_pm_add_stats(enum msm_pm_time_stats_id *enable_stats, int size) "idle-power-collapse"; stats[MSM_PM_STAT_IDLE_POWER_COLLAPSE].first_bucket_time = CONFIG_MSM_IDLE_STATS_FIRST_BUCKET; stats[MSM_PM_STAT_IDLE_POWER_COLLAPSE].sleep_mode = MSM_PM_SLEEP_MODE_POWER_COLLAPSE; stats[MSM_PM_STAT_IDLE_FAILED_POWER_COLLAPSE].name = "idle-failed-power-collapse"; Loading @@ -262,6 +698,8 @@ void msm_pm_add_stats(enum msm_pm_time_stats_id *enable_stats, int size) stats[MSM_PM_STAT_SUSPEND].name = "suspend"; stats[MSM_PM_STAT_SUSPEND].first_bucket_time = CONFIG_MSM_SUSPEND_STATS_FIRST_BUCKET; stats[MSM_PM_STAT_SUSPEND].sleep_mode = MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND; stats[MSM_PM_STAT_FAILED_SUSPEND].name = "failed-suspend"; stats[MSM_PM_STAT_FAILED_SUSPEND].first_bucket_time = Loading @@ -274,6 +712,47 @@ void msm_pm_add_stats(enum msm_pm_time_stats_id *enable_stats, int size) for (i = 0; i < size; i++) stats[enable_stats[i]].enabled = true; if (root_avl) { struct dentry *msm_pm_dbg_core; /* create cpu directory */ snprintf(cpu_name, sizeof(cpu_name), "cpu%u", cpu); msm_pm_dbg_core = debugfs_create_dir(cpu_name, msm_pm_dbg_root); if (!msm_pm_dbg_core) continue; /* create per cpu stats file */ private_data->cpu = cpu; private_data->stats_id = MSM_PM_STAT_COUNT; msm_pm_dentry[cpu] = debugfs_create_file("stats", S_IRUGO, msm_pm_dbg_core, private_data, &msm_pm_stat_fops); if (msm_pm_dentry[cpu]) { /* Create files related to individual states */ int id = 0; struct dentry *handle; struct pm_debugfs_private_data *msm_pm_states_data; for (id = 0; id < MSM_PM_STAT_COUNT; id++) { if (stats[id].enabled != true) continue; msm_pm_states_data = &per_cpu(msm_pm_cpu_states[id], cpu); msm_pm_states_data->cpu = cpu; msm_pm_states_data->stats_id = id; msm_pm_states_data->stats = stats; handle = debugfs_create_file( stats[id].name, S_IRUGO, msm_pm_dbg_core, msm_pm_states_data, &msm_pm_stat_fops); } } } } d_entry = proc_create_data("msm_pm_stats", S_IRUGO | S_IWUSR | S_IWGRP, Loading arch/arm/mach-msm/pm.h +2 −0 Original line number Diff line number Diff line Loading @@ -182,10 +182,12 @@ enum msm_pm_time_stats_id { #ifdef CONFIG_MSM_IDLE_STATS void msm_pm_add_stats(enum msm_pm_time_stats_id *enable_stats, int size); void msm_pm_add_stat(enum msm_pm_time_stats_id id, int64_t t); void msm_pm_l2_add_stat(uint32_t id, int64_t t); #else static inline void msm_pm_add_stats(enum msm_pm_time_stats_id *enable_stats, int size) {} static inline void msm_pm_add_stat(enum msm_pm_time_stats_id id, int64_t t) {} static inline void msm_pm_l2_add_stat(uint32_t id, int64_t t) {} #endif void msm_pm_set_cpr_ops(struct msm_pm_cpr_ops *ops); Loading Loading
arch/arm/mach-msm/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -584,6 +584,7 @@ config MSM7X00A_IDLE_SPIN_TIME menuconfig MSM_IDLE_STATS bool "Collect idle statistics" depends on MSM_PM8X60 default y help Collect idle statistics and export them in proc/msm_pm_stats. Loading
arch/arm/mach-msm/pm-8x60.c +12 −1 Original line number Diff line number Diff line Loading @@ -1002,6 +1002,7 @@ enum msm_pm_sleep_mode msm_pm_idle_enter(struct cpuidle_device *dev, int ret = -ENODEV; int notify_rpm = false; bool timer_halted = false; uint32_t l2_stat_id = MSM_SPM_L2_MODE_LAST; sleep_mode = msm_pm_idle_prepare(dev, drv, index, &msm_pm_idle_rs_limits, states); Loading Loading @@ -1033,6 +1034,8 @@ enum msm_pm_sleep_mode msm_pm_idle_enter(struct cpuidle_device *dev, if (ret) goto cpuidle_enter_bail; l2_stat_id = *(uint32_t *)msm_pm_idle_rs_limits; switch (sleep_mode) { case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT: msm_pm_swfi(); Loading Loading @@ -1083,6 +1086,9 @@ enum msm_pm_sleep_mode msm_pm_idle_enter(struct cpuidle_device *dev, notify_rpm, collapsed); time = ktime_to_ns(ktime_get()) - time; msm_pm_l2_add_stat(l2_stat_id, time); msm_pm_ftrace_lpm_exit(smp_processor_id(), sleep_mode, collapsed); if (exit_stat >= 0) msm_pm_add_stat(exit_stat, time); Loading Loading @@ -1188,6 +1194,7 @@ EXPORT_SYMBOL(msm_pm_enable_retention); static int64_t suspend_time, suspend_period; static int collapsed; static int suspend_power_collapsed; static uint32_t l2_stat_id = MSM_SPM_L2_MODE_LAST; static int msm_pm_enter(suspend_state_t state) { Loading Loading @@ -1237,6 +1244,8 @@ static int msm_pm_enter(suspend_state_t state) rs_limits = pm_sleep_ops.lowest_limits(false, MSM_PM_SLEEP_MODE_POWER_COLLAPSE, &time_param, &power); l2_stat_id = *(uint32_t *)rs_limits; if (rs_limits) { if (pm_sleep_ops.enter_sleep) ret = pm_sleep_ops.enter_sleep( Loading Loading @@ -1295,8 +1304,10 @@ static void msm_suspend_wake(void) if (suspend_power_collapsed) { suspend_time = msm_pm_timer_exit_suspend(suspend_time, suspend_period); if (collapsed) if (collapsed) { msm_pm_add_stat(MSM_PM_STAT_SUSPEND, suspend_time); msm_pm_l2_add_stat(l2_stat_id, suspend_time); } else msm_pm_add_stat(MSM_PM_STAT_FAILED_SUSPEND, suspend_time); Loading
arch/arm/mach-msm/pm-data.c +28 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,13 @@ #include "pm.h" struct msm_pm_platform_data msm_pm_sleep_modes[] = { [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND)] = { .idle_supported = 0, .suspend_supported = 1, .idle_enabled = 0, .suspend_enabled = 1, }, [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = { .idle_supported = 1, .suspend_supported = 1, Loading Loading @@ -49,6 +56,13 @@ struct msm_pm_platform_data msm_pm_sleep_modes[] = { .suspend_enabled = 1, }, [MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND)] = { .idle_supported = 0, .suspend_supported = 0, .idle_enabled = 0, .suspend_enabled = 0, }, [MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = { .idle_supported = 1, .suspend_supported = 1, Loading @@ -70,6 +84,13 @@ struct msm_pm_platform_data msm_pm_sleep_modes[] = { .suspend_enabled = 0, }, [MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND)] = { .idle_supported = 0, .suspend_supported = 0, .idle_enabled = 0, .suspend_enabled = 0, }, [MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = { .idle_supported = 0, .suspend_supported = 1, Loading Loading @@ -98,6 +119,13 @@ struct msm_pm_platform_data msm_pm_sleep_modes[] = { .suspend_enabled = 0, }, [MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND)] = { .idle_supported = 0, .suspend_supported = 0, .idle_enabled = 0, .suspend_enabled = 0, }, [MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = { .idle_supported = 0, .suspend_supported = 1, Loading
arch/arm/mach-msm/pm-stats.c +480 −1 Original line number Diff line number Diff line Loading @@ -18,8 +18,27 @@ #include <linux/uaccess.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/debugfs.h> #include "pm.h" #include "spm.h" static struct dentry *msm_pm_dbg_root; static struct dentry *msm_pm_dentry[NR_CPUS]; struct pm_debugfs_private_data { char *buf; struct msm_pm_time_stats *stats; unsigned int cpu; unsigned int stats_id; }; static DEFINE_PER_CPU_SHARED_ALIGNED( struct pm_debugfs_private_data, msm_pm_debugfs_private_data); static DEFINE_PER_CPU( struct pm_debugfs_private_data, msm_pm_cpu_states[MSM_PM_STAT_COUNT]); static struct pm_debugfs_private_data all_stats_private_data; struct msm_pm_time_stats { const char *name; Loading @@ -30,15 +49,35 @@ struct msm_pm_time_stats { int count; int64_t total_time; bool enabled; int sleep_mode; }; struct msm_pm_cpu_time_stats { struct msm_pm_time_stats stats[MSM_PM_STAT_COUNT]; }; struct pm_l2_debugfs_private_data { char *buf; unsigned int stats_id; }; struct _msm_pm_l2_time_stats { struct msm_pm_time_stats stats[MSM_SPM_L2_MODE_LAST]; }; static DEFINE_MUTEX(msm_pm_stats_mutex); static DEFINE_SPINLOCK(msm_pm_stats_lock); static DEFINE_PER_CPU_SHARED_ALIGNED( struct msm_pm_cpu_time_stats, msm_pm_stats); static DEFINE_SPINLOCK(msm_pm_l2_stats_lock); static struct _msm_pm_l2_time_stats msm_pm_l2_time_stats; static struct pm_l2_debugfs_private_data l2_stats_private_data[] = { {NULL, MSM_SPM_L2_MODE_DISABLED}, {NULL, MSM_SPM_L2_MODE_RETENTION}, {NULL, MSM_SPM_L2_MODE_GDHS}, {NULL, MSM_SPM_L2_MODE_PC_NO_RPM}, {NULL, MSM_SPM_L2_MODE_POWER_COLLAPSE}, {NULL, MSM_SPM_L2_MODE_LAST}, }; /* * Add the given time data to the statistics collection. Loading Loading @@ -83,6 +122,45 @@ add_bail: spin_unlock_irqrestore(&msm_pm_stats_lock, flags); } void msm_pm_l2_add_stat(uint32_t id, int64_t t) { unsigned long flags; struct msm_pm_time_stats *stats; int64_t bt; int i; if (id == MSM_SPM_L2_MODE_DISABLED || id >= MSM_SPM_L2_MODE_LAST) return; spin_lock_irqsave(&msm_pm_l2_stats_lock, flags); stats = msm_pm_l2_time_stats.stats; stats[id].total_time += t; stats[id].count++; bt = t; do_div(bt, stats[id].first_bucket_time); if (bt < 1ULL << (CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT * (CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1))) i = DIV_ROUND_UP(fls((uint32_t)bt), CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT); else i = CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1; if (i >= CONFIG_MSM_IDLE_STATS_BUCKET_COUNT) i = CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1; stats[id].bucket[i]++; if (t < stats[id].min_time[i] || !stats[id].max_time[i]) stats[id].min_time[i] = t; if (t > stats[id].max_time[i]) stats[id].max_time[i] = t; spin_unlock_irqrestore(&msm_pm_l2_stats_lock, flags); } /* * Write out the power management statistics. */ Loading Loading @@ -197,7 +275,344 @@ write_proc_failed: return ret; } #undef MSM_PM_STATS_RESET static size_t read_cpu_state_stats(struct seq_file *m, struct pm_debugfs_private_data *private_data) { struct msm_pm_time_stats *stats = NULL; int i; int64_t bucket_time; int64_t s; uint32_t ns; unsigned int id; unsigned int cpu = 0; int bucket_count = CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1; int bucket_shift = CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT; unsigned long flags; if (private_data == NULL) return 0; stats = private_data->stats; cpu = private_data->cpu; id = private_data->stats_id; spin_lock_irqsave(&msm_pm_stats_lock, flags); s = stats[id].total_time; ns = do_div(s, NSEC_PER_SEC); seq_printf(m, "[cpu %u] %s:\n" " count: %7d\n" " total_time: %lld.%09u\n", cpu, stats[id].name, stats[id].count, s, ns); bucket_time = stats[id].first_bucket_time; for (i = 0; i < bucket_count; i++) { s = bucket_time; ns = do_div(s, NSEC_PER_SEC); seq_printf(m, " <%6lld.%09u: %7d (%lld-%lld)\n", s, ns, stats[id].bucket[i], stats[id].min_time[i], stats[id].max_time[i]); bucket_time <<= bucket_shift; } seq_printf(m, " >=%6lld.%09u: %7d (%lld-%lld)\n", s, ns, stats[id].bucket[i], stats[id].min_time[i], stats[id].max_time[i]); spin_unlock_irqrestore(&msm_pm_stats_lock, flags); return 0; } static size_t read_cpu_stats(struct seq_file *m, struct pm_debugfs_private_data *private_data, unsigned int cpu) { struct msm_pm_time_stats *stats = NULL; int i; int64_t bucket_time; int64_t s; uint32_t ns; unsigned int id; int bucket_count = CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1; int bucket_shift = CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT; unsigned long flags; if (private_data == NULL) return 0; stats = private_data->stats; spin_lock_irqsave(&msm_pm_stats_lock, flags); for (id = 0; id < MSM_PM_STAT_COUNT; id++) { int mode, idx; if (!stats[id].enabled) continue; mode = stats[id].sleep_mode; idx = MSM_PM_MODE(cpu, mode); if ((!msm_pm_sleep_modes[idx].idle_supported) && (!msm_pm_sleep_modes[idx].suspend_supported)) continue; s = stats[id].total_time; ns = do_div(s, NSEC_PER_SEC); seq_printf(m, "[cpu %u] %s:\n" " count: %7d\n" " total_time: %lld.%09u\n", cpu, stats[id].name, stats[id].count, s, ns); bucket_time = stats[id].first_bucket_time; for (i = 0; i < bucket_count; i++) { s = bucket_time; ns = do_div(s, NSEC_PER_SEC); seq_printf(m, " <%6lld.%09u: %7d (%lld-%lld)\n", s, ns, stats[id].bucket[i], stats[id].min_time[i], stats[id].max_time[i]); bucket_time <<= bucket_shift; } seq_printf(m, " >=%6lld.%09u: %7d (%lld-%lld)\n", s, ns, stats[id].bucket[i], stats[id].min_time[i], stats[id].max_time[i]); } spin_unlock_irqrestore(&msm_pm_stats_lock, flags); return 0; } static int msm_pm_stat_file_show(struct seq_file *m, void *v) { unsigned int cpu; static struct pm_debugfs_private_data *private_data; enum msm_pm_time_stats_id stats_id = MSM_PM_STAT_COUNT; if (!m->private) return 0; private_data = m->private; if (num_possible_cpus() == private_data->cpu) { /* statistics of all the cpus to be printed */ unsigned int i; for (i = 0; i < num_possible_cpus(); i++) { private_data = &per_cpu(msm_pm_debugfs_private_data, i); read_cpu_stats(m, private_data, i); } } else { /* only current cpu statistics has to be printed */ cpu = private_data->cpu; stats_id = private_data->stats_id; if (private_data->stats_id == MSM_PM_STAT_COUNT) { /* Read all the status for the CPU */ read_cpu_stats(m, private_data, cpu); } else { if (private_data == NULL) return 0; read_cpu_state_stats(m, private_data); } } return 0; } static int msm_pm_stat_file_open(struct inode *inode, struct file *file) { return single_open(file, msm_pm_stat_file_show, inode->i_private); } static const struct file_operations msm_pm_stat_fops = { .owner = THIS_MODULE, .open = msm_pm_stat_file_open, .read = seq_read, .release = single_release, .llseek = no_llseek, }; static int msm_pm_l2_stat_file_show(struct seq_file *m, void *v) { struct msm_pm_time_stats *stats = NULL; int i; int64_t bucket_time; int64_t s; uint32_t ns; unsigned int id; static struct pm_l2_debugfs_private_data *private_data; if (!m->private) return 0; private_data = m->private; stats = msm_pm_l2_time_stats.stats; if (private_data->stats_id == MSM_SPM_L2_MODE_LAST) { /* All stats print */ for (id = 1; id < MSM_SPM_L2_MODE_LAST; id++) { s = stats[id].total_time; ns = do_div(s, NSEC_PER_SEC); seq_printf(m, "[L2] %s:\n" " count: %7d\n" " total_time: %lld.%09u\n", stats[id].name, stats[id].count, s, ns); bucket_time = stats[id].first_bucket_time; for (i = 0; i < CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1; i++) { s = bucket_time; ns = do_div(s, NSEC_PER_SEC); seq_printf(m, " <%6lld.%09u: %7d (%lld-%lld)\n", s, ns, stats[id].bucket[i], stats[id].min_time[i], stats[id].max_time[i]); bucket_time <<= CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT; } seq_printf(m, ">=%6lld.%09u:%7d (%llid-%lld)\n", s, ns, stats[id].bucket[i], stats[id].min_time[i], stats[id].max_time[i]); } } else { /* individual status print */ id = private_data->stats_id; s = stats[id].total_time; ns = do_div(s, NSEC_PER_SEC); seq_printf(m, "[L2] %s:\n" " count: %7d\n" " total_time: %lld.%09u\n", stats[id].name, stats[id].count, s, ns); bucket_time = stats[id].first_bucket_time; for (i = 0; i < CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1; i++) { s = bucket_time; ns = do_div(s, NSEC_PER_SEC); seq_printf(m, " <%6lld.%09u: %7d (%lld-%lld)\n", s, ns, stats[id].bucket[i], stats[id].min_time[i], stats[id].max_time[i]); bucket_time <<= CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT; } seq_printf(m, ">=%6lld.%09u:%7d (%llid-%lld)\n", s, ns, stats[id].bucket[i], stats[id].min_time[i], stats[id].max_time[i]); } return 0; } static int msm_pm_l2_stat_file_open(struct inode *inode, struct file *file) { return single_open(file, msm_pm_l2_stat_file_show, inode->i_private); } static const struct file_operations msm_pm_l2_stat_fops = { .owner = THIS_MODULE, .open = msm_pm_l2_stat_file_open, .read = seq_read, .release = single_release, .llseek = no_llseek, }; static bool msm_pm_debugfs_create_l2(void) { struct msm_pm_time_stats *stats = msm_pm_l2_time_stats.stats; struct dentry *msm_pm_l2_root; uint32_t stat_id; msm_pm_l2_root = debugfs_create_dir("l2", msm_pm_dbg_root); if (!msm_pm_l2_root) return false; stats[MSM_SPM_L2_MODE_GDHS].name = "GDHS"; stats[MSM_SPM_L2_MODE_GDHS].first_bucket_time = CONFIG_MSM_IDLE_STATS_FIRST_BUCKET; stats[MSM_SPM_L2_MODE_RETENTION].name = "Retention"; stats[MSM_SPM_L2_MODE_RETENTION].first_bucket_time = CONFIG_MSM_IDLE_STATS_FIRST_BUCKET; stats[MSM_SPM_L2_MODE_PC_NO_RPM].name = "No RPM"; stats[MSM_SPM_L2_MODE_PC_NO_RPM].first_bucket_time = CONFIG_MSM_IDLE_STATS_FIRST_BUCKET; stats[MSM_SPM_L2_MODE_POWER_COLLAPSE].name = "PC"; stats[MSM_SPM_L2_MODE_POWER_COLLAPSE].first_bucket_time = CONFIG_MSM_SUSPEND_STATS_FIRST_BUCKET; for (stat_id = 1; stat_id < MSM_SPM_L2_MODE_LAST; stat_id++) { if (!debugfs_create_file( stats[stat_id].name, S_IRUGO, msm_pm_l2_root, (void *)&l2_stats_private_data[stat_id], &msm_pm_l2_stat_fops)) { goto l2_err; } } stat_id = MSM_SPM_L2_MODE_LAST; if (!debugfs_create_file("stats", S_IRUGO, msm_pm_l2_root, (void *)&l2_stats_private_data[stat_id], &msm_pm_l2_stat_fops)) { goto l2_err; } return true; l2_err: debugfs_remove(msm_pm_l2_root); return false; } static bool msm_pm_debugfs_create_root(void) { bool ret = false; msm_pm_dbg_root = debugfs_create_dir("msm_pm_stats", NULL); if (!msm_pm_dbg_root) goto root_error; /* create over all stats file */ all_stats_private_data.cpu = num_possible_cpus(); all_stats_private_data.stats_id = MSM_PM_STAT_COUNT; if (!debugfs_create_file("stats", S_IRUGO, msm_pm_dbg_root, &all_stats_private_data, &msm_pm_stat_fops)) { debugfs_remove(msm_pm_dbg_root); goto root_error; } ret = true; root_error: return ret; } static int msm_pm_stats_open(struct inode *inode, struct file *file) { return single_open(file, msm_pm_stats_show, NULL); Loading @@ -216,11 +631,23 @@ void msm_pm_add_stats(enum msm_pm_time_stats_id *enable_stats, int size) unsigned int cpu; struct proc_dir_entry *d_entry; int i = 0; char cpu_name[8]; bool root_avl = false; root_avl = msm_pm_debugfs_create_root(); if (root_avl) { if (!msm_pm_debugfs_create_l2()) pr_err(" L2 debugfs create error\n"); } for_each_possible_cpu(cpu) { struct msm_pm_time_stats *stats = per_cpu(msm_pm_stats, cpu).stats; struct pm_debugfs_private_data *private_data = &per_cpu(msm_pm_debugfs_private_data, cpu); private_data->stats = stats; stats[MSM_PM_STAT_REQUESTED_IDLE].name = "idle-request"; stats[MSM_PM_STAT_REQUESTED_IDLE].first_bucket_time = CONFIG_MSM_IDLE_STATS_FIRST_BUCKET; Loading @@ -233,14 +660,21 @@ void msm_pm_add_stats(enum msm_pm_time_stats_id *enable_stats, int size) stats[MSM_PM_STAT_IDLE_WFI].first_bucket_time = CONFIG_MSM_IDLE_STATS_FIRST_BUCKET; stats[MSM_PM_STAT_IDLE_WFI].sleep_mode = MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT; stats[MSM_PM_STAT_RETENTION].name = "retention"; stats[MSM_PM_STAT_RETENTION].first_bucket_time = CONFIG_MSM_IDLE_STATS_FIRST_BUCKET; stats[MSM_PM_STAT_RETENTION].sleep_mode = MSM_PM_SLEEP_MODE_RETENTION; stats[MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE].name = "idle-standalone-power-collapse"; stats[MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE]. first_bucket_time = CONFIG_MSM_IDLE_STATS_FIRST_BUCKET; stats[MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE].sleep_mode = MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE; stats[MSM_PM_STAT_IDLE_FAILED_STANDALONE_POWER_COLLAPSE].name = "idle-failed-standalone-power-collapse"; Loading @@ -252,6 +686,8 @@ void msm_pm_add_stats(enum msm_pm_time_stats_id *enable_stats, int size) "idle-power-collapse"; stats[MSM_PM_STAT_IDLE_POWER_COLLAPSE].first_bucket_time = CONFIG_MSM_IDLE_STATS_FIRST_BUCKET; stats[MSM_PM_STAT_IDLE_POWER_COLLAPSE].sleep_mode = MSM_PM_SLEEP_MODE_POWER_COLLAPSE; stats[MSM_PM_STAT_IDLE_FAILED_POWER_COLLAPSE].name = "idle-failed-power-collapse"; Loading @@ -262,6 +698,8 @@ void msm_pm_add_stats(enum msm_pm_time_stats_id *enable_stats, int size) stats[MSM_PM_STAT_SUSPEND].name = "suspend"; stats[MSM_PM_STAT_SUSPEND].first_bucket_time = CONFIG_MSM_SUSPEND_STATS_FIRST_BUCKET; stats[MSM_PM_STAT_SUSPEND].sleep_mode = MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND; stats[MSM_PM_STAT_FAILED_SUSPEND].name = "failed-suspend"; stats[MSM_PM_STAT_FAILED_SUSPEND].first_bucket_time = Loading @@ -274,6 +712,47 @@ void msm_pm_add_stats(enum msm_pm_time_stats_id *enable_stats, int size) for (i = 0; i < size; i++) stats[enable_stats[i]].enabled = true; if (root_avl) { struct dentry *msm_pm_dbg_core; /* create cpu directory */ snprintf(cpu_name, sizeof(cpu_name), "cpu%u", cpu); msm_pm_dbg_core = debugfs_create_dir(cpu_name, msm_pm_dbg_root); if (!msm_pm_dbg_core) continue; /* create per cpu stats file */ private_data->cpu = cpu; private_data->stats_id = MSM_PM_STAT_COUNT; msm_pm_dentry[cpu] = debugfs_create_file("stats", S_IRUGO, msm_pm_dbg_core, private_data, &msm_pm_stat_fops); if (msm_pm_dentry[cpu]) { /* Create files related to individual states */ int id = 0; struct dentry *handle; struct pm_debugfs_private_data *msm_pm_states_data; for (id = 0; id < MSM_PM_STAT_COUNT; id++) { if (stats[id].enabled != true) continue; msm_pm_states_data = &per_cpu(msm_pm_cpu_states[id], cpu); msm_pm_states_data->cpu = cpu; msm_pm_states_data->stats_id = id; msm_pm_states_data->stats = stats; handle = debugfs_create_file( stats[id].name, S_IRUGO, msm_pm_dbg_core, msm_pm_states_data, &msm_pm_stat_fops); } } } } d_entry = proc_create_data("msm_pm_stats", S_IRUGO | S_IWUSR | S_IWGRP, Loading
arch/arm/mach-msm/pm.h +2 −0 Original line number Diff line number Diff line Loading @@ -182,10 +182,12 @@ enum msm_pm_time_stats_id { #ifdef CONFIG_MSM_IDLE_STATS void msm_pm_add_stats(enum msm_pm_time_stats_id *enable_stats, int size); void msm_pm_add_stat(enum msm_pm_time_stats_id id, int64_t t); void msm_pm_l2_add_stat(uint32_t id, int64_t t); #else static inline void msm_pm_add_stats(enum msm_pm_time_stats_id *enable_stats, int size) {} static inline void msm_pm_add_stat(enum msm_pm_time_stats_id id, int64_t t) {} static inline void msm_pm_l2_add_stat(uint32_t id, int64_t t) {} #endif void msm_pm_set_cpr_ops(struct msm_pm_cpr_ops *ops); Loading