aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/idle
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/idle')
-rw-r--r--drivers/idle/intel_idle.c61
1 files changed, 46 insertions, 15 deletions
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index cb3ccf3ed221..41665d2f9f93 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -74,7 +74,7 @@ static int max_cstate = MWAIT_MAX_NUM_CSTATES - 1;
74static unsigned int mwait_substates; 74static unsigned int mwait_substates;
75 75
76/* Reliable LAPIC Timer States, bit 1 for C1 etc. */ 76/* Reliable LAPIC Timer States, bit 1 for C1 etc. */
77static unsigned int lapic_timer_reliable_states; 77static unsigned int lapic_timer_reliable_states = (1 << 1); /* Default to only C1 */
78 78
79static struct cpuidle_device __percpu *intel_idle_cpuidle_devices; 79static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
80static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state); 80static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state);
@@ -94,7 +94,6 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
94 .driver_data = (void *) 0x00, 94 .driver_data = (void *) 0x00,
95 .flags = CPUIDLE_FLAG_TIME_VALID, 95 .flags = CPUIDLE_FLAG_TIME_VALID,
96 .exit_latency = 3, 96 .exit_latency = 3,
97 .power_usage = 1000,
98 .target_residency = 6, 97 .target_residency = 6,
99 .enter = &intel_idle }, 98 .enter = &intel_idle },
100 { /* MWAIT C2 */ 99 { /* MWAIT C2 */
@@ -103,7 +102,6 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
103 .driver_data = (void *) 0x10, 102 .driver_data = (void *) 0x10,
104 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, 103 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
105 .exit_latency = 20, 104 .exit_latency = 20,
106 .power_usage = 500,
107 .target_residency = 80, 105 .target_residency = 80,
108 .enter = &intel_idle }, 106 .enter = &intel_idle },
109 { /* MWAIT C3 */ 107 { /* MWAIT C3 */
@@ -112,11 +110,46 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
112 .driver_data = (void *) 0x20, 110 .driver_data = (void *) 0x20,
113 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, 111 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
114 .exit_latency = 200, 112 .exit_latency = 200,
115 .power_usage = 350,
116 .target_residency = 800, 113 .target_residency = 800,
117 .enter = &intel_idle }, 114 .enter = &intel_idle },
118}; 115};
119 116
117static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
118 { /* MWAIT C0 */ },
119 { /* MWAIT C1 */
120 .name = "SNB-C1",
121 .desc = "MWAIT 0x00",
122 .driver_data = (void *) 0x00,
123 .flags = CPUIDLE_FLAG_TIME_VALID,
124 .exit_latency = 1,
125 .target_residency = 4,
126 .enter = &intel_idle },
127 { /* MWAIT C2 */
128 .name = "SNB-C3",
129 .desc = "MWAIT 0x10",
130 .driver_data = (void *) 0x10,
131 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
132 .exit_latency = 80,
133 .target_residency = 160,
134 .enter = &intel_idle },
135 { /* MWAIT C3 */
136 .name = "SNB-C6",
137 .desc = "MWAIT 0x20",
138 .driver_data = (void *) 0x20,
139 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
140 .exit_latency = 104,
141 .target_residency = 208,
142 .enter = &intel_idle },
143 { /* MWAIT C4 */
144 .name = "SNB-C7",
145 .desc = "MWAIT 0x30",
146 .driver_data = (void *) 0x30,
147 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
148 .exit_latency = 109,
149 .target_residency = 300,
150 .enter = &intel_idle },
151};
152
120static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = { 153static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
121 { /* MWAIT C0 */ }, 154 { /* MWAIT C0 */ },
122 { /* MWAIT C1 */ 155 { /* MWAIT C1 */
@@ -125,7 +158,6 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
125 .driver_data = (void *) 0x00, 158 .driver_data = (void *) 0x00,
126 .flags = CPUIDLE_FLAG_TIME_VALID, 159 .flags = CPUIDLE_FLAG_TIME_VALID,
127 .exit_latency = 1, 160 .exit_latency = 1,
128 .power_usage = 1000,
129 .target_residency = 4, 161 .target_residency = 4,
130 .enter = &intel_idle }, 162 .enter = &intel_idle },
131 { /* MWAIT C2 */ 163 { /* MWAIT C2 */
@@ -134,7 +166,6 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
134 .driver_data = (void *) 0x10, 166 .driver_data = (void *) 0x10,
135 .flags = CPUIDLE_FLAG_TIME_VALID, 167 .flags = CPUIDLE_FLAG_TIME_VALID,
136 .exit_latency = 20, 168 .exit_latency = 20,
137 .power_usage = 500,
138 .target_residency = 80, 169 .target_residency = 80,
139 .enter = &intel_idle }, 170 .enter = &intel_idle },
140 { /* MWAIT C3 */ }, 171 { /* MWAIT C3 */ },
@@ -144,7 +175,6 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
144 .driver_data = (void *) 0x30, 175 .driver_data = (void *) 0x30,
145 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, 176 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
146 .exit_latency = 100, 177 .exit_latency = 100,
147 .power_usage = 250,
148 .target_residency = 400, 178 .target_residency = 400,
149 .enter = &intel_idle }, 179 .enter = &intel_idle },
150 { /* MWAIT C5 */ }, 180 { /* MWAIT C5 */ },
@@ -154,7 +184,6 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
154 .driver_data = (void *) 0x52, 184 .driver_data = (void *) 0x52,
155 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, 185 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
156 .exit_latency = 140, 186 .exit_latency = 140,
157 .power_usage = 150,
158 .target_residency = 560, 187 .target_residency = 560,
159 .enter = &intel_idle }, 188 .enter = &intel_idle },
160}; 189};
@@ -179,13 +208,10 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state)
179 local_irq_disable(); 208 local_irq_disable();
180 209
181 /* 210 /*
182 * If the state flag indicates that the TLB will be flushed or if this 211 * leave_mm() to avoid costly and often unnecessary wakeups
183 * is the deepest c-state supported, do a voluntary leave mm to avoid 212 * for flushing the user TLB's associated with the active mm.
184 * costly and mostly unnecessary wakeups for flushing the user TLB's
185 * associated with the active mm.
186 */ 213 */
187 if (state->flags & CPUIDLE_FLAG_TLB_FLUSHED || 214 if (state->flags & CPUIDLE_FLAG_TLB_FLUSHED)
188 (&dev->states[dev->state_count - 1] == state))
189 leave_mm(cpu); 215 leave_mm(cpu);
190 216
191 if (!(lapic_timer_reliable_states & (1 << (cstate)))) 217 if (!(lapic_timer_reliable_states & (1 << (cstate))))
@@ -269,9 +295,14 @@ static int intel_idle_probe(void)
269 295
270 case 0x1C: /* 28 - Atom Processor */ 296 case 0x1C: /* 28 - Atom Processor */
271 case 0x26: /* 38 - Lincroft Atom Processor */ 297 case 0x26: /* 38 - Lincroft Atom Processor */
272 lapic_timer_reliable_states = (1 << 2) | (1 << 1); /* C2, C1 */ 298 lapic_timer_reliable_states = (1 << 1); /* C1 */
273 cpuidle_state_table = atom_cstates; 299 cpuidle_state_table = atom_cstates;
274 break; 300 break;
301
302 case 0x2A: /* SNB */
303 case 0x2D: /* SNB Xeon */
304 cpuidle_state_table = snb_cstates;
305 break;
275#ifdef FUTURE_USE 306#ifdef FUTURE_USE
276 case 0x17: /* 23 - Core 2 Duo */ 307 case 0x17: /* 23 - Core 2 Duo */
277 lapic_timer_reliable_states = (1 << 2) | (1 << 1); /* C2, C1 */ 308 lapic_timer_reliable_states = (1 << 2) | (1 << 1); /* C2, C1 */