From: rob.lee@linaro.org (Robert Lee)
To: linux-arm-kernel@lists.infradead.org
Subject: [RFC PATCH v4 1/4] cpuidle: Add time keeping and irq enabling
Date: Tue, 31 Jan 2012 21:00:11 -0600 [thread overview]
Message-ID: <1328065215-28108-2-git-send-email-rob.lee@linaro.org> (raw)
In-Reply-To: <1328065215-28108-1-git-send-email-rob.lee@linaro.org>
Make necessary changes to add implement time keepign and irq enabling
in the core cpuidle code. This will allow the remove of these
functionalities from the platform cpuidle implementations.
Signed-off-by: Robert Lee <rob.lee@linaro.org>
---
drivers/cpuidle/cpuidle.c | 75 +++++++++++++++++++++++++++++++++++---------
include/linux/cpuidle.h | 26 ++++++++++-----
2 files changed, 76 insertions(+), 25 deletions(-)
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 59f4261..8ea0fc3 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -57,14 +57,18 @@ static int __cpuidle_register_device(struct cpuidle_device *dev);
* cpuidle_idle_call - the main idle loop
*
* NOTE: no locks or semaphores should be used here
+ * NOTE: Should only be called from a local irq disabled context
* return non-zero on failure
+ *
*/
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;
+ int idx, ret = 0;
+ ktime_t t1, t2;
+ s64 diff;
if (off)
return -ENODEV;
@@ -86,37 +90,76 @@ int cpuidle_idle_call(void)
#endif
/* ask the governor for the next state */
- next_state = cpuidle_curr_governor->select(drv, dev);
+ idx = cpuidle_curr_governor->select(drv, dev);
+
+ target_state = &drv->states[idx];
+
+ /*
+ * Check with the device to see if it can enter this state or if another
+ * state should be used.
+ */
+ if (target_state->pre_enter) {
+ idx = target_state->
+ pre_enter(dev, drv, idx);
+ }
+
+ if (idx < 0) {
+ local_irq_enable();
+ return idx;
+ }
+
if (need_resched()) {
local_irq_enable();
- return 0;
+ return -EBUSY;
}
- target_state = &drv->states[next_state];
+ target_state = &drv->states[idx];
- trace_power_start(POWER_CSTATE, next_state, dev->cpu);
- trace_cpu_idle(next_state, dev->cpu);
+ if ((target_state->flags & CPUIDLE_FLAG_TIME_VALID))
+ t1 = ktime_get();
- entered_state = target_state->enter(dev, drv, next_state);
+ trace_power_start(POWER_CSTATE, idx, dev->cpu);
+ trace_cpu_idle(idx, dev->cpu);
+
+ idx = target_state->enter(dev, drv, idx);
trace_power_end(dev->cpu);
trace_cpu_idle(PWR_EVENT_EXIT, dev->cpu);
- if (entered_state >= 0) {
- /* Update cpuidle counters */
- /* This can be moved to within driver enter routine
- * but that results in multiple copies of same code.
- */
- dev->states_usage[entered_state].time +=
+ if (idx < 0) {
+ local_irq_enable();
+ return idx;
+ }
+
+ if (likely(target_state->flags & drv->states[idx].flags &
+ CPUIDLE_FLAG_TIME_VALID))
+ t2 = ktime_get();
+
+ local_irq_enable();
+
+ if (target_state->post_enter)
+ target_state->post_enter(dev, drv, idx);
+
+ if (likely(target_state->flags & drv->states[idx].flags &
+ CPUIDLE_FLAG_TIME_VALID)) {
+
+ diff = ktime_to_us(ktime_sub(t2, t1));
+ if (diff > INT_MAX)
+ diff = INT_MAX;
+
+ dev->last_residency = (int) diff;
+
+ dev->states_usage[idx].time +=
(unsigned long long)dev->last_residency;
- dev->states_usage[entered_state].usage++;
}
+ dev->states_usage[idx].usage++;
+
/* give the governor an opportunity to reflect on the outcome */
if (cpuidle_curr_governor->reflect)
- cpuidle_curr_governor->reflect(dev, entered_state);
+ cpuidle_curr_governor->reflect(dev, idx);
- return 0;
+ return ret;
}
/**
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index 712abcc..8154f60 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -38,17 +38,25 @@ struct cpuidle_state_usage {
};
struct cpuidle_state {
- char name[CPUIDLE_NAME_LEN];
- char desc[CPUIDLE_DESC_LEN];
+ char name[CPUIDLE_NAME_LEN];
+ char desc[CPUIDLE_DESC_LEN];
+
+ unsigned int flags;
+ unsigned int exit_latency; /* in US */
+ unsigned int power_usage; /* in mW */
+ unsigned int target_residency; /* in US */
+
+ int (*pre_enter) (struct cpuidle_device *dev,
+ struct cpuidle_driver *drv,
+ int index);
- unsigned int flags;
- unsigned int exit_latency; /* in US */
- unsigned int power_usage; /* in mW */
- unsigned int target_residency; /* in US */
+ int (*enter) (struct cpuidle_device *dev,
+ struct cpuidle_driver *drv,
+ int index);
- int (*enter) (struct cpuidle_device *dev,
- struct cpuidle_driver *drv,
- int index);
+ int (*post_enter) (struct cpuidle_device *dev,
+ struct cpuidle_driver *drv,
+ int index);
};
/* Idle State Flags */
--
1.7.1
next prev parent reply other threads:[~2012-02-01 3:00 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-02-01 3:00 [RFC PATCH v4 0/4] Consolidate cpuidle timekeeping and irq enabling Robert Lee
2012-02-01 3:00 ` Robert Lee [this message]
2012-02-04 19:02 ` [RFC PATCH v4 1/4] cpuidle: Add time keeping " Colin Cross
2012-02-04 22:06 ` Turquette, Mike
2012-02-05 1:36 ` Colin Cross
2012-02-05 1:48 ` Turquette, Mike
2012-02-06 16:38 ` Rob Lee
2012-02-06 17:14 ` Rob Lee
2012-02-01 3:00 ` [RFC PATCH v4 2/4] ARM: omap: Remove cpuidle timekeeping and irq enable/disable Robert Lee
2012-02-02 16:21 ` Jean Pihet
2012-02-02 17:35 ` Rob Lee
2012-02-01 3:00 ` [RFC PATCH v4 3/4] acpi: " Robert Lee
2012-02-01 3:00 ` [RFC PATCH v4 4/4] x86: " Robert Lee
2012-02-10 19:32 ` [RFC PATCH v4 0/4] Consolidate cpuidle timekeeping and irq enabling Rob Lee
2012-02-10 20:06 ` Amit Kucheria
2012-02-22 20:52 ` Colin Cross
2012-02-23 6:39 ` Rob Lee
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1328065215-28108-2-git-send-email-rob.lee@linaro.org \
--to=rob.lee@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).