[Skiboot] [PATCH 4/5] cpu: idle split pm enable into sreset and ipi components

Nicholas Piggin npiggin at gmail.com
Thu Sep 14 21:13:45 AEST 2017


pm idle requires the system reset vector and IPI facilities before
it can be enabled. Split these out and manage them individually.

Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
---
 core/cpu.c         | 91 +++++++++++++++++++++++++++++++++++-------------------
 core/fast-reboot.c |  3 +-
 core/init.c        | 10 ++++--
 include/cpu.h      |  8 +++--
 4 files changed, 74 insertions(+), 38 deletions(-)

diff --git a/core/cpu.c b/core/cpu.c
index 01001861..460094ad 100644
--- a/core/cpu.c
+++ b/core/cpu.c
@@ -52,6 +52,8 @@ static bool hile_supported;
 static bool radix_supported;
 static unsigned long hid0_hile;
 static unsigned long hid0_attn;
+static bool sreset_enabled;
+static bool ipi_enabled;
 static bool pm_enabled;
 static bool current_hile_mode;
 static bool current_radix_mode;
@@ -321,9 +323,7 @@ static void cpu_idle_p8(enum cpu_wake_cause wake_on)
 		mtspr(SPR_LPCR, lpcr);
 
 	} else {
-		/* Mark outselves sleeping so cpu_set_pm_enable knows to
-		 * send an IPI
-		 */
+		/* Mark outselves sleeping so wakeup knows to send an IPI */
 		cpu->in_sleep = true;
 		sync();
 
@@ -346,35 +346,6 @@ skip_sleep:
 	reset_cpu_icp();
 }
 
-void cpu_set_pm_enable(bool enabled)
-{
-	struct cpu_thread *cpu;
-
-	prlog(PR_INFO, "CPU: %sing power management\n",
-	      enabled ? "enabl" : "disabl");
-
-	if (proc_gen != proc_gen_p8)
-		return;
-
-	/* Public P8 Mambo has broken NAP */
-	if (chip_quirk(QUIRK_MAMBO_CALLOUTS))
-		return;
-
-	pm_enabled = enabled;
-
-	if (enabled)
-		return;
-
-	/* If disabling, take everybody out of PM */
-	sync();
-	for_each_available_cpu(cpu) {
-		while (cpu->in_sleep || cpu->in_idle) {
-			icp_kick_cpu(cpu);
-			cpu_relax();
-		}
-	}
-}
-
 static void cpu_idle_pm(enum cpu_wake_cause wake_on)
 {
 	switch(proc_gen) {
@@ -444,6 +415,62 @@ no_pm:
 	}
 }
 
+static void cpu_pm_disable(void)
+{
+	struct cpu_thread *cpu;
+
+	pm_enabled = false;
+	sync();
+
+	if (proc_gen == proc_gen_p8) {
+		for_each_available_cpu(cpu) {
+			while (cpu->in_sleep || cpu->in_idle) {
+				icp_kick_cpu(cpu);
+				cpu_relax();
+			}
+		}
+	}
+}
+
+void cpu_set_sreset_enable(bool enabled)
+{
+	if (sreset_enabled == enabled)
+		return;
+
+	if (proc_gen == proc_gen_p8) {
+		/* Public P8 Mambo has broken NAP */
+		if (chip_quirk(QUIRK_MAMBO_CALLOUTS))
+			return;
+
+		sreset_enabled = enabled;
+		sync();
+
+		if (!enabled) {
+			cpu_pm_disable();
+		} else {
+			if (ipi_enabled)
+				pm_enabled = true;
+		}
+	}
+}
+
+void cpu_set_ipi_enable(bool enabled)
+{
+	if (ipi_enabled == enabled)
+		return;
+
+	if (proc_gen == proc_gen_p8) {
+		ipi_enabled = enabled;
+		sync();
+		if (!enabled) {
+			cpu_pm_disable();
+		} else {
+			if (sreset_enabled)
+				pm_enabled = true;
+		}
+	}
+}
+
 void cpu_process_local_jobs(void)
 {
 	struct cpu_thread *cpu = first_available_cpu();
diff --git a/core/fast-reboot.c b/core/fast-reboot.c
index 7bfc06de..8af5c590 100644
--- a/core/fast-reboot.c
+++ b/core/fast-reboot.c
@@ -564,7 +564,8 @@ void __noreturn fast_reboot_entry(void)
 	cpu_fast_reboot_complete();
 
 	/* We can now do NAP mode */
-	cpu_set_pm_enable(true);
+	cpu_set_sreset_enable(true);
+	cpu_set_ipi_enable(true);
 
 	/* Start preloading kernel and ramdisk */
 	start_preload_kernel();
diff --git a/core/init.c b/core/init.c
index 8951e17b..42e6b560 100644
--- a/core/init.c
+++ b/core/init.c
@@ -382,7 +382,7 @@ static bool load_kernel(void)
 		 * by our vectors.
 		 */
 		if (kernel_entry < 0x2000) {
-			cpu_set_pm_enable(false);
+			cpu_set_sreset_enable(false);
 			memcpy(NULL, old_vectors, 0x2000);
 			sync_icache();
 		}
@@ -545,7 +545,8 @@ void __noreturn load_and_boot_kernel(bool is_reboot)
 	mem_dump_free();
 
 	/* Take processours out of nap */
-	cpu_set_pm_enable(false);
+	cpu_set_sreset_enable(false);
+	cpu_set_ipi_enable(false);
 
 	/* Dump the selected console */
 	stdoutp = dt_prop_get_def(dt_chosen, "linux,stdout-path", NULL);
@@ -725,6 +726,7 @@ void setup_reset_vector(void)
 	while(src < &reset_patch_end)
 		*(dst++) = *(src++);
 	sync_icache();
+	cpu_set_sreset_enable(true);
 }
 
 void copy_exception_vectors(void)
@@ -926,6 +928,8 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt)
 
 	/* On P7/P8, get the ICPs and make sure they are in a sane state */
 	init_interrupts();
+	if (proc_gen == proc_gen_p7 || proc_gen == proc_gen_p8)
+		cpu_set_ipi_enable(true);
 
 	/* On P9, initialize XIVE */
 	init_xive();
@@ -951,7 +955,7 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt)
 	setup_reset_vector();
 
 	/* We can now do NAP mode */
-	cpu_set_pm_enable(true);
+	cpu_set_sreset_enable(true);
 
 	/*
 	 * Synchronize time bases. Thi resets all the TB values to a small
diff --git a/include/cpu.h b/include/cpu.h
index f08940f7..0b873178 100644
--- a/include/cpu.h
+++ b/include/cpu.h
@@ -256,8 +256,12 @@ extern void cpu_process_jobs(void);
 extern void cpu_process_local_jobs(void);
 /* Check if there's any job pending */
 bool cpu_check_jobs(struct cpu_thread *cpu);
-/* Enable/disable PM */
-void cpu_set_pm_enable(bool pm_enabled);
+
+/* OPAL sreset vector in place at 0x100 */
+void cpu_set_sreset_enable(bool sreset_enabled);
+
+/* IPI for PM modes is enabled */
+void cpu_set_ipi_enable(bool sreset_enabled);
 
 static inline void cpu_give_self_os(void)
 {
-- 
2.13.3



More information about the Skiboot mailing list