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

Commit 02cf4f98 authored by Len Brown's avatar Len Brown
Browse files

ACPI: acpi_idle: touch TS_POLLING only in the non-MWAIT case



commit d306ebc2
(ACPI: Be in TS_POLLING state during mwait based C-state entry)
fixed an important power & performance issue where ACPI c2 and c3 C-states
were clearing TS_POLLING even when using MWAIT (ACPI_STATE_FFH).
That bug had been causing us to receive redundant scheduling interrups
when we had already been woken up by MONITOR/MWAIT.

Following up on that...

In the MWAIT case, we don't have to subsequently
check need_resched(), as that c heck was there
for the TS_POLLING-clearing case.

Note that not only does the cpuidle calling function
already check need_resched() before calling us, the
low-level entry into monitor/mwait calls it twice --
guaranteeing that a write to the trigger address
can not go un-noticed.

Also, in this case, we don't have to set TS_POLLING
when we wake, because we never cleared it.

Signed-off-by: default avatarLen Brown <len.brown@intel.com>
Acked-by: default avatarVenkatesh Pallipadi <venki@google.com>
parent a7d27c37
Loading
Loading
Loading
Loading
+16 −12
Original line number Diff line number Diff line
@@ -881,6 +881,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
		return(acpi_idle_enter_c1(dev, state));

	local_irq_disable();

	if (cx->entry_method != ACPI_CSTATE_FFH) {
		current_thread_info()->status &= ~TS_POLLING;
		/*
@@ -888,13 +889,13 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
		 * NEED_RESCHED:
		 */
		smp_mb();
	}

		if (unlikely(need_resched())) {
			current_thread_info()->status |= TS_POLLING;
			local_irq_enable();
			return 0;
		}
	}

	/*
	 * Must be done before busmaster disable as we might need to
@@ -918,6 +919,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
	sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS);

	local_irq_enable();
	if (cx->entry_method != ACPI_CSTATE_FFH)
		current_thread_info()->status |= TS_POLLING;

	cx->usage++;
@@ -968,6 +970,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
	}

	local_irq_disable();

	if (cx->entry_method != ACPI_CSTATE_FFH) {
		current_thread_info()->status &= ~TS_POLLING;
		/*
@@ -975,13 +978,13 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
		 * NEED_RESCHED:
		 */
		smp_mb();
	}

		if (unlikely(need_resched())) {
			current_thread_info()->status |= TS_POLLING;
			local_irq_enable();
			return 0;
		}
	}

	acpi_unlazy_tlb(smp_processor_id());

@@ -1032,6 +1035,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
	sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS);

	local_irq_enable();
	if (cx->entry_method != ACPI_CSTATE_FFH)
		current_thread_info()->status |= TS_POLLING;

	cx->usage++;