aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/idle/intel_idle.c18
-rw-r--r--include/linux/cpuidle.h1
2 files changed, 15 insertions, 4 deletions
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 96bf38097996..0906fc5b69b9 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -108,7 +108,7 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
108 .name = "NHM-C3", 108 .name = "NHM-C3",
109 .desc = "MWAIT 0x10", 109 .desc = "MWAIT 0x10",
110 .driver_data = (void *) 0x10, 110 .driver_data = (void *) 0x10,
111 .flags = CPUIDLE_FLAG_TIME_VALID, 111 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
112 .exit_latency = 20, 112 .exit_latency = 20,
113 .power_usage = 500, 113 .power_usage = 500,
114 .target_residency = 80, 114 .target_residency = 80,
@@ -117,7 +117,7 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
117 .name = "NHM-C6", 117 .name = "NHM-C6",
118 .desc = "MWAIT 0x20", 118 .desc = "MWAIT 0x20",
119 .driver_data = (void *) 0x20, 119 .driver_data = (void *) 0x20,
120 .flags = CPUIDLE_FLAG_TIME_VALID, 120 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
121 .exit_latency = 200, 121 .exit_latency = 200,
122 .power_usage = 350, 122 .power_usage = 350,
123 .target_residency = 800, 123 .target_residency = 800,
@@ -149,7 +149,7 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
149 .name = "ATM-C4", 149 .name = "ATM-C4",
150 .desc = "MWAIT 0x30", 150 .desc = "MWAIT 0x30",
151 .driver_data = (void *) 0x30, 151 .driver_data = (void *) 0x30,
152 .flags = CPUIDLE_FLAG_TIME_VALID, 152 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
153 .exit_latency = 100, 153 .exit_latency = 100,
154 .power_usage = 250, 154 .power_usage = 250,
155 .target_residency = 400, 155 .target_residency = 400,
@@ -159,7 +159,7 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
159 .name = "ATM-C6", 159 .name = "ATM-C6",
160 .desc = "MWAIT 0x40", 160 .desc = "MWAIT 0x40",
161 .driver_data = (void *) 0x40, 161 .driver_data = (void *) 0x40,
162 .flags = CPUIDLE_FLAG_TIME_VALID, 162 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
163 .exit_latency = 200, 163 .exit_latency = 200,
164 .power_usage = 150, 164 .power_usage = 150,
165 .target_residency = 800, 165 .target_residency = 800,
@@ -185,6 +185,16 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state)
185 185
186 local_irq_disable(); 186 local_irq_disable();
187 187
188 /*
189 * If the state flag indicates that the TLB will be flushed or if this
190 * is the deepest c-state supported, do a voluntary leave mm to avoid
191 * costly and mostly unnecessary wakeups for flushing the user TLB's
192 * associated with the active mm.
193 */
194 if (state->flags & CPUIDLE_FLAG_TLB_FLUSHED ||
195 (&dev->states[dev->state_count - 1] == state))
196 leave_mm(cpu);
197
188 if (!(lapic_timer_reliable_states & (1 << (cstate)))) 198 if (!(lapic_timer_reliable_states & (1 << (cstate))))
189 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); 199 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
190 200
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index 36ca9721a0c2..1be416bbbb82 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -53,6 +53,7 @@ struct cpuidle_state {
53#define CPUIDLE_FLAG_BALANCED (0x40) /* medium latency, moderate savings */ 53#define CPUIDLE_FLAG_BALANCED (0x40) /* medium latency, moderate savings */
54#define CPUIDLE_FLAG_DEEP (0x80) /* high latency, large savings */ 54#define CPUIDLE_FLAG_DEEP (0x80) /* high latency, large savings */
55#define CPUIDLE_FLAG_IGNORE (0x100) /* ignore during this idle period */ 55#define CPUIDLE_FLAG_IGNORE (0x100) /* ignore during this idle period */
56#define CPUIDLE_FLAG_TLB_FLUSHED (0x200) /* tlb will be flushed */
56 57
57#define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000) 58#define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000)
58 59