aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/idle
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/idle')
-rw-r--r--[-rwxr-xr-x]drivers/idle/intel_idle.c39
1 files changed, 21 insertions, 18 deletions
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index a10152bb1427..cb3ccf3ed221 100755..100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -59,18 +59,11 @@
59#include <linux/hrtimer.h> /* ktime_get_real() */ 59#include <linux/hrtimer.h> /* ktime_get_real() */
60#include <trace/events/power.h> 60#include <trace/events/power.h>
61#include <linux/sched.h> 61#include <linux/sched.h>
62#include <asm/mwait.h>
62 63
63#define INTEL_IDLE_VERSION "0.4" 64#define INTEL_IDLE_VERSION "0.4"
64#define PREFIX "intel_idle: " 65#define PREFIX "intel_idle: "
65 66
66#define MWAIT_SUBSTATE_MASK (0xf)
67#define MWAIT_CSTATE_MASK (0xf)
68#define MWAIT_SUBSTATE_SIZE (4)
69#define MWAIT_MAX_NUM_CSTATES 8
70#define CPUID_MWAIT_LEAF (5)
71#define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1)
72#define CPUID5_ECX_INTERRUPT_BREAK (0x2)
73
74static struct cpuidle_driver intel_idle_driver = { 67static struct cpuidle_driver intel_idle_driver = {
75 .name = "intel_idle", 68 .name = "intel_idle",
76 .owner = THIS_MODULE, 69 .owner = THIS_MODULE,
@@ -83,7 +76,7 @@ static unsigned int mwait_substates;
83/* Reliable LAPIC Timer States, bit 1 for C1 etc. */ 76/* Reliable LAPIC Timer States, bit 1 for C1 etc. */
84static unsigned int lapic_timer_reliable_states; 77static unsigned int lapic_timer_reliable_states;
85 78
86static struct cpuidle_device *intel_idle_cpuidle_devices; 79static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
87static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state); 80static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state);
88 81
89static struct cpuidle_state *cpuidle_state_table; 82static struct cpuidle_state *cpuidle_state_table;
@@ -108,7 +101,7 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
108 .name = "NHM-C3", 101 .name = "NHM-C3",
109 .desc = "MWAIT 0x10", 102 .desc = "MWAIT 0x10",
110 .driver_data = (void *) 0x10, 103 .driver_data = (void *) 0x10,
111 .flags = CPUIDLE_FLAG_TIME_VALID, 104 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
112 .exit_latency = 20, 105 .exit_latency = 20,
113 .power_usage = 500, 106 .power_usage = 500,
114 .target_residency = 80, 107 .target_residency = 80,
@@ -117,7 +110,7 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
117 .name = "NHM-C6", 110 .name = "NHM-C6",
118 .desc = "MWAIT 0x20", 111 .desc = "MWAIT 0x20",
119 .driver_data = (void *) 0x20, 112 .driver_data = (void *) 0x20,
120 .flags = CPUIDLE_FLAG_TIME_VALID, 113 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
121 .exit_latency = 200, 114 .exit_latency = 200,
122 .power_usage = 350, 115 .power_usage = 350,
123 .target_residency = 800, 116 .target_residency = 800,
@@ -149,7 +142,7 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
149 .name = "ATM-C4", 142 .name = "ATM-C4",
150 .desc = "MWAIT 0x30", 143 .desc = "MWAIT 0x30",
151 .driver_data = (void *) 0x30, 144 .driver_data = (void *) 0x30,
152 .flags = CPUIDLE_FLAG_TIME_VALID, 145 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
153 .exit_latency = 100, 146 .exit_latency = 100,
154 .power_usage = 250, 147 .power_usage = 250,
155 .target_residency = 400, 148 .target_residency = 400,
@@ -157,13 +150,13 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
157 { /* MWAIT C5 */ }, 150 { /* MWAIT C5 */ },
158 { /* MWAIT C6 */ 151 { /* MWAIT C6 */
159 .name = "ATM-C6", 152 .name = "ATM-C6",
160 .desc = "MWAIT 0x40", 153 .desc = "MWAIT 0x52",
161 .driver_data = (void *) 0x40, 154 .driver_data = (void *) 0x52,
162 .flags = CPUIDLE_FLAG_TIME_VALID, 155 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
163 .exit_latency = 200, 156 .exit_latency = 140,
164 .power_usage = 150, 157 .power_usage = 150,
165 .target_residency = 800, 158 .target_residency = 560,
166 .enter = NULL }, /* disabled */ 159 .enter = &intel_idle },
167}; 160};
168 161
169/** 162/**
@@ -185,6 +178,16 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state)
185 178
186 local_irq_disable(); 179 local_irq_disable();
187 180
181 /*
182 * If the state flag indicates that the TLB will be flushed or if this
183 * is the deepest c-state supported, do a voluntary leave mm to avoid
184 * costly and mostly unnecessary wakeups for flushing the user TLB's
185 * associated with the active mm.
186 */
187 if (state->flags & CPUIDLE_FLAG_TLB_FLUSHED ||
188 (&dev->states[dev->state_count - 1] == state))
189 leave_mm(cpu);
190
188 if (!(lapic_timer_reliable_states & (1 << (cstate)))) 191 if (!(lapic_timer_reliable_states & (1 << (cstate))))
189 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); 192 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
190 193