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,14 +169,10 @@ acpi_processor_power_activate(struct acpi_processor *pr,
static void acpi_safe_halt(void)
{
int polling = test_thread_flag(TIF_POLLING_NRFLAG);
if (polling) {
clear_thread_flag(TIF_POLLING_NRFLAG);
smp_mb__after_clear_bit();
}
if (!need_resched())
safe_halt();
if (polling)
set_thread_flag(TIF_POLLING_NRFLAG);
}
......@@ -295,6 +291,15 @@ static void acpi_processor_idle(void)
* ------
* 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) {
case ACPI_STATE_C1:
......@@ -327,6 +332,7 @@ static void acpi_processor_idle(void)
t2 = inl(acpi_fadt.xpm_tmr_blk.address);
/* Re-enable interrupts */
local_irq_enable();
set_thread_flag(TIF_POLLING_NRFLAG);
/* Compute time (ticks) that we were actually asleep */
sleep_ticks =
ticks_elapsed(t1, t2) - cx->latency_ticks - C2_OVERHEAD;
......@@ -366,6 +372,7 @@ static void acpi_processor_idle(void)
/* Re-enable interrupts */
local_irq_enable();
set_thread_flag(TIF_POLLING_NRFLAG);
/* Compute time (ticks) that we were actually asleep */
sleep_ticks =
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