[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:
parent
deda498710
commit
2a298a35eb
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue