Commit 2a298a35 authored by Nick Piggin's avatar Nick Piggin Committed by Linus Torvalds

[PATCH] Fix TIF_POLLING_NRFLAG in ACPI idle routines

Commit 64c7c8f8 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: default avatarLinus Torvalds <torvalds@osdl.org>
parent deda4987
...@@ -169,15 +169,11 @@ acpi_processor_power_activate(struct acpi_processor *pr, ...@@ -169,15 +169,11 @@ acpi_processor_power_activate(struct acpi_processor *pr,
static void acpi_safe_halt(void) static void acpi_safe_halt(void)
{ {
int polling = test_thread_flag(TIF_POLLING_NRFLAG); clear_thread_flag(TIF_POLLING_NRFLAG);
if (polling) { smp_mb__after_clear_bit();
clear_thread_flag(TIF_POLLING_NRFLAG);
smp_mb__after_clear_bit();
}
if (!need_resched()) if (!need_resched())
safe_halt(); safe_halt();
if (polling) set_thread_flag(TIF_POLLING_NRFLAG);
set_thread_flag(TIF_POLLING_NRFLAG);
} }
static atomic_t c3_cpu_count; static atomic_t c3_cpu_count;
...@@ -295,6 +291,15 @@ static void acpi_processor_idle(void) ...@@ -295,6 +291,15 @@ static void acpi_processor_idle(void)
* ------ * ------
* Invoke the current Cx state to put the processor to sleep. * Invoke the current Cx state to put the processor to sleep.
*/ */
if (cx->type == ACPI_STATE_C2 || cx->type == ACPI_STATE_C3) {
clear_thread_flag(TIF_POLLING_NRFLAG);
smp_mb__after_clear_bit();
if (need_resched()) {
set_thread_flag(TIF_POLLING_NRFLAG);
return;
}
}
switch (cx->type) { switch (cx->type) {
case ACPI_STATE_C1: case ACPI_STATE_C1:
...@@ -327,6 +332,7 @@ static void acpi_processor_idle(void) ...@@ -327,6 +332,7 @@ static void acpi_processor_idle(void)
t2 = inl(acpi_fadt.xpm_tmr_blk.address); t2 = inl(acpi_fadt.xpm_tmr_blk.address);
/* Re-enable interrupts */ /* Re-enable interrupts */
local_irq_enable(); local_irq_enable();
set_thread_flag(TIF_POLLING_NRFLAG);
/* Compute time (ticks) that we were actually asleep */ /* Compute time (ticks) that we were actually asleep */
sleep_ticks = sleep_ticks =
ticks_elapsed(t1, t2) - cx->latency_ticks - C2_OVERHEAD; ticks_elapsed(t1, t2) - cx->latency_ticks - C2_OVERHEAD;
...@@ -366,6 +372,7 @@ static void acpi_processor_idle(void) ...@@ -366,6 +372,7 @@ static void acpi_processor_idle(void)
/* Re-enable interrupts */ /* Re-enable interrupts */
local_irq_enable(); local_irq_enable();
set_thread_flag(TIF_POLLING_NRFLAG);
/* Compute time (ticks) that we were actually asleep */ /* Compute time (ticks) that we were actually asleep */
sleep_ticks = sleep_ticks =
ticks_elapsed(t1, t2) - cx->latency_ticks - C3_OVERHEAD; ticks_elapsed(t1, t2) - cx->latency_ticks - C3_OVERHEAD;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment