diff options
Diffstat (limited to 'drivers/idle')
-rw-r--r--[-rwxr-xr-x] | drivers/idle/intel_idle.c | 39 |
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 | |||
74 | static struct cpuidle_driver intel_idle_driver = { | 67 | static 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. */ |
84 | static unsigned int lapic_timer_reliable_states; | 77 | static unsigned int lapic_timer_reliable_states; |
85 | 78 | ||
86 | static struct cpuidle_device *intel_idle_cpuidle_devices; | 79 | static struct cpuidle_device __percpu *intel_idle_cpuidle_devices; |
87 | static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state); | 80 | static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state); |
88 | 81 | ||
89 | static struct cpuidle_state *cpuidle_state_table; | 82 | static 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 | ||