* [PATCH 0/3] debugfs entries for PM counters @ 2008-10-14 14:39 Peter 'p2' De Schrijver 2008-10-14 14:39 ` [PATCH 1/3] Add closures to clkdm_for_each and pwrdm_for_each Peter 'p2' De Schrijver 2008-10-29 18:22 ` [PATCH 0/3] debugfs entries for PM counters Kevin Hilman 0 siblings, 2 replies; 13+ messages in thread From: Peter 'p2' De Schrijver @ 2008-10-14 14:39 UTC (permalink / raw) To: linux-omap; +Cc: Peter 'p2' De Schrijver This patchset adds 2 debugfs entries for power management counters. pm_debug/count indicates how many times each powerdomain entered each state (On, Inactive, Retention, Off). pm_debug/time indicates how much time each powerdomain spent per state. Peter 'p2' De Schrijver (3): Add closures to clkdm_for_each. Add pm-debug counters Hook into powerdomain code arch/arm/mach-omap2/clockdomain.c | 5 +- arch/arm/mach-omap2/pm-debug.c | 175 +++++++++++++++++++++++++ arch/arm/mach-omap2/pm.h | 2 + arch/arm/mach-omap2/pm34xx.c | 8 +- arch/arm/mach-omap2/powerdomain.c | 24 +++- arch/arm/plat-omap/include/mach/clockdomain.h | 3 +- arch/arm/plat-omap/include/mach/powerdomain.h | 8 +- 7 files changed, 209 insertions(+), 16 deletions(-) ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/3] Add closures to clkdm_for_each and pwrdm_for_each. 2008-10-14 14:39 [PATCH 0/3] debugfs entries for PM counters Peter 'p2' De Schrijver @ 2008-10-14 14:39 ` Peter 'p2' De Schrijver 2008-10-14 14:39 ` [PATCH 2/3] Add pm-debug counters Peter 'p2' De Schrijver 2008-10-14 19:50 ` [PATCH 1/3] Add closures to clkdm_for_each and pwrdm_for_each Paul Walmsley 2008-10-29 18:22 ` [PATCH 0/3] debugfs entries for PM counters Kevin Hilman 1 sibling, 2 replies; 13+ messages in thread From: Peter 'p2' De Schrijver @ 2008-10-14 14:39 UTC (permalink / raw) To: linux-omap; +Cc: Peter 'p2' De Schrijver First add some infrastructure to easily iterate over clock and power domains. Also add extra fields to the powerdomain struct to keep the time info. Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com> --- arch/arm/mach-omap2/clockdomain.c | 5 +++-- arch/arm/mach-omap2/pm34xx.c | 8 ++++---- arch/arm/plat-omap/include/mach/clockdomain.h | 3 ++- arch/arm/plat-omap/include/mach/powerdomain.h | 8 +++++++- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 5249fe8..b0b5885 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -295,7 +295,8 @@ struct clockdomain *clkdm_lookup(const char *name) * anything else to indicate failure; or -EINVAL if the function pointer * is null. */ -int clkdm_for_each(int (*fn)(struct clockdomain *clkdm)) +int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user), + void *user) { struct clockdomain *clkdm; int ret = 0; @@ -305,7 +306,7 @@ int clkdm_for_each(int (*fn)(struct clockdomain *clkdm)) mutex_lock(&clkdm_mutex); list_for_each_entry(clkdm, &clkdm_list, node) { - ret = (*fn)(clkdm); + ret = (*fn)(clkdm, user); if (ret) break; } diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 1fbb690..be69839 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -518,7 +518,7 @@ static void __init prcm_setup_regs(void) OCP_MOD, OMAP2_PRM_IRQENABLE_MPU_OFFSET); } -static int __init pwrdms_setup(struct powerdomain *pwrdm) +static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused) { struct power_state *pwrst; @@ -538,7 +538,7 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm) return set_pwrdm_state(pwrst->pwrdm, pwrst->next_state); } -static int __init clkdms_setup(struct clockdomain *clkdm) +static int __init clkdms_setup(struct clockdomain *clkdm, void *unused) { omap2_clkdm_allow_idle(clkdm); return 0; @@ -564,13 +564,13 @@ int __init omap3_pm_init(void) goto err1; } - ret = pwrdm_for_each(pwrdms_setup); + ret = pwrdm_for_each(pwrdms_setup, NULL); if (ret) { printk(KERN_ERR "Failed to setup powerdomains\n"); goto err2; } - (void) clkdm_for_each(clkdms_setup); + (void) clkdm_for_each(clkdms_setup, NULL); mpu_pwrdm = pwrdm_lookup("mpu_pwrdm"); if (mpu_pwrdm == NULL) { diff --git a/arch/arm/plat-omap/include/mach/clockdomain.h b/arch/arm/plat-omap/include/mach/clockdomain.h index b9d0dd2..99ebd88 100644 --- a/arch/arm/plat-omap/include/mach/clockdomain.h +++ b/arch/arm/plat-omap/include/mach/clockdomain.h @@ -95,7 +95,8 @@ int clkdm_register(struct clockdomain *clkdm); int clkdm_unregister(struct clockdomain *clkdm); struct clockdomain *clkdm_lookup(const char *name); -int clkdm_for_each(int (*fn)(struct clockdomain *clkdm)); +int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user), + void *user); struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm); void omap2_clkdm_allow_idle(struct clockdomain *clkdm); diff --git a/arch/arm/plat-omap/include/mach/powerdomain.h b/arch/arm/plat-omap/include/mach/powerdomain.h index 52663fc..6271d85 100644 --- a/arch/arm/plat-omap/include/mach/powerdomain.h +++ b/arch/arm/plat-omap/include/mach/powerdomain.h @@ -119,6 +119,11 @@ struct powerdomain { int state; unsigned state_counter[4]; + +#ifdef CONFIG_PM_DEBUG + s64 timer; + s64 state_timer[4]; +#endif }; @@ -128,7 +133,8 @@ int pwrdm_register(struct powerdomain *pwrdm); int pwrdm_unregister(struct powerdomain *pwrdm); struct powerdomain *pwrdm_lookup(const char *name); -int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm)); +int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user), + void *user); int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm); int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm); -- 1.5.6.3 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 2/3] Add pm-debug counters 2008-10-14 14:39 ` [PATCH 1/3] Add closures to clkdm_for_each and pwrdm_for_each Peter 'p2' De Schrijver @ 2008-10-14 14:39 ` Peter 'p2' De Schrijver 2008-10-14 14:39 ` [PATCH 3/3] Hook into powerdomain code Peter 'p2' De Schrijver ` (2 more replies) 2008-10-14 19:50 ` [PATCH 1/3] Add closures to clkdm_for_each and pwrdm_for_each Paul Walmsley 1 sibling, 3 replies; 13+ messages in thread From: Peter 'p2' De Schrijver @ 2008-10-14 14:39 UTC (permalink / raw) To: linux-omap; +Cc: Peter 'p2' De Schrijver This patch provides the debugfs entries and a function which will be called by the PM code to register the time spent per domain per state. Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com> --- arch/arm/mach-omap2/pm-debug.c | 175 +++++++++++++++++++++++++ arch/arm/mach-omap2/pm.h | 2 + 2 files changed, 177 insertions(+) diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c index 0b5c044..4ba6cec 100644 --- a/arch/arm/mach-omap2/pm-debug.c +++ b/arch/arm/mach-omap2/pm-debug.c @@ -29,6 +29,8 @@ #include <mach/clock.h> #include <mach/board.h> +#include <mach/powerdomain.h> +#include <mach/clockdomain.h> #include "prm.h" #include "cm.h" @@ -288,4 +290,177 @@ void omap2_pm_dump(int mode, int resume, unsigned int us) printk("%-20s: 0x%08x\n", regs[i].name, regs[i].val); } +#ifdef CONFIG_DEBUG_FS +#include <linux/debugfs.h> +#include <linux/seq_file.h> + +struct dentry *pm_dbg_dir; + +static int pm_dbg_init_done; + +enum { + DEBUG_FILE_COUNTERS = 0, + DEBUG_FILE_TIMERS, +}; + +static const char pwrdm_state_names[][4] = { + "OFF", + "RET", + "INA", + "ON" +}; + +void pm_dbg_update_time(struct powerdomain *pwrdm, int prev) +{ + s64 t; + struct timespec now; + + if (!pm_dbg_init_done) + return ; + + /* Update timer for previous state */ + getnstimeofday(&now); + t = timespec_to_ns(&now); + + pwrdm->state_timer[prev] += t - pwrdm->timer; + + pwrdm->timer = t; +} + +static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user) +{ + struct seq_file *s = (struct seq_file *)user; + + if (strcmp(clkdm->name, "emu_clkdm") == 0 || + strcmp(clkdm->name, "wkup_clkdm") == 0) + return 0; + + seq_printf(s, "%s->%s (%d)", clkdm->name, + clkdm->pwrdm.ptr->name, + atomic_read(&clkdm->usecount)); + seq_printf(s, "\n"); + + return 0; +} + +static int pwrdm_dbg_show_counter(struct powerdomain *pwrdm, void *user) +{ + struct seq_file *s = (struct seq_file *)user; + int i; + + if (strcmp(pwrdm->name, "emu_pwrdm") == 0 || + strcmp(pwrdm->name, "wkup_pwrdm") == 0) + return 0; + + if (pwrdm->state != pwrdm_read_pwrst(pwrdm)) + printk(KERN_ERR "pwrdm state mismatch(%s) %d != %d\n", + pwrdm->name, pwrdm->state, pwrdm_read_pwrst(pwrdm)); + + seq_printf(s, "%s (%s)", pwrdm->name, + pwrdm_state_names[pwrdm->state]); + for (i = 0; i < 4; i++) + seq_printf(s, ",%s:%d", pwrdm_state_names[i], + pwrdm->state_counter[i]); + + seq_printf(s, "\n"); + + return 0; +} + +static int pwrdm_dbg_show_timer(struct powerdomain *pwrdm, void *user) +{ + struct seq_file *s = (struct seq_file *)user; + int i; + + if (strcmp(pwrdm->name, "emu_pwrdm") == 0 || + strcmp(pwrdm->name, "wkup_pwrdm") == 0) + return 0; + + pwrdm_state_switch(pwrdm); + + seq_printf(s, "%s (%s)", pwrdm->name, + pwrdm_state_names[pwrdm->state]); + + for (i = 0; i < 4; i++) + seq_printf(s, ",%s:%lld", pwrdm_state_names[i], + pwrdm->state_timer[i]); + + seq_printf(s, "\n"); + + return 0; +} + +static void pm_dbg_show_counters(struct seq_file *s, void *unused) +{ + pwrdm_for_each(pwrdm_dbg_show_counter, s); + clkdm_for_each(clkdm_dbg_show_counter, s); +} + +static void pm_dbg_show_timers(struct seq_file *s, void *unused) +{ + pwrdm_for_each(pwrdm_dbg_show_timer, s); +} + +static int pm_dbg_open(struct inode *inode, struct file *file) +{ + switch ((int)inode->i_private) { + case DEBUG_FILE_COUNTERS: + return single_open(file, pm_dbg_show_counters, + &inode->i_private); + case DEBUG_FILE_TIMERS: + default: + return single_open(file, pm_dbg_show_timers, + &inode->i_private); + }; +} + +static const struct file_operations debug_fops = { + .open = pm_dbg_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused) +{ + int i; + s64 t; + struct timespec now; + + getnstimeofday(&now); + t = timespec_to_ns(&now); + + for (i = 0; i < 4; i++) + pwrdm->state_timer[i] = 0; + + pwrdm->timer = t; + + return 0; +} + +static int __init pm_dbg_init(void) +{ + struct dentry *d; + + printk(KERN_INFO "pm_dbg_init()\n"); + + d = debugfs_create_dir("pm_debug", NULL); + if (IS_ERR(d)) + return PTR_ERR(d); + + (void) debugfs_create_file("count", S_IRUGO, + d, (void *)DEBUG_FILE_COUNTERS, &debug_fops); + (void) debugfs_create_file("time", S_IRUGO, + d, (void *)DEBUG_FILE_TIMERS, &debug_fops); + + pwrdm_for_each(pwrdms_setup, NULL); + + pm_dbg_init_done = 1; + + return 0; +} +late_initcall(pm_dbg_init); + +#endif + #endif diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index 68c9278..fb6693b 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -31,6 +31,7 @@ extern void serial_console_fclk_mask(u32 *f1, u32 *f2); extern void pm_init_serial_console(void); extern void serial_console_sleep(int enable); extern int omap2_pm_debug; +extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev); #else #define omap2_read_32k_sync_counter() 0 #define serial_console_sleep(enable) do {} while (0); @@ -38,5 +39,6 @@ extern int omap2_pm_debug; #define omap2_pm_dump(mode, resume, us) do {} while (0); #define serial_console_fclk_mask(f1, f2) do {} while (0); #define omap2_pm_debug 0 +#define pm_dbg_update_time(pwrdm, prev) do {} while (0); #endif /* CONFIG_PM_DEBUG */ #endif -- 1.5.6.3 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 3/3] Hook into powerdomain code 2008-10-14 14:39 ` [PATCH 2/3] Add pm-debug counters Peter 'p2' De Schrijver @ 2008-10-14 14:39 ` Peter 'p2' De Schrijver 2008-10-14 19:55 ` Paul Walmsley 2008-10-14 19:47 ` [PATCH 2/3] Add pm-debug counters Paul Walmsley 2008-10-15 6:12 ` Högander Jouni 2 siblings, 1 reply; 13+ messages in thread From: Peter 'p2' De Schrijver @ 2008-10-14 14:39 UTC (permalink / raw) To: linux-omap; +Cc: Peter 'p2' De Schrijver Make the powerdomain code call the new hook for updating the time. Also implement the updated pwrdm_for_each. Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com> --- arch/arm/mach-omap2/powerdomain.c | 24 ++++++++++++++++-------- 1 files changed, 16 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index 349b7ab..0334609 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c @@ -35,6 +35,8 @@ #include <mach/powerdomain.h> #include <mach/clockdomain.h> +#include "pm.h" + enum { PWRDM_STATE_NOW = 0, PWRDM_STATE_PREV, @@ -134,19 +136,21 @@ static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag) if (state != prev) pwrdm->state_counter[state]++; + pm_dbg_update_time(pwrdm, prev); + pwrdm->state = state; return 0; } -static int _pwrdm_pre_transition_cb(struct powerdomain *pwrdm) +static int _pwrdm_pre_transition_cb(struct powerdomain *pwrdm, void *unused) { pwrdm_clear_all_prev_pwrst(pwrdm); _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW); return 0; } -static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm) +static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused) { _pwrdm_state_switch(pwrdm, PWRDM_STATE_PREV); return 0; @@ -179,9 +183,12 @@ void pwrdm_init(struct powerdomain **pwrdm_list) { struct powerdomain **p = NULL; - if (pwrdm_list) - for (p = pwrdm_list; *p; p++) + if (pwrdm_list) { + for (p = pwrdm_list; *p; p++) { pwrdm_register(*p); + _pwrdm_setup(*p); + } + } } /** @@ -279,7 +286,8 @@ struct powerdomain *pwrdm_lookup(const char *name) * anything else to indicate failure; or -EINVAL if the function * pointer is null. */ -int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm)) +int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user), + void *user) { struct powerdomain *temp_pwrdm; unsigned long flags; @@ -290,7 +298,7 @@ int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm)) read_lock_irqsave(&pwrdm_rwlock, flags); list_for_each_entry(temp_pwrdm, &pwrdm_list, node) { - ret = (*fn)(temp_pwrdm); + ret = (*fn)(temp_pwrdm, user); if (ret) break; } @@ -1195,13 +1203,13 @@ int pwrdm_clk_state_switch(struct clk *clk) int pwrdm_pre_transition(void) { - pwrdm_for_each(_pwrdm_pre_transition_cb); + pwrdm_for_each(_pwrdm_pre_transition_cb, NULL); return 0; } int pwrdm_post_transition(void) { - pwrdm_for_each(_pwrdm_post_transition_cb); + pwrdm_for_each(_pwrdm_post_transition_cb, NULL); return 0; } -- 1.5.6.3 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 3/3] Hook into powerdomain code 2008-10-14 14:39 ` [PATCH 3/3] Hook into powerdomain code Peter 'p2' De Schrijver @ 2008-10-14 19:55 ` Paul Walmsley 2008-10-15 14:32 ` Peter 'p2' De Schrijver 0 siblings, 1 reply; 13+ messages in thread From: Paul Walmsley @ 2008-10-14 19:55 UTC (permalink / raw) To: Peter 'p2' De Schrijver; +Cc: linux-omap On Tue, 14 Oct 2008, Peter 'p2' De Schrijver wrote: > @@ -179,9 +183,12 @@ void pwrdm_init(struct powerdomain **pwrdm_list) > { > struct powerdomain **p = NULL; > > - if (pwrdm_list) > - for (p = pwrdm_list; *p; p++) > + if (pwrdm_list) { > + for (p = pwrdm_list; *p; p++) { > pwrdm_register(*p); > + _pwrdm_setup(*p); perhaps I am going blind - could you point me at where _pwrdm_setup() is defined? > + } > + } > } - Paul ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 3/3] Hook into powerdomain code 2008-10-14 19:55 ` Paul Walmsley @ 2008-10-15 14:32 ` Peter 'p2' De Schrijver 0 siblings, 0 replies; 13+ messages in thread From: Peter 'p2' De Schrijver @ 2008-10-15 14:32 UTC (permalink / raw) To: ext Paul Walmsley; +Cc: linux-omap On Tue, Oct 14, 2008 at 01:55:07PM -0600, ext Paul Walmsley wrote: > On Tue, 14 Oct 2008, Peter 'p2' De Schrijver wrote: > > > @@ -179,9 +183,12 @@ void pwrdm_init(struct powerdomain **pwrdm_list) > > { > > struct powerdomain **p = NULL; > > > > - if (pwrdm_list) > > - for (p = pwrdm_list; *p; p++) > > + if (pwrdm_list) { > > + for (p = pwrdm_list; *p; p++) { > > pwrdm_register(*p); > > + _pwrdm_setup(*p); > > perhaps I am going blind - could you point me at where _pwrdm_setup() is > defined? > Hmm. This seems to be a change which should have been in the normal pm counters patch. Somehow it didn't get there. I will send an updated version of that patch. Cheers, Peter. -- goa is a state of mind ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/3] Add pm-debug counters 2008-10-14 14:39 ` [PATCH 2/3] Add pm-debug counters Peter 'p2' De Schrijver 2008-10-14 14:39 ` [PATCH 3/3] Hook into powerdomain code Peter 'p2' De Schrijver @ 2008-10-14 19:47 ` Paul Walmsley 2008-10-15 6:12 ` Högander Jouni 2 siblings, 0 replies; 13+ messages in thread From: Paul Walmsley @ 2008-10-14 19:47 UTC (permalink / raw) To: Peter 'p2' De Schrijver; +Cc: linux-omap Hi Peter a few quick comments... On Tue, 14 Oct 2008, Peter 'p2' De Schrijver wrote: > This patch provides the debugfs entries and a function which will be called > by the PM code to register the time spent per domain per state. > > Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com> > --- > arch/arm/mach-omap2/pm-debug.c | 175 +++++++++++++++++++++++++ > arch/arm/mach-omap2/pm.h | 2 + > 2 files changed, 177 insertions(+) > > diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c > index 0b5c044..4ba6cec 100644 > --- a/arch/arm/mach-omap2/pm-debug.c > +++ b/arch/arm/mach-omap2/pm-debug.c > @@ -29,6 +29,8 @@ > > #include <mach/clock.h> > #include <mach/board.h> > +#include <mach/powerdomain.h> > +#include <mach/clockdomain.h> > > #include "prm.h" > #include "cm.h" > @@ -288,4 +290,177 @@ void omap2_pm_dump(int mode, int resume, unsigned int us) > printk("%-20s: 0x%08x\n", regs[i].name, regs[i].val); > } > > +#ifdef CONFIG_DEBUG_FS > +#include <linux/debugfs.h> > +#include <linux/seq_file.h> > + > +struct dentry *pm_dbg_dir; > + > +static int pm_dbg_init_done; > + > +enum { > + DEBUG_FILE_COUNTERS = 0, > + DEBUG_FILE_TIMERS, > +}; > + > +static const char pwrdm_state_names[][4] = { > + "OFF", > + "RET", > + "INA", > + "ON" > +}; > + > +void pm_dbg_update_time(struct powerdomain *pwrdm, int prev) > +{ > + s64 t; > + struct timespec now; > + > + if (!pm_dbg_init_done) > + return ; > + > + /* Update timer for previous state */ > + getnstimeofday(&now); > + t = timespec_to_ns(&now); > + > + pwrdm->state_timer[prev] += t - pwrdm->timer; > + > + pwrdm->timer = t; > +} > + > +static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user) > +{ > + struct seq_file *s = (struct seq_file *)user; > + > + if (strcmp(clkdm->name, "emu_clkdm") == 0 || > + strcmp(clkdm->name, "wkup_clkdm") == 0) > + return 0; Is this code intended to skip clockdomains that have no hardware counters? Maybe we should add a flag in the struct clockdomain for this. > + > + seq_printf(s, "%s->%s (%d)", clkdm->name, > + clkdm->pwrdm.ptr->name, > + atomic_read(&clkdm->usecount)); > + seq_printf(s, "\n"); > + > + return 0; > +} > + > +static int pwrdm_dbg_show_counter(struct powerdomain *pwrdm, void *user) > +{ > + struct seq_file *s = (struct seq_file *)user; > + int i; > + > + if (strcmp(pwrdm->name, "emu_pwrdm") == 0 || > + strcmp(pwrdm->name, "wkup_pwrdm") == 0) > + return 0; likewise > + > + if (pwrdm->state != pwrdm_read_pwrst(pwrdm)) > + printk(KERN_ERR "pwrdm state mismatch(%s) %d != %d\n", > + pwrdm->name, pwrdm->state, pwrdm_read_pwrst(pwrdm)); > + > + seq_printf(s, "%s (%s)", pwrdm->name, > + pwrdm_state_names[pwrdm->state]); > + for (i = 0; i < 4; i++) how about for (i = 0; i < ARRAY_SIZE(pwrdm_state_names); i++) ? > + seq_printf(s, ",%s:%d", pwrdm_state_names[i], > + pwrdm->state_counter[i]); > + > + seq_printf(s, "\n"); > + > + return 0; > +} > + > +static int pwrdm_dbg_show_timer(struct powerdomain *pwrdm, void *user) > +{ > + struct seq_file *s = (struct seq_file *)user; > + int i; > + > + if (strcmp(pwrdm->name, "emu_pwrdm") == 0 || > + strcmp(pwrdm->name, "wkup_pwrdm") == 0) > + return 0; likewise with the clockdomain flag comment > + > + pwrdm_state_switch(pwrdm); > + > + seq_printf(s, "%s (%s)", pwrdm->name, > + pwrdm_state_names[pwrdm->state]); > + > + for (i = 0; i < 4; i++) ARRAY_SIZE() > + seq_printf(s, ",%s:%lld", pwrdm_state_names[i], > + pwrdm->state_timer[i]); > + > + seq_printf(s, "\n"); > + > + return 0; > +} > + > +static void pm_dbg_show_counters(struct seq_file *s, void *unused) > +{ > + pwrdm_for_each(pwrdm_dbg_show_counter, s); > + clkdm_for_each(clkdm_dbg_show_counter, s); > +} > + > +static void pm_dbg_show_timers(struct seq_file *s, void *unused) > +{ > + pwrdm_for_each(pwrdm_dbg_show_timer, s); > +} > + > +static int pm_dbg_open(struct inode *inode, struct file *file) > +{ > + switch ((int)inode->i_private) { > + case DEBUG_FILE_COUNTERS: > + return single_open(file, pm_dbg_show_counters, > + &inode->i_private); > + case DEBUG_FILE_TIMERS: > + default: > + return single_open(file, pm_dbg_show_timers, > + &inode->i_private); > + }; > +} > + > +static const struct file_operations debug_fops = { > + .open = pm_dbg_open, > + .read = seq_read, > + .llseek = seq_lseek, > + .release = single_release, > +}; > + > +static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused) > +{ > + int i; > + s64 t; > + struct timespec now; > + > + getnstimeofday(&now); > + t = timespec_to_ns(&now); > + > + for (i = 0; i < 4; i++) likewise here with the ARRAY_SIZE() > + pwrdm->state_timer[i] = 0; > + > + pwrdm->timer = t; > + > + return 0; > +} > + > +static int __init pm_dbg_init(void) > +{ > + struct dentry *d; > + > + printk(KERN_INFO "pm_dbg_init()\n"); > + > + d = debugfs_create_dir("pm_debug", NULL); > + if (IS_ERR(d)) > + return PTR_ERR(d); > + > + (void) debugfs_create_file("count", S_IRUGO, > + d, (void *)DEBUG_FILE_COUNTERS, &debug_fops); > + (void) debugfs_create_file("time", S_IRUGO, > + d, (void *)DEBUG_FILE_TIMERS, &debug_fops); > + > + pwrdm_for_each(pwrdms_setup, NULL); > + > + pm_dbg_init_done = 1; > + > + return 0; > +} > +late_initcall(pm_dbg_init); > + > +#endif > + > #endif > diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h > index 68c9278..fb6693b 100644 > --- a/arch/arm/mach-omap2/pm.h > +++ b/arch/arm/mach-omap2/pm.h > @@ -31,6 +31,7 @@ extern void serial_console_fclk_mask(u32 *f1, u32 *f2); > extern void pm_init_serial_console(void); > extern void serial_console_sleep(int enable); > extern int omap2_pm_debug; > +extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev); > #else > #define omap2_read_32k_sync_counter() 0 > #define serial_console_sleep(enable) do {} while (0); > @@ -38,5 +39,6 @@ extern int omap2_pm_debug; > #define omap2_pm_dump(mode, resume, us) do {} while (0); > #define serial_console_fclk_mask(f1, f2) do {} while (0); > #define omap2_pm_debug 0 > +#define pm_dbg_update_time(pwrdm, prev) do {} while (0); > #endif /* CONFIG_PM_DEBUG */ > #endif > -- > 1.5.6.3 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > - Paul ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/3] Add pm-debug counters 2008-10-14 14:39 ` [PATCH 2/3] Add pm-debug counters Peter 'p2' De Schrijver 2008-10-14 14:39 ` [PATCH 3/3] Hook into powerdomain code Peter 'p2' De Schrijver 2008-10-14 19:47 ` [PATCH 2/3] Add pm-debug counters Paul Walmsley @ 2008-10-15 6:12 ` Högander Jouni 2008-10-15 9:54 ` Tero.Kristo 2 siblings, 1 reply; 13+ messages in thread From: Högander Jouni @ 2008-10-15 6:12 UTC (permalink / raw) To: ext Peter 'p2' De Schrijver; +Cc: linux-omap "ext Peter 'p2' De Schrijver" <peter.de-schrijver@nokia.com> writes: > This patch provides the debugfs entries and a function which will be called > by the PM code to register the time spent per domain per state. > > Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com> > --- > arch/arm/mach-omap2/pm-debug.c | 175 +++++++++++++++++++++++++ > arch/arm/mach-omap2/pm.h | 2 + > 2 files changed, 177 insertions(+) > > diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c > index 0b5c044..4ba6cec 100644 > --- a/arch/arm/mach-omap2/pm-debug.c > +++ b/arch/arm/mach-omap2/pm-debug.c > @@ -29,6 +29,8 @@ > > #include <mach/clock.h> > #include <mach/board.h> > +#include <mach/powerdomain.h> > +#include <mach/clockdomain.h> > > #include "prm.h" > #include "cm.h" > @@ -288,4 +290,177 @@ void omap2_pm_dump(int mode, int resume, unsigned int us) > printk("%-20s: 0x%08x\n", regs[i].name, regs[i].val); > } > > +#ifdef CONFIG_DEBUG_FS > +#include <linux/debugfs.h> > +#include <linux/seq_file.h> > + > +struct dentry *pm_dbg_dir; > + > +static int pm_dbg_init_done; > + > +enum { > + DEBUG_FILE_COUNTERS = 0, > + DEBUG_FILE_TIMERS, > +}; > + > +static const char pwrdm_state_names[][4] = { > + "OFF", > + "RET", > + "INA", > + "ON" > +}; > + > +void pm_dbg_update_time(struct powerdomain *pwrdm, int prev) > +{ > + s64 t; > + struct timespec now; > + > + if (!pm_dbg_init_done) > + return ; > + > + /* Update timer for previous state */ > + getnstimeofday(&now); > + t = timespec_to_ns(&now); > + > + pwrdm->state_timer[prev] += t - pwrdm->timer; > + > + pwrdm->timer = t; > +} > + > +static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user) > +{ > + struct seq_file *s = (struct seq_file *)user; > + > + if (strcmp(clkdm->name, "emu_clkdm") == 0 || > + strcmp(clkdm->name, "wkup_clkdm") == 0) > + return 0; Why emu and wkup are not taken into account? If wkup is closed out here, I think also prm_clkdm and cm_clkdm should be. > + > + seq_printf(s, "%s->%s (%d)", clkdm->name, > + clkdm->pwrdm.ptr->name, > + atomic_read(&clkdm->usecount)); > + seq_printf(s, "\n"); > + > + return 0; > +} > + > +static int pwrdm_dbg_show_counter(struct powerdomain *pwrdm, void *user) > +{ > + struct seq_file *s = (struct seq_file *)user; > + int i; > + > + if (strcmp(pwrdm->name, "emu_pwrdm") == 0 || > + strcmp(pwrdm->name, "wkup_pwrdm") == 0) > + return 0; Why emu is closed out here? It has pwstst register. I think also dpll1..5_pwrdm should be closed out here. I'm not sure why those are even modelled in a clocktree. > + > + if (pwrdm->state != pwrdm_read_pwrst(pwrdm)) > + printk(KERN_ERR "pwrdm state mismatch(%s) %d != %d\n", > + pwrdm->name, pwrdm->state, pwrdm_read_pwrst(pwrdm)); > + > + seq_printf(s, "%s (%s)", pwrdm->name, > + pwrdm_state_names[pwrdm->state]); > + for (i = 0; i < 4; i++) > + seq_printf(s, ",%s:%d", pwrdm_state_names[i], > + pwrdm->state_counter[i]); > + > + seq_printf(s, "\n"); > + > + return 0; > +} > + > +static int pwrdm_dbg_show_timer(struct powerdomain *pwrdm, void *user) > +{ > + struct seq_file *s = (struct seq_file *)user; > + int i; > + > + if (strcmp(pwrdm->name, "emu_pwrdm") == 0 || > + strcmp(pwrdm->name, "wkup_pwrdm") == 0) > + return 0; Same comment as above. > + > + pwrdm_state_switch(pwrdm); > + > + seq_printf(s, "%s (%s)", pwrdm->name, > + pwrdm_state_names[pwrdm->state]); > + > + for (i = 0; i < 4; i++) > + seq_printf(s, ",%s:%lld", pwrdm_state_names[i], > + pwrdm->state_timer[i]); > + > + seq_printf(s, "\n"); > + > + return 0; > +} > + > +static void pm_dbg_show_counters(struct seq_file *s, void *unused) > +{ > + pwrdm_for_each(pwrdm_dbg_show_counter, s); > + clkdm_for_each(clkdm_dbg_show_counter, s); > +} > + > +static void pm_dbg_show_timers(struct seq_file *s, void *unused) > +{ > + pwrdm_for_each(pwrdm_dbg_show_timer, s); > +} > + > +static int pm_dbg_open(struct inode *inode, struct file *file) > +{ > + switch ((int)inode->i_private) { > + case DEBUG_FILE_COUNTERS: > + return single_open(file, pm_dbg_show_counters, > + &inode->i_private); > + case DEBUG_FILE_TIMERS: > + default: > + return single_open(file, pm_dbg_show_timers, > + &inode->i_private); > + }; > +} > + > +static const struct file_operations debug_fops = { > + .open = pm_dbg_open, > + .read = seq_read, > + .llseek = seq_lseek, > + .release = single_release, > +}; > + > +static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused) > +{ > + int i; > + s64 t; > + struct timespec now; > + > + getnstimeofday(&now); > + t = timespec_to_ns(&now); > + > + for (i = 0; i < 4; i++) > + pwrdm->state_timer[i] = 0; > + > + pwrdm->timer = t; > + > + return 0; > +} > + > +static int __init pm_dbg_init(void) > +{ > + struct dentry *d; > + > + printk(KERN_INFO "pm_dbg_init()\n"); > + > + d = debugfs_create_dir("pm_debug", NULL); > + if (IS_ERR(d)) > + return PTR_ERR(d); > + > + (void) debugfs_create_file("count", S_IRUGO, > + d, (void *)DEBUG_FILE_COUNTERS, &debug_fops); > + (void) debugfs_create_file("time", S_IRUGO, > + d, (void *)DEBUG_FILE_TIMERS, &debug_fops); > + > + pwrdm_for_each(pwrdms_setup, NULL); > + > + pm_dbg_init_done = 1; > + > + return 0; > +} > +late_initcall(pm_dbg_init); > + > +#endif > + > #endif > diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h > index 68c9278..fb6693b 100644 > --- a/arch/arm/mach-omap2/pm.h > +++ b/arch/arm/mach-omap2/pm.h > @@ -31,6 +31,7 @@ extern void serial_console_fclk_mask(u32 *f1, u32 *f2); > extern void pm_init_serial_console(void); > extern void serial_console_sleep(int enable); > extern int omap2_pm_debug; > +extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev); > #else > #define omap2_read_32k_sync_counter() 0 > #define serial_console_sleep(enable) do {} while (0); > @@ -38,5 +39,6 @@ extern int omap2_pm_debug; > #define omap2_pm_dump(mode, resume, us) do {} while (0); > #define serial_console_fclk_mask(f1, f2) do {} while (0); > #define omap2_pm_debug 0 > +#define pm_dbg_update_time(pwrdm, prev) do {} while (0); > #endif /* CONFIG_PM_DEBUG */ > #endif > -- > 1.5.6.3 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > > -- Jouni Högander -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [PATCH 2/3] Add pm-debug counters 2008-10-15 6:12 ` Högander Jouni @ 2008-10-15 9:54 ` Tero.Kristo 0 siblings, 0 replies; 13+ messages in thread From: Tero.Kristo @ 2008-10-15 9:54 UTC (permalink / raw) To: jouni.hogander, Peter.De-Schrijver, paul; +Cc: linux-omap >"ext Peter 'p2' De Schrijver" <peter.de-schrijver@nokia.com> writes: > >> This patch provides the debugfs entries and a function which will be >> called by the PM code to register the time spent per domain >per state. >> >> Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com> >> --- >> arch/arm/mach-omap2/pm-debug.c | 175 >+++++++++++++++++++++++++ >> arch/arm/mach-omap2/pm.h | 2 + >> 2 files changed, 177 insertions(+) >> >> diff --git a/arch/arm/mach-omap2/pm-debug.c >> b/arch/arm/mach-omap2/pm-debug.c index 0b5c044..4ba6cec 100644 >> --- a/arch/arm/mach-omap2/pm-debug.c >> +++ b/arch/arm/mach-omap2/pm-debug.c >> @@ -29,6 +29,8 @@ >> >> #include <mach/clock.h> >> #include <mach/board.h> >> +#include <mach/powerdomain.h> >> +#include <mach/clockdomain.h> >> >> #include "prm.h" >> #include "cm.h" >> @@ -288,4 +290,177 @@ void omap2_pm_dump(int mode, int >resume, unsigned int us) >> printk("%-20s: 0x%08x\n", regs[i].name, regs[i].val); } >> >> +#ifdef CONFIG_DEBUG_FS >> +#include <linux/debugfs.h> >> +#include <linux/seq_file.h> >> + >> +struct dentry *pm_dbg_dir; >> + >> +static int pm_dbg_init_done; >> + >> +enum { >> + DEBUG_FILE_COUNTERS = 0, >> + DEBUG_FILE_TIMERS, >> +}; >> + >> +static const char pwrdm_state_names[][4] = { >> + "OFF", >> + "RET", >> + "INA", >> + "ON" >> +}; >> + >> +void pm_dbg_update_time(struct powerdomain *pwrdm, int prev) { >> + s64 t; >> + struct timespec now; >> + >> + if (!pm_dbg_init_done) >> + return ; >> + >> + /* Update timer for previous state */ >> + getnstimeofday(&now); >> + t = timespec_to_ns(&now); >> + >> + pwrdm->state_timer[prev] += t - pwrdm->timer; >> + >> + pwrdm->timer = t; >> +} >> + >> +static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void >> +*user) { >> + struct seq_file *s = (struct seq_file *)user; >> + >> + if (strcmp(clkdm->name, "emu_clkdm") == 0 || >> + strcmp(clkdm->name, "wkup_clkdm") == 0) >> + return 0; > >Why emu and wkup are not taken into account? If wkup is closed >out here, I think also prm_clkdm and cm_clkdm should be. > >> + >> + seq_printf(s, "%s->%s (%d)", clkdm->name, >> + clkdm->pwrdm.ptr->name, >> + atomic_read(&clkdm->usecount)); >> + seq_printf(s, "\n"); >> + >> + return 0; >> +} >> + >> +static int pwrdm_dbg_show_counter(struct powerdomain *pwrdm, void >> +*user) { >> + struct seq_file *s = (struct seq_file *)user; >> + int i; >> + >> + if (strcmp(pwrdm->name, "emu_pwrdm") == 0 || >> + strcmp(pwrdm->name, "wkup_pwrdm") == 0) >> + return 0; > >Why emu is closed out here? It has pwstst register. I closed out emu and wkup powerdomains here because they did not show any useful information. They are missing either prepwstst or pwstst register and this debug stuff relies on accessibility of both of them. If you do not have one, you get "interesting" results (missing prepwstst => OFF count hits the roof as the software assumes you are entering off mode during each sleep period, missing pwstst => you are in OFF state always.) You could show the current state for emu powerdomain yes, but not counters. >I think >also dpll1..5_pwrdm should be closed out here. I'm not sure >why those are even modelled in a clocktree. I tracked the powerdomain code a bit, and it seems dpll1...dpll5 are mapped to some real software accessible powerdomains. E.g. we have dpll1 -> MPU_MOD. Now, a side effect of this is that when you access such a powerdomain, you may alter the HW registers of another powerdomain, which you probably did not want to do. Nasty part of this is that some code does pwrdm_for_each() calls to modify status of all powerdomains, like pm34xx.c. Question for Paul: Is the powerdomain code safe against this kind of stuff? > >> + >> + if (pwrdm->state != pwrdm_read_pwrst(pwrdm)) >> + printk(KERN_ERR "pwrdm state mismatch(%s) %d != %d\n", >> + pwrdm->name, pwrdm->state, >pwrdm_read_pwrst(pwrdm)); >> + >> + seq_printf(s, "%s (%s)", pwrdm->name, >> + pwrdm_state_names[pwrdm->state]); >> + for (i = 0; i < 4; i++) >> + seq_printf(s, ",%s:%d", pwrdm_state_names[i], >> + pwrdm->state_counter[i]); >> + >> + seq_printf(s, "\n"); >> + >> + return 0; >> +} >> + >> +static int pwrdm_dbg_show_timer(struct powerdomain *pwrdm, void >> +*user) { >> + struct seq_file *s = (struct seq_file *)user; >> + int i; >> + >> + if (strcmp(pwrdm->name, "emu_pwrdm") == 0 || >> + strcmp(pwrdm->name, "wkup_pwrdm") == 0) >> + return 0; > >Same comment as above. > >> + >> + pwrdm_state_switch(pwrdm); >> + >> + seq_printf(s, "%s (%s)", pwrdm->name, >> + pwrdm_state_names[pwrdm->state]); >> + >> + for (i = 0; i < 4; i++) >> + seq_printf(s, ",%s:%lld", pwrdm_state_names[i], >> + pwrdm->state_timer[i]); >> + >> + seq_printf(s, "\n"); >> + >> + return 0; >> +} >> + >> +static void pm_dbg_show_counters(struct seq_file *s, void *unused) { >> + pwrdm_for_each(pwrdm_dbg_show_counter, s); >> + clkdm_for_each(clkdm_dbg_show_counter, s); } >> + >> +static void pm_dbg_show_timers(struct seq_file *s, void *unused) { >> + pwrdm_for_each(pwrdm_dbg_show_timer, s); } >> + >> +static int pm_dbg_open(struct inode *inode, struct file *file) { >> + switch ((int)inode->i_private) { >> + case DEBUG_FILE_COUNTERS: >> + return single_open(file, pm_dbg_show_counters, >> + &inode->i_private); >> + case DEBUG_FILE_TIMERS: >> + default: >> + return single_open(file, pm_dbg_show_timers, >> + &inode->i_private); >> + }; >> +} >> + >> +static const struct file_operations debug_fops = { >> + .open = pm_dbg_open, >> + .read = seq_read, >> + .llseek = seq_lseek, >> + .release = single_release, >> +}; >> + >> +static int __init pwrdms_setup(struct powerdomain *pwrdm, void >> +*unused) { >> + int i; >> + s64 t; >> + struct timespec now; >> + >> + getnstimeofday(&now); >> + t = timespec_to_ns(&now); >> + >> + for (i = 0; i < 4; i++) >> + pwrdm->state_timer[i] = 0; >> + >> + pwrdm->timer = t; >> + >> + return 0; >> +} >> + >> +static int __init pm_dbg_init(void) >> +{ >> + struct dentry *d; >> + >> + printk(KERN_INFO "pm_dbg_init()\n"); >> + >> + d = debugfs_create_dir("pm_debug", NULL); >> + if (IS_ERR(d)) >> + return PTR_ERR(d); >> + >> + (void) debugfs_create_file("count", S_IRUGO, >> + d, (void *)DEBUG_FILE_COUNTERS, &debug_fops); >> + (void) debugfs_create_file("time", S_IRUGO, >> + d, (void *)DEBUG_FILE_TIMERS, &debug_fops); >> + >> + pwrdm_for_each(pwrdms_setup, NULL); >> + >> + pm_dbg_init_done = 1; >> + >> + return 0; >> +} >> +late_initcall(pm_dbg_init); >> + >> +#endif >> + >> #endif >> diff --git a/arch/arm/mach-omap2/pm.h >b/arch/arm/mach-omap2/pm.h index >> 68c9278..fb6693b 100644 >> --- a/arch/arm/mach-omap2/pm.h >> +++ b/arch/arm/mach-omap2/pm.h >> @@ -31,6 +31,7 @@ extern void serial_console_fclk_mask(u32 *f1, u32 >> *f2); extern void pm_init_serial_console(void); extern void >> serial_console_sleep(int enable); extern int omap2_pm_debug; >> +extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev); >> #else >> #define omap2_read_32k_sync_counter() 0 >> #define serial_console_sleep(enable) do {} while (0); >> @@ -38,5 +39,6 @@ extern int omap2_pm_debug; >> #define omap2_pm_dump(mode, resume, us) do {} while (0); >> #define serial_console_fclk_mask(f1, f2) do {} while (0); >> #define omap2_pm_debug 0 >> +#define pm_dbg_update_time(pwrdm, prev) do {} while (0); >> #endif /* CONFIG_PM_DEBUG */ >> #endif >> -- >> 1.5.6.3 >> >> -- >> To unsubscribe from this list: send the line "unsubscribe >linux-omap" >> in the body of a message to majordomo@vger.kernel.org More majordomo >> info at http://vger.kernel.org/majordomo-info.html >> >> > >-- >Jouni Högander > >-- >To unsubscribe from this list: send the line "unsubscribe >linux-omap" in the body of a message to >majordomo@vger.kernel.org More majordomo info at >http://vger.kernel.org/majordomo-info.html > -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 1/3] Add closures to clkdm_for_each and pwrdm_for_each. 2008-10-14 14:39 ` [PATCH 1/3] Add closures to clkdm_for_each and pwrdm_for_each Peter 'p2' De Schrijver 2008-10-14 14:39 ` [PATCH 2/3] Add pm-debug counters Peter 'p2' De Schrijver @ 2008-10-14 19:50 ` Paul Walmsley 1 sibling, 0 replies; 13+ messages in thread From: Paul Walmsley @ 2008-10-14 19:50 UTC (permalink / raw) To: Peter 'p2' De Schrijver; +Cc: linux-omap Hello Peter, one very minor comment: On Tue, 14 Oct 2008, Peter 'p2' De Schrijver wrote: > diff --git a/arch/arm/plat-omap/include/mach/powerdomain.h b/arch/arm/plat-omap/include/mach/powerdomain.h > index 52663fc..6271d85 100644 > --- a/arch/arm/plat-omap/include/mach/powerdomain.h > +++ b/arch/arm/plat-omap/include/mach/powerdomain.h > @@ -119,6 +119,11 @@ struct powerdomain { > > int state; > unsigned state_counter[4]; > + > +#ifdef CONFIG_PM_DEBUG > + s64 timer; > + s64 state_timer[4]; > +#endif > }; this probably goes best in patch 2/3? Other than that, looks good to me. - Paul ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 0/3] debugfs entries for PM counters 2008-10-14 14:39 [PATCH 0/3] debugfs entries for PM counters Peter 'p2' De Schrijver 2008-10-14 14:39 ` [PATCH 1/3] Add closures to clkdm_for_each and pwrdm_for_each Peter 'p2' De Schrijver @ 2008-10-29 18:22 ` Kevin Hilman 1 sibling, 0 replies; 13+ messages in thread From: Kevin Hilman @ 2008-10-29 18:22 UTC (permalink / raw) To: Peter 'p2' De Schrijver; +Cc: linux-omap Peter 'p2' De Schrijver wrote: > This patchset adds 2 debugfs entries for power management counters. > pm_debug/count indicates how many times each powerdomain entered each state > (On, Inactive, Retention, Off). > pm_debug/time indicates how much time each powerdomain spent per state. > > Peter 'p2' De Schrijver (3): > Add closures to clkdm_for_each. > Add pm-debug counters > Hook into powerdomain code > Thanks, pulling this series into next PM branch. Kevin ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 0/3] debugfs entries for PM counters @ 2008-10-15 15:13 Peter 'p2' De Schrijver 2008-10-15 15:13 ` [PATCH 1/3] Add closures to clkdm_for_each and pwrdm_for_each Peter 'p2' De Schrijver 0 siblings, 1 reply; 13+ messages in thread From: Peter 'p2' De Schrijver @ 2008-10-15 15:13 UTC (permalink / raw) To: linux-omap; +Cc: Peter 'p2' De Schrijver This patchset adds 2 debugfs entries for power management counters. pm_debug/count indicates how many times each powerdomain entered each state (On, Inactive, Retention, Off). pm_debug/time indicates how much time each powerdomain spent per state. Peter 'p2' De Schrijver (3): Add closures to clkdm_for_each and pwrdm_for_each. Add pm-debug counters Hook into powerdomain code arch/arm/mach-omap2/clockdomain.c | 5 +- arch/arm/mach-omap2/pm-debug.c | 175 +++++++++++++++++++++++++ arch/arm/mach-omap2/pm.h | 2 + arch/arm/mach-omap2/pm34xx.c | 8 +- arch/arm/mach-omap2/powerdomain.c | 17 ++- arch/arm/plat-omap/include/mach/clockdomain.h | 3 +- arch/arm/plat-omap/include/mach/powerdomain.h | 8 +- 7 files changed, 204 insertions(+), 14 deletions(-) ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/3] Add closures to clkdm_for_each and pwrdm_for_each. 2008-10-15 15:13 Peter 'p2' De Schrijver @ 2008-10-15 15:13 ` Peter 'p2' De Schrijver 2008-10-15 15:13 ` [PATCH 2/3] Add pm-debug counters Peter 'p2' De Schrijver 0 siblings, 1 reply; 13+ messages in thread From: Peter 'p2' De Schrijver @ 2008-10-15 15:13 UTC (permalink / raw) To: linux-omap; +Cc: Peter 'p2' De Schrijver First add some infrastructure to easily iterate over clock and power domains. Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com> --- arch/arm/mach-omap2/clockdomain.c | 5 +++-- arch/arm/mach-omap2/pm34xx.c | 8 ++++---- arch/arm/plat-omap/include/mach/clockdomain.h | 3 ++- arch/arm/plat-omap/include/mach/powerdomain.h | 3 ++- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 5249fe8..b0b5885 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -295,7 +295,8 @@ struct clockdomain *clkdm_lookup(const char *name) * anything else to indicate failure; or -EINVAL if the function pointer * is null. */ -int clkdm_for_each(int (*fn)(struct clockdomain *clkdm)) +int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user), + void *user) { struct clockdomain *clkdm; int ret = 0; @@ -305,7 +306,7 @@ int clkdm_for_each(int (*fn)(struct clockdomain *clkdm)) mutex_lock(&clkdm_mutex); list_for_each_entry(clkdm, &clkdm_list, node) { - ret = (*fn)(clkdm); + ret = (*fn)(clkdm, user); if (ret) break; } diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 1fbb690..be69839 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -518,7 +518,7 @@ static void __init prcm_setup_regs(void) OCP_MOD, OMAP2_PRM_IRQENABLE_MPU_OFFSET); } -static int __init pwrdms_setup(struct powerdomain *pwrdm) +static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused) { struct power_state *pwrst; @@ -538,7 +538,7 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm) return set_pwrdm_state(pwrst->pwrdm, pwrst->next_state); } -static int __init clkdms_setup(struct clockdomain *clkdm) +static int __init clkdms_setup(struct clockdomain *clkdm, void *unused) { omap2_clkdm_allow_idle(clkdm); return 0; @@ -564,13 +564,13 @@ int __init omap3_pm_init(void) goto err1; } - ret = pwrdm_for_each(pwrdms_setup); + ret = pwrdm_for_each(pwrdms_setup, NULL); if (ret) { printk(KERN_ERR "Failed to setup powerdomains\n"); goto err2; } - (void) clkdm_for_each(clkdms_setup); + (void) clkdm_for_each(clkdms_setup, NULL); mpu_pwrdm = pwrdm_lookup("mpu_pwrdm"); if (mpu_pwrdm == NULL) { diff --git a/arch/arm/plat-omap/include/mach/clockdomain.h b/arch/arm/plat-omap/include/mach/clockdomain.h index b9d0dd2..99ebd88 100644 --- a/arch/arm/plat-omap/include/mach/clockdomain.h +++ b/arch/arm/plat-omap/include/mach/clockdomain.h @@ -95,7 +95,8 @@ int clkdm_register(struct clockdomain *clkdm); int clkdm_unregister(struct clockdomain *clkdm); struct clockdomain *clkdm_lookup(const char *name); -int clkdm_for_each(int (*fn)(struct clockdomain *clkdm)); +int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user), + void *user); struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm); void omap2_clkdm_allow_idle(struct clockdomain *clkdm); diff --git a/arch/arm/plat-omap/include/mach/powerdomain.h b/arch/arm/plat-omap/include/mach/powerdomain.h index 52663fc..de03f3d 100644 --- a/arch/arm/plat-omap/include/mach/powerdomain.h +++ b/arch/arm/plat-omap/include/mach/powerdomain.h @@ -128,7 +128,8 @@ int pwrdm_register(struct powerdomain *pwrdm); int pwrdm_unregister(struct powerdomain *pwrdm); struct powerdomain *pwrdm_lookup(const char *name); -int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm)); +int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user), + void *user); int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm); int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm); -- 1.5.6.3 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 2/3] Add pm-debug counters 2008-10-15 15:13 ` [PATCH 1/3] Add closures to clkdm_for_each and pwrdm_for_each Peter 'p2' De Schrijver @ 2008-10-15 15:13 ` Peter 'p2' De Schrijver 2008-10-15 15:13 ` [PATCH 3/3] Hook into powerdomain code Peter 'p2' De Schrijver 0 siblings, 1 reply; 13+ messages in thread From: Peter 'p2' De Schrijver @ 2008-10-15 15:13 UTC (permalink / raw) To: linux-omap; +Cc: Peter 'p2' De Schrijver This patch provides the debugfs entries and a function which will be called by the PM code to register the time spent per domain per state. Also some new fields are added to the powerdomain struct to keep the time information. Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com> --- arch/arm/mach-omap2/pm-debug.c | 175 +++++++++++++++++++++++++ arch/arm/mach-omap2/pm.h | 2 + arch/arm/plat-omap/include/mach/powerdomain.h | 5 + 3 files changed, 182 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c index 0b5c044..4ba6cec 100644 --- a/arch/arm/mach-omap2/pm-debug.c +++ b/arch/arm/mach-omap2/pm-debug.c @@ -29,6 +29,8 @@ #include <mach/clock.h> #include <mach/board.h> +#include <mach/powerdomain.h> +#include <mach/clockdomain.h> #include "prm.h" #include "cm.h" @@ -288,4 +290,177 @@ void omap2_pm_dump(int mode, int resume, unsigned int us) printk("%-20s: 0x%08x\n", regs[i].name, regs[i].val); } +#ifdef CONFIG_DEBUG_FS +#include <linux/debugfs.h> +#include <linux/seq_file.h> + +struct dentry *pm_dbg_dir; + +static int pm_dbg_init_done; + +enum { + DEBUG_FILE_COUNTERS = 0, + DEBUG_FILE_TIMERS, +}; + +static const char pwrdm_state_names[][4] = { + "OFF", + "RET", + "INA", + "ON" +}; + +void pm_dbg_update_time(struct powerdomain *pwrdm, int prev) +{ + s64 t; + struct timespec now; + + if (!pm_dbg_init_done) + return ; + + /* Update timer for previous state */ + getnstimeofday(&now); + t = timespec_to_ns(&now); + + pwrdm->state_timer[prev] += t - pwrdm->timer; + + pwrdm->timer = t; +} + +static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user) +{ + struct seq_file *s = (struct seq_file *)user; + + if (strcmp(clkdm->name, "emu_clkdm") == 0 || + strcmp(clkdm->name, "wkup_clkdm") == 0) + return 0; + + seq_printf(s, "%s->%s (%d)", clkdm->name, + clkdm->pwrdm.ptr->name, + atomic_read(&clkdm->usecount)); + seq_printf(s, "\n"); + + return 0; +} + +static int pwrdm_dbg_show_counter(struct powerdomain *pwrdm, void *user) +{ + struct seq_file *s = (struct seq_file *)user; + int i; + + if (strcmp(pwrdm->name, "emu_pwrdm") == 0 || + strcmp(pwrdm->name, "wkup_pwrdm") == 0) + return 0; + + if (pwrdm->state != pwrdm_read_pwrst(pwrdm)) + printk(KERN_ERR "pwrdm state mismatch(%s) %d != %d\n", + pwrdm->name, pwrdm->state, pwrdm_read_pwrst(pwrdm)); + + seq_printf(s, "%s (%s)", pwrdm->name, + pwrdm_state_names[pwrdm->state]); + for (i = 0; i < 4; i++) + seq_printf(s, ",%s:%d", pwrdm_state_names[i], + pwrdm->state_counter[i]); + + seq_printf(s, "\n"); + + return 0; +} + +static int pwrdm_dbg_show_timer(struct powerdomain *pwrdm, void *user) +{ + struct seq_file *s = (struct seq_file *)user; + int i; + + if (strcmp(pwrdm->name, "emu_pwrdm") == 0 || + strcmp(pwrdm->name, "wkup_pwrdm") == 0) + return 0; + + pwrdm_state_switch(pwrdm); + + seq_printf(s, "%s (%s)", pwrdm->name, + pwrdm_state_names[pwrdm->state]); + + for (i = 0; i < 4; i++) + seq_printf(s, ",%s:%lld", pwrdm_state_names[i], + pwrdm->state_timer[i]); + + seq_printf(s, "\n"); + + return 0; +} + +static void pm_dbg_show_counters(struct seq_file *s, void *unused) +{ + pwrdm_for_each(pwrdm_dbg_show_counter, s); + clkdm_for_each(clkdm_dbg_show_counter, s); +} + +static void pm_dbg_show_timers(struct seq_file *s, void *unused) +{ + pwrdm_for_each(pwrdm_dbg_show_timer, s); +} + +static int pm_dbg_open(struct inode *inode, struct file *file) +{ + switch ((int)inode->i_private) { + case DEBUG_FILE_COUNTERS: + return single_open(file, pm_dbg_show_counters, + &inode->i_private); + case DEBUG_FILE_TIMERS: + default: + return single_open(file, pm_dbg_show_timers, + &inode->i_private); + }; +} + +static const struct file_operations debug_fops = { + .open = pm_dbg_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused) +{ + int i; + s64 t; + struct timespec now; + + getnstimeofday(&now); + t = timespec_to_ns(&now); + + for (i = 0; i < 4; i++) + pwrdm->state_timer[i] = 0; + + pwrdm->timer = t; + + return 0; +} + +static int __init pm_dbg_init(void) +{ + struct dentry *d; + + printk(KERN_INFO "pm_dbg_init()\n"); + + d = debugfs_create_dir("pm_debug", NULL); + if (IS_ERR(d)) + return PTR_ERR(d); + + (void) debugfs_create_file("count", S_IRUGO, + d, (void *)DEBUG_FILE_COUNTERS, &debug_fops); + (void) debugfs_create_file("time", S_IRUGO, + d, (void *)DEBUG_FILE_TIMERS, &debug_fops); + + pwrdm_for_each(pwrdms_setup, NULL); + + pm_dbg_init_done = 1; + + return 0; +} +late_initcall(pm_dbg_init); + +#endif + #endif diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index 68c9278..fb6693b 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -31,6 +31,7 @@ extern void serial_console_fclk_mask(u32 *f1, u32 *f2); extern void pm_init_serial_console(void); extern void serial_console_sleep(int enable); extern int omap2_pm_debug; +extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev); #else #define omap2_read_32k_sync_counter() 0 #define serial_console_sleep(enable) do {} while (0); @@ -38,5 +39,6 @@ extern int omap2_pm_debug; #define omap2_pm_dump(mode, resume, us) do {} while (0); #define serial_console_fclk_mask(f1, f2) do {} while (0); #define omap2_pm_debug 0 +#define pm_dbg_update_time(pwrdm, prev) do {} while (0); #endif /* CONFIG_PM_DEBUG */ #endif diff --git a/arch/arm/plat-omap/include/mach/powerdomain.h b/arch/arm/plat-omap/include/mach/powerdomain.h index de03f3d..6271d85 100644 --- a/arch/arm/plat-omap/include/mach/powerdomain.h +++ b/arch/arm/plat-omap/include/mach/powerdomain.h @@ -119,6 +119,11 @@ struct powerdomain { int state; unsigned state_counter[4]; + +#ifdef CONFIG_PM_DEBUG + s64 timer; + s64 state_timer[4]; +#endif }; -- 1.5.6.3 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 3/3] Hook into powerdomain code 2008-10-15 15:13 ` [PATCH 2/3] Add pm-debug counters Peter 'p2' De Schrijver @ 2008-10-15 15:13 ` Peter 'p2' De Schrijver 0 siblings, 0 replies; 13+ messages in thread From: Peter 'p2' De Schrijver @ 2008-10-15 15:13 UTC (permalink / raw) To: linux-omap; +Cc: Peter 'p2' De Schrijver Make the powerdomain code call the new hook for updating the time. Also implement the updated pwrdm_for_each. Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com> --- arch/arm/mach-omap2/powerdomain.c | 17 +++++++++++------ 1 files changed, 11 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index 3a9e151..0334609 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c @@ -35,6 +35,8 @@ #include <mach/powerdomain.h> #include <mach/clockdomain.h> +#include "pm.h" + enum { PWRDM_STATE_NOW = 0, PWRDM_STATE_PREV, @@ -134,19 +136,21 @@ static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag) if (state != prev) pwrdm->state_counter[state]++; + pm_dbg_update_time(pwrdm, prev); + pwrdm->state = state; return 0; } -static int _pwrdm_pre_transition_cb(struct powerdomain *pwrdm) +static int _pwrdm_pre_transition_cb(struct powerdomain *pwrdm, void *unused) { pwrdm_clear_all_prev_pwrst(pwrdm); _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW); return 0; } -static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm) +static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused) { _pwrdm_state_switch(pwrdm, PWRDM_STATE_PREV); return 0; @@ -282,7 +286,8 @@ struct powerdomain *pwrdm_lookup(const char *name) * anything else to indicate failure; or -EINVAL if the function * pointer is null. */ -int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm)) +int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user), + void *user) { struct powerdomain *temp_pwrdm; unsigned long flags; @@ -293,7 +298,7 @@ int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm)) read_lock_irqsave(&pwrdm_rwlock, flags); list_for_each_entry(temp_pwrdm, &pwrdm_list, node) { - ret = (*fn)(temp_pwrdm); + ret = (*fn)(temp_pwrdm, user); if (ret) break; } @@ -1198,13 +1203,13 @@ int pwrdm_clk_state_switch(struct clk *clk) int pwrdm_pre_transition(void) { - pwrdm_for_each(_pwrdm_pre_transition_cb); + pwrdm_for_each(_pwrdm_pre_transition_cb, NULL); return 0; } int pwrdm_post_transition(void) { - pwrdm_for_each(_pwrdm_post_transition_cb); + pwrdm_for_each(_pwrdm_post_transition_cb, NULL); return 0; } -- 1.5.6.3 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 0/3] Add PM debug counters on top of PM counters @ 2008-10-07 13:33 Peter 'p2' De Schrijver 2008-10-07 13:33 ` [PATCH 1/3] Add closures to clkdm_for_each Peter 'p2' De Schrijver 0 siblings, 1 reply; 13+ messages in thread From: Peter 'p2' De Schrijver @ 2008-10-07 13:33 UTC (permalink / raw) To: linux-omap; +Cc: Peter 'p2' De Schrijver This patch provides the PM debug counters and time feature on top of the PM counters. Patch based on pm-1 branch + PM counters patch. Peter 'p2' De Schrijver (3): Add closures to clkdm_for_each Add pm-debug counters Hook into powerdomain code arch/arm/mach-omap2/clockdomain.c | 31 +----- arch/arm/mach-omap2/pm-debug.c | 153 ++++++++++++------------- arch/arm/mach-omap2/pm.h | 19 +--- arch/arm/mach-omap2/pm24xx.c | 2 +- arch/arm/mach-omap2/pm34xx.c | 13 +-- arch/arm/mach-omap2/powerdomain.c | 95 +++------------- arch/arm/plat-omap/include/mach/clockdomain.h | 3 +- arch/arm/plat-omap/include/mach/powerdomain.h | 14 ++- 8 files changed, 114 insertions(+), 216 deletions(-) ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/3] Add closures to clkdm_for_each 2008-10-07 13:33 [PATCH 0/3] Add PM debug counters on top of PM counters Peter 'p2' De Schrijver @ 2008-10-07 13:33 ` Peter 'p2' De Schrijver 2008-10-07 13:33 ` [PATCH 2/3] Add pm-debug counters Peter 'p2' De Schrijver 0 siblings, 1 reply; 13+ messages in thread From: Peter 'p2' De Schrijver @ 2008-10-07 13:33 UTC (permalink / raw) To: linux-omap; +Cc: Peter 'p2' De Schrijver Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com> --- arch/arm/mach-omap2/clockdomain.c | 31 ++---------------------- arch/arm/mach-omap2/pm24xx.c | 2 +- arch/arm/mach-omap2/pm34xx.c | 13 ++++------ arch/arm/plat-omap/include/mach/clockdomain.h | 3 +- 4 files changed, 11 insertions(+), 38 deletions(-) diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 33290a7..f0f02a5 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -297,7 +297,8 @@ struct clockdomain *clkdm_lookup(const char *name) * anything else to indicate failure; or -EINVAL if the function pointer * is null. */ -int clkdm_for_each(int (*fn)(struct clockdomain *clkdm)) +int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user), + void *user) { struct clockdomain *clkdm; int ret = 0; @@ -307,7 +308,7 @@ int clkdm_for_each(int (*fn)(struct clockdomain *clkdm)) mutex_lock(&clkdm_mutex); list_for_each_entry(clkdm, &clkdm_list, node) { - ret = (*fn)(clkdm); + ret = (*fn)(clkdm, user); if (ret) break; } @@ -569,8 +570,6 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) else omap2_clkdm_wakeup(clkdm); - pm_dbg_clkdm_state_switch(clkdm); - pwrdm_clkdm_state_switch(clkdm); return 0; @@ -624,31 +623,7 @@ int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk) else omap2_clkdm_sleep(clkdm); - pm_dbg_clkdm_state_switch(clkdm); - pwrdm_clkdm_state_switch(clkdm); return 0; } - -#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) -#include <linux/debugfs.h> -#include <linux/seq_file.h> -int clkdm_dbg_show_counters(struct seq_file *s, void *unused) -{ - struct clockdomain *clkdm; - - list_for_each_entry(clkdm, &clkdm_list, node) { - if (strcmp(clkdm->name, "emu_clkdm") == 0 || - strcmp(clkdm->name, "wkup_clkdm") == 0) - continue; - seq_printf(s, "%s->%s (%d)", clkdm->name, - clkdm->pwrdm.ptr->name, - atomic_read(&clkdm->usecount)); - seq_printf(s, "\n"); - } - - return 0; -} - -#endif diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c index 4be9385..3ec68f7 100644 --- a/arch/arm/mach-omap2/pm24xx.c +++ b/arch/arm/mach-omap2/pm24xx.c @@ -401,7 +401,7 @@ static void __init prcm_setup_regs(void) omap2_clkdm_sleep(gfx_clkdm); /* Enable clockdomain hardware-supervised control for all clkdms */ - clkdm_for_each(_pm_clkdm_enable_hwsup); + clkdm_for_each(_pm_clkdm_enable_hwsup, NULL); /* Enable clock autoidle for all domains */ cm_write_mod_reg(OMAP24XX_AUTO_CAM | diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 90e108b..2688086 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -174,8 +174,6 @@ static void omap_sram_idle(void) disable_smartreflex(SR1); disable_smartreflex(SR2); - pm_dbg_pre_suspend(); - pwrdm_pre_transition(); omap2_gpio_prepare_for_retention(); @@ -192,13 +190,12 @@ static void omap_sram_idle(void) omap2_gpio_resume_after_retention(); - pm_dbg_post_suspend(); + pwrdm_post_transition(); /* Enable smartreflex after WFI */ enable_smartreflex(SR1); enable_smartreflex(SR2); - pwrdm_post_transition(); } @@ -538,7 +535,7 @@ static void __init prcm_setup_regs(void) OCP_MOD, OMAP2_PRM_IRQENABLE_MPU_OFFSET); } -static int __init pwrdms_setup(struct powerdomain *pwrdm) +static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused) { struct power_state *pwrst; @@ -558,7 +555,7 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm) return set_pwrdm_state(pwrst->pwrdm, pwrst->next_state); } -static int __init clkdms_setup(struct clockdomain *clkdm) +static int __init clkdms_setup(struct clockdomain *clkdm, void *unused) { omap2_clkdm_allow_idle(clkdm); return 0; @@ -584,13 +581,13 @@ int __init omap3_pm_init(void) goto err1; } - ret = pwrdm_for_each(pwrdms_setup); + ret = pwrdm_for_each(pwrdms_setup, NULL); if (ret) { printk(KERN_ERR "Failed to setup powerdomains\n"); goto err2; } - (void) clkdm_for_each(clkdms_setup); + (void) clkdm_for_each(clkdms_setup, NULL); mpu_pwrdm = pwrdm_lookup("mpu_pwrdm"); if (mpu_pwrdm == NULL) { diff --git a/arch/arm/plat-omap/include/mach/clockdomain.h b/arch/arm/plat-omap/include/mach/clockdomain.h index b9d0dd2..99ebd88 100644 --- a/arch/arm/plat-omap/include/mach/clockdomain.h +++ b/arch/arm/plat-omap/include/mach/clockdomain.h @@ -95,7 +95,8 @@ int clkdm_register(struct clockdomain *clkdm); int clkdm_unregister(struct clockdomain *clkdm); struct clockdomain *clkdm_lookup(const char *name); -int clkdm_for_each(int (*fn)(struct clockdomain *clkdm)); +int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user), + void *user); struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm); void omap2_clkdm_allow_idle(struct clockdomain *clkdm); -- 1.5.6.3 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 2/3] Add pm-debug counters 2008-10-07 13:33 ` [PATCH 1/3] Add closures to clkdm_for_each Peter 'p2' De Schrijver @ 2008-10-07 13:33 ` Peter 'p2' De Schrijver 2008-10-07 13:33 ` [PATCH 3/3] Hook into powerdomain code Peter 'p2' De Schrijver 0 siblings, 1 reply; 13+ messages in thread From: Peter 'p2' De Schrijver @ 2008-10-07 13:33 UTC (permalink / raw) To: linux-omap; +Cc: Peter 'p2' De Schrijver Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com> --- arch/arm/mach-omap2/pm-debug.c | 153 ++++++++++++------------- arch/arm/mach-omap2/pm.h | 19 +--- arch/arm/plat-omap/include/mach/powerdomain.h | 14 ++- 3 files changed, 87 insertions(+), 99 deletions(-) diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c index 380a2a0..64d40c4 100644 --- a/arch/arm/mach-omap2/pm-debug.c +++ b/arch/arm/mach-omap2/pm-debug.c @@ -167,8 +167,8 @@ struct dentry *pm_dbg_dir; static int pm_dbg_init_done; enum { - PM_DBG_STATE_NOW = 0, - PM_DBG_STATE_PREV, + DEBUG_FILE_COUNTERS = 0, + DEBUG_FILE_TIMERS, }; struct pm_module_def { @@ -218,6 +218,13 @@ static const struct pm_module_def pm_dbg_reg_modules[] = { static void *pm_dbg_reg_set[PM_DBG_MAX_REG_SETS]; +static const char pwrdm_state_names[][4] = { + "OFF", + "RET", + "INA", + "ON" +}; + static int pm_dbg_get_regset_size(void) { static int regset_size; @@ -318,107 +325,96 @@ int pm_dbg_regset_save(int reg_set) return 0; } -static int _pm_dbg_state_switch(struct powerdomain *pwrdm, int flag) +void pm_dbg_update_time(struct powerdomain *pwrdm, int prev) { s64 t; struct timespec now; - int prev; - int state; - if (pwrdm == NULL) - return -EINVAL; + if (!pm_dbg_init_done) + return ; - state = pwrdm_read_pwrst(pwrdm); + /* Update timer for previous state */ + getnstimeofday(&now); + t = timespec_to_ns(&now); - switch (flag) { - case PM_DBG_STATE_NOW: - prev = pwrdm->state; - break; - case PM_DBG_STATE_PREV: - prev = pwrdm_read_prev_pwrst(pwrdm); - if (pwrdm->state != prev) - pwrdm->state_counter[prev]++; - break; - default: - return -EINVAL; - } + pwrdm->state_timer[prev] += t - pwrdm->timer; - if (pm_dbg_init_done) { - /* Update timer for previous state */ - getnstimeofday(&now); - t = timespec_to_ns(&now); + pwrdm->timer = t; - pwrdm->state_timer[prev] += t - pwrdm->timer; +} - pwrdm->timer = t; +static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user) +{ + struct seq_file *s = (struct seq_file *)user; - if (state != prev) - pwrdm->state_counter[state]++; - } + if (strcmp(clkdm->name, "emu_clkdm") == 0 || + strcmp(clkdm->name, "wkup_clkdm") == 0) + return 0; - pwrdm->state = state; + seq_printf(s, "%s->%s (%d)", clkdm->name, + clkdm->pwrdm.ptr->name, + atomic_read(&clkdm->usecount)); + seq_printf(s, "\n"); return 0; } -int pm_dbg_pwrdm_state_switch(struct powerdomain *pwrdm) +static int pwrdm_dbg_show_counter(struct powerdomain *pwrdm, void *user) { - return _pm_dbg_state_switch(pwrdm, PM_DBG_STATE_NOW); -} + struct seq_file *s = (struct seq_file *)user; + int i; -int pm_dbg_clkdm_state_switch(struct clockdomain *clkdm) -{ - if (clkdm != NULL && clkdm->pwrdm.ptr != NULL) { - pwrdm_wait_transition(clkdm->pwrdm.ptr); - return pm_dbg_pwrdm_state_switch(clkdm->pwrdm.ptr); - } + if (strcmp(pwrdm->name, "emu_pwrdm") == 0 || + strcmp(pwrdm->name, "wkup_pwrdm") == 0) + return 0; - return -EINVAL; -} + if (pwrdm->state != pwrdm_read_pwrst(pwrdm)) + printk(KERN_ERR "pwrdm state mismatch(%s) %d != %d\n", + pwrdm->name, pwrdm->state, pwrdm_read_pwrst(pwrdm)); -int pm_dbg_clk_state_switch(struct clk *clk) -{ - if (clk != NULL && clk->clkdm.ptr != NULL) - return pm_dbg_clkdm_state_switch(clk->clkdm.ptr); - return -EINVAL; -} + seq_printf(s, "%s (%s)", pwrdm->name, + pwrdm_state_names[pwrdm->state]); + for (i = 0; i < 4; i++) + seq_printf(s, ",%s:%d", pwrdm_state_names[i], + pwrdm->state_counter[i]); -static int pm_dbg_pre_suspend_cb(struct powerdomain *pwrdm) -{ - pwrdm_clear_all_prev_pwrst(pwrdm); - _pm_dbg_state_switch(pwrdm, PM_DBG_STATE_NOW); - return 0; -} + seq_printf(s, "\n"); -static int pm_dbg_post_suspend_cb(struct powerdomain *pwrdm) -{ - _pm_dbg_state_switch(pwrdm, PM_DBG_STATE_PREV); return 0; } -int pm_dbg_pre_suspend(void) +static int pwrdm_dbg_show_timer(struct powerdomain *pwrdm, void *user) { - pwrdm_for_each(pm_dbg_pre_suspend_cb); + struct seq_file *s = (struct seq_file *)user; + int i; + + if (strcmp(pwrdm->name, "emu_pwrdm") == 0 || + strcmp(pwrdm->name, "wkup_pwrdm") == 0) + return 0; + + pwrdm_state_switch(pwrdm); + + seq_printf(s, "%s (%s)", pwrdm->name, + pwrdm_state_names[pwrdm->state]); + + for (i = 0; i < 4; i++) + seq_printf(s, ",%s:%lld", pwrdm_state_names[i], + pwrdm->state_timer[i]); + + seq_printf(s, "\n"); + return 0; } -int pm_dbg_post_suspend(void) +static void pm_dbg_show_counters(struct seq_file *s, void *unused) { - pwrdm_for_each(pm_dbg_post_suspend_cb); - return 0; + pwrdm_for_each(pwrdm_dbg_show_counter, s); + clkdm_for_each(clkdm_dbg_show_counter, s); } -enum { - DEBUG_FILE_COUNTERS = 0, - DEBUG_FILE_TIMERS, -}; - -int pm_dbg_show_counters(struct seq_file *s, void *unused) +static void pm_dbg_show_timers(struct seq_file *s, void *unused) { - pwrdm_dbg_show_counters(s, unused); - clkdm_dbg_show_counters(s, unused); - - return 0; + pwrdm_for_each(pwrdm_dbg_show_timer, s); } static int pm_dbg_open(struct inode *inode, struct file *file) @@ -429,7 +425,7 @@ static int pm_dbg_open(struct inode *inode, struct file *file) &inode->i_private); case DEBUG_FILE_TIMERS: default: - return single_open(file, pwrdm_dbg_show_timers, + return single_open(file, pm_dbg_show_timers, &inode->i_private); }; } @@ -489,23 +485,18 @@ int pm_dbg_regset_init(int reg_set) return 0; } -static int __init pwrdms_setup(struct powerdomain *pwrdm) +static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused) { - s64 t; int i; + s64 t; struct timespec now; getnstimeofday(&now); t = timespec_to_ns(&now); - for (i = 0; i < 4; i++) { - pwrdm->state_counter[i] = 0; + for (i = 0; i < 4; i++) pwrdm->state_timer[i] = 0; - } - pwrdm_wait_transition(pwrdm); - pwrdm->state = pwrdm_read_pwrst(pwrdm); - pwrdm->state_counter[pwrdm->state] = 1; pwrdm->timer = t; (void) debugfs_create_file(pwrdm->name, S_IRUGO|S_IWUSR, @@ -535,7 +526,7 @@ static int __init pm_dbg_init(void) if (IS_ERR(pm_dbg_dir)) return PTR_ERR(pm_dbg_dir); - pwrdm_for_each(pwrdms_setup); + pwrdm_for_each(pwrdms_setup, NULL); pm_dbg_dir = debugfs_create_dir("registers", d); if (IS_ERR(pm_dbg_dir)) diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index 038931c..55a9cdd 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -31,32 +31,21 @@ extern int omap2_pm_debug; #define omap2_pm_debug 0 #endif +extern int set_pwrdm_state(struct powerdomain *pwrdm, u32 state); + #if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) struct seq_file; struct clk; struct clockdomain; struct powerdomain; -extern int pm_dbg_pwrdm_state_switch(struct powerdomain *pwrdm); -extern int pm_dbg_clkdm_state_switch(struct clockdomain *clkdm); -extern int pm_dbg_clk_state_switch(struct clk *clk); -extern int pm_dbg_pre_suspend(void); -extern int pm_dbg_post_suspend(void); extern int pm_dbg_regset_save(int reg_set); extern int pm_dbg_regset_init(int reg_set); -extern int pwrdm_dbg_show_counters(struct seq_file *s, void *unused); -extern int pwrdm_dbg_show_timers(struct seq_file *s, void *unused); extern int clkdm_dbg_show_counters(struct seq_file *s, void *unused); -extern int set_pwrdm_state(struct powerdomain *pwrdm, u32 state); +extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev); #else -#define pm_dbg_pwrdm_state_switch(domain) do; while (0) -#define pm_dbg_clkdm_state_switch(domain) do; while (0) -#define pm_dbg_clk_state_switch(domain) do; while (0) -#define pm_dbg_pre_suspend() do; while (0) -#define pm_dbg_post_suspend() do; while (0) #define pm_dbg_regset_save(reg_set) do; while (0) #define pm_dbg_regset_init(reg_set) do; while (0) -#define pwrdm_dbg_show_counters(s,unused) do; while (0) -#define pwrdm_dbg_show_timers(s,unused) do; while (0) #define clkdm_dbg_show_counters(s,unused) do; while (0) +#define pm_dbg_update_time(pwrdm, prev) do; while (0) #endif /* CONFIG_PM_DEBUG */ #endif diff --git a/arch/arm/plat-omap/include/mach/powerdomain.h b/arch/arm/plat-omap/include/mach/powerdomain.h index 1c27d7d..2d6f9a0 100644 --- a/arch/arm/plat-omap/include/mach/powerdomain.h +++ b/arch/arm/plat-omap/include/mach/powerdomain.h @@ -74,6 +74,11 @@ struct pwrdm_dep { int state; unsigned state_counter[4]; + +#ifdef CONFIG_PM_DEBUG + s64 timer; + s64 state_timer[4]; +#endif }; struct powerdomain { @@ -118,9 +123,11 @@ struct powerdomain { struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS]; struct list_head node; -#ifdef CONFIG_PM_DEBUG + int state; - int state_counter[4]; + unsigned state_counter[4]; + +#ifdef CONFIG_PM_DEBUG s64 timer; s64 state_timer[4]; #endif @@ -133,7 +140,8 @@ int pwrdm_register(struct powerdomain *pwrdm); int pwrdm_unregister(struct powerdomain *pwrdm); struct powerdomain *pwrdm_lookup(const char *name); -int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm)); +int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user), + void *user); int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm); int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm); -- 1.5.6.3 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 3/3] Hook into powerdomain code 2008-10-07 13:33 ` [PATCH 2/3] Add pm-debug counters Peter 'p2' De Schrijver @ 2008-10-07 13:33 ` Peter 'p2' De Schrijver 0 siblings, 0 replies; 13+ messages in thread From: Peter 'p2' De Schrijver @ 2008-10-07 13:33 UTC (permalink / raw) To: linux-omap; +Cc: Peter 'p2' De Schrijver Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com> --- arch/arm/mach-omap2/powerdomain.c | 95 ++++++------------------------------ 1 files changed, 16 insertions(+), 79 deletions(-) diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index 63ea29a..4ae7b01 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c @@ -35,6 +35,8 @@ #include <mach/powerdomain.h> #include <mach/clockdomain.h> +#include "pm.h" + enum { PWRDM_STATE_NOW = 0, PWRDM_STATE_PREV, @@ -134,19 +136,21 @@ static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag) if (state != prev) pwrdm->state_counter[state]++; + pm_dbg_update_time(pwrdm, prev); + pwrdm->state = state; return 0; } -static int _pwrdm_pre_transition_cb(struct powerdomain *pwrdm) +static int _pwrdm_pre_transition_cb(struct powerdomain *pwrdm, void *unused) { pwrdm_clear_all_prev_pwrst(pwrdm); _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW); return 0; } -static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm) +static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused) { _pwrdm_state_switch(pwrdm, PWRDM_STATE_PREV); return 0; @@ -179,9 +183,12 @@ void pwrdm_init(struct powerdomain **pwrdm_list) { struct powerdomain **p = NULL; - if (pwrdm_list) - for (p = pwrdm_list; *p; p++) + if (pwrdm_list) { + for (p = pwrdm_list; *p; p++) { pwrdm_register(*p); + _pwrdm_setup(*p); + } + } } /** @@ -279,7 +286,8 @@ struct powerdomain *pwrdm_lookup(const char *name) * anything else to indicate failure; or -EINVAL if the function * pointer is null. */ -int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm)) +int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user), + void *user) { struct powerdomain *temp_pwrdm; unsigned long flags; @@ -290,7 +298,7 @@ int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm)) read_lock_irqsave(&pwrdm_rwlock, flags); list_for_each_entry(temp_pwrdm, &pwrdm_list, node) { - ret = (*fn)(temp_pwrdm); + ret = (*fn)(temp_pwrdm, user); if (ret) break; } @@ -456,13 +464,13 @@ int pwrdm_clk_state_switch(struct clk *clk) int pwrdm_pre_transition(void) { - pwrdm_for_each(_pwrdm_pre_transition_cb); + pwrdm_for_each(_pwrdm_pre_transition_cb, NULL); return 0; } int pwrdm_post_transition(void) { - pwrdm_for_each(_pwrdm_post_transition_cb); + pwrdm_for_each(_pwrdm_post_transition_cb, NULL); return 0; } @@ -1203,74 +1211,3 @@ int pwrdm_wait_transition(struct powerdomain *pwrdm) return 0; } - -#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) - -#include <linux/debugfs.h> -#include <linux/seq_file.h> -#include "pm.h" - -static const char pwrdm_state_names[][4] = { - "OFF", - "RET", - "INA", - "ON" -}; - -int pwrdm_dbg_show_counters(struct seq_file *s, void *unused) -{ - int i; - struct powerdomain *pwrdm; - unsigned long flags; - - read_lock_irqsave(&pwrdm_rwlock, flags); - list_for_each_entry(pwrdm, &pwrdm_list, node) { - if (strcmp(pwrdm->name, "emu_pwrdm") == 0 || - strcmp(pwrdm->name, "wkup_pwrdm") == 0) - continue; - if (pwrdm->state != pwrdm_read_pwrst(pwrdm)) - printk(KERN_ERR "pwrdm state mismatch(%s) %d != %d\n", - pwrdm->name, pwrdm->state, - pwrdm_read_pwrst(pwrdm)); - seq_printf(s, "%s (%s)", pwrdm->name, - pwrdm_state_names[pwrdm->state]); - for (i = 0; i < 4; i++) { - seq_printf(s, ",%s:%d", pwrdm_state_names[i], - pwrdm->state_counter[i]); - } - seq_printf(s, "\n"); - } - read_unlock_irqrestore(&pwrdm_rwlock, flags); - - return 0; -} - -int pwrdm_dbg_show_timers(struct seq_file *s, void *unused) -{ - int i; - struct powerdomain *pwrdm; - unsigned long flags; - - read_lock_irqsave(&pwrdm_rwlock, flags); - list_for_each_entry(pwrdm, &pwrdm_list, node) { - if (strcmp(pwrdm->name, "emu_pwrdm") == 0 || - strcmp(pwrdm->name, "wkup_pwrdm") == 0) - continue; - - /* Update timer for current state */ - pm_dbg_pwrdm_state_switch(pwrdm); - - seq_printf(s, "%s (%s)", pwrdm->name, - pwrdm_state_names[pwrdm->state]); - for (i = 0; i < 4; i++) { - seq_printf(s, ",%s:%lld", pwrdm_state_names[i], - pwrdm->state_timer[i]); - } - seq_printf(s, "\n"); - } - read_unlock_irqrestore(&pwrdm_rwlock, flags); - - return 0; -} - -#endif -- 1.5.6.3 ^ permalink raw reply related [flat|nested] 13+ messages in thread
end of thread, other threads:[~2008-10-29 18:22 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-10-14 14:39 [PATCH 0/3] debugfs entries for PM counters Peter 'p2' De Schrijver 2008-10-14 14:39 ` [PATCH 1/3] Add closures to clkdm_for_each and pwrdm_for_each Peter 'p2' De Schrijver 2008-10-14 14:39 ` [PATCH 2/3] Add pm-debug counters Peter 'p2' De Schrijver 2008-10-14 14:39 ` [PATCH 3/3] Hook into powerdomain code Peter 'p2' De Schrijver 2008-10-14 19:55 ` Paul Walmsley 2008-10-15 14:32 ` Peter 'p2' De Schrijver 2008-10-14 19:47 ` [PATCH 2/3] Add pm-debug counters Paul Walmsley 2008-10-15 6:12 ` Högander Jouni 2008-10-15 9:54 ` Tero.Kristo 2008-10-14 19:50 ` [PATCH 1/3] Add closures to clkdm_for_each and pwrdm_for_each Paul Walmsley 2008-10-29 18:22 ` [PATCH 0/3] debugfs entries for PM counters Kevin Hilman -- strict thread matches above, loose matches on Subject: below -- 2008-10-15 15:13 Peter 'p2' De Schrijver 2008-10-15 15:13 ` [PATCH 1/3] Add closures to clkdm_for_each and pwrdm_for_each Peter 'p2' De Schrijver 2008-10-15 15:13 ` [PATCH 2/3] Add pm-debug counters Peter 'p2' De Schrijver 2008-10-15 15:13 ` [PATCH 3/3] Hook into powerdomain code Peter 'p2' De Schrijver 2008-10-07 13:33 [PATCH 0/3] Add PM debug counters on top of PM counters Peter 'p2' De Schrijver 2008-10-07 13:33 ` [PATCH 1/3] Add closures to clkdm_for_each Peter 'p2' De Schrijver 2008-10-07 13:33 ` [PATCH 2/3] Add pm-debug counters Peter 'p2' De Schrijver 2008-10-07 13:33 ` [PATCH 3/3] Hook into powerdomain code Peter 'p2' De Schrijver
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox