idle, x86: Allow off-lined CPU to enter deeper C states
Currently when a CPU is off-lined it enters either MWAIT-based idle or,
if MWAIT is not desired or supported, HLT-based idle (which places the
processor in C1 state). This patch allows processors without MWAIT
support to stay in states deeper than C1.
Signed-off-by: Boris Ostrovsky <boris.ostrovsky@amd.com>
Signed-off-by: Len Brown <len.brown@intel.com>
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 0e8e2de..6b1d32a 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -770,6 +770,35 @@
return index;
}
+
+/**
+ * acpi_idle_play_dead - enters an ACPI state for long-term idle (i.e. off-lining)
+ * @dev: the target CPU
+ * @index: the index of suggested state
+ */
+static int acpi_idle_play_dead(struct cpuidle_device *dev, int index)
+{
+ struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
+ struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage);
+
+ ACPI_FLUSH_CPU_CACHE();
+
+ while (1) {
+
+ if (cx->entry_method == ACPI_CSTATE_HALT)
+ halt();
+ else if (cx->entry_method == ACPI_CSTATE_SYSTEMIO) {
+ inb(cx->address);
+ /* See comment in acpi_idle_do_entry() */
+ inl(acpi_gbl_FADT.xpm_timer_block.address);
+ } else
+ return -ENODEV;
+ }
+
+ /* Never reached */
+ return 0;
+}
+
/**
* acpi_idle_enter_simple - enters an ACPI state without BM handling
* @dev: the target CPU
@@ -1077,12 +1106,14 @@
state->flags |= CPUIDLE_FLAG_TIME_VALID;
state->enter = acpi_idle_enter_c1;
+ state->enter_dead = acpi_idle_play_dead;
drv->safe_state_index = count;
break;
case ACPI_STATE_C2:
state->flags |= CPUIDLE_FLAG_TIME_VALID;
state->enter = acpi_idle_enter_simple;
+ state->enter_dead = acpi_idle_play_dead;
drv->safe_state_index = count;
break;