diff options
author | Nick Piggin <nickpiggin@yahoo.com.au> | 2005-12-01 20:44:19 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-12-02 17:20:21 -0500 |
commit | 2a298a35ebe060a6f2b06b20c2a34ea188ddfd37 (patch) | |
tree | 226dd2569d657231a3c24d8228467a039ffc6681 /drivers/acpi | |
parent | deda498710e190c7922c2634ed630ee64ce86c05 (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/acpi')
-rw-r--r-- | drivers/acpi/processor_idle.c | 21 |
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 | ||
170 | static void acpi_safe_halt(void) | 170 | static 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 | ||
183 | static atomic_t c3_cpu_count; | 179 | static 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; |