aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorNick Piggin <nickpiggin@yahoo.com.au>2005-12-01 20:44:19 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-12-02 17:20:21 -0500
commit2a298a35ebe060a6f2b06b20c2a34ea188ddfd37 (patch)
tree226dd2569d657231a3c24d8228467a039ffc6681 /drivers
parentdeda498710e190c7922c2634ed630ee64ce86c05 (diff)
[PATCH] Fix TIF_POLLING_NRFLAG in ACPI idle routines
Commit 64c7c8f88559624abdbe12b5da6502e8879f8d28 broke the ACPI C2 and C3 sleep states, because it left TIF_POLLING_NRFLAG active even though those states do not actually poll the reschedule flag at all. As a result, the CPU wouldn't get sent an IPI when it was to be woken up, and would only notice that it had runnable processes on the next timer tick. Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/processor_idle.c21
1 files changed, 14 insertions, 7 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 83fd1b6c10c4..acd875e0caca 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -169,15 +169,11 @@ acpi_processor_power_activate(struct acpi_processor *pr,
169 169
170static void acpi_safe_halt(void) 170static void acpi_safe_halt(void)
171{ 171{
172 int polling = test_thread_flag(TIF_POLLING_NRFLAG); 172 clear_thread_flag(TIF_POLLING_NRFLAG);
173 if (polling) { 173 smp_mb__after_clear_bit();
174 clear_thread_flag(TIF_POLLING_NRFLAG);
175 smp_mb__after_clear_bit();
176 }
177 if (!need_resched()) 174 if (!need_resched())
178 safe_halt(); 175 safe_halt();
179 if (polling) 176 set_thread_flag(TIF_POLLING_NRFLAG);
180 set_thread_flag(TIF_POLLING_NRFLAG);
181} 177}
182 178
183static atomic_t c3_cpu_count; 179static atomic_t c3_cpu_count;
@@ -295,6 +291,15 @@ static void acpi_processor_idle(void)
295 * ------ 291 * ------
296 * Invoke the current Cx state to put the processor to sleep. 292 * Invoke the current Cx state to put the processor to sleep.
297 */ 293 */
294 if (cx->type == ACPI_STATE_C2 || cx->type == ACPI_STATE_C3) {
295 clear_thread_flag(TIF_POLLING_NRFLAG);
296 smp_mb__after_clear_bit();
297 if (need_resched()) {
298 set_thread_flag(TIF_POLLING_NRFLAG);
299 return;
300 }
301 }
302
298 switch (cx->type) { 303 switch (cx->type) {
299 304
300 case ACPI_STATE_C1: 305 case ACPI_STATE_C1:
@@ -327,6 +332,7 @@ static void acpi_processor_idle(void)
327 t2 = inl(acpi_fadt.xpm_tmr_blk.address); 332 t2 = inl(acpi_fadt.xpm_tmr_blk.address);
328 /* Re-enable interrupts */ 333 /* Re-enable interrupts */
329 local_irq_enable(); 334 local_irq_enable();
335 set_thread_flag(TIF_POLLING_NRFLAG);
330 /* Compute time (ticks) that we were actually asleep */ 336 /* Compute time (ticks) that we were actually asleep */
331 sleep_ticks = 337 sleep_ticks =
332 ticks_elapsed(t1, t2) - cx->latency_ticks - C2_OVERHEAD; 338 ticks_elapsed(t1, t2) - cx->latency_ticks - C2_OVERHEAD;
@@ -366,6 +372,7 @@ static void acpi_processor_idle(void)
366 372
367 /* Re-enable interrupts */ 373 /* Re-enable interrupts */
368 local_irq_enable(); 374 local_irq_enable();
375 set_thread_flag(TIF_POLLING_NRFLAG);
369 /* Compute time (ticks) that we were actually asleep */ 376 /* Compute time (ticks) that we were actually asleep */
370 sleep_ticks = 377 sleep_ticks =
371 ticks_elapsed(t1, t2) - cx->latency_ticks - C3_OVERHEAD; 378 ticks_elapsed(t1, t2) - cx->latency_ticks - C3_OVERHEAD;