Re: [PATCH v8 0/8] Consolidate cpuidle functionality
On 03/21/2012 05:31 AM, Rafael J. Wysocki wrote: On Wednesday, March 21, 2012, Amit Kucheria wrote: On Wed, Mar 21, 2012 at 12:48 AM, Kevin Hilman khil...@ti.com wrote: Arnd Bergmann arnd.bergm...@linaro.org writes: On Tuesday 20 March 2012, Robert Lee wrote: This patch series moves various functionality duplicated in platform cpuidle drivers to the core cpuidle driver. Also, the platform irq disabling was removed as it appears that all calls into cpuidle_call_idle will have already called local_irq_disable(). These changes have been pulled into linux-next. Len, Andrew, can a request be made for Linus to pull these changes? FWIW, Len seems to be rather inactive on the kernel mailing list right now and generally not very interested in anything outside of x86 and acpi. If he doesn't reply in the next few days and Andrew also isn't interested in handling these patches, I'd suggest you just send the pull request to Linus, with Len on Cc and explain that you tried to send them through him but gave up in the end. FWIW, I have not had good luck getting response for proposed core CPUidle changes either: http://lkml.org/lkml/2011/9/19/374 Maybe it's time that drivers/cpuidle gets a maintainer. With lots of discussions of scheduler changes that affect load estimation, I suspect we're all going to have a bit of CPUidle work to do in the not-so-distant future. I don't mean to be piling on to Len here, but Daniel Lezcano too has a bunch of clean ups that didn't get any maintainer review for over two months. He has now refreshed them for 3.3 and is getting ready to send them out again. We (Linaro) expect to be spending a lot of time on cpuidle in the future and would be glad to help review, test and collect patches into a tree for Linus/Andrew to pull while we wait for Len to respond or another maintainer to emerge. Well, I discussed that before with Arjan and he said he would maintain CPUidle if Len didn't have the time, but it seems he didn't expect that there would be a lot of work on it in the near future. So, I suggest that if neither Len nor Arjan reappear shortly, people can send CPUidle patches to me. Thanks, Rafael I'll be glad to assist you in this. Cheers, Deepthi -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v6 1/9] cpuidle: Add common time keeping and irq enabling
Hi Rob, On 02/29/2012 08:41 AM, Robert Lee wrote: Make necessary changes to implement time keeping and irq enabling in the core cpuidle code. This will allow the removal of these functionalities from various platform cpuidle implementations whose timekeeping and irq enabling follows the form in this common code. Signed-off-by: Robert Lee rob@linaro.org --- arch/arm/include/asm/cpuidle.h | 14 ++ drivers/cpuidle/cpuidle.c | 90 include/linux/cpuidle.h| 13 ++ 3 files changed, 99 insertions(+), 18 deletions(-) create mode 100644 arch/arm/include/asm/cpuidle.h diff --git a/arch/arm/include/asm/cpuidle.h b/arch/arm/include/asm/cpuidle.h new file mode 100644 index 000..1d2075b --- /dev/null +++ b/arch/arm/include/asm/cpuidle.h @@ -0,0 +1,14 @@ +#ifndef __ASM_ARM_CPUIDLE_H +#define __ASM_ARM_CPUIDLE_H + +/* Common ARM WFI state */ +#define CPUIDLE_ARM_WFI_STATE {\ + .enter = cpuidle_simple_enter,\ + .exit_latency = 1,\ + .target_residency = 1,\ + .flags = CPUIDLE_FLAG_TIME_VALID,\ + .name = WFI,\ + .desc = ARM core clock gating (WFI),\ +} + +#endif diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 59f4261..00b02f5 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -18,6 +18,7 @@ #include linux/ktime.h #include linux/hrtimer.h #include linux/module.h +#include asm/proc-fns.h #include trace/events/power.h #include cpuidle.h @@ -53,6 +54,24 @@ static void cpuidle_kick_cpus(void) {} static int __cpuidle_register_device(struct cpuidle_device *dev); +static inline int cpuidle_enter(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{ + struct cpuidle_state *target_state = drv-states[index]; + return target_state-enter(dev, drv, index); +} + +static inline int cpuidle_enter_tk(struct cpuidle_device *dev, +struct cpuidle_driver *drv, int index) +{ + return cpuidle_wrap_enter(dev, drv, index, cpuidle_enter); +} + +typedef int (*cpuidle_enter_t)(struct cpuidle_device *dev, +struct cpuidle_driver *drv, int index); + +static cpuidle_enter_t cpuidle_enter_ops; + /** * cpuidle_idle_call - the main idle loop * @@ -63,7 +82,6 @@ int cpuidle_idle_call(void) { struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); struct cpuidle_driver *drv = cpuidle_get_driver(); - struct cpuidle_state *target_state; int next_state, entered_state; if (off) @@ -92,12 +110,10 @@ int cpuidle_idle_call(void) return 0; } - target_state = drv-states[next_state]; - trace_power_start(POWER_CSTATE, next_state, dev-cpu); trace_cpu_idle(next_state, dev-cpu); - entered_state = target_state-enter(dev, drv, next_state); + entered_state = cpuidle_enter_ops(dev, drv, next_state); trace_power_end(dev-cpu); trace_cpu_idle(PWR_EVENT_EXIT, dev-cpu); @@ -110,7 +126,8 @@ int cpuidle_idle_call(void) dev-states_usage[entered_state].time += (unsigned long long)dev-last_residency; dev-states_usage[entered_state].usage++; - } + } else + dev-last_residency = 0; /* give the governor an opportunity to reflect on the outcome */ if (cpuidle_curr_governor-reflect) @@ -164,20 +181,29 @@ void cpuidle_resume_and_unlock(void) EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock); -#ifdef CONFIG_ARCH_HAS_CPU_RELAX -static int poll_idle(struct cpuidle_device *dev, - struct cpuidle_driver *drv, int index) +/** + * cpuidle_wrap_enter - performs timekeeping and irqen around enter function + * @dev: pointer to a valid cpuidle_device object + * @drv: pointer to a valid cpuidle_driver object + * @index: index of the target cpuidle state. + */ +int cpuidle_wrap_enter(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index, + int (*enter)(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index)) { - ktime_t t1, t2; + ktime_t time_start, time_end; s64 diff; - t1 = ktime_get(); + time_start = ktime_get(); + + index = enter(dev, drv, index); + + time_end = ktime_get(); + local_irq_enable(); - while (!need_resched()) - cpu_relax(); - t2 = ktime_get(); - diff = ktime_to_us(ktime_sub(t2, t1)); + diff = ktime_to_us(ktime_sub(time_end, time_start)); if (diff INT_MAX) diff = INT_MAX; @@ -186,6 +212,31 @@ static int poll_idle(struct cpuidle_device *dev, return index; } +int
Re: [PATCH v7 1/9] cpuidle: Add common time keeping and irq enabling
, + struct cpuidle_driver *drv, int index, + int (*enter)(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index)) +{ return -ENODEV; } #endif For the generic cpuidle changes Reviewed-by: Deepthi Dharwar deep...@linux.vnet.ibm.com -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] CPUIdle: Reevaluate C-states under CPU load to favor deeper C-states
On Saturday 05 November 2011 03:16 AM, Kevin Hilman wrote: ping v2 Kevin Hilman khil...@ti.com writes: From: Nicole Chalhoub n-chalh...@ti.com While there is CPU load, program a C-state specific one-shot timer in order to give CPUidle another opportunity to pick a deeper C-state instead of spending potentially long idle times in a shallow C-state. Long winded version: When going idle with a high load average, CPUidle menu governor will decide to pick a shallow C-state since one of the guiding principles of the menu governor is The busier the system, the less impact of C-states is acceptable (taken from cpuidle/governors/menu.c.) That makes perfect sense. However, there are missed power-saving opportunities for bursty workloads with long idle times (e.g. MP3 playback.) Given such a workload, because of the load average, CPUidle tends to pick a shallow C-state. Because we also go tickless, this shallow C-state is used for the duration of the idle period. If the idle period is long, a deeper C state would've resulted in better power savings. This patch provides an additional opportuntity for CPUidle to pick a deeper C-state by programming a timer (with a C-state specific timeout) such that the CPUidle governor will have another opportunity to pick a deeper C-state. Adding this timer for C-state reevaluation improved the load estimation on our ARM/OMAP4 platform and increased the time spent in deep C-states (~50% of idle time in C-states deeper than C1). A power saving of ~10mA at battery level is observed during MP3 playback on OMAP4/Blaze board. Signed-off-by: Nicole Chalhoub n-chalh...@ti.com Signed-off-by: Kevin Hilman khil...@ti.com --- drivers/cpuidle/cpuidle.c| 28 +- drivers/cpuidle/governors/menu.c | 39 - include/linux/cpuidle.h |4 +++ 3 files changed, 63 insertions(+), 8 deletions(-) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 1994885..4b1ac0c 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -92,13 +92,33 @@ static void cpuidle_idle_call(void) target_state-time += (unsigned long long)dev-last_residency; target_state-usage++; -/* give the governor an opportunity to reflect on the outcome */ -if (cpuidle_curr_governor-reflect) +hrtimer_cancel(dev-cstate_timer); + +/* + * Give the governor an opportunity to reflect on the outcome + * Do not take into account the wakeups due to the hrtimer, they + * should not impact the predicted idle time. + */ +if ((!dev-hrtimer_expired) cpuidle_curr_governor-reflect) cpuidle_curr_governor-reflect(dev); trace_power_end(0); } /** + * cstate_reassessment_timer - interrupt handler of the cstate hrtimer + * @handle: the expired hrtimer + */ +static enum hrtimer_restart cstate_reassessment_timer(struct hrtimer *handle) +{ +struct cpuidle_device *data = +container_of(handle, struct cpuidle_device, cstate_timer); + +data-hrtimer_expired = 1; + +return HRTIMER_NORESTART; +} + +/** * cpuidle_install_idle_handler - installs the cpuidle idle loop handler */ void cpuidle_install_idle_handler(void) @@ -185,6 +205,10 @@ int cpuidle_enable_device(struct cpuidle_device *dev) dev-enabled = 1; +dev-hrtimer_expired = 0; +hrtimer_init(dev-cstate_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); +dev-cstate_timer.function = cstate_reassessment_timer; + enabled_devices++; return 0; diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 1b12870..fd54584 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -125,10 +125,21 @@ struct menu_device { #define LOAD_INT(x) ((x) FSHIFT) #define LOAD_FRAC(x) LOAD_INT(((x) (FIXED_1-1)) * 100) -static int get_loadavg(void) +static int get_loadavg(struct cpuidle_device *dev) { -unsigned long this = this_cpu_load(); +unsigned long this; +/* + * this_cpu_load() returns the value of rq-load.weight + * at the previous scheduler tick and not the current value. + * If the timer expired, that means we are in idle,there + * are no more runnable processes in the current queue + * =return the current value of rq-load.weight which is 0. + */ +if (dev-hrtimer_expired == 1) +return 0; +else +this = this_cpu_load(); return LOAD_INT(this) * 10 + LOAD_FRAC(this) / 10; } @@ -166,13 +177,13 @@ static inline int which_bucket(unsigned int duration) * to be, the higher this multiplier, and thus the higher * the barrier to go to an expensive C state. */ -static inline int performance_multiplier(void) +static inline int performance_multiplier(struct cpuidle_device *dev) { int mult = 1; /* for higher
Re: [PATCH v9 2/4] cpuidle: Remove CPUIDLE_FLAG_IGNORE and dev-prepare()
On Friday 28 October 2011 07:54 PM, Arjan van de Ven wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 10/28/2011 3:50 AM, Deepthi Dharwar wrote: The cpuidle_device-prepare() mechanism causes updates to the cpuidle_state[].flags, setting and clearing CPUIDLE_FLAG_IGNORE to tell the governor not to chose a state on a per-cpu basis at run-time. State demotion is now handled by the driver and it returns the actual state entered. Hence, this mechanism is not required. Also this removes per-cpu flags from cpuidle_state enabling it to be made global. having worked on some newer platforms this one is really still needed. doing this inside the actual states does not work, because if the deepest 3 states are invalid, the same (somewhat expensive) test would have to be done 3 times, and each of the states would have to fail before the 4th one gets chosen. that's just not going to work (in the state handler you can't know what other state to fall back to, and especially not how to enter such a fallback state) -BEGIN PGP SIGNATURE- Version: GnuPG v2.0.17 (MingW32) iQEcBAEBAgAGBQJOqrsGAAoJEEHdSxh4DVnEu7EH/i5lEJctBAIubJOcZz/tvBFp XYmAe/HqNtSXeHOVsJkTf8y4ppE8487exF7xxMik4GRN0CZNCtkyMezqDVu+eDim O/UUbScsAc5cSY6mkjOFXLFup+mi1nkRUnAbxXEyTMhWwcbfr2OvcuO7l7TmATML hu87P3PVEafEop3q2+uWMc57fFxnNFfEDqRx6N9V+OJKV5dHrRYL4G4E01fYGFLo xTR0IW7nB15L0C29zk9uk/Dqow8SoJZA83c7p7AieP5zdntb6p7noIf03qmdp19f fulwMwembCHivo+pLO+jAMhKD1T6VYoCyiYW0LHrQ2E07fayBhFJCxlazgKFcl0= =FL6o -END PGP SIGNATURE- Hi Arjan, Thanks for the review. We retain the dev-prepare() routine and CPUIDLE_FLAG_IGNORE but still allow the dev-enter() to return index ? So by retaining it, transition to the idle states would be much quicker in case one more states are invalid. Also to note is that in the newer design, we have split the cpuidle_state structure. One global struct, cpuidle_states[] that contains all the state related information including flags, and the other cpuidle_device that contain statistics and other data that are per-cpu basis. So the flags are not per cpu per state basis but maintained globally as per state basis. So if we have to enable CPUIDLE_FLAG_IGNORE flag in this current new design, then I am thinking if we needed to have this on a per-cpu basis. If so, then flags have to be moved into cpuidle_device struct rather than cpuidle_state struct. Is it a good idea to retain these flags as global (part of cpuidle_states) or make it per-cpu basis ? -Thanks Deepthi -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v9 0/4] cpuidle: Global registration of idle states with per-cpu statistics
Version 6 of this patch series dated 22nd Sept 2011 was Acked-by: Arjan van de Ven ar...@linux.intel.com Acked-by: Kevin Hilman khil...@ti.com for OMAP specific parts. Reviewed-by: Kevin Hilman khil...@ti.com Tested-by: Jean Pihet j-pi...@ti.com Hi Len, Can you please queue this series for the next mainline merge window by merging it into your development tree and also linux-next for further testing. I have also tested it by applying these patches on your ACPI tree hosted @github. Thanks -Deepthi -- The following patch series implements global registration of cpuidle states, and also has the necessary data structure changes to accommodate the per-cpu writable members of the cpuidle_states structure. This patch series had been in discussion earlier and following are the links to the previous discussions. v8 -- https://lkml.org/lkml/2011/10/3/52 v7 -- https://lkml.org/lkml/2011/9/27/74 v6 -- https://lkml.org/lkml/2011/9/22/58 v5 -- https://lkml.org/lkml/2011/6/6/259 v4 -- https://lkml.org/lkml/2011/4/28/312 v3 -- https://lkml.org/lkml/2011/2/8/73 v2 -- https://lkml.org/lkml/2011/1/13/98 v1 -- https://lkml.org/lkml/2011/3/22/161 Changes from previous version (v8): 1. Rebased and tested on 3.1 Tests done: 1. Compile tested for ARM using the following configs: da8xx_omapl_defconfig, kirkwood_defconfig, omap2plus_defconfig, at91rm9200_defconfig 2. Boot tested on x86 nehalem with multiple C-states for both intel_idle and acpi_idle drivers. 3. Boot tested on T60p thinkpad that has T2600 cpu with multiple C-states. Also tested the case when there is dynamic changes in C-states AC - Battery Power switch. Brief description of the patches: Core change in this series is to split the cpuidle_device structure into two parts, i.e global and per-cpu basis. The per-cpu pieces are mostly generic statistics that can be independent of current running driver. As a result of these changes, there is single copy of cpuidle_states structure and single registration done by one cpu. The low level driver is free to set per-cpu driver data on each cpu if needed using the cpuidle_set_statedata() as the case today. Only in very rare cases asymmetric C-states exist which can be handled within the cpuidle driver. Most architectures do not have asymmetric C-states. First two patches in the series facilitate splitting of cpuidle_states and cpuidle_device structure and next two patches do the actual split, change the API's and make existing code follow the changed API. [1/4] - Move the idle residency accounting part from cpuidle.c to the respective low level drivers, so that the accounting can be accurately maintained if the driver decides to demote the chosen (suggested) by the governor. [2/4] - removes the cpuidle_device()-prepare API since is is not widely used and the only use case was to allow software demotion using CPUIDLE_FLAG_IGNORE flag. Both these functions can be absorbed within the cpuidle back-end driver ad hence deprecating the prepare routine and the CPUIDLE_FLAG_IGNORE flag. - Ref: https://lkml.org/lkml/2011/3/25/52 [3/4] - Splits the usage statistics (read/write) part out of cpuidle_state structure, so that the states can become read only and hence made global. [4/4] - Most APIs will now need to pass pointer to both global cpuidle_driver and per-cpu cpuidle_device structure. arch/arm/mach-at91/cpuidle.c | 41 +++-- arch/arm/mach-davinci/cpuidle.c | 51 --- arch/arm/mach-exynos4/cpuidle.c | 30 ++-- arch/arm/mach-kirkwood/cpuidle.c | 42 +++--- arch/arm/mach-omap2/cpuidle34xx.c | 133 +++-- arch/sh/kernel/cpu/shmobile/cpuidle.c | 28 ++-- drivers/acpi/processor_driver.c | 20 --- drivers/acpi/processor_idle.c | 251 +++-- drivers/cpuidle/cpuidle.c | 86 --- drivers/cpuidle/driver.c | 25 +++ drivers/cpuidle/governors/ladder.c| 41 - drivers/cpuidle/governors/menu.c | 29 ++-- drivers/cpuidle/sysfs.c | 22 ++- drivers/idle/intel_idle.c | 130 + include/acpi/processor.h |1 include/linux/cpuidle.h | 52 --- 16 files changed, 650 insertions(+), 332 deletions(-) -- -Deepthi -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v9 1/4] cpuidle: Move dev-last_residency update to driver enter routine; remove dev-last_state
Cpuidle governor only suggests the state to enter using the governor-select() interface, but allows the low level driver to override the recommended state. The actual entered state may be different because of software or hardware demotion. Software demotion is done by the back-end cpuidle driver and can be accounted correctly. Current cpuidle code uses last_state field to capture the actual state entered and based on that updates the statistics for the state entered. Ideally the driver enter routine should update the counters, and it should return the state actually entered rather than the time spent there. The generic cpuidle code should simply handle where the counters live in the sysfs namespace, not updating the counters. Reference: https://lkml.org/lkml/2011/3/25/52 Signed-off-by: Deepthi Dharwar deep...@linux.vnet.ibm.com Signed-off-by: Trinabh Gupta g.trin...@gmail.com Tested-by: Jean Pihet j-pi...@ti.com Reviewed-by: Kevin Hilman khil...@ti.com Acked-by: Arjan van de Ven ar...@linux.intel.com Acked-by: Kevin Hilman khil...@ti.com --- arch/arm/mach-at91/cpuidle.c | 10 +++- arch/arm/mach-davinci/cpuidle.c |9 +++- arch/arm/mach-exynos4/cpuidle.c |7 ++- arch/arm/mach-kirkwood/cpuidle.c | 12 - arch/arm/mach-omap2/cpuidle34xx.c | 67 + arch/sh/kernel/cpu/shmobile/cpuidle.c | 12 +++-- drivers/acpi/processor_idle.c | 75 ++--- drivers/cpuidle/cpuidle.c | 32 +++--- drivers/cpuidle/governors/ladder.c| 13 ++ drivers/cpuidle/governors/menu.c |7 ++- drivers/idle/intel_idle.c | 12 - include/linux/cpuidle.h |7 +-- 12 files changed, 164 insertions(+), 99 deletions(-) diff --git a/arch/arm/mach-at91/cpuidle.c b/arch/arm/mach-at91/cpuidle.c index 1cfeac1..4696a0d 100644 --- a/arch/arm/mach-at91/cpuidle.c +++ b/arch/arm/mach-at91/cpuidle.c @@ -33,7 +33,7 @@ static struct cpuidle_driver at91_idle_driver = { /* Actual code that puts the SoC in different idle states */ static int at91_enter_idle(struct cpuidle_device *dev, - struct cpuidle_state *state) + int index) { struct timeval before, after; int idle_time; @@ -41,10 +41,10 @@ static int at91_enter_idle(struct cpuidle_device *dev, local_irq_disable(); do_gettimeofday(before); - if (state == dev-states[0]) + if (index == 0) /* Wait for interrupt state */ cpu_do_idle(); - else if (state == dev-states[1]) { + else if (index == 1) { asm(b 1f; .align 5; 1:); asm(mcr p15, 0, r0, c7, c10, 4); /* drain write buffer */ saved_lpr = sdram_selfrefresh_enable(); @@ -55,7 +55,9 @@ static int at91_enter_idle(struct cpuidle_device *dev, local_irq_enable(); idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + (after.tv_usec - before.tv_usec); - return idle_time; + + dev-last_residency = idle_time; + return index; } /* Initialize CPU idle by registering the idle states */ diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c index bd59f31..ca8582a 100644 --- a/arch/arm/mach-davinci/cpuidle.c +++ b/arch/arm/mach-davinci/cpuidle.c @@ -78,9 +78,9 @@ static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = { /* Actual code that puts the SoC in different idle states */ static int davinci_enter_idle(struct cpuidle_device *dev, - struct cpuidle_state *state) + int index) { - struct davinci_ops *ops = cpuidle_get_statedata(state); + struct davinci_ops *ops = cpuidle_get_statedata(dev-states[index]); struct timeval before, after; int idle_time; @@ -98,7 +98,10 @@ static int davinci_enter_idle(struct cpuidle_device *dev, local_irq_enable(); idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + (after.tv_usec - before.tv_usec); - return idle_time; + + dev-last_residency = idle_time; + + return index; } static int __init davinci_cpuidle_probe(struct platform_device *pdev) diff --git a/arch/arm/mach-exynos4/cpuidle.c b/arch/arm/mach-exynos4/cpuidle.c index bf7e96f..ea026e7 100644 --- a/arch/arm/mach-exynos4/cpuidle.c +++ b/arch/arm/mach-exynos4/cpuidle.c @@ -16,7 +16,7 @@ #include asm/proc-fns.h static int exynos4_enter_idle(struct cpuidle_device *dev, - struct cpuidle_state *state); + int index); static struct cpuidle_state exynos4_cpuidle_set[] = { [0] = { @@ -37,7 +37,7 @@ static struct cpuidle_driver exynos4_idle_driver = { }; static int exynos4_enter_idle(struct cpuidle_device *dev
[PATCH v9 2/4] cpuidle: Remove CPUIDLE_FLAG_IGNORE and dev-prepare()
The cpuidle_device-prepare() mechanism causes updates to the cpuidle_state[].flags, setting and clearing CPUIDLE_FLAG_IGNORE to tell the governor not to chose a state on a per-cpu basis at run-time. State demotion is now handled by the driver and it returns the actual state entered. Hence, this mechanism is not required. Also this removes per-cpu flags from cpuidle_state enabling it to be made global. Reference: https://lkml.org/lkml/2011/3/25/52 Signed-off-by: Deepthi Dharwar deep...@linux.vnet.ibm Signed-off-by: Trinabh Gupta g.trin...@gmail.com Tested-by: Jean Pihet j-pi...@ti.com Acked-by: Arjan van de Ven ar...@linux.intel.com Reviewed-by: Kevin Hilman khil...@ti.com --- drivers/cpuidle/cpuidle.c| 10 -- drivers/cpuidle/governors/menu.c |2 -- include/linux/cpuidle.h |3 --- 3 files changed, 0 insertions(+), 15 deletions(-) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 8faf3a6..984d178 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -83,16 +83,6 @@ int cpuidle_idle_call(void) hrtimer_peek_ahead_timers(); #endif - /* -* Call the device's prepare function before calling the -* governor's select function. -prepare gives the device's -* cpuidle driver a chance to update any dynamic information -* of its cpuidle states for the current idle period, e.g. -* state availability, latencies, residencies, etc. -*/ - if (dev-prepare) - dev-prepare(dev); - /* ask the governor for the next state */ next_state = cpuidle_curr_governor-select(dev); if (need_resched()) { diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 3c44c53..31dd287 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -288,8 +288,6 @@ static int menu_select(struct cpuidle_device *dev) for (i = CPUIDLE_DRIVER_STATE_START; i dev-state_count; i++) { struct cpuidle_state *s = dev-states[i]; - if (s-flags CPUIDLE_FLAG_IGNORE) - continue; if (s-target_residency data-predicted_us) continue; if (s-exit_latency latency_req) diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 8da811b..c6d85cf 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -47,7 +47,6 @@ struct cpuidle_state { /* Idle State Flags */ #define CPUIDLE_FLAG_TIME_VALID(0x01) /* is residency time measurable? */ -#define CPUIDLE_FLAG_IGNORE(0x100) /* ignore during this idle period */ #define CPUIDLE_DRIVER_FLAGS_MASK (0x) @@ -93,8 +92,6 @@ struct cpuidle_device { struct completion kobj_unregister; void*governor_data; int safe_state_index; - - int (*prepare) (struct cpuidle_device *dev); }; DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices); -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v9 3/4] cpuidle: Split cpuidle_state structure and move per-cpu statistics fields
This is the first step towards global registration of cpuidle states. The statistics used primarily by the governor are per-cpu and have to be split from rest of the fields inside cpuidle_state, which would be made global i.e. single copy. The driver_data field is also per-cpu and moved. Signed-off-by: Deepthi Dharwar deep...@linux.vnet.ibm.com Signed-off-by: Trinabh Gupta g.trin...@gmail.com Tested-by: Jean Pihet j-pi...@ti.com Reviewed-by: Kevin Hilman khil...@ti.com Acked-by: Arjan van de Ven ar...@linux.intel.com Acked-by: Kevin Hilman khil...@ti.com --- arch/arm/mach-davinci/cpuidle.c |5 ++-- arch/arm/mach-omap2/cpuidle34xx.c | 13 ++ drivers/acpi/processor_idle.c | 25 ++-- drivers/cpuidle/cpuidle.c | 11 + drivers/cpuidle/sysfs.c | 19 ++- drivers/idle/intel_idle.c | 46 +++-- include/linux/cpuidle.h | 25 7 files changed, 90 insertions(+), 54 deletions(-) diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c index ca8582a..f2d2f34 100644 --- a/arch/arm/mach-davinci/cpuidle.c +++ b/arch/arm/mach-davinci/cpuidle.c @@ -80,7 +80,8 @@ static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = { static int davinci_enter_idle(struct cpuidle_device *dev, int index) { - struct davinci_ops *ops = cpuidle_get_statedata(dev-states[index]); + struct cpuidle_state_usage *state_usage = dev-states_usage[index]; + struct davinci_ops *ops = cpuidle_get_statedata(state_usage); struct timeval before, after; int idle_time; @@ -142,7 +143,7 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev) strcpy(device-states[1].desc, WFI and DDR Self Refresh); if (pdata-ddr2_pdown) davinci_states[1].flags |= DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN; - cpuidle_set_statedata(device-states[1], davinci_states[1]); + cpuidle_set_statedata(device-states_usage[1], davinci_states[1]); device-state_count = DAVINCI_CPUIDLE_MAX_STATES; diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index 58425c7..d3fce7b 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c @@ -97,7 +97,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev, int index) { struct omap3_idle_statedata *cx = - cpuidle_get_statedata(dev-states[index]); + cpuidle_get_statedata(dev-states_usage[index]); struct timespec ts_preidle, ts_postidle, ts_idle; u32 mpu_state = cx-mpu_state, core_state = cx-core_state; int idle_time; @@ -160,8 +160,9 @@ return_sleep_time: static int next_valid_state(struct cpuidle_device *dev, int index) { + struct cpuidle_state_usage *curr_usage = dev-states_usage[index]; struct cpuidle_state *curr = dev-states[index]; - struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr); + struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage); u32 mpu_deepest_state = PWRDM_POWER_RET; u32 core_deepest_state = PWRDM_POWER_RET; int next_index = -1; @@ -202,7 +203,7 @@ static int next_valid_state(struct cpuidle_device *dev, */ idx--; for (; idx = 0; idx--) { - cx = cpuidle_get_statedata(dev-states[idx]); + cx = cpuidle_get_statedata(dev-states_usage[idx]); if ((cx-valid) (cx-mpu_state = mpu_deepest_state) (cx-core_state = core_deepest_state)) { @@ -231,7 +232,6 @@ static int next_valid_state(struct cpuidle_device *dev, static int omap3_enter_idle_bm(struct cpuidle_device *dev, int index) { - struct cpuidle_state *state = dev-states[index]; int new_state_idx; u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state; struct omap3_idle_statedata *cx; @@ -264,7 +264,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, * Prevent PER off if CORE is not in retention or off as this * would disable PER wakeups completely. */ - cx = cpuidle_get_statedata(state); + cx = cpuidle_get_statedata(dev-states_usage[index]); core_next_state = cx-core_state; per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd); if ((per_next_state == PWRDM_POWER_OFF) @@ -318,6 +318,7 @@ static inline struct omap3_idle_statedata *_fill_cstate( { struct omap3_idle_statedata *cx = omap3_idle_data[idx]; struct cpuidle_state *state = dev-states[idx]; + struct cpuidle_state_usage *state_usage = dev-states_usage[idx
[PATCH v9 4/4] cpuidle: Single/Global registration of idle states
This patch makes the cpuidle_states structure global (single copy) instead of per-cpu. The statistics needed on per-cpu basis by the governor are kept per-cpu. This simplifies the cpuidle subsystem as state registration is done by single cpu only. Having single copy of cpuidle_states saves memory. Rare case of asymmetric C-states can be handled within the cpuidle driver and architectures such as POWER do not have asymmetric C-states. Having single/global registration of all the idle states, dynamic C-state transitions on x86 are handled by the boot cpu. Here, the boot cpu would disable all the devices, re-populate the states and later enable all the devices, irrespective of the cpu that would receive the notification first. Reference: https://lkml.org/lkml/2011/4/25/83 Signed-off-by: Deepthi Dharwar deep...@linux.vnet.ibm.com Signed-off-by: Trinabh Gupta g.trin...@gmail.com Tested-by: Jean Pihet j-pi...@ti.com Reviewed-by: Kevin Hilman khil...@ti.com Acked-by: Arjan van de Ven ar...@linux.intel.com Acked-by: Kevin Hilman khil...@ti.com --- arch/arm/mach-at91/cpuidle.c | 31 +++-- arch/arm/mach-davinci/cpuidle.c | 39 --- arch/arm/mach-exynos4/cpuidle.c | 23 ++-- arch/arm/mach-kirkwood/cpuidle.c | 30 +++-- arch/arm/mach-omap2/cpuidle34xx.c | 73 - arch/sh/kernel/cpu/shmobile/cpuidle.c | 18 ++- drivers/acpi/processor_driver.c | 20 +-- drivers/acpi/processor_idle.c | 191 + drivers/cpuidle/cpuidle.c | 45 ++-- drivers/cpuidle/driver.c | 25 drivers/cpuidle/governors/ladder.c| 28 +++-- drivers/cpuidle/governors/menu.c | 20 ++- drivers/cpuidle/sysfs.c |3 - drivers/idle/intel_idle.c | 80 +++--- include/acpi/processor.h |1 include/linux/cpuidle.h | 19 ++- 16 files changed, 439 insertions(+), 207 deletions(-) diff --git a/arch/arm/mach-at91/cpuidle.c b/arch/arm/mach-at91/cpuidle.c index 4696a0d..93178f6 100644 --- a/arch/arm/mach-at91/cpuidle.c +++ b/arch/arm/mach-at91/cpuidle.c @@ -33,6 +33,7 @@ static struct cpuidle_driver at91_idle_driver = { /* Actual code that puts the SoC in different idle states */ static int at91_enter_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) { struct timeval before, after; @@ -64,27 +65,29 @@ static int at91_enter_idle(struct cpuidle_device *dev, static int at91_init_cpuidle(void) { struct cpuidle_device *device; - - cpuidle_register_driver(at91_idle_driver); + struct cpuidle_driver *driver = at91_idle_driver; device = per_cpu(at91_cpuidle_device, smp_processor_id()); device-state_count = AT91_MAX_STATES; + driver-state_count = AT91_MAX_STATES; /* Wait for interrupt state */ - device-states[0].enter = at91_enter_idle; - device-states[0].exit_latency = 1; - device-states[0].target_residency = 1; - device-states[0].flags = CPUIDLE_FLAG_TIME_VALID; - strcpy(device-states[0].name, WFI); - strcpy(device-states[0].desc, Wait for interrupt); + driver-states[0].enter = at91_enter_idle; + driver-states[0].exit_latency = 1; + driver-states[0].target_residency = 1; + driver-states[0].flags = CPUIDLE_FLAG_TIME_VALID; + strcpy(driver-states[0].name, WFI); + strcpy(driver-states[0].desc, Wait for interrupt); /* Wait for interrupt and RAM self refresh state */ - device-states[1].enter = at91_enter_idle; - device-states[1].exit_latency = 10; - device-states[1].target_residency = 1; - device-states[1].flags = CPUIDLE_FLAG_TIME_VALID; - strcpy(device-states[1].name, RAM_SR); - strcpy(device-states[1].desc, WFI and RAM Self Refresh); + driver-states[1].enter = at91_enter_idle; + driver-states[1].exit_latency = 10; + driver-states[1].target_residency = 1; + driver-states[1].flags = CPUIDLE_FLAG_TIME_VALID; + strcpy(driver-states[1].name, RAM_SR); + strcpy(driver-states[1].desc, WFI and RAM Self Refresh); + + cpuidle_register_driver(at91_idle_driver); if (cpuidle_register_device(device)) { printk(KERN_ERR at91_init_cpuidle: Failed registering\n); diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c index f2d2f34..dbeeccd 100644 --- a/arch/arm/mach-davinci/cpuidle.c +++ b/arch/arm/mach-davinci/cpuidle.c @@ -78,6 +78,7 @@ static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = { /* Actual code that puts the SoC in different idle states */ static int davinci_enter_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) { struct cpuidle_state_usage *state_usage = dev
[PATCH V8 0/4] cpuidle: Global registration of idle states with per-cpu statistics
Version 6 of this patch series dated 22nd Sept 2011 was Acked-by: Arjan van de Ven ar...@linux.intel.com Acked-by: Kevin Hilman khil...@ti.com for OMAP specific parts. Reviewed-by: Kevin Hilman khil...@ti.com Tested-by: Jean Pihet j-pi...@ti.com Hi Len, Can you please queue this series for the next mainline merge window by merging it into your development tree and also linux-next for further testing. I also tested it by applying these patches on your ACPI tree hosted @github. Thanks -Deepthi -- The following patch series implements global registration of cpuidle states, and also has the necessary data structure changes to accommodate the per-cpu writable members of the cpuidle_states structure. This patch series had been in discussion earlier and following are the links to the previous discussions. v7 -- https://lkml.org/lkml/2011/9/27/74 v6 -- https://lkml.org/lkml/2011/9/22/58 v5 -- https://lkml.org/lkml/2011/6/6/259 v4 -- https://lkml.org/lkml/2011/4/28/312 v3 -- https://lkml.org/lkml/2011/2/8/73 v2 -- https://lkml.org/lkml/2011/1/13/98 v1 -- https://lkml.org/lkml/2011/3/22/161 Changes from previous version (V7): 1. Rebased and tested it on 3.1-rc8 2. As suggested by Kevin in V7, Signature of Jean was moved from signed-off tag to tested-by. Tests done: 1. Compile tested for ARM using the following configs: da8xx_omapl_defconfig, exynos4_defconfig, kirkwood_defconfig, omap2plus_defconfig, at91rm9200_defconfig 2. Boot tested on x86 nehalem with multiple C-states for both intel_idle and acpi_idle drivers. 3. Boot tested on T60p thinkpad that has T2600 cpu with multiple C-states. Also tested the case when there is dynamic changes in C-states AC - Battery Power switch. Brief description of the patches: Core change in this series is to split the cpuidle_device structure into two parts, i.e global and per-cpu basis. The per-cpu pieces are mostly generic statistics that can be independent of current running driver. As a result of these changes, there is single copy of cpuidle_states structure and single registration done by one cpu. The low level driver is free to set per-cpu driver data on each cpu if needed using the cpuidle_set_statedata() as the case today. Only in very rare cases asymmetric C-states exist which can be handled within the cpuidle driver. Most architectures do not have asymmetric C-states. First two patches in the series facilitate splitting of cpuidle_states and cpuidle_device structure and next two patches do the actual split, change the API's and make existing code follow the changed API. [1/4] - Move the idle residency accounting part from cpuidle.c to the respective low level drivers, so that the accounting can be accurately maintained if the driver decides to demote the chosen (suggested) by the governor. [2/4] - removes the cpuidle_device()-prepare API since is is not widely used and the only use case was to allow software demotion using CPUIDLE_FLAG_IGNORE flag. Both these functions can be absorbed within the cpuidle back-end driver ad hence deprecating the prepare routine and the CPUIDLE_FLAG_IGNORE flag. - Ref: https://lkml.org/lkml/2011/3/25/52 [3/4] - Splits the usage statistics (read/write) part out of cpuidle_state structure, so that the states can become read only and hence made global. [4/4] - Most APIs will now need to pass pointer to both global cpuidle_driver and per-cpu cpuidle_device structure. arch/arm/mach-at91/cpuidle.c | 41 +++-- arch/arm/mach-davinci/cpuidle.c | 51 --- arch/arm/mach-exynos4/cpuidle.c | 30 ++-- arch/arm/mach-kirkwood/cpuidle.c | 42 +++--- arch/arm/mach-omap2/cpuidle34xx.c | 133 +++-- arch/sh/kernel/cpu/shmobile/cpuidle.c | 28 ++-- drivers/acpi/processor_driver.c | 20 --- drivers/acpi/processor_idle.c | 251 +++-- drivers/cpuidle/cpuidle.c | 86 --- drivers/cpuidle/driver.c | 25 +++ drivers/cpuidle/governors/ladder.c| 41 - drivers/cpuidle/governors/menu.c | 29 ++-- drivers/cpuidle/sysfs.c | 22 ++- drivers/idle/intel_idle.c | 130 + include/acpi/processor.h |1 include/linux/cpuidle.h | 52 --- 16 files changed, 650 insertions(+), 332 deletions(-) -- -Deepthi -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V8 1/4] cpuidle: Move dev-last_residency update to driver enter routine; remove dev-last_state
Cpuidle governor only suggests the state to enter using the governor-select() interface, but allows the low level driver to override the recommended state. The actual entered state may be different because of software or hardware demotion. Software demotion is done by the back-end cpuidle driver and can be accounted correctly. Current cpuidle code uses last_state field to capture the actual state entered and based on that updates the statistics for the state entered. Ideally the driver enter routine should update the counters, and it should return the state actually entered rather than the time spent there. The generic cpuidle code should simply handle where the counters live in the sysfs namespace, not updating the counters. Reference: https://lkml.org/lkml/2011/3/25/52 Signed-off-by: Deepthi Dharwar deep...@linux.vnet.ibm.com Signed-off-by: Trinabh Gupta g.trin...@gmail.com Tested-by: Jean Pihet j-pi...@ti.com Reviewed-by: Kevin Hilman khil...@ti.com Acked-by: Arjan van de Ven ar...@linux.intel.com Acked-by: Kevin Hilman khil...@ti.com --- arch/arm/mach-at91/cpuidle.c | 10 +++- arch/arm/mach-davinci/cpuidle.c |9 +++- arch/arm/mach-exynos4/cpuidle.c |7 ++- arch/arm/mach-kirkwood/cpuidle.c | 12 - arch/arm/mach-omap2/cpuidle34xx.c | 67 + arch/sh/kernel/cpu/shmobile/cpuidle.c | 12 +++-- drivers/acpi/processor_idle.c | 75 ++--- drivers/cpuidle/cpuidle.c | 32 +++--- drivers/cpuidle/governors/ladder.c| 13 ++ drivers/cpuidle/governors/menu.c |7 ++- drivers/idle/intel_idle.c | 12 - include/linux/cpuidle.h |7 +-- 12 files changed, 164 insertions(+), 99 deletions(-) diff --git a/arch/arm/mach-at91/cpuidle.c b/arch/arm/mach-at91/cpuidle.c index 1cfeac1..4696a0d 100644 --- a/arch/arm/mach-at91/cpuidle.c +++ b/arch/arm/mach-at91/cpuidle.c @@ -33,7 +33,7 @@ static struct cpuidle_driver at91_idle_driver = { /* Actual code that puts the SoC in different idle states */ static int at91_enter_idle(struct cpuidle_device *dev, - struct cpuidle_state *state) + int index) { struct timeval before, after; int idle_time; @@ -41,10 +41,10 @@ static int at91_enter_idle(struct cpuidle_device *dev, local_irq_disable(); do_gettimeofday(before); - if (state == dev-states[0]) + if (index == 0) /* Wait for interrupt state */ cpu_do_idle(); - else if (state == dev-states[1]) { + else if (index == 1) { asm(b 1f; .align 5; 1:); asm(mcr p15, 0, r0, c7, c10, 4); /* drain write buffer */ saved_lpr = sdram_selfrefresh_enable(); @@ -55,7 +55,9 @@ static int at91_enter_idle(struct cpuidle_device *dev, local_irq_enable(); idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + (after.tv_usec - before.tv_usec); - return idle_time; + + dev-last_residency = idle_time; + return index; } /* Initialize CPU idle by registering the idle states */ diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c index bd59f31..ca8582a 100644 --- a/arch/arm/mach-davinci/cpuidle.c +++ b/arch/arm/mach-davinci/cpuidle.c @@ -78,9 +78,9 @@ static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = { /* Actual code that puts the SoC in different idle states */ static int davinci_enter_idle(struct cpuidle_device *dev, - struct cpuidle_state *state) + int index) { - struct davinci_ops *ops = cpuidle_get_statedata(state); + struct davinci_ops *ops = cpuidle_get_statedata(dev-states[index]); struct timeval before, after; int idle_time; @@ -98,7 +98,10 @@ static int davinci_enter_idle(struct cpuidle_device *dev, local_irq_enable(); idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + (after.tv_usec - before.tv_usec); - return idle_time; + + dev-last_residency = idle_time; + + return index; } static int __init davinci_cpuidle_probe(struct platform_device *pdev) diff --git a/arch/arm/mach-exynos4/cpuidle.c b/arch/arm/mach-exynos4/cpuidle.c index bf7e96f..ea026e7 100644 --- a/arch/arm/mach-exynos4/cpuidle.c +++ b/arch/arm/mach-exynos4/cpuidle.c @@ -16,7 +16,7 @@ #include asm/proc-fns.h static int exynos4_enter_idle(struct cpuidle_device *dev, - struct cpuidle_state *state); + int index); static struct cpuidle_state exynos4_cpuidle_set[] = { [0] = { @@ -37,7 +37,7 @@ static struct cpuidle_driver exynos4_idle_driver = { }; static int exynos4_enter_idle(struct cpuidle_device *dev
[PATCH V8 2/4] cpuidle: Remove CPUIDLE_FLAG_IGNORE and dev-prepare()
The cpuidle_device-prepare() mechanism causes updates to the cpuidle_state[].flags, setting and clearing CPUIDLE_FLAG_IGNORE to tell the governor not to chose a state on a per-cpu basis at run-time. State demotion is now handled by the driver and it returns the actual state entered. Hence, this mechanism is not required. Also this removes per-cpu flags from cpuidle_state enabling it to be made global. Reference: https://lkml.org/lkml/2011/3/25/52 Signed-off-by: Deepthi Dharwar deep...@linux.vnet.ibm Signed-off-by: Trinabh Gupta g.trin...@gmail.com Tested-by: Jean Pihet j-pi...@ti.com Acked-by: Arjan van de Ven ar...@linux.intel.com Reviewed-by: Kevin Hilman khil...@ti.com --- drivers/cpuidle/cpuidle.c| 10 -- drivers/cpuidle/governors/menu.c |2 -- include/linux/cpuidle.h |3 --- 3 files changed, 0 insertions(+), 15 deletions(-) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 88bd121..f66bcf9 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -83,16 +83,6 @@ int cpuidle_idle_call(void) hrtimer_peek_ahead_timers(); #endif - /* -* Call the device's prepare function before calling the -* governor's select function. -prepare gives the device's -* cpuidle driver a chance to update any dynamic information -* of its cpuidle states for the current idle period, e.g. -* state availability, latencies, residencies, etc. -*/ - if (dev-prepare) - dev-prepare(dev); - /* ask the governor for the next state */ next_state = cpuidle_curr_governor-select(dev); if (need_resched()) { diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index e4b200c..af724e8 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -288,8 +288,6 @@ static int menu_select(struct cpuidle_device *dev) for (i = CPUIDLE_DRIVER_STATE_START; i dev-state_count; i++) { struct cpuidle_state *s = dev-states[i]; - if (s-flags CPUIDLE_FLAG_IGNORE) - continue; if (s-target_residency data-predicted_us) continue; if (s-exit_latency latency_req) diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 8da811b..c6d85cf 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -47,7 +47,6 @@ struct cpuidle_state { /* Idle State Flags */ #define CPUIDLE_FLAG_TIME_VALID(0x01) /* is residency time measurable? */ -#define CPUIDLE_FLAG_IGNORE(0x100) /* ignore during this idle period */ #define CPUIDLE_DRIVER_FLAGS_MASK (0x) @@ -93,8 +92,6 @@ struct cpuidle_device { struct completion kobj_unregister; void*governor_data; int safe_state_index; - - int (*prepare) (struct cpuidle_device *dev); }; DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices); -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V8 3/4] cpuidle: Split cpuidle_state structure and move per-cpu statistics fields
This is the first step towards global registration of cpuidle states. The statistics used primarily by the governor are per-cpu and have to be split from rest of the fields inside cpuidle_state, which would be made global i.e. single copy. The driver_data field is also per-cpu and moved. Signed-off-by: Deepthi Dharwar deep...@linux.vnet.ibm.com Signed-off-by: Trinabh Gupta g.trin...@gmail.com Tested-by: Jean Pihet j-pi...@ti.com Reviewed-by: Kevin Hilman khil...@ti.com Acked-by: Arjan van de Ven ar...@linux.intel.com Acked-by: Kevin Hilman khil...@ti.com --- arch/arm/mach-davinci/cpuidle.c |5 ++-- arch/arm/mach-omap2/cpuidle34xx.c | 13 ++ drivers/acpi/processor_idle.c | 25 ++-- drivers/cpuidle/cpuidle.c | 11 + drivers/cpuidle/sysfs.c | 19 ++- drivers/idle/intel_idle.c | 46 +++-- include/linux/cpuidle.h | 25 7 files changed, 90 insertions(+), 54 deletions(-) diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c index ca8582a..f2d2f34 100644 --- a/arch/arm/mach-davinci/cpuidle.c +++ b/arch/arm/mach-davinci/cpuidle.c @@ -80,7 +80,8 @@ static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = { static int davinci_enter_idle(struct cpuidle_device *dev, int index) { - struct davinci_ops *ops = cpuidle_get_statedata(dev-states[index]); + struct cpuidle_state_usage *state_usage = dev-states_usage[index]; + struct davinci_ops *ops = cpuidle_get_statedata(state_usage); struct timeval before, after; int idle_time; @@ -142,7 +143,7 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev) strcpy(device-states[1].desc, WFI and DDR Self Refresh); if (pdata-ddr2_pdown) davinci_states[1].flags |= DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN; - cpuidle_set_statedata(device-states[1], davinci_states[1]); + cpuidle_set_statedata(device-states_usage[1], davinci_states[1]); device-state_count = DAVINCI_CPUIDLE_MAX_STATES; diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index 58425c7..d3fce7b 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c @@ -97,7 +97,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev, int index) { struct omap3_idle_statedata *cx = - cpuidle_get_statedata(dev-states[index]); + cpuidle_get_statedata(dev-states_usage[index]); struct timespec ts_preidle, ts_postidle, ts_idle; u32 mpu_state = cx-mpu_state, core_state = cx-core_state; int idle_time; @@ -160,8 +160,9 @@ return_sleep_time: static int next_valid_state(struct cpuidle_device *dev, int index) { + struct cpuidle_state_usage *curr_usage = dev-states_usage[index]; struct cpuidle_state *curr = dev-states[index]; - struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr); + struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage); u32 mpu_deepest_state = PWRDM_POWER_RET; u32 core_deepest_state = PWRDM_POWER_RET; int next_index = -1; @@ -202,7 +203,7 @@ static int next_valid_state(struct cpuidle_device *dev, */ idx--; for (; idx = 0; idx--) { - cx = cpuidle_get_statedata(dev-states[idx]); + cx = cpuidle_get_statedata(dev-states_usage[idx]); if ((cx-valid) (cx-mpu_state = mpu_deepest_state) (cx-core_state = core_deepest_state)) { @@ -231,7 +232,6 @@ static int next_valid_state(struct cpuidle_device *dev, static int omap3_enter_idle_bm(struct cpuidle_device *dev, int index) { - struct cpuidle_state *state = dev-states[index]; int new_state_idx; u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state; struct omap3_idle_statedata *cx; @@ -264,7 +264,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, * Prevent PER off if CORE is not in retention or off as this * would disable PER wakeups completely. */ - cx = cpuidle_get_statedata(state); + cx = cpuidle_get_statedata(dev-states_usage[index]); core_next_state = cx-core_state; per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd); if ((per_next_state == PWRDM_POWER_OFF) @@ -318,6 +318,7 @@ static inline struct omap3_idle_statedata *_fill_cstate( { struct omap3_idle_statedata *cx = omap3_idle_data[idx]; struct cpuidle_state *state = dev-states[idx]; + struct cpuidle_state_usage *state_usage = dev-states_usage[idx
[PATCH V8 4/4] cpuidle: Single/Global registration of idle states
This patch makes the cpuidle_states structure global (single copy) instead of per-cpu. The statistics needed on per-cpu basis by the governor are kept per-cpu. This simplifies the cpuidle subsystem as state registration is done by single cpu only. Having single copy of cpuidle_states saves memory. Rare case of asymmetric C-states can be handled within the cpuidle driver and architectures such as POWER do not have asymmetric C-states. Having single/global registration of all the idle states, dynamic C-state transitions on x86 are handled by the boot cpu. Here, the boot cpu would disable all the devices, re-populate the states and later enable all the devices, irrespective of the cpu that would receive the notification first. Reference: https://lkml.org/lkml/2011/4/25/83 Signed-off-by: Deepthi Dharwar deep...@linux.vnet.ibm.com Signed-off-by: Trinabh Gupta g.trin...@gmail.com Tested-by: Jean Pihet j-pi...@ti.com Reviewed-by: Kevin Hilman khil...@ti.com Acked-by: Arjan van de Ven ar...@linux.intel.com Acked-by: Kevin Hilman khil...@ti.com --- arch/arm/mach-at91/cpuidle.c | 31 +++-- arch/arm/mach-davinci/cpuidle.c | 39 --- arch/arm/mach-exynos4/cpuidle.c | 23 ++-- arch/arm/mach-kirkwood/cpuidle.c | 30 +++-- arch/arm/mach-omap2/cpuidle34xx.c | 73 - arch/sh/kernel/cpu/shmobile/cpuidle.c | 18 ++- drivers/acpi/processor_driver.c | 20 +-- drivers/acpi/processor_idle.c | 191 + drivers/cpuidle/cpuidle.c | 45 ++-- drivers/cpuidle/driver.c | 25 drivers/cpuidle/governors/ladder.c| 28 +++-- drivers/cpuidle/governors/menu.c | 20 ++- drivers/cpuidle/sysfs.c |3 - drivers/idle/intel_idle.c | 80 +++--- include/acpi/processor.h |1 include/linux/cpuidle.h | 19 ++- 16 files changed, 439 insertions(+), 207 deletions(-) diff --git a/arch/arm/mach-at91/cpuidle.c b/arch/arm/mach-at91/cpuidle.c index 4696a0d..93178f6 100644 --- a/arch/arm/mach-at91/cpuidle.c +++ b/arch/arm/mach-at91/cpuidle.c @@ -33,6 +33,7 @@ static struct cpuidle_driver at91_idle_driver = { /* Actual code that puts the SoC in different idle states */ static int at91_enter_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) { struct timeval before, after; @@ -64,27 +65,29 @@ static int at91_enter_idle(struct cpuidle_device *dev, static int at91_init_cpuidle(void) { struct cpuidle_device *device; - - cpuidle_register_driver(at91_idle_driver); + struct cpuidle_driver *driver = at91_idle_driver; device = per_cpu(at91_cpuidle_device, smp_processor_id()); device-state_count = AT91_MAX_STATES; + driver-state_count = AT91_MAX_STATES; /* Wait for interrupt state */ - device-states[0].enter = at91_enter_idle; - device-states[0].exit_latency = 1; - device-states[0].target_residency = 1; - device-states[0].flags = CPUIDLE_FLAG_TIME_VALID; - strcpy(device-states[0].name, WFI); - strcpy(device-states[0].desc, Wait for interrupt); + driver-states[0].enter = at91_enter_idle; + driver-states[0].exit_latency = 1; + driver-states[0].target_residency = 1; + driver-states[0].flags = CPUIDLE_FLAG_TIME_VALID; + strcpy(driver-states[0].name, WFI); + strcpy(driver-states[0].desc, Wait for interrupt); /* Wait for interrupt and RAM self refresh state */ - device-states[1].enter = at91_enter_idle; - device-states[1].exit_latency = 10; - device-states[1].target_residency = 1; - device-states[1].flags = CPUIDLE_FLAG_TIME_VALID; - strcpy(device-states[1].name, RAM_SR); - strcpy(device-states[1].desc, WFI and RAM Self Refresh); + driver-states[1].enter = at91_enter_idle; + driver-states[1].exit_latency = 10; + driver-states[1].target_residency = 1; + driver-states[1].flags = CPUIDLE_FLAG_TIME_VALID; + strcpy(driver-states[1].name, RAM_SR); + strcpy(driver-states[1].desc, WFI and RAM Self Refresh); + + cpuidle_register_driver(at91_idle_driver); if (cpuidle_register_device(device)) { printk(KERN_ERR at91_init_cpuidle: Failed registering\n); diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c index f2d2f34..dbeeccd 100644 --- a/arch/arm/mach-davinci/cpuidle.c +++ b/arch/arm/mach-davinci/cpuidle.c @@ -78,6 +78,7 @@ static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = { /* Actual code that puts the SoC in different idle states */ static int davinci_enter_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) { struct cpuidle_state_usage *state_usage = dev
[PATCH V7 0/4] cpuidle: Global registration of idle states with per-cpu statistics
Version 6 of this patch series dated 22nd Sept 2011 was Acked-by: Arjan van de Ven ar...@linux.intel.com Acked-by: Kevin Hilman khil...@ti.com for OMAP specific parts. Reviewed-by: Kevin Hilman khil...@ti.com Signed-off-by: Jean Pihet j-pi...@ti.com Hi Len, Can you please queue this series for the next mainline merge window by merging it into your development tree and also linux-next for further testing. I also tested it, by applying these patches on your ACPI tree hosted @github. Thanks -Deepthi The following patch series implements global registration of cpuidle states, and also has the necessary data structure changes to accommodate the per-cpu writable members of the cpuidle_states structure. This patch series had been in discussion earlier and following are the links to the previous discussions. v1 -- https://lkml.org/lkml/2011/3/22/161 v2 -- https://lkml.org/lkml/2011/1/13/98 v3 -- https://lkml.org/lkml/2011/2/8/73 v4 -- https://lkml.org/lkml/2011/4/28/312 v5 -- https://lkml.org/lkml/2011/6/6/259 v6 -- https://lkml.org/lkml/2011/9/22/58 Changes from previous version (V6): Removed the RFC tag. Tests done: 1. Compile tested for ARM using the following configs: da8xx_omapl_defconfig, exynos4_defconfig, kirkwood_defconfig, omap2plus_defconfig, at91rm9200_defconfig 2. Boot tested on x86 nehalem with multiple C-states for both intel_idle and acpi_idle drivers. 3. Boot tested on T60p thinkpad that has T2600 cpu with multiple C-states. Also tested the case when there is dynamic changes in C-states AC - Battery Power switch. Brief description of the patches: Core change in this series is to split the cpuidle_device structure into two parts, i.e global and per-cpu basis. The per-cpu pieces are mostly generic statistics that can be independent of current running driver. As a result of these changes, there is single copy of cpuidle_states structure and single registration done by one cpu. The low level driver is free to set per-cpu driver data on each cpu if needed using the cpuidle_set_statedata() as the case today. Only in very rare cases asymmetric C-states exist which can be handled within the cpuidle driver. Most architectures do not have asymmetric C-states. First two patches in the series facilitate splitting of cpuidle_states and cpuidle_device structure and next two patches do the actual split, change the API's and make existing code follow the changed API. [1/4] - Move the idle residency accounting part from cpuidle.c to the respective low level drivers, so that the accounting can be accurately maintained if the driver decides to demote the chosen (suggested) by the governor. [2/4] - removes the cpuidle_device()-prepare API since is is not widely used and the only use case was to allow software demotion using CPUIDLE_FLAG_IGNORE flag. Both these functions can be absorbed within the cpuidle back-end driver ad hence deprecating the prepare routine and the CPUIDLE_FLAG_IGNORE flag. - Ref: https://lkml.org/lkml/2011/3/25/52 [3/4] - Splits the usage statistics (read/write) part out of cpuidle_state structure, so that the states can become read only and hence made global. [4/4] - Most APIs will now need to pass pointer to both global cpuidle_driver and per-cpu cpuidle_device structure. arch/arm/mach-at91/cpuidle.c | 41 +++-- arch/arm/mach-davinci/cpuidle.c | 51 --- arch/arm/mach-exynos4/cpuidle.c | 30 ++-- arch/arm/mach-kirkwood/cpuidle.c | 42 +++--- arch/arm/mach-omap2/cpuidle34xx.c | 133 +++-- arch/sh/kernel/cpu/shmobile/cpuidle.c | 28 ++-- drivers/acpi/processor_driver.c | 20 --- drivers/acpi/processor_idle.c | 251 +++-- drivers/cpuidle/cpuidle.c | 86 --- drivers/cpuidle/driver.c | 25 +++ drivers/cpuidle/governors/ladder.c| 41 - drivers/cpuidle/governors/menu.c | 29 ++-- drivers/cpuidle/sysfs.c | 22 ++- drivers/idle/intel_idle.c | 130 + include/acpi/processor.h |1 include/linux/cpuidle.h | 52 --- 16 files changed, 650 insertions(+), 332 deletions(-) -- -Deepthi -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V7 1/4] cpuidle: Move dev-last_residency update to driver enter routine; remove dev-last_state
Cpuidle governor only suggests the state to enter using the governor-select() interface, but allows the low level driver to override the recommended state. The actual entered state may be different because of software or hardware demotion. Software demotion is done by the back-end cpuidle driver and can be accounted correctly. Current cpuidle code uses last_state field to capture the actual state entered and based on that updates the statistics for the state entered. Ideally the driver enter routine should update the counters, and it should return the state actually entered rather than the time spent there. The generic cpuidle code should simply handle where the counters live in the sysfs namespace, not updating the counters. Reference: https://lkml.org/lkml/2011/3/25/52 Signed-off-by: Deepthi Dharwar deep...@linux.vnet.ibm.com Signed-off-by: Trinabh Gupta g.trin...@gmail.com Signed-off-by: Jean Pihet j-pi...@ti.com Reviewed-by: Kevin Hilman khil...@ti.com Acked-by: Arjan van de Ven ar...@linux.intel.com Acked-by: Kevin Hilman khil...@ti.com --- arch/arm/mach-at91/cpuidle.c | 10 +++- arch/arm/mach-davinci/cpuidle.c |9 +++- arch/arm/mach-exynos4/cpuidle.c |7 ++- arch/arm/mach-kirkwood/cpuidle.c | 12 - arch/arm/mach-omap2/cpuidle34xx.c | 67 + arch/sh/kernel/cpu/shmobile/cpuidle.c | 12 +++-- drivers/acpi/processor_idle.c | 75 ++--- drivers/cpuidle/cpuidle.c | 32 +++--- drivers/cpuidle/governors/ladder.c| 13 ++ drivers/cpuidle/governors/menu.c |7 ++- drivers/idle/intel_idle.c | 12 - include/linux/cpuidle.h |7 +-- 12 files changed, 164 insertions(+), 99 deletions(-) diff --git a/arch/arm/mach-at91/cpuidle.c b/arch/arm/mach-at91/cpuidle.c index 1cfeac1..4696a0d 100644 --- a/arch/arm/mach-at91/cpuidle.c +++ b/arch/arm/mach-at91/cpuidle.c @@ -33,7 +33,7 @@ static struct cpuidle_driver at91_idle_driver = { /* Actual code that puts the SoC in different idle states */ static int at91_enter_idle(struct cpuidle_device *dev, - struct cpuidle_state *state) + int index) { struct timeval before, after; int idle_time; @@ -41,10 +41,10 @@ static int at91_enter_idle(struct cpuidle_device *dev, local_irq_disable(); do_gettimeofday(before); - if (state == dev-states[0]) + if (index == 0) /* Wait for interrupt state */ cpu_do_idle(); - else if (state == dev-states[1]) { + else if (index == 1) { asm(b 1f; .align 5; 1:); asm(mcr p15, 0, r0, c7, c10, 4); /* drain write buffer */ saved_lpr = sdram_selfrefresh_enable(); @@ -55,7 +55,9 @@ static int at91_enter_idle(struct cpuidle_device *dev, local_irq_enable(); idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + (after.tv_usec - before.tv_usec); - return idle_time; + + dev-last_residency = idle_time; + return index; } /* Initialize CPU idle by registering the idle states */ diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c index bd59f31..ca8582a 100644 --- a/arch/arm/mach-davinci/cpuidle.c +++ b/arch/arm/mach-davinci/cpuidle.c @@ -78,9 +78,9 @@ static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = { /* Actual code that puts the SoC in different idle states */ static int davinci_enter_idle(struct cpuidle_device *dev, - struct cpuidle_state *state) + int index) { - struct davinci_ops *ops = cpuidle_get_statedata(state); + struct davinci_ops *ops = cpuidle_get_statedata(dev-states[index]); struct timeval before, after; int idle_time; @@ -98,7 +98,10 @@ static int davinci_enter_idle(struct cpuidle_device *dev, local_irq_enable(); idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + (after.tv_usec - before.tv_usec); - return idle_time; + + dev-last_residency = idle_time; + + return index; } static int __init davinci_cpuidle_probe(struct platform_device *pdev) diff --git a/arch/arm/mach-exynos4/cpuidle.c b/arch/arm/mach-exynos4/cpuidle.c index bf7e96f..ea026e7 100644 --- a/arch/arm/mach-exynos4/cpuidle.c +++ b/arch/arm/mach-exynos4/cpuidle.c @@ -16,7 +16,7 @@ #include asm/proc-fns.h static int exynos4_enter_idle(struct cpuidle_device *dev, - struct cpuidle_state *state); + int index); static struct cpuidle_state exynos4_cpuidle_set[] = { [0] = { @@ -37,7 +37,7 @@ static struct cpuidle_driver exynos4_idle_driver = { }; static int exynos4_enter_idle(struct cpuidle_device *dev
[PATCH V7 2/4] cpuidle: Remove CPUIDLE_FLAG_IGNORE and dev-prepare()
The cpuidle_device-prepare() mechanism causes updates to the cpuidle_state[].flags, setting and clearing CPUIDLE_FLAG_IGNORE to tell the governor not to chose a state on a per-cpu basis at run-time. State demotion is now handled by the driver and it returns the actual state entered. Hence, this mechanism is not required. Also this removes per-cpu flags from cpuidle_state enabling it to be made global. Reference: https://lkml.org/lkml/2011/3/25/52 Signed-off-by: Deepthi Dharwar deep...@linux.vnet.ibm Signed-off-by: Trinabh Gupta g.trin...@gmail.com Signed-off-by: Jean Pihet j-pi...@ti.com Acked-by: Arjan van de Ven ar...@linux.intel.com Reviewed-by: Kevin Hilman khil...@ti.com --- drivers/cpuidle/cpuidle.c| 10 -- drivers/cpuidle/governors/menu.c |2 -- include/linux/cpuidle.h |3 --- 3 files changed, 0 insertions(+), 15 deletions(-) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 88bd121..f66bcf9 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -83,16 +83,6 @@ int cpuidle_idle_call(void) hrtimer_peek_ahead_timers(); #endif - /* -* Call the device's prepare function before calling the -* governor's select function. -prepare gives the device's -* cpuidle driver a chance to update any dynamic information -* of its cpuidle states for the current idle period, e.g. -* state availability, latencies, residencies, etc. -*/ - if (dev-prepare) - dev-prepare(dev); - /* ask the governor for the next state */ next_state = cpuidle_curr_governor-select(dev); if (need_resched()) { diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index e4b200c..af724e8 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -288,8 +288,6 @@ static int menu_select(struct cpuidle_device *dev) for (i = CPUIDLE_DRIVER_STATE_START; i dev-state_count; i++) { struct cpuidle_state *s = dev-states[i]; - if (s-flags CPUIDLE_FLAG_IGNORE) - continue; if (s-target_residency data-predicted_us) continue; if (s-exit_latency latency_req) diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 8da811b..c6d85cf 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -47,7 +47,6 @@ struct cpuidle_state { /* Idle State Flags */ #define CPUIDLE_FLAG_TIME_VALID(0x01) /* is residency time measurable? */ -#define CPUIDLE_FLAG_IGNORE(0x100) /* ignore during this idle period */ #define CPUIDLE_DRIVER_FLAGS_MASK (0x) @@ -93,8 +92,6 @@ struct cpuidle_device { struct completion kobj_unregister; void*governor_data; int safe_state_index; - - int (*prepare) (struct cpuidle_device *dev); }; DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices); -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V7 3/4] cpuidle: Split cpuidle_state structure and move per-cpu statistics fields
This is the first step towards global registration of cpuidle states. The statistics used primarily by the governor are per-cpu and have to be split from rest of the fields inside cpuidle_state, which would be made global i.e. single copy. The driver_data field is also per-cpu and moved. Signed-off-by: Deepthi Dharwar deep...@linux.vnet.ibm.com Signed-off-by: Trinabh Gupta g.trin...@gmail.com Signed-off-by: Jean Pihet j-pi...@ti.com Reviewed-by: Kevin Hilman khil...@ti.com Acked-by: Arjan van de Ven ar...@linux.intel.com Acked-by: Kevin Hilman khil...@ti.com --- arch/arm/mach-davinci/cpuidle.c |5 ++-- arch/arm/mach-omap2/cpuidle34xx.c | 13 ++ drivers/acpi/processor_idle.c | 25 ++-- drivers/cpuidle/cpuidle.c | 11 + drivers/cpuidle/sysfs.c | 19 ++- drivers/idle/intel_idle.c | 46 +++-- include/linux/cpuidle.h | 25 7 files changed, 90 insertions(+), 54 deletions(-) diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c index ca8582a..f2d2f34 100644 --- a/arch/arm/mach-davinci/cpuidle.c +++ b/arch/arm/mach-davinci/cpuidle.c @@ -80,7 +80,8 @@ static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = { static int davinci_enter_idle(struct cpuidle_device *dev, int index) { - struct davinci_ops *ops = cpuidle_get_statedata(dev-states[index]); + struct cpuidle_state_usage *state_usage = dev-states_usage[index]; + struct davinci_ops *ops = cpuidle_get_statedata(state_usage); struct timeval before, after; int idle_time; @@ -142,7 +143,7 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev) strcpy(device-states[1].desc, WFI and DDR Self Refresh); if (pdata-ddr2_pdown) davinci_states[1].flags |= DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN; - cpuidle_set_statedata(device-states[1], davinci_states[1]); + cpuidle_set_statedata(device-states_usage[1], davinci_states[1]); device-state_count = DAVINCI_CPUIDLE_MAX_STATES; diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index 58425c7..d3fce7b 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c @@ -97,7 +97,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev, int index) { struct omap3_idle_statedata *cx = - cpuidle_get_statedata(dev-states[index]); + cpuidle_get_statedata(dev-states_usage[index]); struct timespec ts_preidle, ts_postidle, ts_idle; u32 mpu_state = cx-mpu_state, core_state = cx-core_state; int idle_time; @@ -160,8 +160,9 @@ return_sleep_time: static int next_valid_state(struct cpuidle_device *dev, int index) { + struct cpuidle_state_usage *curr_usage = dev-states_usage[index]; struct cpuidle_state *curr = dev-states[index]; - struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr); + struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage); u32 mpu_deepest_state = PWRDM_POWER_RET; u32 core_deepest_state = PWRDM_POWER_RET; int next_index = -1; @@ -202,7 +203,7 @@ static int next_valid_state(struct cpuidle_device *dev, */ idx--; for (; idx = 0; idx--) { - cx = cpuidle_get_statedata(dev-states[idx]); + cx = cpuidle_get_statedata(dev-states_usage[idx]); if ((cx-valid) (cx-mpu_state = mpu_deepest_state) (cx-core_state = core_deepest_state)) { @@ -231,7 +232,6 @@ static int next_valid_state(struct cpuidle_device *dev, static int omap3_enter_idle_bm(struct cpuidle_device *dev, int index) { - struct cpuidle_state *state = dev-states[index]; int new_state_idx; u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state; struct omap3_idle_statedata *cx; @@ -264,7 +264,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, * Prevent PER off if CORE is not in retention or off as this * would disable PER wakeups completely. */ - cx = cpuidle_get_statedata(state); + cx = cpuidle_get_statedata(dev-states_usage[index]); core_next_state = cx-core_state; per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd); if ((per_next_state == PWRDM_POWER_OFF) @@ -318,6 +318,7 @@ static inline struct omap3_idle_statedata *_fill_cstate( { struct omap3_idle_statedata *cx = omap3_idle_data[idx]; struct cpuidle_state *state = dev-states[idx]; + struct cpuidle_state_usage *state_usage = dev-states_usage[idx
[PATCH V7 4/4] cpuidle: Single/Global registration of idle states
This patch makes the cpuidle_states structure global (single copy) instead of per-cpu. The statistics needed on per-cpu basis by the governor are kept per-cpu. This simplifies the cpuidle subsystem as state registration is done by single cpu only. Having single copy of cpuidle_states saves memory. Rare case of asymmetric C-states can be handled within the cpuidle driver and architectures such as POWER do not have asymmetric C-states. Having single/global registration for all the idle states, dynamic C-state transitions on x86 are handled by the boot cpu. Here, the boot cpu would disable all the devices, re-populate the states and later enable all the devices, irrespective of the cpu that would receive the notification first. Reference: https://lkml.org/lkml/2011/4/25/83 Signed-off-by: Deepthi Dharwar deep...@linux.vnet.ibm.com Signed-off-by: Trinabh Gupta g.trin...@gmail.com Signed-off-by: Jean Pihet j-pi...@ti.com Reviewed-by: Kevin Hilman khil...@ti.com Acked-by: Arjan van de Ven ar...@linux.intel.com Acked-by: Kevin Hilman khil...@ti.com --- arch/arm/mach-at91/cpuidle.c | 31 +++-- arch/arm/mach-davinci/cpuidle.c | 39 --- arch/arm/mach-exynos4/cpuidle.c | 23 ++-- arch/arm/mach-kirkwood/cpuidle.c | 30 +++-- arch/arm/mach-omap2/cpuidle34xx.c | 73 - arch/sh/kernel/cpu/shmobile/cpuidle.c | 18 ++- drivers/acpi/processor_driver.c | 20 +-- drivers/acpi/processor_idle.c | 191 + drivers/cpuidle/cpuidle.c | 45 ++-- drivers/cpuidle/driver.c | 25 drivers/cpuidle/governors/ladder.c| 28 +++-- drivers/cpuidle/governors/menu.c | 20 ++- drivers/cpuidle/sysfs.c |3 - drivers/idle/intel_idle.c | 80 +++--- include/acpi/processor.h |1 include/linux/cpuidle.h | 19 ++- 16 files changed, 439 insertions(+), 207 deletions(-) diff --git a/arch/arm/mach-at91/cpuidle.c b/arch/arm/mach-at91/cpuidle.c index 4696a0d..93178f6 100644 --- a/arch/arm/mach-at91/cpuidle.c +++ b/arch/arm/mach-at91/cpuidle.c @@ -33,6 +33,7 @@ static struct cpuidle_driver at91_idle_driver = { /* Actual code that puts the SoC in different idle states */ static int at91_enter_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) { struct timeval before, after; @@ -64,27 +65,29 @@ static int at91_enter_idle(struct cpuidle_device *dev, static int at91_init_cpuidle(void) { struct cpuidle_device *device; - - cpuidle_register_driver(at91_idle_driver); + struct cpuidle_driver *driver = at91_idle_driver; device = per_cpu(at91_cpuidle_device, smp_processor_id()); device-state_count = AT91_MAX_STATES; + driver-state_count = AT91_MAX_STATES; /* Wait for interrupt state */ - device-states[0].enter = at91_enter_idle; - device-states[0].exit_latency = 1; - device-states[0].target_residency = 1; - device-states[0].flags = CPUIDLE_FLAG_TIME_VALID; - strcpy(device-states[0].name, WFI); - strcpy(device-states[0].desc, Wait for interrupt); + driver-states[0].enter = at91_enter_idle; + driver-states[0].exit_latency = 1; + driver-states[0].target_residency = 1; + driver-states[0].flags = CPUIDLE_FLAG_TIME_VALID; + strcpy(driver-states[0].name, WFI); + strcpy(driver-states[0].desc, Wait for interrupt); /* Wait for interrupt and RAM self refresh state */ - device-states[1].enter = at91_enter_idle; - device-states[1].exit_latency = 10; - device-states[1].target_residency = 1; - device-states[1].flags = CPUIDLE_FLAG_TIME_VALID; - strcpy(device-states[1].name, RAM_SR); - strcpy(device-states[1].desc, WFI and RAM Self Refresh); + driver-states[1].enter = at91_enter_idle; + driver-states[1].exit_latency = 10; + driver-states[1].target_residency = 1; + driver-states[1].flags = CPUIDLE_FLAG_TIME_VALID; + strcpy(driver-states[1].name, RAM_SR); + strcpy(driver-states[1].desc, WFI and RAM Self Refresh); + + cpuidle_register_driver(at91_idle_driver); if (cpuidle_register_device(device)) { printk(KERN_ERR at91_init_cpuidle: Failed registering\n); diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c index f2d2f34..dbeeccd 100644 --- a/arch/arm/mach-davinci/cpuidle.c +++ b/arch/arm/mach-davinci/cpuidle.c @@ -78,6 +78,7 @@ static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = { /* Actual code that puts the SoC in different idle states */ static int davinci_enter_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) { struct cpuidle_state_usage *state_usage
Re: [RFC PATCH V6 0/4] cpuidle: Global registration of idle states with per-cpu statistics
On Friday 23 September 2011 01:15 AM, Kevin Hilman wrote: Deepthi Dharwar deep...@linux.vnet.ibm.com writes: The following patch series implements global registration of cpuidle states, and also has the necessary data structure changes to accommodate the per-cpu writable members of the cpuidle_states structure. I reviewed earlier versions of the series, and this version still looks good to me. Any reason it is still RFC? Reviewed-by: Kevin Hilman khil...@ti.com and for the OMAP-specific parts, Acked-by: Kevin Hilman khil...@ti.com Kevin Hi Kevin, Thanks for reviewing the patch. This was posted as an RFC, as there were a couple of ToDos listed in this patch series which I thought needed additional review before I could ask for inclusion. To Do : == 1. Russell King pointed out that in (V5 1/4) of this patch in arch/arm/mach-at91/cpuidle.c, AT91 pieces may be broken. In at91_enter_idle() routine, folks need to fix the two consecutive asm() statements by combining it to one as per the GCC reference manual. Reference: https://lkml.org/lkml/2011/6/6/273 2. In (V6 4/4), handle the case when idle states may change at run time and acpi_processor_cst_has_changed() routine is called in a better way than the current solution in this patch. In this current solution where global registration is implemented, the boot cpu on x86 would disable all the devices, repopulate the states and later enable all the devices, irrespective of the cpu that would receive the notification first. Reference: https://lkml.org/lkml/2011/4/25/83 Thanks Regards, -Deepthi -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH V6 0/4] cpuidle: Global registration of idle states with per-cpu statistics
The following patch series implements global registration of cpuidle states, and also has the necessary data structure changes to accommodate the per-cpu writable members of the cpuidle_states structure. This patch series had been in discussion earlier and following are the links to the previous discussions. v1 -- https://lkml.org/lkml/2011/3/22/161 v2 -- https://lkml.org/lkml/2011/1/13/98 v3 -- https://lkml.org/lkml/2011/2/8/73 v4 -- https://lkml.org/lkml/2011/4/28/312 v5 -- https://lkml.org/lkml/2011/6/6/259 Changes from previous version (V5): Rebased the series to 3.1-rc7 Tests done: 1. Compile tested for ARM using the following configs: da8xx_omapl_defconfig, exynos4_defconfig, kirkwood_defconfig, omap2plus_defconfig, at91rm9200_defconfig 2. Boot tested on x86 nehalem with multiple C-states for both intel_idle and acpi_idle drivers. 3. Boot tested on T60p thinkpad that has T2600 cpu with multiple C-states. Also tested the case when there is dynamic changes in C-states AC - Battery Power switch. Brief description of the patches: Core change in this series is to split the cpuidle_device structure into two parts, i.e global and per-cpu basis. The per-cpu pieces are mostly generic statistics that can be independent of current running driver. As a result of these changes, there is single copy of cpuidle_states structure and single registration done by one cpu. The low level driver is free to set per-cpu driver data on each cpu if needed using the cpuidle_set_statedata() as the case today. Only in very rare cases asymmetric C-states exist which can be handled within the cpuidle driver. Most architectures do not have asymmetric C-states. First two patches in the series facilitate splitting of cpuidle_states and cpuidle_device structure and next two patches do the actual split, change the API's and make existing code follow the changed API. [1/4] - Move the idle residency accounting part from cpuidle.c to the respective low level drivers, so that the accounting can be accurately maintained if the driver decides to demote the chosen (suggested) by the governor. [2/4] - removes the cpuidle_device()-prepare API since is is not widely used and the only use case was to allow software demotion using CPUIDLE_FLAG_IGNORE flag. Both these functions can be absorbed within the cpuidle back-end driver ad hence deprecating the prepare routine and the CPUIDLE_FLAG_IGNORE flag. - Ref: https://lkml.org/lkml/2011/3/25/52 [3/4] - Splits the usage statistics (read/write) part out of cpuidle_state structure, so that the states can become read only and hence made global. [4/4] - Most APIs will now need to pass pointer to both global cpuidle_driver and per-cpu cpuidle_device structure. arch/arm/mach-at91/cpuidle.c | 41 +++-- arch/arm/mach-davinci/cpuidle.c | 51 --- arch/arm/mach-exynos4/cpuidle.c | 30 ++-- arch/arm/mach-kirkwood/cpuidle.c | 42 +++--- arch/arm/mach-omap2/cpuidle34xx.c | 133 +++-- arch/sh/kernel/cpu/shmobile/cpuidle.c | 28 ++-- drivers/acpi/processor_driver.c | 20 --- drivers/acpi/processor_idle.c | 251 +++-- drivers/cpuidle/cpuidle.c | 86 --- drivers/cpuidle/driver.c | 25 +++ drivers/cpuidle/governors/ladder.c| 41 - drivers/cpuidle/governors/menu.c | 29 ++-- drivers/cpuidle/sysfs.c | 22 ++- drivers/idle/intel_idle.c | 130 + include/acpi/processor.h |1 include/linux/cpuidle.h | 52 --- 16 files changed, 650 insertions(+), 332 deletions(-) -- Thanks -Deepthi -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH V6 2/4] cpuidle: Remove CPUIDLE_FLAG_IGNORE and dev-prepare()
The cpuidle_device-prepare() mechanism causes updates to the cpuidle_state[].flags, setting and clearing CPUIDLE_FLAG_IGNORE to tell the governor not to chose a state on a per-cpu basis at run-time. State demotion is now handled by the driver and it returns the actual state entered. Hence, this mechanism is not required. Also this removes per-cpu flags from cpuidle_state enabling it to be made global. Ref: https://lkml.org/lkml/2011/3/25/52 Signed-off-by: Deepthi Dharwar deep...@linux.vnet.ibm Signed-off-by: Trinabh Gupta g.trin...@gmail.com --- drivers/cpuidle/cpuidle.c| 10 -- drivers/cpuidle/governors/menu.c |2 -- include/linux/cpuidle.h |3 --- 3 files changed, 0 insertions(+), 15 deletions(-) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 88bd121..f66bcf9 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -83,16 +83,6 @@ int cpuidle_idle_call(void) hrtimer_peek_ahead_timers(); #endif - /* -* Call the device's prepare function before calling the -* governor's select function. -prepare gives the device's -* cpuidle driver a chance to update any dynamic information -* of its cpuidle states for the current idle period, e.g. -* state availability, latencies, residencies, etc. -*/ - if (dev-prepare) - dev-prepare(dev); - /* ask the governor for the next state */ next_state = cpuidle_curr_governor-select(dev); if (need_resched()) { diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index e4b200c..af724e8 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -288,8 +288,6 @@ static int menu_select(struct cpuidle_device *dev) for (i = CPUIDLE_DRIVER_STATE_START; i dev-state_count; i++) { struct cpuidle_state *s = dev-states[i]; - if (s-flags CPUIDLE_FLAG_IGNORE) - continue; if (s-target_residency data-predicted_us) continue; if (s-exit_latency latency_req) diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 8da811b..c6d85cf 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -47,7 +47,6 @@ struct cpuidle_state { /* Idle State Flags */ #define CPUIDLE_FLAG_TIME_VALID(0x01) /* is residency time measurable? */ -#define CPUIDLE_FLAG_IGNORE(0x100) /* ignore during this idle period */ #define CPUIDLE_DRIVER_FLAGS_MASK (0x) @@ -93,8 +92,6 @@ struct cpuidle_device { struct completion kobj_unregister; void*governor_data; int safe_state_index; - - int (*prepare) (struct cpuidle_device *dev); }; DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices); -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH V6 1/4] cpuidle: Move dev-last_residency update to driver enter routine; remove dev-last_state
Cpuidle governor only suggests the state to enter using the governor-select() interface, but allows the low level driver to override the recommended state. The actual entered state may be different because of software or hardware demotion. Software demotion is done by the back-end cpuidle driver and can be accounted correctly. Current cpuidle code uses last_state field to capture the actual state entered and based on that updates the statistics for the state entered. Ideally the driver enter routine should update the counters, and it should return the state actually entered rather than the time spent there. The generic cpuidle code should simply handle where the counters live in the sysfs namespace, not updating the counters. Reference: https://lkml.org/lkml/2011/3/25/52 To Do : == Russell King pointed out that in (V5) of this patch in arch/arm/mach-at91/cpuidle.c, AT91 pieces may be broken. In at91_enter_idle() routine, folks need to fix the two consecutive asm() statements by combining it to one as per the GCC reference manual. Reference: https://lkml.org/lkml/2011/6/6/273 Signed-off-by: Deepthi Dharwar deep...@linux.vnet.ibm.com Signed-off-by: Trinabh Gupta g.trin...@gmail.com --- arch/arm/mach-at91/cpuidle.c | 10 +++- arch/arm/mach-davinci/cpuidle.c |9 +++- arch/arm/mach-exynos4/cpuidle.c |7 ++- arch/arm/mach-kirkwood/cpuidle.c | 12 - arch/arm/mach-omap2/cpuidle34xx.c | 67 + arch/sh/kernel/cpu/shmobile/cpuidle.c | 12 +++-- drivers/acpi/processor_idle.c | 75 ++--- drivers/cpuidle/cpuidle.c | 32 +++--- drivers/cpuidle/governors/ladder.c| 13 ++ drivers/cpuidle/governors/menu.c |7 ++- drivers/idle/intel_idle.c | 12 - include/linux/cpuidle.h |7 +-- 12 files changed, 164 insertions(+), 99 deletions(-) diff --git a/arch/arm/mach-at91/cpuidle.c b/arch/arm/mach-at91/cpuidle.c index 1cfeac1..4696a0d 100644 --- a/arch/arm/mach-at91/cpuidle.c +++ b/arch/arm/mach-at91/cpuidle.c @@ -33,7 +33,7 @@ static struct cpuidle_driver at91_idle_driver = { /* Actual code that puts the SoC in different idle states */ static int at91_enter_idle(struct cpuidle_device *dev, - struct cpuidle_state *state) + int index) { struct timeval before, after; int idle_time; @@ -41,10 +41,10 @@ static int at91_enter_idle(struct cpuidle_device *dev, local_irq_disable(); do_gettimeofday(before); - if (state == dev-states[0]) + if (index == 0) /* Wait for interrupt state */ cpu_do_idle(); - else if (state == dev-states[1]) { + else if (index == 1) { asm(b 1f; .align 5; 1:); asm(mcr p15, 0, r0, c7, c10, 4); /* drain write buffer */ saved_lpr = sdram_selfrefresh_enable(); @@ -55,7 +55,9 @@ static int at91_enter_idle(struct cpuidle_device *dev, local_irq_enable(); idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + (after.tv_usec - before.tv_usec); - return idle_time; + + dev-last_residency = idle_time; + return index; } /* Initialize CPU idle by registering the idle states */ diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c index bd59f31..ca8582a 100644 --- a/arch/arm/mach-davinci/cpuidle.c +++ b/arch/arm/mach-davinci/cpuidle.c @@ -78,9 +78,9 @@ static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = { /* Actual code that puts the SoC in different idle states */ static int davinci_enter_idle(struct cpuidle_device *dev, - struct cpuidle_state *state) + int index) { - struct davinci_ops *ops = cpuidle_get_statedata(state); + struct davinci_ops *ops = cpuidle_get_statedata(dev-states[index]); struct timeval before, after; int idle_time; @@ -98,7 +98,10 @@ static int davinci_enter_idle(struct cpuidle_device *dev, local_irq_enable(); idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + (after.tv_usec - before.tv_usec); - return idle_time; + + dev-last_residency = idle_time; + + return index; } static int __init davinci_cpuidle_probe(struct platform_device *pdev) diff --git a/arch/arm/mach-exynos4/cpuidle.c b/arch/arm/mach-exynos4/cpuidle.c index bf7e96f..ea026e7 100644 --- a/arch/arm/mach-exynos4/cpuidle.c +++ b/arch/arm/mach-exynos4/cpuidle.c @@ -16,7 +16,7 @@ #include asm/proc-fns.h static int exynos4_enter_idle(struct cpuidle_device *dev, - struct cpuidle_state *state); + int index); static struct cpuidle_state exynos4_cpuidle_set[] = { [0] = { @@ -37,7 +37,7
[RFC PATCH V6 3/4] cpuidle: Split cpuidle_state structure and move per-cpu statistics fields
This is the first step towards global registration of cpuidle states. The statistics used primarily by the governor are per-cpu and have to be split from rest of the fields inside cpuidle_state, which would be made global i.e. single copy. The driver_data field is also per-cpu and moved. Signed-off-by: Deepthi Dharwar deep...@linux.vnet.ibm.com Signed-off-by: Trinabh Gupta g.trin...@gmail.com --- arch/arm/mach-davinci/cpuidle.c |5 ++-- arch/arm/mach-omap2/cpuidle34xx.c | 13 ++ drivers/acpi/processor_idle.c | 25 ++-- drivers/cpuidle/cpuidle.c | 11 + drivers/cpuidle/sysfs.c | 19 ++- drivers/idle/intel_idle.c | 46 +++-- include/linux/cpuidle.h | 25 7 files changed, 90 insertions(+), 54 deletions(-) diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c index ca8582a..f2d2f34 100644 --- a/arch/arm/mach-davinci/cpuidle.c +++ b/arch/arm/mach-davinci/cpuidle.c @@ -80,7 +80,8 @@ static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = { static int davinci_enter_idle(struct cpuidle_device *dev, int index) { - struct davinci_ops *ops = cpuidle_get_statedata(dev-states[index]); + struct cpuidle_state_usage *state_usage = dev-states_usage[index]; + struct davinci_ops *ops = cpuidle_get_statedata(state_usage); struct timeval before, after; int idle_time; @@ -142,7 +143,7 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev) strcpy(device-states[1].desc, WFI and DDR Self Refresh); if (pdata-ddr2_pdown) davinci_states[1].flags |= DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN; - cpuidle_set_statedata(device-states[1], davinci_states[1]); + cpuidle_set_statedata(device-states_usage[1], davinci_states[1]); device-state_count = DAVINCI_CPUIDLE_MAX_STATES; diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index 58425c7..d3fce7b 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c @@ -97,7 +97,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev, int index) { struct omap3_idle_statedata *cx = - cpuidle_get_statedata(dev-states[index]); + cpuidle_get_statedata(dev-states_usage[index]); struct timespec ts_preidle, ts_postidle, ts_idle; u32 mpu_state = cx-mpu_state, core_state = cx-core_state; int idle_time; @@ -160,8 +160,9 @@ return_sleep_time: static int next_valid_state(struct cpuidle_device *dev, int index) { + struct cpuidle_state_usage *curr_usage = dev-states_usage[index]; struct cpuidle_state *curr = dev-states[index]; - struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr); + struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage); u32 mpu_deepest_state = PWRDM_POWER_RET; u32 core_deepest_state = PWRDM_POWER_RET; int next_index = -1; @@ -202,7 +203,7 @@ static int next_valid_state(struct cpuidle_device *dev, */ idx--; for (; idx = 0; idx--) { - cx = cpuidle_get_statedata(dev-states[idx]); + cx = cpuidle_get_statedata(dev-states_usage[idx]); if ((cx-valid) (cx-mpu_state = mpu_deepest_state) (cx-core_state = core_deepest_state)) { @@ -231,7 +232,6 @@ static int next_valid_state(struct cpuidle_device *dev, static int omap3_enter_idle_bm(struct cpuidle_device *dev, int index) { - struct cpuidle_state *state = dev-states[index]; int new_state_idx; u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state; struct omap3_idle_statedata *cx; @@ -264,7 +264,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, * Prevent PER off if CORE is not in retention or off as this * would disable PER wakeups completely. */ - cx = cpuidle_get_statedata(state); + cx = cpuidle_get_statedata(dev-states_usage[index]); core_next_state = cx-core_state; per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd); if ((per_next_state == PWRDM_POWER_OFF) @@ -318,6 +318,7 @@ static inline struct omap3_idle_statedata *_fill_cstate( { struct omap3_idle_statedata *cx = omap3_idle_data[idx]; struct cpuidle_state *state = dev-states[idx]; + struct cpuidle_state_usage *state_usage = dev-states_usage[idx]; state-exit_latency = cpuidle_params_table[idx].exit_latency; state-target_residency = cpuidle_params_table[idx].target_residency; @@ -326,7 +327,7 @@ static
[RFC PATCH V6 4/4] cpuidle: Single/Global registration of idle states
This patch makes the cpuidle_states structure global (single copy) instead of per-cpu. The statistics needed on per-cpu basis by the governor are kept per-cpu. This simplifies the cpuidle subsystem as state registration is done by single cpu only. Having single copy of cpuidle_states saves memory. Rare case of asymmetric C-states can be handled within the cpuidle driver and architectures such as POWER do not have asymmetric C-states. ToDo: Handle the case when idle states may change at run time and acpi_processor_cst_has_changed() routine is called in a better way than the current solution in this patch. In this current solution where global registration is implemented, the boot cpu on x86 would disable all the devices, repopulate the states and later enable all the devices, irrespective of the cpu that would receive the notification first. Reference: https://lkml.org/lkml/2011/4/25/83 Signed-off-by: Deepthi Dharwar deep...@linux.vnet.ibm.com Signed-off-by: Trinabh Gupta g.trin...@gmail.com --- arch/arm/mach-at91/cpuidle.c | 31 +++-- arch/arm/mach-davinci/cpuidle.c | 39 --- arch/arm/mach-exynos4/cpuidle.c | 23 ++-- arch/arm/mach-kirkwood/cpuidle.c | 30 +++-- arch/arm/mach-omap2/cpuidle34xx.c | 73 - arch/sh/kernel/cpu/shmobile/cpuidle.c | 18 ++- drivers/acpi/processor_driver.c | 20 +-- drivers/acpi/processor_idle.c | 191 + drivers/cpuidle/cpuidle.c | 45 ++-- drivers/cpuidle/driver.c | 25 drivers/cpuidle/governors/ladder.c| 28 +++-- drivers/cpuidle/governors/menu.c | 20 ++- drivers/cpuidle/sysfs.c |3 - drivers/idle/intel_idle.c | 80 +++--- include/acpi/processor.h |1 include/linux/cpuidle.h | 19 ++- 16 files changed, 439 insertions(+), 207 deletions(-) diff --git a/arch/arm/mach-at91/cpuidle.c b/arch/arm/mach-at91/cpuidle.c index 4696a0d..93178f6 100644 --- a/arch/arm/mach-at91/cpuidle.c +++ b/arch/arm/mach-at91/cpuidle.c @@ -33,6 +33,7 @@ static struct cpuidle_driver at91_idle_driver = { /* Actual code that puts the SoC in different idle states */ static int at91_enter_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) { struct timeval before, after; @@ -64,27 +65,29 @@ static int at91_enter_idle(struct cpuidle_device *dev, static int at91_init_cpuidle(void) { struct cpuidle_device *device; - - cpuidle_register_driver(at91_idle_driver); + struct cpuidle_driver *driver = at91_idle_driver; device = per_cpu(at91_cpuidle_device, smp_processor_id()); device-state_count = AT91_MAX_STATES; + driver-state_count = AT91_MAX_STATES; /* Wait for interrupt state */ - device-states[0].enter = at91_enter_idle; - device-states[0].exit_latency = 1; - device-states[0].target_residency = 1; - device-states[0].flags = CPUIDLE_FLAG_TIME_VALID; - strcpy(device-states[0].name, WFI); - strcpy(device-states[0].desc, Wait for interrupt); + driver-states[0].enter = at91_enter_idle; + driver-states[0].exit_latency = 1; + driver-states[0].target_residency = 1; + driver-states[0].flags = CPUIDLE_FLAG_TIME_VALID; + strcpy(driver-states[0].name, WFI); + strcpy(driver-states[0].desc, Wait for interrupt); /* Wait for interrupt and RAM self refresh state */ - device-states[1].enter = at91_enter_idle; - device-states[1].exit_latency = 10; - device-states[1].target_residency = 1; - device-states[1].flags = CPUIDLE_FLAG_TIME_VALID; - strcpy(device-states[1].name, RAM_SR); - strcpy(device-states[1].desc, WFI and RAM Self Refresh); + driver-states[1].enter = at91_enter_idle; + driver-states[1].exit_latency = 10; + driver-states[1].target_residency = 1; + driver-states[1].flags = CPUIDLE_FLAG_TIME_VALID; + strcpy(driver-states[1].name, RAM_SR); + strcpy(driver-states[1].desc, WFI and RAM Self Refresh); + + cpuidle_register_driver(at91_idle_driver); if (cpuidle_register_device(device)) { printk(KERN_ERR at91_init_cpuidle: Failed registering\n); diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c index f2d2f34..dbeeccd 100644 --- a/arch/arm/mach-davinci/cpuidle.c +++ b/arch/arm/mach-davinci/cpuidle.c @@ -78,6 +78,7 @@ static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = { /* Actual code that puts the SoC in different idle states */ static int davinci_enter_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) { struct cpuidle_state_usage *state_usage = dev-states_usage[index]; @@ -109,6 +110,7