From patchwork Mon Feb 27 04:47:35 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob X-Patchwork-Id: 6940 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 1A31C23E01 for ; Mon, 27 Feb 2012 04:47:58 +0000 (UTC) Received: from mail-iy0-f180.google.com (mail-iy0-f180.google.com [209.85.210.180]) by fiordland.canonical.com (Postfix) with ESMTP id CFFB9A185F0 for ; Mon, 27 Feb 2012 04:47:57 +0000 (UTC) Received: by mail-iy0-f180.google.com with SMTP id z7so7824105iab.11 for ; Sun, 26 Feb 2012 20:47:57 -0800 (PST) Received: from mr.google.com ([10.50.89.196]) by 10.50.89.196 with SMTP id bq4mr15517498igb.26.1330318077692 (num_hops = 1); Sun, 26 Feb 2012 20:47:57 -0800 (PST) Received: by 10.50.89.196 with SMTP id bq4mr12517422igb.26.1330318077614; Sun, 26 Feb 2012 20:47:57 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.231.11.10 with SMTP id r10csp57805ibr; Sun, 26 Feb 2012 20:47:57 -0800 (PST) Received: by 10.101.10.20 with SMTP id n20mr4362078ani.1.1330318076860; Sun, 26 Feb 2012 20:47:56 -0800 (PST) Received: from mail-gy0-f178.google.com (mail-gy0-f178.google.com [209.85.160.178]) by mx.google.com with ESMTPS id i19si5555965anm.46.2012.02.26.20.47.56 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 26 Feb 2012 20:47:56 -0800 (PST) Received-SPF: neutral (google.com: 209.85.160.178 is neither permitted nor denied by best guess record for domain of rob.lee@linaro.org) client-ip=209.85.160.178; Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.160.178 is neither permitted nor denied by best guess record for domain of rob.lee@linaro.org) smtp.mail=rob.lee@linaro.org Received: by mail-gy0-f178.google.com with SMTP id f1so185829ghb.37 for ; Sun, 26 Feb 2012 20:47:56 -0800 (PST) Received-SPF: pass (google.com: domain of rob.lee@linaro.org designates 10.236.173.195 as permitted sender) client-ip=10.236.173.195; Received: from mr.google.com ([10.236.173.195]) by 10.236.173.195 with SMTP id v43mr19216404yhl.40.1330318076703 (num_hops = 1); Sun, 26 Feb 2012 20:47:56 -0800 (PST) MIME-Version: 1.0 Received: by 10.236.173.195 with SMTP id v43mr14299995yhl.40.1330318074101; Sun, 26 Feb 2012 20:47:54 -0800 (PST) Received: from b18647-20 ([67.23.168.6]) by mx.google.com with ESMTPS id w44sm35245363yhk.17.2012.02.26.20.47.51 (version=SSLv3 cipher=OTHER); Sun, 26 Feb 2012 20:47:53 -0800 (PST) From: Robert Lee To: len.brown@intel.com, khilman@ti.com Cc: robherring2@gmail.com, Baohua.Song@csr.com, amit.kucheria@linaro.org, nicolas.ferre@atmel.com, linux@maxim.org.za, kgene.kim@samsung.com, amit.kachhap@linaro.org, magnus.damm@gmail.com, nsekhar@ti.com, daniel.lezcano@linaro.org, mturquette@linaro.org, vincent.guittot@linaro.org, arnd.bergmann@linaro.org, linux-arm-kernel@lists.infradead.org, linaro-dev@lists.linaro.org, patches@linaro.org, deepthi@linux.vnet.ibm.com, broonie@opensource.wolfsonmicro.com, nicolas.pitre@linaro.org, linux@arm.linux.org.uk, jean.pihet@newoldbits.com Subject: [PATCH v5 1/9] cpuidle: Add commonly used functionality for consolidation Date: Sun, 26 Feb 2012 22:47:35 -0600 Message-Id: <1330318063-25460-2-git-send-email-rob.lee@linaro.org> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1330318063-25460-1-git-send-email-rob.lee@linaro.org> References: <1330318063-25460-1-git-send-email-rob.lee@linaro.org> X-Gm-Message-State: ALoCoQlG83K7NbNnoC88FbxzK9rQ7gPk6uSMZpE513QwrIs5ArztG61bmBeNwHcan6XQQmggDc1Y Add functionality that is commonly duplicated by various platforms. Signed-off-by: Robert Lee --- drivers/cpuidle/cpuidle.c | 37 ++++++++++++++++++------------ include/linux/cpuidle.h | 55 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 15 deletions(-) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 59f4261..f21d58e 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "cpuidle.h" @@ -97,7 +98,11 @@ int cpuidle_idle_call(void) 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); + if (drv->en_core_tk_irqen) + entered_state = cpuidle_wrap_enter(dev, drv, next_state, + target_state->enter); + else + entered_state = target_state->enter(dev, drv, next_state); trace_power_end(dev->cpu); trace_cpu_idle(PWR_EVENT_EXIT, dev->cpu); @@ -164,28 +169,31 @@ 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, +int cpuidle_simple_enter(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { - ktime_t t1, t2; - s64 diff; + cpu_do_idle(); + + return index; +} - t1 = ktime_get(); - local_irq_enable(); +#ifdef CONFIG_ARCH_HAS_CPU_RELAX +static inline int __poll_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{ while (!need_resched()) cpu_relax(); - t2 = ktime_get(); - diff = ktime_to_us(ktime_sub(t2, t1)); - if (diff > INT_MAX) - diff = INT_MAX; - - dev->last_residency = (int) diff; - return index; } +static int poll_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{ + return cpuidle_wrap_enter(dev, drv, next_state, + __poll_idle); +} + static void poll_idle_init(struct cpuidle_driver *drv) { struct cpuidle_state *state = &drv->states[0]; @@ -195,7 +203,6 @@ static void poll_idle_init(struct cpuidle_driver *drv) state->exit_latency = 0; state->target_residency = 0; state->power_usage = -1; - state->flags = 0; state->enter = poll_idle; } #else diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 712abcc..6563683 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -15,6 +15,7 @@ #include #include #include +#include #define CPUIDLE_STATE_MAX 8 #define CPUIDLE_NAME_LEN 16 @@ -56,6 +57,16 @@ struct cpuidle_state { #define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000) +/* 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)",\ +} + /** * cpuidle_get_statedata - retrieves private driver state data * @st_usage: the state usage statistics @@ -122,6 +133,14 @@ struct cpuidle_driver { struct module *owner; unsigned int power_specified:1; + /* + * use the core cpuidle time keeping. This has been implemented for the + * entire driver instead of per state as currently the device enter + * fuction allows the entered state to change which requires handling + * that requires a (subjectively) unnecessary decrease to efficiency + * in this commonly called code. + */ + unsigned int en_core_tk_irqen:1; struct cpuidle_state states[CPUIDLE_STATE_MAX]; int state_count; int safe_state_index; @@ -140,6 +159,39 @@ 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_simple_enter(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index); + +/** + * cpuidle_enter_wrap - performing timekeeping and irq 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. + */ +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)) +{ + 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; +} #else static inline void disable_cpuidle(void) { } @@ -157,6 +209,9 @@ 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_simple_enter(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{return -ENODEV; } #endif