From cd0f57ad5870a0975d1a6dbeb1704188257295e4 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 6 Feb 2012 08:17:08 -0800 Subject: [PATCH] --- yaml --- r: 298024 b: refs/heads/master c: d6795fe32da13bde39ea483e42799a22daa730b5 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/Documentation/cpuidle/sysfs.txt | 5 -- trunk/arch/arm/include/asm/cpuidle.h | 29 ------ trunk/arch/arm/kernel/Makefile | 2 +- trunk/arch/arm/kernel/cpuidle.c | 21 ----- trunk/arch/arm/mach-at91/cpuidle.c | 67 +++++++++----- trunk/arch/arm/mach-davinci/cpuidle.c | 83 ++++++++++-------- trunk/arch/arm/mach-kirkwood/cpuidle.c | 72 ++++++++++----- trunk/arch/arm/mach-omap2/cpuidle34xx.c | 42 +++++---- trunk/arch/arm/mach-omap2/cpuidle44xx.c | 21 ++++- trunk/arch/arm/mach-shmobile/cpuidle.c | 31 +++++-- trunk/arch/sh/kernel/cpu/shmobile/cpuidle.c | 10 ++- trunk/arch/x86/kernel/smpboot.c | 4 +- trunk/drivers/acpi/ec.c | 8 +- trunk/drivers/acpi/processor_idle.c | 31 ------- trunk/drivers/cpuidle/cpuidle.c | 97 ++------------------- trunk/drivers/cpuidle/driver.c | 2 +- trunk/drivers/cpuidle/governors/menu.c | 7 +- trunk/drivers/cpuidle/sysfs.c | 40 --------- trunk/include/linux/cpuidle.h | 22 +---- 20 files changed, 238 insertions(+), 358 deletions(-) delete mode 100644 trunk/arch/arm/include/asm/cpuidle.h delete mode 100644 trunk/arch/arm/kernel/cpuidle.c diff --git a/[refs] b/[refs] index 9b3b40ff290b..b3bf6b636f00 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 02401c06b7f6bec65f314e3cec7894502c973501 +refs/heads/master: d6795fe32da13bde39ea483e42799a22daa730b5 diff --git a/trunk/Documentation/cpuidle/sysfs.txt b/trunk/Documentation/cpuidle/sysfs.txt index 9d28a3406e74..50d7b1642759 100644 --- a/trunk/Documentation/cpuidle/sysfs.txt +++ b/trunk/Documentation/cpuidle/sysfs.txt @@ -36,7 +36,6 @@ drwxr-xr-x 2 root root 0 Feb 8 10:42 state3 /sys/devices/system/cpu/cpu0/cpuidle/state0: total 0 -r--r--r-- 1 root root 4096 Feb 8 10:42 desc --rw-r--r-- 1 root root 4096 Feb 8 10:42 disable -r--r--r-- 1 root root 4096 Feb 8 10:42 latency -r--r--r-- 1 root root 4096 Feb 8 10:42 name -r--r--r-- 1 root root 4096 Feb 8 10:42 power @@ -46,7 +45,6 @@ total 0 /sys/devices/system/cpu/cpu0/cpuidle/state1: total 0 -r--r--r-- 1 root root 4096 Feb 8 10:42 desc --rw-r--r-- 1 root root 4096 Feb 8 10:42 disable -r--r--r-- 1 root root 4096 Feb 8 10:42 latency -r--r--r-- 1 root root 4096 Feb 8 10:42 name -r--r--r-- 1 root root 4096 Feb 8 10:42 power @@ -56,7 +54,6 @@ total 0 /sys/devices/system/cpu/cpu0/cpuidle/state2: total 0 -r--r--r-- 1 root root 4096 Feb 8 10:42 desc --rw-r--r-- 1 root root 4096 Feb 8 10:42 disable -r--r--r-- 1 root root 4096 Feb 8 10:42 latency -r--r--r-- 1 root root 4096 Feb 8 10:42 name -r--r--r-- 1 root root 4096 Feb 8 10:42 power @@ -66,7 +63,6 @@ total 0 /sys/devices/system/cpu/cpu0/cpuidle/state3: total 0 -r--r--r-- 1 root root 4096 Feb 8 10:42 desc --rw-r--r-- 1 root root 4096 Feb 8 10:42 disable -r--r--r-- 1 root root 4096 Feb 8 10:42 latency -r--r--r-- 1 root root 4096 Feb 8 10:42 name -r--r--r-- 1 root root 4096 Feb 8 10:42 power @@ -76,7 +72,6 @@ total 0 * desc : Small description about the idle state (string) -* disable : Option to disable this idle state (bool) * latency : Latency to exit out of this idle state (in microseconds) * name : Name of the idle state (string) * power : Power consumed while in this idle state (in milliwatts) diff --git a/trunk/arch/arm/include/asm/cpuidle.h b/trunk/arch/arm/include/asm/cpuidle.h deleted file mode 100644 index 2fca60ab513a..000000000000 --- a/trunk/arch/arm/include/asm/cpuidle.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __ASM_ARM_CPUIDLE_H -#define __ASM_ARM_CPUIDLE_H - -#ifdef CONFIG_CPU_IDLE -extern int arm_cpuidle_simple_enter(struct cpuidle_device *dev, - struct cpuidle_driver *drv, int index); -#else -static inline int arm_cpuidle_simple_enter(struct cpuidle_device *dev, - struct cpuidle_driver *drv, int index) { return -ENODEV; } -#endif - -/* Common ARM WFI state */ -#define ARM_CPUIDLE_WFI_STATE_PWR(p) {\ - .enter = arm_cpuidle_simple_enter,\ - .exit_latency = 1,\ - .target_residency = 1,\ - .power_usage = p,\ - .flags = CPUIDLE_FLAG_TIME_VALID,\ - .name = "WFI",\ - .desc = "ARM WFI",\ -} - -/* - * in case power_specified == 1, give a default WFI power value needed - * by some governors - */ -#define ARM_CPUIDLE_WFI_STATE ARM_CPUIDLE_WFI_STATE_PWR(UINT_MAX) - -#endif diff --git a/trunk/arch/arm/kernel/Makefile b/trunk/arch/arm/kernel/Makefile index 940c27fde498..43b740d0e374 100644 --- a/trunk/arch/arm/kernel/Makefile +++ b/trunk/arch/arm/kernel/Makefile @@ -21,7 +21,7 @@ obj-$(CONFIG_DEPRECATED_PARAM_STRUCT) += compat.o obj-$(CONFIG_LEDS) += leds.o obj-$(CONFIG_OC_ETM) += etm.o -obj-$(CONFIG_CPU_IDLE) += cpuidle.o + obj-$(CONFIG_ISA_DMA_API) += dma.o obj-$(CONFIG_ARCH_ACORN) += ecard.o obj-$(CONFIG_FIQ) += fiq.o fiqasm.o diff --git a/trunk/arch/arm/kernel/cpuidle.c b/trunk/arch/arm/kernel/cpuidle.c deleted file mode 100644 index 89545f6c8403..000000000000 --- a/trunk/arch/arm/kernel/cpuidle.c +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2012 Linaro Ltd. - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include -#include - -int arm_cpuidle_simple_enter(struct cpuidle_device *dev, - struct cpuidle_driver *drv, int index) -{ - cpu_do_idle(); - - return index; -} diff --git a/trunk/arch/arm/mach-at91/cpuidle.c b/trunk/arch/arm/mach-at91/cpuidle.c index d40b3f317f7f..a851e6c98421 100644 --- a/trunk/arch/arm/mach-at91/cpuidle.c +++ b/trunk/arch/arm/mach-at91/cpuidle.c @@ -17,10 +17,9 @@ #include #include #include +#include #include #include -#include -#include #include "pm.h" @@ -28,46 +27,66 @@ static DEFINE_PER_CPU(struct cpuidle_device, at91_cpuidle_device); +static struct cpuidle_driver at91_idle_driver = { + .name = "at91_idle", + .owner = THIS_MODULE, +}; + /* 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; + int idle_time; u32 saved_lpr; - __asm__("b 1f; .align 5; 1:\n" - " mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */ - - saved_lpr = sdram_selfrefresh_enable(); - cpu_do_idle(); - sdram_selfrefresh_disable(saved_lpr); + local_irq_disable(); + do_gettimeofday(&before); + if (index == 0) + /* Wait for interrupt state */ + cpu_do_idle(); + 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(); + cpu_do_idle(); + sdram_selfrefresh_disable(saved_lpr); + } + do_gettimeofday(&after); + local_irq_enable(); + idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + + (after.tv_usec - before.tv_usec); + dev->last_residency = idle_time; return index; } -static struct cpuidle_driver at91_idle_driver = { - .name = "at91_idle", - .owner = THIS_MODULE, - .en_core_tk_irqen = 1, - .states[0] = ARM_CPUIDLE_WFI_STATE, - .states[1] = { - .enter = at91_enter_idle, - .exit_latency = 10, - .target_residency = 100000, - .flags = CPUIDLE_FLAG_TIME_VALID, - .name = "RAM_SR", - .desc = "WFI and DDR Self Refresh", - }, - .state_count = AT91_MAX_STATES, -}; - /* Initialize CPU idle by registering the idle states */ static int at91_init_cpuidle(void) { struct cpuidle_device *device; + 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 */ + driver->states[0].enter = at91_enter_idle; + driver->states[0].exit_latency = 1; + driver->states[0].target_residency = 10000; + 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 */ + driver->states[1].enter = at91_enter_idle; + driver->states[1].exit_latency = 10; + driver->states[1].target_residency = 10000; + 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); diff --git a/trunk/arch/arm/mach-davinci/cpuidle.c b/trunk/arch/arm/mach-davinci/cpuidle.c index 9107691adbdb..a30c7c5a6d83 100644 --- a/trunk/arch/arm/mach-davinci/cpuidle.c +++ b/trunk/arch/arm/mach-davinci/cpuidle.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include @@ -31,43 +30,12 @@ struct davinci_ops { u32 flags; }; -/* 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]; - struct davinci_ops *ops = cpuidle_get_statedata(state_usage); - - if (ops && ops->enter) - ops->enter(ops->flags); - - index = cpuidle_wrap_enter(dev, drv, index, - arm_cpuidle_simple_enter); - - if (ops && ops->exit) - ops->exit(ops->flags); - - return index; -} - /* fields in davinci_ops.flags */ #define DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN BIT(0) static struct cpuidle_driver davinci_idle_driver = { - .name = "cpuidle-davinci", - .owner = THIS_MODULE, - .en_core_tk_irqen = 1, - .states[0] = ARM_CPUIDLE_WFI_STATE, - .states[1] = { - .enter = davinci_enter_idle, - .exit_latency = 10, - .target_residency = 100000, - .flags = CPUIDLE_FLAG_TIME_VALID, - .name = "DDR SR", - .desc = "WFI and DDR Self Refresh", - }, - .state_count = DAVINCI_CPUIDLE_MAX_STATES, + .name = "cpuidle-davinci", + .owner = THIS_MODULE, }; static DEFINE_PER_CPU(struct cpuidle_device, davinci_cpuidle_device); @@ -109,10 +77,41 @@ 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]; + struct davinci_ops *ops = cpuidle_get_statedata(state_usage); + struct timeval before, after; + int idle_time; + + local_irq_disable(); + do_gettimeofday(&before); + + if (ops && ops->enter) + ops->enter(ops->flags); + /* Wait for interrupt state */ + cpu_do_idle(); + if (ops && ops->exit) + ops->exit(ops->flags); + + do_gettimeofday(&after); + local_irq_enable(); + idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + + (after.tv_usec - before.tv_usec); + + dev->last_residency = idle_time; + + return index; +} + static int __init davinci_cpuidle_probe(struct platform_device *pdev) { int ret; struct cpuidle_device *device; + struct cpuidle_driver *driver = &davinci_idle_driver; struct davinci_cpuidle_config *pdata = pdev->dev.platform_data; device = &per_cpu(davinci_cpuidle_device, smp_processor_id()); @@ -124,11 +123,27 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev) ddr2_reg_base = pdata->ddr2_ctlr_base; + /* Wait for interrupt state */ + driver->states[0].enter = davinci_enter_idle; + driver->states[0].exit_latency = 1; + driver->states[0].target_residency = 10000; + 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 DDR self refresh state */ + driver->states[1].enter = davinci_enter_idle; + driver->states[1].exit_latency = 10; + driver->states[1].target_residency = 10000; + driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID; + strcpy(driver->states[1].name, "DDR SR"); + strcpy(driver->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_usage[1], &davinci_states[1]); device->state_count = DAVINCI_CPUIDLE_MAX_STATES; + driver->state_count = DAVINCI_CPUIDLE_MAX_STATES; ret = cpuidle_register_driver(&davinci_idle_driver); if (ret) { diff --git a/trunk/arch/arm/mach-kirkwood/cpuidle.c b/trunk/arch/arm/mach-kirkwood/cpuidle.c index 0f1710941878..7088180b018b 100644 --- a/trunk/arch/arm/mach-kirkwood/cpuidle.c +++ b/trunk/arch/arm/mach-kirkwood/cpuidle.c @@ -20,47 +20,77 @@ #include #include #include -#include #include #define KIRKWOOD_MAX_STATES 2 +static struct cpuidle_driver kirkwood_idle_driver = { + .name = "kirkwood_idle", + .owner = THIS_MODULE, +}; + +static DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device); + /* Actual code that puts the SoC in different idle states */ static int kirkwood_enter_idle(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { - writel(0x7, DDR_OPERATION_BASE); - cpu_do_idle(); + struct timeval before, after; + int idle_time; - return index; -} + local_irq_disable(); + do_gettimeofday(&before); + if (index == 0) + /* Wait for interrupt state */ + cpu_do_idle(); + else if (index == 1) { + /* + * Following write will put DDR in self refresh. + * Note that we have 256 cycles before DDR puts it + * self in self-refresh, so the wait-for-interrupt + * call afterwards won't get the DDR from self refresh + * mode. + */ + writel(0x7, DDR_OPERATION_BASE); + cpu_do_idle(); + } + do_gettimeofday(&after); + local_irq_enable(); + idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + + (after.tv_usec - before.tv_usec); -static struct cpuidle_driver kirkwood_idle_driver = { - .name = "kirkwood_idle", - .owner = THIS_MODULE, - .en_core_tk_irqen = 1, - .states[0] = ARM_CPUIDLE_WFI_STATE, - .states[1] = { - .enter = kirkwood_enter_idle, - .exit_latency = 10, - .target_residency = 100000, - .flags = CPUIDLE_FLAG_TIME_VALID, - .name = "DDR SR", - .desc = "WFI and DDR Self Refresh", - }, - .state_count = KIRKWOOD_MAX_STATES, -}; + /* Update last residency */ + dev->last_residency = idle_time; -static DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device); + return index; +} /* Initialize CPU idle by registering the idle states */ static int kirkwood_init_cpuidle(void) { struct cpuidle_device *device; + struct cpuidle_driver *driver = &kirkwood_idle_driver; device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id()); device->state_count = KIRKWOOD_MAX_STATES; + driver->state_count = KIRKWOOD_MAX_STATES; + + /* Wait for interrupt state */ + driver->states[0].enter = kirkwood_enter_idle; + driver->states[0].exit_latency = 1; + driver->states[0].target_residency = 10000; + 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 DDR self refresh state */ + driver->states[1].enter = kirkwood_enter_idle; + driver->states[1].exit_latency = 10; + driver->states[1].target_residency = 10000; + driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID; + strcpy(driver->states[1].name, "DDR SR"); + strcpy(driver->states[1].desc, "WFI and DDR Self Refresh"); cpuidle_register_driver(&kirkwood_idle_driver); if (cpuidle_register_device(device)) { diff --git a/trunk/arch/arm/mach-omap2/cpuidle34xx.c b/trunk/arch/arm/mach-omap2/cpuidle34xx.c index 535866489ce3..464cffde58fe 100644 --- a/trunk/arch/arm/mach-omap2/cpuidle34xx.c +++ b/trunk/arch/arm/mach-omap2/cpuidle34xx.c @@ -87,14 +87,29 @@ static int _cpuidle_deny_idle(struct powerdomain *pwrdm, return 0; } -static int __omap3_enter_idle(struct cpuidle_device *dev, +/** + * omap3_enter_idle - Programs OMAP3 to enter the specified state + * @dev: cpuidle device + * @drv: cpuidle driver + * @index: the index of state to be entered + * + * Called from the CPUidle framework to program the device to the + * specified target state selected by the governor. + */ +static int omap3_enter_idle(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { struct omap3_idle_statedata *cx = 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; + + /* Used to keep track of the total time in idle */ + getnstimeofday(&ts_preidle); + local_irq_disable(); local_fiq_disable(); pwrdm_set_next_pwrst(mpu_pd, mpu_state); @@ -133,26 +148,19 @@ static int __omap3_enter_idle(struct cpuidle_device *dev, } return_sleep_time: + getnstimeofday(&ts_postidle); + ts_idle = timespec_sub(ts_postidle, ts_preidle); + local_irq_enable(); local_fiq_enable(); - return index; -} + idle_time = ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * \ + USEC_PER_SEC; -/** - * omap3_enter_idle - Programs OMAP3 to enter the specified state - * @dev: cpuidle device - * @drv: cpuidle driver - * @index: the index of state to be entered - * - * Called from the CPUidle framework to program the device to the - * specified target state selected by the governor. - */ -static inline int omap3_enter_idle(struct cpuidle_device *dev, - struct cpuidle_driver *drv, - int index) -{ - return cpuidle_wrap_enter(dev, drv, index, __omap3_enter_idle); + /* Update cpuidle counters */ + dev->last_residency = idle_time; + + return index; } /** diff --git a/trunk/arch/arm/mach-omap2/cpuidle44xx.c b/trunk/arch/arm/mach-omap2/cpuidle44xx.c index f386cbe9c889..72e018b9b260 100644 --- a/trunk/arch/arm/mach-omap2/cpuidle44xx.c +++ b/trunk/arch/arm/mach-omap2/cpuidle44xx.c @@ -62,9 +62,15 @@ static int omap4_enter_idle(struct cpuidle_device *dev, { struct omap4_idle_statedata *cx = cpuidle_get_statedata(&dev->states_usage[index]); + struct timespec ts_preidle, ts_postidle, ts_idle; u32 cpu1_state; + int idle_time; int cpu_id = smp_processor_id(); + /* Used to keep track of the total time in idle */ + getnstimeofday(&ts_preidle); + + local_irq_disable(); local_fiq_disable(); /* @@ -122,17 +128,26 @@ static int omap4_enter_idle(struct cpuidle_device *dev, if (index > 0) clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id); + getnstimeofday(&ts_postidle); + ts_idle = timespec_sub(ts_postidle, ts_preidle); + + local_irq_enable(); local_fiq_enable(); + idle_time = ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * \ + USEC_PER_SEC; + + /* Update cpuidle counters */ + dev->last_residency = idle_time; + return index; } DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev); struct cpuidle_driver omap4_idle_driver = { - .name = "omap4_idle", - .owner = THIS_MODULE, - .en_core_tk_irqen = 1, + .name = "omap4_idle", + .owner = THIS_MODULE, }; static inline void _fill_cstate(struct cpuidle_driver *drv, diff --git a/trunk/arch/arm/mach-shmobile/cpuidle.c b/trunk/arch/arm/mach-shmobile/cpuidle.c index ca23b202b02d..1b2334277e85 100644 --- a/trunk/arch/arm/mach-shmobile/cpuidle.c +++ b/trunk/arch/arm/mach-shmobile/cpuidle.c @@ -14,7 +14,6 @@ #include #include #include -#include #include static void shmobile_enter_wfi(void) @@ -30,19 +29,37 @@ static int shmobile_cpuidle_enter(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { + ktime_t before, after; + + before = ktime_get(); + + local_irq_disable(); + local_fiq_disable(); + shmobile_cpuidle_modes[index](); + local_irq_enable(); + local_fiq_enable(); + + after = ktime_get(); + dev->last_residency = ktime_to_ns(ktime_sub(after, before)) >> 10; + return index; } static struct cpuidle_device shmobile_cpuidle_dev; static struct cpuidle_driver shmobile_cpuidle_driver = { - .name = "shmobile_cpuidle", - .owner = THIS_MODULE, - .en_core_tk_irqen = 1, - .states[0] = ARM_CPUIDLE_WFI_STATE, - .safe_state_index = 0, /* C1 */ - .state_count = 1, + .name = "shmobile_cpuidle", + .owner = THIS_MODULE, + .states[0] = { + .name = "C1", + .desc = "WFI", + .exit_latency = 1, + .target_residency = 1 * 2, + .flags = CPUIDLE_FLAG_TIME_VALID, + }, + .safe_state_index = 0, /* C1 */ + .state_count = 1, }; void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv); diff --git a/trunk/arch/sh/kernel/cpu/shmobile/cpuidle.c b/trunk/arch/sh/kernel/cpu/shmobile/cpuidle.c index 1ddc876d3b26..6d62eb40e750 100644 --- a/trunk/arch/sh/kernel/cpu/shmobile/cpuidle.c +++ b/trunk/arch/sh/kernel/cpu/shmobile/cpuidle.c @@ -29,6 +29,7 @@ static int cpuidle_sleep_enter(struct cpuidle_device *dev, int index) { unsigned long allowed_mode = SUSP_SH_SLEEP; + ktime_t before, after; int requested_state = index; int allowed_state; int k; @@ -46,16 +47,19 @@ static int cpuidle_sleep_enter(struct cpuidle_device *dev, */ k = min_t(int, allowed_state, requested_state); + before = ktime_get(); sh_mobile_call_standby(cpuidle_mode[k]); + after = ktime_get(); + + dev->last_residency = (int)ktime_to_ns(ktime_sub(after, before)) >> 10; return k; } static struct cpuidle_device cpuidle_dev; static struct cpuidle_driver cpuidle_driver = { - .name = "sh_idle", - .owner = THIS_MODULE, - .en_core_tk_irqen = 1, + .name = "sh_idle", + .owner = THIS_MODULE, }; void sh_mobile_setup_cpuidle(void) diff --git a/trunk/arch/x86/kernel/smpboot.c b/trunk/arch/x86/kernel/smpboot.c index 93a2a0932b51..66d250c00d11 100644 --- a/trunk/arch/x86/kernel/smpboot.c +++ b/trunk/arch/x86/kernel/smpboot.c @@ -50,7 +50,6 @@ #include #include #include -#include #include #include @@ -1423,8 +1422,7 @@ void native_play_dead(void) tboot_shutdown(TB_SHUTDOWN_WFS); mwait_play_dead(); /* Only returns on failure */ - if (cpuidle_play_dead()) - hlt_play_dead(); + hlt_play_dead(); } #else /* ... !CONFIG_HOTPLUG_CPU */ diff --git a/trunk/drivers/acpi/ec.c b/trunk/drivers/acpi/ec.c index b19a18dd994f..3268dcfbaa9b 100644 --- a/trunk/drivers/acpi/ec.c +++ b/trunk/drivers/acpi/ec.c @@ -812,10 +812,10 @@ static int acpi_ec_add(struct acpi_device *device) first_ec = ec; device->driver_data = ec; - WARN(!request_region(ec->data_addr, 1, "EC data"), - "Could not request EC data io port 0x%lx", ec->data_addr); - WARN(!request_region(ec->command_addr, 1, "EC cmd"), - "Could not request EC cmd io port 0x%lx", ec->command_addr); + ret = !!request_region(ec->data_addr, 1, "EC data"); + WARN(!ret, "Could not request EC data io port 0x%lx", ec->data_addr); + ret = !!request_region(ec->command_addr, 1, "EC cmd"); + WARN(!ret, "Could not request EC cmd io port 0x%lx", ec->command_addr); pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", ec->gpe, ec->command_addr, ec->data_addr); diff --git a/trunk/drivers/acpi/processor_idle.c b/trunk/drivers/acpi/processor_idle.c index 6b1d32a161ae..0e8e2de2ed3e 100644 --- a/trunk/drivers/acpi/processor_idle.c +++ b/trunk/drivers/acpi/processor_idle.c @@ -770,35 +770,6 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, return index; } - -/** - * acpi_idle_play_dead - enters an ACPI state for long-term idle (i.e. off-lining) - * @dev: the target CPU - * @index: the index of suggested state - */ -static int acpi_idle_play_dead(struct cpuidle_device *dev, int index) -{ - struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; - struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage); - - ACPI_FLUSH_CPU_CACHE(); - - while (1) { - - if (cx->entry_method == ACPI_CSTATE_HALT) - halt(); - else if (cx->entry_method == ACPI_CSTATE_SYSTEMIO) { - inb(cx->address); - /* See comment in acpi_idle_do_entry() */ - inl(acpi_gbl_FADT.xpm_timer_block.address); - } else - return -ENODEV; - } - - /* Never reached */ - return 0; -} - /** * acpi_idle_enter_simple - enters an ACPI state without BM handling * @dev: the target CPU @@ -1106,14 +1077,12 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr) state->flags |= CPUIDLE_FLAG_TIME_VALID; state->enter = acpi_idle_enter_c1; - state->enter_dead = acpi_idle_play_dead; drv->safe_state_index = count; break; case ACPI_STATE_C2: state->flags |= CPUIDLE_FLAG_TIME_VALID; state->enter = acpi_idle_enter_simple; - state->enter_dead = acpi_idle_play_dead; drv->safe_state_index = count; break; diff --git a/trunk/drivers/cpuidle/cpuidle.c b/trunk/drivers/cpuidle/cpuidle.c index 3e146b2ada4a..59f4261c753a 100644 --- a/trunk/drivers/cpuidle/cpuidle.c +++ b/trunk/drivers/cpuidle/cpuidle.c @@ -53,52 +53,6 @@ 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_play_dead - cpu off-lining - * - * Only returns in case of an error - */ -int cpuidle_play_dead(void) -{ - struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); - struct cpuidle_driver *drv = cpuidle_get_driver(); - int i, dead_state = -1; - int power_usage = -1; - - /* Find lowest-power state that supports long-term idle */ - for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { - struct cpuidle_state *s = &drv->states[i]; - - if (s->power_usage < power_usage && s->enter_dead) { - power_usage = s->power_usage; - dead_state = i; - } - } - - if (dead_state != -1) - return drv->states[dead_state].enter_dead(dev, dead_state); - - return -ENODEV; -} - /** * cpuidle_idle_call - the main idle loop * @@ -109,6 +63,7 @@ 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) @@ -137,10 +92,12 @@ 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 = cpuidle_enter_ops(dev, drv, next_state); + entered_state = target_state->enter(dev, drv, next_state); trace_power_end(dev->cpu); trace_cpu_idle(PWR_EVENT_EXIT, dev->cpu); @@ -153,8 +110,6 @@ 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 */ @@ -209,37 +164,6 @@ void cpuidle_resume_and_unlock(void) EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock); -/** - * 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 time_start, time_end; - s64 diff; - - time_start = ktime_get(); - - index = enter(dev, drv, index); - - time_end = ktime_get(); - - local_irq_enable(); - - diff = ktime_to_us(ktime_sub(time_end, time_start)); - if (diff > INT_MAX) - diff = INT_MAX; - - dev->last_residency = (int) diff; - - return index; -} - #ifdef CONFIG_ARCH_HAS_CPU_RELAX static int poll_idle(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) @@ -273,7 +197,6 @@ static void poll_idle_init(struct cpuidle_driver *drv) state->power_usage = -1; state->flags = 0; state->enter = poll_idle; - state->disable = 0; } #else static void poll_idle_init(struct cpuidle_driver *drv) {} @@ -289,14 +212,13 @@ static void poll_idle_init(struct cpuidle_driver *drv) {} int cpuidle_enable_device(struct cpuidle_device *dev) { int ret, i; - struct cpuidle_driver *drv = cpuidle_get_driver(); if (dev->enabled) return 0; - if (!drv || !cpuidle_curr_governor) + if (!cpuidle_get_driver() || !cpuidle_curr_governor) return -EIO; if (!dev->state_count) - dev->state_count = drv->state_count; + return -EINVAL; if (dev->registered == 0) { ret = __cpuidle_register_device(dev); @@ -304,16 +226,13 @@ int cpuidle_enable_device(struct cpuidle_device *dev) return ret; } - cpuidle_enter_ops = drv->en_core_tk_irqen ? - cpuidle_enter_tk : cpuidle_enter; - - poll_idle_init(drv); + poll_idle_init(cpuidle_get_driver()); if ((ret = cpuidle_add_state_sysfs(dev))) return ret; if (cpuidle_curr_governor->enable && - (ret = cpuidle_curr_governor->enable(drv, dev))) + (ret = cpuidle_curr_governor->enable(cpuidle_get_driver(), dev))) goto fail_sysfs; for (i = 0; i < dev->state_count; i++) { diff --git a/trunk/drivers/cpuidle/driver.c b/trunk/drivers/cpuidle/driver.c index 40cd3f3024df..284d7af5a9c8 100644 --- a/trunk/drivers/cpuidle/driver.c +++ b/trunk/drivers/cpuidle/driver.c @@ -47,7 +47,7 @@ static void __cpuidle_register_driver(struct cpuidle_driver *drv) */ int cpuidle_register_driver(struct cpuidle_driver *drv) { - if (!drv || !drv->state_count) + if (!drv) return -EINVAL; if (cpuidle_disabled()) diff --git a/trunk/drivers/cpuidle/governors/menu.c b/trunk/drivers/cpuidle/governors/menu.c index 06335756ea14..ad0952601ae2 100644 --- a/trunk/drivers/cpuidle/governors/menu.c +++ b/trunk/drivers/cpuidle/governors/menu.c @@ -236,7 +236,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) { struct menu_device *data = &__get_cpu_var(menu_devices); int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); - int power_usage = -1; + unsigned int power_usage = -1; int i; int multiplier; struct timespec t; @@ -280,8 +280,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) * We want to default to C1 (hlt), not to busy polling * unless the timer is happening really really soon. */ - if (data->expected_us > 5 && - drv->states[CPUIDLE_DRIVER_STATE_START].disable == 0) + if (data->expected_us > 5) data->last_state_idx = CPUIDLE_DRIVER_STATE_START; /* @@ -291,8 +290,6 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { struct cpuidle_state *s = &drv->states[i]; - if (s->disable) - continue; if (s->target_residency > data->predicted_us) continue; if (s->exit_latency > latency_req) diff --git a/trunk/drivers/cpuidle/sysfs.c b/trunk/drivers/cpuidle/sysfs.c index 88032b4dc6d2..3fe41fe4851a 100644 --- a/trunk/drivers/cpuidle/sysfs.c +++ b/trunk/drivers/cpuidle/sysfs.c @@ -11,7 +11,6 @@ #include #include #include -#include #include "cpuidle.h" @@ -223,9 +222,6 @@ struct cpuidle_state_attr { #define define_one_state_ro(_name, show) \ static struct cpuidle_state_attr attr_##_name = __ATTR(_name, 0444, show, NULL) -#define define_one_state_rw(_name, show, store) \ -static struct cpuidle_state_attr attr_##_name = __ATTR(_name, 0644, show, store) - #define define_show_state_function(_name) \ static ssize_t show_state_##_name(struct cpuidle_state *state, \ struct cpuidle_state_usage *state_usage, char *buf) \ @@ -233,24 +229,6 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, \ return sprintf(buf, "%u\n", state->_name);\ } -#define define_store_state_function(_name) \ -static ssize_t store_state_##_name(struct cpuidle_state *state, \ - const char *buf, size_t size) \ -{ \ - long value; \ - int err; \ - if (!capable(CAP_SYS_ADMIN)) \ - return -EPERM; \ - err = kstrtol(buf, 0, &value); \ - if (err) \ - return err; \ - if (value) \ - state->disable = 1; \ - else \ - state->disable = 0; \ - return size; \ -} - #define define_show_state_ull_function(_name) \ static ssize_t show_state_##_name(struct cpuidle_state *state, \ struct cpuidle_state_usage *state_usage, char *buf) \ @@ -273,8 +251,6 @@ define_show_state_ull_function(usage) define_show_state_ull_function(time) define_show_state_str_function(name) define_show_state_str_function(desc) -define_show_state_function(disable) -define_store_state_function(disable) define_one_state_ro(name, show_state_name); define_one_state_ro(desc, show_state_desc); @@ -282,7 +258,6 @@ define_one_state_ro(latency, show_state_exit_latency); define_one_state_ro(power, show_state_power_usage); define_one_state_ro(usage, show_state_usage); define_one_state_ro(time, show_state_time); -define_one_state_rw(disable, show_state_disable, store_state_disable); static struct attribute *cpuidle_state_default_attrs[] = { &attr_name.attr, @@ -291,7 +266,6 @@ static struct attribute *cpuidle_state_default_attrs[] = { &attr_power.attr, &attr_usage.attr, &attr_time.attr, - &attr_disable.attr, NULL }; @@ -313,22 +287,8 @@ static ssize_t cpuidle_state_show(struct kobject * kobj, return ret; } -static ssize_t cpuidle_state_store(struct kobject *kobj, - struct attribute *attr, const char *buf, size_t size) -{ - int ret = -EIO; - struct cpuidle_state *state = kobj_to_state(kobj); - struct cpuidle_state_attr *cattr = attr_to_stateattr(attr); - - if (cattr->store) - ret = cattr->store(state, buf, size); - - return ret; -} - static const struct sysfs_ops cpuidle_state_sysfs_ops = { .show = cpuidle_state_show, - .store = cpuidle_state_store, }; static void cpuidle_state_sysfs_release(struct kobject *kobj) diff --git a/trunk/include/linux/cpuidle.h b/trunk/include/linux/cpuidle.h index 6c26a3da0e03..712abcc205ae 100644 --- a/trunk/include/linux/cpuidle.h +++ b/trunk/include/linux/cpuidle.h @@ -15,7 +15,6 @@ #include #include #include -#include #define CPUIDLE_STATE_MAX 8 #define CPUIDLE_NAME_LEN 16 @@ -44,15 +43,12 @@ struct cpuidle_state { unsigned int flags; unsigned int exit_latency; /* in US */ - int power_usage; /* in mW */ + unsigned int power_usage; /* in mW */ unsigned int target_residency; /* in US */ - unsigned int disable; int (*enter) (struct cpuidle_device *dev, struct cpuidle_driver *drv, int index); - - int (*enter_dead) (struct cpuidle_device *dev, int index); }; /* Idle State Flags */ @@ -100,6 +96,7 @@ struct cpuidle_device { struct list_head device_list; struct kobject kobj; struct completion kobj_unregister; + void *governor_data; }; DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices); @@ -121,12 +118,10 @@ static inline int cpuidle_get_last_residency(struct cpuidle_device *dev) ****************************/ struct cpuidle_driver { - const char *name; + char name[CPUIDLE_NAME_LEN]; struct module *owner; unsigned int power_specified:1; - /* set to 1 to use the core cpuidle time keeping (for all states). */ - unsigned int en_core_tk_irqen:1; struct cpuidle_state states[CPUIDLE_STATE_MAX]; int state_count; int safe_state_index; @@ -145,11 +140,6 @@ extern void cpuidle_pause_and_lock(void); extern void cpuidle_resume_and_unlock(void); extern int cpuidle_enable_device(struct cpuidle_device *dev); extern void cpuidle_disable_device(struct cpuidle_device *dev); -extern 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)); -extern int cpuidle_play_dead(void); #else static inline void disable_cpuidle(void) { } @@ -167,12 +157,6 @@ static inline void cpuidle_resume_and_unlock(void) { } static inline int cpuidle_enable_device(struct cpuidle_device *dev) {return -ENODEV; } static inline void cpuidle_disable_device(struct cpuidle_device *dev) { } -static inline 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)) -{ return -ENODEV; } -static inline int cpuidle_play_dead(void) {return -ENODEV; } #endif