Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+14 −7
Original line number Original line Diff line number Diff line
@@ -169,14 +169,10 @@ 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);
	if (polling) {
	clear_thread_flag(TIF_POLLING_NRFLAG);
	clear_thread_flag(TIF_POLLING_NRFLAG);
	smp_mb__after_clear_bit();
	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);
}
}


@@ -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)
		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)


		/* 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;