[RFC PATCH v4 4/4] x86: Remove cpuidle timekeeping and irq enable/disable
Robert Lee
rob.lee at linaro.org
Tue Jan 31 22:00:14 EST 2012
Now that the core cpuidle driver keeps time and handles irq enabling,
remove this functionality. Also, remove irq disabling as all paths to
cpuidle_idle_call already call local_irq_disable. Also, restructure
idle functions as needed by the cpuidle core driver changes.
Signed-off-by: Robert Lee <rob.lee at linaro.org>
---
drivers/idle/intel_idle.c | 110 ++++++++++++++++++++++++++++++++-------------
1 files changed, 79 insertions(+), 31 deletions(-)
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 20bce51..482deb6 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -82,8 +82,14 @@ static unsigned int mwait_substates;
static unsigned int lapic_timer_reliable_states = (1 << 1); /* Default to only C1 */
static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
+
+static int intel_pre_idle(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index);
static int intel_idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index);
+static int intel_post_idle(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index);
+
static struct cpuidle_state *cpuidle_state_table;
@@ -114,21 +120,27 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
.flags = CPUIDLE_FLAG_TIME_VALID,
.exit_latency = 3,
.target_residency = 6,
- .enter = &intel_idle },
+ .pre_enter = &intel_pre_idle,
+ .enter = &intel_idle,
+ .post_enter = &intel_post_idle },
{ /* MWAIT C2 */
.name = "C3-NHM",
.desc = "MWAIT 0x10",
.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
.exit_latency = 20,
.target_residency = 80,
- .enter = &intel_idle },
+ .pre_enter = &intel_pre_idle,
+ .enter = &intel_idle,
+ .post_enter = &intel_post_idle },
{ /* MWAIT C3 */
.name = "C6-NHM",
.desc = "MWAIT 0x20",
.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
.exit_latency = 200,
.target_residency = 800,
- .enter = &intel_idle },
+ .pre_enter = &intel_pre_idle,
+ .enter = &intel_idle,
+ .post_enter = &intel_post_idle },
};
static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
@@ -139,28 +151,36 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
.flags = CPUIDLE_FLAG_TIME_VALID,
.exit_latency = 1,
.target_residency = 1,
- .enter = &intel_idle },
+ .pre_enter = &intel_pre_idle,
+ .enter = &intel_idle,
+ .post_enter = &intel_post_idle },
{ /* MWAIT C2 */
.name = "C3-SNB",
.desc = "MWAIT 0x10",
.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
.exit_latency = 80,
.target_residency = 211,
- .enter = &intel_idle },
+ .pre_enter = &intel_pre_idle,
+ .enter = &intel_idle,
+ .post_enter = &intel_post_idle },
{ /* MWAIT C3 */
.name = "C6-SNB",
.desc = "MWAIT 0x20",
.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
.exit_latency = 104,
.target_residency = 345,
- .enter = &intel_idle },
+ .pre_enter = &intel_pre_idle,
+ .enter = &intel_idle,
+ .post_enter = &intel_post_idle },
{ /* MWAIT C4 */
.name = "C7-SNB",
.desc = "MWAIT 0x30",
.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
.exit_latency = 109,
.target_residency = 345,
- .enter = &intel_idle },
+ .pre_enter = &intel_pre_idle,
+ .enter = &intel_idle,
+ .post_enter = &intel_post_idle },
};
static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
@@ -171,14 +191,18 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
.flags = CPUIDLE_FLAG_TIME_VALID,
.exit_latency = 1,
.target_residency = 4,
- .enter = &intel_idle },
+ .pre_enter = &intel_pre_idle,
+ .enter = &intel_idle,
+ .post_enter = &intel_post_idle },
{ /* MWAIT C2 */
.name = "C2-ATM",
.desc = "MWAIT 0x10",
.flags = CPUIDLE_FLAG_TIME_VALID,
.exit_latency = 20,
.target_residency = 80,
- .enter = &intel_idle },
+ .pre_enter = &intel_pre_idle,
+ .enter = &intel_idle,
+ .post_enter = &intel_post_idle },
{ /* MWAIT C3 */ },
{ /* MWAIT C4 */
.name = "C4-ATM",
@@ -186,7 +210,9 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
.exit_latency = 100,
.target_residency = 400,
- .enter = &intel_idle },
+ .pre_enter = &intel_pre_idle,
+ .enter = &intel_idle,
+ .post_enter = &intel_post_idle },
{ /* MWAIT C5 */ },
{ /* MWAIT C6 */
.name = "C6-ATM",
@@ -194,7 +220,9 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
.exit_latency = 140,
.target_residency = 560,
- .enter = &intel_idle },
+ .pre_enter = &intel_pre_idle,
+ .enter = &intel_idle,
+ .post_enter = &intel_post_idle },
};
static long get_driver_data(int cstate)
@@ -227,24 +255,20 @@ static long get_driver_data(int cstate)
}
/**
- * intel_idle
+ * intel_pre_idle
* @dev: cpuidle_device
* @drv: cpuidle driver
* @index: index of cpuidle state
*
* Must be called under local_irq_disable().
*/
-static int intel_idle(struct cpuidle_device *dev,
+static int intel_pre_idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
{
- unsigned long ecx = 1; /* break on interrupt flag */
struct cpuidle_state *state = &drv->states[index];
- struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
- unsigned long eax = (unsigned long)cpuidle_get_statedata(state_usage);
+ const unsigned long eax =
+ (unsigned long)dev->states_usage[index].driver_data;
unsigned int cstate;
- ktime_t kt_before, kt_after;
- s64 usec_delta;
- int cpu = smp_processor_id();
cstate = (((eax) >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) + 1;
@@ -253,12 +277,27 @@ static int intel_idle(struct cpuidle_device *dev,
* for flushing the user TLB's associated with the active mm.
*/
if (state->flags & CPUIDLE_FLAG_TLB_FLUSHED)
- leave_mm(cpu);
+ leave_mm(dev->cpu);
if (!(lapic_timer_reliable_states & (1 << (cstate))))
- clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
- kt_before = ktime_get_real();
+ return index;
+}
+
+/**
+ * intel_idle
+ * @dev: cpuidle_device
+ * @drv: cpuidle driver
+ * @index: index of cpuidle state
+ *
+ * Must be called under local_irq_disable().
+ */
+static int intel_idle(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index)
+{
+ const unsigned long eax =
+ (unsigned long)dev->states_usage[index].driver_data;
stop_critical_timings();
if (!need_resched()) {
@@ -266,21 +305,30 @@ static int intel_idle(struct cpuidle_device *dev,
__monitor((void *)¤t_thread_info()->flags, 0, 0);
smp_mb();
if (!need_resched())
- __mwait(eax, ecx);
+ __mwait(eax, 1);
}
-
start_critical_timings();
- kt_after = ktime_get_real();
- usec_delta = ktime_to_us(ktime_sub(kt_after, kt_before));
+ return index;
+}
- local_irq_enable();
+/**
+ * intel_post_idle
+ * @dev: cpuidle_device
+ * @drv: cpuidle driver
+ * @index: index of cpuidle state
+ */
+static int intel_post_idle(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index)
+{
+ const unsigned long eax =
+ (unsigned long)dev->states_usage[index].driver_data;
+ unsigned int cstate;
- if (!(lapic_timer_reliable_states & (1 << (cstate))))
- clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
+ cstate = (((eax) >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) + 1;
- /* Update cpuidle counters */
- dev->last_residency = (int)usec_delta;
+ if (!(lapic_timer_reliable_states & (1 << (cstate))))
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
return index;
}
--
1.7.1
More information about the linux-arm-kernel
mailing list