msm: pm2: Modify PM2 idle statistics maintanace functions
Currently pm2.c idle statistic functions doesn't have a support
for dual core targets. Modify idle statistic functions to know
about the number of CPU's it is running and print the idle
statistical(msm_pm_stats) data accordingly. This makes the code
simple in future where modem is the master and APPS is a multicore
(e.g. 8x25).
Change-Id: I713f7e2f88860486883f7fd122f67e5bf85d3d4d
Signed-off-by: Murali Nalajala <mnalajal@codeaurora.org>
diff --git a/arch/arm/mach-msm/pm2.c b/arch/arm/mach-msm/pm2.c
index 4cdd7ae..d1cd0a9 100644
--- a/arch/arm/mach-msm/pm2.c
+++ b/arch/arm/mach-msm/pm2.c
@@ -3,7 +3,7 @@
* MSM Power Management Routines
*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2012 Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -166,10 +166,20 @@
static struct msm_pm_platform_data *msm_pm_modes;
-static struct kobject *msm_pm_mode_kobjs[MSM_PM_SLEEP_MODE_NR];
-static struct attribute_group *msm_pm_mode_attr_group[MSM_PM_SLEEP_MODE_NR];
-static struct attribute **msm_pm_mode_attrs[MSM_PM_SLEEP_MODE_NR];
-static struct kobj_attribute *msm_pm_mode_kobj_attrs[MSM_PM_SLEEP_MODE_NR];
+struct msm_pm_kobj_attribute {
+ unsigned int cpu;
+ struct kobj_attribute ka;
+};
+
+#define GET_CPU_OF_ATTR(attr) \
+ (container_of(attr, struct msm_pm_kobj_attribute, ka)->cpu)
+
+struct msm_pm_sysfs_sleep_mode {
+ struct kobject *kobj;
+ struct attribute_group attr_group;
+ struct attribute *attrs[MSM_PM_MODE_ATTR_NR + 1];
+ struct msm_pm_kobj_attribute kas[MSM_PM_MODE_ATTR_NR];
+};
/*
* Write out the attribute.
@@ -182,6 +192,8 @@
for (i = 0; i < MSM_PM_SLEEP_MODE_NR; i++) {
struct kernel_param kp;
+ unsigned int cpu;
+ struct msm_pm_platform_data *mode;
if (msm_pm_sleep_mode_labels[i] == NULL)
continue;
@@ -189,23 +201,28 @@
if (strcmp(kobj->name, msm_pm_sleep_mode_labels[i]))
continue;
+ cpu = GET_CPU_OF_ATTR(attr);
+ mode = &msm_pm_modes[MSM_PM_MODE(cpu, i)];
+
if (!strcmp(attr->attr.name,
msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_SUSPEND])) {
- u32 arg = msm_pm_modes[i].suspend_enabled;
+ u32 arg = mode->suspend_enabled;
kp.arg = &arg;
ret = param_get_ulong(buf, &kp);
} else if (!strcmp(attr->attr.name,
msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_IDLE])) {
- u32 arg = msm_pm_modes[i].idle_enabled;
+ u32 arg = mode->idle_enabled;
kp.arg = &arg;
ret = param_get_ulong(buf, &kp);
} else if (!strcmp(attr->attr.name,
msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_LATENCY])) {
- kp.arg = &msm_pm_modes[i].latency;
+ u32 arg = mode->latency;
+ kp.arg = &arg;
ret = param_get_ulong(buf, &kp);
} else if (!strcmp(attr->attr.name,
msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_RESIDENCY])) {
- kp.arg = &msm_pm_modes[i].residency;
+ u32 arg = mode->residency;
+ kp.arg = &arg;
ret = param_get_ulong(buf, &kp);
}
@@ -213,7 +230,7 @@
}
if (ret > 0) {
- strcat(buf, "\n");
+ strlcat(buf, "\n", PAGE_SIZE);
ret++;
}
@@ -231,6 +248,8 @@
for (i = 0; i < MSM_PM_SLEEP_MODE_NR; i++) {
struct kernel_param kp;
+ unsigned int cpu;
+ struct msm_pm_platform_data *mode;
if (msm_pm_sleep_mode_labels[i] == NULL)
continue;
@@ -238,21 +257,24 @@
if (strcmp(kobj->name, msm_pm_sleep_mode_labels[i]))
continue;
+ cpu = GET_CPU_OF_ATTR(attr);
+ mode = &msm_pm_modes[MSM_PM_MODE(cpu, i)];
+
if (!strcmp(attr->attr.name,
msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_SUSPEND])) {
- kp.arg = &msm_pm_modes[i].suspend_enabled;
+ kp.arg = &mode->suspend_enabled;
ret = param_set_byte(buf, &kp);
} else if (!strcmp(attr->attr.name,
msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_IDLE])) {
- kp.arg = &msm_pm_modes[i].idle_enabled;
+ kp.arg = &mode->idle_enabled;
ret = param_set_byte(buf, &kp);
} else if (!strcmp(attr->attr.name,
msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_LATENCY])) {
- kp.arg = &msm_pm_modes[i].latency;
+ kp.arg = &mode->latency;
ret = param_set_ulong(buf, &kp);
} else if (!strcmp(attr->attr.name,
msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_RESIDENCY])) {
- kp.arg = &msm_pm_modes[i].residency;
+ kp.arg = &mode->residency;
ret = param_set_ulong(buf, &kp);
}
@@ -262,6 +284,86 @@
return ret ? ret : count;
}
+ /* Add sysfs entries for one cpu. */
+static int __init msm_pm_mode_sysfs_add_cpu(
+ unsigned int cpu, struct kobject *modes_kobj)
+{
+ char cpu_name[8];
+ struct kobject *cpu_kobj;
+ struct msm_pm_sysfs_sleep_mode *mode = NULL;
+ int i, j, k;
+ int ret;
+
+ snprintf(cpu_name, sizeof(cpu_name), "cpu%u", cpu);
+ cpu_kobj = kobject_create_and_add(cpu_name, modes_kobj);
+ if (!cpu_kobj) {
+ pr_err("%s: cannot create %s kobject\n", __func__, cpu_name);
+ ret = -ENOMEM;
+ goto mode_sysfs_add_cpu_exit;
+ }
+
+ for (i = 0; i < MSM_PM_SLEEP_MODE_NR; i++) {
+ int idx = MSM_PM_MODE(cpu, i);
+
+ if ((!msm_pm_modes[idx].suspend_supported) &&
+ (!msm_pm_modes[idx].idle_supported))
+ continue;
+
+ mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+ if (!mode) {
+ pr_err("%s: cannot allocate memory for attributes\n",
+ __func__);
+ ret = -ENOMEM;
+ goto mode_sysfs_add_cpu_exit;
+ }
+
+ mode->kobj = kobject_create_and_add(
+ msm_pm_sleep_mode_labels[i], cpu_kobj);
+ if (!mode->kobj) {
+ pr_err("%s: cannot create kobject\n", __func__);
+ ret = -ENOMEM;
+ goto mode_sysfs_add_cpu_exit;
+ }
+
+ for (k = 0, j = 0; k < MSM_PM_MODE_ATTR_NR; k++) {
+ if ((k == MSM_PM_MODE_ATTR_IDLE) &&
+ !msm_pm_modes[idx].idle_supported)
+ continue;
+ if ((k == MSM_PM_MODE_ATTR_SUSPEND) &&
+ !msm_pm_modes[idx].suspend_supported)
+ continue;
+ mode->kas[j].cpu = cpu;
+ mode->kas[j].ka.attr.mode = 0644;
+ mode->kas[j].ka.show = msm_pm_mode_attr_show;
+ mode->kas[j].ka.store = msm_pm_mode_attr_store;
+ mode->kas[j].ka.attr.name = msm_pm_mode_attr_labels[k];
+ mode->attrs[j] = &mode->kas[j].ka.attr;
+ j++;
+ }
+ mode->attrs[j] = NULL;
+
+ mode->attr_group.attrs = mode->attrs;
+ ret = sysfs_create_group(mode->kobj, &mode->attr_group);
+ if (ret) {
+ printk(KERN_ERR
+ "%s: cannot create kobject attribute group\n",
+ __func__);
+ goto mode_sysfs_add_cpu_exit;
+ }
+ }
+
+ ret = 0;
+
+mode_sysfs_add_cpu_exit:
+ if (ret) {
+ if (mode && mode->kobj)
+ kobject_del(mode->kobj);
+ kfree(mode);
+ }
+
+ return ret;
+}
+
/*
* Add sysfs entries for the sleep modes.
*/
@@ -269,13 +371,7 @@
{
struct kobject *module_kobj = NULL;
struct kobject *modes_kobj = NULL;
-
- struct kobject *kobj;
- struct attribute_group *attr_group;
- struct attribute **attrs;
- struct kobj_attribute *kobj_attrs;
-
- int i, j, k;
+ unsigned int cpu;
int ret;
module_kobj = kset_find_obj(module_kset, KBUILD_MODNAME);
@@ -283,98 +379,32 @@
printk(KERN_ERR "%s: cannot find kobject for module %s\n",
__func__, KBUILD_MODNAME);
ret = -ENOENT;
- goto mode_sysfs_add_cleanup;
+ goto mode_sysfs_add_exit;
}
modes_kobj = kobject_create_and_add("modes", module_kobj);
if (!modes_kobj) {
printk(KERN_ERR "%s: cannot create modes kobject\n", __func__);
ret = -ENOMEM;
- goto mode_sysfs_add_cleanup;
+ goto mode_sysfs_add_exit;
}
- for (i = 0; i < ARRAY_SIZE(msm_pm_mode_kobjs); i++) {
- if (!msm_pm_modes[i].suspend_supported &&
- !msm_pm_modes[i].idle_supported)
- continue;
-
- kobj = kobject_create_and_add(
- msm_pm_sleep_mode_labels[i], modes_kobj);
- attr_group = kzalloc(sizeof(*attr_group), GFP_KERNEL);
- attrs = kzalloc(sizeof(*attrs) * (MSM_PM_MODE_ATTR_NR + 1),
- GFP_KERNEL);
- kobj_attrs = kzalloc(sizeof(*kobj_attrs) * MSM_PM_MODE_ATTR_NR,
- GFP_KERNEL);
-
- if (!kobj || !attr_group || !attrs || !kobj_attrs) {
- printk(KERN_ERR
- "%s: cannot create kobject or attributes\n",
- __func__);
- ret = -ENOMEM;
- goto mode_sysfs_add_abort;
- }
-
- for (k = 0, j = 0; k < MSM_PM_MODE_ATTR_NR; k++) {
- if ((k == MSM_PM_MODE_ATTR_SUSPEND) &&
- (!msm_pm_modes[i].suspend_supported))
- continue;
- if ((k == MSM_PM_MODE_ATTR_IDLE) &&
- (!msm_pm_modes[i].idle_supported))
- continue;
-
- kobj_attrs[j].attr.mode = 0644;
- kobj_attrs[j].show = msm_pm_mode_attr_show;
- kobj_attrs[j].store = msm_pm_mode_attr_store;
- kobj_attrs[j].attr.name = msm_pm_mode_attr_labels[k];
- attrs[j] = &kobj_attrs[j].attr;
- j++;
- }
- attrs[j] = NULL;
-
- attr_group->attrs = attrs;
- ret = sysfs_create_group(kobj, attr_group);
- if (ret) {
- printk(KERN_ERR
- "%s: cannot create kobject attribute group\n",
- __func__);
- goto mode_sysfs_add_abort;
- }
-
- msm_pm_mode_kobjs[i] = kobj;
- msm_pm_mode_attr_group[i] = attr_group;
- msm_pm_mode_attrs[i] = attrs;
- msm_pm_mode_kobj_attrs[i] = kobj_attrs;
+ for_each_possible_cpu(cpu) {
+ ret = msm_pm_mode_sysfs_add_cpu(cpu, modes_kobj);
+ if (ret)
+ goto mode_sysfs_add_exit;
}
- return 0;
+ ret = 0;
-mode_sysfs_add_abort:
- kfree(kobj_attrs);
- kfree(attrs);
- kfree(attr_group);
- kobject_put(kobj);
-
-mode_sysfs_add_cleanup:
- for (i = ARRAY_SIZE(msm_pm_mode_kobjs) - 1; i >= 0; i--) {
- if (!msm_pm_mode_kobjs[i])
- continue;
-
- sysfs_remove_group(
- msm_pm_mode_kobjs[i], msm_pm_mode_attr_group[i]);
-
- kfree(msm_pm_mode_kobj_attrs[i]);
- kfree(msm_pm_mode_attrs[i]);
- kfree(msm_pm_mode_attr_group[i]);
- kobject_put(msm_pm_mode_kobjs[i]);
- }
-
+mode_sysfs_add_exit:
return ret;
}
void __init msm_pm_set_platform_data(
struct msm_pm_platform_data *data, int count)
{
- BUG_ON(MSM_PM_SLEEP_MODE_NR != count);
+ BUG_ON(MSM_PM_SLEEP_MODE_NR * num_possible_cpus() > count);
msm_pm_modes = data;
}
@@ -674,7 +704,7 @@
MSM_PM_STAT_COUNT
};
-static struct msm_pm_time_stats {
+struct msm_pm_time_stats {
const char *name;
int64_t first_bucket_time;
int bucket[CONFIG_MSM_IDLE_STATS_BUCKET_COUNT];
@@ -682,74 +712,37 @@
int64_t max_time[CONFIG_MSM_IDLE_STATS_BUCKET_COUNT];
int count;
int64_t total_time;
-} msm_pm_stats[MSM_PM_STAT_COUNT] = {
- [MSM_PM_STAT_REQUESTED_IDLE].name = "idle-request",
- [MSM_PM_STAT_REQUESTED_IDLE].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
- [MSM_PM_STAT_IDLE_SPIN].name = "idle-spin",
- [MSM_PM_STAT_IDLE_SPIN].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
- [MSM_PM_STAT_IDLE_WFI].name = "idle-wfi",
- [MSM_PM_STAT_IDLE_WFI].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
- [MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE].name =
- "idle-standalone-power-collapse",
- [MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
- [MSM_PM_STAT_IDLE_FAILED_STANDALONE_POWER_COLLAPSE].name =
- "idle-failed-standalone-power-collapse",
- [MSM_PM_STAT_IDLE_FAILED_STANDALONE_POWER_COLLAPSE].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
- [MSM_PM_STAT_IDLE_SLEEP].name = "idle-sleep",
- [MSM_PM_STAT_IDLE_SLEEP].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
- [MSM_PM_STAT_IDLE_FAILED_SLEEP].name = "idle-failed-sleep",
- [MSM_PM_STAT_IDLE_FAILED_SLEEP].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
- [MSM_PM_STAT_IDLE_POWER_COLLAPSE].name = "idle-power-collapse",
- [MSM_PM_STAT_IDLE_POWER_COLLAPSE].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
- [MSM_PM_STAT_IDLE_FAILED_POWER_COLLAPSE].name =
- "idle-failed-power-collapse",
- [MSM_PM_STAT_IDLE_FAILED_POWER_COLLAPSE].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
- [MSM_PM_STAT_SUSPEND].name = "suspend",
- [MSM_PM_STAT_SUSPEND].first_bucket_time =
- CONFIG_MSM_SUSPEND_STATS_FIRST_BUCKET,
-
- [MSM_PM_STAT_FAILED_SUSPEND].name = "failed-suspend",
- [MSM_PM_STAT_FAILED_SUSPEND].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
-
- [MSM_PM_STAT_NOT_IDLE].name = "not-idle",
- [MSM_PM_STAT_NOT_IDLE].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET,
};
+struct msm_pm_cpu_time_stats {
+ struct msm_pm_time_stats stats[MSM_PM_STAT_COUNT];
+};
+
+static DEFINE_PER_CPU_SHARED_ALIGNED(
+ struct msm_pm_cpu_time_stats, msm_pm_stats);
+
static uint32_t msm_pm_sleep_limit = SLEEP_LIMIT_NONE;
+static DEFINE_SPINLOCK(msm_pm_stats_lock);
+
/*
* Add the given time data to the statistics collection.
*/
static void msm_pm_add_stat(enum msm_pm_time_stats_id id, int64_t t)
{
+ unsigned long flags;
+ struct msm_pm_time_stats *stats;
int i;
int64_t bt;
- msm_pm_stats[id].total_time += t;
- msm_pm_stats[id].count++;
+ spin_lock_irqsave(&msm_pm_stats_lock, flags);
+ stats = __get_cpu_var(msm_pm_stats).stats;
+
+ stats[id].total_time += t;
+ stats[id].count++;
bt = t;
- do_div(bt, msm_pm_stats[id].first_bucket_time);
+ do_div(bt, stats[id].first_bucket_time);
if (bt < 1ULL << (CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT *
(CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1)))
@@ -758,12 +751,17 @@
else
i = CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1;
- msm_pm_stats[id].bucket[i]++;
+ if (i >= CONFIG_MSM_IDLE_STATS_BUCKET_COUNT)
+ i = CONFIG_MSM_IDLE_STATS_BUCKET_COUNT - 1;
- if (t < msm_pm_stats[id].min_time[i] || !msm_pm_stats[id].max_time[i])
- msm_pm_stats[id].min_time[i] = t;
- if (t > msm_pm_stats[id].max_time[i])
- msm_pm_stats[id].max_time[i] = t;
+ 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_stats_lock, flags);
}
/*
@@ -793,7 +791,8 @@
static int msm_pm_read_proc
(char *page, char **start, off_t off, int count, int *eof, void *data)
{
- int i;
+ unsigned int cpu = off / MSM_PM_STAT_COUNT;
+ int id = off % MSM_PM_STAT_COUNT;
char *p = page;
if (count < 1024) {
@@ -809,44 +808,51 @@
SNPRINTF(p, count, "for TCXO shutdown\n\n");
else
SNPRINTF(p, count, "against TCXO shutdown\n\n");
+ }
- *start = (char *) 1;
- *eof = 0;
- } else if (--off < ARRAY_SIZE(msm_pm_stats)) {
+ if (cpu < num_possible_cpus()) {
+ unsigned long flags;
+ struct msm_pm_time_stats *stats;
+ int i;
int64_t bucket_time;
int64_t s;
uint32_t ns;
- s = msm_pm_stats[off].total_time;
+ spin_lock_irqsave(&msm_pm_stats_lock, flags);
+ stats = per_cpu(msm_pm_stats, cpu).stats;
+
+ s = stats[id].total_time;
ns = do_div(s, NSEC_PER_SEC);
SNPRINTF(p, count,
- "%s:\n"
+ "[cpu %u] %s:\n"
" count: %7d\n"
" total_time: %lld.%09u\n",
- msm_pm_stats[off].name,
- msm_pm_stats[off].count,
+ cpu, stats[id].name,
+ stats[id].count,
s, ns);
- bucket_time = msm_pm_stats[off].first_bucket_time;
+ 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);
SNPRINTF(p, count,
" <%6lld.%09u: %7d (%lld-%lld)\n",
- s, ns, msm_pm_stats[off].bucket[i],
- msm_pm_stats[off].min_time[i],
- msm_pm_stats[off].max_time[i]);
+ s, ns, stats[id].bucket[i],
+ stats[id].min_time[i],
+ stats[id].max_time[i]);
bucket_time <<= CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT;
}
SNPRINTF(p, count, " >=%6lld.%09u: %7d (%lld-%lld)\n",
- s, ns, msm_pm_stats[off].bucket[i],
- msm_pm_stats[off].min_time[i],
- msm_pm_stats[off].max_time[i]);
+ s, ns, stats[id].bucket[i],
+ stats[id].min_time[i],
+ stats[id].max_time[i]);
*start = (char *) 1;
- *eof = (off + 1 >= ARRAY_SIZE(msm_pm_stats));
+ *eof = (off + 1 >= MSM_PM_STAT_COUNT * num_possible_cpus());
+
+ spin_unlock_irqrestore(&msm_pm_stats_lock, flags);
}
return p - page;
@@ -864,7 +870,7 @@
char buf[sizeof(MSM_PM_STATS_RESET)];
int ret;
unsigned long flags;
- int i;
+ unsigned int cpu;
if (count < strlen(MSM_PM_STATS_RESET)) {
ret = -EINVAL;
@@ -881,26 +887,32 @@
goto write_proc_failed;
}
- local_irq_save(flags);
- for (i = 0; i < ARRAY_SIZE(msm_pm_stats); i++) {
- memset(msm_pm_stats[i].bucket,
- 0, sizeof(msm_pm_stats[i].bucket));
- memset(msm_pm_stats[i].min_time,
- 0, sizeof(msm_pm_stats[i].min_time));
- memset(msm_pm_stats[i].max_time,
- 0, sizeof(msm_pm_stats[i].max_time));
- msm_pm_stats[i].count = 0;
- msm_pm_stats[i].total_time = 0;
- }
+ spin_lock_irqsave(&msm_pm_stats_lock, flags);
+ for_each_possible_cpu(cpu) {
+ struct msm_pm_time_stats *stats;
+ int i;
+ stats = per_cpu(msm_pm_stats, cpu).stats;
+ for (i = 0; i < MSM_PM_STAT_COUNT; i++) {
+ memset(stats[i].bucket,
+ 0, sizeof(stats[i].bucket));
+ memset(stats[i].min_time,
+ 0, sizeof(stats[i].min_time));
+ memset(stats[i].max_time,
+ 0, sizeof(stats[i].max_time));
+ stats[i].count = 0;
+ stats[i].total_time = 0;
+ }
+ }
msm_pm_sleep_limit = SLEEP_LIMIT_NONE;
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&msm_pm_stats_lock, flags);
return count;
write_proc_failed:
return ret;
}
+
#undef MSM_PM_STATS_RESET
#endif /* CONFIG_MSM_IDLE_STATS */
@@ -1389,6 +1401,7 @@
int low_power;
int ret;
int i;
+ unsigned int cpu;
#ifdef CONFIG_MSM_IDLE_STATS
int64_t t1;
@@ -1399,6 +1412,8 @@
if (!atomic_read(&msm_pm_init_done))
return;
+ cpu = smp_processor_id();
+
latency_qos = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
timer_expiration = msm_timer_enter_idle();
@@ -1450,7 +1465,8 @@
}
for (i = 0; i < ARRAY_SIZE(allow); i++) {
- struct msm_pm_platform_data *mode = &msm_pm_modes[i];
+ struct msm_pm_platform_data *mode =
+ &msm_pm_modes[MSM_PM_MODE(cpu, i)];
if (!mode->idle_supported || !mode->idle_enabled ||
mode->latency >= latency_qos ||
mode->residency * 1000ULL >= timer_expiration)
@@ -1629,7 +1645,8 @@
}
for (i = 0; i < ARRAY_SIZE(allow); i++) {
- struct msm_pm_platform_data *mode = &msm_pm_modes[i];
+ struct msm_pm_platform_data *mode;
+ mode = &msm_pm_modes[MSM_PM_MODE(0, i)];
if (!mode->suspend_supported || !mode->suspend_enabled)
allow[i] = false;
}
@@ -1778,6 +1795,7 @@
{
#ifdef CONFIG_MSM_IDLE_STATS
struct proc_dir_entry *d_entry;
+ unsigned int cpu;
#endif
int ret;
#ifdef CONFIG_CPU_V7
@@ -1846,6 +1864,66 @@
msm_pm_mode_sysfs_add();
#ifdef CONFIG_MSM_IDLE_STATS
+ for_each_possible_cpu(cpu) {
+ struct msm_pm_time_stats *stats =
+ per_cpu(msm_pm_stats, cpu).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;
+
+ stats[MSM_PM_STAT_IDLE_SPIN].name = "idle-spin";
+ stats[MSM_PM_STAT_IDLE_SPIN].first_bucket_time =
+ CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+ stats[MSM_PM_STAT_IDLE_WFI].name = "idle-wfi";
+ stats[MSM_PM_STAT_IDLE_WFI].first_bucket_time =
+ CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+ 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_FAILED_STANDALONE_POWER_COLLAPSE].name =
+ "idle-failed-standalone-power-collapse";
+ stats[MSM_PM_STAT_IDLE_FAILED_STANDALONE_POWER_COLLAPSE].
+ first_bucket_time =
+ CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+ stats[MSM_PM_STAT_IDLE_SLEEP].name = "idle-sleep";
+ stats[MSM_PM_STAT_IDLE_SLEEP].first_bucket_time =
+ CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+ stats[MSM_PM_STAT_IDLE_FAILED_SLEEP].name =
+ "idle-failed-sleep";
+ stats[MSM_PM_STAT_IDLE_FAILED_SLEEP].first_bucket_time =
+ CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+ stats[MSM_PM_STAT_IDLE_POWER_COLLAPSE].name =
+ "idle-power-collapse";
+ stats[MSM_PM_STAT_IDLE_POWER_COLLAPSE].first_bucket_time =
+ CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+ stats[MSM_PM_STAT_IDLE_FAILED_POWER_COLLAPSE].name =
+ "idle-failed-power-collapse";
+ stats[MSM_PM_STAT_IDLE_FAILED_POWER_COLLAPSE].
+ first_bucket_time =
+ CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+ 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_FAILED_SUSPEND].name = "failed-suspend";
+ stats[MSM_PM_STAT_FAILED_SUSPEND].first_bucket_time =
+ CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+
+ stats[MSM_PM_STAT_NOT_IDLE].name = "not-idle";
+ stats[MSM_PM_STAT_NOT_IDLE].first_bucket_time =
+ CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
+ }
d_entry = create_proc_entry("msm_pm_stats",
S_IRUGO | S_IWUSR | S_IWGRP, NULL);
if (d_entry) {