[PATCH] Fix TIF_POLLING_NRFLAG in ACPI idle routines

Commit 64c7c8f885 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>
This commit is contained in:
Nick Piggin 2005-12-02 12:44:19 +11:00 committed by Linus Torvalds
parent deda498710
commit 2a298a35eb

View file

@ -169,15 +169,11 @@ 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();
}
clear_thread_flag(TIF_POLLING_NRFLAG);
smp_mb__after_clear_bit();
if (!need_resched())
safe_halt();
if (polling)
set_thread_flag(TIF_POLLING_NRFLAG);
set_thread_flag(TIF_POLLING_NRFLAG);
}
static atomic_t c3_cpu_count;
@ -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;