diff options
Diffstat (limited to 'drivers/cpuidle')
-rw-r--r-- | drivers/cpuidle/Kconfig | 4 | ||||
-rw-r--r-- | drivers/cpuidle/cpuidle.c | 43 |
2 files changed, 44 insertions, 3 deletions
diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig index 3bed4127d4ad..7dbc4a83c45c 100644 --- a/drivers/cpuidle/Kconfig +++ b/drivers/cpuidle/Kconfig @@ -1,13 +1,13 @@ config CPU_IDLE bool "CPU idle PM support" + default ACPI help CPU idle is a generic framework for supporting software-controlled idle processor power management. It includes modular cross-platform governors that can be swapped during runtime. - If you're using a mobile platform that supports CPU idle PM (e.g. - an ACPI-capable notebook), you should say Y here. + If you're using an ACPI-enabled platform, you should say Y here. config CPU_IDLE_GOV_LADDER bool diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 2a98d99cbd46..d868d737742f 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -15,6 +15,7 @@ #include <linux/pm_qos_params.h> #include <linux/cpu.h> #include <linux/cpuidle.h> +#include <linux/ktime.h> #include "cpuidle.h" @@ -82,7 +83,7 @@ void cpuidle_uninstall_idle_handler(void) { if (enabled_devices && (pm_idle != pm_idle_old)) { pm_idle = pm_idle_old; - cpu_idle_wait(); + cpuidle_kick_cpus(); } } @@ -180,6 +181,44 @@ void cpuidle_disable_device(struct cpuidle_device *dev) EXPORT_SYMBOL_GPL(cpuidle_disable_device); +#ifdef CONFIG_ARCH_HAS_CPU_RELAX +static int poll_idle(struct cpuidle_device *dev, struct cpuidle_state *st) +{ + ktime_t t1, t2; + s64 diff; + int ret; + + t1 = ktime_get(); + local_irq_enable(); + while (!need_resched()) + cpu_relax(); + + t2 = ktime_get(); + diff = ktime_to_us(ktime_sub(t2, t1)); + if (diff > INT_MAX) + diff = INT_MAX; + + ret = (int) diff; + return ret; +} + +static void poll_idle_init(struct cpuidle_device *dev) +{ + struct cpuidle_state *state = &dev->states[0]; + + cpuidle_set_statedata(state, NULL); + + snprintf(state->name, CPUIDLE_NAME_LEN, "C0 (poll idle)"); + state->exit_latency = 0; + state->target_residency = 0; + state->power_usage = -1; + state->flags = CPUIDLE_FLAG_POLL | CPUIDLE_FLAG_TIME_VALID; + state->enter = poll_idle; +} +#else +static void poll_idle_init(struct cpuidle_device *dev) {} +#endif /* CONFIG_ARCH_HAS_CPU_RELAX */ + /** * cpuidle_register_device - registers a CPU's idle PM feature * @dev: the cpu @@ -198,6 +237,8 @@ int cpuidle_register_device(struct cpuidle_device *dev) mutex_lock(&cpuidle_lock); + poll_idle_init(dev); + per_cpu(cpuidle_devices, dev->cpu) = dev; list_add(&dev->device_list, &cpuidle_detected_devices); if ((ret = cpuidle_add_sysfs(sys_dev))) { |